@tangle-network/sandbox-ui 0.106.0 → 0.107.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/chat.d.ts +1 -287
- package/dist/chat.js +3 -14
- package/dist/{chunk-XIXYQNXD.js → chunk-EKYA6AFY.js} +120 -613
- package/dist/globals.css +0 -91
- package/dist/index.d.ts +1 -1
- package/dist/index.js +16 -26
- package/dist/styles.css +0 -91
- package/package.json +1 -3
- package/dist/chunk-WGOOQAW3.js +0 -12
- package/dist/mention-editor-Q3TKSZDL.js +0 -490
|
@@ -1,490 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MENTION_PILL_CLASS
|
|
3
|
-
} from "./chunk-WGOOQAW3.js";
|
|
4
|
-
import {
|
|
5
|
-
cn
|
|
6
|
-
} from "./chunk-EI44GEQ5.js";
|
|
7
|
-
import "./chunk-CZ7CSFO4.js";
|
|
8
|
-
|
|
9
|
-
// src/chat/mention-editor.tsx
|
|
10
|
-
import { mergeAttributes } from "@tiptap/core";
|
|
11
|
-
import Mention from "@tiptap/extension-mention";
|
|
12
|
-
import { EditorContent, useEditor } from "@tiptap/react";
|
|
13
|
-
import StarterKit from "@tiptap/starter-kit";
|
|
14
|
-
import { exitSuggestion } from "@tiptap/suggestion";
|
|
15
|
-
import * as React2 from "react";
|
|
16
|
-
|
|
17
|
-
// src/chat/mention-list.tsx
|
|
18
|
-
import { Loader2 } from "lucide-react";
|
|
19
|
-
import * as React from "react";
|
|
20
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
-
var MentionList = React.forwardRef(
|
|
22
|
-
function MentionList2({
|
|
23
|
-
items,
|
|
24
|
-
loading,
|
|
25
|
-
error,
|
|
26
|
-
emptyText = "No matches",
|
|
27
|
-
renderItem,
|
|
28
|
-
onSelect,
|
|
29
|
-
className
|
|
30
|
-
}, ref) {
|
|
31
|
-
const [selected, setSelected] = React.useState(0);
|
|
32
|
-
const selectedRef = React.useRef(0);
|
|
33
|
-
const move = (next) => {
|
|
34
|
-
selectedRef.current = next;
|
|
35
|
-
setSelected(next);
|
|
36
|
-
};
|
|
37
|
-
React.useEffect(() => {
|
|
38
|
-
move(0);
|
|
39
|
-
}, [items]);
|
|
40
|
-
React.useImperativeHandle(
|
|
41
|
-
ref,
|
|
42
|
-
() => ({
|
|
43
|
-
onKeyDown(event) {
|
|
44
|
-
const count = items.length;
|
|
45
|
-
switch (event.key) {
|
|
46
|
-
case "ArrowDown":
|
|
47
|
-
if (count > 0) move((selectedRef.current + 1) % count);
|
|
48
|
-
return true;
|
|
49
|
-
case "ArrowUp":
|
|
50
|
-
if (count > 0) move((selectedRef.current - 1 + count) % count);
|
|
51
|
-
return true;
|
|
52
|
-
case "Enter":
|
|
53
|
-
case "Tab":
|
|
54
|
-
if (count > 0) onSelect(items[selectedRef.current]);
|
|
55
|
-
return true;
|
|
56
|
-
default:
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}),
|
|
61
|
-
[items, onSelect]
|
|
62
|
-
);
|
|
63
|
-
return /* @__PURE__ */ jsxs(
|
|
64
|
-
"div",
|
|
65
|
-
{
|
|
66
|
-
role: "listbox",
|
|
67
|
-
"aria-label": "File mentions",
|
|
68
|
-
className: cn(
|
|
69
|
-
"max-h-64 min-w-[16rem] max-w-sm overflow-y-auto rounded-xl border border-border",
|
|
70
|
-
"bg-popover text-popover-foreground p-1 shadow-lg",
|
|
71
|
-
className
|
|
72
|
-
),
|
|
73
|
-
children: [
|
|
74
|
-
loading && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-2.5 py-2 text-muted-foreground text-sm", children: [
|
|
75
|
-
/* @__PURE__ */ jsx(Loader2, { className: "size-3.5 animate-spin", "data-motion": "essential" }),
|
|
76
|
-
"Searching\u2026"
|
|
77
|
-
] }),
|
|
78
|
-
!loading && error && /* @__PURE__ */ jsx("div", { className: "px-2.5 py-2 text-[var(--status-error,#ff4d6d)] text-sm", children: "Couldn\u2019t load matches" }),
|
|
79
|
-
!loading && !error && items.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-2.5 py-2 text-muted-foreground text-sm", children: emptyText }),
|
|
80
|
-
!loading && !error && items.map((item, index) => {
|
|
81
|
-
const active = index === selected;
|
|
82
|
-
return /* @__PURE__ */ jsx(
|
|
83
|
-
"button",
|
|
84
|
-
{
|
|
85
|
-
type: "button",
|
|
86
|
-
role: "option",
|
|
87
|
-
"aria-selected": active,
|
|
88
|
-
onMouseDown: (event) => {
|
|
89
|
-
event.preventDefault();
|
|
90
|
-
onSelect(item);
|
|
91
|
-
},
|
|
92
|
-
onMouseEnter: () => move(index),
|
|
93
|
-
className: cn(
|
|
94
|
-
"flex w-full items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-sm",
|
|
95
|
-
active ? "bg-primary/10 text-foreground" : "text-muted-foreground"
|
|
96
|
-
),
|
|
97
|
-
children: renderItem ? renderItem(item) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
98
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: item.label }),
|
|
99
|
-
item.detail && /* @__PURE__ */ jsx("span", { className: "ml-auto truncate text-muted-foreground text-xs", children: item.detail })
|
|
100
|
-
] })
|
|
101
|
-
},
|
|
102
|
-
item.id
|
|
103
|
-
);
|
|
104
|
-
})
|
|
105
|
-
]
|
|
106
|
-
}
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
// src/chat/mention-serialize.ts
|
|
112
|
-
var MENTION_TYPE = "mention";
|
|
113
|
-
function serializeMentionDoc(doc) {
|
|
114
|
-
return (doc.content ?? []).map(serializeBlock).join("\n");
|
|
115
|
-
}
|
|
116
|
-
function serializeBlock(node) {
|
|
117
|
-
if (node.type === "paragraph") {
|
|
118
|
-
return (node.content ?? []).map(serializeInline).join("");
|
|
119
|
-
}
|
|
120
|
-
return "";
|
|
121
|
-
}
|
|
122
|
-
function serializeInline(node) {
|
|
123
|
-
if (node.type === "text") return node.text ?? "";
|
|
124
|
-
if (node.type === "hardBreak") return "\n";
|
|
125
|
-
if (node.type === MENTION_TYPE) return `@${node.attrs?.id ?? ""}`;
|
|
126
|
-
return "";
|
|
127
|
-
}
|
|
128
|
-
function collectMentions(doc) {
|
|
129
|
-
const out = [];
|
|
130
|
-
const walk = (node) => {
|
|
131
|
-
if (node.type === MENTION_TYPE && node.attrs?.id) {
|
|
132
|
-
out.push({
|
|
133
|
-
id: node.attrs.id,
|
|
134
|
-
label: node.attrs.label ?? node.attrs.id,
|
|
135
|
-
kind: node.attrs.kind ?? void 0
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
for (const child of node.content ?? []) walk(child);
|
|
139
|
-
};
|
|
140
|
-
walk(doc);
|
|
141
|
-
return out;
|
|
142
|
-
}
|
|
143
|
-
function parseMentionValue(value, known) {
|
|
144
|
-
const lines = value.split("\n");
|
|
145
|
-
return {
|
|
146
|
-
type: "doc",
|
|
147
|
-
content: lines.map((line) => ({
|
|
148
|
-
type: "paragraph",
|
|
149
|
-
content: parseLine(line, known)
|
|
150
|
-
}))
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
function parseLine(line, known) {
|
|
154
|
-
const content = [];
|
|
155
|
-
let text = "";
|
|
156
|
-
const flush = () => {
|
|
157
|
-
if (text) {
|
|
158
|
-
content.push({ type: "text", text });
|
|
159
|
-
text = "";
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
let i = 0;
|
|
163
|
-
while (i < line.length) {
|
|
164
|
-
if (line[i] === "@") {
|
|
165
|
-
const id = matchKnownId(line, i + 1, known);
|
|
166
|
-
if (id) {
|
|
167
|
-
const item = known.get(id);
|
|
168
|
-
flush();
|
|
169
|
-
content.push({
|
|
170
|
-
type: MENTION_TYPE,
|
|
171
|
-
attrs: {
|
|
172
|
-
id: item.id,
|
|
173
|
-
label: item.label,
|
|
174
|
-
kind: item.kind ?? null
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
i += 1 + id.length;
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
text += line[i];
|
|
182
|
-
i += 1;
|
|
183
|
-
}
|
|
184
|
-
flush();
|
|
185
|
-
return content;
|
|
186
|
-
}
|
|
187
|
-
function matchKnownId(line, pos, known) {
|
|
188
|
-
let best = null;
|
|
189
|
-
for (const id of known.keys()) {
|
|
190
|
-
if (id.length === 0) continue;
|
|
191
|
-
if (best !== null && id.length <= best.length) continue;
|
|
192
|
-
if (!line.startsWith(id, pos)) continue;
|
|
193
|
-
const after = pos + id.length;
|
|
194
|
-
if (after < line.length && !/\s/.test(line[after])) continue;
|
|
195
|
-
best = id;
|
|
196
|
-
}
|
|
197
|
-
return best;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// src/chat/mention-editor.tsx
|
|
201
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
202
|
-
function buildComposerStarterKit() {
|
|
203
|
-
return StarterKit.configure({
|
|
204
|
-
blockquote: false,
|
|
205
|
-
bold: false,
|
|
206
|
-
bulletList: false,
|
|
207
|
-
code: false,
|
|
208
|
-
codeBlock: false,
|
|
209
|
-
dropcursor: false,
|
|
210
|
-
heading: false,
|
|
211
|
-
horizontalRule: false,
|
|
212
|
-
italic: false,
|
|
213
|
-
link: false,
|
|
214
|
-
listItem: false,
|
|
215
|
-
listKeymap: false,
|
|
216
|
-
orderedList: false,
|
|
217
|
-
strike: false,
|
|
218
|
-
trailingNode: false,
|
|
219
|
-
underline: false
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
function buildMentionExtension(trigger, suggestion) {
|
|
223
|
-
return Mention.extend({
|
|
224
|
-
addAttributes() {
|
|
225
|
-
return {
|
|
226
|
-
id: {
|
|
227
|
-
default: null,
|
|
228
|
-
parseHTML: (element) => element.getAttribute("data-id"),
|
|
229
|
-
renderHTML: (attrs) => attrs.id ? { "data-id": attrs.id } : {}
|
|
230
|
-
},
|
|
231
|
-
label: {
|
|
232
|
-
default: null,
|
|
233
|
-
parseHTML: (element) => element.getAttribute("data-label"),
|
|
234
|
-
renderHTML: (attrs) => attrs.label ? { "data-label": attrs.label } : {}
|
|
235
|
-
},
|
|
236
|
-
kind: {
|
|
237
|
-
default: null,
|
|
238
|
-
parseHTML: (element) => element.getAttribute("data-kind"),
|
|
239
|
-
renderHTML: (attrs) => attrs.kind ? { "data-kind": attrs.kind } : {}
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
}).configure({
|
|
244
|
-
HTMLAttributes: { class: MENTION_PILL_CLASS },
|
|
245
|
-
renderText: ({ node }) => `${trigger}${node.attrs.id}`,
|
|
246
|
-
renderHTML: ({ options, node }) => [
|
|
247
|
-
"span",
|
|
248
|
-
mergeAttributes(options.HTMLAttributes, {
|
|
249
|
-
title: node.attrs.id ?? void 0
|
|
250
|
-
}),
|
|
251
|
-
`${trigger}${node.attrs.label ?? node.attrs.id}`
|
|
252
|
-
],
|
|
253
|
-
suggestion
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
var EDITOR_CLASS = cn(
|
|
257
|
-
"w-full whitespace-pre-wrap break-words bg-transparent px-2 py-1",
|
|
258
|
-
"text-foreground text-sm leading-relaxed outline-none"
|
|
259
|
-
);
|
|
260
|
-
var FETCH_DEBOUNCE_MS = 100;
|
|
261
|
-
function mentionsKey(mentions) {
|
|
262
|
-
return mentions.map((item) => item.id).join("\0");
|
|
263
|
-
}
|
|
264
|
-
function MentionEditor({
|
|
265
|
-
value,
|
|
266
|
-
onChange,
|
|
267
|
-
onSubmit,
|
|
268
|
-
placeholder,
|
|
269
|
-
disabled,
|
|
270
|
-
autoFocus,
|
|
271
|
-
minRows,
|
|
272
|
-
maxHeight,
|
|
273
|
-
mention,
|
|
274
|
-
registerFocus,
|
|
275
|
-
onPasteFiles
|
|
276
|
-
}) {
|
|
277
|
-
const trigger = mention.trigger ?? "@";
|
|
278
|
-
const [anchor, setAnchor] = React2.useState(null);
|
|
279
|
-
const [open, setOpen] = React2.useState(false);
|
|
280
|
-
const [query, setQuery] = React2.useState("");
|
|
281
|
-
const [items, setItems] = React2.useState([]);
|
|
282
|
-
const [loading, setLoading] = React2.useState(false);
|
|
283
|
-
const [errored, setErrored] = React2.useState(false);
|
|
284
|
-
const openRef = React2.useRef(false);
|
|
285
|
-
const commandRef = React2.useRef(null);
|
|
286
|
-
const listRef = React2.useRef(null);
|
|
287
|
-
const knownRef = React2.useRef(/* @__PURE__ */ new Map());
|
|
288
|
-
const requestIdRef = React2.useRef(0);
|
|
289
|
-
const clientRectRef = React2.useRef(null);
|
|
290
|
-
const lastMentionsKeyRef = React2.useRef("");
|
|
291
|
-
const onSubmitRef = React2.useRef(onSubmit);
|
|
292
|
-
onSubmitRef.current = onSubmit;
|
|
293
|
-
const onChangeRef = React2.useRef(onChange);
|
|
294
|
-
onChangeRef.current = onChange;
|
|
295
|
-
const onMentionsChangeRef = React2.useRef(mention.onMentionsChange);
|
|
296
|
-
onMentionsChangeRef.current = mention.onMentionsChange;
|
|
297
|
-
const onPasteFilesRef = React2.useRef(onPasteFiles);
|
|
298
|
-
onPasteFilesRef.current = onPasteFiles;
|
|
299
|
-
const fetchItemsRef = React2.useRef(mention.fetchItems);
|
|
300
|
-
fetchItemsRef.current = mention.fetchItems;
|
|
301
|
-
const editor = useEditor(
|
|
302
|
-
{
|
|
303
|
-
immediatelyRender: false,
|
|
304
|
-
editable: !disabled,
|
|
305
|
-
autofocus: autoFocus ? "end" : false,
|
|
306
|
-
content: parseMentionValue(value, knownRef.current),
|
|
307
|
-
editorProps: {
|
|
308
|
-
attributes: {
|
|
309
|
-
class: EDITOR_CLASS,
|
|
310
|
-
role: "textbox",
|
|
311
|
-
"aria-multiline": "true",
|
|
312
|
-
"aria-label": "Message input"
|
|
313
|
-
},
|
|
314
|
-
handleKeyDown: (_view, event) => {
|
|
315
|
-
if (event.key !== "Enter" || event.shiftKey) return false;
|
|
316
|
-
if (event.isComposing || event.keyCode === 229) return false;
|
|
317
|
-
if (openRef.current) return false;
|
|
318
|
-
event.preventDefault();
|
|
319
|
-
onSubmitRef.current();
|
|
320
|
-
return true;
|
|
321
|
-
},
|
|
322
|
-
handlePaste: (_view, event) => {
|
|
323
|
-
const files = event.clipboardData?.files;
|
|
324
|
-
if (files && files.length > 0 && onPasteFilesRef.current) {
|
|
325
|
-
return onPasteFilesRef.current(files);
|
|
326
|
-
}
|
|
327
|
-
return false;
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
|
-
onUpdate: ({ editor: editor2 }) => {
|
|
331
|
-
const json = editor2.getJSON();
|
|
332
|
-
onChangeRef.current(serializeMentionDoc(json));
|
|
333
|
-
const mentions = collectMentions(json);
|
|
334
|
-
for (const item of mentions) knownRef.current.set(item.id, item);
|
|
335
|
-
lastMentionsKeyRef.current = mentionsKey(mentions);
|
|
336
|
-
onMentionsChangeRef.current?.(mentions);
|
|
337
|
-
},
|
|
338
|
-
extensions: [
|
|
339
|
-
buildComposerStarterKit(),
|
|
340
|
-
buildMentionExtension(trigger, {
|
|
341
|
-
char: trigger,
|
|
342
|
-
allowSpaces: false,
|
|
343
|
-
// Items are fetched by this component (so it can model loading and
|
|
344
|
-
// error states), not by the suggestion plugin.
|
|
345
|
-
items: () => [],
|
|
346
|
-
command: ({ editor: editor2, range, props }) => {
|
|
347
|
-
const item = props;
|
|
348
|
-
editor2.chain().focus().insertContentAt(range, [
|
|
349
|
-
{
|
|
350
|
-
type: "mention",
|
|
351
|
-
attrs: {
|
|
352
|
-
id: item.id,
|
|
353
|
-
label: item.label,
|
|
354
|
-
kind: item.kind ?? null
|
|
355
|
-
}
|
|
356
|
-
},
|
|
357
|
-
{ type: "text", text: " " }
|
|
358
|
-
]).run();
|
|
359
|
-
knownRef.current.set(item.id, item);
|
|
360
|
-
},
|
|
361
|
-
render: () => ({
|
|
362
|
-
onStart: (props) => {
|
|
363
|
-
openRef.current = true;
|
|
364
|
-
commandRef.current = props.command;
|
|
365
|
-
clientRectRef.current = props.clientRect ?? null;
|
|
366
|
-
setOpen(true);
|
|
367
|
-
setQuery(props.query);
|
|
368
|
-
setAnchor(props.clientRect?.() ?? null);
|
|
369
|
-
},
|
|
370
|
-
onUpdate: (props) => {
|
|
371
|
-
commandRef.current = props.command;
|
|
372
|
-
clientRectRef.current = props.clientRect ?? null;
|
|
373
|
-
setQuery(props.query);
|
|
374
|
-
setAnchor(props.clientRect?.() ?? null);
|
|
375
|
-
},
|
|
376
|
-
onKeyDown: (props) => {
|
|
377
|
-
if (props.event.key === "Escape") {
|
|
378
|
-
exitSuggestion(props.view);
|
|
379
|
-
return true;
|
|
380
|
-
}
|
|
381
|
-
return listRef.current?.onKeyDown(props.event) ?? false;
|
|
382
|
-
},
|
|
383
|
-
onExit: () => {
|
|
384
|
-
openRef.current = false;
|
|
385
|
-
commandRef.current = null;
|
|
386
|
-
setOpen(false);
|
|
387
|
-
setItems([]);
|
|
388
|
-
setLoading(false);
|
|
389
|
-
setErrored(false);
|
|
390
|
-
}
|
|
391
|
-
})
|
|
392
|
-
})
|
|
393
|
-
]
|
|
394
|
-
},
|
|
395
|
-
[]
|
|
396
|
-
);
|
|
397
|
-
React2.useEffect(() => {
|
|
398
|
-
if (!open) return;
|
|
399
|
-
const requestId = requestIdRef.current += 1;
|
|
400
|
-
setLoading(true);
|
|
401
|
-
setErrored(false);
|
|
402
|
-
const timer = setTimeout(() => {
|
|
403
|
-
Promise.resolve(fetchItemsRef.current(query)).then((results) => {
|
|
404
|
-
if (requestId !== requestIdRef.current) return;
|
|
405
|
-
for (const item of results) knownRef.current.set(item.id, item);
|
|
406
|
-
setItems(results);
|
|
407
|
-
setLoading(false);
|
|
408
|
-
}).catch(() => {
|
|
409
|
-
if (requestId !== requestIdRef.current) return;
|
|
410
|
-
setErrored(true);
|
|
411
|
-
setLoading(false);
|
|
412
|
-
});
|
|
413
|
-
}, FETCH_DEBOUNCE_MS);
|
|
414
|
-
return () => clearTimeout(timer);
|
|
415
|
-
}, [open, query]);
|
|
416
|
-
React2.useEffect(() => {
|
|
417
|
-
if (!open) return;
|
|
418
|
-
const reposition = () => setAnchor(clientRectRef.current?.() ?? null);
|
|
419
|
-
window.addEventListener("scroll", reposition, true);
|
|
420
|
-
window.addEventListener("resize", reposition);
|
|
421
|
-
return () => {
|
|
422
|
-
window.removeEventListener("scroll", reposition, true);
|
|
423
|
-
window.removeEventListener("resize", reposition);
|
|
424
|
-
};
|
|
425
|
-
}, [open]);
|
|
426
|
-
React2.useEffect(() => {
|
|
427
|
-
if (!editor) return;
|
|
428
|
-
if (serializeMentionDoc(editor.getJSON()) === value) return;
|
|
429
|
-
const doc = parseMentionValue(value, knownRef.current);
|
|
430
|
-
editor.commands.setContent(doc, { emitUpdate: false });
|
|
431
|
-
const mentions = collectMentions(doc);
|
|
432
|
-
const key = mentionsKey(mentions);
|
|
433
|
-
if (key !== lastMentionsKeyRef.current) {
|
|
434
|
-
lastMentionsKeyRef.current = key;
|
|
435
|
-
onMentionsChangeRef.current?.(mentions);
|
|
436
|
-
}
|
|
437
|
-
}, [editor, value]);
|
|
438
|
-
React2.useEffect(() => {
|
|
439
|
-
editor?.setEditable(!disabled);
|
|
440
|
-
}, [editor, disabled]);
|
|
441
|
-
React2.useEffect(() => {
|
|
442
|
-
if (!editor || !registerFocus) return;
|
|
443
|
-
registerFocus(() => editor.commands.focus());
|
|
444
|
-
}, [editor, registerFocus]);
|
|
445
|
-
return /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
|
|
446
|
-
/* @__PURE__ */ jsxs2(
|
|
447
|
-
"div",
|
|
448
|
-
{
|
|
449
|
-
className: "overflow-y-auto",
|
|
450
|
-
style: { maxHeight, minHeight: `${minRows * 1.5}rem` },
|
|
451
|
-
children: [
|
|
452
|
-
/* @__PURE__ */ jsx2(EditorContent, { editor }),
|
|
453
|
-
value.length === 0 && /* @__PURE__ */ jsx2("div", { className: "pointer-events-none absolute top-1 left-2 text-muted-foreground text-sm leading-relaxed", children: placeholder })
|
|
454
|
-
]
|
|
455
|
-
}
|
|
456
|
-
),
|
|
457
|
-
open && /* @__PURE__ */ jsx2(
|
|
458
|
-
"div",
|
|
459
|
-
{
|
|
460
|
-
className: "absolute z-20",
|
|
461
|
-
style: anchorStyle(anchor),
|
|
462
|
-
"data-testid": "mention-popover",
|
|
463
|
-
children: /* @__PURE__ */ jsx2(
|
|
464
|
-
MentionList,
|
|
465
|
-
{
|
|
466
|
-
ref: listRef,
|
|
467
|
-
items,
|
|
468
|
-
loading,
|
|
469
|
-
error: errored,
|
|
470
|
-
emptyText: mention.emptyText,
|
|
471
|
-
renderItem: mention.renderItem,
|
|
472
|
-
onSelect: (item) => commandRef.current?.(item),
|
|
473
|
-
className: mention.popoverClassName
|
|
474
|
-
}
|
|
475
|
-
)
|
|
476
|
-
}
|
|
477
|
-
)
|
|
478
|
-
] });
|
|
479
|
-
}
|
|
480
|
-
function anchorStyle(rect) {
|
|
481
|
-
if (!rect || rect.left === 0 && rect.bottom === 0) {
|
|
482
|
-
return { position: "absolute", top: "100%", left: 0 };
|
|
483
|
-
}
|
|
484
|
-
return { position: "fixed", top: rect.bottom + 4, left: rect.left };
|
|
485
|
-
}
|
|
486
|
-
export {
|
|
487
|
-
buildComposerStarterKit,
|
|
488
|
-
buildMentionExtension,
|
|
489
|
-
MentionEditor as default
|
|
490
|
-
};
|