@portabletext/plugin-emoji-picker 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,13 +7,26 @@
7
7
  The `useEmojiPicker` hook handles the state and logic needed to create an emoji picker for the Portable Text Editor. It manages keyword matching, keyboard navigation, and emoji insertion, but is not concerned with the UI, how the picker is rendered, or how it's positioned in the document.
8
8
 
9
9
  ```tsx
10
- import {matchEmojis, useEmojiPicker} from '@portabletext/plugin-emoji-picker'
10
+ import {
11
+ createMatchEmojis,
12
+ useEmojiPicker,
13
+ } from '@portabletext/plugin-emoji-picker'
14
+
15
+ const matchEmojis = createMatchEmojis({
16
+ emojis: {
17
+ '😂': ['joy', 'laugh'],
18
+ '❤️': ['heart', 'love'],
19
+ '🎉': ['party', 'celebrate'],
20
+ '👍': ['thumbsup', 'yes', 'approve'],
21
+ '🔥': ['fire', 'hot', 'lit'],
22
+ },
23
+ })
11
24
 
12
25
  function EmojiPicker() {
13
26
  const {keyword, matches, selectedIndex, onNavigateTo, onSelect, onDismiss} =
14
27
  useEmojiPicker({matchEmojis})
15
28
 
16
- if (keyword.length < 2) {
29
+ if (keyword.length < 1) {
17
30
  return null
18
31
  }
19
32
 
@@ -43,6 +56,16 @@ function EmojiPicker() {
43
56
  }
44
57
  ```
45
58
 
59
+ **Tip:** For a comprehensive emoji library, you can install [`emojilib`](https://www.npmjs.com/package/emojilib) and use it directly:
60
+
61
+ ```tsx
62
+ import emojilib from 'emojilib'
63
+
64
+ const matchEmojis = createMatchEmojis({
65
+ emojis: emojilib,
66
+ })
67
+ ```
68
+
46
69
  ## How It Works
47
70
 
48
71
  The emoji picker activates when users type `:` followed by a keyword (e.g., `:smile` or `:joy`).
@@ -63,36 +86,66 @@ The emoji picker activates when users type `:` followed by a keyword (e.g., `:sm
63
86
 
64
87
  **Returns:**
65
88
 
66
- - `keyword`: The matches keyword, including colons.
89
+ - `keyword`: The matched keyword.
67
90
  - `matches`: Emoji matches found for the current keyword.
68
91
  - `selectedIndex`: Index of the selected match
69
92
  - `onNavigateTo(index)`: Navigate to a specific match by index.
70
93
  - `onSelect()`: Select the current match.
71
94
  - `onDismiss()`: Dismiss the emoji picker.
72
95
 
73
- ## Custom Emoji Sets
96
+ ## Custom Search Algorithm
74
97
 
75
- The `matchEmojis` function is generic and can return any shape of emoji match required for your UI. However, the default implementation returns `EmojiMatch` objects and can be created using `createMatchEmojis`:
98
+ You can implement a custom search algorithm with your own matching logic and data structures. The only requirement is that your function adheres to the `MatchEmojis` type and returns matches that extend `BaseEmojiMatch`:
76
99
 
77
100
  ```tsx
78
- import {
79
- createMatchEmojis,
80
- useEmojiPicker,
101
+ import type {
102
+ BaseEmojiMatch,
103
+ MatchEmojis,
81
104
  } from '@portabletext/plugin-emoji-picker'
82
105
 
83
- const myMatchEmojis = createMatchEmojis({
84
- emojis: {
85
- '😂': ['joy', 'laugh'],
86
- '😹': ['joy_cat', 'laugh_cat'],
87
- '❤️': ['heart', 'love'],
88
- '🎉': ['party', 'celebrate'],
89
- },
90
- })
106
+ // Custom emoji match type with relevance scoring
107
+ type CustomEmojiMatch = BaseEmojiMatch & {
108
+ key: string
109
+ label: string
110
+ score: number
111
+ }
112
+
113
+ // Custom search algorithm with fuzzy matching and scoring
114
+ const myCustomMatchEmojis: MatchEmojis<CustomEmojiMatch> = ({keyword}) => {
115
+ const emojis = [
116
+ {emoji: '😂', labels: ['joy', 'laugh', 'happy']},
117
+ {emoji: '❤️', labels: ['heart', 'love']},
118
+ {emoji: '🎉', labels: ['party', 'celebrate', 'tada']},
119
+ ]
120
+
121
+ return emojis
122
+ .flatMap(({emoji, labels}) =>
123
+ labels
124
+ .map((label) => {
125
+ // Calculate relevance score
126
+ const isExact = label === keyword
127
+ const score = label.startsWith(keyword)
128
+ ? 100 // Exact prefix match
129
+ : label.includes(keyword)
130
+ ? 50 // Contains keyword
131
+ : 0 // No match
132
+
133
+ return {
134
+ type: isExact ? 'exact' : 'partial',
135
+ key: `${emoji}-${label}`,
136
+ emoji,
137
+ label,
138
+ score,
139
+ } as CustomEmojiMatch
140
+ })
141
+ .filter((match) => match.score > 0),
142
+ )
143
+ .sort((a, b) => b.score - a.score) // Sort by relevance
144
+ .slice(0, 10) // Limit to 10 results
145
+ }
91
146
 
92
147
  function MyEmojiPicker() {
93
- const picker = useEmojiPicker({matchEmojis: myMatchEmojis})
94
- // ... render your UI
148
+ const picker = useEmojiPicker({matchEmojis: myCustomMatchEmojis})
149
+ // ... render your UI with custom match data
95
150
  }
96
151
  ```
97
-
98
- The default `matchEmojis` export includes a comprehensive set of emojis. You can also implement a completely custom matching function that returns any shape you need for your specific UI requirements.