@portabletext/plugin-emoji-picker 1.0.3 → 1.0.4

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/dist/index.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { c } from "react/compiler-runtime";
2
2
  import { useEditor } from "@portabletext/editor";
3
3
  import { useActorRef, useSelector } from "@xstate/react";
4
- import { raise, defineBehavior, effect, forward } from "@portabletext/editor/behaviors";
5
- import * as selectors from "@portabletext/editor/selectors";
6
- import * as utils from "@portabletext/editor/utils";
4
+ import { raise, defineBehavior, effect } from "@portabletext/editor/behaviors";
5
+ import { getFocusSpan, isPointAfterSelection, isPointBeforeSelection, getMarkState, getNextSpan } from "@portabletext/editor/selectors";
7
6
  import { createKeyboardShortcut } from "@portabletext/keyboard-shortcuts";
8
7
  import { defineInputRule, defineInputRuleBehavior } from "@portabletext/plugin-input-rule";
9
- import { setup, or, not, assign, sendTo, fromCallback, assertEvent } from "xstate";
8
+ import { setup, not, assign, sendTo, fromCallback, assertEvent } from "xstate";
10
9
  function createMatchEmojis(config) {
11
10
  return ({
12
11
  keyword
@@ -62,22 +61,99 @@ const arrowUpShortcut = createKeyboardShortcut({
62
61
  default: [{
63
62
  key: "Escape"
64
63
  }]
65
- }), triggerRule = defineInputRule({
64
+ }), getTriggerState = (snapshot) => {
65
+ const focusSpan = getFocusSpan(snapshot), markState = getMarkState(snapshot);
66
+ if (!focusSpan || !markState || !snapshot.context.selection)
67
+ return;
68
+ const focusSpanTextBefore = focusSpan.node.text.slice(0, snapshot.context.selection.focus.offset), focusSpanTextAfter = focusSpan.node.text.slice(snapshot.context.selection.focus.offset), nextSpan = getNextSpan(snapshot);
69
+ return {
70
+ focusSpan,
71
+ markState,
72
+ focusSpanTextBefore,
73
+ focusSpanTextAfter,
74
+ nextSpan
75
+ };
76
+ };
77
+ function createTriggerActions({
78
+ snapshot,
79
+ payload,
80
+ keywordState
81
+ }) {
82
+ if (payload.markState.state === "unchanged") {
83
+ const focusSpan2 = {
84
+ node: {
85
+ _key: payload.focusSpan.node._key,
86
+ _type: payload.focusSpan.node._type,
87
+ text: `${payload.focusSpanTextBefore}${payload.lastMatch.text}${payload.focusSpanTextAfter}`,
88
+ marks: payload.markState.marks
89
+ },
90
+ path: payload.focusSpan.path,
91
+ textBefore: payload.focusSpanTextBefore,
92
+ textAfter: payload.focusSpanTextAfter
93
+ };
94
+ return keywordState === "complete" ? [raise(createKeywordFoundEvent({
95
+ focusSpan: focusSpan2
96
+ }))] : [raise(createTriggerFoundEvent({
97
+ focusSpan: focusSpan2
98
+ }))];
99
+ }
100
+ const newSpan = {
101
+ _key: snapshot.context.keyGenerator(),
102
+ _type: payload.focusSpan.node._type,
103
+ text: payload.lastMatch.text,
104
+ marks: payload.markState.marks
105
+ }, focusSpan = {
106
+ node: {
107
+ _key: newSpan._key,
108
+ _type: newSpan._type,
109
+ text: `${newSpan.text}${payload.nextSpan?.node.text ?? ""}`,
110
+ marks: payload.markState.marks
111
+ },
112
+ path: [{
113
+ _key: payload.focusSpan.path[0]._key
114
+ }, "children", {
115
+ _key: newSpan._key
116
+ }],
117
+ textBefore: "",
118
+ textAfter: payload.nextSpan?.node.text ?? ""
119
+ };
120
+ return [raise({
121
+ type: "select",
122
+ at: payload.lastMatch.targetOffsets
123
+ }), raise({
124
+ type: "delete",
125
+ at: payload.lastMatch.targetOffsets
126
+ }), raise({
127
+ type: "insert.child",
128
+ child: newSpan
129
+ }), ...keywordState === "complete" ? [raise(createKeywordFoundEvent({
130
+ focusSpan
131
+ }))] : [raise(createTriggerFoundEvent({
132
+ focusSpan
133
+ }))]];
134
+ }
135
+ const triggerRule = defineInputRule({
66
136
  on: /:/,
67
137
  guard: ({
138
+ snapshot,
68
139
  event
69
140
  }) => {
70
141
  const lastMatch = event.matches.at(-1);
71
- return lastMatch === void 0 ? !1 : {
72
- keyword: lastMatch.text,
73
- keywordAnchor: {
74
- point: lastMatch.selection.anchor,
75
- blockOffset: lastMatch.targetOffsets.anchor
76
- },
77
- keywordFocus: lastMatch.targetOffsets.focus
78
- };
142
+ if (lastMatch === void 0)
143
+ return !1;
144
+ const triggerState = getTriggerState(snapshot);
145
+ return triggerState ? {
146
+ lastMatch,
147
+ ...triggerState
148
+ } : !1;
79
149
  },
80
- actions: [(_, payload) => [raise(createTriggerFoundEvent(payload))]]
150
+ actions: [({
151
+ snapshot
152
+ }, payload) => createTriggerActions({
153
+ snapshot,
154
+ payload,
155
+ keywordState: "partial"
156
+ })]
81
157
  });
82
158
  function createTriggerFoundEvent(payload) {
83
159
  return {
@@ -88,48 +164,47 @@ function createTriggerFoundEvent(payload) {
88
164
  const partialKeywordRule = defineInputRule({
89
165
  on: /:[\S]+/,
90
166
  guard: ({
167
+ snapshot,
91
168
  event
92
169
  }) => {
93
170
  const lastMatch = event.matches.at(-1);
94
- if (lastMatch === void 0)
171
+ if (lastMatch === void 0 || lastMatch.targetOffsets.anchor.offset < event.textBefore.length)
95
172
  return !1;
96
- const keyword = lastMatch.text, keywordAnchor = {
97
- point: lastMatch.selection.anchor,
98
- blockOffset: lastMatch.targetOffsets.anchor
99
- }, keywordFocus = lastMatch.targetOffsets.focus;
100
- return {
101
- keyword,
102
- keywordAnchor,
103
- keywordFocus
104
- };
173
+ const triggerState = getTriggerState(snapshot);
174
+ return triggerState ? {
175
+ ...triggerState,
176
+ lastMatch
177
+ } : !1;
105
178
  },
106
- actions: [(_, payload) => [raise(createPartialKeywordFoundEvent(payload))]]
107
- });
108
- function createPartialKeywordFoundEvent(payload) {
109
- return {
110
- type: "custom.partial keyword found",
111
- ...payload
112
- };
113
- }
114
- const keywordRule = defineInputRule({
179
+ actions: [({
180
+ snapshot
181
+ }, payload) => createTriggerActions({
182
+ snapshot,
183
+ payload,
184
+ keywordState: "partial"
185
+ })]
186
+ }), keywordRule = defineInputRule({
115
187
  on: /:[\S]+:/,
116
188
  guard: ({
189
+ snapshot,
117
190
  event
118
191
  }) => {
119
192
  const lastMatch = event.matches.at(-1);
120
- if (lastMatch === void 0)
193
+ if (lastMatch === void 0 || lastMatch.targetOffsets.anchor.offset < event.textBefore.length)
121
194
  return !1;
122
- const keyword = lastMatch.text, keywordAnchor = {
123
- point: lastMatch.selection.anchor,
124
- blockOffset: lastMatch.targetOffsets.anchor
125
- }, keywordFocus = lastMatch.targetOffsets.focus;
126
- return {
127
- keyword,
128
- keywordAnchor,
129
- keywordFocus
130
- };
195
+ const triggerState = getTriggerState(snapshot);
196
+ return triggerState ? {
197
+ ...triggerState,
198
+ lastMatch
199
+ } : !1;
131
200
  },
132
- actions: [(_, payload) => [raise(createKeywordFoundEvent(payload))]]
201
+ actions: [({
202
+ snapshot
203
+ }, payload) => createTriggerActions({
204
+ snapshot,
205
+ payload,
206
+ keywordState: "complete"
207
+ })]
133
208
  });
134
209
  function createKeywordFoundEvent(payload) {
135
210
  return {
@@ -154,15 +229,6 @@ const triggerListenerCallback = ({
154
229
  sendBack(event);
155
230
  })]]
156
231
  })
157
- }), input.editor.registerBehavior({
158
- behavior: defineBehavior({
159
- on: "custom.partial keyword found",
160
- actions: [({
161
- event
162
- }) => [effect(() => {
163
- sendBack(event);
164
- })]]
165
- })
166
232
  }), input.editor.registerBehavior({
167
233
  behavior: defineBehavior({
168
234
  on: "custom.trigger found",
@@ -238,10 +304,16 @@ const triggerListenerCallback = ({
238
304
  type: "dismiss"
239
305
  });
240
306
  }), raise({
241
- type: "delete.text",
307
+ type: "delete",
242
308
  at: {
243
- anchor: event.anchor,
244
- focus: event.focus
309
+ anchor: {
310
+ path: event.focusSpan.path,
311
+ offset: event.focusSpan.textBefore.length
312
+ },
313
+ focus: {
314
+ path: event.focusSpan.path,
315
+ offset: event.focusSpan.node.text.length - event.focusSpan.textAfter.length
316
+ }
245
317
  }
246
318
  }), raise({
247
319
  type: "insert.text",
@@ -265,22 +337,19 @@ const triggerListenerCallback = ({
265
337
  }) => {
266
338
  if (!enterShortcut.guard(event.originEvent) && !tabShortcut.guard(event.originEvent))
267
339
  return !1;
268
- const anchor = context.keywordAnchor?.blockOffset, focus = context.keywordFocus, match = context.matches[context.selectedIndex];
269
- return match && anchor && focus ? {
270
- anchor,
271
- focus,
340
+ const focusSpan = context.focusSpan, match = context.matches[context.selectedIndex];
341
+ return match && focusSpan ? {
342
+ focusSpan,
272
343
  emoji: match.emoji
273
344
  } : !1;
274
345
  },
275
346
  actions: [(_, {
276
- anchor,
277
- focus,
347
+ focusSpan,
278
348
  emoji
279
349
  }) => [raise({
280
350
  type: "custom.insert emoji",
281
351
  emoji,
282
- anchor,
283
- focus
352
+ focusSpan
284
353
  })]]
285
354
  })
286
355
  }), input.context.editor.registerBehavior({
@@ -295,19 +364,6 @@ const triggerListenerCallback = ({
295
364
  });
296
365
  })]]
297
366
  })
298
- }), input.context.editor.registerBehavior({
299
- behavior: defineInputRuleBehavior({
300
- rules: [keywordRule]
301
- })
302
- }), input.context.editor.registerBehavior({
303
- behavior: defineBehavior({
304
- on: "custom.keyword found",
305
- actions: [({
306
- event
307
- }) => [effect(() => {
308
- sendBack(event);
309
- })]]
310
- })
311
367
  })];
312
368
  return () => {
313
369
  for (const unregister of unregisterBehaviors)
@@ -322,75 +378,7 @@ const triggerListenerCallback = ({
322
378
  type: "selection changed",
323
379
  snapshot
324
380
  });
325
- }).unsubscribe, textChangeListener = ({
326
- sendBack,
327
- input
328
- }) => {
329
- const unregisterBehaviors = [input.editor.registerBehavior({
330
- behavior: defineBehavior({
331
- on: "insert.text",
332
- guard: ({
333
- snapshot
334
- }) => snapshot.context.selection ? {
335
- focus: snapshot.context.selection.focus
336
- } : !1,
337
- actions: [({
338
- event
339
- }, {
340
- focus
341
- }) => [effect(() => {
342
- sendBack({
343
- ...event,
344
- focus
345
- });
346
- }), forward(event)]]
347
- })
348
- }), input.editor.registerBehavior({
349
- behavior: defineBehavior({
350
- on: "delete.backward",
351
- guard: ({
352
- snapshot,
353
- event
354
- }) => event.unit === "character" && snapshot.context.selection ? {
355
- focus: snapshot.context.selection.focus
356
- } : !1,
357
- actions: [({
358
- event
359
- }, {
360
- focus
361
- }) => [effect(() => {
362
- sendBack({
363
- type: "delete.backward",
364
- focus
365
- });
366
- }), forward(event)]]
367
- })
368
- }), input.editor.registerBehavior({
369
- behavior: defineBehavior({
370
- on: "delete.forward",
371
- guard: ({
372
- snapshot,
373
- event
374
- }) => event.unit === "character" && snapshot.context.selection ? {
375
- focus: snapshot.context.selection.focus
376
- } : !1,
377
- actions: [({
378
- event
379
- }, {
380
- focus
381
- }) => [effect(() => {
382
- sendBack({
383
- type: "delete.forward",
384
- focus
385
- });
386
- }), forward(event)]]
387
- })
388
- })];
389
- return () => {
390
- for (const unregister of unregisterBehaviors)
391
- unregister();
392
- };
393
- }, emojiPickerMachine = setup({
381
+ }).unsubscribe, emojiPickerMachine = setup({
394
382
  types: {
395
383
  context: {},
396
384
  input: {},
@@ -402,60 +390,44 @@ const triggerListenerCallback = ({
402
390
  "arrow listener": fromCallback(arrowListenerCallback),
403
391
  "trigger listener": fromCallback(triggerListenerCallback),
404
392
  "escape listener": fromCallback(escapeListenerCallback),
405
- "selection listener": fromCallback(selectionListenerCallback),
406
- "text change listener": fromCallback(textChangeListener)
393
+ "selection listener": fromCallback(selectionListenerCallback)
407
394
  },
408
395
  actions: {
409
- "init keyword": assign({
410
- keyword: ({
411
- context,
412
- event
413
- }) => event.type !== "custom.trigger found" && event.type !== "custom.partial keyword found" && event.type !== "custom.keyword found" ? context.keyword : event.keyword
414
- }),
415
- "set keyword anchor": assign({
416
- keywordAnchor: ({
396
+ "set focus span": assign({
397
+ focusSpan: ({
417
398
  context,
418
399
  event
419
- }) => event.type !== "custom.trigger found" && event.type !== "custom.partial keyword found" && event.type !== "custom.keyword found" ? context.keywordAnchor : event.keywordAnchor
400
+ }) => event.type !== "custom.trigger found" && event.type !== "custom.keyword found" ? context.focusSpan : event.focusSpan
420
401
  }),
421
- "set keyword focus": assign({
422
- keywordFocus: ({
423
- context,
424
- event
425
- }) => event.type !== "custom.trigger found" && event.type !== "custom.partial keyword found" && event.type !== "custom.keyword found" ? context.keywordFocus : event.keywordFocus
426
- }),
427
- "update keyword focus": assign({
428
- keywordFocus: ({
429
- context,
430
- event
431
- }) => (assertEvent(event, ["insert.text", "delete.backward", "delete.forward"]), context.keywordFocus ? {
432
- path: context.keywordFocus.path,
433
- offset: event.type === "insert.text" ? context.keywordFocus.offset + event.text.length : event.type === "delete.backward" || event.type === "delete.forward" ? context.keywordFocus.offset - 1 : event.focus.offset
434
- } : context.keywordFocus)
402
+ "update focus span": assign({
403
+ focusSpan: ({
404
+ context
405
+ }) => {
406
+ if (!context.focusSpan)
407
+ return;
408
+ const snapshot = context.editor.getSnapshot(), focusSpan = getFocusSpan(snapshot);
409
+ if (!focusSpan || JSON.stringify(focusSpan.path) !== JSON.stringify(context.focusSpan.path) || !focusSpan.node.text.startsWith(context.focusSpan.textBefore) || !focusSpan.node.text.endsWith(context.focusSpan.textAfter))
410
+ return;
411
+ const keywordAnchor = {
412
+ path: focusSpan.path,
413
+ offset: context.focusSpan.textBefore.length
414
+ }, keywordFocus = {
415
+ path: focusSpan.path,
416
+ offset: focusSpan.node.text.length - context.focusSpan.textAfter.length
417
+ }, selectionIsBeforeKeyword = isPointAfterSelection(keywordAnchor)(snapshot), selectionIsAfterKeyword = isPointBeforeSelection(keywordFocus)(snapshot);
418
+ if (!(selectionIsBeforeKeyword || selectionIsAfterKeyword))
419
+ return {
420
+ node: focusSpan.node,
421
+ path: focusSpan.path,
422
+ textBefore: context.focusSpan.textBefore,
423
+ textAfter: context.focusSpan.textAfter
424
+ };
425
+ }
435
426
  }),
436
427
  "update keyword": assign({
437
428
  keyword: ({
438
- context,
439
- event
440
- }) => {
441
- if (assertEvent(event, "selection changed"), !context.keywordAnchor || !context.keywordFocus)
442
- return "";
443
- const keywordFocusPoint = utils.blockOffsetToSpanSelectionPoint({
444
- context: event.snapshot.context,
445
- blockOffset: context.keywordFocus,
446
- direction: "forward"
447
- });
448
- return keywordFocusPoint ? selectors.getSelectionText({
449
- ...event.snapshot,
450
- context: {
451
- ...event.snapshot.context,
452
- selection: {
453
- anchor: context.keywordAnchor.point,
454
- focus: keywordFocusPoint
455
- }
456
- }
457
- }) : "";
458
- }
429
+ context
430
+ }) => context.focusSpan ? context.focusSpan.textBefore.length > 0 && context.focusSpan.textAfter.length > 0 ? context.focusSpan.node.text.slice(context.focusSpan.textBefore.length, -context.focusSpan.textAfter.length) : context.focusSpan.textBefore.length > 0 ? context.focusSpan.node.text.slice(context.focusSpan.textBefore.length) : context.focusSpan.textAfter.length > 0 ? context.focusSpan.node.text.slice(0, -context.focusSpan.textAfter.length) : context.focusSpan.node.text : ""
459
431
  }),
460
432
  "update matches": assign({
461
433
  matches: ({
@@ -485,12 +457,6 @@ const triggerListenerCallback = ({
485
457
  event
486
458
  }) => (assertEvent(event, "navigate to"), event.index)
487
459
  }),
488
- "update emoji insert listener context": sendTo("emoji insert listener", ({
489
- context
490
- }) => ({
491
- type: "context changed",
492
- context
493
- })),
494
460
  "update submit listener context": sendTo("submit listener", ({
495
461
  context
496
462
  }) => ({
@@ -498,86 +464,52 @@ const triggerListenerCallback = ({
498
464
  context
499
465
  })),
500
466
  "insert selected match": ({
501
- context,
502
- event
467
+ context
503
468
  }) => {
504
469
  const match = context.matches[context.selectedIndex];
505
- !match || !context.keywordAnchor || !context.keywordFocus || event.type === "custom.keyword found" && match.type !== "exact" || context.editor.send({
470
+ !match || !context.focusSpan || context.editor.send({
506
471
  type: "custom.insert emoji",
507
472
  emoji: match.emoji,
508
- anchor: context.keywordAnchor.blockOffset,
509
- focus: context.keywordFocus
473
+ focusSpan: context.focusSpan
510
474
  });
511
475
  },
512
476
  reset: assign({
513
- keywordAnchor: void 0,
514
- keywordFocus: void 0,
477
+ focusSpan: void 0,
515
478
  keyword: "",
516
479
  matches: [],
517
480
  selectedIndex: 0
518
481
  })
519
482
  },
520
483
  guards: {
484
+ "no focus span": ({
485
+ context
486
+ }) => !context.focusSpan,
521
487
  "has matches": ({
522
488
  context
523
489
  }) => context.matches.length > 0,
524
490
  "no matches": not("has matches"),
525
- "keyword is wel-formed": ({
491
+ "keyword is malformed": ({
492
+ context
493
+ }) => !context.incompleteKeywordRegex.test(context.keyword),
494
+ "keyword is direct match": ({
526
495
  context
527
- }) => context.incompleteKeywordRegex.test(context.keyword),
528
- "keyword is malformed": not("keyword is wel-formed"),
529
- "selection is before keyword": ({
530
- context,
531
- event
532
- }) => (assertEvent(event, "selection changed"), context.keywordAnchor ? selectors.isPointAfterSelection(context.keywordAnchor.point)(event.snapshot) : !0),
533
- "selection is after keyword": ({
534
- context,
535
- event
536
- }) => {
537
- if (assertEvent(event, "selection changed"), context.keywordFocus === void 0)
538
- return !0;
539
- const keywordFocusPoint = utils.blockOffsetToSpanSelectionPoint({
540
- context: event.snapshot.context,
541
- blockOffset: context.keywordFocus,
542
- direction: "forward"
543
- });
544
- return keywordFocusPoint ? selectors.isPointBeforeSelection(keywordFocusPoint)(event.snapshot) : !0;
545
- },
546
- "selection is expanded": ({
547
- event
548
- }) => (assertEvent(event, "selection changed"), selectors.isSelectionExpanded(event.snapshot)),
549
- "selection moved unexpectedly": or(["selection is before keyword", "selection is after keyword", "selection is expanded"]),
550
- "unexpected text insertion": ({
551
- context,
552
- event
553
496
  }) => {
554
- if (event.type !== "insert.text" || !context.keywordAnchor)
497
+ if (!/^:[\S]+:$/.test(context.keyword))
555
498
  return !1;
556
- const snapshot = context.editor.getSnapshot();
557
- return selectors.isPointBeforeSelection(event.focus)({
558
- ...snapshot,
559
- context: {
560
- ...snapshot.context,
561
- selection: {
562
- anchor: context.keywordAnchor.point,
563
- focus: context.keywordAnchor.point
564
- }
565
- }
566
- }) || utils.isEqualSelectionPoints(event.focus, context.keywordAnchor.point);
499
+ const match = context.matches.at(context.selectedIndex);
500
+ return !(!match || match.type !== "exact");
567
501
  }
568
502
  }
569
503
  }).createMachine({
570
- /** @xstate-layout N4IgpgJg5mDOIC5RgLYHsBWBLABABywGMBrMAJwDosIAbMAYkLRrQDsctXZyAXSAbQAMAXUSg8aWFh5Y2YkAA9EARmUB2AJwUAzADYNADgCs65YO1q1ygDQgAnojUG1O5c+W7tAJmdfdRgF8A21RMXAIScgpuAEMyQgALTih6Tm4yHgo+BR4hUSQQCSkZOQKlBABaZW0DHSMAFksNQUF6oyNzL1sHBC9vCnrGtS8GtQaNNt0gkPRsfCJSSlj4pNYUiDA6PgoAMzQyAHc4iDz5IulZVnlyr3MKE30LA31DZoNuxD6vAaHdP29vOo1NNwLNwgsostEsl6BstmAKAAjGIkI5kE4iM6SC6lUDlerabT3arDfS3eoaPQfXr9QaWEaNcaTEGhOYRRbRMBxaFrWFYWAofmwU4Fc4lK5lFTqWqDAwUjReeoGbwaNTU1TPCh-QxNNS6XQGHwssHzSJLLkrGHcOiEcU4RIxNYCTGi7Hi66IfxE1oeZX1EbeZXUhUUZSKjxOOV6bTmY1hU0cqGrFLWsC2y72hKOmAnZT5cRuy4ehDVXQUVXDIyWGpmAzveyfLRKwQaVRVwR1ixeONsiHm7nJ+gigvFIuSkvKVuhgwaEwKmMKwbqkaCAaverqVuvKbBUHx9mQi08qAUVhoHAoGI8RJwHCwBJoA4w4eFQu4xSfaoDA3KOmCVSTn06r-i4-hGH0ZiEoI4H1D24JmpyA7JNED5PmsF5XjesD0KwMQAG5YFAV5gDgECPqwL5imOeKIIM9ShsoRh1i2erPB41L6C40GqISUb6n8cEJoeSFrChj7JBh14JHAOH4YRxE4AArnglFvhKNEIGoq4+E0yraPULa6PUHGqhQ3HVDUBL8dogkHv2lqife4noZeUkybhBFEXwOA8Ggqmju+5RGPqFBqP6ujDD4v4tjYDYIMqLjVKo5gdM4TGBLurLwYmR7JmJaFQJJWGpFwvB3psaZ8BARUJP5OLqR+CD1Loq5ymYfyeP4spGOqv70fpv7NBSBKtBlMz7n2iEOSeTkFTVMl1e645eB49wGP+K0UpBbjaMBzQUF4IzBYq7TNa2QS7meGzwAUWVCWQWIBQ15RVJq2ijJoLRtB03jUhUVYUHKtz-gqeoxkYGi2ZN1B0I99XFqobTlh4-5-Ot4H1j0ZirbcENhR4RmKrBmUmnZU3HnDS0aVUjHlh2cqtkqfTBdSSr0RMGieBS7htASUMIUmyFnvNsB3qhySU9RjUVBFdN1ltTPvbowZOGZEWHe9xgTHo-M5SJM3iy5mHSTdI7w+OlnlgY6heJzbgUv4ytxaqtSCBFg1eJFM4XQEQA */
571
504
  id: "emoji picker",
572
505
  context: ({
573
506
  input
574
507
  }) => ({
575
508
  editor: input.editor,
576
509
  keyword: "",
577
- keywordAnchor: void 0,
578
- keywordFocus: void 0,
510
+ focusSpan: void 0,
579
511
  matchEmojis: input.matchEmojis,
580
- incompleteKeywordRegex: /:[\S]*$/,
512
+ incompleteKeywordRegex: /^:[\S]*$/,
581
513
  matches: [],
582
514
  selectedIndex: 0
583
515
  }),
@@ -605,14 +537,10 @@ const triggerListenerCallback = ({
605
537
  on: {
606
538
  "custom.trigger found": {
607
539
  target: "searching",
608
- actions: ["set keyword anchor", "set keyword focus", "init keyword"]
609
- },
610
- "custom.partial keyword found": {
611
- target: "searching",
612
- actions: ["set keyword anchor", "set keyword focus", "init keyword"]
540
+ actions: ["set focus span", "update keyword"]
613
541
  },
614
542
  "custom.keyword found": {
615
- actions: ["set keyword anchor", "set keyword focus", "init keyword", "update matches", "insert selected match"],
543
+ actions: ["set focus span", "update keyword", "update matches", "insert selected match"],
616
544
  target: "idle",
617
545
  reenter: !0
618
546
  }
@@ -641,43 +569,25 @@ const triggerListenerCallback = ({
641
569
  }) => ({
642
570
  editor: context.editor
643
571
  })
644
- }, {
645
- src: "text change listener",
646
- input: ({
647
- context
648
- }) => ({
649
- editor: context.editor
650
- })
651
572
  }],
652
573
  on: {
653
- "custom.keyword found": {
654
- actions: ["set keyword anchor", "set keyword focus", "init keyword", "update matches", "insert selected match"]
655
- },
656
- "insert.text": [{
657
- guard: "unexpected text insertion",
658
- target: "idle"
659
- }, {
660
- actions: ["update keyword focus"]
661
- }],
662
- "delete.forward": {
663
- actions: ["update keyword focus"]
664
- },
665
- "delete.backward": {
666
- actions: ["update keyword focus"]
667
- },
668
574
  dismiss: {
669
575
  target: "idle"
670
576
  },
671
577
  "selection changed": [{
672
- guard: "selection moved unexpectedly",
673
- target: "idle"
674
- }, {
675
- actions: ["update keyword", "update matches", "reset selected index", "update submit listener context"]
578
+ actions: ["update focus span", "update keyword", "update matches", "reset selected index", "update submit listener context"]
676
579
  }]
677
580
  },
678
581
  always: [{
582
+ guard: "no focus span",
583
+ target: "idle"
584
+ }, {
679
585
  guard: "keyword is malformed",
680
586
  target: "idle"
587
+ }, {
588
+ guard: "keyword is direct match",
589
+ actions: ["insert selected match"],
590
+ target: "idle"
681
591
  }],
682
592
  initial: "no matches showing",
683
593
  states: {