@tiptap/suggestion 3.26.1 → 3.27.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/dist/index.cjs +619 -270
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +193 -2
- package/dist/index.d.ts +193 -2
- package/dist/index.js +624 -270
- package/dist/index.js.map +1 -1
- package/package.json +10 -5
- package/src/__tests__/suggestion.test.ts +837 -0
- package/src/helpers.ts +129 -0
- package/src/plugin/async.ts +89 -0
- package/src/plugin/floating-ui.ts +204 -0
- package/src/plugin/props.ts +94 -0
- package/src/plugin/state.ts +182 -0
- package/src/plugin/view.ts +236 -0
- package/src/suggestion.ts +97 -606
- package/src/types.ts +439 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Middleware, AutoUpdateOptions } from '@floating-ui/dom';
|
|
1
2
|
import { Range, Editor } from '@tiptap/core';
|
|
2
3
|
import { PluginKey, Transaction, EditorState, Plugin } from '@tiptap/pm/state';
|
|
3
4
|
import { EditorView } from '@tiptap/pm/view';
|
|
@@ -18,6 +19,56 @@ type SuggestionMatch = {
|
|
|
18
19
|
} | null;
|
|
19
20
|
declare function findSuggestionMatch(config: Trigger): SuggestionMatch;
|
|
20
21
|
|
|
22
|
+
type SuggestionPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end';
|
|
23
|
+
type SuggestionFloatingUiOptions = {
|
|
24
|
+
strategy?: 'absolute' | 'fixed';
|
|
25
|
+
middleware?: Middleware[];
|
|
26
|
+
};
|
|
27
|
+
type SuggestionFloatingUiConfig = {
|
|
28
|
+
placement: SuggestionPlacement;
|
|
29
|
+
strategy: 'absolute' | 'fixed';
|
|
30
|
+
middleware: Middleware[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The computed position handed to a custom `onPosition` callback when using
|
|
34
|
+
* managed positioning via {@link SuggestionProps.mount}.
|
|
35
|
+
*/
|
|
36
|
+
type SuggestionPositionData = {
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
placement: SuggestionPlacement;
|
|
40
|
+
strategy: 'absolute' | 'fixed';
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Options for managed mounting + positioning via {@link SuggestionProps.mount}.
|
|
44
|
+
*/
|
|
45
|
+
type SuggestionMountOptions = {
|
|
46
|
+
/**
|
|
47
|
+
* Override how the computed position is applied to the element.
|
|
48
|
+
* When provided, the plugin stops writing `style.left`/`style.top` itself and
|
|
49
|
+
* hands you the computed coordinates so you can apply them however you want
|
|
50
|
+
* (custom transforms, animation, writing to a framework ref, etc.).
|
|
51
|
+
*/
|
|
52
|
+
onPosition?: (data: SuggestionPositionData) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Options forwarded to Floating UI's `autoUpdate`. Use this to opt into
|
|
55
|
+
* `animationFrame` polling for anchors that move inside transformed or
|
|
56
|
+
* animated containers, or to disable specific observers.
|
|
57
|
+
* @see https://floating-ui.com/docs/autoUpdate
|
|
58
|
+
*/
|
|
59
|
+
autoUpdate?: AutoUpdateOptions;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Mounts a floating element and takes over its positioning. The plugin appends
|
|
63
|
+
* the element into the configured `container` (default `document.body`), keeps
|
|
64
|
+
* it anchored to the suggestion's cursor rect, and automatically repositions it
|
|
65
|
+
* on scroll, resize, and layout shifts via Floating UI's `autoUpdate` — no
|
|
66
|
+
* manual listeners required.
|
|
67
|
+
*
|
|
68
|
+
* Returns an `unmount` function that tears down the listeners and removes the
|
|
69
|
+
* element (when the plugin mounted it). Call it from `onExit`.
|
|
70
|
+
*/
|
|
71
|
+
type SuggestionMount = (element: HTMLElement, options?: SuggestionMountOptions) => () => void;
|
|
21
72
|
interface SuggestionOptions<I = any, TSelected = any> {
|
|
22
73
|
/**
|
|
23
74
|
* The plugin key for the suggestion plugin.
|
|
@@ -128,6 +179,67 @@ interface SuggestionOptions<I = any, TSelected = any> {
|
|
|
128
179
|
range: Range;
|
|
129
180
|
props: TSelected;
|
|
130
181
|
}) => void;
|
|
182
|
+
/**
|
|
183
|
+
* Minimum query length before `items()` is called.
|
|
184
|
+
* When the query is shorter, empty items are passed to the renderer.
|
|
185
|
+
* @default 0 (no filter, same as before)
|
|
186
|
+
* @example 2
|
|
187
|
+
*/
|
|
188
|
+
minQueryLength?: number;
|
|
189
|
+
/**
|
|
190
|
+
* Debounce in milliseconds. When set, `items()` will only be called
|
|
191
|
+
* after the user stops typing for this duration.
|
|
192
|
+
* @default 0 (no debounce, same as before)
|
|
193
|
+
* @example 300
|
|
194
|
+
*/
|
|
195
|
+
debounce?: number;
|
|
196
|
+
/**
|
|
197
|
+
* Items shown immediately when the suggestion popup opens,
|
|
198
|
+
* before the async `items()` call resolves.
|
|
199
|
+
* Useful for showing recent or popular items while loading.
|
|
200
|
+
* @default undefined (no pre-populated items)
|
|
201
|
+
*/
|
|
202
|
+
initialItems?: I[];
|
|
203
|
+
/**
|
|
204
|
+
* Placement of the popup relative to the cursor.
|
|
205
|
+
* Consumers can read this from `SuggestionProps` to configure their positioning library.
|
|
206
|
+
* @default 'bottom-start'
|
|
207
|
+
*/
|
|
208
|
+
placement?: SuggestionPlacement;
|
|
209
|
+
/**
|
|
210
|
+
* Offset of the popup in pixels.
|
|
211
|
+
* Consumers can read this from `SuggestionProps` to configure their positioning library.
|
|
212
|
+
* @default { mainAxis: 4, crossAxis: 0 }
|
|
213
|
+
*/
|
|
214
|
+
offset?: {
|
|
215
|
+
mainAxis?: number;
|
|
216
|
+
crossAxis?: number;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* CSS selector or element that defines the containment context for the popup.
|
|
220
|
+
* Consumers can read this from `SuggestionProps` when rendering inside modals or dialogs.
|
|
221
|
+
* @default undefined (no containment)
|
|
222
|
+
*/
|
|
223
|
+
container?: string | HTMLElement;
|
|
224
|
+
/**
|
|
225
|
+
* Whether the popup should automatically flip when there isn't enough space.
|
|
226
|
+
* Consumers can read this from `SuggestionProps` to configure their positioning library.
|
|
227
|
+
* @default true
|
|
228
|
+
*/
|
|
229
|
+
flip?: boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Additional Floating UI options and middleware passed through to the renderer.
|
|
232
|
+
* The plugin keeps ownership of the anchor and placement, but consumers can
|
|
233
|
+
* append custom middleware here.
|
|
234
|
+
*/
|
|
235
|
+
floatingUi?: SuggestionFloatingUiOptions;
|
|
236
|
+
/**
|
|
237
|
+
* Dismiss the suggestion when the user interacts outside both the popup and
|
|
238
|
+
* the editor. Only applies when using managed mounting via
|
|
239
|
+
* {@link SuggestionProps.mount} (the plugin needs to know the popup element).
|
|
240
|
+
* @default true
|
|
241
|
+
*/
|
|
242
|
+
dismissOnOutsideClick?: boolean;
|
|
131
243
|
/**
|
|
132
244
|
* A function that returns the suggestion items in form of an array.
|
|
133
245
|
* @param props The props object.
|
|
@@ -139,6 +251,7 @@ interface SuggestionOptions<I = any, TSelected = any> {
|
|
|
139
251
|
items?: (props: {
|
|
140
252
|
query: string;
|
|
141
253
|
editor: Editor;
|
|
254
|
+
signal: AbortSignal;
|
|
142
255
|
}) => I[] | Promise<I[]>;
|
|
143
256
|
/**
|
|
144
257
|
* The render function for the suggestion.
|
|
@@ -165,6 +278,9 @@ interface SuggestionOptions<I = any, TSelected = any> {
|
|
|
165
278
|
}) => boolean;
|
|
166
279
|
findSuggestionMatch?: typeof findSuggestionMatch;
|
|
167
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* The props passed to the suggestion's render functions (onStart, onUpdate, onExit).
|
|
283
|
+
*/
|
|
168
284
|
interface SuggestionProps<I = any, TSelected = any> {
|
|
169
285
|
/**
|
|
170
286
|
* The editor instance.
|
|
@@ -203,18 +319,93 @@ interface SuggestionProps<I = any, TSelected = any> {
|
|
|
203
319
|
* @example () => new DOMRect(0, 0, 0, 0)
|
|
204
320
|
*/
|
|
205
321
|
clientRect?: (() => DOMRect | null) | null;
|
|
322
|
+
/**
|
|
323
|
+
* Placement of the popup relative to the cursor.
|
|
324
|
+
* @default 'bottom-start'
|
|
325
|
+
*/
|
|
326
|
+
placement: SuggestionPlacement;
|
|
327
|
+
/**
|
|
328
|
+
* Offset of the popup in pixels.
|
|
329
|
+
* @default { mainAxis: 4, crossAxis: 0 }
|
|
330
|
+
*/
|
|
331
|
+
offset: {
|
|
332
|
+
mainAxis: number;
|
|
333
|
+
crossAxis: number;
|
|
334
|
+
};
|
|
335
|
+
/**
|
|
336
|
+
* CSS selector or element that defines the containment context for the popup.
|
|
337
|
+
* @default undefined
|
|
338
|
+
*/
|
|
339
|
+
container?: string | HTMLElement;
|
|
340
|
+
/**
|
|
341
|
+
* Whether the popup should automatically flip when there isn't enough space.
|
|
342
|
+
* @default true
|
|
343
|
+
*/
|
|
344
|
+
flip: boolean;
|
|
345
|
+
/**
|
|
346
|
+
* Resolved Floating UI config for direct use with `computePosition()`.
|
|
347
|
+
* This is the escape hatch: reach for it only when you mount the element
|
|
348
|
+
* yourself and want to run the positioning loop manually instead of using
|
|
349
|
+
* {@link SuggestionProps.mount}.
|
|
350
|
+
*/
|
|
351
|
+
floatingUi: SuggestionFloatingUiConfig;
|
|
352
|
+
/**
|
|
353
|
+
* Mounts your floating element and takes over positioning — the recommended,
|
|
354
|
+
* default way to render a suggestion popup.
|
|
355
|
+
*
|
|
356
|
+
* Pass the element you rendered (e.g. from `ReactRenderer`/`VueRenderer`). The
|
|
357
|
+
* plugin appends it into the configured `container` (default `document.body`),
|
|
358
|
+
* keeps it anchored to the cursor, and repositions it on scroll, resize, and
|
|
359
|
+
* layout shifts — no manual listeners required. Returns an `unmount` function
|
|
360
|
+
* that tears everything down; call it in `onExit`.
|
|
361
|
+
*
|
|
362
|
+
* Escape hatch: mount the element yourself and skip this, then run your own
|
|
363
|
+
* positioning loop with {@link SuggestionProps.floatingUi} +
|
|
364
|
+
* {@link SuggestionProps.clientRect}.
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```ts
|
|
368
|
+
* onStart: props => {
|
|
369
|
+
* component = new ReactRenderer(DropdownList, { props, editor: props.editor })
|
|
370
|
+
* unmount = props.mount(component.element)
|
|
371
|
+
* },
|
|
372
|
+
* onExit: () => unmount?.(),
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
mount: SuggestionMount;
|
|
376
|
+
/**
|
|
377
|
+
* Whether the items are currently being loaded.
|
|
378
|
+
* `true` before the async `items()` call resolves.
|
|
379
|
+
* Useful for showing a loading spinner or skeleton.
|
|
380
|
+
* @default false
|
|
381
|
+
*/
|
|
382
|
+
loading: boolean;
|
|
206
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* The props passed to the suggestion's onKeyDown render function
|
|
386
|
+
*/
|
|
207
387
|
interface SuggestionKeyDownProps {
|
|
208
388
|
view: EditorView;
|
|
209
389
|
event: KeyboardEvent;
|
|
210
390
|
range: Range;
|
|
211
391
|
}
|
|
392
|
+
/** @internal Internal state shape for the suggestion plugin. */
|
|
393
|
+
interface SuggestionPluginState {
|
|
394
|
+
active: boolean;
|
|
395
|
+
range: Range;
|
|
396
|
+
query: null | string;
|
|
397
|
+
text: null | string;
|
|
398
|
+
composing: boolean;
|
|
399
|
+
decorationId?: string | null;
|
|
400
|
+
dismissedRange: Range | null;
|
|
401
|
+
}
|
|
402
|
+
|
|
212
403
|
declare const SuggestionPluginKey: PluginKey<any>;
|
|
213
404
|
/**
|
|
214
405
|
* This utility allows you to create suggestions.
|
|
215
406
|
* @see https://tiptap.dev/api/utilities/suggestion
|
|
216
407
|
*/
|
|
217
|
-
declare function Suggestion<I = any, TSelected = any>({ pluginKey, editor, char, allowSpaces, allowToIncludeChar, allowedPrefixes, startOfLine, decorationTag, decorationClass, decorationContent, decorationEmptyClass, command, items, render, allow, findSuggestionMatch, shouldShow, shouldResetDismissed, }: SuggestionOptions<I, TSelected>): Plugin<
|
|
408
|
+
declare function Suggestion<I = any, TSelected = any>({ pluginKey, editor, char, allowSpaces, allowToIncludeChar, allowedPrefixes, startOfLine, decorationTag, decorationClass, decorationContent, decorationEmptyClass, command, items, minQueryLength, debounce, initialItems, placement, offset: offsetOption, container, flip, floatingUi, dismissOnOutsideClick, render, allow, findSuggestionMatch, shouldShow, shouldResetDismissed, }: SuggestionOptions<I, TSelected>): Plugin<SuggestionPluginState>;
|
|
218
409
|
/**
|
|
219
410
|
* Programmatically exit a suggestion plugin by dispatching a metadata-only
|
|
220
411
|
* transaction. This is the safe, recommended API to remove suggestion
|
|
@@ -222,4 +413,4 @@ declare function Suggestion<I = any, TSelected = any>({ pluginKey, editor, char,
|
|
|
222
413
|
*/
|
|
223
414
|
declare function exitSuggestion(view: EditorView, pluginKeyRef?: PluginKey): void;
|
|
224
415
|
|
|
225
|
-
export { Suggestion, type SuggestionKeyDownProps, type SuggestionMatch, type SuggestionOptions, SuggestionPluginKey, type SuggestionProps, type Trigger, Suggestion as default, exitSuggestion, findSuggestionMatch };
|
|
416
|
+
export { Suggestion, type SuggestionFloatingUiConfig, type SuggestionFloatingUiOptions, type SuggestionKeyDownProps, type SuggestionMatch, type SuggestionMount, type SuggestionMountOptions, type SuggestionOptions, type SuggestionPlacement, SuggestionPluginKey, type SuggestionPositionData, type SuggestionProps, type Trigger, Suggestion as default, exitSuggestion, findSuggestionMatch };
|