@liveblocks/react-ui 3.2.1 → 3.3.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/_private/index.cjs +4 -2
- package/dist/_private/index.cjs.map +1 -1
- package/dist/_private/index.d.cts +100 -33
- package/dist/_private/index.d.ts +100 -33
- package/dist/_private/index.js +3 -2
- package/dist/_private/index.js.map +1 -1
- package/dist/components/AiChat.cjs +11 -9
- package/dist/components/AiChat.cjs.map +1 -1
- package/dist/components/AiChat.js +12 -10
- package/dist/components/AiChat.js.map +1 -1
- package/dist/components/Thread.cjs +58 -0
- package/dist/components/Thread.cjs.map +1 -1
- package/dist/components/Thread.js +59 -1
- package/dist/components/Thread.js.map +1 -1
- package/dist/components/internal/AiComposer.cjs +132 -0
- package/dist/components/internal/AiComposer.cjs.map +1 -0
- package/dist/components/internal/AiComposer.js +130 -0
- package/dist/components/internal/AiComposer.js.map +1 -0
- package/dist/components/internal/Button.cjs.map +1 -1
- package/dist/components/internal/Button.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -11
- package/dist/index.d.ts +113 -11
- package/dist/index.js.map +1 -1
- package/dist/overrides.cjs +4 -3
- package/dist/overrides.cjs.map +1 -1
- package/dist/overrides.js +4 -3
- package/dist/overrides.js.map +1 -1
- package/dist/primitives/AiComposer/contexts.cjs +24 -0
- package/dist/primitives/AiComposer/contexts.cjs.map +1 -0
- package/dist/primitives/AiComposer/contexts.js +19 -0
- package/dist/primitives/AiComposer/contexts.js.map +1 -0
- package/dist/primitives/AiComposer/index.cjs +348 -0
- package/dist/primitives/AiComposer/index.cjs.map +1 -0
- package/dist/primitives/AiComposer/index.js +340 -0
- package/dist/primitives/AiComposer/index.js.map +1 -0
- package/dist/primitives/index.d.cts +8 -1
- package/dist/primitives/index.d.ts +8 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/src/styles/index.css +36 -10
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/components/internal/AiChatComposer.cjs +0 -161
- package/dist/components/internal/AiChatComposer.cjs.map +0 -1
- package/dist/components/internal/AiChatComposer.js +0 -159
- package/dist/components/internal/AiChatComposer.js.map +0 -1
- package/dist/primitives/AiChatComposer/index.cjs +0 -202
- package/dist/primitives/AiChatComposer/index.cjs.map +0 -1
- package/dist/primitives/AiChatComposer/index.js +0 -195
- package/dist/primitives/AiChatComposer/index.js.map +0 -1
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Signal, kInternal } from '@liveblocks/core';
|
|
3
|
+
import { useClient } from '@liveblocks/react';
|
|
4
|
+
import { useSignal, useLayoutEffect } from '@liveblocks/react/_private';
|
|
5
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
6
|
+
import { forwardRef, useRef, useState, useCallback, useImperativeHandle, useMemo } from 'react';
|
|
7
|
+
import { createEditor, Transforms, Editor } from 'slate';
|
|
8
|
+
import { withHistory } from 'slate-history';
|
|
9
|
+
import { withReact, ReactEditor, Slate, Editable } from 'slate-react';
|
|
10
|
+
import { requestSubmit } from '../../utils/request-submit.js';
|
|
11
|
+
import { useInitial } from '../../utils/use-initial.js';
|
|
12
|
+
import { withNormalize } from '../slate/plugins/normalize.js';
|
|
13
|
+
import { isEmpty } from '../slate/utils/is-empty.js';
|
|
14
|
+
import { AiComposerEditorContext, AiComposerContext, useAiComposerEditorContext, useAiComposer } from './contexts.js';
|
|
15
|
+
|
|
16
|
+
const AI_COMPOSER_SUBMIT_NAME = "AiComposerSubmit";
|
|
17
|
+
const AI_COMPOSER_ABORT_NAME = "AiComposerAbort";
|
|
18
|
+
const AI_COMPOSER_EDITOR_NAME = "AiComposerEditor";
|
|
19
|
+
const AI_COMPOSER_FORM_NAME = "AiComposerForm";
|
|
20
|
+
const emptyMessages\u03A3 = new Signal([]);
|
|
21
|
+
function getLastMessageId(messages) {
|
|
22
|
+
const lastMessage = messages[messages.length - 1];
|
|
23
|
+
if (lastMessage === void 0) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return lastMessage.id;
|
|
27
|
+
}
|
|
28
|
+
function getAbortableMessageId(messages) {
|
|
29
|
+
return messages.find(
|
|
30
|
+
(message) => message.role === "assistant" && (message.status === "generating" || message.status === "awaiting-tool")
|
|
31
|
+
)?.id;
|
|
32
|
+
}
|
|
33
|
+
const AiComposerForm = forwardRef(
|
|
34
|
+
({
|
|
35
|
+
onComposerSubmit,
|
|
36
|
+
onSubmit,
|
|
37
|
+
disabled,
|
|
38
|
+
chatId,
|
|
39
|
+
branchId,
|
|
40
|
+
asChild,
|
|
41
|
+
...props
|
|
42
|
+
}, forwardedRef) => {
|
|
43
|
+
const Component = asChild ? Slot : "form";
|
|
44
|
+
const client = useClient();
|
|
45
|
+
const formRef = useRef(null);
|
|
46
|
+
const editor = useInitial(
|
|
47
|
+
() => withNormalize(withHistory(withReact(createEditor())))
|
|
48
|
+
);
|
|
49
|
+
const [isEditorEmpty, setEditorEmpty] = useState(true);
|
|
50
|
+
const [isSubmitting, setSubmitting] = useState(false);
|
|
51
|
+
const [isFocused, setFocused] = useState(false);
|
|
52
|
+
const messages\u03A3 = chatId ? client[kInternal].ai.signals.getChatMessagesForBranch\u03A3(chatId, branchId) : emptyMessages\u03A3;
|
|
53
|
+
const lastMessageId = useSignal(messages\u03A3, getLastMessageId);
|
|
54
|
+
const abortableMessageId = useSignal(messages\u03A3, getAbortableMessageId);
|
|
55
|
+
const isDisabled = isSubmitting || disabled === true;
|
|
56
|
+
const canAbort = abortableMessageId !== void 0;
|
|
57
|
+
const canSubmit = !isEditorEmpty && !canAbort;
|
|
58
|
+
const clear = useCallback(() => {
|
|
59
|
+
Transforms.delete(editor, {
|
|
60
|
+
at: {
|
|
61
|
+
anchor: Editor.start(editor, []),
|
|
62
|
+
focus: Editor.end(editor, [])
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}, [editor]);
|
|
66
|
+
const select = useCallback(() => {
|
|
67
|
+
Transforms.select(editor, Editor.end(editor, []));
|
|
68
|
+
}, [editor]);
|
|
69
|
+
const focus = useCallback(
|
|
70
|
+
(resetSelection = true) => {
|
|
71
|
+
try {
|
|
72
|
+
if (!ReactEditor.isFocused(editor)) {
|
|
73
|
+
Transforms.select(
|
|
74
|
+
editor,
|
|
75
|
+
resetSelection || !editor.selection ? Editor.end(editor, []) : editor.selection
|
|
76
|
+
);
|
|
77
|
+
ReactEditor.focus(editor);
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
[editor]
|
|
83
|
+
);
|
|
84
|
+
const blur = useCallback(() => {
|
|
85
|
+
try {
|
|
86
|
+
ReactEditor.blur(editor);
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
}, [editor]);
|
|
90
|
+
const onSubmitEnd = useCallback(() => {
|
|
91
|
+
clear();
|
|
92
|
+
setSubmitting(false);
|
|
93
|
+
}, [clear]);
|
|
94
|
+
const handleSubmit = useCallback(
|
|
95
|
+
(event) => {
|
|
96
|
+
if (disabled) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const isEditorEmpty2 = isEmpty(editor, editor.children);
|
|
100
|
+
if (isEditorEmpty2) {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
onSubmit?.(event);
|
|
105
|
+
if (onComposerSubmit === void 0 || event.isDefaultPrevented()) {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const content = editor.children.map((block) => {
|
|
110
|
+
if ("type" in block && block.type === "paragraph") {
|
|
111
|
+
return block.children.map((child) => {
|
|
112
|
+
if ("text" in child) {
|
|
113
|
+
return child.text;
|
|
114
|
+
}
|
|
115
|
+
return "";
|
|
116
|
+
}).join("");
|
|
117
|
+
}
|
|
118
|
+
return "";
|
|
119
|
+
}).join("\n");
|
|
120
|
+
const promise = onComposerSubmit(
|
|
121
|
+
{ text: content, lastMessageId },
|
|
122
|
+
event
|
|
123
|
+
);
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
if (promise) {
|
|
126
|
+
setSubmitting(true);
|
|
127
|
+
promise.then(onSubmitEnd);
|
|
128
|
+
} else {
|
|
129
|
+
onSubmitEnd();
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
[disabled, editor, onSubmit, onComposerSubmit, onSubmitEnd, lastMessageId]
|
|
133
|
+
);
|
|
134
|
+
useLayoutEffect(() => {
|
|
135
|
+
setEditorEmpty(isEmpty(editor, editor.children));
|
|
136
|
+
}, [editor]);
|
|
137
|
+
const handleEditorValueChange = useCallback(() => {
|
|
138
|
+
setEditorEmpty(isEmpty(editor, editor.children));
|
|
139
|
+
}, [editor]);
|
|
140
|
+
const submit = useCallback(() => {
|
|
141
|
+
if (!canSubmit) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
requestAnimationFrame(() => {
|
|
145
|
+
if (formRef.current) {
|
|
146
|
+
requestSubmit(formRef.current);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}, [canSubmit]);
|
|
150
|
+
const abort = useCallback(() => {
|
|
151
|
+
if (!canAbort || !abortableMessageId) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
client[kInternal].ai.abort(abortableMessageId);
|
|
155
|
+
}, [canAbort, abortableMessageId, client]);
|
|
156
|
+
useImperativeHandle(
|
|
157
|
+
forwardedRef,
|
|
158
|
+
() => formRef.current,
|
|
159
|
+
[]
|
|
160
|
+
);
|
|
161
|
+
return /* @__PURE__ */ jsx(AiComposerEditorContext.Provider, {
|
|
162
|
+
value: {
|
|
163
|
+
editor,
|
|
164
|
+
onEditorValueChange: handleEditorValueChange,
|
|
165
|
+
abortableMessageId,
|
|
166
|
+
setFocused
|
|
167
|
+
},
|
|
168
|
+
children: /* @__PURE__ */ jsx(AiComposerContext.Provider, {
|
|
169
|
+
value: {
|
|
170
|
+
isDisabled,
|
|
171
|
+
isEmpty: isEditorEmpty,
|
|
172
|
+
isFocused,
|
|
173
|
+
canSubmit,
|
|
174
|
+
canAbort,
|
|
175
|
+
submit,
|
|
176
|
+
abort,
|
|
177
|
+
clear,
|
|
178
|
+
focus,
|
|
179
|
+
blur,
|
|
180
|
+
select
|
|
181
|
+
},
|
|
182
|
+
children: /* @__PURE__ */ jsx(Component, {
|
|
183
|
+
onSubmit: handleSubmit,
|
|
184
|
+
...props,
|
|
185
|
+
ref: formRef
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
function AiComposerEditorPlaceholder({
|
|
192
|
+
attributes,
|
|
193
|
+
children
|
|
194
|
+
}) {
|
|
195
|
+
const { opacity: _opacity, ...style } = attributes.style;
|
|
196
|
+
return /* @__PURE__ */ jsx("span", {
|
|
197
|
+
...attributes,
|
|
198
|
+
style,
|
|
199
|
+
"data-placeholder": "",
|
|
200
|
+
children
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
const AiComposerEditor = forwardRef(
|
|
204
|
+
({
|
|
205
|
+
defaultValue = "",
|
|
206
|
+
onKeyDown,
|
|
207
|
+
onFocus,
|
|
208
|
+
onBlur,
|
|
209
|
+
disabled,
|
|
210
|
+
autoFocus,
|
|
211
|
+
dir,
|
|
212
|
+
...props
|
|
213
|
+
}, forwardedRef) => {
|
|
214
|
+
const { editor, onEditorValueChange, setFocused } = useAiComposerEditorContext();
|
|
215
|
+
const {
|
|
216
|
+
submit,
|
|
217
|
+
isDisabled: isComposerDisabled,
|
|
218
|
+
isFocused,
|
|
219
|
+
focus,
|
|
220
|
+
blur,
|
|
221
|
+
select
|
|
222
|
+
} = useAiComposer();
|
|
223
|
+
const isDisabled = disabled || isComposerDisabled;
|
|
224
|
+
const handleKeyDown = useCallback(
|
|
225
|
+
(event) => {
|
|
226
|
+
onKeyDown?.(event);
|
|
227
|
+
if (event.isDefaultPrevented())
|
|
228
|
+
return;
|
|
229
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
submit();
|
|
232
|
+
} else if (event.key === "Enter" && event.shiftKey) {
|
|
233
|
+
event.preventDefault();
|
|
234
|
+
editor.insertBreak();
|
|
235
|
+
} else if (event.key === "Escape") {
|
|
236
|
+
blur();
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
[editor, onKeyDown, submit, blur]
|
|
240
|
+
);
|
|
241
|
+
const handleFocus = useCallback(
|
|
242
|
+
(event) => {
|
|
243
|
+
onFocus?.(event);
|
|
244
|
+
if (!event.isDefaultPrevented()) {
|
|
245
|
+
setFocused(true);
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
[onFocus, setFocused]
|
|
249
|
+
);
|
|
250
|
+
const handleBlur = useCallback(
|
|
251
|
+
(event) => {
|
|
252
|
+
onBlur?.(event);
|
|
253
|
+
if (!event.isDefaultPrevented()) {
|
|
254
|
+
setFocused(false);
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
[onBlur, setFocused]
|
|
258
|
+
);
|
|
259
|
+
useImperativeHandle(
|
|
260
|
+
forwardedRef,
|
|
261
|
+
() => ReactEditor.toDOMNode(editor, editor),
|
|
262
|
+
[editor]
|
|
263
|
+
);
|
|
264
|
+
useLayoutEffect(() => {
|
|
265
|
+
if (autoFocus) {
|
|
266
|
+
focus();
|
|
267
|
+
}
|
|
268
|
+
}, [autoFocus, editor, focus]);
|
|
269
|
+
useLayoutEffect(() => {
|
|
270
|
+
if (isFocused && editor.selection === null) {
|
|
271
|
+
select();
|
|
272
|
+
}
|
|
273
|
+
}, [editor, select, isFocused]);
|
|
274
|
+
const initialValue = useMemo(() => {
|
|
275
|
+
return defaultValue.split("\n").map((text) => ({ type: "paragraph", children: [{ text }] }));
|
|
276
|
+
}, [defaultValue]);
|
|
277
|
+
return /* @__PURE__ */ jsx(Slate, {
|
|
278
|
+
editor,
|
|
279
|
+
initialValue,
|
|
280
|
+
onValueChange: onEditorValueChange,
|
|
281
|
+
children: /* @__PURE__ */ jsx(Editable, {
|
|
282
|
+
dir,
|
|
283
|
+
enterKeyHint: "send",
|
|
284
|
+
autoCapitalize: "sentences",
|
|
285
|
+
"aria-label": "Composer editor",
|
|
286
|
+
onKeyDown: handleKeyDown,
|
|
287
|
+
onFocus: handleFocus,
|
|
288
|
+
onBlur: handleBlur,
|
|
289
|
+
"data-focused": isFocused || void 0,
|
|
290
|
+
"data-disabled": isDisabled || void 0,
|
|
291
|
+
...props,
|
|
292
|
+
readOnly: isDisabled,
|
|
293
|
+
disabled: isDisabled,
|
|
294
|
+
renderPlaceholder: AiComposerEditorPlaceholder
|
|
295
|
+
})
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
const AiComposerSubmit = forwardRef(({ disabled, asChild, ...props }, forwardedRef) => {
|
|
300
|
+
const Component = asChild ? Slot : "button";
|
|
301
|
+
const { isDisabled: isComposerDisabled, canSubmit } = useAiComposer();
|
|
302
|
+
const isDisabled = isComposerDisabled || disabled || !canSubmit;
|
|
303
|
+
return /* @__PURE__ */ jsx(Component, {
|
|
304
|
+
type: "submit",
|
|
305
|
+
...props,
|
|
306
|
+
ref: forwardedRef,
|
|
307
|
+
disabled: isDisabled
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
const AiComposerAbort = forwardRef(({ disabled, onClick, asChild, ...props }, forwardedRef) => {
|
|
311
|
+
const Component = asChild ? Slot : "button";
|
|
312
|
+
const { isDisabled: isComposerDisabled, canAbort, abort } = useAiComposer();
|
|
313
|
+
const isDisabled = isComposerDisabled || disabled || !canAbort;
|
|
314
|
+
const handleClick = useCallback(
|
|
315
|
+
(event) => {
|
|
316
|
+
onClick?.(event);
|
|
317
|
+
if (event.isDefaultPrevented()) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
abort();
|
|
321
|
+
},
|
|
322
|
+
[abort, onClick]
|
|
323
|
+
);
|
|
324
|
+
return /* @__PURE__ */ jsx(Component, {
|
|
325
|
+
type: "button",
|
|
326
|
+
...props,
|
|
327
|
+
ref: forwardedRef,
|
|
328
|
+
disabled: isDisabled,
|
|
329
|
+
onClick: handleClick
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
if (process.env.NODE_ENV !== "production") {
|
|
333
|
+
AiComposerEditor.displayName = AI_COMPOSER_EDITOR_NAME;
|
|
334
|
+
AiComposerForm.displayName = AI_COMPOSER_FORM_NAME;
|
|
335
|
+
AiComposerSubmit.displayName = AI_COMPOSER_SUBMIT_NAME;
|
|
336
|
+
AiComposerAbort.displayName = AI_COMPOSER_ABORT_NAME;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export { AiComposerAbort as Abort, AiComposerAbort, AiComposerForm, AiComposerSubmit, AiComposerEditor as Editor, AiComposerForm as Form, AiComposerSubmit as Submit };
|
|
340
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/primitives/AiComposer/index.tsx"],"sourcesContent":["import {\n type AiChatMessage,\n kInternal,\n Signal,\n type WithNavigation,\n} from \"@liveblocks/core\";\nimport { useClient } from \"@liveblocks/react\";\nimport { useLayoutEffect, useSignal } from \"@liveblocks/react/_private\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport type { FocusEvent, FormEvent, KeyboardEvent, MouseEvent } from \"react\";\nimport {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport {\n createEditor,\n Editor as SlateEditor,\n Transforms as SlateTransforms,\n} from \"slate\";\nimport { withHistory } from \"slate-history\";\nimport {\n Editable,\n ReactEditor,\n type RenderPlaceholderProps,\n Slate,\n withReact,\n} from \"slate-react\";\n\nimport type { AiComposerBody } from \"../../types\";\nimport { requestSubmit } from \"../../utils/request-submit\";\nimport { useInitial } from \"../../utils/use-initial\";\nimport { withNormalize } from \"../slate/plugins/normalize\";\nimport { isEmpty } from \"../slate/utils/is-empty\";\nimport {\n AiComposerContext,\n AiComposerEditorContext,\n useAiComposer,\n useAiComposerEditorContext,\n} from \"./contexts\";\nimport type {\n AiComposerEditorProps,\n AiComposerFormProps,\n AiComposerSubmitProps,\n} from \"./types\";\n\nconst AI_COMPOSER_SUBMIT_NAME = \"AiComposerSubmit\";\nconst AI_COMPOSER_ABORT_NAME = \"AiComposerAbort\";\nconst AI_COMPOSER_EDITOR_NAME = \"AiComposerEditor\";\nconst AI_COMPOSER_FORM_NAME = \"AiComposerForm\";\n\ntype UiChatMessage = WithNavigation<AiChatMessage>;\n\n/* -------------------------------------------------------------------------------------------------\n * Form\n * -----------------------------------------------------------------------------------------------*/\n\nconst emptyMessagesΣ = new Signal<UiChatMessage[]>([]);\n\nfunction getLastMessageId(messages: UiChatMessage[]) {\n const lastMessage = messages[messages.length - 1];\n\n if (lastMessage === undefined) {\n return null;\n }\n\n return lastMessage.id;\n}\n\nfunction getAbortableMessageId(messages: UiChatMessage[]) {\n return messages.find(\n (message) =>\n message.role === \"assistant\" &&\n (message.status === \"generating\" || message.status === \"awaiting-tool\")\n )?.id;\n}\n\n/**\n * Surrounds the AI composer's content and handles submissions.\n *\n * @example\n * <AiComposer.Form onComposerSubmit={({ text }) => {}}>\n *\t <AiComposer.Editor />\n * <AiComposer.Submit />\n * </AiComposer.Form>\n */\nexport const AiComposerForm = forwardRef<HTMLFormElement, AiComposerFormProps>(\n (\n {\n onComposerSubmit,\n onSubmit,\n disabled,\n chatId,\n branchId,\n asChild,\n ...props\n },\n forwardedRef\n ) => {\n const Component = asChild ? Slot : \"form\";\n const client = useClient();\n const formRef = useRef<HTMLFormElement | null>(null);\n const editor = useInitial(() =>\n withNormalize(withHistory(withReact(createEditor())))\n );\n const [isEditorEmpty, setEditorEmpty] = useState(true);\n const [isSubmitting, setSubmitting] = useState(false);\n const [isFocused, setFocused] = useState(false);\n const messagesΣ = chatId\n ? client[kInternal].ai.signals.getChatMessagesForBranchΣ(chatId, branchId)\n : emptyMessagesΣ;\n const lastMessageId = useSignal(messagesΣ, getLastMessageId);\n const abortableMessageId = useSignal(messagesΣ, getAbortableMessageId);\n\n const isDisabled = isSubmitting || disabled === true;\n const canAbort = abortableMessageId !== undefined;\n const canSubmit = !isEditorEmpty && !canAbort;\n\n const clear = useCallback(() => {\n SlateTransforms.delete(editor, {\n at: {\n anchor: SlateEditor.start(editor, []),\n focus: SlateEditor.end(editor, []),\n },\n });\n }, [editor]);\n\n const select = useCallback(() => {\n SlateTransforms.select(editor, SlateEditor.end(editor, []));\n }, [editor]);\n\n const focus = useCallback(\n (resetSelection = true) => {\n try {\n if (!ReactEditor.isFocused(editor)) {\n SlateTransforms.select(\n editor,\n resetSelection || !editor.selection\n ? SlateEditor.end(editor, [])\n : editor.selection\n );\n ReactEditor.focus(editor);\n }\n } catch {\n // Slate's DOM-specific methods will throw if the editor's DOM\n // node no longer exists. This action doesn't make sense on an\n // unmounted editor so we can safely ignore it.\n }\n },\n [editor]\n );\n\n const blur = useCallback(() => {\n try {\n ReactEditor.blur(editor);\n } catch {\n // Slate's DOM-specific methods will throw if the editor's DOM\n // node no longer exists. This action doesn't make sense on an\n // unmounted editor so we can safely ignore it.\n }\n }, [editor]);\n\n const onSubmitEnd = useCallback(() => {\n clear();\n setSubmitting(false);\n }, [clear]);\n\n const handleSubmit = useCallback(\n (event: FormEvent<HTMLFormElement>) => {\n if (disabled) {\n return;\n }\n\n // In some situations (e.g. pressing Enter while composing diacritics), it's possible\n // for the form to be submitted as empty even though we already checked whether the\n // editor was empty when handling the key press.\n const isEditorEmpty = isEmpty(editor, editor.children);\n\n // We even prevent the user's `onSubmit` handler from being called if the editor is empty.\n if (isEditorEmpty) {\n event.preventDefault();\n\n return;\n }\n\n onSubmit?.(event);\n\n if (onComposerSubmit === undefined || event.isDefaultPrevented()) {\n event.preventDefault();\n return;\n }\n\n // Extract the text content from the editor.\n const content = editor.children\n .map((block) => {\n if (\"type\" in block && block.type === \"paragraph\") {\n return block.children\n .map((child) => {\n if (\"text\" in child) {\n return child.text;\n }\n return \"\";\n })\n .join(\"\");\n }\n return \"\";\n })\n .join(\"\\n\");\n\n const promise = onComposerSubmit(\n { text: content, lastMessageId },\n event\n );\n\n event.preventDefault();\n\n if (promise) {\n setSubmitting(true);\n promise.then(onSubmitEnd);\n } else {\n onSubmitEnd();\n }\n },\n [disabled, editor, onSubmit, onComposerSubmit, onSubmitEnd, lastMessageId]\n );\n\n useLayoutEffect(() => {\n setEditorEmpty(isEmpty(editor, editor.children));\n }, [editor]);\n\n const handleEditorValueChange = useCallback(() => {\n setEditorEmpty(isEmpty(editor, editor.children));\n }, [editor]);\n\n const submit = useCallback(() => {\n if (!canSubmit) {\n return;\n }\n\n // We need to wait for the next frame in some cases like when composing diacritics,\n // we want any native handling to be done first while still being handled on `keydown`.\n requestAnimationFrame(() => {\n if (formRef.current) {\n requestSubmit(formRef.current);\n }\n });\n }, [canSubmit]);\n\n const abort = useCallback(() => {\n if (!canAbort || !abortableMessageId) {\n return;\n }\n\n client[kInternal].ai.abort(abortableMessageId);\n }, [canAbort, abortableMessageId, client]);\n\n useImperativeHandle<HTMLFormElement | null, HTMLFormElement | null>(\n forwardedRef,\n () => formRef.current,\n []\n );\n\n return (\n <AiComposerEditorContext.Provider\n value={{\n editor,\n onEditorValueChange: handleEditorValueChange,\n abortableMessageId,\n setFocused,\n }}\n >\n <AiComposerContext.Provider\n value={{\n isDisabled,\n isEmpty: isEditorEmpty,\n isFocused,\n canSubmit,\n canAbort,\n submit,\n abort,\n clear,\n focus,\n blur,\n select,\n }}\n >\n <Component onSubmit={handleSubmit} {...props} ref={formRef} />\n </AiComposerContext.Provider>\n </AiComposerEditorContext.Provider>\n );\n }\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Editor\n * -----------------------------------------------------------------------------------------------*/\n\nfunction AiComposerEditorPlaceholder({\n attributes,\n children,\n}: RenderPlaceholderProps) {\n const { opacity: _opacity, ...style } = attributes.style;\n\n return (\n <span {...attributes} style={style} data-placeholder=\"\">\n {children}\n </span>\n );\n}\n\n/**\n * Displays the AI composer's editor.\n *\n * @example\n * <AiComposer.Editor placeholder=\"Write a message…\" />\n */\nconst AiComposerEditor = forwardRef<HTMLDivElement, AiComposerEditorProps>(\n (\n {\n defaultValue = \"\",\n onKeyDown,\n onFocus,\n onBlur,\n disabled,\n autoFocus,\n dir,\n ...props\n },\n forwardedRef\n ) => {\n const { editor, onEditorValueChange, setFocused } =\n useAiComposerEditorContext();\n const {\n submit,\n isDisabled: isComposerDisabled,\n isFocused,\n focus,\n blur,\n select,\n } = useAiComposer();\n const isDisabled = disabled || isComposerDisabled;\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.isDefaultPrevented()) return;\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n submit();\n } else if (event.key === \"Enter\" && event.shiftKey) {\n event.preventDefault();\n editor.insertBreak();\n } else if (event.key === \"Escape\") {\n blur();\n }\n },\n [editor, onKeyDown, submit, blur]\n );\n\n const handleFocus = useCallback(\n (event: FocusEvent<HTMLDivElement>) => {\n onFocus?.(event);\n\n if (!event.isDefaultPrevented()) {\n setFocused(true);\n }\n },\n [onFocus, setFocused]\n );\n\n const handleBlur = useCallback(\n (event: FocusEvent<HTMLDivElement>) => {\n onBlur?.(event);\n\n if (!event.isDefaultPrevented()) {\n setFocused(false);\n }\n },\n [onBlur, setFocused]\n );\n\n useImperativeHandle(\n forwardedRef,\n () => ReactEditor.toDOMNode(editor, editor) as HTMLDivElement,\n [editor]\n );\n\n // Manually focus the editor when `autoFocus` is true\n useLayoutEffect(() => {\n if (autoFocus) {\n focus();\n }\n }, [autoFocus, editor, focus]);\n\n // Manually add a selection in the editor if the selection\n // is still empty after being focused\n useLayoutEffect(() => {\n if (isFocused && editor.selection === null) {\n select();\n }\n }, [editor, select, isFocused]);\n\n const initialValue: AiComposerBody = useMemo(() => {\n return defaultValue\n .split(\"\\n\")\n .map((text) => ({ type: \"paragraph\", children: [{ text }] }));\n }, [defaultValue]);\n\n return (\n <Slate\n editor={editor}\n initialValue={initialValue}\n onValueChange={onEditorValueChange}\n >\n <Editable\n dir={dir}\n enterKeyHint=\"send\"\n autoCapitalize=\"sentences\"\n aria-label=\"Composer editor\"\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-focused={isFocused || undefined}\n data-disabled={isDisabled || undefined}\n {...props}\n readOnly={isDisabled}\n disabled={isDisabled}\n renderPlaceholder={AiComposerEditorPlaceholder}\n />\n </Slate>\n );\n }\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Submit\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * A button to submit the AI composer's content.\n *\n * @example\n * <AiComposer.Submit>Send</AiComposer.Submit>\n */\nexport const AiComposerSubmit = forwardRef<\n HTMLButtonElement,\n AiComposerSubmitProps\n>(({ disabled, asChild, ...props }, forwardedRef) => {\n const Component = asChild ? Slot : \"button\";\n const { isDisabled: isComposerDisabled, canSubmit } = useAiComposer();\n const isDisabled = isComposerDisabled || disabled || !canSubmit;\n\n return (\n <Component\n type=\"submit\"\n {...props}\n ref={forwardedRef}\n disabled={isDisabled}\n />\n );\n});\n\n/* -------------------------------------------------------------------------------------------------\n * Abort\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * A button to abort a response related to the AI composer.\n *\n * @example\n * <AiComposer.Abort>Cancel</AiComposer.Abort>\n */\nexport const AiComposerAbort = forwardRef<\n HTMLButtonElement,\n AiComposerSubmitProps\n>(({ disabled, onClick, asChild, ...props }, forwardedRef) => {\n const Component = asChild ? Slot : \"button\";\n const { isDisabled: isComposerDisabled, canAbort, abort } = useAiComposer();\n const isDisabled = isComposerDisabled || disabled || !canAbort;\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n abort();\n },\n [abort, onClick]\n );\n\n return (\n <Component\n type=\"button\"\n {...props}\n ref={forwardedRef}\n disabled={isDisabled}\n onClick={handleClick}\n />\n );\n});\n\nif (process.env.NODE_ENV !== \"production\") {\n AiComposerEditor.displayName = AI_COMPOSER_EDITOR_NAME;\n AiComposerForm.displayName = AI_COMPOSER_FORM_NAME;\n AiComposerSubmit.displayName = AI_COMPOSER_SUBMIT_NAME;\n AiComposerAbort.displayName = AI_COMPOSER_ABORT_NAME;\n}\n\n// NOTE: Every export from this file will be available publicly as AiComposer.*\nexport {\n AiComposerAbort as Abort,\n AiComposerEditor as Editor,\n AiComposerForm as Form,\n AiComposerSubmit as Submit,\n};\n"],"names":["SlateTransforms","SlateEditor","isEditorEmpty"],"mappings":"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"}
|
|
@@ -22,6 +22,13 @@ type ComposerBodyMarks = {
|
|
|
22
22
|
[K in ComposerBodyMark]: boolean;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
interface AiComposerSubmitMessage {
|
|
26
|
+
/**
|
|
27
|
+
* The submitted message text.
|
|
28
|
+
*/
|
|
29
|
+
text: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
25
32
|
type CommentMentionProps = ComponentPropsWithSlot<"span">;
|
|
26
33
|
type CommentBodyMentionProps = {
|
|
27
34
|
/**
|
|
@@ -498,4 +505,4 @@ interface TimestampProps extends Omit<ComponentPropsWithSlot<"time">, "children"
|
|
|
498
505
|
*/
|
|
499
506
|
declare const Timestamp: react.ForwardRefExoticComponent<TimestampProps & react.RefAttributes<HTMLTimeElement>>;
|
|
500
507
|
|
|
501
|
-
export { AttachmentTooLargeError, index$1 as Comment, CommentBodyComponents, CommentBodyLinkProps, CommentBodyMentionProps, CommentBodyProps, CommentLinkProps, CommentMentionProps, index as Composer, ComposerAttachFilesProps, ComposerAttachmentsDropAreaProps, ComposerBodyMark, ComposerBodyMarks, ComposerContext, ComposerEditorComponents, ComposerEditorFloatingToolbarProps, ComposerEditorLinkProps, ComposerEditorMentionProps, ComposerEditorMentionSuggestionsProps, ComposerEditorProps, ComposerFloatingToolbarProps, ComposerFormProps, ComposerLinkProps, ComposerMarkToggleProps, ComposerMentionProps, ComposerSubmitComment, ComposerSubmitProps, ComposerSuggestionsListItemProps, ComposerSuggestionsListProps, FileSize, FileSizeProps, Timestamp, TimestampProps, useComposer };
|
|
508
|
+
export { AiComposerSubmitMessage, AttachmentTooLargeError, index$1 as Comment, CommentBodyComponents, CommentBodyLinkProps, CommentBodyMentionProps, CommentBodyProps, CommentLinkProps, CommentMentionProps, index as Composer, ComposerAttachFilesProps, ComposerAttachmentsDropAreaProps, ComposerBodyMark, ComposerBodyMarks, ComposerContext, ComposerEditorComponents, ComposerEditorFloatingToolbarProps, ComposerEditorLinkProps, ComposerEditorMentionProps, ComposerEditorMentionSuggestionsProps, ComposerEditorProps, ComposerFloatingToolbarProps, ComposerFormProps, ComposerLinkProps, ComposerMarkToggleProps, ComposerMentionProps, ComposerSubmitComment, ComposerSubmitProps, ComposerSuggestionsListItemProps, ComposerSuggestionsListProps, FileSize, FileSizeProps, Timestamp, TimestampProps, useComposer };
|
|
@@ -22,6 +22,13 @@ type ComposerBodyMarks = {
|
|
|
22
22
|
[K in ComposerBodyMark]: boolean;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
interface AiComposerSubmitMessage {
|
|
26
|
+
/**
|
|
27
|
+
* The submitted message text.
|
|
28
|
+
*/
|
|
29
|
+
text: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
25
32
|
type CommentMentionProps = ComponentPropsWithSlot<"span">;
|
|
26
33
|
type CommentBodyMentionProps = {
|
|
27
34
|
/**
|
|
@@ -498,4 +505,4 @@ interface TimestampProps extends Omit<ComponentPropsWithSlot<"time">, "children"
|
|
|
498
505
|
*/
|
|
499
506
|
declare const Timestamp: react.ForwardRefExoticComponent<TimestampProps & react.RefAttributes<HTMLTimeElement>>;
|
|
500
507
|
|
|
501
|
-
export { AttachmentTooLargeError, index$1 as Comment, CommentBodyComponents, CommentBodyLinkProps, CommentBodyMentionProps, CommentBodyProps, CommentLinkProps, CommentMentionProps, index as Composer, ComposerAttachFilesProps, ComposerAttachmentsDropAreaProps, ComposerBodyMark, ComposerBodyMarks, ComposerContext, ComposerEditorComponents, ComposerEditorFloatingToolbarProps, ComposerEditorLinkProps, ComposerEditorMentionProps, ComposerEditorMentionSuggestionsProps, ComposerEditorProps, ComposerFloatingToolbarProps, ComposerFormProps, ComposerLinkProps, ComposerMarkToggleProps, ComposerMentionProps, ComposerSubmitComment, ComposerSubmitProps, ComposerSuggestionsListItemProps, ComposerSuggestionsListProps, FileSize, FileSizeProps, Timestamp, TimestampProps, useComposer };
|
|
508
|
+
export { AiComposerSubmitMessage, AttachmentTooLargeError, index$1 as Comment, CommentBodyComponents, CommentBodyLinkProps, CommentBodyMentionProps, CommentBodyProps, CommentLinkProps, CommentMentionProps, index as Composer, ComposerAttachFilesProps, ComposerAttachmentsDropAreaProps, ComposerBodyMark, ComposerBodyMarks, ComposerContext, ComposerEditorComponents, ComposerEditorFloatingToolbarProps, ComposerEditorLinkProps, ComposerEditorMentionProps, ComposerEditorMentionSuggestionsProps, ComposerEditorProps, ComposerFloatingToolbarProps, ComposerFormProps, ComposerLinkProps, ComposerMarkToggleProps, ComposerMentionProps, ComposerSubmitComment, ComposerSubmitProps, ComposerSuggestionsListItemProps, ComposerSuggestionsListProps, FileSize, FileSizeProps, Timestamp, TimestampProps, useComposer };
|
package/dist/version.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const PKG_NAME = "@liveblocks/react-ui";
|
|
4
|
-
const PKG_VERSION = typeof "3.
|
|
4
|
+
const PKG_VERSION = typeof "3.3.0" === "string" && "3.3.0";
|
|
5
5
|
const PKG_FORMAT = typeof "cjs" === "string" && "cjs";
|
|
6
6
|
|
|
7
7
|
exports.PKG_FORMAT = PKG_FORMAT;
|
package/dist/version.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PKG_NAME = "@liveblocks/react-ui";
|
|
2
|
-
const PKG_VERSION = typeof "3.
|
|
2
|
+
const PKG_VERSION = typeof "3.3.0" === "string" && "3.3.0";
|
|
3
3
|
const PKG_FORMAT = typeof "esm" === "string" && "esm";
|
|
4
4
|
|
|
5
5
|
export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/react-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
78
|
"@floating-ui/react-dom": "^2.1.2",
|
|
79
|
-
"@liveblocks/client": "3.
|
|
80
|
-
"@liveblocks/core": "3.
|
|
81
|
-
"@liveblocks/react": "3.
|
|
79
|
+
"@liveblocks/client": "3.3.0",
|
|
80
|
+
"@liveblocks/core": "3.3.0",
|
|
81
|
+
"@liveblocks/react": "3.3.0",
|
|
82
82
|
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
|
83
83
|
"@radix-ui/react-popover": "^1.1.2",
|
|
84
84
|
"@radix-ui/react-slot": "^1.1.0",
|
package/src/styles/index.css
CHANGED
|
@@ -306,6 +306,10 @@
|
|
|
306
306
|
transition-property: background, color, opacity, box-shadow;
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
+
&:where([data-variant="ghost"]) {
|
|
310
|
+
background: transparent;
|
|
311
|
+
}
|
|
312
|
+
|
|
309
313
|
&:where(:has(.lb-button-label)) {
|
|
310
314
|
gap: calc(0.175 * var(--lb-spacing));
|
|
311
315
|
padding-inline: calc(0.55 * var(--lb-spacing));
|
|
@@ -1591,6 +1595,30 @@
|
|
|
1591
1595
|
}
|
|
1592
1596
|
}
|
|
1593
1597
|
|
|
1598
|
+
.lb-thread-show-more {
|
|
1599
|
+
position: relative;
|
|
1600
|
+
z-index: 1;
|
|
1601
|
+
display: flex;
|
|
1602
|
+
gap: calc(0.5 * var(--lb-spacing));
|
|
1603
|
+
justify-content: center;
|
|
1604
|
+
align-items: center;
|
|
1605
|
+
|
|
1606
|
+
&::before,
|
|
1607
|
+
&::after {
|
|
1608
|
+
content: "";
|
|
1609
|
+
z-index: 0;
|
|
1610
|
+
flex: 1 0 auto;
|
|
1611
|
+
min-inline-size: var(--lb-spacing);
|
|
1612
|
+
block-size: 0;
|
|
1613
|
+
border-block-start: 1px dashed var(--lb-foreground-subtle);
|
|
1614
|
+
transition-property: border;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
:where(.lb-thread-show-more + .lb-thread-new-indicator) {
|
|
1619
|
+
margin-block-start: calc(0.5 * var(--lb-spacing));
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1594
1622
|
.lb-thread-new-indicator {
|
|
1595
1623
|
position: relative;
|
|
1596
1624
|
z-index: 1;
|
|
@@ -2408,18 +2436,16 @@
|
|
|
2408
2436
|
}
|
|
2409
2437
|
|
|
2410
2438
|
/*************************************
|
|
2411
|
-
*
|
|
2439
|
+
* AI Composer *
|
|
2412
2440
|
*************************************/
|
|
2413
2441
|
|
|
2414
|
-
.lb-ai-
|
|
2442
|
+
.lb-ai-composer {
|
|
2415
2443
|
position: relative;
|
|
2416
2444
|
inline-size: 100%;
|
|
2417
2445
|
color: var(--lb-foreground);
|
|
2418
2446
|
}
|
|
2419
2447
|
|
|
2420
|
-
.lb-ai-
|
|
2421
|
-
:has(.lb-ai-chat-composer-editor:not(:focus-visible))
|
|
2422
|
-
) {
|
|
2448
|
+
.lb-ai-composer-form:where(:has(.lb-ai-composer-editor:not(:focus-visible))) {
|
|
2423
2449
|
:where(.lb-button[data-variant="primary"]) {
|
|
2424
2450
|
--lb-button-background: var(--lb-foreground-subtle);
|
|
2425
2451
|
|
|
@@ -2433,7 +2459,7 @@
|
|
|
2433
2459
|
}
|
|
2434
2460
|
}
|
|
2435
2461
|
|
|
2436
|
-
.lb-ai-
|
|
2462
|
+
.lb-ai-composer-editor {
|
|
2437
2463
|
max-block-size: 15rem;
|
|
2438
2464
|
padding: var(--lb-spacing) var(--lb-spacing) 0;
|
|
2439
2465
|
color: var(--lb-foreground-secondary);
|
|
@@ -2476,7 +2502,7 @@
|
|
|
2476
2502
|
}
|
|
2477
2503
|
}
|
|
2478
2504
|
|
|
2479
|
-
.lb-ai-
|
|
2505
|
+
.lb-ai-composer-footer {
|
|
2480
2506
|
display: flex;
|
|
2481
2507
|
gap: calc(0.75 * var(--lb-spacing));
|
|
2482
2508
|
align-items: center;
|
|
@@ -2484,14 +2510,14 @@
|
|
|
2484
2510
|
padding: var(--lb-spacing);
|
|
2485
2511
|
}
|
|
2486
2512
|
|
|
2487
|
-
.lb-ai-
|
|
2488
|
-
.lb-ai-
|
|
2513
|
+
.lb-ai-composer-actions,
|
|
2514
|
+
.lb-ai-composer-editor-actions {
|
|
2489
2515
|
display: flex;
|
|
2490
2516
|
gap: calc(0.125 * var(--lb-spacing));
|
|
2491
2517
|
align-items: center;
|
|
2492
2518
|
}
|
|
2493
2519
|
|
|
2494
|
-
.lb-ai-
|
|
2520
|
+
.lb-ai-composer-editor-actions {
|
|
2495
2521
|
margin-inline-end: auto;
|
|
2496
2522
|
}
|
|
2497
2523
|
|