Socket
Socket
Sign inDemoInstall

react-native-controlled-mentions

Package Overview
Dependencies
577
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-controlled-mentions

Fully controlled React Native mentions component


Version published
Maintainers
1
Weekly downloads
9,397
decreased by-34.31%

Weekly downloads

Readme

Source

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 nameDescriptionTypeRequiredDefault
valueThe same as in TextInputstringtrue
onChangeThe same as in TextInput(value: string) => voidtrue
partTypesDeclare what part types you want to support (mentions, hashtags, urls)PartType[]false[]
inputRefReference to the TextInput component inside MentionInputRef<TextInput>false
containerStyleStyle to the MentionInput's root componentStyleProp<TextStyle>false
...textInputPropsOther text input propsTextInputPropsfalse

PartType type

MentionPartType | PatternPartType

MentionPartType type props

Property nameDescriptionTypeRequiredDefault
triggerCharacter that will trigger current mention typestringtrue
renderSuggestionsRenderer for mention suggestions component(props: MentionSuggestionsProps) => ReactNodefalse
allowedSpacesCountHow much spaces are allowed for mention keywordnumberfalse1
isInsertSpaceAfterMentionShould we add a space after selected mentions if the mention is at the end of rowbooleanfalsefalse
isBottomMentionSuggestionsRenderShould we render either at the top or bottom of the inputbooleanfalse
textStyleText style for mentions in TextInputStyleProp<TextStyle>false
getPlainStringFunction for generating custom mention text in text input(mention: MentionData) => stringfalse

PatternPartType type props

Property nameDescriptionTypeRequiredDefault
patternRegExp for parsing a pattern, should include global flagRegExptrue
textStyleText style for pattern in TextInputStyleProp<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

Buy Me A Coffee

Keywords

FAQs

Last updated on 11 Mar 2021

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc