@liveblocks/react-tiptap 2.16.0 → 2.16.1-ai

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.
Files changed (46) hide show
  1. package/dist/LiveblocksExtension.js +141 -21
  2. package/dist/LiveblocksExtension.js.map +1 -1
  3. package/dist/LiveblocksExtension.mjs +141 -21
  4. package/dist/LiveblocksExtension.mjs.map +1 -1
  5. package/dist/ai/AiExtension.js +288 -0
  6. package/dist/ai/AiExtension.js.map +1 -0
  7. package/dist/ai/AiExtension.mjs +285 -0
  8. package/dist/ai/AiExtension.mjs.map +1 -0
  9. package/dist/ai/AiToolbar.js +540 -0
  10. package/dist/ai/AiToolbar.js.map +1 -0
  11. package/dist/ai/AiToolbar.mjs +537 -0
  12. package/dist/ai/AiToolbar.mjs.map +1 -0
  13. package/dist/comments/CommentsExtension.js.map +1 -1
  14. package/dist/comments/CommentsExtension.mjs.map +1 -1
  15. package/dist/index.d.mts +54 -14
  16. package/dist/index.d.ts +54 -14
  17. package/dist/index.js +2 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +1 -0
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/toolbar/FloatingToolbar.js +7 -0
  22. package/dist/toolbar/FloatingToolbar.js.map +1 -1
  23. package/dist/toolbar/FloatingToolbar.mjs +7 -0
  24. package/dist/toolbar/FloatingToolbar.mjs.map +1 -1
  25. package/dist/toolbar/Toolbar.js +36 -2
  26. package/dist/toolbar/Toolbar.js.map +1 -1
  27. package/dist/toolbar/Toolbar.mjs +37 -3
  28. package/dist/toolbar/Toolbar.mjs.map +1 -1
  29. package/dist/toolbar/shared.js +4 -1
  30. package/dist/toolbar/shared.js.map +1 -1
  31. package/dist/toolbar/shared.mjs +5 -2
  32. package/dist/toolbar/shared.mjs.map +1 -1
  33. package/dist/types.js.map +1 -1
  34. package/dist/types.mjs.map +1 -1
  35. package/dist/utils.js +29 -1
  36. package/dist/utils.js.map +1 -1
  37. package/dist/utils.mjs +27 -2
  38. package/dist/utils.mjs.map +1 -1
  39. package/dist/version.js +1 -1
  40. package/dist/version.js.map +1 -1
  41. package/dist/version.mjs +1 -1
  42. package/dist/version.mjs.map +1 -1
  43. package/package.json +7 -6
  44. package/src/styles/index.css +319 -3
  45. package/styles.css +1 -1
  46. package/styles.css.map +1 -1
@@ -0,0 +1,537 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { hide, offset, autoUpdate, useFloating } from '@floating-ui/react-dom';
3
+ import { useLayoutEffect } from '@liveblocks/react/_private';
4
+ import { CheckIcon, UndoIcon, CrossIcon, SparklesIcon, ShortcutTooltip, Button, SendIcon, EditIcon, ShortenIcon, LengthenIcon, QuestionMarkIcon, useRefs, TooltipProvider } from '@liveblocks/react-ui/_private';
5
+ import { useEditorState } from '@tiptap/react';
6
+ import { Command, useCommandState } from 'cmdk';
7
+ import { createContext, useContext, forwardRef, useCallback, useRef, useMemo, useEffect } from 'react';
8
+ import { createPortal } from 'react-dom';
9
+ import { classNames } from '../classnames.mjs';
10
+ import { useCurrentEditor, EditorProvider } from '../context.mjs';
11
+ import { getDomRangeFromSelection } from '../utils.mjs';
12
+ import { DEFAULT_STATE } from './AiExtension.mjs';
13
+
14
+ const AI_TOOLBAR_COLLISION_PADDING = 10;
15
+ const AiToolbarContext = createContext(null);
16
+ function useAiToolbarContext() {
17
+ const context = useContext(AiToolbarContext);
18
+ if (!context) {
19
+ throw new Error("useAiToolbarContext must be used within an AiToolbar");
20
+ }
21
+ return context;
22
+ }
23
+ function tiptapFloating(editor) {
24
+ return {
25
+ name: "tiptap",
26
+ options: editor,
27
+ fn({ elements }) {
28
+ if (!editor) {
29
+ return {};
30
+ }
31
+ const editorRect = editor.view.dom.getBoundingClientRect();
32
+ elements.floating.style.setProperty(
33
+ "--lb-tiptap-editor-width",
34
+ `${editorRect.width}px`
35
+ );
36
+ elements.floating.style.setProperty(
37
+ "--lb-tiptap-editor-height",
38
+ `${editorRect.height}px`
39
+ );
40
+ return {
41
+ x: editorRect.x
42
+ };
43
+ }
44
+ };
45
+ }
46
+ const AiToolbarDropdownGroup = forwardRef(({ children, label, ...props }, forwardedRef) => {
47
+ return /* @__PURE__ */ jsx(Command.Group, {
48
+ heading: /* @__PURE__ */ jsx("span", {
49
+ className: "lb-dropdown-label",
50
+ children: label
51
+ }),
52
+ ...props,
53
+ ref: forwardedRef,
54
+ children
55
+ });
56
+ });
57
+ const AiToolbarSuggestionsGroup = forwardRef((props, forwardedRef) => {
58
+ return /* @__PURE__ */ jsx(AiToolbarDropdownGroup, {
59
+ ref: forwardedRef,
60
+ ...props
61
+ });
62
+ });
63
+ const AiToolbarDropdownItem = forwardRef(({ children, onSelect, icon, ...props }, forwardedRef) => {
64
+ return /* @__PURE__ */ jsxs(Command.Item, {
65
+ className: "lb-dropdown-item",
66
+ onSelect,
67
+ ...props,
68
+ ref: forwardedRef,
69
+ children: [
70
+ icon ? /* @__PURE__ */ jsx("span", {
71
+ className: "lb-icon-container",
72
+ children: icon
73
+ }) : null,
74
+ children ? /* @__PURE__ */ jsx("span", {
75
+ className: "lb-dropdown-item-label",
76
+ children
77
+ }) : null
78
+ ]
79
+ });
80
+ });
81
+ const AiToolbarSuggestion = forwardRef(({ prompt: manualPrompt, ...props }, forwardedRef) => {
82
+ const editor = useCurrentEditor("Suggestion", "AiToolbar");
83
+ const handleSelect = useCallback(
84
+ (prompt) => {
85
+ editor.commands.$startAiToolbarThinking(
86
+ manualPrompt ?? prompt
87
+ );
88
+ },
89
+ [editor, manualPrompt]
90
+ );
91
+ return /* @__PURE__ */ jsx(AiToolbarDropdownItem, {
92
+ ...props,
93
+ onSelect: handleSelect,
94
+ ref: forwardedRef
95
+ });
96
+ });
97
+ function AiToolbarReviewingSuggestions() {
98
+ const editor = useCurrentEditor("ReviewingSuggestions", "AiToolbar");
99
+ const { state } = useAiToolbarContext();
100
+ const { prompt } = state;
101
+ const handleRetry = useCallback(() => {
102
+ editor.commands.$startAiToolbarThinking(prompt);
103
+ }, [editor, prompt]);
104
+ const handleDiscard = useCallback(() => {
105
+ editor.commands.$closeAiToolbar();
106
+ }, [editor]);
107
+ const handleAccept = useCallback(() => {
108
+ editor.commands.$acceptAiToolbarOutput();
109
+ }, [editor]);
110
+ return /* @__PURE__ */ jsxs(Fragment, {
111
+ children: [
112
+ /* @__PURE__ */ jsx(AiToolbarDropdownItem, {
113
+ icon: /* @__PURE__ */ jsx(CheckIcon, {}),
114
+ onSelect: handleAccept,
115
+ children: "Replace selection"
116
+ }),
117
+ /* @__PURE__ */ jsx(AiToolbarDropdownItem, {
118
+ icon: /* @__PURE__ */ jsx(CheckIcon, {}),
119
+ children: "Insert below"
120
+ }),
121
+ /* @__PURE__ */ jsx(AiToolbarDropdownItem, {
122
+ icon: /* @__PURE__ */ jsx(UndoIcon, {}),
123
+ onSelect: handleRetry,
124
+ children: "Try again"
125
+ }),
126
+ /* @__PURE__ */ jsx(AiToolbarDropdownItem, {
127
+ icon: /* @__PURE__ */ jsx(CrossIcon, {}),
128
+ onSelect: handleDiscard,
129
+ children: "Discard"
130
+ })
131
+ ]
132
+ });
133
+ }
134
+ function AiToolbarCustomPromptContent() {
135
+ const editor = useCurrentEditor("CustomPromptContent", "AiToolbar");
136
+ const aiName = editor.storage.liveblocksAi.name;
137
+ const textAreaRef = useRef(null);
138
+ const { state, dropdownRef, isDropdownHidden } = useAiToolbarContext();
139
+ const { customPrompt } = state;
140
+ const isCustomPromptEmpty = useMemo(
141
+ () => customPrompt.trim() === "",
142
+ [customPrompt]
143
+ );
144
+ useLayoutEffect(
145
+ () => {
146
+ setTimeout(() => {
147
+ const textArea = textAreaRef.current;
148
+ if (!textArea) {
149
+ return;
150
+ }
151
+ textArea.focus();
152
+ textArea.setSelectionRange(
153
+ textArea.value.length,
154
+ textArea.value.length
155
+ );
156
+ }, 0);
157
+ },
158
+ []
159
+ );
160
+ const handlePromptKeyDown = (event) => {
161
+ if (event.key === "Enter") {
162
+ event.preventDefault();
163
+ event.stopPropagation();
164
+ if (event.shiftKey) {
165
+ editor.commands._updateAiToolbarCustomPrompt(
166
+ (customPrompt2) => customPrompt2 + "\n"
167
+ );
168
+ } else {
169
+ const selectedDropdownItem = dropdownRef.current?.querySelector(
170
+ "[role='option'][data-selected='true']"
171
+ );
172
+ if (!isDropdownHidden && selectedDropdownItem) {
173
+ selectedDropdownItem.click();
174
+ } else if (!isCustomPromptEmpty) {
175
+ editor.commands.$startAiToolbarThinking(
176
+ customPrompt
177
+ );
178
+ }
179
+ }
180
+ }
181
+ };
182
+ const handleCustomPromptChange = useCallback(
183
+ (customPrompt2) => {
184
+ editor.commands._updateAiToolbarCustomPrompt(
185
+ customPrompt2
186
+ );
187
+ },
188
+ [editor]
189
+ );
190
+ const handleSendClick = useCallback(() => {
191
+ if (isCustomPromptEmpty) {
192
+ return;
193
+ }
194
+ editor.commands.$startAiToolbarThinking(
195
+ customPrompt
196
+ );
197
+ }, [editor, customPrompt, isCustomPromptEmpty]);
198
+ return /* @__PURE__ */ jsxs("div", {
199
+ className: "lb-tiptap-ai-toolbar-content",
200
+ children: [
201
+ /* @__PURE__ */ jsx("span", {
202
+ className: "lb-icon-container lb-tiptap-ai-toolbar-icon-container",
203
+ children: /* @__PURE__ */ jsx(SparklesIcon, {})
204
+ }),
205
+ /* @__PURE__ */ jsx("div", {
206
+ className: "lb-tiptap-ai-toolbar-custom-prompt-container",
207
+ "data-value": customPrompt,
208
+ children: /* @__PURE__ */ jsx(Command.Input, {
209
+ value: customPrompt,
210
+ onValueChange: handleCustomPromptChange,
211
+ asChild: true,
212
+ children: /* @__PURE__ */ jsx("textarea", {
213
+ ref: textAreaRef,
214
+ className: "lb-tiptap-ai-toolbar-custom-prompt",
215
+ placeholder: `Ask ${aiName} anything\u2026`,
216
+ onKeyDown: handlePromptKeyDown,
217
+ rows: 1,
218
+ autoFocus: true
219
+ })
220
+ })
221
+ }),
222
+ /* @__PURE__ */ jsx("div", {
223
+ className: "lb-tiptap-ai-toolbar-actions",
224
+ children: /* @__PURE__ */ jsx(ShortcutTooltip, {
225
+ content: `Ask ${aiName}`,
226
+ shortcut: "Enter",
227
+ children: /* @__PURE__ */ jsx(Button, {
228
+ className: "lb-tiptap-ai-toolbar-action",
229
+ variant: "primary",
230
+ "aria-label": `Ask ${aiName}`,
231
+ icon: /* @__PURE__ */ jsx(SendIcon, {}),
232
+ disabled: isCustomPromptEmpty,
233
+ onClick: handleSendClick
234
+ })
235
+ })
236
+ })
237
+ ]
238
+ });
239
+ }
240
+ function AiToolbarAsking() {
241
+ return /* @__PURE__ */ jsx(AiToolbarCustomPromptContent, {});
242
+ }
243
+ function AiToolbarThinking() {
244
+ const editor = useCurrentEditor("AiToolbarThinking", "AiToolbar");
245
+ const contentRef = useRef(null);
246
+ const aiName = editor.storage.liveblocksAi.name;
247
+ const handleCancel = useCallback(() => {
248
+ editor.commands.$cancelAiToolbarThinking();
249
+ }, [editor]);
250
+ useLayoutEffect(() => {
251
+ contentRef.current?.focus();
252
+ window.getSelection()?.removeAllRanges();
253
+ }, []);
254
+ return /* @__PURE__ */ jsx(Fragment, {
255
+ children: /* @__PURE__ */ jsxs("div", {
256
+ className: "lb-tiptap-ai-toolbar-content",
257
+ tabIndex: 0,
258
+ ref: contentRef,
259
+ children: [
260
+ /* @__PURE__ */ jsx("span", {
261
+ className: "lb-icon-container lb-tiptap-ai-toolbar-icon-container",
262
+ children: /* @__PURE__ */ jsx(SparklesIcon, {})
263
+ }),
264
+ /* @__PURE__ */ jsxs("div", {
265
+ className: "lb-tiptap-ai-toolbar-thinking",
266
+ children: [
267
+ aiName,
268
+ " is thinking\u2026"
269
+ ]
270
+ }),
271
+ /* @__PURE__ */ jsx("div", {
272
+ className: "lb-tiptap-ai-toolbar-actions",
273
+ children: /* @__PURE__ */ jsx(ShortcutTooltip, {
274
+ content: "Cancel",
275
+ shortcut: "Escape",
276
+ children: /* @__PURE__ */ jsx(Button, {
277
+ className: "lb-tiptap-ai-toolbar-action",
278
+ variant: "secondary",
279
+ "aria-label": "Cancel",
280
+ icon: /* @__PURE__ */ jsx(UndoIcon, {}),
281
+ onClick: handleCancel
282
+ })
283
+ })
284
+ })
285
+ ]
286
+ })
287
+ });
288
+ }
289
+ function AiToolbarReviewing() {
290
+ return /* @__PURE__ */ jsx(Fragment, {
291
+ children: /* @__PURE__ */ jsx(AiToolbarCustomPromptContent, {})
292
+ });
293
+ }
294
+ function AiToolbarContainer({
295
+ state,
296
+ toolbarRef,
297
+ dropdownRef,
298
+ children
299
+ }) {
300
+ const editor = useCurrentEditor("AiToolbarContainer", "AiToolbar");
301
+ const phase = state.phase;
302
+ const customPrompt = state.customPrompt;
303
+ const isCustomPromptMultiline = useMemo(
304
+ () => customPrompt?.includes("\n"),
305
+ [customPrompt]
306
+ );
307
+ const hasDropdownItems = useCommandState(
308
+ (state2) => state2.filtered.count > 0
309
+ );
310
+ const isDropdownHidden = isCustomPromptMultiline || !hasDropdownItems;
311
+ useEffect(() => {
312
+ if (!editor) {
313
+ return;
314
+ }
315
+ const handleKeyDown = (event) => {
316
+ if (!event.defaultPrevented && event.key === "Escape") {
317
+ event.preventDefault();
318
+ event.stopPropagation();
319
+ if (phase === "thinking") {
320
+ editor.commands.$cancelAiToolbarThinking();
321
+ } else {
322
+ editor.chain().$closeAiToolbar().focus().run();
323
+ }
324
+ }
325
+ };
326
+ document.addEventListener("keydown", handleKeyDown);
327
+ return () => {
328
+ document.removeEventListener("keydown", handleKeyDown);
329
+ };
330
+ }, [editor, phase]);
331
+ return /* @__PURE__ */ jsxs(AiToolbarContext.Provider, {
332
+ value: { state, toolbarRef, dropdownRef, isDropdownHidden },
333
+ children: [
334
+ /* @__PURE__ */ jsxs("div", {
335
+ className: "lb-tiptap-ai-toolbar-container",
336
+ children: [
337
+ /* @__PURE__ */ jsx("div", {
338
+ className: "lb-elevation lb-tiptap-ai-toolbar",
339
+ children: state.phase === "asking" ? /* @__PURE__ */ jsx(AiToolbarAsking, {}) : state.phase === "thinking" ? /* @__PURE__ */ jsx(AiToolbarThinking, {}) : state.phase === "reviewing" ? /* @__PURE__ */ jsx(AiToolbarReviewing, {}) : null
340
+ }),
341
+ /* @__PURE__ */ jsxs("div", {
342
+ className: "lb-tiptap-ai-toolbar-halo",
343
+ "data-active": state.phase === "thinking" ? "" : void 0,
344
+ "aria-hidden": true,
345
+ children: [
346
+ /* @__PURE__ */ jsx("div", {
347
+ className: "lb-tiptap-ai-toolbar-halo-horizontal"
348
+ }),
349
+ /* @__PURE__ */ jsx("div", {
350
+ className: "lb-tiptap-ai-toolbar-halo-vertical"
351
+ })
352
+ ]
353
+ })
354
+ ]
355
+ }),
356
+ state.phase === "asking" || state.phase === "reviewing" ? /* @__PURE__ */ jsx(Command.List, {
357
+ className: "lb-elevation lb-dropdown lb-tiptap-ai-toolbar-dropdown",
358
+ "data-hidden": isDropdownHidden ? "" : void 0,
359
+ ref: dropdownRef,
360
+ children: state.phase === "reviewing" ? /* @__PURE__ */ jsx(AiToolbarReviewingSuggestions, {}) : children
361
+ }) : null
362
+ ]
363
+ });
364
+ }
365
+ const defaultSuggestions = /* @__PURE__ */ jsxs(Fragment, {
366
+ children: [
367
+ /* @__PURE__ */ jsxs(AiToolbarSuggestionsGroup, {
368
+ label: "Modify",
369
+ children: [
370
+ /* @__PURE__ */ jsx(AiToolbarSuggestion, {
371
+ icon: /* @__PURE__ */ jsx(EditIcon, {}),
372
+ children: "Improve writing"
373
+ }),
374
+ /* @__PURE__ */ jsx(AiToolbarSuggestion, {
375
+ icon: /* @__PURE__ */ jsx(CheckIcon, {}),
376
+ children: "Fix mistakes"
377
+ }),
378
+ /* @__PURE__ */ jsx(AiToolbarSuggestion, {
379
+ icon: /* @__PURE__ */ jsx(ShortenIcon, {}),
380
+ children: "Simplify"
381
+ }),
382
+ /* @__PURE__ */ jsx(AiToolbarSuggestion, {
383
+ icon: /* @__PURE__ */ jsx(LengthenIcon, {}),
384
+ children: "Add more detail"
385
+ })
386
+ ]
387
+ }),
388
+ /* @__PURE__ */ jsx(AiToolbarSuggestionsGroup, {
389
+ label: "Generate",
390
+ children: /* @__PURE__ */ jsx(AiToolbarSuggestion, {
391
+ icon: /* @__PURE__ */ jsx(QuestionMarkIcon, {}),
392
+ children: "Explain"
393
+ })
394
+ })
395
+ ]
396
+ });
397
+ const AiToolbar = Object.assign(
398
+ forwardRef(
399
+ ({
400
+ position = "bottom",
401
+ offset: sideOffset = 6,
402
+ editor,
403
+ className,
404
+ suggestions: Suggestions = defaultSuggestions,
405
+ ...props
406
+ }, forwardedRef) => {
407
+ const state = useEditorState({
408
+ editor,
409
+ selector: (ctx) => {
410
+ return ctx.editor?.storage.liveblocksAi?.state;
411
+ }
412
+ }) ?? DEFAULT_STATE;
413
+ const selection = editor?.state.selection;
414
+ const phase = state.phase;
415
+ const floatingOptions = useMemo(() => {
416
+ const detectOverflowOptions = {
417
+ padding: AI_TOOLBAR_COLLISION_PADDING
418
+ };
419
+ return {
420
+ strategy: "fixed",
421
+ placement: position,
422
+ middleware: [
423
+ tiptapFloating(editor),
424
+ hide(detectOverflowOptions),
425
+ offset(sideOffset)
426
+ ],
427
+ whileElementsMounted: (...args) => {
428
+ return autoUpdate(...args, {
429
+ animationFrame: true
430
+ });
431
+ }
432
+ };
433
+ }, [editor, position, sideOffset]);
434
+ const isOpen = selection !== void 0 && state.phase !== "closed";
435
+ const {
436
+ refs: { setReference, setFloating },
437
+ strategy,
438
+ x,
439
+ y,
440
+ isPositioned
441
+ } = useFloating({
442
+ ...floatingOptions,
443
+ open: isOpen
444
+ });
445
+ const toolbarRef = useRef(null);
446
+ const mergedRefs = useRefs(forwardedRef, toolbarRef, setFloating);
447
+ const dropdownRef = useRef(null);
448
+ useEffect(() => {
449
+ if (!editor) {
450
+ return;
451
+ }
452
+ if (!selection && phase !== "closed") {
453
+ editor.commands.$closeAiToolbar();
454
+ }
455
+ }, [phase, editor, selection]);
456
+ useLayoutEffect(() => {
457
+ if (!editor || !isOpen) {
458
+ return;
459
+ }
460
+ setReference(null);
461
+ setTimeout(() => {
462
+ if (state.phase === "reviewing") {
463
+ const domRange = getDomRangeFromSelection(state.contentTarget, editor);
464
+ setReference(domRange);
465
+ } else if (!selection) {
466
+ setReference(null);
467
+ } else {
468
+ const domRange = getDomRangeFromSelection(selection, editor);
469
+ setReference(domRange);
470
+ }
471
+ }, 0);
472
+ }, [selection, editor, isOpen, state.phase, state.contentTarget, setReference]);
473
+ useEffect(() => {
474
+ if (!editor || !isOpen) {
475
+ return;
476
+ }
477
+ const handleOutsideEvent = (event) => {
478
+ if (!toolbarRef.current) {
479
+ return;
480
+ }
481
+ if (event.target && !toolbarRef.current.contains(event.target) && (dropdownRef.current ? !dropdownRef.current.contains(event.target) : true)) {
482
+ editor.commands.$closeAiToolbar();
483
+ }
484
+ };
485
+ setTimeout(() => {
486
+ document.addEventListener("pointerdown", handleOutsideEvent);
487
+ }, 0);
488
+ return () => {
489
+ document.removeEventListener("pointerdown", handleOutsideEvent);
490
+ };
491
+ }, [editor, isOpen]);
492
+ if (!editor || !isOpen) {
493
+ return null;
494
+ }
495
+ return createPortal(
496
+ /* @__PURE__ */ jsx(TooltipProvider, {
497
+ children: /* @__PURE__ */ jsx(EditorProvider, {
498
+ editor,
499
+ children: /* @__PURE__ */ jsx(Command, {
500
+ role: "toolbar",
501
+ label: "AI toolbar",
502
+ "aria-orientation": "horizontal",
503
+ className: classNames(
504
+ "lb-root lb-portal lb-tiptap-ai-toolbar-portal",
505
+ className
506
+ ),
507
+ ref: mergedRefs,
508
+ style: {
509
+ position: strategy,
510
+ top: 0,
511
+ left: 0,
512
+ transform: isPositioned ? `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)` : "translate3d(0, -200%, 0)"
513
+ },
514
+ ...props,
515
+ children: /* @__PURE__ */ jsx(AiToolbarContainer, {
516
+ state,
517
+ dropdownRef,
518
+ toolbarRef,
519
+ children: typeof Suggestions === "function" ? /* @__PURE__ */ jsx(Suggestions, {
520
+ children: defaultSuggestions
521
+ }) : Suggestions
522
+ })
523
+ })
524
+ })
525
+ }),
526
+ document.body
527
+ );
528
+ }
529
+ ),
530
+ {
531
+ SuggestionsGroup: AiToolbarSuggestionsGroup,
532
+ Suggestion: AiToolbarSuggestion
533
+ }
534
+ );
535
+
536
+ export { AI_TOOLBAR_COLLISION_PADDING, AiToolbar };
537
+ //# sourceMappingURL=AiToolbar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AiToolbar.mjs","sources":["../../src/ai/AiToolbar.tsx"],"sourcesContent":["import {\n autoUpdate,\n type DetectOverflowOptions,\n hide,\n type Middleware,\n offset,\n useFloating,\n type UseFloatingOptions,\n} from \"@floating-ui/react-dom\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport {\n Button,\n CheckIcon,\n CrossIcon,\n EditIcon,\n LengthenIcon,\n QuestionMarkIcon,\n SendIcon,\n ShortcutTooltip,\n ShortenIcon,\n SparklesIcon,\n TooltipProvider,\n UndoIcon,\n useRefs,\n} from \"@liveblocks/react-ui/_private\";\nimport { type Editor, useEditorState } from \"@tiptap/react\";\nimport { Command, useCommandState } from \"cmdk\";\nimport type {\n ComponentProps,\n ComponentType,\n KeyboardEvent as ReactKeyboardEvent,\n PropsWithChildren,\n ReactNode,\n RefObject,\n} from \"react\";\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { classNames } from \"../classnames\";\nimport { EditorProvider, useCurrentEditor } from \"../context\";\nimport type {\n AiCommands,\n AiExtensionStorage,\n AiToolbarState,\n ChainedAiCommands,\n FloatingPosition,\n} from \"../types\";\nimport { getDomRangeFromSelection } from \"../utils\";\nimport { DEFAULT_STATE } from \"./AiExtension\";\n\nexport const AI_TOOLBAR_COLLISION_PADDING = 10;\n\nexport interface AiToolbarProps\n extends Omit<ComponentProps<\"div\">, \"value\" | \"defaultValue\"> {\n editor: Editor | null;\n position?: FloatingPosition;\n offset?: number;\n suggestions?: ReactNode | ComponentType<PropsWithChildren>;\n}\n\ninterface AiToolbarDropdownGroupProps extends ComponentProps<\"div\"> {\n label: string;\n}\n\ninterface AiToolbarDropdownItemProps\n extends ComponentProps<typeof Command.Item> {\n icon?: ReactNode;\n}\n\ntype AiToolbarSuggestionsGroupProps = AiToolbarDropdownGroupProps;\n\ninterface AiToolbarSuggestionProps extends ComponentProps<\"div\"> {\n prompt?: string;\n icon?: ReactNode;\n}\n\ninterface AiToolbarContext {\n state: AiToolbarState;\n toolbarRef: RefObject<HTMLDivElement>;\n dropdownRef: RefObject<HTMLDivElement>;\n isDropdownHidden: boolean;\n}\n\nconst AiToolbarContext = createContext<AiToolbarContext | null>(null);\n\nfunction useAiToolbarContext() {\n const context = useContext(AiToolbarContext);\n\n if (!context) {\n throw new Error(\"useAiToolbarContext must be used within an AiToolbar\");\n }\n\n return context;\n}\n\n/**\n * A custom Floating UI middleware to position/scale the toolbar:\n * - Vertically: relative to the reference (e.g. selection)\n * - Horizontally: relative to the editor\n * - Width: relative to the editor\n */\nfunction tiptapFloating(editor: Editor | null): Middleware {\n return {\n name: \"tiptap\",\n options: editor,\n fn({ elements }) {\n if (!editor) {\n return {};\n }\n\n const editorRect = editor.view.dom.getBoundingClientRect();\n\n elements.floating.style.setProperty(\n \"--lb-tiptap-editor-width\",\n `${editorRect.width}px`\n );\n elements.floating.style.setProperty(\n \"--lb-tiptap-editor-height\",\n `${editorRect.height}px`\n );\n\n return {\n x: editorRect.x,\n };\n },\n };\n}\n\nconst AiToolbarDropdownGroup = forwardRef<\n HTMLDivElement,\n AiToolbarDropdownGroupProps\n>(({ children, label, ...props }, forwardedRef) => {\n return (\n <Command.Group\n heading={<span className=\"lb-dropdown-label\">{label}</span>}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </Command.Group>\n );\n});\n\nconst AiToolbarSuggestionsGroup = forwardRef<\n HTMLDivElement,\n AiToolbarSuggestionsGroupProps\n>((props, forwardedRef) => {\n return <AiToolbarDropdownGroup ref={forwardedRef} {...props} />;\n});\n\nconst AiToolbarDropdownItem = forwardRef<\n HTMLDivElement,\n AiToolbarDropdownItemProps\n>(({ children, onSelect, icon, ...props }, forwardedRef) => {\n return (\n <Command.Item\n className=\"lb-dropdown-item\"\n onSelect={onSelect}\n {...props}\n ref={forwardedRef}\n >\n {icon ? <span className=\"lb-icon-container\">{icon}</span> : null}\n {children ? (\n <span className=\"lb-dropdown-item-label\">{children}</span>\n ) : null}\n </Command.Item>\n );\n});\n\nconst AiToolbarSuggestion = forwardRef<\n HTMLDivElement,\n AiToolbarSuggestionProps\n>(({ prompt: manualPrompt, ...props }, forwardedRef) => {\n const editor = useCurrentEditor(\"Suggestion\", \"AiToolbar\");\n\n const handleSelect = useCallback(\n (prompt: string) => {\n (editor.commands as unknown as AiCommands).$startAiToolbarThinking(\n manualPrompt ?? prompt\n );\n },\n [editor, manualPrompt]\n );\n\n return (\n <AiToolbarDropdownItem\n {...props}\n onSelect={handleSelect}\n ref={forwardedRef}\n />\n );\n});\n\nfunction AiToolbarReviewingSuggestions() {\n const editor = useCurrentEditor(\"ReviewingSuggestions\", \"AiToolbar\");\n const { state } = useAiToolbarContext();\n const { prompt } = state as Extract<AiToolbarState, { phase: \"reviewing\" }>;\n\n const handleRetry = useCallback(() => {\n (editor.commands as unknown as AiCommands).$startAiToolbarThinking(prompt);\n }, [editor, prompt]);\n\n const handleDiscard = useCallback(() => {\n (editor.commands as unknown as AiCommands).$closeAiToolbar();\n }, [editor]);\n\n const handleAccept = useCallback(() => {\n (editor.commands as unknown as AiCommands).$acceptAiToolbarOutput();\n }, [editor]);\n\n return (\n <>\n <AiToolbarDropdownItem icon={<CheckIcon />} onSelect={handleAccept}>\n {/* TODO: Add logic */}\n Replace selection\n </AiToolbarDropdownItem>\n <AiToolbarDropdownItem icon={<CheckIcon />}>\n {/* TODO: Add logic */}\n Insert below\n </AiToolbarDropdownItem>\n <AiToolbarDropdownItem icon={<UndoIcon />} onSelect={handleRetry}>\n Try again\n </AiToolbarDropdownItem>\n <AiToolbarDropdownItem icon={<CrossIcon />} onSelect={handleDiscard}>\n Discard\n </AiToolbarDropdownItem>\n </>\n );\n}\n\nfunction AiToolbarCustomPromptContent() {\n const editor = useCurrentEditor(\"CustomPromptContent\", \"AiToolbar\");\n const aiName = (editor.storage.liveblocksAi as AiExtensionStorage).name;\n const textAreaRef = useRef<HTMLTextAreaElement>(null);\n const { state, dropdownRef, isDropdownHidden } = useAiToolbarContext();\n const { customPrompt } = state as Exclude<\n AiToolbarState,\n { phase: \"closed\" }\n >;\n const isCustomPromptEmpty = useMemo(\n () => customPrompt.trim() === \"\",\n [customPrompt]\n );\n\n useLayoutEffect(\n () => {\n setTimeout(() => {\n const textArea = textAreaRef.current;\n\n if (!textArea) {\n return;\n }\n\n textArea.focus();\n textArea.setSelectionRange(\n textArea.value.length,\n textArea.value.length\n );\n }, 0);\n },\n [] // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handlePromptKeyDown = (\n event: ReactKeyboardEvent<HTMLTextAreaElement>\n ) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n event.stopPropagation();\n\n if (event.shiftKey) {\n // If the shift key is pressed, add a new line\n (editor.commands as unknown as AiCommands)._updateAiToolbarCustomPrompt(\n (customPrompt) => customPrompt + \"\\n\"\n );\n } else {\n const selectedDropdownItem = dropdownRef.current?.querySelector(\n \"[role='option'][data-selected='true']\"\n ) as HTMLElement | null;\n\n if (!isDropdownHidden && selectedDropdownItem) {\n // If there's a selected dropdown item, select it\n selectedDropdownItem.click();\n } else if (!isCustomPromptEmpty) {\n // Otherwise, submit the custom prompt\n (editor.commands as unknown as AiCommands).$startAiToolbarThinking(\n customPrompt\n );\n }\n }\n }\n };\n\n const handleCustomPromptChange = useCallback(\n (customPrompt: string) => {\n (editor.commands as unknown as AiCommands)._updateAiToolbarCustomPrompt(\n customPrompt\n );\n },\n [editor]\n );\n\n const handleSendClick = useCallback(() => {\n if (isCustomPromptEmpty) {\n return;\n }\n\n (editor.commands as unknown as AiCommands).$startAiToolbarThinking(\n customPrompt\n );\n }, [editor, customPrompt, isCustomPromptEmpty]);\n\n return (\n <div className=\"lb-tiptap-ai-toolbar-content\">\n <span className=\"lb-icon-container lb-tiptap-ai-toolbar-icon-container\">\n <SparklesIcon />\n </span>\n <div\n className=\"lb-tiptap-ai-toolbar-custom-prompt-container\"\n data-value={customPrompt}\n >\n <Command.Input\n value={customPrompt}\n onValueChange={handleCustomPromptChange}\n asChild\n >\n <textarea\n ref={textAreaRef}\n className=\"lb-tiptap-ai-toolbar-custom-prompt\"\n placeholder={`Ask ${aiName} anything…`}\n onKeyDown={handlePromptKeyDown}\n rows={1}\n autoFocus\n />\n </Command.Input>\n </div>\n <div className=\"lb-tiptap-ai-toolbar-actions\">\n <ShortcutTooltip content={`Ask ${aiName}`} shortcut=\"Enter\">\n <Button\n className=\"lb-tiptap-ai-toolbar-action\"\n variant=\"primary\"\n aria-label={`Ask ${aiName}`}\n icon={<SendIcon />}\n disabled={isCustomPromptEmpty}\n onClick={handleSendClick}\n />\n </ShortcutTooltip>\n </div>\n </div>\n );\n}\n\nfunction AiToolbarAsking() {\n return <AiToolbarCustomPromptContent />;\n}\n\nfunction AiToolbarThinking() {\n const editor = useCurrentEditor(\"AiToolbarThinking\", \"AiToolbar\");\n const contentRef = useRef<HTMLDivElement>(null);\n const aiName = (editor.storage.liveblocksAi as AiExtensionStorage).name;\n\n const handleCancel = useCallback(() => {\n (editor.commands as unknown as AiCommands).$cancelAiToolbarThinking();\n }, [editor]);\n\n // Focus the toolbar content and clear the current window selection while thinking\n useLayoutEffect(() => {\n contentRef.current?.focus();\n window.getSelection()?.removeAllRanges();\n }, []);\n\n return (\n <>\n <div\n className=\"lb-tiptap-ai-toolbar-content\"\n tabIndex={0}\n ref={contentRef}\n >\n <span className=\"lb-icon-container lb-tiptap-ai-toolbar-icon-container\">\n <SparklesIcon />\n </span>\n <div className=\"lb-tiptap-ai-toolbar-thinking\">\n {aiName} is thinking…\n </div>\n <div className=\"lb-tiptap-ai-toolbar-actions\">\n <ShortcutTooltip content=\"Cancel\" shortcut=\"Escape\">\n <Button\n className=\"lb-tiptap-ai-toolbar-action\"\n variant=\"secondary\"\n aria-label=\"Cancel\"\n icon={<UndoIcon />}\n onClick={handleCancel}\n />\n </ShortcutTooltip>\n </div>\n </div>\n </>\n );\n}\n\nfunction AiToolbarReviewing() {\n return (\n <>\n {/* <div className=\"lb-tiptap-ai-toolbar-output-container\">\n <div className=\"lb-tiptap-ai-toolbar-output\">\n TODO: Display non-diff outputs inline here\n </div>\n </div> */}\n <AiToolbarCustomPromptContent />\n </>\n );\n}\n\nfunction AiToolbarContainer({\n state,\n toolbarRef,\n dropdownRef,\n children,\n}: PropsWithChildren<{\n state: AiExtensionStorage[\"state\"];\n toolbarRef: RefObject<HTMLDivElement>;\n dropdownRef: RefObject<HTMLDivElement>;\n}>) {\n const editor = useCurrentEditor(\"AiToolbarContainer\", \"AiToolbar\");\n const phase = state.phase;\n const customPrompt = state.customPrompt;\n const isCustomPromptMultiline = useMemo(\n () => customPrompt?.includes(\"\\n\"),\n [customPrompt]\n );\n const hasDropdownItems = useCommandState(\n (state) => state.filtered.count > 0\n ) as boolean;\n const isDropdownHidden = isCustomPromptMultiline || !hasDropdownItems;\n\n useEffect(() => {\n if (!editor) {\n return;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!event.defaultPrevented && event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n\n if (phase === \"thinking\") {\n (editor.commands as unknown as AiCommands).$cancelAiToolbarThinking();\n } else {\n (editor.chain() as ChainedAiCommands).$closeAiToolbar().focus().run();\n }\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [editor, phase]);\n\n return (\n <AiToolbarContext.Provider\n value={{ state, toolbarRef, dropdownRef, isDropdownHidden }}\n >\n <div className=\"lb-tiptap-ai-toolbar-container\">\n <div className=\"lb-elevation lb-tiptap-ai-toolbar\">\n {state.phase === \"asking\" ? (\n <AiToolbarAsking />\n ) : state.phase === \"thinking\" ? (\n <AiToolbarThinking />\n ) : state.phase === \"reviewing\" ? (\n <AiToolbarReviewing />\n ) : null}\n </div>\n <div\n className=\"lb-tiptap-ai-toolbar-halo\"\n data-active={state.phase === \"thinking\" ? \"\" : undefined}\n aria-hidden\n >\n <div className=\"lb-tiptap-ai-toolbar-halo-horizontal\" />\n <div className=\"lb-tiptap-ai-toolbar-halo-vertical\" />\n </div>\n </div>\n {state.phase === \"asking\" || state.phase === \"reviewing\" ? (\n <Command.List\n className=\"lb-elevation lb-dropdown lb-tiptap-ai-toolbar-dropdown\"\n data-hidden={isDropdownHidden ? \"\" : undefined}\n ref={dropdownRef}\n >\n {state.phase === \"reviewing\" ? (\n <AiToolbarReviewingSuggestions />\n ) : (\n children\n )}\n </Command.List>\n ) : null}\n </AiToolbarContext.Provider>\n );\n}\n\nconst defaultSuggestions = (\n <>\n <AiToolbarSuggestionsGroup label=\"Modify\">\n <AiToolbarSuggestion icon={<EditIcon />}>\n Improve writing\n </AiToolbarSuggestion>\n <AiToolbarSuggestion icon={<CheckIcon />}>\n Fix mistakes\n </AiToolbarSuggestion>\n <AiToolbarSuggestion icon={<ShortenIcon />}>Simplify</AiToolbarSuggestion>\n <AiToolbarSuggestion icon={<LengthenIcon />}>\n Add more detail\n </AiToolbarSuggestion>\n </AiToolbarSuggestionsGroup>\n <AiToolbarSuggestionsGroup label=\"Generate\">\n <AiToolbarSuggestion icon={<QuestionMarkIcon />}>\n Explain\n </AiToolbarSuggestion>\n </AiToolbarSuggestionsGroup>\n </>\n);\n\nexport const AiToolbar = Object.assign(\n forwardRef<HTMLDivElement, AiToolbarProps>(\n (\n {\n position = \"bottom\",\n offset: sideOffset = 6,\n editor,\n className,\n suggestions: Suggestions = defaultSuggestions,\n ...props\n },\n forwardedRef\n ) => {\n const state =\n useEditorState({\n editor,\n selector: (ctx) => {\n return (\n ctx.editor?.storage.liveblocksAi as AiExtensionStorage | undefined\n )?.state;\n },\n }) ?? DEFAULT_STATE;\n const selection = editor?.state.selection;\n const phase = state.phase;\n const floatingOptions: UseFloatingOptions = useMemo(() => {\n const detectOverflowOptions: DetectOverflowOptions = {\n padding: AI_TOOLBAR_COLLISION_PADDING,\n };\n\n return {\n strategy: \"fixed\",\n placement: position,\n middleware: [\n tiptapFloating(editor),\n hide(detectOverflowOptions),\n offset(sideOffset),\n ],\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n };\n }, [editor, position, sideOffset]);\n const isOpen = selection !== undefined && state.phase !== \"closed\";\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n isPositioned,\n } = useFloating({\n ...floatingOptions,\n open: isOpen,\n });\n const toolbarRef = useRef<HTMLDivElement>(null);\n const mergedRefs = useRefs(forwardedRef, toolbarRef, setFloating);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!editor) {\n return;\n }\n\n if (!selection && phase !== \"closed\") {\n (editor.commands as unknown as AiCommands).$closeAiToolbar();\n }\n }, [phase, editor, selection]);\n\n useLayoutEffect(() => {\n if (!editor || !isOpen) {\n return;\n }\n\n setReference(null);\n\n setTimeout(() => {\n if (state.phase === \"reviewing\") {\n const domRange = getDomRangeFromSelection(state.contentTarget, editor);\n setReference(domRange);\n } else if (!selection) {\n setReference(null);\n } else {\n const domRange = getDomRangeFromSelection(selection, editor);\n setReference(domRange);\n }\n }, 0);\n }, [selection, editor, isOpen, state.phase, state.contentTarget, setReference]);\n\n // Close the toolbar when clicking anywhere outside of it\n useEffect(() => {\n if (!editor || !isOpen) {\n return;\n }\n\n const handleOutsideEvent = (event: MouseEvent) => {\n if (!toolbarRef.current) {\n return;\n }\n\n if (\n event.target &&\n !toolbarRef.current.contains(event.target as Node) &&\n (dropdownRef.current\n ? !dropdownRef.current.contains(event.target as Node)\n : true)\n ) {\n (editor.commands as unknown as AiCommands).$closeAiToolbar();\n }\n };\n\n setTimeout(() => {\n document.addEventListener(\"pointerdown\", handleOutsideEvent);\n }, 0);\n\n return () => {\n document.removeEventListener(\"pointerdown\", handleOutsideEvent);\n };\n }, [editor, isOpen]);\n\n if (!editor || !isOpen) {\n return null;\n }\n\n return createPortal(\n <TooltipProvider>\n <EditorProvider editor={editor}>\n <Command\n role=\"toolbar\"\n label=\"AI toolbar\"\n aria-orientation=\"horizontal\"\n className={classNames(\n \"lb-root lb-portal lb-tiptap-ai-toolbar-portal\",\n className\n )}\n ref={mergedRefs}\n style={{\n position: strategy,\n top: 0,\n left: 0,\n transform: isPositioned\n ? `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`\n : \"translate3d(0, -200%, 0)\",\n }}\n {...props}\n >\n <AiToolbarContainer\n state={state}\n dropdownRef={dropdownRef}\n toolbarRef={toolbarRef}\n >\n {typeof Suggestions === \"function\" ? (\n <Suggestions children={defaultSuggestions} />\n ) : (\n Suggestions\n )}\n </AiToolbarContainer>\n </Command>\n </EditorProvider>\n </TooltipProvider>,\n document.body\n );\n }\n ),\n {\n SuggestionsGroup: AiToolbarSuggestionsGroup,\n Suggestion: AiToolbarSuggestion,\n }\n);\n"],"names":["customPrompt","state"],"mappings":"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"}