Skip to content

Instantly share code, notes, and snippets.

@Aryk
Created August 24, 2022 18:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Aryk/a1699136cda19cfc730f0e7e8023a5c1 to your computer and use it in GitHub Desktop.
Save Aryk/a1699136cda19cfc730f0e7e8023a5c1 to your computer and use it in GitHub Desktop.
Aryk's Fix for react-native-controlled-mentions
import React, {useMemo, useRef} from 'react';
import { NativeSyntheticEvent, Text, TextInputSelectionChangeEventData } from 'react-native';
import {
defaultTriggerTextStyle,
emptyObject,
generateValueFromMentionStateAndChangedText,
getConfigsArray,
getTriggerPartSuggestionKeywords,
parseValue,
} from "react-native-controlled-mentions/dist/utils";
import {Position, UseMentionsConfig} from "react-native-controlled-mentions/dist/types";
/**
* Hook that stores mention context.
*
* @param value
* @param onChange
* @param triggersConfig
* @param patterns
*/
const useMentions = <TriggerName extends string>({
value,
onChange,
triggersConfig = emptyObject,
patternsConfig = emptyObject,
onSelectionChange,
}: UseMentionsConfig<TriggerName>) => {
const selectionRef = useRef<Position>({
start: 0,
end: 0,
});
/**
* State that includes current parts and plain text
*/
const mentionState = useMemo(
() => parseValue(value, getConfigsArray(triggersConfig, patternsConfig)),
[value, triggersConfig, patternsConfig],
);
/**
* Callback that handles TextInput text change
*
* @param text
*/
const handleTextChange = (text: string) => {
onChange(generateValueFromMentionStateAndChangedText(mentionState, text));
};
/**
* Callback that handles TextInput selection change
*
* @param event
*/
const handleSelectionChange = (
event: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
) => {
const newSelection = event.nativeEvent.selection;
selectionRef.current = newSelection;
onSelectionChange && onSelectionChange(newSelection);
};
/**
* Object with triggers and their current keyword state depending on current text and selection
*/
const triggers = useMemo(
() =>
getTriggerPartSuggestionKeywords<TriggerName>(
mentionState,
selectionRef.current,
triggersConfig,
onChange,
),
[mentionState, triggersConfig, onChange],
);
/**
* `TextInput` props that we can provide to the `TextInput` component.
*/
const textInputProps = {
onChangeText: handleTextChange,
onSelectionChange: handleSelectionChange,
children: React.createElement(
Text,
null,
mentionState.parts.map(({ text, config, data }, index) =>
config
? React.createElement(
Text,
{
key: `${index}-${data?.trigger ?? 'pattern'}`,
style: config.textStyle ?? defaultTriggerTextStyle,
},
text,
)
: React.createElement(Text, { key: index }, text),
),
),
};
return {
triggers,
textInputProps,
mentionState,
};
};
export { useMentions };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment