@liveblocks/react-tiptap 2.16.1-ai2 → 2.16.1-ai4
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/LiveblocksExtension.js +7 -11
- package/dist/LiveblocksExtension.js.map +1 -1
- package/dist/LiveblocksExtension.mjs +7 -11
- package/dist/LiveblocksExtension.mjs.map +1 -1
- package/dist/ai/AiExtension.js +186 -109
- package/dist/ai/AiExtension.js.map +1 -1
- package/dist/ai/AiExtension.mjs +187 -111
- package/dist/ai/AiExtension.mjs.map +1 -1
- package/dist/ai/AiToolbar.js +182 -89
- package/dist/ai/AiToolbar.js.map +1 -1
- package/dist/ai/AiToolbar.mjs +186 -93
- package/dist/ai/AiToolbar.mjs.map +1 -1
- package/dist/comments/FloatingComposer.js +2 -2
- package/dist/comments/FloatingComposer.js.map +1 -1
- package/dist/comments/FloatingComposer.mjs +2 -2
- package/dist/comments/FloatingComposer.mjs.map +1 -1
- package/dist/index.d.mts +57 -16
- package/dist/index.d.ts +57 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/toolbar/Toolbar.js +1 -1
- package/dist/toolbar/Toolbar.js.map +1 -1
- package/dist/toolbar/Toolbar.mjs +1 -1
- package/dist/toolbar/Toolbar.mjs.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils.js +98 -6
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +98 -7
- package/dist/utils.mjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +6 -6
- package/src/styles/index.css +115 -59
- package/src/styles/utils.css +6 -0
- package/styles.css +1 -1
- package/styles.css.map +1 -1
package/dist/ai/AiToolbar.js
CHANGED
|
@@ -45,26 +45,36 @@ function tiptapFloating(editor) {
|
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
function flipToolbar() {
|
|
49
|
+
return {
|
|
50
|
+
name: "flipToolbar",
|
|
51
|
+
fn({ elements, middlewareData, rects }) {
|
|
52
|
+
const shiftOffsetY = middlewareData.shift?.y ?? 0;
|
|
53
|
+
if (Math.abs(shiftOffsetY) >= rects.floating.height) {
|
|
54
|
+
elements.floating.setAttribute("data-liveblocks-ai-toolbar-flip", "");
|
|
55
|
+
} else {
|
|
56
|
+
elements.floating.removeAttribute("data-liveblocks-ai-toolbar-flip");
|
|
57
|
+
}
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const AiToolbarDropdownSeparator = react.forwardRef(({ className, ...props }, forwardedRef) => {
|
|
63
|
+
return /* @__PURE__ */ jsxRuntime.jsx(cmdk.Command.Separator, {
|
|
64
|
+
className: classnames.classNames("lb-dropdown-separator", className),
|
|
54
65
|
...props,
|
|
55
|
-
ref: forwardedRef
|
|
56
|
-
children
|
|
66
|
+
ref: forwardedRef
|
|
57
67
|
});
|
|
58
68
|
});
|
|
59
|
-
const
|
|
60
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
69
|
+
const AiToolbarSuggestionsSeparator = react.forwardRef((props, forwardedRef) => {
|
|
70
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownSeparator, {
|
|
61
71
|
ref: forwardedRef,
|
|
62
72
|
...props
|
|
63
73
|
});
|
|
64
74
|
});
|
|
65
|
-
const AiToolbarDropdownItem = react.forwardRef(({ children, onSelect, icon, ...props }, forwardedRef) => {
|
|
75
|
+
const AiToolbarDropdownItem = react.forwardRef(({ children, onSelect, icon, className, ...props }, forwardedRef) => {
|
|
66
76
|
return /* @__PURE__ */ jsxRuntime.jsxs(cmdk.Command.Item, {
|
|
67
|
-
className: "lb-dropdown-item",
|
|
77
|
+
className: classnames.classNames("lb-dropdown-item", className),
|
|
68
78
|
onSelect,
|
|
69
79
|
...props,
|
|
70
80
|
ref: forwardedRef,
|
|
@@ -80,6 +90,14 @@ const AiToolbarDropdownItem = react.forwardRef(({ children, onSelect, icon, ...p
|
|
|
80
90
|
]
|
|
81
91
|
});
|
|
82
92
|
});
|
|
93
|
+
const AiToolbarSuggestionsLabel = react.forwardRef(({ children, className, ...props }, forwardedRef) => {
|
|
94
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
95
|
+
ref: forwardedRef,
|
|
96
|
+
className: classnames.classNames("lb-dropdown-label", className),
|
|
97
|
+
...props,
|
|
98
|
+
children
|
|
99
|
+
});
|
|
100
|
+
});
|
|
83
101
|
const AiToolbarSuggestion = react.forwardRef(({ prompt: manualPrompt, ...props }, forwardedRef) => {
|
|
84
102
|
const editor = context.useCurrentEditor("Suggestion", "AiToolbar");
|
|
85
103
|
const handleSelect = react.useCallback(
|
|
@@ -99,62 +117,50 @@ const AiToolbarSuggestion = react.forwardRef(({ prompt: manualPrompt, ...props }
|
|
|
99
117
|
function AiToolbarReviewingSuggestions() {
|
|
100
118
|
const editor = context.useCurrentEditor("ReviewingSuggestions", "AiToolbar");
|
|
101
119
|
const { state } = useAiToolbarContext();
|
|
102
|
-
const {
|
|
103
|
-
|
|
104
|
-
editor.commands.$closeAiToolbar();
|
|
105
|
-
}, [editor]);
|
|
106
|
-
const handleAccept = react.useCallback(() => {
|
|
107
|
-
editor.commands.$acceptAiToolbarOutput();
|
|
108
|
-
}, [editor]);
|
|
109
|
-
if (output.type === "insert" || output.type === "modification") {
|
|
120
|
+
const { response } = state;
|
|
121
|
+
if (AiExtension.isContextualPromptDiffResponse(response)) {
|
|
110
122
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
111
123
|
children: [
|
|
112
124
|
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownItem, {
|
|
113
125
|
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.CheckIcon, {}),
|
|
114
|
-
onSelect:
|
|
126
|
+
onSelect: editor.commands.$acceptAiToolbarResponse,
|
|
115
127
|
children: "Accept"
|
|
116
128
|
}),
|
|
117
129
|
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownItem, {
|
|
118
130
|
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.UndoIcon, {}),
|
|
119
|
-
|
|
131
|
+
onSelect: editor.commands.$startAiToolbarThinking,
|
|
120
132
|
children: "Try again"
|
|
121
133
|
}),
|
|
122
134
|
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownItem, {
|
|
123
135
|
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.CrossIcon, {}),
|
|
124
|
-
onSelect:
|
|
136
|
+
onSelect: editor.commands.$closeAiToolbar,
|
|
125
137
|
children: "Discard"
|
|
126
138
|
})
|
|
127
139
|
]
|
|
128
140
|
});
|
|
129
|
-
} else
|
|
141
|
+
} else {
|
|
130
142
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
131
143
|
children: [
|
|
132
144
|
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownItem, {
|
|
133
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.
|
|
134
|
-
|
|
135
|
-
children: "Replace selection"
|
|
136
|
-
}),
|
|
137
|
-
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownItem, {
|
|
138
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.CheckIcon, {}),
|
|
139
|
-
disabled: true,
|
|
145
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.ArrowCornerDownRightIcon, {}),
|
|
146
|
+
onSelect: editor.commands.$acceptAiToolbarResponse,
|
|
140
147
|
children: "Insert below"
|
|
141
148
|
}),
|
|
142
149
|
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownItem, {
|
|
143
150
|
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.UndoIcon, {}),
|
|
144
|
-
|
|
151
|
+
onSelect: editor.commands.$startAiToolbarThinking,
|
|
145
152
|
children: "Try again"
|
|
146
153
|
}),
|
|
147
154
|
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarDropdownItem, {
|
|
148
155
|
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.CrossIcon, {}),
|
|
149
|
-
onSelect:
|
|
156
|
+
onSelect: editor.commands.$closeAiToolbar,
|
|
150
157
|
children: "Discard"
|
|
151
158
|
})
|
|
152
159
|
]
|
|
153
160
|
});
|
|
154
161
|
}
|
|
155
|
-
return null;
|
|
156
162
|
}
|
|
157
|
-
function AiToolbarCustomPromptContent(
|
|
163
|
+
function AiToolbarCustomPromptContent() {
|
|
158
164
|
const editor = context.useCurrentEditor("CustomPromptContent", "AiToolbar");
|
|
159
165
|
const aiName = editor.storage.liveblocksAi.name;
|
|
160
166
|
const textAreaRef = react.useRef(null);
|
|
@@ -196,7 +202,8 @@ function AiToolbarCustomPromptContent({ disabled }) {
|
|
|
196
202
|
selectedDropdownItem.click();
|
|
197
203
|
} else if (!isCustomPromptEmpty) {
|
|
198
204
|
editor.commands.$startAiToolbarThinking(
|
|
199
|
-
customPrompt
|
|
205
|
+
customPrompt,
|
|
206
|
+
state.phase === "reviewing"
|
|
200
207
|
);
|
|
201
208
|
}
|
|
202
209
|
}
|
|
@@ -215,9 +222,10 @@ function AiToolbarCustomPromptContent({ disabled }) {
|
|
|
215
222
|
return;
|
|
216
223
|
}
|
|
217
224
|
editor.commands.$startAiToolbarThinking(
|
|
218
|
-
customPrompt
|
|
225
|
+
customPrompt,
|
|
226
|
+
state.phase === "reviewing"
|
|
219
227
|
);
|
|
220
|
-
}, [editor, customPrompt, isCustomPromptEmpty]);
|
|
228
|
+
}, [editor, customPrompt, isCustomPromptEmpty, state.phase]);
|
|
221
229
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
222
230
|
className: "lb-tiptap-ai-toolbar-content",
|
|
223
231
|
children: [
|
|
@@ -238,8 +246,7 @@ function AiToolbarCustomPromptContent({ disabled }) {
|
|
|
238
246
|
placeholder: `Ask ${aiName} anything\u2026`,
|
|
239
247
|
onKeyDown: handlePromptKeyDown,
|
|
240
248
|
rows: 1,
|
|
241
|
-
autoFocus: true
|
|
242
|
-
disabled
|
|
249
|
+
autoFocus: true
|
|
243
250
|
})
|
|
244
251
|
})
|
|
245
252
|
}),
|
|
@@ -253,7 +260,7 @@ function AiToolbarCustomPromptContent({ disabled }) {
|
|
|
253
260
|
variant: "primary",
|
|
254
261
|
"aria-label": `Ask ${aiName}`,
|
|
255
262
|
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.SendIcon, {}),
|
|
256
|
-
disabled: isCustomPromptEmpty
|
|
263
|
+
disabled: isCustomPromptEmpty,
|
|
257
264
|
onClick: handleSendClick
|
|
258
265
|
})
|
|
259
266
|
})
|
|
@@ -262,7 +269,23 @@ function AiToolbarCustomPromptContent({ disabled }) {
|
|
|
262
269
|
});
|
|
263
270
|
}
|
|
264
271
|
function AiToolbarAsking() {
|
|
265
|
-
|
|
272
|
+
const { state } = useAiToolbarContext();
|
|
273
|
+
const { error } = state;
|
|
274
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
275
|
+
children: [
|
|
276
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarCustomPromptContent, {}),
|
|
277
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
278
|
+
className: "lb-tiptap-ai-toolbar-error",
|
|
279
|
+
children: [
|
|
280
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
281
|
+
className: "lb-icon-container",
|
|
282
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(_private.WarningIcon, {})
|
|
283
|
+
}),
|
|
284
|
+
"There was a problem with your request."
|
|
285
|
+
]
|
|
286
|
+
}) : null
|
|
287
|
+
]
|
|
288
|
+
});
|
|
266
289
|
}
|
|
267
290
|
function AiToolbarThinking() {
|
|
268
291
|
const editor = context.useCurrentEditor("AiToolbarThinking", "AiToolbar");
|
|
@@ -312,19 +335,17 @@ function AiToolbarThinking() {
|
|
|
312
335
|
}
|
|
313
336
|
function AiToolbarReviewing() {
|
|
314
337
|
const { state } = useAiToolbarContext();
|
|
315
|
-
const {
|
|
338
|
+
const { response } = state;
|
|
316
339
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
317
340
|
children: [
|
|
318
|
-
|
|
319
|
-
className: "lb-tiptap-ai-toolbar-
|
|
341
|
+
response.type === "other" ? /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
342
|
+
className: "lb-tiptap-ai-toolbar-response-container",
|
|
320
343
|
children: /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
321
|
-
className: "lb-tiptap-ai-toolbar-
|
|
322
|
-
children:
|
|
344
|
+
className: "lb-tiptap-ai-toolbar-response",
|
|
345
|
+
children: response.text
|
|
323
346
|
})
|
|
324
347
|
}) : null,
|
|
325
|
-
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarCustomPromptContent, {
|
|
326
|
-
disabled: true
|
|
327
|
-
})
|
|
348
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarCustomPromptContent, {})
|
|
328
349
|
]
|
|
329
350
|
});
|
|
330
351
|
}
|
|
@@ -365,7 +386,12 @@ function AiToolbarContainer({
|
|
|
365
386
|
};
|
|
366
387
|
}, [editor, state.phase]);
|
|
367
388
|
return /* @__PURE__ */ jsxRuntime.jsxs(AiToolbarContext.Provider, {
|
|
368
|
-
value: {
|
|
389
|
+
value: {
|
|
390
|
+
state,
|
|
391
|
+
toolbarRef,
|
|
392
|
+
dropdownRef,
|
|
393
|
+
isDropdownHidden
|
|
394
|
+
},
|
|
369
395
|
children: [
|
|
370
396
|
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
371
397
|
className: "lb-tiptap-ai-toolbar-container",
|
|
@@ -400,40 +426,42 @@ function AiToolbarContainer({
|
|
|
400
426
|
}
|
|
401
427
|
const defaultSuggestions = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
402
428
|
children: [
|
|
403
|
-
/* @__PURE__ */ jsxRuntime.
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.EditIcon, {}),
|
|
408
|
-
children: "Improve writing"
|
|
409
|
-
}),
|
|
410
|
-
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
411
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.CheckIcon, {}),
|
|
412
|
-
children: "Fix mistakes"
|
|
413
|
-
}),
|
|
414
|
-
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
415
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.ShortenIcon, {}),
|
|
416
|
-
children: "Simplify"
|
|
417
|
-
}),
|
|
418
|
-
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
419
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.LengthenIcon, {}),
|
|
420
|
-
children: "Add more detail"
|
|
421
|
-
})
|
|
422
|
-
]
|
|
429
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
430
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.EditIcon, {}),
|
|
431
|
+
prompt: "Improve the quality of the text",
|
|
432
|
+
children: "Improve writing"
|
|
423
433
|
}),
|
|
424
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
434
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
435
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.CheckIcon, {}),
|
|
436
|
+
prompt: "Fix spelling & grammar errors in the text",
|
|
437
|
+
children: "Fix mistakes"
|
|
438
|
+
}),
|
|
439
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
440
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.ShortenIcon, {}),
|
|
441
|
+
prompt: "Shorten the text, simplifying it",
|
|
442
|
+
children: "Simplify"
|
|
443
|
+
}),
|
|
444
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
445
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.LengthenIcon, {}),
|
|
446
|
+
prompt: "Lengthen the text, going into more detail",
|
|
447
|
+
children: "Add more detail"
|
|
448
|
+
}),
|
|
449
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestionsSeparator, {}),
|
|
450
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
451
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.SparklesTextIcon, {}),
|
|
452
|
+
prompt: "Continue writing from the text's end",
|
|
453
|
+
children: "Continue writing"
|
|
454
|
+
}),
|
|
455
|
+
/* @__PURE__ */ jsxRuntime.jsx(AiToolbarSuggestion, {
|
|
456
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(_private.QuestionMarkIcon, {}),
|
|
457
|
+
prompt: "Explain what the text is about",
|
|
458
|
+
children: "Explain"
|
|
430
459
|
})
|
|
431
460
|
]
|
|
432
461
|
});
|
|
433
462
|
const AiToolbar = Object.assign(
|
|
434
463
|
react.forwardRef(
|
|
435
464
|
({
|
|
436
|
-
position = "bottom",
|
|
437
465
|
offset: sideOffset = 6,
|
|
438
466
|
editor,
|
|
439
467
|
className,
|
|
@@ -446,18 +474,25 @@ const AiToolbar = Object.assign(
|
|
|
446
474
|
return ctx.editor?.storage.liveblocksAi?.state;
|
|
447
475
|
}
|
|
448
476
|
}) ?? AiExtension.DEFAULT_STATE;
|
|
449
|
-
const selection =
|
|
477
|
+
const selection = editor?.state.selection;
|
|
450
478
|
const floatingOptions = react.useMemo(() => {
|
|
451
479
|
const detectOverflowOptions = {
|
|
452
480
|
padding: AI_TOOLBAR_COLLISION_PADDING
|
|
453
481
|
};
|
|
454
482
|
return {
|
|
455
483
|
strategy: "fixed",
|
|
456
|
-
placement:
|
|
484
|
+
placement: "bottom",
|
|
457
485
|
middleware: [
|
|
458
486
|
tiptapFloating(editor),
|
|
459
487
|
reactDom.hide(detectOverflowOptions),
|
|
460
|
-
reactDom.offset(sideOffset)
|
|
488
|
+
reactDom.offset(sideOffset),
|
|
489
|
+
reactDom.shift({
|
|
490
|
+
...detectOverflowOptions,
|
|
491
|
+
mainAxis: false,
|
|
492
|
+
crossAxis: true,
|
|
493
|
+
limiter: reactDom.limitShift()
|
|
494
|
+
}),
|
|
495
|
+
flipToolbar()
|
|
461
496
|
],
|
|
462
497
|
whileElementsMounted: (...args) => {
|
|
463
498
|
return reactDom.autoUpdate(...args, {
|
|
@@ -465,7 +500,7 @@ const AiToolbar = Object.assign(
|
|
|
465
500
|
});
|
|
466
501
|
}
|
|
467
502
|
};
|
|
468
|
-
}, [editor,
|
|
503
|
+
}, [editor, sideOffset]);
|
|
469
504
|
const isOpen = selection !== void 0 && state.phase !== "closed";
|
|
470
505
|
const {
|
|
471
506
|
refs: { setReference, setFloating },
|
|
@@ -480,6 +515,28 @@ const AiToolbar = Object.assign(
|
|
|
480
515
|
const toolbarRef = react.useRef(null);
|
|
481
516
|
const mergedRefs = _private.useRefs(forwardedRef, toolbarRef, setFloating);
|
|
482
517
|
const dropdownRef = react.useRef(null);
|
|
518
|
+
const [selectedDropdownValue, setSelectedDropdownValue] = react.useState("");
|
|
519
|
+
react.useEffect(() => {
|
|
520
|
+
if (state.phase === "closed") {
|
|
521
|
+
setSelectedDropdownValue("");
|
|
522
|
+
}
|
|
523
|
+
}, [state.phase]);
|
|
524
|
+
react.useEffect(() => {
|
|
525
|
+
if (state.phase === "closed") {
|
|
526
|
+
setSelectedDropdownValue("");
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const selectedDropdownItem = dropdownRef.current?.querySelector(
|
|
530
|
+
"[role='option'][data-selected='true']"
|
|
531
|
+
);
|
|
532
|
+
if (selectedDropdownItem) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const firstDropdownItem = dropdownRef.current?.querySelector("[role='option']");
|
|
536
|
+
setSelectedDropdownValue(
|
|
537
|
+
firstDropdownItem?.dataset.value ?? ""
|
|
538
|
+
);
|
|
539
|
+
}, [state.phase, dropdownRef, setSelectedDropdownValue]);
|
|
483
540
|
react.useEffect(() => {
|
|
484
541
|
if (!editor) {
|
|
485
542
|
return;
|
|
@@ -494,14 +551,47 @@ const AiToolbar = Object.assign(
|
|
|
494
551
|
}
|
|
495
552
|
setReference(null);
|
|
496
553
|
setTimeout(() => {
|
|
497
|
-
if (
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
554
|
+
if (state.phase === "reviewing" && AiExtension.isContextualPromptDiffResponse(state.response)) {
|
|
555
|
+
const changes = editor.view.dom.querySelectorAll(
|
|
556
|
+
"ychange[data-liveblocks]"
|
|
557
|
+
);
|
|
558
|
+
setReference({
|
|
559
|
+
getBoundingClientRect: () => {
|
|
560
|
+
const rects = [];
|
|
561
|
+
changes.forEach((change) => {
|
|
562
|
+
rects.push(change.getBoundingClientRect());
|
|
563
|
+
});
|
|
564
|
+
const minX = Math.min(...rects.map((rect) => rect.left));
|
|
565
|
+
const minY = Math.min(...rects.map((rect) => rect.top));
|
|
566
|
+
const maxX = Math.max(...rects.map((rect) => rect.right));
|
|
567
|
+
const maxY = Math.max(...rects.map((rect) => rect.bottom));
|
|
568
|
+
return {
|
|
569
|
+
x: minX,
|
|
570
|
+
y: minY,
|
|
571
|
+
width: maxX - minX,
|
|
572
|
+
height: maxY - minY,
|
|
573
|
+
top: minY,
|
|
574
|
+
left: minX,
|
|
575
|
+
bottom: maxY,
|
|
576
|
+
right: maxX
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
} else if (selection) {
|
|
581
|
+
const domRange = utils.getDomRangeFromSelection(editor, selection);
|
|
501
582
|
setReference(domRange);
|
|
583
|
+
} else {
|
|
584
|
+
setReference(null);
|
|
502
585
|
}
|
|
503
586
|
}, 0);
|
|
504
|
-
}, [
|
|
587
|
+
}, [
|
|
588
|
+
selection,
|
|
589
|
+
editor,
|
|
590
|
+
isOpen,
|
|
591
|
+
setReference,
|
|
592
|
+
state.phase,
|
|
593
|
+
state.response
|
|
594
|
+
]);
|
|
505
595
|
react.useEffect(() => {
|
|
506
596
|
if (!editor || !isOpen) {
|
|
507
597
|
return;
|
|
@@ -543,6 +633,8 @@ const AiToolbar = Object.assign(
|
|
|
543
633
|
left: 0,
|
|
544
634
|
transform: isPositioned ? `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)` : "translate3d(0, -200%, 0)"
|
|
545
635
|
},
|
|
636
|
+
value: selectedDropdownValue,
|
|
637
|
+
onValueChange: setSelectedDropdownValue,
|
|
546
638
|
...props,
|
|
547
639
|
children: /* @__PURE__ */ jsxRuntime.jsx(AiToolbarContainer, {
|
|
548
640
|
state,
|
|
@@ -560,8 +652,9 @@ const AiToolbar = Object.assign(
|
|
|
560
652
|
}
|
|
561
653
|
),
|
|
562
654
|
{
|
|
563
|
-
|
|
564
|
-
|
|
655
|
+
Suggestion: AiToolbarSuggestion,
|
|
656
|
+
SuggestionsLabel: AiToolbarSuggestionsLabel,
|
|
657
|
+
SuggestionsSeparator: AiToolbarSuggestionsSeparator
|
|
565
658
|
}
|
|
566
659
|
);
|
|
567
660
|
|