@portabletext/plugin-typeahead-picker 2.0.5 → 2.1.0
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 +37 -0
- package/dist/index.d.ts +74 -2
- package/dist/index.js +28 -27
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -183,6 +183,41 @@ const commandPicker = defineTypeaheadPicker<CommandMatch>({
|
|
|
183
183
|
|
|
184
184
|
`/heading` shows matching commands, but only when `/` is at the start of a block. Text like `hello /heading` will NOT trigger the picker.
|
|
185
185
|
|
|
186
|
+
### Picker with guard
|
|
187
|
+
|
|
188
|
+
Use `guard` to conditionally prevent the picker from activating. The guard runs at trigger time (when the trigger character is typed) and has the same signature as a behavior guard, receiving `snapshot`, `event`, and `dom`.
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
const emojiPicker = defineTypeaheadPicker<EmojiMatch>({
|
|
192
|
+
trigger: /:/,
|
|
193
|
+
keyword: /\S*/,
|
|
194
|
+
delimiter: ':',
|
|
195
|
+
getMatches: ({keyword}) => searchEmojis(keyword),
|
|
196
|
+
|
|
197
|
+
// Guard runs when `:` is typed - return false to block activation
|
|
198
|
+
guard: ({snapshot, event, dom}) => {
|
|
199
|
+
// Don't activate if another UI element is open
|
|
200
|
+
if (isDialogOpen()) {
|
|
201
|
+
return false
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return true
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
actions: [
|
|
208
|
+
({event}) => [
|
|
209
|
+
raise({type: 'delete', at: event.patternSelection}),
|
|
210
|
+
raise({type: 'insert.text', text: event.match.emoji}),
|
|
211
|
+
],
|
|
212
|
+
],
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The guard is useful for:
|
|
217
|
+
|
|
218
|
+
- Avoiding conflicts when another picker or dialog is already open
|
|
219
|
+
- Checking editor state or mode before allowing the picker
|
|
220
|
+
|
|
186
221
|
## API Reference
|
|
187
222
|
|
|
188
223
|
### `defineTypeaheadPicker(config)`
|
|
@@ -196,6 +231,7 @@ Creates a picker definition to pass to `useTypeaheadPicker`.
|
|
|
196
231
|
| `trigger` | `RegExp` | Pattern that activates the picker. Can include `^` for start-of-block triggers. Must be single-character (e.g., `/:/`, `/@/`, `/^\//`). |
|
|
197
232
|
| `keyword` | `RegExp` | Pattern matching characters after the trigger (e.g., `/\S*/`, `/\w*/`). |
|
|
198
233
|
| `delimiter` | `string?` | Optional delimiter that triggers auto-completion (e.g., `':'` for `:joy:`) |
|
|
234
|
+
| `guard` | `TypeaheadTriggerGuard?` | Optional guard that runs at trigger time to conditionally prevent activation |
|
|
199
235
|
| `mode` | `'sync' \| 'async'` | Whether `getMatches` returns synchronously or a Promise (default: `'sync'`) |
|
|
200
236
|
| `debounceMs` | `number?` | Delay in ms before calling `getMatches`. Useful for both async (API calls) and sync (expensive local search) modes. (default: `0`) |
|
|
201
237
|
| `getMatches` | `(ctx: {keyword: string}) => TMatch[]` | Function that returns matches for the keyword |
|
|
@@ -463,6 +499,7 @@ The following keyboard shortcuts are handled automatically by the picker:
|
|
|
463
499
|
- **Check position anchors**: `^` means start of block, not start of line. `hello /command` won't match `/^\//`
|
|
464
500
|
- **Check for conflicts**: Only one picker can be active at a time
|
|
465
501
|
- **Avoid multi-character triggers**: Triggers like `/##/` don't work because the picker only activates on newly typed single characters
|
|
502
|
+
- **Check guard**: If you have a `guard` configured, ensure it's returning `true` when activation should be allowed
|
|
466
503
|
|
|
467
504
|
### Auto-completion doesn't work
|
|
468
505
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type {EditorSelection} from '@portabletext/editor'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
BehaviorActionSet,
|
|
4
|
+
BehaviorGuard,
|
|
5
|
+
} from '@portabletext/editor/behaviors'
|
|
3
6
|
|
|
4
7
|
declare type AsyncConfigWithDelimiter<TMatch extends AutoCompleteMatch> =
|
|
5
8
|
BaseConfigWithDelimiter<TMatch> & {
|
|
@@ -89,6 +92,11 @@ declare type BaseConfigWithDelimiter<TMatch extends AutoCompleteMatch> = {
|
|
|
89
92
|
* @example `':'` - typing `:joy:` auto-inserts the joy emoji
|
|
90
93
|
*/
|
|
91
94
|
delimiter: string
|
|
95
|
+
/**
|
|
96
|
+
* Guard function that runs at trigger time to conditionally prevent activation.
|
|
97
|
+
* Return `false` to block activation, or `true` to allow it.
|
|
98
|
+
*/
|
|
99
|
+
guard?: TypeaheadTriggerGuard
|
|
92
100
|
/**
|
|
93
101
|
* Actions to execute when a match is selected.
|
|
94
102
|
* Typically deletes the trigger text and inserts the selected content.
|
|
@@ -113,6 +121,11 @@ declare type BaseConfigWithoutDelimiter<TMatch extends object> = {
|
|
|
113
121
|
*/
|
|
114
122
|
keyword: RegExp
|
|
115
123
|
delimiter?: undefined
|
|
124
|
+
/**
|
|
125
|
+
* Guard function that runs at trigger time to conditionally prevent activation.
|
|
126
|
+
* Return `false` to block activation, or `true` to allow it.
|
|
127
|
+
*/
|
|
128
|
+
guard?: TypeaheadTriggerGuard
|
|
116
129
|
/**
|
|
117
130
|
* Actions to execute when a match is selected.
|
|
118
131
|
* Typically deletes the trigger text and inserts the selected content.
|
|
@@ -156,6 +169,24 @@ declare type BaseConfigWithoutDelimiter<TMatch extends object> = {
|
|
|
156
169
|
* })
|
|
157
170
|
* ```
|
|
158
171
|
*
|
|
172
|
+
* @example Picker with guard (runs at trigger time)
|
|
173
|
+
* ```ts
|
|
174
|
+
* const emojiPicker = defineTypeaheadPicker({
|
|
175
|
+
* trigger: /:/,
|
|
176
|
+
* keyword: /[\S]+/,
|
|
177
|
+
* getMatches: ({keyword}) => searchEmojis(keyword),
|
|
178
|
+
* guard: ({snapshot}) => {
|
|
179
|
+
* // Return false to prevent picker from activating
|
|
180
|
+
* if (anotherPickerIsOpen()) return false
|
|
181
|
+
* return true
|
|
182
|
+
* },
|
|
183
|
+
* actions: [({event}) => [
|
|
184
|
+
* raise({type: 'delete', at: event.patternSelection}),
|
|
185
|
+
* raise({type: 'insert.text', text: event.match.emoji}),
|
|
186
|
+
* ]],
|
|
187
|
+
* })
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
159
190
|
* @public
|
|
160
191
|
*/
|
|
161
192
|
export declare function defineTypeaheadPicker<TMatch extends object>(
|
|
@@ -383,6 +414,14 @@ declare type TypeaheadPickerDefinitionBase<TMatch extends object> = {
|
|
|
383
414
|
* @example `':'` - typing `:joy:` auto-inserts the joy emoji
|
|
384
415
|
*/
|
|
385
416
|
delimiter?: string
|
|
417
|
+
/**
|
|
418
|
+
* Guard function that runs at trigger time to conditionally prevent the picker
|
|
419
|
+
* from activating.
|
|
420
|
+
* Return `false` to block activation, or `true` to allow it.
|
|
421
|
+
*
|
|
422
|
+
* @see {@link TypeaheadTriggerGuard}
|
|
423
|
+
*/
|
|
424
|
+
guard?: TypeaheadTriggerGuard
|
|
386
425
|
/**
|
|
387
426
|
* Actions to execute when a match is selected.
|
|
388
427
|
* Typically deletes the trigger text and inserts the selected content.
|
|
@@ -491,7 +530,7 @@ export declare type TypeaheadSelectActionSet<TMatch> = BehaviorActionSet<
|
|
|
491
530
|
* @public
|
|
492
531
|
*/
|
|
493
532
|
export declare type TypeaheadSelectEvent<TMatch> = {
|
|
494
|
-
type: 'typeahead
|
|
533
|
+
type: 'custom.typeahead select'
|
|
495
534
|
/** The match that was selected */
|
|
496
535
|
match: TMatch
|
|
497
536
|
/** The extracted keyword (e.g., `joy` from `:joy`) */
|
|
@@ -500,6 +539,39 @@ export declare type TypeaheadSelectEvent<TMatch> = {
|
|
|
500
539
|
patternSelection: NonNullable<EditorSelection>
|
|
501
540
|
}
|
|
502
541
|
|
|
542
|
+
/**
|
|
543
|
+
* Event passed to the trigger guard when the picker is about to activate.
|
|
544
|
+
*
|
|
545
|
+
* @public
|
|
546
|
+
*/
|
|
547
|
+
export declare type TypeaheadTriggerEvent = {
|
|
548
|
+
type: 'custom.typeahead trigger found'
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Guard function that runs at trigger time to conditionally prevent the picker
|
|
553
|
+
* from activating. Has the same signature as a behavior guard.
|
|
554
|
+
*
|
|
555
|
+
* Return `false` to block activation, or `true` to allow it.
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```ts
|
|
559
|
+
* guard: ({snapshot, event, dom}) => {
|
|
560
|
+
* // Block activation if another picker is open
|
|
561
|
+
* if (anotherPickerIsOpen()) return false
|
|
562
|
+
*
|
|
563
|
+
* // Allow activation
|
|
564
|
+
* return true
|
|
565
|
+
* }
|
|
566
|
+
* ```
|
|
567
|
+
*
|
|
568
|
+
* @public
|
|
569
|
+
*/
|
|
570
|
+
export declare type TypeaheadTriggerGuard = BehaviorGuard<
|
|
571
|
+
TypeaheadTriggerEvent,
|
|
572
|
+
true
|
|
573
|
+
>
|
|
574
|
+
|
|
503
575
|
/**
|
|
504
576
|
* React hook that activates a typeahead picker and returns its current state.
|
|
505
577
|
*
|
package/dist/index.js
CHANGED
|
@@ -295,20 +295,31 @@ function createInputRules(definition) {
|
|
|
295
295
|
});
|
|
296
296
|
return rules.push(triggerRule), rules;
|
|
297
297
|
}
|
|
298
|
+
function createTriggerGuard(definition) {
|
|
299
|
+
return ({
|
|
300
|
+
event,
|
|
301
|
+
snapshot,
|
|
302
|
+
dom
|
|
303
|
+
}) => event.pickerId !== definition._id ? !1 : definition.guard ? definition.guard({
|
|
304
|
+
snapshot,
|
|
305
|
+
dom,
|
|
306
|
+
event: {
|
|
307
|
+
type: "custom.typeahead trigger found"
|
|
308
|
+
}
|
|
309
|
+
}) : !0;
|
|
310
|
+
}
|
|
298
311
|
const triggerListenerCallback = () => ({
|
|
299
312
|
sendBack,
|
|
300
313
|
input
|
|
301
314
|
}) => {
|
|
302
|
-
const rules = createInputRules(input.definition), unregisterBehaviors = [input.editor.registerBehavior({
|
|
315
|
+
const rules = createInputRules(input.definition), triggerGuard = createTriggerGuard(input.definition), unregisterBehaviors = [input.editor.registerBehavior({
|
|
303
316
|
behavior: defineInputRuleBehavior({
|
|
304
317
|
rules
|
|
305
318
|
})
|
|
306
319
|
}), input.editor.registerBehavior({
|
|
307
320
|
behavior: defineBehavior({
|
|
308
321
|
on: "custom.typeahead keyword found",
|
|
309
|
-
guard:
|
|
310
|
-
event
|
|
311
|
-
}) => event.pickerId === input.definition._id,
|
|
322
|
+
guard: triggerGuard,
|
|
312
323
|
actions: [({
|
|
313
324
|
event
|
|
314
325
|
}) => [effect(() => {
|
|
@@ -318,9 +329,7 @@ const triggerListenerCallback = () => ({
|
|
|
318
329
|
}), input.editor.registerBehavior({
|
|
319
330
|
behavior: defineBehavior({
|
|
320
331
|
on: "custom.typeahead trigger found",
|
|
321
|
-
guard:
|
|
322
|
-
event
|
|
323
|
-
}) => event.pickerId === input.definition._id,
|
|
332
|
+
guard: triggerGuard,
|
|
324
333
|
actions: [({
|
|
325
334
|
event
|
|
326
335
|
}) => [effect(() => {
|
|
@@ -478,12 +487,12 @@ const triggerListenerCallback = () => ({
|
|
|
478
487
|
})]]
|
|
479
488
|
})
|
|
480
489
|
});
|
|
481
|
-
},
|
|
490
|
+
}, selectMatchListenerCallback = () => ({
|
|
482
491
|
sendBack,
|
|
483
492
|
input
|
|
484
493
|
}) => input.context.editor.registerBehavior({
|
|
485
494
|
behavior: defineBehavior({
|
|
486
|
-
on: "custom.typeahead
|
|
495
|
+
on: "custom.typeahead select match",
|
|
487
496
|
guard: ({
|
|
488
497
|
event
|
|
489
498
|
}) => event.pickerId === input.context.definition._id,
|
|
@@ -511,7 +520,7 @@ const triggerListenerCallback = () => ({
|
|
|
511
520
|
snapshot,
|
|
512
521
|
dom,
|
|
513
522
|
event: {
|
|
514
|
-
type: "typeahead
|
|
523
|
+
type: "custom.typeahead select",
|
|
515
524
|
match: event.match,
|
|
516
525
|
keyword: event.keyword,
|
|
517
526
|
patternSelection
|
|
@@ -520,15 +529,7 @@ const triggerListenerCallback = () => ({
|
|
|
520
529
|
for (const action of actions)
|
|
521
530
|
allActions.push(action);
|
|
522
531
|
}
|
|
523
|
-
return allActions
|
|
524
|
-
queueMicrotask(() => {
|
|
525
|
-
const currentSelection = input.context.editor.getSnapshot().context.selection;
|
|
526
|
-
currentSelection && input.context.editor.send({
|
|
527
|
-
type: "select",
|
|
528
|
-
at: currentSelection
|
|
529
|
-
});
|
|
530
|
-
});
|
|
531
|
-
})), allActions;
|
|
532
|
+
return allActions;
|
|
532
533
|
}]
|
|
533
534
|
})
|
|
534
535
|
});
|
|
@@ -551,7 +552,7 @@ function createTypeaheadPickerMachine() {
|
|
|
551
552
|
"selection listener": fromCallback(selectionListenerCallback()),
|
|
552
553
|
"submit listener": fromCallback(submitListenerCallback()),
|
|
553
554
|
"text insertion listener": fromCallback(textInsertionListenerCallback()),
|
|
554
|
-
"
|
|
555
|
+
"select match listener": fromCallback(selectMatchListenerCallback()),
|
|
555
556
|
"get matches": fromPromise(async ({
|
|
556
557
|
input
|
|
557
558
|
}) => {
|
|
@@ -704,14 +705,14 @@ function createTypeaheadPickerMachine() {
|
|
|
704
705
|
} : {
|
|
705
706
|
selectedIndex: (context.selectedIndex + 1) % context.matches.length
|
|
706
707
|
}),
|
|
707
|
-
"
|
|
708
|
+
"select match": ({
|
|
708
709
|
context
|
|
709
710
|
}, params) => {
|
|
710
711
|
if (!context.focusSpan)
|
|
711
712
|
return;
|
|
712
713
|
const match = params.exact ? getFirstExactMatch(context.matches) : context.matches[context.selectedIndex];
|
|
713
714
|
match && context.editor.send({
|
|
714
|
-
type: "custom.typeahead
|
|
715
|
+
type: "custom.typeahead select match",
|
|
715
716
|
match,
|
|
716
717
|
focusSpan: context.focusSpan,
|
|
717
718
|
keyword: context.keyword,
|
|
@@ -825,7 +826,7 @@ function createTypeaheadPickerMachine() {
|
|
|
825
826
|
},
|
|
826
827
|
"checking complete": {
|
|
827
828
|
invoke: [{
|
|
828
|
-
src: "
|
|
829
|
+
src: "select match listener",
|
|
829
830
|
input: ({
|
|
830
831
|
context
|
|
831
832
|
}) => ({
|
|
@@ -849,7 +850,7 @@ function createTypeaheadPickerMachine() {
|
|
|
849
850
|
event
|
|
850
851
|
}) => event.output.matches
|
|
851
852
|
}), {
|
|
852
|
-
type: "
|
|
853
|
+
type: "select match",
|
|
853
854
|
params: {
|
|
854
855
|
exact: !0
|
|
855
856
|
}
|
|
@@ -870,7 +871,7 @@ function createTypeaheadPickerMachine() {
|
|
|
870
871
|
},
|
|
871
872
|
active: {
|
|
872
873
|
invoke: [{
|
|
873
|
-
src: "
|
|
874
|
+
src: "select match listener",
|
|
874
875
|
input: ({
|
|
875
876
|
context
|
|
876
877
|
}) => ({
|
|
@@ -924,7 +925,7 @@ function createTypeaheadPickerMachine() {
|
|
|
924
925
|
}, {
|
|
925
926
|
guard: "is complete keyword",
|
|
926
927
|
actions: [{
|
|
927
|
-
type: "
|
|
928
|
+
type: "select match",
|
|
928
929
|
params: {
|
|
929
930
|
exact: !1
|
|
930
931
|
}
|
|
@@ -1073,7 +1074,7 @@ function createTypeaheadPickerMachine() {
|
|
|
1073
1074
|
select: {
|
|
1074
1075
|
target: "#typeahead picker.idle",
|
|
1075
1076
|
actions: [{
|
|
1076
|
-
type: "
|
|
1077
|
+
type: "select match",
|
|
1077
1078
|
params: {
|
|
1078
1079
|
exact: !1
|
|
1079
1080
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/define-typeahead-picker.ts","../src/extract-keyword.ts","../src/typeahead-picker-machine.tsx","../src/use-typeahead-picker.ts"],"sourcesContent":["import type {\n AutoCompleteMatch,\n TypeaheadPickerDefinition,\n TypeaheadSelectActionSet,\n} from './typeahead-picker.types'\n\ntype BaseConfigWithoutDelimiter<TMatch extends object> = {\n /**\n * Pattern that activates the picker. Must be a single character.\n * Can include `^` for start-of-block triggers.\n *\n * @example `/:/` - activates on colon\n * @example `/@/` - activates on at-sign\n * @example `/^\\//` - activates on slash at start of block\n */\n trigger: RegExp\n /**\n * Pattern matching the keyword portion after the trigger.\n * The entire match becomes the keyword passed to `getMatches`.\n * Common patterns: non-whitespace (`\\S*`) or word characters (`\\w*`).\n */\n keyword: RegExp\n delimiter?: undefined\n /**\n * Actions to execute when a match is selected.\n * Typically deletes the trigger text and inserts the selected content.\n */\n actions: Array<TypeaheadSelectActionSet<TMatch>>\n}\n\ntype BaseConfigWithDelimiter<TMatch extends AutoCompleteMatch> = {\n /**\n * Pattern that activates the picker. Must be a single character.\n * Can include `^` for start-of-block triggers.\n *\n * @example `/:/` - activates on colon\n * @example `/@/` - activates on at-sign\n * @example `/^\\//` - activates on slash at start of block\n */\n trigger: RegExp\n /**\n * Pattern matching the keyword portion after the trigger.\n * The entire match becomes the keyword passed to `getMatches`.\n * Common patterns: non-whitespace (`\\S*`) or word characters (`\\w*`).\n */\n keyword: RegExp\n /**\n * Character that triggers auto-completion.\n * Typing this after a keyword with an exact match auto-inserts it.\n *\n * @example `':'` - typing `:joy:` auto-inserts the joy emoji\n */\n delimiter: string\n /**\n * Actions to execute when a match is selected.\n * Typically deletes the trigger text and inserts the selected content.\n */\n actions: Array<TypeaheadSelectActionSet<TMatch>>\n}\n\ntype SyncConfigWithoutDelimiter<TMatch extends object> =\n BaseConfigWithoutDelimiter<TMatch> & {\n /**\n * Whether `getMatches` returns synchronously or asynchronously.\n * @defaultValue `'sync'`\n */\n mode?: 'sync'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Useful for expensive local searches.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => ReadonlyArray<TMatch>\n }\n\ntype SyncConfigWithDelimiter<TMatch extends AutoCompleteMatch> =\n BaseConfigWithDelimiter<TMatch> & {\n /**\n * Whether `getMatches` returns synchronously or asynchronously.\n * @defaultValue `'sync'`\n */\n mode?: 'sync'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Useful for expensive local searches.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => ReadonlyArray<TMatch>\n }\n\ntype AsyncConfigWithoutDelimiter<TMatch extends object> =\n BaseConfigWithoutDelimiter<TMatch> & {\n /**\n * Set to `'async'` when `getMatches` returns a Promise.\n */\n mode: 'async'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Recommended for API calls to reduce request frequency.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Async function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => Promise<ReadonlyArray<TMatch>>\n }\n\ntype AsyncConfigWithDelimiter<TMatch extends AutoCompleteMatch> =\n BaseConfigWithDelimiter<TMatch> & {\n /**\n * Set to `'async'` when `getMatches` returns a Promise.\n */\n mode: 'async'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Recommended for API calls to reduce request frequency.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Async function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => Promise<ReadonlyArray<TMatch>>\n }\n\n/**\n * Creates a typeahead picker definition to use with {@link useTypeaheadPicker}.\n *\n * @example Emoji picker with auto-complete\n * ```ts\n * const emojiPicker = defineTypeaheadPicker({\n * trigger: /:/,\n * keyword: /[\\S]+/,\n * delimiter: ':',\n * getMatches: ({keyword}) => searchEmojis(keyword),\n * actions: [insertEmojiAction],\n * })\n * ```\n *\n * @example Async mention picker\n * ```ts\n * const mentionPicker = defineTypeaheadPicker({\n * mode: 'async',\n * trigger: /@/,\n * keyword: /[\\w]+/,\n * debounceMs: 200,\n * getMatches: async ({keyword}) => api.searchUsers(keyword),\n * actions: [insertMentionAction],\n * })\n * ```\n *\n * @example Slash commands at start of block\n * ```ts\n * const slashCommandPicker = defineTypeaheadPicker({\n * trigger: /^\\//,\n * keyword: /[\\w]+/,\n * getMatches: ({keyword}) => filterCommands(keyword),\n * actions: [executeCommandAction],\n * })\n * ```\n *\n * @public\n */\nexport function defineTypeaheadPicker<TMatch extends object>(\n config: SyncConfigWithoutDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends AutoCompleteMatch>(\n config: SyncConfigWithDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends object>(\n config: AsyncConfigWithoutDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends AutoCompleteMatch>(\n config: AsyncConfigWithDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends object>(\n config:\n | SyncConfigWithoutDelimiter<TMatch>\n | SyncConfigWithDelimiter<TMatch & AutoCompleteMatch>\n | AsyncConfigWithoutDelimiter<TMatch>\n | AsyncConfigWithDelimiter<TMatch & AutoCompleteMatch>,\n): TypeaheadPickerDefinition<TMatch> {\n return {\n ...config,\n _id: Symbol('typeahead-picker'),\n } as TypeaheadPickerDefinition<TMatch>\n}\n","/**\n * Extract keyword from pattern text using the trigger pattern.\n * Removes the trigger match from the start and delimiter from the end.\n *\n * @param patternText - The full pattern text (e.g., `:joy:` or `:joy`)\n * @param triggerPattern - Pattern matching the trigger (e.g., /:/)\n * @param delimiter - Optional delimiter character (e.g., `:`)\n * @param completePattern - Optional complete pattern to detect if this is a complete match\n */\nexport function extractKeyword(\n patternText: string,\n triggerPattern: RegExp,\n delimiter?: string,\n completePattern?: RegExp,\n): string {\n const triggerMatch = patternText.match(triggerPattern)\n\n if (!triggerMatch || triggerMatch.index !== 0) {\n return patternText\n }\n\n let keyword = patternText.slice(triggerMatch[0].length)\n\n if (delimiter && keyword.endsWith(delimiter)) {\n // Check if this is a complete match (pattern matches the complete pattern exactly)\n const isCompleteMatch =\n completePattern &&\n (() => {\n const completeMatch = patternText.match(completePattern)\n return (\n completeMatch &&\n completeMatch.index === 0 &&\n completeMatch[0] === patternText\n )\n })()\n\n // Strip delimiter if:\n // - This is a complete match (even if keyword becomes empty), OR\n // - Keyword would remain non-empty after stripping\n if (isCompleteMatch || keyword.length > delimiter.length) {\n keyword = keyword.slice(0, -delimiter.length)\n }\n }\n\n return keyword\n}\n","import type {\n ChildPath,\n Editor,\n EditorSelector,\n EditorSnapshot,\n PortableTextSpan,\n} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n forward,\n raise,\n} from '@portabletext/editor/behaviors'\nimport {\n getFocusSpan,\n getMarkState,\n getNextSpan,\n getPreviousSpan,\n isPointAfterSelection,\n isPointBeforeSelection,\n isSelectionCollapsed,\n type MarkState,\n} from '@portabletext/editor/selectors'\nimport {isEqualPaths, isEqualSelectionPoints} from '@portabletext/editor/utils'\nimport {createKeyboardShortcut} from '@portabletext/keyboard-shortcuts'\nimport {\n defineInputRule,\n defineInputRuleBehavior,\n type InputRuleMatch,\n} from '@portabletext/plugin-input-rule'\nimport {\n assign,\n fromCallback,\n fromPromise,\n sendTo,\n setup,\n type AnyEventObject,\n type CallbackLogicFunction,\n} from 'xstate'\nimport {extractKeyword} from './extract-keyword'\nimport type {\n AutoCompleteMatch,\n TypeaheadPickerDefinition,\n} from './typeahead-picker.types'\n\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Build the trigger pattern from the definition.\n */\nfunction buildTriggerPattern<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): RegExp {\n return new RegExp(definition.trigger.source)\n}\n\n/**\n * Build the partial pattern (trigger + keyword) from the definition.\n */\nfunction buildPartialPattern<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): RegExp {\n return new RegExp(definition.trigger.source + definition.keyword.source)\n}\n\n/**\n * Build the complete pattern (trigger + keyword + delimiter) from the definition.\n */\nfunction buildCompletePattern<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): RegExp | undefined {\n if (!definition.delimiter) {\n return undefined\n }\n\n const escapedDelimiter = escapeRegExp(definition.delimiter)\n return new RegExp(\n definition.trigger.source + definition.keyword.source + escapedDelimiter,\n )\n}\n\nconst arrowUpShortcut = createKeyboardShortcut({\n default: [{key: 'ArrowUp'}],\n})\nconst arrowDownShortcut = createKeyboardShortcut({\n default: [{key: 'ArrowDown'}],\n})\nconst enterShortcut = createKeyboardShortcut({\n default: [{key: 'Enter'}],\n})\nconst tabShortcut = createKeyboardShortcut({\n default: [{key: 'Tab'}],\n})\nconst escapeShortcut = createKeyboardShortcut({\n default: [{key: 'Escape'}],\n})\n\nconst getTriggerState: EditorSelector<\n | {\n focusSpan: {\n node: PortableTextSpan\n path: ChildPath\n }\n markState: MarkState\n focusSpanTextBefore: string\n focusSpanTextAfter: string\n previousSpan:\n | {\n node: PortableTextSpan\n path: ChildPath\n }\n | undefined\n nextSpan:\n | {\n node: PortableTextSpan\n path: ChildPath\n }\n | undefined\n }\n | undefined\n> = (snapshot) => {\n const focusSpan = getFocusSpan(snapshot)\n const markState = getMarkState(snapshot)\n\n if (!focusSpan || !markState || !snapshot.context.selection) {\n return undefined\n }\n\n const focusSpanTextBefore = focusSpan.node.text.slice(\n 0,\n snapshot.context.selection.focus.offset,\n )\n const focusSpanTextAfter = focusSpan.node.text.slice(\n snapshot.context.selection.focus.offset,\n )\n const previousSpan = getPreviousSpan(snapshot)\n const nextSpan = getNextSpan(snapshot)\n\n return {\n focusSpan,\n markState,\n focusSpanTextBefore,\n focusSpanTextAfter,\n previousSpan,\n nextSpan,\n }\n}\n\ntype FocusSpanData = {\n node: PortableTextSpan\n path: ChildPath\n textBefore: string\n textAfter: string\n}\n\nfunction createTriggerActions({\n snapshot,\n payload,\n keywordState,\n pickerId,\n}: {\n snapshot: EditorSnapshot\n payload: TriggerPayload\n keywordState: 'partial' | 'complete'\n pickerId: symbol\n}) {\n if (payload.markState.state === 'unchanged') {\n const textBeforeMatch = payload.focusSpanTextBefore.slice(\n 0,\n payload.lastMatch.targetOffsets.anchor.offset,\n )\n const focusSpan = {\n node: {\n _key: payload.focusSpan.node._key,\n _type: payload.focusSpan.node._type,\n text: `${textBeforeMatch}${payload.lastMatch.text}${payload.focusSpanTextAfter}`,\n marks: payload.markState.marks,\n },\n path: payload.focusSpan.path,\n textBefore: textBeforeMatch,\n textAfter: payload.focusSpanTextAfter,\n }\n\n if (keywordState === 'complete') {\n return [\n raise(\n createKeywordFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]\n }\n\n return [\n raise(\n createTriggerFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]\n }\n\n const newSpan = {\n _key: snapshot.context.keyGenerator(),\n _type: payload.focusSpan.node._type,\n text: payload.lastMatch.text,\n marks: payload.markState.marks,\n }\n\n let focusSpan: FocusSpanData = {\n node: {\n _key: newSpan._key,\n _type: newSpan._type,\n text: `${newSpan.text}${payload.nextSpan?.node.text ?? payload.focusSpanTextAfter}`,\n marks: payload.markState.marks,\n },\n path: [\n {_key: payload.focusSpan.path[0]._key},\n 'children',\n {_key: newSpan._key},\n ] satisfies ChildPath,\n textBefore: '',\n textAfter: payload.nextSpan?.node.text ?? payload.focusSpanTextAfter,\n }\n\n if (\n payload.previousSpan &&\n payload.focusSpanTextBefore.length === 0 &&\n JSON.stringify(payload.previousSpan.node.marks ?? []) ===\n JSON.stringify(payload.markState.marks)\n ) {\n focusSpan = {\n node: {\n _key: payload.previousSpan.node._key,\n _type: newSpan._type,\n text: `${payload.previousSpan.node.text}${newSpan.text}`,\n marks: newSpan.marks,\n },\n path: payload.previousSpan.path,\n textBefore: payload.previousSpan.node.text,\n textAfter: '',\n }\n }\n\n return [\n raise({type: 'select', at: payload.lastMatch.targetOffsets}),\n raise({type: 'delete', at: payload.lastMatch.targetOffsets}),\n raise({type: 'insert.child', child: newSpan}),\n ...(keywordState === 'complete'\n ? [\n raise(\n createKeywordFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]\n : [\n raise(\n createTriggerFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]),\n ]\n}\n\ntype TriggerFoundEvent = {\n type: 'custom.typeahead trigger found'\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}\n\nfunction createTriggerFoundEvent(payload: {\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}): TriggerFoundEvent {\n return {\n type: 'custom.typeahead trigger found',\n ...payload,\n }\n}\n\ntype KeywordFoundEvent = {\n type: 'custom.typeahead keyword found'\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}\n\nfunction createKeywordFoundEvent(payload: {\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}): KeywordFoundEvent {\n return {\n type: 'custom.typeahead keyword found',\n ...payload,\n }\n}\n\ntype TypeaheadPickerMachineContext<TMatch extends object> = {\n editor: Editor\n definition: TypeaheadPickerDefinition<TMatch>\n triggerPattern: RegExp\n partialPattern: RegExp\n completePattern: RegExp | undefined\n matches: ReadonlyArray<TMatch>\n selectedIndex: number\n focusSpan: FocusSpanData | undefined\n patternText: string\n keyword: string\n requestedKeyword: string\n error: Error | undefined\n isLoading: boolean\n}\n\ntype TypeaheadPickerMachineEvent<TMatch extends object> =\n | TriggerFoundEvent\n | KeywordFoundEvent\n | {type: 'selection changed'}\n | {type: 'dismiss'}\n | {type: 'navigate down'}\n | {type: 'navigate up'}\n | {type: 'navigate to'; index: number}\n | {type: 'select'}\n | {type: 'matches loaded'; matches: ReadonlyArray<TMatch>}\n | {type: 'matches error'; error: Error}\n\ntype TriggerPayload = ReturnType<typeof getTriggerState> & {\n lastMatch: InputRuleMatch\n extractedKeyword: string\n}\n\n/**\n * Extract the pattern text (trigger + keyword) from focus span data.\n */\nfunction extractPatternTextFromFocusSpan(focusSpan: FocusSpanData): string {\n if (focusSpan.textBefore.length > 0 && focusSpan.textAfter.length > 0) {\n return focusSpan.node.text.slice(\n focusSpan.textBefore.length,\n -focusSpan.textAfter.length,\n )\n }\n\n if (focusSpan.textBefore.length > 0) {\n return focusSpan.node.text.slice(focusSpan.textBefore.length)\n }\n\n if (focusSpan.textAfter.length > 0) {\n return focusSpan.node.text.slice(0, -focusSpan.textAfter.length)\n }\n\n return focusSpan.node.text\n}\n\nfunction createInputRules<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n) {\n const rules: Array<ReturnType<typeof defineInputRule<TriggerPayload>>> = []\n\n const triggerPattern = buildTriggerPattern(definition)\n const partialPattern = buildPartialPattern(definition)\n const completePattern = buildCompletePattern(definition)\n\n if (completePattern) {\n const completeRule = defineInputRule<TriggerPayload>({\n on: completePattern,\n guard: ({snapshot, event}) => {\n const lastMatch = event.matches.at(-1)\n\n if (lastMatch === undefined) {\n return false\n }\n\n if (lastMatch.targetOffsets.anchor.offset < event.textBefore.length) {\n // Match starts before insertion. Check if the inserted text itself\n // matches the complete pattern (e.g., inserting `:dog:` after `foo:`).\n const insertedMatch = event.textInserted.match(completePattern)\n\n if (insertedMatch === null || insertedMatch.index !== 0) {\n return false\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch: {\n ...lastMatch,\n text: event.textInserted,\n targetOffsets: {\n ...lastMatch.targetOffsets,\n anchor: {\n ...lastMatch.targetOffsets.anchor,\n offset: event.textBefore.length,\n },\n },\n },\n extractedKeyword: extractKeyword(\n event.textInserted,\n triggerPattern,\n definition.delimiter,\n completePattern,\n ),\n }\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch,\n extractedKeyword: extractKeyword(\n lastMatch.text,\n triggerPattern,\n definition.delimiter,\n completePattern,\n ),\n }\n },\n actions: [\n ({snapshot}, payload) =>\n createTriggerActions({\n snapshot,\n payload,\n keywordState: 'complete',\n pickerId: definition._id,\n }),\n ],\n })\n\n rules.push(completeRule)\n }\n\n const partialRule = defineInputRule<TriggerPayload>({\n on: partialPattern,\n guard: ({snapshot, event}) => {\n const lastMatch = event.matches.at(-1)\n\n if (lastMatch === undefined) {\n return false\n }\n\n if (lastMatch.targetOffsets.anchor.offset < event.textBefore.length) {\n // Match starts before insertion. Check if the inserted text itself\n // matches the partial pattern (e.g., inserting `:dog` after `foo:`).\n const insertedMatch = event.textInserted.match(partialPattern)\n\n if (insertedMatch === null || insertedMatch.index !== 0) {\n return false\n }\n\n // Don't match if this is actually a complete pattern\n if (completePattern) {\n const completeMatch = event.textInserted.match(completePattern)\n\n if (\n completeMatch !== null &&\n completeMatch.index === 0 &&\n completeMatch[0] === event.textInserted\n ) {\n return false\n }\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch: {\n ...lastMatch,\n text: event.textInserted,\n targetOffsets: {\n ...lastMatch.targetOffsets,\n anchor: {\n ...lastMatch.targetOffsets.anchor,\n offset: event.textBefore.length,\n },\n },\n },\n extractedKeyword: extractKeyword(\n event.textInserted,\n triggerPattern,\n definition.delimiter,\n ),\n }\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch,\n extractedKeyword: extractKeyword(\n lastMatch.text,\n triggerPattern,\n definition.delimiter,\n ),\n }\n },\n actions: [\n ({snapshot}, payload) =>\n createTriggerActions({\n snapshot,\n payload,\n keywordState: 'partial',\n pickerId: definition._id,\n }),\n ],\n })\n\n rules.push(partialRule)\n\n const triggerRule = defineInputRule<TriggerPayload>({\n on: triggerPattern,\n guard: ({snapshot, event}) => {\n const lastMatch = event.matches.at(-1)\n\n if (lastMatch === undefined) {\n return false\n }\n\n if (event.textInserted !== lastMatch.text) {\n return false\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch,\n extractedKeyword: '',\n }\n },\n actions: [\n ({snapshot}, payload) =>\n createTriggerActions({\n snapshot,\n payload,\n keywordState: 'partial',\n pickerId: definition._id,\n }),\n ],\n })\n\n rules.push(triggerRule)\n\n return rules\n}\n\nconst triggerListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor; definition: TypeaheadPickerDefinition<TMatch>}\n> => {\n return ({sendBack, input}) => {\n const rules = createInputRules(input.definition)\n\n const unregisterBehaviors = [\n input.editor.registerBehavior({\n behavior: defineInputRuleBehavior({rules}),\n }),\n input.editor.registerBehavior({\n behavior: defineBehavior<KeywordFoundEvent, KeywordFoundEvent['type']>({\n on: 'custom.typeahead keyword found',\n guard: ({event}) => event.pickerId === input.definition._id,\n actions: [\n ({event}) => [\n effect(() => {\n sendBack(event)\n }),\n ],\n ],\n }),\n }),\n input.editor.registerBehavior({\n behavior: defineBehavior<TriggerFoundEvent, TriggerFoundEvent['type']>({\n on: 'custom.typeahead trigger found',\n guard: ({event}) => event.pickerId === input.definition._id,\n actions: [\n ({event}) => [\n effect(() => {\n sendBack(event)\n }),\n ],\n ],\n }),\n }),\n ]\n\n return () => {\n for (const unregister of unregisterBehaviors) {\n unregister()\n }\n }\n }\n}\n\nconst escapeListenerCallback = <TMatch extends object>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor}\n> => {\n return ({sendBack, input}) => {\n return input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => escapeShortcut.guard(event.originEvent),\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n })\n }\n}\n\nconst arrowListenerCallback = <TMatch extends object>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor}\n> => {\n return ({sendBack, input}) => {\n const unregisterBehaviors = [\n input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => arrowDownShortcut.guard(event.originEvent),\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'navigate down'})\n }),\n ],\n ],\n }),\n }),\n input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => arrowUpShortcut.guard(event.originEvent),\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'navigate up'})\n }),\n ],\n ],\n }),\n }),\n ]\n\n return () => {\n for (const unregister of unregisterBehaviors) {\n unregister()\n }\n }\n }\n}\n\nconst selectionListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor}\n> => {\n return ({sendBack, input}) => {\n const subscription = input.editor.on('selection', () => {\n sendBack({type: 'selection changed'})\n })\n\n return subscription.unsubscribe\n }\n}\n\nconst submitListenerCallback = <TMatch extends object>(): CallbackLogicFunction<\n {type: 'context changed'; context: TypeaheadPickerMachineContext<TMatch>},\n TypeaheadPickerMachineEvent<TMatch>,\n {context: TypeaheadPickerMachineContext<TMatch>}\n> => {\n return ({sendBack, input, receive}) => {\n let context = input.context\n\n receive((event) => {\n context = event.context\n })\n\n const unregisterBehaviors = [\n input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => {\n if (\n !enterShortcut.guard(event.originEvent) &&\n !tabShortcut.guard(event.originEvent)\n ) {\n return false\n }\n\n const focusSpan = context.focusSpan\n const match = context.matches[context.selectedIndex]\n\n return match && focusSpan ? {focusSpan, match} : false\n },\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'select'})\n }),\n ],\n ],\n }),\n }),\n input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) =>\n (enterShortcut.guard(event.originEvent) ||\n tabShortcut.guard(event.originEvent)) &&\n context.patternText.length === 1,\n actions: [\n ({event}) => [\n forward(event),\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n }),\n input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) =>\n (enterShortcut.guard(event.originEvent) ||\n tabShortcut.guard(event.originEvent)) &&\n context.patternText.length > 1 &&\n context.matches.length === 0,\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n }),\n ]\n\n return () => {\n for (const unregister of unregisterBehaviors) {\n unregister()\n }\n }\n }\n}\n\nconst textInsertionListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n {type: 'context changed'; context: TypeaheadPickerMachineContext<TMatch>},\n TypeaheadPickerMachineEvent<TMatch>,\n {context: TypeaheadPickerMachineContext<TMatch>}\n> => {\n return ({sendBack, input, receive}) => {\n let context = input.context\n\n receive((event) => {\n context = event.context\n })\n\n return input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'insert.text',\n guard: ({snapshot}) => {\n if (!context.focusSpan) {\n return false\n }\n\n if (!snapshot.context.selection) {\n return false\n }\n\n const keywordAnchor = {\n path: context.focusSpan.path,\n offset: context.focusSpan.textBefore.length,\n }\n\n return isEqualSelectionPoints(\n snapshot.context.selection.focus,\n keywordAnchor,\n )\n },\n actions: [\n ({event}) => [\n forward(event),\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n })\n }\n}\n\ntype InsertMatchEvent<TMatch extends object> = {\n type: 'custom.typeahead insert match'\n match: TMatch\n focusSpan: FocusSpanData\n keyword: string\n pickerId: symbol\n}\n\nconst insertMatchListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {context: TypeaheadPickerMachineContext<TMatch>}\n> => {\n return ({sendBack, input}) => {\n return input.context.editor.registerBehavior({\n behavior: defineBehavior<InsertMatchEvent<TMatch>>({\n on: 'custom.typeahead insert match',\n guard: ({event}) => event.pickerId === input.context.definition._id,\n actions: [\n ({event, snapshot, dom}) => {\n const patternSelection = {\n anchor: {\n path: event.focusSpan.path,\n offset: event.focusSpan.textBefore.length,\n },\n focus: {\n path: event.focusSpan.path,\n offset:\n event.focusSpan.node.text.length -\n event.focusSpan.textAfter.length,\n },\n }\n\n const allActions: Array<\n ReturnType<typeof raise> | ReturnType<typeof effect>\n > = [\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ]\n\n for (const actionSet of input.context.definition.actions) {\n const actions = actionSet(\n {\n snapshot,\n dom,\n event: {\n type: 'typeahead.select',\n match: event.match,\n keyword: event.keyword,\n patternSelection,\n },\n },\n true,\n )\n for (const action of actions) {\n allActions.push(\n action as\n | ReturnType<typeof raise>\n | ReturnType<typeof effect>,\n )\n }\n }\n\n // Dispatch a select event after all actions complete to exit\n // input-rule's \"input rule applied\" state. We use queueMicrotask\n // to ensure this runs after the cursor has moved to its final position.\n allActions.push(\n effect(() => {\n queueMicrotask(() => {\n const currentSelection =\n input.context.editor.getSnapshot().context.selection\n if (currentSelection) {\n input.context.editor.send({\n type: 'select',\n at: currentSelection,\n })\n }\n })\n }),\n )\n\n return allActions\n },\n ],\n }),\n })\n }\n}\n\nexport function createTypeaheadPickerMachine<TMatch extends object>() {\n return setup({\n types: {\n context: {} as TypeaheadPickerMachineContext<TMatch>,\n input: {} as {\n editor: Editor\n definition: TypeaheadPickerDefinition<TMatch>\n },\n events: {} as TypeaheadPickerMachineEvent<TMatch>,\n },\n delays: {\n DEBOUNCE: ({context}) => context.definition.debounceMs ?? 0,\n },\n actors: {\n 'trigger listener': fromCallback(triggerListenerCallback<TMatch>()),\n 'escape listener': fromCallback(escapeListenerCallback<TMatch>()),\n 'arrow listener': fromCallback(arrowListenerCallback<TMatch>()),\n 'selection listener': fromCallback(selectionListenerCallback<TMatch>()),\n 'submit listener': fromCallback(submitListenerCallback<TMatch>()),\n 'text insertion listener': fromCallback(\n textInsertionListenerCallback<TMatch>(),\n ),\n 'insert match listener': fromCallback(\n insertMatchListenerCallback<TMatch>(),\n ),\n 'get matches': fromPromise(\n async ({\n input,\n }: {\n input: {\n keyword: string\n getMatches: TypeaheadPickerDefinition<TMatch>['getMatches']\n }\n }) => {\n const result = input.getMatches({keyword: input.keyword})\n const matches = await Promise.resolve(result)\n return {keyword: input.keyword, matches}\n },\n ),\n },\n actions: {\n 'handle trigger found': assign(({context, event}) => {\n if (\n event.type !== 'custom.typeahead trigger found' &&\n event.type !== 'custom.typeahead keyword found'\n ) {\n return {}\n }\n\n const focusSpan = event.focusSpan\n const patternText = extractPatternTextFromFocusSpan(focusSpan)\n const keyword = event.extractedKeyword\n\n if (\n context.definition.mode === 'async' ||\n context.definition.debounceMs\n ) {\n return {\n focusSpan,\n patternText,\n keyword,\n isLoading: true,\n selectedIndex: 0,\n }\n }\n\n const matches = context.definition.getMatches({\n keyword,\n }) as Array<TMatch>\n\n return {\n focusSpan,\n patternText,\n keyword,\n matches,\n requestedKeyword: keyword,\n isLoading: false,\n selectedIndex: 0,\n }\n }),\n 'update focus span': assign({\n focusSpan: ({context}) => {\n if (!context.focusSpan) {\n return context.focusSpan\n }\n\n const snapshot = context.editor.getSnapshot()\n const focusSpan = getFocusSpan(snapshot)\n\n if (!snapshot.context.selection || !focusSpan) {\n return undefined\n }\n\n const nextSpan = getNextSpan({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: {path: context.focusSpan.path, offset: 0},\n focus: {path: context.focusSpan.path, offset: 0},\n },\n },\n })\n\n if (!isEqualPaths(focusSpan.path, context.focusSpan.path)) {\n if (\n nextSpan &&\n context.focusSpan.textAfter.length === 0 &&\n snapshot.context.selection.focus.offset === 0 &&\n isSelectionCollapsed(snapshot)\n ) {\n // This is an edge case where the caret is moved from the end of\n // the focus span to the start of the next span.\n return context.focusSpan\n }\n\n return undefined\n }\n\n if (!focusSpan.node.text.startsWith(context.focusSpan.textBefore)) {\n return undefined\n }\n\n if (!focusSpan.node.text.endsWith(context.focusSpan.textAfter)) {\n return undefined\n }\n\n const keywordAnchor = {\n path: focusSpan.path,\n offset: context.focusSpan.textBefore.length,\n }\n const keywordFocus = {\n path: focusSpan.path,\n offset:\n focusSpan.node.text.length - context.focusSpan.textAfter.length,\n }\n\n const selectionIsBeforeKeyword =\n isPointAfterSelection(keywordAnchor)(snapshot)\n const selectionIsAfterKeyword =\n isPointBeforeSelection(keywordFocus)(snapshot)\n\n if (selectionIsBeforeKeyword || selectionIsAfterKeyword) {\n return undefined\n }\n\n return {\n node: focusSpan.node,\n path: focusSpan.path,\n textBefore: context.focusSpan.textBefore,\n textAfter: context.focusSpan.textAfter,\n }\n },\n }),\n 'update pattern text': assign(({context}) => {\n if (!context.focusSpan) {\n return {}\n }\n\n const patternText = extractPatternTextFromFocusSpan(context.focusSpan)\n\n if (patternText === context.patternText) {\n return {}\n }\n\n return {patternText, selectedIndex: 0}\n }),\n 'update keyword': assign(({context}) => {\n if (!context.focusSpan || !context.patternText) {\n return {}\n }\n\n const keyword = extractKeyword(\n context.patternText,\n context.triggerPattern,\n context.definition.delimiter,\n context.completePattern,\n )\n\n if (keyword === context.keyword) {\n return {}\n }\n\n return {keyword}\n }),\n 'update matches': assign(({context}) => {\n if (!context.focusSpan || !context.patternText) {\n return {}\n }\n\n if (\n context.definition.mode === 'async' ||\n context.definition.debounceMs\n ) {\n return {\n isLoading:\n context.isLoading || context.requestedKeyword !== context.keyword,\n }\n }\n\n const matches = context.definition.getMatches({\n keyword: context.keyword,\n }) as Array<TMatch>\n\n return {\n matches,\n requestedKeyword: context.keyword,\n isLoading: false,\n }\n }),\n 'handle async load complete': assign(({context, event}) => {\n const output = (\n event as unknown as {\n output: {keyword: string; matches: ReadonlyArray<TMatch>}\n }\n ).output\n\n if (output.keyword !== context.keyword) {\n return {isLoading: context.keyword !== context.requestedKeyword}\n }\n\n return {\n matches: output.matches,\n isLoading: context.keyword !== context.requestedKeyword,\n }\n }),\n 'reset': assign({\n patternText: '',\n keyword: '',\n matches: [],\n selectedIndex: 0,\n isLoading: false,\n requestedKeyword: '',\n focusSpan: undefined,\n error: undefined,\n }),\n 'navigate': assign(({context, event}) => {\n if (context.matches.length === 0) {\n return {selectedIndex: 0}\n }\n\n if (event.type === 'navigate to') {\n return {selectedIndex: event.index}\n }\n\n if (event.type === 'navigate up') {\n return {\n selectedIndex:\n (context.selectedIndex - 1 + context.matches.length) %\n context.matches.length,\n }\n }\n\n return {\n selectedIndex: (context.selectedIndex + 1) % context.matches.length,\n }\n }),\n 'insert match': ({context}, params: {exact?: boolean}) => {\n if (!context.focusSpan) {\n return\n }\n\n const match = params.exact\n ? getFirstExactMatch(context.matches)\n : context.matches[context.selectedIndex]\n\n if (!match) {\n return\n }\n\n context.editor.send({\n type: 'custom.typeahead insert match',\n match,\n focusSpan: context.focusSpan,\n keyword: context.keyword,\n pickerId: context.definition._id,\n })\n },\n 'update submit listener context': sendTo(\n 'submit listener',\n ({context}) => ({type: 'context changed', context}),\n ),\n 'update text insertion listener context': sendTo(\n 'text insertion listener',\n ({context}) => ({type: 'context changed', context}),\n ),\n 'handle error': assign({\n isLoading: false,\n error: ({event}) => (event as {error: Error}).error,\n }),\n },\n guards: {\n 'no focus span': ({context}) => !context.focusSpan,\n 'invalid pattern': ({context}) => {\n if (!context.patternText) {\n return true\n }\n\n // Check if trigger pattern matches entire text (just the trigger, no keyword yet)\n const triggerMatch = context.patternText.match(context.triggerPattern)\n\n if (\n triggerMatch &&\n triggerMatch.index === 0 &&\n triggerMatch[0] === context.patternText\n ) {\n return false\n }\n\n // Check partial pattern matches entire text\n const partialMatch = context.patternText.match(context.partialPattern)\n\n if (\n partialMatch &&\n partialMatch.index === 0 &&\n partialMatch[0] === context.patternText\n ) {\n return false\n }\n\n // Check complete pattern matches entire text (if configured)\n if (context.completePattern) {\n const completeMatch = context.patternText.match(\n context.completePattern,\n )\n\n if (\n completeMatch &&\n completeMatch.index === 0 &&\n completeMatch[0] === context.patternText\n ) {\n return false\n }\n }\n\n return true\n },\n 'no debounce': ({context}) =>\n !context.definition.debounceMs || context.definition.debounceMs === 0,\n 'is complete keyword': ({context}) => {\n if (!context.completePattern || !context.focusSpan) {\n return false\n }\n\n const fullKeywordText = context.focusSpan.node.text.slice(\n context.focusSpan.textBefore.length,\n context.focusSpan.textAfter.length > 0\n ? -context.focusSpan.textAfter.length\n : undefined,\n )\n const completeMatch = fullKeywordText.match(context.completePattern)\n\n if (\n !completeMatch ||\n completeMatch.index !== 0 ||\n completeMatch[0] !== fullKeywordText\n ) {\n return false\n }\n\n return hasAtLeastOneExactMatch(context.matches)\n },\n 'has matches': ({context}) => context.matches.length > 0,\n 'no matches': ({context}) => context.matches.length === 0,\n 'is loading': ({context}) => context.isLoading,\n },\n }).createMachine({\n id: 'typeahead picker',\n context: ({input}) => ({\n editor: input.editor,\n definition: input.definition,\n triggerPattern: buildTriggerPattern(input.definition),\n partialPattern: buildPartialPattern(input.definition),\n completePattern: buildCompletePattern(input.definition),\n matches: [],\n selectedIndex: 0,\n focusSpan: undefined,\n patternText: '',\n keyword: '',\n requestedKeyword: '',\n error: undefined,\n isLoading: false,\n }),\n initial: 'idle',\n states: {\n 'idle': {\n entry: ['reset'],\n invoke: {\n src: 'trigger listener',\n input: ({context}) => ({\n editor: context.editor,\n definition: context.definition,\n }),\n },\n on: {\n 'custom.typeahead trigger found': {\n target: 'active',\n actions: ['handle trigger found'],\n },\n 'custom.typeahead keyword found': {\n target: 'checking complete',\n actions: ['handle trigger found'],\n },\n },\n },\n 'checking complete': {\n invoke: [\n {\n src: 'insert match listener',\n input: ({context}) => ({context}),\n },\n {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: [\n {\n guard: ({event}) =>\n hasAtLeastOneExactMatch(event.output.matches),\n target: 'idle',\n actions: [\n assign({matches: ({event}) => event.output.matches}),\n {type: 'insert match', params: {exact: true}},\n ],\n },\n {\n target: 'active',\n actions: [assign({matches: ({event}) => event.output.matches})],\n },\n ],\n onError: {\n target: 'active.no matches',\n actions: ['handle error'],\n },\n },\n ],\n },\n 'active': {\n invoke: [\n {\n src: 'insert match listener',\n input: ({context}) => ({context}),\n },\n {\n src: 'escape listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'selection listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'submit listener',\n id: 'submit listener',\n input: ({context}) => ({context}),\n },\n {\n src: 'text insertion listener',\n id: 'text insertion listener',\n input: ({context}) => ({context}),\n },\n ],\n on: {\n 'dismiss': {\n target: 'idle',\n },\n 'selection changed': {\n actions: [\n 'update focus span',\n 'update pattern text',\n 'update keyword',\n 'update matches',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n },\n always: [\n {\n guard: 'no focus span',\n target: 'idle',\n },\n {\n guard: 'invalid pattern',\n target: 'idle',\n },\n {\n guard: 'is complete keyword',\n actions: [{type: 'insert match', params: {exact: false}}],\n target: 'idle',\n },\n ],\n initial: 'evaluating',\n states: {\n 'evaluating': {\n always: [\n {\n guard: 'is loading',\n target: 'loading',\n },\n {\n guard: 'has matches',\n target: 'showing matches',\n },\n {\n target: 'no matches',\n },\n ],\n },\n 'loading': {\n entry: [assign({requestedKeyword: ({context}) => context.keyword})],\n initial: 'debouncing',\n states: {\n debouncing: {\n always: [{guard: 'no debounce', target: 'fetching'}],\n after: {\n DEBOUNCE: 'fetching',\n },\n },\n fetching: {\n invoke: {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: {\n target: '#typeahead picker.active.evaluating',\n actions: [\n assign(({context, event}) => {\n if (event.output.keyword !== context.keyword) {\n return {\n isLoading:\n context.patternText !== context.requestedKeyword,\n }\n }\n\n return {\n matches: event.output.matches,\n isLoading:\n context.keyword !== context.requestedKeyword,\n }\n }),\n ],\n },\n onError: {\n target: '#typeahead picker.active.no matches',\n actions: ['handle error'],\n },\n },\n },\n },\n },\n 'no matches': {\n entry: [assign({selectedIndex: 0})],\n always: [\n {\n guard: 'has matches',\n target: 'showing matches',\n },\n ],\n initial: 'idle',\n states: {\n idle: {\n always: [{guard: 'is loading', target: 'loading'}],\n },\n loading: {\n entry: [\n assign({\n requestedKeyword: ({context}) => context.keyword,\n }),\n ],\n initial: 'debouncing',\n states: {\n debouncing: {\n always: [{guard: 'no debounce', target: 'fetching'}],\n after: {\n DEBOUNCE: 'fetching',\n },\n },\n fetching: {\n invoke: {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: {\n target: '#typeahead picker.active.no matches.idle',\n actions: ['handle async load complete'],\n },\n onError: {\n target: '#typeahead picker.active.no matches.idle',\n actions: ['handle error'],\n },\n },\n },\n },\n },\n },\n },\n 'showing matches': {\n entry: [\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n invoke: {\n src: 'arrow listener',\n input: ({context}) => ({editor: context.editor}),\n },\n always: [\n {\n guard: 'no matches',\n target: 'no matches',\n },\n ],\n on: {\n 'navigate down': {\n actions: [\n 'navigate',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n 'navigate up': {\n actions: [\n 'navigate',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n 'navigate to': {\n actions: [\n 'navigate',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n 'select': {\n target: '#typeahead picker.idle',\n actions: [{type: 'insert match', params: {exact: false}}],\n },\n },\n initial: 'idle',\n states: {\n idle: {\n always: [{guard: 'is loading', target: 'loading'}],\n },\n loading: {\n entry: [\n assign({\n requestedKeyword: ({context}) => context.keyword,\n }),\n ],\n initial: 'debouncing',\n states: {\n debouncing: {\n always: [{guard: 'no debounce', target: 'fetching'}],\n after: {\n DEBOUNCE: 'fetching',\n },\n },\n fetching: {\n invoke: {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: {\n target: '#typeahead picker.active.showing matches.idle',\n actions: ['handle async load complete'],\n },\n onError: {\n target: '#typeahead picker.active.showing matches.idle',\n actions: ['handle error'],\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n })\n}\n\n/**\n * Check if matches contain at least one exact match.\n */\nfunction hasAtLeastOneExactMatch<TMatch extends object>(\n matches: ReadonlyArray<TMatch>,\n): boolean {\n return matches.some(\n (match) =>\n (match as unknown as AutoCompleteMatch | undefined)?.type === 'exact',\n )\n}\n\n/**\n * Get the first exact match from matches.\n */\nfunction getFirstExactMatch<TMatch extends object>(\n matches: ReadonlyArray<TMatch>,\n): TMatch | undefined {\n return matches.find(\n (match) =>\n (match as unknown as AutoCompleteMatch | undefined)?.type === 'exact',\n )\n}\n","import {useEditor} from '@portabletext/editor'\nimport {useActor} from '@xstate/react'\nimport {createTypeaheadPickerMachine} from './typeahead-picker-machine'\nimport type {\n TypeaheadPicker,\n TypeaheadPickerDefinition,\n TypeaheadPickerEvent,\n TypeaheadPickerState,\n} from './typeahead-picker.types'\n\n/**\n * React hook that activates a typeahead picker and returns its current state.\n *\n * Call inside a component rendered within an `EditorProvider`.\n * The picker automatically monitors the editor for trigger patterns.\n *\n * @example\n * ```tsx\n * function MentionPickerUI() {\n * const picker = useTypeaheadPicker(mentionPickerDefinition)\n *\n * if (picker.snapshot.matches('idle')) return null\n * if (picker.snapshot.matches({active: 'loading'})) return <Spinner />\n * if (picker.snapshot.matches({active: 'no matches'})) return <NoResults />\n *\n * const {matches, selectedIndex} = picker.snapshot.context\n *\n * return (\n * <ul>\n * {matches.map((match, index) => (\n * <li\n * key={match.key}\n * aria-selected={index === selectedIndex}\n * onMouseEnter={() => picker.send({type: 'navigate to', index})}\n * onClick={() => picker.send({type: 'select'})}\n * >\n * {match.name}\n * </li>\n * ))}\n * </ul>\n * )\n * }\n * ```\n *\n * @public\n */\nexport function useTypeaheadPicker<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): TypeaheadPicker<TMatch> {\n const editor = useEditor()\n const [actorSnapshot, send] = useActor(\n createTypeaheadPickerMachine<TMatch>(),\n {\n input: {\n editor,\n definition,\n },\n },\n )\n\n return {\n snapshot: {\n matches: (state: TypeaheadPickerState) => actorSnapshot.matches(state),\n context: {\n keyword: actorSnapshot.context.keyword,\n matches: actorSnapshot.context.matches as ReadonlyArray<TMatch>,\n selectedIndex: actorSnapshot.context.selectedIndex,\n error: actorSnapshot.context.error,\n },\n },\n send: (event: TypeaheadPickerEvent) => {\n send(event)\n },\n }\n}\n"],"names":["defineTypeaheadPicker","config","_id","extractKeyword","patternText","triggerPattern","delimiter","completePattern","triggerMatch","match","index","keyword","slice","length","endsWith","completeMatch","escapeRegExp","str","replace","buildTriggerPattern","definition","RegExp","trigger","source","buildPartialPattern","buildCompletePattern","escapedDelimiter","arrowUpShortcut","createKeyboardShortcut","default","key","arrowDownShortcut","enterShortcut","tabShortcut","escapeShortcut","getTriggerState","snapshot","focusSpan","getFocusSpan","markState","getMarkState","context","selection","focusSpanTextBefore","node","text","focus","offset","focusSpanTextAfter","previousSpan","getPreviousSpan","nextSpan","getNextSpan","createTriggerActions","payload","keywordState","pickerId","state","textBeforeMatch","lastMatch","targetOffsets","anchor","_key","_type","marks","path","textBefore","textAfter","raise","createKeywordFoundEvent","extractedKeyword","createTriggerFoundEvent","newSpan","keyGenerator","JSON","stringify","type","at","child","extractPatternTextFromFocusSpan","createInputRules","rules","partialPattern","completeRule","defineInputRule","on","guard","event","matches","undefined","insertedMatch","textInserted","triggerState","actions","push","partialRule","triggerRule","triggerListenerCallback","sendBack","input","unregisterBehaviors","editor","registerBehavior","behavior","defineInputRuleBehavior","defineBehavior","effect","unregister","escapeListenerCallback","originEvent","arrowListenerCallback","selectionListenerCallback","unsubscribe","submitListenerCallback","receive","selectedIndex","forward","textInsertionListenerCallback","keywordAnchor","isEqualSelectionPoints","insertMatchListenerCallback","dom","patternSelection","allActions","actionSet","action","queueMicrotask","currentSelection","getSnapshot","send","createTypeaheadPickerMachine","setup","types","events","delays","DEBOUNCE","debounceMs","actors","fromCallback","fromPromise","result","getMatches","Promise","resolve","assign","mode","isLoading","requestedKeyword","isEqualPaths","isSelectionCollapsed","startsWith","keywordFocus","selectionIsBeforeKeyword","isPointAfterSelection","selectionIsAfterKeyword","isPointBeforeSelection","output","error","insert match","params","exact","getFirstExactMatch","sendTo","guards","no focus span","invalid pattern","partialMatch","no debounce","is complete keyword","fullKeywordText","hasAtLeastOneExactMatch","has matches","no matches","is loading","createMachine","id","initial","states","entry","invoke","src","target","onDone","onError","always","debouncing","after","fetching","idle","loading","some","find","useTypeaheadPicker","$","_c","useEditor","t0","Symbol","for","t1","actorSnapshot","useActor","t2","t3","t4","t5","t6","t7"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/define-typeahead-picker.ts","../src/extract-keyword.ts","../src/typeahead-picker-machine.tsx","../src/use-typeahead-picker.ts"],"sourcesContent":["import type {\n AutoCompleteMatch,\n TypeaheadPickerDefinition,\n TypeaheadSelectActionSet,\n TypeaheadTriggerGuard,\n} from './typeahead-picker.types'\n\ntype BaseConfigWithoutDelimiter<TMatch extends object> = {\n /**\n * Pattern that activates the picker. Must be a single character.\n * Can include `^` for start-of-block triggers.\n *\n * @example `/:/` - activates on colon\n * @example `/@/` - activates on at-sign\n * @example `/^\\//` - activates on slash at start of block\n */\n trigger: RegExp\n /**\n * Pattern matching the keyword portion after the trigger.\n * The entire match becomes the keyword passed to `getMatches`.\n * Common patterns: non-whitespace (`\\S*`) or word characters (`\\w*`).\n */\n keyword: RegExp\n delimiter?: undefined\n /**\n * Guard function that runs at trigger time to conditionally prevent activation.\n * Return `false` to block activation, or `true` to allow it.\n */\n guard?: TypeaheadTriggerGuard\n /**\n * Actions to execute when a match is selected.\n * Typically deletes the trigger text and inserts the selected content.\n */\n actions: Array<TypeaheadSelectActionSet<TMatch>>\n}\n\ntype BaseConfigWithDelimiter<TMatch extends AutoCompleteMatch> = {\n /**\n * Pattern that activates the picker. Must be a single character.\n * Can include `^` for start-of-block triggers.\n *\n * @example `/:/` - activates on colon\n * @example `/@/` - activates on at-sign\n * @example `/^\\//` - activates on slash at start of block\n */\n trigger: RegExp\n /**\n * Pattern matching the keyword portion after the trigger.\n * The entire match becomes the keyword passed to `getMatches`.\n * Common patterns: non-whitespace (`\\S*`) or word characters (`\\w*`).\n */\n keyword: RegExp\n /**\n * Character that triggers auto-completion.\n * Typing this after a keyword with an exact match auto-inserts it.\n *\n * @example `':'` - typing `:joy:` auto-inserts the joy emoji\n */\n delimiter: string\n /**\n * Guard function that runs at trigger time to conditionally prevent activation.\n * Return `false` to block activation, or `true` to allow it.\n */\n guard?: TypeaheadTriggerGuard\n /**\n * Actions to execute when a match is selected.\n * Typically deletes the trigger text and inserts the selected content.\n */\n actions: Array<TypeaheadSelectActionSet<TMatch>>\n}\n\ntype SyncConfigWithoutDelimiter<TMatch extends object> =\n BaseConfigWithoutDelimiter<TMatch> & {\n /**\n * Whether `getMatches` returns synchronously or asynchronously.\n * @defaultValue `'sync'`\n */\n mode?: 'sync'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Useful for expensive local searches.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => ReadonlyArray<TMatch>\n }\n\ntype SyncConfigWithDelimiter<TMatch extends AutoCompleteMatch> =\n BaseConfigWithDelimiter<TMatch> & {\n /**\n * Whether `getMatches` returns synchronously or asynchronously.\n * @defaultValue `'sync'`\n */\n mode?: 'sync'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Useful for expensive local searches.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => ReadonlyArray<TMatch>\n }\n\ntype AsyncConfigWithoutDelimiter<TMatch extends object> =\n BaseConfigWithoutDelimiter<TMatch> & {\n /**\n * Set to `'async'` when `getMatches` returns a Promise.\n */\n mode: 'async'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Recommended for API calls to reduce request frequency.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Async function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => Promise<ReadonlyArray<TMatch>>\n }\n\ntype AsyncConfigWithDelimiter<TMatch extends AutoCompleteMatch> =\n BaseConfigWithDelimiter<TMatch> & {\n /**\n * Set to `'async'` when `getMatches` returns a Promise.\n */\n mode: 'async'\n /**\n * Debounce delay in milliseconds before calling `getMatches`.\n * Recommended for API calls to reduce request frequency.\n * @defaultValue `0` (no debounce)\n */\n debounceMs?: number\n /**\n * Async function that returns matches for the current keyword.\n * Called whenever the keyword changes (after debounce if configured).\n */\n getMatches: (context: {keyword: string}) => Promise<ReadonlyArray<TMatch>>\n }\n\n/**\n * Creates a typeahead picker definition to use with {@link useTypeaheadPicker}.\n *\n * @example Emoji picker with auto-complete\n * ```ts\n * const emojiPicker = defineTypeaheadPicker({\n * trigger: /:/,\n * keyword: /[\\S]+/,\n * delimiter: ':',\n * getMatches: ({keyword}) => searchEmojis(keyword),\n * actions: [insertEmojiAction],\n * })\n * ```\n *\n * @example Async mention picker\n * ```ts\n * const mentionPicker = defineTypeaheadPicker({\n * mode: 'async',\n * trigger: /@/,\n * keyword: /[\\w]+/,\n * debounceMs: 200,\n * getMatches: async ({keyword}) => api.searchUsers(keyword),\n * actions: [insertMentionAction],\n * })\n * ```\n *\n * @example Slash commands at start of block\n * ```ts\n * const slashCommandPicker = defineTypeaheadPicker({\n * trigger: /^\\//,\n * keyword: /[\\w]+/,\n * getMatches: ({keyword}) => filterCommands(keyword),\n * actions: [executeCommandAction],\n * })\n * ```\n *\n * @example Picker with guard (runs at trigger time)\n * ```ts\n * const emojiPicker = defineTypeaheadPicker({\n * trigger: /:/,\n * keyword: /[\\S]+/,\n * getMatches: ({keyword}) => searchEmojis(keyword),\n * guard: ({snapshot}) => {\n * // Return false to prevent picker from activating\n * if (anotherPickerIsOpen()) return false\n * return true\n * },\n * actions: [({event}) => [\n * raise({type: 'delete', at: event.patternSelection}),\n * raise({type: 'insert.text', text: event.match.emoji}),\n * ]],\n * })\n * ```\n *\n * @public\n */\nexport function defineTypeaheadPicker<TMatch extends object>(\n config: SyncConfigWithoutDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends AutoCompleteMatch>(\n config: SyncConfigWithDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends object>(\n config: AsyncConfigWithoutDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends AutoCompleteMatch>(\n config: AsyncConfigWithDelimiter<TMatch>,\n): TypeaheadPickerDefinition<TMatch>\n/** @public */\nexport function defineTypeaheadPicker<TMatch extends object>(\n config:\n | SyncConfigWithoutDelimiter<TMatch>\n | SyncConfigWithDelimiter<TMatch & AutoCompleteMatch>\n | AsyncConfigWithoutDelimiter<TMatch>\n | AsyncConfigWithDelimiter<TMatch & AutoCompleteMatch>,\n): TypeaheadPickerDefinition<TMatch> {\n return {\n ...config,\n _id: Symbol('typeahead-picker'),\n } as TypeaheadPickerDefinition<TMatch>\n}\n","/**\n * Extract keyword from pattern text using the trigger pattern.\n * Removes the trigger match from the start and delimiter from the end.\n *\n * @param patternText - The full pattern text (e.g., `:joy:` or `:joy`)\n * @param triggerPattern - Pattern matching the trigger (e.g., /:/)\n * @param delimiter - Optional delimiter character (e.g., `:`)\n * @param completePattern - Optional complete pattern to detect if this is a complete match\n */\nexport function extractKeyword(\n patternText: string,\n triggerPattern: RegExp,\n delimiter?: string,\n completePattern?: RegExp,\n): string {\n const triggerMatch = patternText.match(triggerPattern)\n\n if (!triggerMatch || triggerMatch.index !== 0) {\n return patternText\n }\n\n let keyword = patternText.slice(triggerMatch[0].length)\n\n if (delimiter && keyword.endsWith(delimiter)) {\n // Check if this is a complete match (pattern matches the complete pattern exactly)\n const isCompleteMatch =\n completePattern &&\n (() => {\n const completeMatch = patternText.match(completePattern)\n return (\n completeMatch &&\n completeMatch.index === 0 &&\n completeMatch[0] === patternText\n )\n })()\n\n // Strip delimiter if:\n // - This is a complete match (even if keyword becomes empty), OR\n // - Keyword would remain non-empty after stripping\n if (isCompleteMatch || keyword.length > delimiter.length) {\n keyword = keyword.slice(0, -delimiter.length)\n }\n }\n\n return keyword\n}\n","import type {\n ChildPath,\n Editor,\n EditorSelector,\n EditorSnapshot,\n PortableTextSpan,\n} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n forward,\n raise,\n type BehaviorAction,\n} from '@portabletext/editor/behaviors'\nimport {\n getFocusSpan,\n getMarkState,\n getNextSpan,\n getPreviousSpan,\n isPointAfterSelection,\n isPointBeforeSelection,\n isSelectionCollapsed,\n type MarkState,\n} from '@portabletext/editor/selectors'\nimport {isEqualPaths, isEqualSelectionPoints} from '@portabletext/editor/utils'\nimport {createKeyboardShortcut} from '@portabletext/keyboard-shortcuts'\nimport {\n defineInputRule,\n defineInputRuleBehavior,\n type InputRuleMatch,\n} from '@portabletext/plugin-input-rule'\nimport {\n assign,\n fromCallback,\n fromPromise,\n sendTo,\n setup,\n type AnyEventObject,\n type CallbackLogicFunction,\n} from 'xstate'\nimport {extractKeyword} from './extract-keyword'\nimport type {\n AutoCompleteMatch,\n TypeaheadPickerDefinition,\n} from './typeahead-picker.types'\n\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Build the trigger pattern from the definition.\n */\nfunction buildTriggerPattern<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): RegExp {\n return new RegExp(definition.trigger.source)\n}\n\n/**\n * Build the partial pattern (trigger + keyword) from the definition.\n */\nfunction buildPartialPattern<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): RegExp {\n return new RegExp(definition.trigger.source + definition.keyword.source)\n}\n\n/**\n * Build the complete pattern (trigger + keyword + delimiter) from the definition.\n */\nfunction buildCompletePattern<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): RegExp | undefined {\n if (!definition.delimiter) {\n return undefined\n }\n\n const escapedDelimiter = escapeRegExp(definition.delimiter)\n return new RegExp(\n definition.trigger.source + definition.keyword.source + escapedDelimiter,\n )\n}\n\nconst arrowUpShortcut = createKeyboardShortcut({\n default: [{key: 'ArrowUp'}],\n})\nconst arrowDownShortcut = createKeyboardShortcut({\n default: [{key: 'ArrowDown'}],\n})\nconst enterShortcut = createKeyboardShortcut({\n default: [{key: 'Enter'}],\n})\nconst tabShortcut = createKeyboardShortcut({\n default: [{key: 'Tab'}],\n})\nconst escapeShortcut = createKeyboardShortcut({\n default: [{key: 'Escape'}],\n})\n\nconst getTriggerState: EditorSelector<\n | {\n focusSpan: {\n node: PortableTextSpan\n path: ChildPath\n }\n markState: MarkState\n focusSpanTextBefore: string\n focusSpanTextAfter: string\n previousSpan:\n | {\n node: PortableTextSpan\n path: ChildPath\n }\n | undefined\n nextSpan:\n | {\n node: PortableTextSpan\n path: ChildPath\n }\n | undefined\n }\n | undefined\n> = (snapshot) => {\n const focusSpan = getFocusSpan(snapshot)\n const markState = getMarkState(snapshot)\n\n if (!focusSpan || !markState || !snapshot.context.selection) {\n return undefined\n }\n\n const focusSpanTextBefore = focusSpan.node.text.slice(\n 0,\n snapshot.context.selection.focus.offset,\n )\n const focusSpanTextAfter = focusSpan.node.text.slice(\n snapshot.context.selection.focus.offset,\n )\n const previousSpan = getPreviousSpan(snapshot)\n const nextSpan = getNextSpan(snapshot)\n\n return {\n focusSpan,\n markState,\n focusSpanTextBefore,\n focusSpanTextAfter,\n previousSpan,\n nextSpan,\n }\n}\n\ntype FocusSpanData = {\n node: PortableTextSpan\n path: ChildPath\n textBefore: string\n textAfter: string\n}\n\nfunction createTriggerActions({\n snapshot,\n payload,\n keywordState,\n pickerId,\n}: {\n snapshot: EditorSnapshot\n payload: TriggerPayload\n keywordState: 'partial' | 'complete'\n pickerId: symbol\n}) {\n if (payload.markState.state === 'unchanged') {\n const textBeforeMatch = payload.focusSpanTextBefore.slice(\n 0,\n payload.lastMatch.targetOffsets.anchor.offset,\n )\n const focusSpan = {\n node: {\n _key: payload.focusSpan.node._key,\n _type: payload.focusSpan.node._type,\n text: `${textBeforeMatch}${payload.lastMatch.text}${payload.focusSpanTextAfter}`,\n marks: payload.markState.marks,\n },\n path: payload.focusSpan.path,\n textBefore: textBeforeMatch,\n textAfter: payload.focusSpanTextAfter,\n }\n\n if (keywordState === 'complete') {\n return [\n raise(\n createKeywordFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]\n }\n\n return [\n raise(\n createTriggerFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]\n }\n\n const newSpan = {\n _key: snapshot.context.keyGenerator(),\n _type: payload.focusSpan.node._type,\n text: payload.lastMatch.text,\n marks: payload.markState.marks,\n }\n\n let focusSpan: FocusSpanData = {\n node: {\n _key: newSpan._key,\n _type: newSpan._type,\n text: `${newSpan.text}${payload.nextSpan?.node.text ?? payload.focusSpanTextAfter}`,\n marks: payload.markState.marks,\n },\n path: [\n {_key: payload.focusSpan.path[0]._key},\n 'children',\n {_key: newSpan._key},\n ] satisfies ChildPath,\n textBefore: '',\n textAfter: payload.nextSpan?.node.text ?? payload.focusSpanTextAfter,\n }\n\n if (\n payload.previousSpan &&\n payload.focusSpanTextBefore.length === 0 &&\n JSON.stringify(payload.previousSpan.node.marks ?? []) ===\n JSON.stringify(payload.markState.marks)\n ) {\n focusSpan = {\n node: {\n _key: payload.previousSpan.node._key,\n _type: newSpan._type,\n text: `${payload.previousSpan.node.text}${newSpan.text}`,\n marks: newSpan.marks,\n },\n path: payload.previousSpan.path,\n textBefore: payload.previousSpan.node.text,\n textAfter: '',\n }\n }\n\n return [\n raise({type: 'select', at: payload.lastMatch.targetOffsets}),\n raise({type: 'delete', at: payload.lastMatch.targetOffsets}),\n raise({type: 'insert.child', child: newSpan}),\n ...(keywordState === 'complete'\n ? [\n raise(\n createKeywordFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]\n : [\n raise(\n createTriggerFoundEvent({\n focusSpan,\n extractedKeyword: payload.extractedKeyword,\n pickerId,\n }),\n ),\n ]),\n ]\n}\n\ntype TriggerFoundEvent = {\n type: 'custom.typeahead trigger found'\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}\n\nfunction createTriggerFoundEvent(payload: {\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}): TriggerFoundEvent {\n return {\n type: 'custom.typeahead trigger found',\n ...payload,\n }\n}\n\ntype KeywordFoundEvent = {\n type: 'custom.typeahead keyword found'\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}\n\nfunction createKeywordFoundEvent(payload: {\n focusSpan: FocusSpanData\n extractedKeyword: string\n pickerId: symbol\n}): KeywordFoundEvent {\n return {\n type: 'custom.typeahead keyword found',\n ...payload,\n }\n}\n\ntype TypeaheadPickerMachineContext<TMatch extends object> = {\n editor: Editor\n definition: TypeaheadPickerDefinition<TMatch>\n triggerPattern: RegExp\n partialPattern: RegExp\n completePattern: RegExp | undefined\n matches: ReadonlyArray<TMatch>\n selectedIndex: number\n focusSpan: FocusSpanData | undefined\n patternText: string\n keyword: string\n requestedKeyword: string\n error: Error | undefined\n isLoading: boolean\n}\n\ntype TypeaheadPickerMachineEvent<TMatch extends object> =\n | TriggerFoundEvent\n | KeywordFoundEvent\n | {type: 'selection changed'}\n | {type: 'dismiss'}\n | {type: 'navigate down'}\n | {type: 'navigate up'}\n | {type: 'navigate to'; index: number}\n | {type: 'select'}\n | {type: 'matches loaded'; matches: ReadonlyArray<TMatch>}\n | {type: 'matches error'; error: Error}\n\ntype TriggerPayload = ReturnType<typeof getTriggerState> & {\n lastMatch: InputRuleMatch\n extractedKeyword: string\n}\n\n/**\n * Extract the pattern text (trigger + keyword) from focus span data.\n */\nfunction extractPatternTextFromFocusSpan(focusSpan: FocusSpanData): string {\n if (focusSpan.textBefore.length > 0 && focusSpan.textAfter.length > 0) {\n return focusSpan.node.text.slice(\n focusSpan.textBefore.length,\n -focusSpan.textAfter.length,\n )\n }\n\n if (focusSpan.textBefore.length > 0) {\n return focusSpan.node.text.slice(focusSpan.textBefore.length)\n }\n\n if (focusSpan.textAfter.length > 0) {\n return focusSpan.node.text.slice(0, -focusSpan.textAfter.length)\n }\n\n return focusSpan.node.text\n}\n\nfunction createInputRules<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n) {\n const rules: Array<ReturnType<typeof defineInputRule<TriggerPayload>>> = []\n\n const triggerPattern = buildTriggerPattern(definition)\n const partialPattern = buildPartialPattern(definition)\n const completePattern = buildCompletePattern(definition)\n\n if (completePattern) {\n const completeRule = defineInputRule<TriggerPayload>({\n on: completePattern,\n guard: ({snapshot, event}) => {\n const lastMatch = event.matches.at(-1)\n\n if (lastMatch === undefined) {\n return false\n }\n\n if (lastMatch.targetOffsets.anchor.offset < event.textBefore.length) {\n // Match starts before insertion. Check if the inserted text itself\n // matches the complete pattern (e.g., inserting `:dog:` after `foo:`).\n const insertedMatch = event.textInserted.match(completePattern)\n\n if (insertedMatch === null || insertedMatch.index !== 0) {\n return false\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch: {\n ...lastMatch,\n text: event.textInserted,\n targetOffsets: {\n ...lastMatch.targetOffsets,\n anchor: {\n ...lastMatch.targetOffsets.anchor,\n offset: event.textBefore.length,\n },\n },\n },\n extractedKeyword: extractKeyword(\n event.textInserted,\n triggerPattern,\n definition.delimiter,\n completePattern,\n ),\n }\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch,\n extractedKeyword: extractKeyword(\n lastMatch.text,\n triggerPattern,\n definition.delimiter,\n completePattern,\n ),\n }\n },\n actions: [\n ({snapshot}, payload) =>\n createTriggerActions({\n snapshot,\n payload,\n keywordState: 'complete',\n pickerId: definition._id,\n }),\n ],\n })\n\n rules.push(completeRule)\n }\n\n const partialRule = defineInputRule<TriggerPayload>({\n on: partialPattern,\n guard: ({snapshot, event}) => {\n const lastMatch = event.matches.at(-1)\n\n if (lastMatch === undefined) {\n return false\n }\n\n if (lastMatch.targetOffsets.anchor.offset < event.textBefore.length) {\n // Match starts before insertion. Check if the inserted text itself\n // matches the partial pattern (e.g., inserting `:dog` after `foo:`).\n const insertedMatch = event.textInserted.match(partialPattern)\n\n if (insertedMatch === null || insertedMatch.index !== 0) {\n return false\n }\n\n // Don't match if this is actually a complete pattern\n if (completePattern) {\n const completeMatch = event.textInserted.match(completePattern)\n\n if (\n completeMatch !== null &&\n completeMatch.index === 0 &&\n completeMatch[0] === event.textInserted\n ) {\n return false\n }\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch: {\n ...lastMatch,\n text: event.textInserted,\n targetOffsets: {\n ...lastMatch.targetOffsets,\n anchor: {\n ...lastMatch.targetOffsets.anchor,\n offset: event.textBefore.length,\n },\n },\n },\n extractedKeyword: extractKeyword(\n event.textInserted,\n triggerPattern,\n definition.delimiter,\n ),\n }\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch,\n extractedKeyword: extractKeyword(\n lastMatch.text,\n triggerPattern,\n definition.delimiter,\n ),\n }\n },\n actions: [\n ({snapshot}, payload) =>\n createTriggerActions({\n snapshot,\n payload,\n keywordState: 'partial',\n pickerId: definition._id,\n }),\n ],\n })\n\n rules.push(partialRule)\n\n const triggerRule = defineInputRule<TriggerPayload>({\n on: triggerPattern,\n guard: ({snapshot, event}) => {\n const lastMatch = event.matches.at(-1)\n\n if (lastMatch === undefined) {\n return false\n }\n\n if (event.textInserted !== lastMatch.text) {\n return false\n }\n\n const triggerState = getTriggerState(snapshot)\n\n if (!triggerState) {\n return false\n }\n\n return {\n ...triggerState,\n lastMatch,\n extractedKeyword: '',\n }\n },\n actions: [\n ({snapshot}, payload) =>\n createTriggerActions({\n snapshot,\n payload,\n keywordState: 'partial',\n pickerId: definition._id,\n }),\n ],\n })\n\n rules.push(triggerRule)\n\n return rules\n}\n\nfunction createTriggerGuard<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n) {\n return ({\n event,\n snapshot,\n dom,\n }: {\n event: TriggerFoundEvent | KeywordFoundEvent\n snapshot: EditorSnapshot\n dom: Parameters<NonNullable<typeof definition.guard>>[0]['dom']\n }): true | false => {\n if (event.pickerId !== definition._id) {\n return false\n }\n\n if (!definition.guard) {\n return true\n }\n\n return definition.guard({\n snapshot,\n dom,\n event: {\n type: 'custom.typeahead trigger found',\n },\n })\n }\n}\n\nconst triggerListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor; definition: TypeaheadPickerDefinition<TMatch>}\n> => {\n return ({sendBack, input}) => {\n const rules = createInputRules(input.definition)\n const triggerGuard = createTriggerGuard(input.definition)\n\n const unregisterBehaviors = [\n input.editor.registerBehavior({\n behavior: defineInputRuleBehavior({rules}),\n }),\n input.editor.registerBehavior({\n behavior: defineBehavior<KeywordFoundEvent, KeywordFoundEvent['type']>({\n on: 'custom.typeahead keyword found',\n guard: triggerGuard,\n actions: [\n ({event}) => [\n effect(() => {\n sendBack(event)\n }),\n ],\n ],\n }),\n }),\n input.editor.registerBehavior({\n behavior: defineBehavior<TriggerFoundEvent, TriggerFoundEvent['type']>({\n on: 'custom.typeahead trigger found',\n guard: triggerGuard,\n actions: [\n ({event}) => [\n effect(() => {\n sendBack(event)\n }),\n ],\n ],\n }),\n }),\n ]\n\n return () => {\n for (const unregister of unregisterBehaviors) {\n unregister()\n }\n }\n }\n}\n\nconst escapeListenerCallback = <TMatch extends object>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor}\n> => {\n return ({sendBack, input}) => {\n return input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => escapeShortcut.guard(event.originEvent),\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n })\n }\n}\n\nconst arrowListenerCallback = <TMatch extends object>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor}\n> => {\n return ({sendBack, input}) => {\n const unregisterBehaviors = [\n input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => arrowDownShortcut.guard(event.originEvent),\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'navigate down'})\n }),\n ],\n ],\n }),\n }),\n input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => arrowUpShortcut.guard(event.originEvent),\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'navigate up'})\n }),\n ],\n ],\n }),\n }),\n ]\n\n return () => {\n for (const unregister of unregisterBehaviors) {\n unregister()\n }\n }\n }\n}\n\nconst selectionListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {editor: Editor}\n> => {\n return ({sendBack, input}) => {\n const subscription = input.editor.on('selection', () => {\n sendBack({type: 'selection changed'})\n })\n\n return subscription.unsubscribe\n }\n}\n\nconst submitListenerCallback = <TMatch extends object>(): CallbackLogicFunction<\n {type: 'context changed'; context: TypeaheadPickerMachineContext<TMatch>},\n TypeaheadPickerMachineEvent<TMatch>,\n {context: TypeaheadPickerMachineContext<TMatch>}\n> => {\n return ({sendBack, input, receive}) => {\n let context = input.context\n\n receive((event) => {\n context = event.context\n })\n\n const unregisterBehaviors = [\n input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) => {\n if (\n !enterShortcut.guard(event.originEvent) &&\n !tabShortcut.guard(event.originEvent)\n ) {\n return false\n }\n\n const focusSpan = context.focusSpan\n const match = context.matches[context.selectedIndex]\n\n return match && focusSpan ? {focusSpan, match} : false\n },\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'select'})\n }),\n ],\n ],\n }),\n }),\n input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) =>\n (enterShortcut.guard(event.originEvent) ||\n tabShortcut.guard(event.originEvent)) &&\n context.patternText.length === 1,\n actions: [\n ({event}) => [\n forward(event),\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n }),\n input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'keyboard.keydown',\n guard: ({event}) =>\n (enterShortcut.guard(event.originEvent) ||\n tabShortcut.guard(event.originEvent)) &&\n context.patternText.length > 1 &&\n context.matches.length === 0,\n actions: [\n () => [\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n }),\n ]\n\n return () => {\n for (const unregister of unregisterBehaviors) {\n unregister()\n }\n }\n }\n}\n\nconst textInsertionListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n {type: 'context changed'; context: TypeaheadPickerMachineContext<TMatch>},\n TypeaheadPickerMachineEvent<TMatch>,\n {context: TypeaheadPickerMachineContext<TMatch>}\n> => {\n return ({sendBack, input, receive}) => {\n let context = input.context\n\n receive((event) => {\n context = event.context\n })\n\n return input.context.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'insert.text',\n guard: ({snapshot}) => {\n if (!context.focusSpan) {\n return false\n }\n\n if (!snapshot.context.selection) {\n return false\n }\n\n const keywordAnchor = {\n path: context.focusSpan.path,\n offset: context.focusSpan.textBefore.length,\n }\n\n return isEqualSelectionPoints(\n snapshot.context.selection.focus,\n keywordAnchor,\n )\n },\n actions: [\n ({event}) => [\n forward(event),\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ],\n ],\n }),\n })\n }\n}\n\ntype InsertMatchEvent<TMatch extends object> = {\n type: 'custom.typeahead insert match'\n match: TMatch\n focusSpan: FocusSpanData\n keyword: string\n pickerId: symbol\n}\n\nconst selectMatchListenerCallback = <\n TMatch extends object,\n>(): CallbackLogicFunction<\n AnyEventObject,\n TypeaheadPickerMachineEvent<TMatch>,\n {context: TypeaheadPickerMachineContext<TMatch>}\n> => {\n return ({sendBack, input}) => {\n return input.context.editor.registerBehavior({\n behavior: defineBehavior<InsertMatchEvent<TMatch>>({\n on: 'custom.typeahead select match',\n guard: ({event}) => event.pickerId === input.context.definition._id,\n actions: [\n ({event, snapshot, dom}) => {\n const patternSelection = {\n anchor: {\n path: event.focusSpan.path,\n offset: event.focusSpan.textBefore.length,\n },\n focus: {\n path: event.focusSpan.path,\n offset:\n event.focusSpan.node.text.length -\n event.focusSpan.textAfter.length,\n },\n }\n\n const allActions: Array<BehaviorAction> = [\n effect(() => {\n sendBack({type: 'dismiss'})\n }),\n ]\n\n for (const actionSet of input.context.definition.actions) {\n const actions = actionSet(\n {\n snapshot,\n dom,\n event: {\n type: 'custom.typeahead select',\n match: event.match,\n keyword: event.keyword,\n patternSelection,\n },\n },\n true,\n )\n\n for (const action of actions) {\n allActions.push(action)\n }\n }\n\n return allActions\n },\n ],\n }),\n })\n }\n}\n\nexport function createTypeaheadPickerMachine<TMatch extends object>() {\n return setup({\n types: {\n context: {} as TypeaheadPickerMachineContext<TMatch>,\n input: {} as {\n editor: Editor\n definition: TypeaheadPickerDefinition<TMatch>\n },\n events: {} as TypeaheadPickerMachineEvent<TMatch>,\n },\n delays: {\n DEBOUNCE: ({context}) => context.definition.debounceMs ?? 0,\n },\n actors: {\n 'trigger listener': fromCallback(triggerListenerCallback<TMatch>()),\n 'escape listener': fromCallback(escapeListenerCallback<TMatch>()),\n 'arrow listener': fromCallback(arrowListenerCallback<TMatch>()),\n 'selection listener': fromCallback(selectionListenerCallback<TMatch>()),\n 'submit listener': fromCallback(submitListenerCallback<TMatch>()),\n 'text insertion listener': fromCallback(\n textInsertionListenerCallback<TMatch>(),\n ),\n 'select match listener': fromCallback(\n selectMatchListenerCallback<TMatch>(),\n ),\n 'get matches': fromPromise(\n async ({\n input,\n }: {\n input: {\n keyword: string\n getMatches: TypeaheadPickerDefinition<TMatch>['getMatches']\n }\n }) => {\n const result = input.getMatches({keyword: input.keyword})\n const matches = await Promise.resolve(result)\n return {keyword: input.keyword, matches}\n },\n ),\n },\n actions: {\n 'handle trigger found': assign(({context, event}) => {\n if (\n event.type !== 'custom.typeahead trigger found' &&\n event.type !== 'custom.typeahead keyword found'\n ) {\n return {}\n }\n\n const focusSpan = event.focusSpan\n const patternText = extractPatternTextFromFocusSpan(focusSpan)\n const keyword = event.extractedKeyword\n\n if (\n context.definition.mode === 'async' ||\n context.definition.debounceMs\n ) {\n return {\n focusSpan,\n patternText,\n keyword,\n isLoading: true,\n selectedIndex: 0,\n }\n }\n\n const matches = context.definition.getMatches({\n keyword,\n }) as Array<TMatch>\n\n return {\n focusSpan,\n patternText,\n keyword,\n matches,\n requestedKeyword: keyword,\n isLoading: false,\n selectedIndex: 0,\n }\n }),\n 'update focus span': assign({\n focusSpan: ({context}) => {\n if (!context.focusSpan) {\n return context.focusSpan\n }\n\n const snapshot = context.editor.getSnapshot()\n const focusSpan = getFocusSpan(snapshot)\n\n if (!snapshot.context.selection || !focusSpan) {\n return undefined\n }\n\n const nextSpan = getNextSpan({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: {path: context.focusSpan.path, offset: 0},\n focus: {path: context.focusSpan.path, offset: 0},\n },\n },\n })\n\n if (!isEqualPaths(focusSpan.path, context.focusSpan.path)) {\n if (\n nextSpan &&\n context.focusSpan.textAfter.length === 0 &&\n snapshot.context.selection.focus.offset === 0 &&\n isSelectionCollapsed(snapshot)\n ) {\n // This is an edge case where the caret is moved from the end of\n // the focus span to the start of the next span.\n return context.focusSpan\n }\n\n return undefined\n }\n\n if (!focusSpan.node.text.startsWith(context.focusSpan.textBefore)) {\n return undefined\n }\n\n if (!focusSpan.node.text.endsWith(context.focusSpan.textAfter)) {\n return undefined\n }\n\n const keywordAnchor = {\n path: focusSpan.path,\n offset: context.focusSpan.textBefore.length,\n }\n const keywordFocus = {\n path: focusSpan.path,\n offset:\n focusSpan.node.text.length - context.focusSpan.textAfter.length,\n }\n\n const selectionIsBeforeKeyword =\n isPointAfterSelection(keywordAnchor)(snapshot)\n const selectionIsAfterKeyword =\n isPointBeforeSelection(keywordFocus)(snapshot)\n\n if (selectionIsBeforeKeyword || selectionIsAfterKeyword) {\n return undefined\n }\n\n return {\n node: focusSpan.node,\n path: focusSpan.path,\n textBefore: context.focusSpan.textBefore,\n textAfter: context.focusSpan.textAfter,\n }\n },\n }),\n 'update pattern text': assign(({context}) => {\n if (!context.focusSpan) {\n return {}\n }\n\n const patternText = extractPatternTextFromFocusSpan(context.focusSpan)\n\n if (patternText === context.patternText) {\n return {}\n }\n\n return {patternText, selectedIndex: 0}\n }),\n 'update keyword': assign(({context}) => {\n if (!context.focusSpan || !context.patternText) {\n return {}\n }\n\n const keyword = extractKeyword(\n context.patternText,\n context.triggerPattern,\n context.definition.delimiter,\n context.completePattern,\n )\n\n if (keyword === context.keyword) {\n return {}\n }\n\n return {keyword}\n }),\n 'update matches': assign(({context}) => {\n if (!context.focusSpan || !context.patternText) {\n return {}\n }\n\n if (\n context.definition.mode === 'async' ||\n context.definition.debounceMs\n ) {\n return {\n isLoading:\n context.isLoading || context.requestedKeyword !== context.keyword,\n }\n }\n\n const matches = context.definition.getMatches({\n keyword: context.keyword,\n }) as Array<TMatch>\n\n return {\n matches,\n requestedKeyword: context.keyword,\n isLoading: false,\n }\n }),\n 'handle async load complete': assign(({context, event}) => {\n const output = (\n event as unknown as {\n output: {keyword: string; matches: ReadonlyArray<TMatch>}\n }\n ).output\n\n if (output.keyword !== context.keyword) {\n return {isLoading: context.keyword !== context.requestedKeyword}\n }\n\n return {\n matches: output.matches,\n isLoading: context.keyword !== context.requestedKeyword,\n }\n }),\n 'reset': assign({\n patternText: '',\n keyword: '',\n matches: [],\n selectedIndex: 0,\n isLoading: false,\n requestedKeyword: '',\n focusSpan: undefined,\n error: undefined,\n }),\n 'navigate': assign(({context, event}) => {\n if (context.matches.length === 0) {\n return {selectedIndex: 0}\n }\n\n if (event.type === 'navigate to') {\n return {selectedIndex: event.index}\n }\n\n if (event.type === 'navigate up') {\n return {\n selectedIndex:\n (context.selectedIndex - 1 + context.matches.length) %\n context.matches.length,\n }\n }\n\n return {\n selectedIndex: (context.selectedIndex + 1) % context.matches.length,\n }\n }),\n 'select match': ({context}, params: {exact?: boolean}) => {\n if (!context.focusSpan) {\n return\n }\n\n const match = params.exact\n ? getFirstExactMatch(context.matches)\n : context.matches[context.selectedIndex]\n\n if (!match) {\n return\n }\n\n context.editor.send({\n type: 'custom.typeahead select match',\n match,\n focusSpan: context.focusSpan,\n keyword: context.keyword,\n pickerId: context.definition._id,\n })\n },\n 'update submit listener context': sendTo(\n 'submit listener',\n ({context}) => ({type: 'context changed', context}),\n ),\n 'update text insertion listener context': sendTo(\n 'text insertion listener',\n ({context}) => ({type: 'context changed', context}),\n ),\n 'handle error': assign({\n isLoading: false,\n error: ({event}) => (event as {error: Error}).error,\n }),\n },\n guards: {\n 'no focus span': ({context}) => !context.focusSpan,\n 'invalid pattern': ({context}) => {\n if (!context.patternText) {\n return true\n }\n\n // Check if trigger pattern matches entire text (just the trigger, no keyword yet)\n const triggerMatch = context.patternText.match(context.triggerPattern)\n\n if (\n triggerMatch &&\n triggerMatch.index === 0 &&\n triggerMatch[0] === context.patternText\n ) {\n return false\n }\n\n // Check partial pattern matches entire text\n const partialMatch = context.patternText.match(context.partialPattern)\n\n if (\n partialMatch &&\n partialMatch.index === 0 &&\n partialMatch[0] === context.patternText\n ) {\n return false\n }\n\n // Check complete pattern matches entire text (if configured)\n if (context.completePattern) {\n const completeMatch = context.patternText.match(\n context.completePattern,\n )\n\n if (\n completeMatch &&\n completeMatch.index === 0 &&\n completeMatch[0] === context.patternText\n ) {\n return false\n }\n }\n\n return true\n },\n 'no debounce': ({context}) =>\n !context.definition.debounceMs || context.definition.debounceMs === 0,\n 'is complete keyword': ({context}) => {\n if (!context.completePattern || !context.focusSpan) {\n return false\n }\n\n const fullKeywordText = context.focusSpan.node.text.slice(\n context.focusSpan.textBefore.length,\n context.focusSpan.textAfter.length > 0\n ? -context.focusSpan.textAfter.length\n : undefined,\n )\n const completeMatch = fullKeywordText.match(context.completePattern)\n\n if (\n !completeMatch ||\n completeMatch.index !== 0 ||\n completeMatch[0] !== fullKeywordText\n ) {\n return false\n }\n\n return hasAtLeastOneExactMatch(context.matches)\n },\n 'has matches': ({context}) => context.matches.length > 0,\n 'no matches': ({context}) => context.matches.length === 0,\n 'is loading': ({context}) => context.isLoading,\n },\n }).createMachine({\n id: 'typeahead picker',\n context: ({input}) => ({\n editor: input.editor,\n definition: input.definition,\n triggerPattern: buildTriggerPattern(input.definition),\n partialPattern: buildPartialPattern(input.definition),\n completePattern: buildCompletePattern(input.definition),\n matches: [],\n selectedIndex: 0,\n focusSpan: undefined,\n patternText: '',\n keyword: '',\n requestedKeyword: '',\n error: undefined,\n isLoading: false,\n }),\n initial: 'idle',\n states: {\n 'idle': {\n entry: ['reset'],\n invoke: {\n src: 'trigger listener',\n input: ({context}) => ({\n editor: context.editor,\n definition: context.definition,\n }),\n },\n on: {\n 'custom.typeahead trigger found': {\n target: 'active',\n actions: ['handle trigger found'],\n },\n 'custom.typeahead keyword found': {\n target: 'checking complete',\n actions: ['handle trigger found'],\n },\n },\n },\n 'checking complete': {\n invoke: [\n {\n src: 'select match listener',\n input: ({context}) => ({context}),\n },\n {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: [\n {\n guard: ({event}) =>\n hasAtLeastOneExactMatch(event.output.matches),\n target: 'idle',\n actions: [\n assign({matches: ({event}) => event.output.matches}),\n {type: 'select match', params: {exact: true}},\n ],\n },\n {\n target: 'active',\n actions: [assign({matches: ({event}) => event.output.matches})],\n },\n ],\n onError: {\n target: 'active.no matches',\n actions: ['handle error'],\n },\n },\n ],\n },\n 'active': {\n invoke: [\n {\n src: 'select match listener',\n input: ({context}) => ({context}),\n },\n {\n src: 'escape listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'selection listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'submit listener',\n id: 'submit listener',\n input: ({context}) => ({context}),\n },\n {\n src: 'text insertion listener',\n id: 'text insertion listener',\n input: ({context}) => ({context}),\n },\n ],\n on: {\n 'dismiss': {\n target: 'idle',\n },\n 'selection changed': {\n actions: [\n 'update focus span',\n 'update pattern text',\n 'update keyword',\n 'update matches',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n },\n always: [\n {\n guard: 'no focus span',\n target: 'idle',\n },\n {\n guard: 'invalid pattern',\n target: 'idle',\n },\n {\n guard: 'is complete keyword',\n actions: [{type: 'select match', params: {exact: false}}],\n target: 'idle',\n },\n ],\n initial: 'evaluating',\n states: {\n 'evaluating': {\n always: [\n {\n guard: 'is loading',\n target: 'loading',\n },\n {\n guard: 'has matches',\n target: 'showing matches',\n },\n {\n target: 'no matches',\n },\n ],\n },\n 'loading': {\n entry: [assign({requestedKeyword: ({context}) => context.keyword})],\n initial: 'debouncing',\n states: {\n debouncing: {\n always: [{guard: 'no debounce', target: 'fetching'}],\n after: {\n DEBOUNCE: 'fetching',\n },\n },\n fetching: {\n invoke: {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: {\n target: '#typeahead picker.active.evaluating',\n actions: [\n assign(({context, event}) => {\n if (event.output.keyword !== context.keyword) {\n return {\n isLoading:\n context.patternText !== context.requestedKeyword,\n }\n }\n\n return {\n matches: event.output.matches,\n isLoading:\n context.keyword !== context.requestedKeyword,\n }\n }),\n ],\n },\n onError: {\n target: '#typeahead picker.active.no matches',\n actions: ['handle error'],\n },\n },\n },\n },\n },\n 'no matches': {\n entry: [assign({selectedIndex: 0})],\n always: [\n {\n guard: 'has matches',\n target: 'showing matches',\n },\n ],\n initial: 'idle',\n states: {\n idle: {\n always: [{guard: 'is loading', target: 'loading'}],\n },\n loading: {\n entry: [\n assign({\n requestedKeyword: ({context}) => context.keyword,\n }),\n ],\n initial: 'debouncing',\n states: {\n debouncing: {\n always: [{guard: 'no debounce', target: 'fetching'}],\n after: {\n DEBOUNCE: 'fetching',\n },\n },\n fetching: {\n invoke: {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: {\n target: '#typeahead picker.active.no matches.idle',\n actions: ['handle async load complete'],\n },\n onError: {\n target: '#typeahead picker.active.no matches.idle',\n actions: ['handle error'],\n },\n },\n },\n },\n },\n },\n },\n 'showing matches': {\n entry: [\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n invoke: {\n src: 'arrow listener',\n input: ({context}) => ({editor: context.editor}),\n },\n always: [\n {\n guard: 'no matches',\n target: 'no matches',\n },\n ],\n on: {\n 'navigate down': {\n actions: [\n 'navigate',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n 'navigate up': {\n actions: [\n 'navigate',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n 'navigate to': {\n actions: [\n 'navigate',\n 'update submit listener context',\n 'update text insertion listener context',\n ],\n },\n 'select': {\n target: '#typeahead picker.idle',\n actions: [{type: 'select match', params: {exact: false}}],\n },\n },\n initial: 'idle',\n states: {\n idle: {\n always: [{guard: 'is loading', target: 'loading'}],\n },\n loading: {\n entry: [\n assign({\n requestedKeyword: ({context}) => context.keyword,\n }),\n ],\n initial: 'debouncing',\n states: {\n debouncing: {\n always: [{guard: 'no debounce', target: 'fetching'}],\n after: {\n DEBOUNCE: 'fetching',\n },\n },\n fetching: {\n invoke: {\n src: 'get matches',\n input: ({context}) => ({\n keyword: context.keyword,\n getMatches: context.definition.getMatches,\n }),\n onDone: {\n target: '#typeahead picker.active.showing matches.idle',\n actions: ['handle async load complete'],\n },\n onError: {\n target: '#typeahead picker.active.showing matches.idle',\n actions: ['handle error'],\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n })\n}\n\n/**\n * Check if matches contain at least one exact match.\n */\nfunction hasAtLeastOneExactMatch<TMatch extends object>(\n matches: ReadonlyArray<TMatch>,\n): boolean {\n return matches.some(\n (match) =>\n (match as unknown as AutoCompleteMatch | undefined)?.type === 'exact',\n )\n}\n\n/**\n * Get the first exact match from matches.\n */\nfunction getFirstExactMatch<TMatch extends object>(\n matches: ReadonlyArray<TMatch>,\n): TMatch | undefined {\n return matches.find(\n (match) =>\n (match as unknown as AutoCompleteMatch | undefined)?.type === 'exact',\n )\n}\n","import {useEditor} from '@portabletext/editor'\nimport {useActor} from '@xstate/react'\nimport {createTypeaheadPickerMachine} from './typeahead-picker-machine'\nimport type {\n TypeaheadPicker,\n TypeaheadPickerDefinition,\n TypeaheadPickerEvent,\n TypeaheadPickerState,\n} from './typeahead-picker.types'\n\n/**\n * React hook that activates a typeahead picker and returns its current state.\n *\n * Call inside a component rendered within an `EditorProvider`.\n * The picker automatically monitors the editor for trigger patterns.\n *\n * @example\n * ```tsx\n * function MentionPickerUI() {\n * const picker = useTypeaheadPicker(mentionPickerDefinition)\n *\n * if (picker.snapshot.matches('idle')) return null\n * if (picker.snapshot.matches({active: 'loading'})) return <Spinner />\n * if (picker.snapshot.matches({active: 'no matches'})) return <NoResults />\n *\n * const {matches, selectedIndex} = picker.snapshot.context\n *\n * return (\n * <ul>\n * {matches.map((match, index) => (\n * <li\n * key={match.key}\n * aria-selected={index === selectedIndex}\n * onMouseEnter={() => picker.send({type: 'navigate to', index})}\n * onClick={() => picker.send({type: 'select'})}\n * >\n * {match.name}\n * </li>\n * ))}\n * </ul>\n * )\n * }\n * ```\n *\n * @public\n */\nexport function useTypeaheadPicker<TMatch extends object>(\n definition: TypeaheadPickerDefinition<TMatch>,\n): TypeaheadPicker<TMatch> {\n const editor = useEditor()\n const [actorSnapshot, send] = useActor(\n createTypeaheadPickerMachine<TMatch>(),\n {\n input: {\n editor,\n definition,\n },\n },\n )\n\n return {\n snapshot: {\n matches: (state: TypeaheadPickerState) => actorSnapshot.matches(state),\n context: {\n keyword: actorSnapshot.context.keyword,\n matches: actorSnapshot.context.matches as ReadonlyArray<TMatch>,\n selectedIndex: actorSnapshot.context.selectedIndex,\n error: actorSnapshot.context.error,\n },\n },\n send: (event: TypeaheadPickerEvent) => {\n send(event)\n },\n }\n}\n"],"names":["defineTypeaheadPicker","config","_id","extractKeyword","patternText","triggerPattern","delimiter","completePattern","triggerMatch","match","index","keyword","slice","length","endsWith","completeMatch","escapeRegExp","str","replace","buildTriggerPattern","definition","RegExp","trigger","source","buildPartialPattern","buildCompletePattern","escapedDelimiter","arrowUpShortcut","createKeyboardShortcut","default","key","arrowDownShortcut","enterShortcut","tabShortcut","escapeShortcut","getTriggerState","snapshot","focusSpan","getFocusSpan","markState","getMarkState","context","selection","focusSpanTextBefore","node","text","focus","offset","focusSpanTextAfter","previousSpan","getPreviousSpan","nextSpan","getNextSpan","createTriggerActions","payload","keywordState","pickerId","state","textBeforeMatch","lastMatch","targetOffsets","anchor","_key","_type","marks","path","textBefore","textAfter","raise","createKeywordFoundEvent","extractedKeyword","createTriggerFoundEvent","newSpan","keyGenerator","JSON","stringify","type","at","child","extractPatternTextFromFocusSpan","createInputRules","rules","partialPattern","completeRule","defineInputRule","on","guard","event","matches","undefined","insertedMatch","textInserted","triggerState","actions","push","partialRule","triggerRule","createTriggerGuard","dom","triggerListenerCallback","sendBack","input","triggerGuard","unregisterBehaviors","editor","registerBehavior","behavior","defineInputRuleBehavior","defineBehavior","effect","unregister","escapeListenerCallback","originEvent","arrowListenerCallback","selectionListenerCallback","unsubscribe","submitListenerCallback","receive","selectedIndex","forward","textInsertionListenerCallback","keywordAnchor","isEqualSelectionPoints","selectMatchListenerCallback","patternSelection","allActions","actionSet","action","createTypeaheadPickerMachine","setup","types","events","delays","DEBOUNCE","debounceMs","actors","fromCallback","fromPromise","result","getMatches","Promise","resolve","assign","mode","isLoading","requestedKeyword","getSnapshot","isEqualPaths","isSelectionCollapsed","startsWith","keywordFocus","selectionIsBeforeKeyword","isPointAfterSelection","selectionIsAfterKeyword","isPointBeforeSelection","output","error","select match","params","exact","getFirstExactMatch","send","sendTo","guards","no focus span","invalid pattern","partialMatch","no debounce","is complete keyword","fullKeywordText","hasAtLeastOneExactMatch","has matches","no matches","is loading","createMachine","id","initial","states","entry","invoke","src","target","onDone","onError","always","debouncing","after","fetching","idle","loading","some","find","useTypeaheadPicker","$","_c","useEditor","t0","Symbol","for","t1","actorSnapshot","useActor","t2","t3","t4","t5","t6","t7"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/plugin-typeahead-picker",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Generic typeahead picker infrastructure for the Portable Text Editor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"portabletext",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@xstate/react": "^6.0.0",
|
|
36
36
|
"xstate": "^5.25.0",
|
|
37
37
|
"@portabletext/keyboard-shortcuts": "^2.1.2",
|
|
38
|
-
"@portabletext/plugin-input-rule": "^2.0.
|
|
38
|
+
"@portabletext/plugin-input-rule": "^2.0.21"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@sanity/pkg-utils": "^10.2.1",
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"typescript": "5.9.3",
|
|
53
53
|
"typescript-eslint": "^8.48.0",
|
|
54
54
|
"vitest": "^4.0.16",
|
|
55
|
-
"@portabletext/editor": "^4.3.
|
|
55
|
+
"@portabletext/editor": "^4.3.6",
|
|
56
56
|
"@portabletext/schema": "2.1.1",
|
|
57
57
|
"racejar": "2.0.2"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@portabletext/editor": "^4.3.
|
|
60
|
+
"@portabletext/editor": "^4.3.6",
|
|
61
61
|
"react": "^19.2"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|