Created
August 24, 2022 18:42
-
-
Save Aryk/a1699136cda19cfc730f0e7e8023a5c1 to your computer and use it in GitHub Desktop.
Aryk's Fix for react-native-controlled-mentions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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