Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

react-native-headless-mention

imranbarbhuiya308MIT1.2.4TypeScript support: included

A headless react native mention component for both iOS and Android.

react native, expo, mention, headless, headless ui, hashtag, tag

readme

react-native-headless-mention

A headless mention component for React Native.

GitHub codecov npm

Description

A headless mention component for React Native. It's a headless component, so you'll need to provide your styles and suggestions renderer.

Features

  • Written In Typescript
  • Offers CJS, and ESM builds
  • Full TypeScript & JavaScript support

Install

You can use the following command to install this package, or replace npm install with your package manager of choice.

npm i react-native-headless-mention

Usage

For mention with autocomplete

import { useState, useRef, useEffect } from 'react';
import { Pressable, Text, View } from 'react-native';
import { Input, type MentionSuggestionsProps } from 'react-native-headless-mention';

const suggestions = [
    { id: '1', name: 'Parbez' },
    { id: '2', name: 'Voxelli' },
    { id: '3', name: 'Sho' },
    { id: '4', name: 'Hound' },
    { id: '5', name: 'Sarcaster' },
];

const renderSuggestions = ({ keyword, onSuggestionPress }: MentionSuggestionsProps) => {
    if (keyword === undefined) 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>
    );
};

export default function Campaigns() {
    const [value, setValue] = useState('');

    return (
        <Input
            onChange={setValue}
            partTypes={[
                {
                    trigger: '@',
                    renderSuggestions,
                    textStyle: { fontWeight: 'bold', color: 'blue' },
                    getLabel(mention) {
                        const user = suggestions.find((one) => one.id === mention.id);
                        return user ? `@${user.name}` : `<@${mention.id}>`;
                    },
                    pattern: /<(?<trigger>@)(?<id>\d+)>/g,
                },
            ]}
            value={value}
        />
    );
}

[!Important] The pattern must be a global regex. If it's a mention regex then don't forget to add the group name trigger and id in the regex.

[!Note] 2nd param of onChange provides all the parts of the value. You can use it to get the mentions present in the value.

Get mentions from the value

import { parseValue, type MentionPartType } from 'react-native-headless-mention';


const partTypes: MentionPartType[] = [
    {
        trigger: '@',
        renderSuggestions,
        textStyle: { fontWeight: '500' },
        getLabel(mention) {
            const user = suggestions.find((one) => one.id === mention.id);
            return user ? `@${user.name}` : `<@${mention.id}>`;
        },
        pattern: /<(?<trigger>@)(?<id>\d+)>/g,
        renderPosition: 'bottom',
    },
];

const values = parseValue(value, partTypes);

console.log(values.parts.filter((part) => part.data?.trigger === '@').map((part) => part.data?.id));

For formatting

This lib can also be used for formatting. It doesn't provide any pre-defined formatting but you can do it with regex. Here's a simple demo to achive simple markdown support

import { useState, useRef, useEffect } from 'react';
import { Pressable, Text, View } from 'react-native';
import { Input } from 'react-native-headless-mention';


export default function Campaigns() {
    const [value, setValue] = useState('');

    return (
        <Input
            onChange={setValue}
            partTypes={[
                {
                    textStyle: { fontWeight: '700' },
                    pattern: /\*\*(?<text>\S(?:.*?\S)?)\*\*/g,
                },
                {
                    textStyle: { textDecorationLine: 'underline' },
                    pattern: /__(?<text>\S(?:.*?\S)?)__/g,
                },
                {
                    textStyle: { fontStyle: 'italic' },
                    pattern: /\*(?<text>\S(?:.*?\S)?)\*/g,
                },
                {
                    textStyle: { fontStyle: 'italic' },
                    pattern: /_(?<text>\S(?:.*?\S)?)_/g,
                },
                {
                    textStyle: { textDecorationLine: 'line-through' },
                    pattern: /~(?<text>\S(?:.*?\S)?)~/g,
                },
            ]}
            value={value}
        />
    );
}

Buy me some doughnuts

If you want to support me by donating, you can do so by using any of the following methods. Thank you very much in advance!

Buy Me A Coffee Buy Me A Coffee Buy Me a Coffee at ko-fi.com

Contributors ✨

Thanks goes to these wonderful people:

changelog

Changelog

All notable changes to this project will be documented in this file.

1.2.4 - (2024-12-13)

🐛 Bug Fixes

1.2.3 - (2024-12-13)

🐛 Bug Fixes

  • Should handle cursor position properly for emoji input (fe94ba9)

🧪 Testing

1.2.1 - (2024-10-24)

🐛 Bug Fixes

  • deps: Update dependency diff to v7 (#81) (94d2a9d)
  • Add a video (1c7198c)

1.2.0 - (2024-04-02)

🐛 Bug Fixes

  • Editing text removes texts after the cursor (db20e30)

🚀 Features

  • Allow custom text input component (06736aa)

1.1.2 - (2024-02-09)

🐛 Bug Fixes

1.1.1 - (2024-02-09)

📝 Documentation

1.1.0 - (2024-02-09)

🚀 Features

0.0.1 - (2024-02-07)

🐛 Bug Fixes

🚀 Features