npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-native-controlled-mentions-nkm

v1.0.0

Published

Fully controlled React Native mentions component

Downloads

2

Readme

react-native-controlled-mentions npm version

Pretty simple and fully controlled mention input. It can:

  • Gracefully render formatted mentions directly in RN TextInput component
  • Support for different mention types (@user mentions, #hashtags, etc)
  • Use value/onChange as in usual TextInput props
  • Completely typed (written on TypeScript)
  • No need for native libraries

In addition, you can add custom styling for a regex pattern (like URLs) using the optimized recursive function for parsing the value.

Demo

Try it on Expo Snack: https://snack.expo.io/@dabakovich/mentionsapp

Getting started

Install the library using either Yarn:

yarn add react-native-controlled-mentions

or npm:

npm install --save react-native-controlled-mentions

Usage

Import the MentionInput component:

import { MentionInput } from 'react-native-controlled-mentions'

Replace your TextInput by MentionInput component and add the partTypes property where you can define what mention or pattern types you want to support. It takes an array of PartType objects.

<MentionInput
  value={value}
  onChange={setValue}

  partTypes={[
    {
      trigger: '@', // Should be a single character like '@' or '#'
      renderSuggestions,
      textStyle: {fontWeight: 'bold', color: 'blue'}, // The mention style in the input
    },
  ]}
/>

Define your renderSuggestions functional component that receive MentionSuggestionsProps:

const suggestions = [
  {id: '1', name: 'David Tabaka'},
  {id: '2', name: 'Mary'},
  {id: '3', name: 'Tony'},
  {id: '4', name: 'Mike'},
  {id: '5', name: 'Grey'},
];

const renderSuggestions: FC<MentionSuggestionsProps> = ({keyword, onSuggestionPress}) => {
  if (keyword == null) {
    return null;
  }

  return (
    <View>
      {suggestions
        .filter(one => one.name.toLocaleLowerCase().includes(keyword.toLocaleLowerCase()))
        .map(one => (
          <Pressable
            key={one.id}
            onPress={() => onSuggestionPress(one)}

            style={{padding: 12}}
          >
            <Text>{one.name}</Text>
          </Pressable>
        ))
      }
    </View>
  );
};

You're done!

The whole example is in the /example folder.

API

MentionInput component props

| Property name | Description | Type | Required | Default | |------------------- |-------------------------------------------------------------------- |---------------------------------------- |------------ |------------ | | value | The same as in TextInput | string | true | | | onChange | The same as in TextInput | (value: string) => void | true | | | partTypes | Declare what part types you want to support (mentions, hashtags, urls)| PartType[] | false | [] | | inputRef | Reference to the TextInput component inside MentionInput | Ref<TextInput> | false | | | containerStyle | Style to the MentionInput's root component | StyleProp<TextStyle> | false | | | ...textInputProps | Other text input props | TextInputProps | false | |

PartType type

MentionPartType | PatternPartType

MentionPartType type props

| Property name | Description | Type | Required | Default | |------------------------------------ |----------------------------------------------------------------------------------- |----------------------------------------------------------------------------------- |------------ |----------- | | trigger | Character that will trigger current mention type | string | true | | | renderSuggestions | Renderer for mention suggestions component | (props: MentionSuggestionsProps) => ReactNode | false | | | allowedSpacesCount | How much spaces are allowed for mention keyword | number | false | 1 | | isInsertSpaceAfterMention | Should we add a space after selected mentions if the mention is at the end of row | boolean | false | false | | isBottomMentionSuggestionsRender | Should we render either at the top or bottom of the input | boolean | false | | | textStyle | Text style for mentions in TextInput | StyleProp<TextStyle> | false | | | getPlainString | Function for generating custom mention text in text input | (mention: MentionData) => string | false | |

PatternPartType type props

| Property name | Description | Type | Required | Default | |--------------------------- |----------------------------------------------------------------------------------- |----------------------------------------------------------------------------------- |------------ |----------- | | pattern | RegExp for parsing a pattern, should include global flag | RegExp | true | | | textStyle | Text style for pattern in TextInput | StyleProp<TextStyle> | false | |

MentionSuggestionsProps type props

keyword: string | undefined

Keyword that will provide string between trigger character (e.g. '@') and cursor.

If the cursor is not tracking any mention typing the keyword will be undefined.

Examples where @name is just plain text yet, not mention and | is cursor position:

'|abc @name dfg' - keyword is undefined
'abc @| dfg' - keyword is ''
'abc @name| dfg' - keyword is 'name'
'abc @na|me dfg' - keyword is 'na'
'abc @|name dfg' - keyword is against ''
'abc @name |dfg' - keyword is against undefined

onSuggestionPress: (suggestion: Suggestion) => void

You should call that callback when user selects any suggestion.

Suggestion type props

id: string

Unique id for each suggestion.

name: string

Name that will be shown in MentionInput when user will select the suggestion.

MentionData type props

For example, we have that mention value @[David Tabaka](123). Then after parsing that string by mentionRegEx we will get next properties:

original: string

The whole mention value string - @[David Tabaka](123)

trigger: string

The extracted trigger - @

name: string

The extracted name - David Tabaka

id: string

The extracted id - 123

mentionRegEx

/(?<original>(?<trigger>.)\[(?<name>([^[]*))]\((?<id>([\d\w-]*))\))/gi;

Parsing MentionInput's value

You can import RegEx that is using in the component and then extract all your mentions from MentionInput's value using your own logic.

import { mentionRegEx } from 'react-native-controlled-mentions';

Or you can use replaceMentionValues helper to replace all mentions from MentionInput's input using your replacer function that receives MentionData type and returns string.

import { replaceMentionValues } from 'react-native-controlled-mentions';

const value = 'Hello @[David Tabaka](5)! How are you?';

console.log(replaceMentionValues(value, ({id}) => `@${id}`)); // Hello @5! How are you?
console.log(replaceMentionValues(value, ({name}) => `@${name}`)); // Hello @David Tabaka! How are you?

Rendering MentionInput's value

If you want to parse and render your value somewhere else you can use parseValue tool which gives you array of parts and then use your own part renderer to resolve this issue.

Here is an example:

import {
  Part,
  PartType,
  parseValue,
  isMentionPartType,
} from 'react-native-controlled-mentions';

/**
 * Part renderer
 * 
 * @param part
 * @param index
 */
const renderPart = (
  part: Part,
  index: number,
) => {
  // Just plain text
  if (!part.partType) {
    return <Text key={index}>{part.text}</Text>;
  }

  // Mention type part
  if (isMentionPartType(part.partType)) {
    return (
      <Text
        key={`${index}-${part.data?.trigger}`}
        style={part.partType.textStyle}
        onPress={() => console.log('Pressed', part.data)}
      >
        {part.text}
      </Text>
    );
  }

  // Other styled part types
  return (
    <Text
      key={`${index}-pattern`}
      style={part.partType.textStyle}
    >
      {part.text}
    </Text>
  );
};

/**
 * Value renderer. Parsing value to parts array and then mapping the array using 'renderPart'
 * 
 * @param value - value from MentionInput
 * @param partTypes - the part types array that you providing to MentionInput
 */
const renderValue: FC = (
  value: string,
  partTypes: PartType[],
) => {
  const {parts} = parseValue(value, partTypes);

  return <Text>{parts.map(renderPart)}</Text>;
};

To Do

  • ~~Add support for different text formatting (e.g. URLs)~~
  • ~~Add more customizations~~ DONE
  • ~~Add ability to handle few mention types ("#", "@" etc)~~ DONE

Known issues

  • Mention name regex accepts white spaces (e.g. {name: ' ', value: 1})
  • ~~Keyboard auto-correction not working if suggested word has the same length~~ FIXED
  • ~~Text becomes transparent when setting custom font size in TextInput~~ FIXED

Support Me