@comitor/ui 3.11.1 → 3.12.1

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 (75) hide show
  1. package/README.md +10 -5
  2. package/dist/chat/chat-composer.d.ts +36 -0
  3. package/dist/chat/chat-composer.js +85 -0
  4. package/dist/chat/chat-composer.js.map +1 -0
  5. package/dist/chat/chat-constants.d.ts +63 -0
  6. package/dist/chat/chat-constants.js +1 -0
  7. package/dist/chat/chat-constants.js.map +1 -0
  8. package/dist/chat/chat-message.d.ts +51 -0
  9. package/dist/chat/chat-message.js +137 -0
  10. package/dist/chat/chat-message.js.map +1 -0
  11. package/dist/chat/chat-sources.d.ts +25 -0
  12. package/dist/chat/chat-sources.js +97 -0
  13. package/dist/chat/chat-sources.js.map +1 -0
  14. package/dist/chat/chat-steps.d.ts +20 -0
  15. package/dist/chat/chat-steps.js +84 -0
  16. package/dist/chat/chat-steps.js.map +1 -0
  17. package/dist/chat/chat-thread.d.ts +21 -0
  18. package/dist/chat/chat-thread.js +87 -0
  19. package/dist/chat/chat-thread.js.map +1 -0
  20. package/dist/chat/index.d.ts +12 -0
  21. package/dist/chat/index.js +14 -0
  22. package/dist/chat/index.js.map +1 -0
  23. package/dist/components/composite/gantt-constants.d.ts +127 -0
  24. package/dist/components/composite/gantt-constants.js +5 -0
  25. package/dist/components/composite/gantt-constants.js.map +1 -0
  26. package/dist/components/composite/gantt-utils.d.ts +106 -0
  27. package/dist/components/composite/gantt-utils.js +196 -0
  28. package/dist/components/composite/gantt-utils.js.map +1 -0
  29. package/dist/components/composite/gantt.d.ts +93 -0
  30. package/dist/components/composite/gantt.js +1137 -0
  31. package/dist/components/composite/gantt.js.map +1 -0
  32. package/dist/components/composite/stat-card.d.ts +1 -1
  33. package/dist/components/composite/tree-view-constants.d.ts +96 -0
  34. package/dist/components/composite/tree-view-constants.js +85 -0
  35. package/dist/components/composite/tree-view-constants.js.map +1 -0
  36. package/dist/components/composite/tree-view.d.ts +58 -0
  37. package/dist/components/composite/tree-view.js +388 -0
  38. package/dist/components/composite/tree-view.js.map +1 -0
  39. package/dist/components/ui/badge.d.ts +1 -1
  40. package/dist/components/ui/button.d.ts +1 -1
  41. package/dist/editor/bubble-toolbar.d.ts +1 -1
  42. package/dist/editor/editor-core.d.ts +2 -2
  43. package/dist/editor/editor-core.js +6 -0
  44. package/dist/editor/editor-core.js.map +1 -1
  45. package/dist/editor/editor-types.d.ts +1 -1
  46. package/dist/editor/fixed-toolbar.d.ts +1 -1
  47. package/dist/editor/image-upload.d.ts +1 -1
  48. package/dist/editor/index.d.ts +1 -1
  49. package/dist/editor/markdown-editor.d.ts +1 -1
  50. package/dist/editor/markdown-extensions.d.ts +3 -1
  51. package/dist/editor/markdown-extensions.js +3 -1
  52. package/dist/editor/markdown-extensions.js.map +1 -1
  53. package/dist/editor/rich-text-editor.d.ts +1 -1
  54. package/dist/editor/slash-commands.d.ts +1 -1
  55. package/dist/editor/toolbar-actions.d.ts +1 -1
  56. package/dist/{editor-types-CSrMeuSw.d.ts → editor-types-BacXD2VN.d.ts} +7 -1
  57. package/dist/i18n/locale-provider.d.ts +3 -0
  58. package/dist/i18n/messages.d.ts +6 -0
  59. package/dist/i18n/messages.js +11 -2
  60. package/dist/i18n/messages.js.map +1 -1
  61. package/dist/i18n/namespaces/chat.d.ts +8 -0
  62. package/dist/i18n/namespaces/chat.js +47 -0
  63. package/dist/i18n/namespaces/chat.js.map +1 -0
  64. package/dist/i18n/namespaces/gantt.d.ts +10 -0
  65. package/dist/i18n/namespaces/gantt.js +57 -0
  66. package/dist/i18n/namespaces/gantt.js.map +1 -0
  67. package/dist/i18n/namespaces/tree-view.d.ts +8 -0
  68. package/dist/i18n/namespaces/tree-view.js +21 -0
  69. package/dist/i18n/namespaces/tree-view.js.map +1 -0
  70. package/dist/index.d.ts +6 -1
  71. package/dist/index.js +6 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/lib/avatar-tone.d.ts +4 -0
  74. package/dist/lib/avatar-tone.js.map +1 -1
  75. package/package.json +9 -2
@@ -0,0 +1,388 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { createElement } from "react";
4
+ import {
5
+ dragAndDropFeature,
6
+ hotkeysCoreFeature,
7
+ isOrderedDragTarget,
8
+ selectionFeature,
9
+ syncDataLoaderFeature
10
+ } from "@headless-tree/core";
11
+ import { useTree } from "@headless-tree/react";
12
+ import { useVirtualizer } from "@tanstack/react-virtual";
13
+ import { ChevronRight } from "lucide-react";
14
+ import * as React from "react";
15
+ import { useComitorLabels, useComitorLocale } from "../../i18n/locale-provider.js";
16
+ import { cn } from "../../lib/cn.js";
17
+ import {
18
+ computeTreeNumbering,
19
+ computeTreeRollup,
20
+ groupTreeChildren
21
+ } from "./tree-view-constants.js";
22
+ const ROOT_ID = "__comitor_tree_root__";
23
+ function useCoarsePointer() {
24
+ const subscribe = React.useCallback((onChange) => {
25
+ const mql = window.matchMedia("(pointer: coarse)");
26
+ mql.addEventListener("change", onChange);
27
+ return () => mql.removeEventListener("change", onChange);
28
+ }, []);
29
+ return React.useSyncExternalStore(
30
+ subscribe,
31
+ () => window.matchMedia("(pointer: coarse)").matches,
32
+ () => false
33
+ );
34
+ }
35
+ function useSemiControlled(value, defaultValue, onChange) {
36
+ const [inner, setInner] = React.useState(defaultValue ?? []);
37
+ const current = value ?? inner;
38
+ const currentRef = React.useRef(current);
39
+ currentRef.current = current;
40
+ const onChangeRef = React.useRef(onChange);
41
+ onChangeRef.current = onChange;
42
+ const controlled = value !== void 0;
43
+ const set = React.useCallback(
44
+ (updater) => {
45
+ const next = typeof updater === "function" ? updater(currentRef.current) : updater;
46
+ currentRef.current = next;
47
+ if (!controlled) setInner(next);
48
+ onChangeRef.current?.(next);
49
+ },
50
+ [controlled]
51
+ );
52
+ return [current, set];
53
+ }
54
+ const FEATURES = [syncDataLoaderFeature, selectionFeature, hotkeysCoreFeature, dragAndDropFeature];
55
+ function TreeView({
56
+ items,
57
+ expandedIds,
58
+ defaultExpandedIds,
59
+ onExpandedIdsChange,
60
+ selectedIds,
61
+ defaultSelectedIds,
62
+ onSelectedIdsChange,
63
+ onMove,
64
+ onItemOpen,
65
+ columns,
66
+ numbering = false,
67
+ renderItem,
68
+ rowHeight: rowHeightProp,
69
+ indent = 20,
70
+ readOnly = false,
71
+ labels,
72
+ className,
73
+ "aria-label": ariaLabel,
74
+ ...props
75
+ }) {
76
+ const t = useComitorLabels("treeView", labels);
77
+ const { locale } = useComitorLocale();
78
+ const coarse = useCoarsePointer();
79
+ const rowHeight = rowHeightProp ?? (coarse ? 44 : 32);
80
+ const editable = !readOnly && !!onMove;
81
+ const [expanded, setExpanded] = useSemiControlled(expandedIds, defaultExpandedIds, onExpandedIdsChange);
82
+ const [selected, setSelected] = useSemiControlled(selectedIds, defaultSelectedIds, onSelectedIdsChange);
83
+ const children = React.useMemo(() => groupTreeChildren(items), [items]);
84
+ const byId = React.useMemo(() => new Map(items.map((item) => [item.id, item])), [items]);
85
+ const numbers = React.useMemo(() => numbering ? computeTreeNumbering(items) : null, [numbering, items]);
86
+ const rollups = React.useMemo(
87
+ () => (columns ?? []).map((column) => column.value ? computeTreeRollup(items, column) : null),
88
+ [columns, items]
89
+ );
90
+ const numberFormat = React.useMemo(() => new Intl.NumberFormat(locale, { maximumFractionDigits: 1 }), [locale]);
91
+ const dataRef = React.useRef({ children, byId });
92
+ dataRef.current = { children, byId };
93
+ const dataLoader = React.useMemo(
94
+ () => ({
95
+ getItem: (id) => dataRef.current.byId.get(id) ?? { id, parentId: null, name: "" },
96
+ getChildren: (id) => (dataRef.current.children.get(id === ROOT_ID ? null : id) ?? []).map((child) => child.id)
97
+ }),
98
+ []
99
+ );
100
+ const isFolder = (id) => (children.get(id)?.length ?? 0) > 0 || !!byId.get(id)?.isFolder;
101
+ const [announcement, setAnnouncement] = React.useState("");
102
+ const pendingFocusRef = React.useRef(null);
103
+ const emitMove = (move) => {
104
+ if (!onMove) return;
105
+ const first = byId.get(move.ids[0] ?? "");
106
+ const remaining = (children.get(move.parentId) ?? []).filter((item) => !move.ids.includes(item.id));
107
+ const total = remaining.length + move.ids.length;
108
+ const position = Math.min(move.index, remaining.length) + 1;
109
+ onMove(move);
110
+ if (move.parentId) setExpanded((old) => old.includes(move.parentId) ? old : [...old, move.parentId]);
111
+ if (first) {
112
+ const sameParent = move.ids.length === 1 && first.parentId === move.parentId;
113
+ setAnnouncement(
114
+ sameParent ? t.movedTo(first.name, position, total) : t.movedInto(first.name, move.parentId ? byId.get(move.parentId)?.name ?? t.root : t.root, position, total)
115
+ );
116
+ pendingFocusRef.current = first.id;
117
+ }
118
+ };
119
+ const siblingsOf = (item) => children.get(item.parentId != null && byId.has(item.parentId) ? item.parentId : null) ?? [];
120
+ const canMoveItem = (id) => !!id && id !== ROOT_ID && editable && !byId.get(id)?.readOnly;
121
+ const outline = {
122
+ canIndent: (id) => {
123
+ const item = byId.get(id);
124
+ return !!item && canMoveItem(id) && siblingsOf(item).indexOf(item) > 0;
125
+ },
126
+ indent: (id) => {
127
+ const item = byId.get(id);
128
+ if (!item) return;
129
+ const siblings = siblingsOf(item);
130
+ const prev = siblings[siblings.indexOf(item) - 1];
131
+ if (!prev) return;
132
+ emitMove({ ids: [id], parentId: prev.id, index: children.get(prev.id)?.length ?? 0, kind: "indent" });
133
+ },
134
+ canOutdent: (id) => {
135
+ const item = byId.get(id);
136
+ return !!item && canMoveItem(id) && item.parentId != null && byId.has(item.parentId);
137
+ },
138
+ outdent: (id) => {
139
+ const item = byId.get(id);
140
+ const parent = item?.parentId != null ? byId.get(item.parentId) : void 0;
141
+ if (!item || !parent) return;
142
+ const grand = parent.parentId != null && byId.has(parent.parentId) ? parent.parentId : null;
143
+ const index = (children.get(grand) ?? []).indexOf(parent) + 1;
144
+ emitMove({ ids: [id], parentId: grand, index, kind: "outdent" });
145
+ },
146
+ canShift: (id, direction) => {
147
+ const item = byId.get(id);
148
+ if (!item || !canMoveItem(id)) return false;
149
+ const siblings = siblingsOf(item);
150
+ const index = siblings.indexOf(item) + direction;
151
+ return index >= 0 && index < siblings.length;
152
+ },
153
+ shift: (id, direction) => {
154
+ const item = byId.get(id);
155
+ if (!item) return;
156
+ const index = siblingsOf(item).indexOf(item) + direction;
157
+ emitMove({
158
+ ids: [id],
159
+ parentId: siblingsOf(item) === children.get(null) ? null : item.parentId,
160
+ index,
161
+ kind: direction < 0 ? "move-up" : "move-down"
162
+ });
163
+ }
164
+ };
165
+ const onDrop = (dragged, target) => {
166
+ const ids = dragged.map((item) => item.getId());
167
+ const targetId = target.item.getId();
168
+ const parentId = targetId === ROOT_ID ? null : targetId;
169
+ const index = isOrderedDragTarget(target) ? target.insertionIndex : (children.get(parentId) ?? []).filter((item) => !ids.includes(item.id)).length;
170
+ emitMove({ ids, parentId, index, kind: "drag" });
171
+ };
172
+ const scrollRef = React.useRef(null);
173
+ const headerHeight = columns?.length ? 32 : 0;
174
+ const virtualizerRef = React.useRef(null);
175
+ const tree = useTree({
176
+ rootItemId: ROOT_ID,
177
+ dataLoader,
178
+ getItemName: (item) => item.getItemData()?.name ?? "",
179
+ isItemFolder: (item) => isFolder(item.getId()),
180
+ state: { expandedItems: expanded, selectedItems: selected },
181
+ setExpandedItems: setExpanded,
182
+ setSelectedItems: setSelected,
183
+ indent,
184
+ canReorder: editable,
185
+ canDrag: (dragged) => editable && dragged.every((item) => !item.getItemData()?.readOnly),
186
+ // Chỉ NHÁNH nhận thả vào trong (gốc là nhánh) — đúng mặc định `target.item.isFolder()` của Headless
187
+ // Tree, mà khai `canDrop` là đè mất. Lá chỉ nhận thả trước/sau; biến lá thành nhánh là `Tab` hoặc
188
+ // `isFolder` (docs/tree-view.md §6). 3.12.0 viết `() => editable`: thả giữa một lá là lồng vào nó.
189
+ canDrop: (_, target) => editable && target.item.isFolder(),
190
+ onDrop,
191
+ scrollToItem: (item) => virtualizerRef.current?.scrollToIndex(item.getItemMeta().index, { align: "auto" }),
192
+ features: FEATURES
193
+ });
194
+ const onKeyDownCapture = (event) => {
195
+ if (event.target.getAttribute("role") !== "treeitem") return;
196
+ if (event.ctrlKey || event.metaKey) return;
197
+ const id = tree.getFocusedItem().getId();
198
+ const run = (action) => {
199
+ event.preventDefault();
200
+ event.stopPropagation();
201
+ action();
202
+ };
203
+ if (event.key === "Tab" && !event.altKey) {
204
+ if (event.shiftKey ? outline.canOutdent(id) : outline.canIndent(id)) {
205
+ run(() => event.shiftKey ? outline.outdent(id) : outline.indent(id));
206
+ }
207
+ return;
208
+ }
209
+ if (editable && event.altKey && !event.shiftKey && (event.key === "ArrowUp" || event.key === "ArrowDown")) {
210
+ const direction = event.key === "ArrowUp" ? -1 : 1;
211
+ run(() => {
212
+ if (outline.canShift(id, direction)) outline.shift(id, direction);
213
+ });
214
+ return;
215
+ }
216
+ if (event.key === "Enter" && !event.shiftKey && !event.altKey && onItemOpen) {
217
+ const data = byId.get(id);
218
+ if (data) run(() => onItemOpen(data));
219
+ }
220
+ };
221
+ React.useEffect(() => {
222
+ tree.rebuildTree();
223
+ const id = pendingFocusRef.current;
224
+ if (id) {
225
+ pendingFocusRef.current = null;
226
+ tree.getItemInstance(id)?.setFocused();
227
+ tree.updateDomFocus();
228
+ }
229
+ }, [items]);
230
+ const treeItems = tree.getItems();
231
+ const virtualizer = useVirtualizer({
232
+ count: treeItems.length,
233
+ getScrollElement: () => scrollRef.current,
234
+ estimateSize: () => rowHeight,
235
+ overscan: 10,
236
+ scrollMargin: headerHeight
237
+ });
238
+ virtualizerRef.current = virtualizer;
239
+ React.useEffect(() => {
240
+ virtualizer.measure();
241
+ }, [virtualizer, rowHeight]);
242
+ const instructionsId = React.useId();
243
+ const columnText = (column, index, item) => {
244
+ const value = rollups[index]?.get(item.id);
245
+ if (value == null) return null;
246
+ return column.formatText ? column.formatText(value, item) : numberFormat.format(value);
247
+ };
248
+ return /* @__PURE__ */ jsxs(
249
+ "div",
250
+ {
251
+ "data-slot": "tree-view",
252
+ className: cn("flex min-h-0 flex-col overflow-hidden rounded-lg border bg-card text-card-foreground", className),
253
+ ...props,
254
+ children: [
255
+ /* @__PURE__ */ jsxs("div", { ref: scrollRef, className: "relative min-h-0 flex-1 overflow-auto overscroll-contain", children: [
256
+ columns && columns.length > 0 && // Tiêu đề cột là của MẮT: cây ARIA không có hàng tiêu đề, nên giá trị cột đi vào tên của
257
+ // từng mục ("Thiết kế, Ước lượng: 12").
258
+ /* @__PURE__ */ jsxs(
259
+ "div",
260
+ {
261
+ "aria-hidden": "true",
262
+ "data-slot": "tree-view-header",
263
+ className: "sticky top-0 z-10 flex items-center gap-2 border-b bg-card pe-3 font-medium text-muted-foreground text-xs",
264
+ style: { height: headerHeight, paddingInlineStart: 8 + 20 },
265
+ children: [
266
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 truncate", children: t.nameHeader }),
267
+ columns.map((column) => /* @__PURE__ */ jsx(
268
+ "div",
269
+ {
270
+ className: cn("shrink-0 truncate", column.align === "start" ? "text-start" : "text-end"),
271
+ style: { width: column.width ?? 96 },
272
+ children: column.header
273
+ },
274
+ column.id
275
+ ))
276
+ ]
277
+ }
278
+ ),
279
+ /* @__PURE__ */ jsxs(
280
+ "div",
281
+ {
282
+ ...tree.getContainerProps(ariaLabel ?? t.label),
283
+ "aria-describedby": editable ? instructionsId : void 0,
284
+ className: "relative outline-hidden",
285
+ onKeyDownCapture,
286
+ style: { height: virtualizer.getTotalSize() },
287
+ children: [
288
+ virtualizer.getVirtualItems().map((virtualItem) => {
289
+ const item = treeItems[virtualItem.index];
290
+ if (!item) return null;
291
+ const data = item.getItemData();
292
+ if (!data) return null;
293
+ const meta = item.getItemMeta();
294
+ const folder = item.isFolder();
295
+ const isExpanded = folder && item.isExpanded();
296
+ const number = numbers?.get(data.id) ?? "";
297
+ const itemProps = item.getProps();
298
+ const label = [
299
+ number ? `${number} ${data.name}` : data.name,
300
+ ...(columns ?? []).flatMap((column, index) => {
301
+ const text = columnText(column, index, data);
302
+ return text != null && typeof column.header === "string" ? [`${column.header}: ${text}`] : [];
303
+ })
304
+ ].join(", ");
305
+ return /* @__PURE__ */ createElement(
306
+ "div",
307
+ {
308
+ ...itemProps,
309
+ key: item.getKey(),
310
+ role: "treeitem",
311
+ tabIndex: item.isFocused() ? 0 : -1,
312
+ "aria-label": label,
313
+ "data-slot": "tree-view-item",
314
+ "data-folder": folder || void 0,
315
+ className: cn(
316
+ "absolute inset-x-0 flex cursor-default select-none items-center gap-2 pe-3 text-foreground text-sm outline-hidden",
317
+ "hover:bg-muted focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-ring",
318
+ item.isSelected() && "bg-accent text-accent-foreground hover:bg-accent",
319
+ item.isDragTarget() && "bg-accent"
320
+ ),
321
+ style: {
322
+ top: virtualItem.start - headerHeight,
323
+ height: rowHeight,
324
+ paddingInlineStart: 8 + meta.level * indent
325
+ },
326
+ onDoubleClick: () => onItemOpen?.(data)
327
+ },
328
+ /* @__PURE__ */ jsx(
329
+ "span",
330
+ {
331
+ "aria-hidden": "true",
332
+ className: "flex size-5 shrink-0 items-center justify-center text-muted-foreground",
333
+ children: folder && /* @__PURE__ */ jsx(
334
+ ChevronRight,
335
+ {
336
+ className: cn(
337
+ "size-3.5 transition-transform rtl:rotate-180",
338
+ isExpanded && "rotate-90 rtl:rotate-90"
339
+ )
340
+ }
341
+ )
342
+ }
343
+ ),
344
+ number && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "shrink-0 text-muted-foreground text-xs tabular-nums", children: number }),
345
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("min-w-0 flex-1 truncate", folder && "font-medium"), children: renderItem ? renderItem(data, { level: meta.level, expanded: isExpanded, folder, number }) : data.name }),
346
+ columns?.map((column, index) => {
347
+ const value = rollups[index]?.get(data.id);
348
+ const rolledUp = !!column.rollup && (children.get(data.id)?.length ?? 0) > 0;
349
+ return /* @__PURE__ */ jsx(
350
+ "span",
351
+ {
352
+ "aria-hidden": "true",
353
+ className: cn(
354
+ "shrink-0 truncate tabular-nums",
355
+ column.align === "start" ? "text-start" : "text-end",
356
+ rolledUp ? "font-medium" : "text-muted-foreground"
357
+ ),
358
+ style: { width: column.width ?? 96 },
359
+ children: column.render ? column.render(data) : value == null ? null : column.format ? column.format(value, data, { rolledUp }) : numberFormat.format(value)
360
+ },
361
+ column.id
362
+ );
363
+ })
364
+ );
365
+ }),
366
+ /* @__PURE__ */ jsx(
367
+ "div",
368
+ {
369
+ "aria-hidden": "true",
370
+ "data-slot": "tree-view-drag-line",
371
+ className: "pointer-events-none -mt-px h-0.5 rounded-full bg-primary-ink",
372
+ style: tree.getDragLineStyle()
373
+ }
374
+ )
375
+ ]
376
+ }
377
+ )
378
+ ] }),
379
+ editable && /* @__PURE__ */ jsx("p", { id: instructionsId, className: "sr-only", children: t.instructions }),
380
+ /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", className: "sr-only", children: announcement })
381
+ ]
382
+ }
383
+ );
384
+ }
385
+ export {
386
+ TreeView
387
+ };
388
+ //# sourceMappingURL=tree-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/composite/tree-view.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Lõi cây: Headless Tree (https://headless-tree.lukasbach.com) — MIT License, Copyright (c) 2023\n * Lukas Bach. Gói dùng nó làm THƯ VIỆN (dependency), không chép mã: Headless Tree lo trạng thái\n * focus/mở/chọn, ARIA `tree`/`treeitem`, phím điều hướng theo W3C và kéo thả có đổi cha; phần vẽ,\n * phím dàn ý, đánh số, cột cộng dồn và ảo hoá là của gói. Lý do chọn: docs/tree-view.md.\n */\nimport {\n type DragTarget,\n dragAndDropFeature,\n hotkeysCoreFeature,\n type ItemInstance,\n isOrderedDragTarget,\n selectionFeature,\n syncDataLoaderFeature,\n type TreeInstance\n} from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { ChevronRight } from \"lucide-react\";\nimport * as React from \"react\";\nimport { useComitorLabels, useComitorLocale } from \"../../i18n/locale-provider.js\";\nimport { cn } from \"../../lib/cn.js\";\nimport {\n computeTreeNumbering,\n computeTreeRollup,\n groupTreeChildren,\n type TreeViewColumn,\n type TreeViewItem,\n type TreeViewLabels,\n type TreeViewMove\n} from \"./tree-view-constants.js\";\n\nexport interface TreeViewProps<T extends TreeViewItem>\n extends Omit<React.ComponentProps<\"div\">, \"children\" | \"onChange\" | \"onSelect\"> {\n /** Danh sách PHẲNG — `parentId` + thứ tự trong mảng (xem `TreeViewItem`). */\n items: T[];\n /** Nhánh đang mở (controlled). Bỏ trống thì cây tự giữ, bắt đầu từ `defaultExpandedIds`. */\n expandedIds?: string[];\n defaultExpandedIds?: string[];\n onExpandedIdsChange?: (ids: string[]) => void;\n /** Mục đang chọn (controlled). Bấm = chọn một; Ctrl/⌘ = thêm/bớt; Shift = chọn dải. */\n selectedIds?: string[];\n defaultSelectedIds?: string[];\n onSelectedIdsChange?: (ids: string[]) => void;\n /**\n * Người dùng đổi chỗ (kéo thả, Tab, Shift+Tab, Alt+↑/↓). Cây KHÔNG tự ghi: app áp bằng\n * `moveTreeItems` (hoặc gọi API) rồi truyền `items` mới. Không truyền = thứ tự chỉ đọc.\n */\n onMove?: (move: TreeViewMove) => void;\n /** Mở một mục: Enter, hoặc bấm đúp. */\n onItemOpen?: (item: T) => void;\n /** Cột phụ bên phải tên — số liệu có cộng dồn ở nhánh (giờ ước lượng, tiến độ…). */\n columns?: TreeViewColumn<T>[];\n /** Hiện số hiệu dàn ý `1.2.3` trước tên (WBS). */\n numbering?: boolean;\n /** Vẽ phần tên của một dòng — thay cho tên trần (icon, nhãn trạng thái…). */\n renderItem?: (\n item: T,\n state: { level: number; expanded: boolean; folder: boolean; number: string }\n ) => React.ReactNode;\n /** Chiều cao dòng, px (mặc định 32 — và 44 trên thiết bị chạm). */\n rowHeight?: number;\n /** Thụt lề mỗi bậc, px (mặc định 20). */\n indent?: number;\n /** Khoá mọi thao tác đổi chỗ dù có `onMove`. */\n readOnly?: boolean;\n labels?: Partial<TreeViewLabels>;\n}\n\nconst ROOT_ID = \"__comitor_tree_root__\";\n\nfunction useCoarsePointer(): boolean {\n const subscribe = React.useCallback((onChange: () => void) => {\n const mql = window.matchMedia(\"(pointer: coarse)\");\n mql.addEventListener(\"change\", onChange);\n return () => mql.removeEventListener(\"change\", onChange);\n }, []);\n return React.useSyncExternalStore(\n subscribe,\n () => window.matchMedia(\"(pointer: coarse)\").matches,\n () => false\n );\n}\n\n/** State nửa controlled: có `value` thì theo `value`, không thì tự giữ — cùng báo `onChange`. */\nfunction useSemiControlled(\n value: string[] | undefined,\n defaultValue: string[] | undefined,\n onChange: ((next: string[]) => void) | undefined\n) {\n const [inner, setInner] = React.useState<string[]>(defaultValue ?? []);\n const current = value ?? inner;\n const currentRef = React.useRef(current);\n currentRef.current = current;\n const onChangeRef = React.useRef(onChange);\n onChangeRef.current = onChange;\n const controlled = value !== undefined;\n const set = React.useCallback(\n (updater: string[] | ((old: string[]) => string[])) => {\n const next = typeof updater === \"function\" ? updater(currentRef.current) : updater;\n currentRef.current = next;\n if (!controlled) setInner(next);\n onChangeRef.current?.(next);\n },\n [controlled]\n );\n return [current, set] as const;\n}\n\nconst FEATURES = [syncDataLoaderFeature, selectionFeature, hotkeysCoreFeature, dragAndDropFeature];\n\n/**\n * Cây có thao tác DÀN Ý — dựng cho WBS (dự án → giai đoạn → hạng mục → việc), dùng được cho mọi\n * cây có thứ tự (danh mục, sơ đồ tổ chức, thư mục).\n *\n * ─ CONTROLLED ─\n * Dữ liệu và thứ tự là của app. Mọi lần đổi chỗ đi ra qua MỘT callback `onMove` (cha mới + vị trí\n * mới), kể cả khi nó đến từ kéo thả hay từ phím; `moveTreeItems` áp nó lên danh sách phẳng.\n *\n * ─ BÀN PHÍM ─ (một điểm dừng Tab — mục đang focus; mũi tên theo mẫu Treeview của W3C)\n * ↑ ↓ — chuyển mục · → — mở nhánh / xuống con đầu · ← — thu nhánh / lên cha · Home End\n * Tab — thụt vào (thành con cuối của mục đứng trên) · Shift+Tab — lùi ra (đứng sau cha cũ)\n * Alt+↑ / Alt+↓ — đổi chỗ với anh em · Enter — `onItemOpen` · Shift+↑/↓, Ctrl+A — chọn\n * Tab chỉ bị giữ lại khi thật sự thụt được; ở mục đầu tiên của một cấp nó đi tiếp ra ngoài như\n * thường — cây không thành cái bẫy bàn phím.\n */\nexport function TreeView<T extends TreeViewItem>({\n items,\n expandedIds,\n defaultExpandedIds,\n onExpandedIdsChange,\n selectedIds,\n defaultSelectedIds,\n onSelectedIdsChange,\n onMove,\n onItemOpen,\n columns,\n numbering = false,\n renderItem,\n rowHeight: rowHeightProp,\n indent = 20,\n readOnly = false,\n labels,\n className,\n \"aria-label\": ariaLabel,\n ...props\n}: TreeViewProps<T>) {\n const t = useComitorLabels(\"treeView\", labels);\n const { locale } = useComitorLocale();\n const coarse = useCoarsePointer();\n const rowHeight = rowHeightProp ?? (coarse ? 44 : 32);\n const editable = !readOnly && !!onMove;\n\n const [expanded, setExpanded] = useSemiControlled(expandedIds, defaultExpandedIds, onExpandedIdsChange);\n const [selected, setSelected] = useSemiControlled(selectedIds, defaultSelectedIds, onSelectedIdsChange);\n\n // ── Dữ liệu ──────────────────────────────────────────────────────────────────────────────────────\n const children = React.useMemo(() => groupTreeChildren(items), [items]);\n const byId = React.useMemo(() => new Map(items.map((item) => [item.id, item])), [items]);\n const numbers = React.useMemo(() => (numbering ? computeTreeNumbering(items) : null), [numbering, items]);\n const rollups = React.useMemo(\n () => (columns ?? []).map((column) => (column.value ? computeTreeRollup(items, column) : null)),\n [columns, items]\n );\n const numberFormat = React.useMemo(() => new Intl.NumberFormat(locale, { maximumFractionDigits: 1 }), [locale]);\n\n // Headless Tree đọc dữ liệu qua `dataLoader` — đi qua ref để loader ổn định giữa các lần render.\n const dataRef = React.useRef({ children, byId });\n dataRef.current = { children, byId };\n const dataLoader = React.useMemo(\n () => ({\n getItem: (id: string) => dataRef.current.byId.get(id) ?? ({ id, parentId: null, name: \"\" } as unknown as T),\n getChildren: (id: string) =>\n (dataRef.current.children.get(id === ROOT_ID ? null : id) ?? []).map((child) => child.id)\n }),\n []\n );\n\n const isFolder = (id: string) => (children.get(id)?.length ?? 0) > 0 || !!byId.get(id)?.isFolder;\n\n // ── Lời xướng + chuyển chỗ ───────────────────────────────────────────────────────────────────────\n const [announcement, setAnnouncement] = React.useState(\"\");\n const pendingFocusRef = React.useRef<string | null>(null);\n\n const emitMove = (move: TreeViewMove) => {\n if (!onMove) return;\n const first = byId.get(move.ids[0] ?? \"\");\n const remaining = (children.get(move.parentId) ?? []).filter((item) => !move.ids.includes(item.id));\n const total = remaining.length + move.ids.length;\n const position = Math.min(move.index, remaining.length) + 1;\n onMove(move);\n if (move.parentId) setExpanded((old) => (old.includes(move.parentId!) ? old : [...old, move.parentId!]));\n if (first) {\n const sameParent = move.ids.length === 1 && first.parentId === move.parentId;\n setAnnouncement(\n sameParent\n ? t.movedTo(first.name, position, total)\n : t.movedInto(first.name, move.parentId ? (byId.get(move.parentId)?.name ?? t.root) : t.root, position, total)\n );\n pendingFocusRef.current = first.id;\n }\n };\n\n const siblingsOf = (item: T) =>\n children.get(item.parentId != null && byId.has(item.parentId) ? item.parentId : null) ?? [];\n const canMoveItem = (id: string | undefined): id is string =>\n !!id && id !== ROOT_ID && editable && !byId.get(id)?.readOnly;\n\n const outline = {\n canIndent: (id: string) => {\n const item = byId.get(id);\n return !!item && canMoveItem(id) && siblingsOf(item).indexOf(item) > 0;\n },\n indent: (id: string) => {\n const item = byId.get(id);\n if (!item) return;\n const siblings = siblingsOf(item);\n const prev = siblings[siblings.indexOf(item) - 1];\n if (!prev) return;\n emitMove({ ids: [id], parentId: prev.id, index: children.get(prev.id)?.length ?? 0, kind: \"indent\" });\n },\n canOutdent: (id: string) => {\n const item = byId.get(id);\n return !!item && canMoveItem(id) && item.parentId != null && byId.has(item.parentId);\n },\n outdent: (id: string) => {\n const item = byId.get(id);\n const parent = item?.parentId != null ? byId.get(item.parentId) : undefined;\n if (!item || !parent) return;\n const grand = parent.parentId != null && byId.has(parent.parentId) ? parent.parentId : null;\n const index = (children.get(grand) ?? []).indexOf(parent) + 1;\n emitMove({ ids: [id], parentId: grand, index, kind: \"outdent\" });\n },\n canShift: (id: string, direction: -1 | 1) => {\n const item = byId.get(id);\n if (!item || !canMoveItem(id)) return false;\n const siblings = siblingsOf(item);\n const index = siblings.indexOf(item) + direction;\n return index >= 0 && index < siblings.length;\n },\n shift: (id: string, direction: -1 | 1) => {\n const item = byId.get(id);\n if (!item) return;\n const index = siblingsOf(item).indexOf(item) + direction;\n emitMove({\n ids: [id],\n parentId: siblingsOf(item) === children.get(null) ? null : item.parentId,\n index,\n kind: direction < 0 ? \"move-up\" : \"move-down\"\n });\n }\n };\n\n const onDrop = (dragged: ItemInstance<T>[], target: DragTarget<T>) => {\n const ids = dragged.map((item) => item.getId());\n const targetId = target.item.getId();\n const parentId = targetId === ROOT_ID ? null : targetId;\n const index = isOrderedDragTarget(target)\n ? target.insertionIndex\n : (children.get(parentId) ?? []).filter((item) => !ids.includes(item.id)).length;\n emitMove({ ids, parentId, index, kind: \"drag\" });\n };\n\n // ── Ảo hoá ───────────────────────────────────────────────────────────────────────────────────────\n const scrollRef = React.useRef<HTMLDivElement>(null);\n const headerHeight = columns?.length ? 32 : 0;\n const virtualizerRef = React.useRef<ReturnType<typeof useVirtualizer<HTMLDivElement, Element>> | null>(null);\n\n const tree: TreeInstance<T> = useTree<T>({\n rootItemId: ROOT_ID,\n dataLoader,\n getItemName: (item) => item.getItemData()?.name ?? \"\",\n isItemFolder: (item) => isFolder(item.getId()),\n state: { expandedItems: expanded, selectedItems: selected },\n setExpandedItems: setExpanded,\n setSelectedItems: setSelected,\n indent,\n canReorder: editable,\n canDrag: (dragged) => editable && dragged.every((item) => !item.getItemData()?.readOnly),\n // Chỉ NHÁNH nhận thả vào trong (gốc là nhánh) — đúng mặc định `target.item.isFolder()` của Headless\n // Tree, mà khai `canDrop` là đè mất. Lá chỉ nhận thả trước/sau; biến lá thành nhánh là `Tab` hoặc\n // `isFolder` (docs/tree-view.md §6). 3.12.0 viết `() => editable`: thả giữa một lá là lồng vào nó.\n canDrop: (_, target) => editable && target.item.isFolder(),\n onDrop,\n scrollToItem: (item) => virtualizerRef.current?.scrollToIndex(item.getItemMeta().index, { align: \"auto\" }),\n features: FEATURES\n });\n\n /*\n * Phím dàn ý + Enter tự xử lý ở pha CAPTURE, KHÔNG đăng ký làm hotkey của Headless Tree: bộ\n * hotkey của nó khớp tổ hợp bằng cách tự đếm `keydown` của từng phím đang giữ, nên Shift/Alt nhấn\n * TRƯỚC khi focus vào cây (hoặc sự kiện không kèm `keydown` riêng của phím bổ trợ) là tổ hợp hụt —\n * đo ở harness: Shift+Tab rơi về Tab trần, Alt+↓ thành ↓ (chuyển mục thay vì dời mục). Đọc cờ\n * `shiftKey`/`altKey` của chính sự kiện thì không có trạng thái nào để lệch. React chạy capture ở\n * gốc, trước listener của Headless Tree trên khung cây, nên `stopPropagation` chặn được nó.\n */\n const onKeyDownCapture = (event: React.KeyboardEvent) => {\n if ((event.target as HTMLElement).getAttribute(\"role\") !== \"treeitem\") return;\n if (event.ctrlKey || event.metaKey) return;\n const id = tree.getFocusedItem().getId();\n const run = (action: () => void) => {\n event.preventDefault();\n event.stopPropagation();\n action();\n };\n if (event.key === \"Tab\" && !event.altKey) {\n if (event.shiftKey ? outline.canOutdent(id) : outline.canIndent(id)) {\n run(() => (event.shiftKey ? outline.outdent(id) : outline.indent(id)));\n }\n return;\n }\n if (editable && event.altKey && !event.shiftKey && (event.key === \"ArrowUp\" || event.key === \"ArrowDown\")) {\n const direction = event.key === \"ArrowUp\" ? -1 : 1;\n // Không dời được (đầu/cuối hàng anh em) vẫn nuốt phím: để rơi xuống thì Alt+↓ thành ↓ trần —\n // focus nhảy đi, người dùng tưởng mục đã dời.\n run(() => {\n if (outline.canShift(id, direction)) outline.shift(id, direction);\n });\n return;\n }\n if (event.key === \"Enter\" && !event.shiftKey && !event.altKey && onItemOpen) {\n const data = byId.get(id);\n if (data) run(() => onItemOpen(data));\n }\n };\n\n // Dữ liệu đổi (sau một lần chuyển chỗ, hoặc app nạp thêm) → dựng lại cây, rồi trả focus về mục\n // vừa chuyển: mục đổi cha là một phần tử mới trong DOM, focus cũ đã rơi khỏi cây.\n // biome-ignore lint/correctness/useExhaustiveDependencies: chỉ chạy khi DỮ LIỆU đổi\n React.useEffect(() => {\n tree.rebuildTree();\n const id = pendingFocusRef.current;\n if (id) {\n pendingFocusRef.current = null;\n tree.getItemInstance(id)?.setFocused();\n tree.updateDomFocus();\n }\n }, [items]);\n\n const treeItems = tree.getItems();\n const virtualizer = useVirtualizer({\n count: treeItems.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => rowHeight,\n overscan: 10,\n scrollMargin: headerHeight\n });\n virtualizerRef.current = virtualizer;\n // biome-ignore lint/correctness/useExhaustiveDependencies: đo lại khi cỡ dòng đổi (chạm ⇄ chuột)\n React.useEffect(() => {\n virtualizer.measure();\n }, [virtualizer, rowHeight]);\n\n const instructionsId = React.useId();\n\n const columnText = (column: TreeViewColumn<T>, index: number, item: T): string | null => {\n const value = rollups[index]?.get(item.id);\n if (value == null) return null;\n return column.formatText ? column.formatText(value, item) : numberFormat.format(value);\n };\n\n return (\n <div\n data-slot=\"tree-view\"\n className={cn(\"flex min-h-0 flex-col overflow-hidden rounded-lg border bg-card text-card-foreground\", className)}\n {...props}\n >\n <div ref={scrollRef} className=\"relative min-h-0 flex-1 overflow-auto overscroll-contain\">\n {columns && columns.length > 0 && (\n // Tiêu đề cột là của MẮT: cây ARIA không có hàng tiêu đề, nên giá trị cột đi vào tên của\n // từng mục (\"Thiết kế, Ước lượng: 12\").\n <div\n aria-hidden=\"true\"\n data-slot=\"tree-view-header\"\n className=\"sticky top-0 z-10 flex items-center gap-2 border-b bg-card pe-3 font-medium text-muted-foreground text-xs\"\n style={{ height: headerHeight, paddingInlineStart: 8 + 20 }}\n >\n <div className=\"min-w-0 flex-1 truncate\">{t.nameHeader}</div>\n {columns.map((column) => (\n <div\n key={column.id}\n className={cn(\"shrink-0 truncate\", column.align === \"start\" ? \"text-start\" : \"text-end\")}\n style={{ width: column.width ?? 96 }}\n >\n {column.header}\n </div>\n ))}\n </div>\n )}\n\n <div\n {...tree.getContainerProps(ariaLabel ?? t.label)}\n aria-describedby={editable ? instructionsId : undefined}\n className=\"relative outline-hidden\"\n onKeyDownCapture={onKeyDownCapture}\n style={{ height: virtualizer.getTotalSize() }}\n >\n {virtualizer.getVirtualItems().map((virtualItem) => {\n const item = treeItems[virtualItem.index];\n if (!item) return null;\n const data = item.getItemData();\n if (!data) return null;\n const meta = item.getItemMeta();\n const folder = item.isFolder();\n const isExpanded = folder && item.isExpanded();\n const number = numbers?.get(data.id) ?? \"\";\n const itemProps = item.getProps();\n const label = [\n number ? `${number} ${data.name}` : data.name,\n ...(columns ?? []).flatMap((column, index) => {\n const text = columnText(column, index, data);\n return text != null && typeof column.header === \"string\" ? [`${column.header}: ${text}`] : [];\n })\n ].join(\", \");\n\n return (\n <div\n {...itemProps}\n key={item.getKey()}\n // Lặp lại hai thuộc tính Headless Tree đã rải — để biome đọc được vai trò của thẻ.\n role=\"treeitem\"\n tabIndex={item.isFocused() ? 0 : -1}\n aria-label={label}\n data-slot=\"tree-view-item\"\n data-folder={folder || undefined}\n className={cn(\n \"absolute inset-x-0 flex cursor-default select-none items-center gap-2 pe-3 text-foreground text-sm outline-hidden\",\n \"hover:bg-muted focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-ring\",\n item.isSelected() && \"bg-accent text-accent-foreground hover:bg-accent\",\n item.isDragTarget() && \"bg-accent\"\n )}\n style={{\n top: virtualItem.start - headerHeight,\n height: rowHeight,\n paddingInlineStart: 8 + meta.level * indent\n }}\n onDoubleClick={() => onItemOpen?.(data)}\n >\n <span\n aria-hidden=\"true\"\n className=\"flex size-5 shrink-0 items-center justify-center text-muted-foreground\"\n >\n {folder && (\n <ChevronRight\n className={cn(\n \"size-3.5 transition-transform rtl:rotate-180\",\n isExpanded && \"rotate-90 rtl:rotate-90\"\n )}\n />\n )}\n </span>\n {number && (\n <span aria-hidden=\"true\" className=\"shrink-0 text-muted-foreground text-xs tabular-nums\">\n {number}\n </span>\n )}\n <span aria-hidden=\"true\" className={cn(\"min-w-0 flex-1 truncate\", folder && \"font-medium\")}>\n {renderItem\n ? renderItem(data, { level: meta.level, expanded: isExpanded, folder, number })\n : data.name}\n </span>\n {columns?.map((column, index) => {\n const value = rollups[index]?.get(data.id);\n const rolledUp = !!column.rollup && (children.get(data.id)?.length ?? 0) > 0;\n return (\n <span\n key={column.id}\n aria-hidden=\"true\"\n className={cn(\n \"shrink-0 truncate tabular-nums\",\n column.align === \"start\" ? \"text-start\" : \"text-end\",\n rolledUp ? \"font-medium\" : \"text-muted-foreground\"\n )}\n style={{ width: column.width ?? 96 }}\n >\n {column.render\n ? column.render(data)\n : value == null\n ? null\n : column.format\n ? column.format(value, data, { rolledUp })\n : numberFormat.format(value)}\n </span>\n );\n })}\n </div>\n );\n })}\n <div\n aria-hidden=\"true\"\n data-slot=\"tree-view-drag-line\"\n className=\"pointer-events-none -mt-px h-0.5 rounded-full bg-primary-ink\"\n style={tree.getDragLineStyle()}\n />\n </div>\n </div>\n\n {editable && (\n <p id={instructionsId} className=\"sr-only\">\n {t.instructions}\n </p>\n )}\n <div role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -3,7 +3,7 @@ import { VariantProps } from 'class-variance-authority';
3
3
  import * as React from 'react';
4
4
 
5
5
  declare const badgeVariants: (props?: ({
6
- variant?: "default" | "destructive" | "warning" | "success" | "primary" | "secondary" | "outline" | null | undefined;
6
+ variant?: "primary" | "default" | "destructive" | "warning" | "success" | "secondary" | "outline" | null | undefined;
7
7
  size?: "sm" | "md" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {
@@ -3,7 +3,7 @@ import { VariantProps } from 'class-variance-authority';
3
3
  import * as React from 'react';
4
4
 
5
5
  declare const buttonVariants: (props?: ({
6
- variant?: "link" | "default" | "destructive" | "primary" | "secondary" | "outline" | "ghost" | null | undefined;
6
+ variant?: "primary" | "link" | "default" | "destructive" | "secondary" | "outline" | "ghost" | null | undefined;
7
7
  size?: "default" | "sm" | "md" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface ButtonProps extends React.ComponentProps<"button">, VariantProps<typeof buttonVariants> {
@@ -1,6 +1,6 @@
1
1
  import { Editor } from '@tiptap/core';
2
2
  import * as React from 'react';
3
- import { f as EditorFormat } from '../editor-types-CSrMeuSw.js';
3
+ import { g as EditorFormat } from '../editor-types-BacXD2VN.js';
4
4
  import { MarkdownEditorLabels } from './markdown-editor-constants.js';
5
5
  import '../components/composite/empty-state.js';
6
6
 
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { g as EditorBaseProps, f as EditorFormat, a as EditorToolbarMode, E as EditorHandleBase } from '../editor-types-CSrMeuSw.js';
2
+ import { f as EditorBaseProps, g as EditorFormat, a as EditorToolbarMode, E as EditorHandleBase } from '../editor-types-BacXD2VN.js';
3
3
  import '@tiptap/core';
4
4
  import '../components/composite/empty-state.js';
5
5
  import './markdown-editor-constants.js';
@@ -24,6 +24,6 @@ interface EditorCoreProps<THandle> extends EditorBaseProps {
24
24
  */
25
25
  createHandle: (core: EditorCoreHandle) => THandle;
26
26
  }
27
- declare function EditorCore<THandle>({ format, toolbar, value, defaultValue, onChange, onSubmit, onFocus, onBlur, placeholder, editable, autoFocus, variant, mentions, onImageUpload, onImageUploadError, resolveImageSrc, extensions: extraExtensions, labels: labelsProp, name, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, className, contentClassName, slot, handleRef, createHandle }: EditorCoreProps<THandle>): React.JSX.Element;
27
+ declare function EditorCore<THandle>({ format, toolbar, value, defaultValue, onChange, onSubmit, submitOnEnter, onFocus, onBlur, placeholder, editable, autoFocus, variant, mentions, onImageUpload, onImageUploadError, resolveImageSrc, extensions: extraExtensions, labels: labelsProp, name, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, className, contentClassName, slot, handleRef, createHandle }: EditorCoreProps<THandle>): React.JSX.Element;
28
28
 
29
29
  export { EditorCore, type EditorCoreHandle, type EditorCoreProps };
@@ -51,6 +51,7 @@ function EditorCore({
51
51
  defaultValue,
52
52
  onChange,
53
53
  onSubmit,
54
+ submitOnEnter = false,
54
55
  onFocus,
55
56
  onBlur,
56
57
  placeholder,
@@ -107,6 +108,11 @@ function EditorCore({
107
108
  if (!onSubmit) return false;
108
109
  onSubmit();
109
110
  return true;
111
+ },
112
+ onEnterShortcut: () => {
113
+ if (!submitOnEnter || !onSubmit || slashStore.getSnapshot() || mentionStore.getSnapshot()) return false;
114
+ onSubmit();
115
+ return true;
110
116
  }
111
117
  });
112
118
  const initialValue = value ?? defaultValue ?? "";