@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 +73 -20
- package/dist/index.cjs +6 -1908
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -9
- package/dist/index.d.ts +2 -9
- package/dist/index.js +6 -1908
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/create-match-emojis.ts +0 -8
- package/src/emoji-picker-machine.tsx +7 -6
- package/src/emoji-picker.feature +25 -3
- package/src/emoji-picker.test.tsx +7 -1
- package/src/use-emoji-picker.ts +10 -6
- package/src/emojis.ts +0 -15216
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/plugin-emoji-picker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Easily configure an Emoji Picker for the Portable Text Editor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"portabletext",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
"typescript": "5.9.3",
|
|
57
57
|
"typescript-eslint": "^8.46.1",
|
|
58
58
|
"vitest": "^3.2.4",
|
|
59
|
-
"
|
|
59
|
+
"@portabletext/editor": "2.15.5",
|
|
60
60
|
"@portabletext/schema": "1.2.0",
|
|
61
|
-
"
|
|
61
|
+
"racejar": "1.3.2"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"@portabletext/editor": "^2.15.5",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {emojis} from './emojis'
|
|
2
1
|
import type {MatchEmojis} from './match-emojis'
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -43,13 +42,6 @@ export type EmojiMatch =
|
|
|
43
42
|
endSlice: string
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
/**
|
|
47
|
-
* Proposed, but not required, default implementation of `MatchEmojis`.
|
|
48
|
-
*
|
|
49
|
-
* @beta
|
|
50
|
-
*/
|
|
51
|
-
export const matchEmojis = createMatchEmojis({emojis})
|
|
52
|
-
|
|
53
45
|
/**
|
|
54
46
|
* Proposed, but not required, function to create a `MatchEmojis` function.
|
|
55
47
|
*
|
|
@@ -97,7 +97,7 @@ function createTriggerFoundEvent(payload: {
|
|
|
97
97
|
* Listen for a partial keyword like ":joy"
|
|
98
98
|
*/
|
|
99
99
|
const partialKeywordRule = defineInputRule({
|
|
100
|
-
on: /:[
|
|
100
|
+
on: /:[\S]+/,
|
|
101
101
|
guard: ({event}) => {
|
|
102
102
|
const lastMatch = event.matches.at(-1)
|
|
103
103
|
|
|
@@ -139,7 +139,7 @@ function createPartialKeywordFoundEvent(payload: {
|
|
|
139
139
|
* Listen for a complete keyword like ":joy:"
|
|
140
140
|
*/
|
|
141
141
|
const keywordRule = defineInputRule({
|
|
142
|
-
on: /:[
|
|
142
|
+
on: /:[\S]+:/,
|
|
143
143
|
guard: ({event}) => {
|
|
144
144
|
const lastMatch = event.matches.at(-1)
|
|
145
145
|
|
|
@@ -675,9 +675,10 @@ export const emojiPickerMachine = setup({
|
|
|
675
675
|
? context.keyword.slice(1)
|
|
676
676
|
: context.keyword
|
|
677
677
|
// Strip trailing colon
|
|
678
|
-
rawKeyword =
|
|
679
|
-
|
|
680
|
-
|
|
678
|
+
rawKeyword =
|
|
679
|
+
rawKeyword.length > 1 && rawKeyword.endsWith(':')
|
|
680
|
+
? rawKeyword.slice(0, -1)
|
|
681
|
+
: rawKeyword
|
|
681
682
|
|
|
682
683
|
if (rawKeyword === undefined) {
|
|
683
684
|
return []
|
|
@@ -837,7 +838,7 @@ export const emojiPickerMachine = setup({
|
|
|
837
838
|
keywordAnchor: undefined,
|
|
838
839
|
keywordFocus: undefined,
|
|
839
840
|
matchEmojis: input.matchEmojis,
|
|
840
|
-
incompleteKeywordRegex: /:
|
|
841
|
+
incompleteKeywordRegex: /:[\S]*$/,
|
|
841
842
|
matches: [],
|
|
842
843
|
selectedIndex: 0,
|
|
843
844
|
}),
|
package/src/emoji-picker.feature
CHANGED
|
@@ -32,14 +32,14 @@ Feature: Emoji Picker
|
|
|
32
32
|
Scenario: Picking wrong direct hit
|
|
33
33
|
When ":jo:" is typed
|
|
34
34
|
Then the text is ":jo:"
|
|
35
|
-
And the keyword is "
|
|
36
|
-
And the matches are "
|
|
35
|
+
And the keyword is "jo"
|
|
36
|
+
And the matches are "đ,đš,đšī¸"
|
|
37
37
|
|
|
38
38
|
Scenario: Colon after wrong direct hit
|
|
39
39
|
When ":jo:" is typed
|
|
40
40
|
And ":" is typed
|
|
41
41
|
Then the text is ":jo::"
|
|
42
|
-
And the keyword is ":
|
|
42
|
+
And the keyword is "jo:"
|
|
43
43
|
And the matches are ""
|
|
44
44
|
|
|
45
45
|
Scenario: Picking wrong direct hit after undoing direct hit
|
|
@@ -174,3 +174,25 @@ Feature: Emoji Picker
|
|
|
174
174
|
| text | position | keyword | button | final text |
|
|
175
175
|
| "foo bar baz" | after "foo" | ":j" | "{ArrowRight}" | "foo:j \|bar baz" |
|
|
176
176
|
| "foo bar baz" | after "foo" | ":j" | "{ArrowLeft}{ArrowLeft}{ArrowLeft}" | "fo\|o:j bar baz" |
|
|
177
|
+
|
|
178
|
+
Scenario: Dismissing by pressing Space
|
|
179
|
+
Given the text ""
|
|
180
|
+
When ":joy" is typed
|
|
181
|
+
Then the keyword is "joy"
|
|
182
|
+
When " " is typed
|
|
183
|
+
Then the keyword is ""
|
|
184
|
+
|
|
185
|
+
Scenario Outline: Allow special characters
|
|
186
|
+
Given the text <text>
|
|
187
|
+
When <inserted text> is inserted
|
|
188
|
+
Then the keyword is <keyword>
|
|
189
|
+
And the matches are <matches>
|
|
190
|
+
|
|
191
|
+
Examples:
|
|
192
|
+
| text | inserted text | keyword | matches |
|
|
193
|
+
| "" | ":joy!" | "joy!" | "đšī¸" |
|
|
194
|
+
| "" | ":*" | "*" | "đ" |
|
|
195
|
+
| "" | ":!" | "!" | "đšī¸,âī¸,âī¸,âŧī¸" |
|
|
196
|
+
| "" | ":!!" | "!!" | "âŧī¸" |
|
|
197
|
+
| "" | "::)" | ":)" | "đ" |
|
|
198
|
+
| "" | "::" | ":" | "đ" |
|
|
@@ -64,6 +64,12 @@ Feature({
|
|
|
64
64
|
const emojis: Record<string, Array<string>> = {
|
|
65
65
|
'đ': ['joy'],
|
|
66
66
|
'đš': ['joy_cat'],
|
|
67
|
+
'đšī¸': ['joy!stick'],
|
|
68
|
+
'đ': ['*'],
|
|
69
|
+
'âī¸': ['!'],
|
|
70
|
+
'âī¸': ['!?'],
|
|
71
|
+
'âŧī¸': ['!!'],
|
|
72
|
+
'đ': [':)'],
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
const matchEmojis = createMatchEmojis({emojis})
|
|
@@ -75,7 +81,7 @@ function EmojiPickerPlugin() {
|
|
|
75
81
|
<>
|
|
76
82
|
<div data-testid="keyword">{keyword}</div>
|
|
77
83
|
<div data-testid="matches">
|
|
78
|
-
{matches.map((match) => match.emoji).join(',
|
|
84
|
+
{matches.map((match) => match.emoji).join(',')}
|
|
79
85
|
</div>
|
|
80
86
|
</>
|
|
81
87
|
)
|
package/src/use-emoji-picker.ts
CHANGED
|
@@ -9,14 +9,14 @@ import type {BaseEmojiMatch, MatchEmojis} from './match-emojis'
|
|
|
9
9
|
*/
|
|
10
10
|
export type EmojiPicker<TEmojiMatch extends BaseEmojiMatch = BaseEmojiMatch> = {
|
|
11
11
|
/**
|
|
12
|
-
* The matched keyword
|
|
12
|
+
* The matched keyword.
|
|
13
13
|
*
|
|
14
14
|
* Can be used to display the keyword in the UI or conditionally render the
|
|
15
15
|
* list of matches.
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```tsx
|
|
19
|
-
* if (keyword.length <
|
|
19
|
+
* if (keyword.length < 1) {
|
|
20
20
|
* return null
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
@@ -145,10 +145,14 @@ export function useEmojiPicker<
|
|
|
145
145
|
const emojiPickerActor = useActorRef(emojiPickerMachine, {
|
|
146
146
|
input: {editor, matchEmojis: props.matchEmojis},
|
|
147
147
|
})
|
|
148
|
-
const keyword = useSelector(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
const keyword = useSelector(emojiPickerActor, (snapshot) => {
|
|
149
|
+
const rawKeyword = snapshot.context.keyword.startsWith(':')
|
|
150
|
+
? snapshot.context.keyword.slice(1)
|
|
151
|
+
: snapshot.context.keyword
|
|
152
|
+
return rawKeyword.length > 1 && rawKeyword.endsWith(':')
|
|
153
|
+
? rawKeyword.slice(0, -1)
|
|
154
|
+
: rawKeyword
|
|
155
|
+
})
|
|
152
156
|
const matches = useSelector(
|
|
153
157
|
emojiPickerActor,
|
|
154
158
|
(snapshot) => snapshot.context.matches as ReadonlyArray<TEmojiMatch>,
|