@4399ywkf/editor 0.3.1 → 0.4.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.
@@ -1,13 +1,12 @@
1
+ import { useTiptapEditor, isExtensionAvailable, isNodeInSchema, Button, cn, getSelectionBoundingRect, isSelectionValid, getSelectedNodesOfType, selectCurrentBlockContent, Popover, PopoverTrigger, PopoverContent, isValidPosition, updateNodesAttr, parseShortcutKeys, isMarkInSchema, isNodeTypeSelected, SR_ONLY, sanitizeUrl, selectionWithinConvertibleTypes, getSelectedBlockNodes, findNodePosition, Card, CardBody, CardItemGroup, Input, clamp, focusNextNode, getAvatar, getUrlParam, handleImageUpload, getNodeDisplayName, isTextSelectionValid, AIButton, CardGroupLabel, getElementOverflowPosition } from './chunk-GSBPP62I.js';
1
2
  import * as React from 'react';
2
- import { createContext, forwardRef, isValidElement, version, cloneElement, useMemo, memo, useState, useCallback, useRef, useEffect, useLayoutEffect, useContext, Fragment as Fragment$2, Children } from 'react';
3
+ import { createContext, memo, forwardRef, useState, useCallback, useRef, useEffect, useMemo, useLayoutEffect, useContext, Children, isValidElement, cloneElement } from 'react';
3
4
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
4
- import { Node, mergeAttributes, ReactNodeViewRenderer, Extension as Extension$1, NodeViewWrapper, NodeViewContent, useCurrentEditor, useEditorState, isNodeSelection, posToDOMRect, isTextSelection, findParentNodeClosestToPos, EditorContext, EditorContent, useEditor } from '@tiptap/react';
5
- import { PluginKey, Plugin, TextSelection, Selection, NodeSelection, AllSelection } from '@tiptap/pm/state';
6
- import { columnResizing, tableEditing, cellAround, CellSelection, TableView, moveTableRow, moveTableColumn, TableMap, findTable, mergeCells, splitCell, selectedRect, deleteCellSelection, selectionCell, isInTable, columnResizingPluginKey, deleteRow, deleteColumn, toggleHeader, addRowBefore, addRowAfter, addColumnBefore, addColumnAfter, rowIsHeader, columnIsHeader } from '@tiptap/pm/tables';
5
+ import { PluginKey, Plugin, TextSelection, Selection, NodeSelection } from '@tiptap/pm/state';
6
+ import { Node, mergeAttributes, ReactNodeViewRenderer, Extension as Extension$1, NodeViewWrapper, NodeViewContent, useEditorState, EditorContext, EditorContent, useEditor, isNodeSelection } from '@tiptap/react';
7
7
  import { Extension, Node as Node$1, mergeAttributes as mergeAttributes$1 } from '@tiptap/core';
8
- import { useMergeRefs, FloatingPortal, shift, flip, offset, FloatingDelayGroup, useFloating, autoUpdate, useTransitionStyles, useDismiss, useInteractions, useHover, useFocus, useRole, size } from '@floating-ui/react';
9
8
  import { Fragment, Slice } from '@tiptap/pm/model';
10
- import * as PopoverPrimitive from '@radix-ui/react-popover';
9
+ import { shift, flip, offset, useMergeRefs, useFloating, autoUpdate, useTransitionStyles, useDismiss, useInteractions, FloatingPortal, size } from '@floating-ui/react';
11
10
  import { Doc } from 'yjs';
12
11
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
13
12
  import throttle from 'lodash.throttle';
@@ -34,6 +33,7 @@ import TiptapHorizontalRule from '@tiptap/extension-horizontal-rule';
34
33
  import { Image as Image$1 } from '@tiptap/extension-image';
35
34
  import { Table } from '@tiptap/extension-table/table';
36
35
  import { TableCell, TableHeader, TableRow } from '@tiptap/extension-table';
36
+ import { columnResizing, tableEditing, cellAround, TableView, CellSelection, moveTableRow, moveTableColumn, TableMap, findTable, mergeCells, splitCell, selectedRect, deleteCellSelection, selectionCell, isInTable, columnResizingPluginKey, deleteRow, deleteColumn, toggleHeader, addRowBefore, addRowAfter, addColumnBefore, addColumnAfter, rowIsHeader, columnIsHeader } from '@tiptap/pm/tables';
37
37
  import { canJoin, Mapping } from '@tiptap/pm/transform';
38
38
  import { Decoration, DecorationSet } from '@tiptap/pm/view';
39
39
  import * as Ariakit2 from '@ariakit/react';
@@ -44,7 +44,6 @@ import { cva } from 'class-variance-authority';
44
44
  import { SuggestionPluginKey, Suggestion } from '@tiptap/suggestion';
45
45
  import { DragHandle } from '@tiptap/extension-drag-handle-react';
46
46
 
47
- // src/contexts/editor-config-context.tsx
48
47
  var DEFAULT_MAX_FILE_SIZES = {
49
48
  image: 5 * 1024 * 1024,
50
49
  video: 100 * 1024 * 1024,
@@ -74,391 +73,6 @@ function EditorConfigProvider({
74
73
  return /* @__PURE__ */ jsx(EditorConfigContext.Provider, { value, children });
75
74
  }
76
75
  var useEditorConfig = () => useContext(EditorConfigContext);
77
- function getActivePageEditor(editor) {
78
- const storage = editor.storage;
79
- const pages = storage.pages;
80
- if (!pages || !("activeEditor" in pages)) return null;
81
- return pages.activeEditor ?? null;
82
- }
83
- function useTiptapEditor(providedEditor) {
84
- const { editor: coreEditor } = useCurrentEditor();
85
- const mainEditor = providedEditor ?? coreEditor;
86
- const [storageEditor, setStorageEditor] = useState(null);
87
- useEffect(() => {
88
- if (!mainEditor) {
89
- setStorageEditor(null);
90
- return;
91
- }
92
- const updateHandler = () => setStorageEditor(getActivePageEditor(mainEditor));
93
- updateHandler();
94
- mainEditor.on("update", updateHandler);
95
- mainEditor.on("selectionUpdate", updateHandler);
96
- return () => {
97
- mainEditor.off("update", updateHandler);
98
- mainEditor.off("selectionUpdate", updateHandler);
99
- };
100
- }, [mainEditor]);
101
- useEffect(() => {
102
- if (!storageEditor) return;
103
- const handleDestroy = () => setStorageEditor(null);
104
- storageEditor.on("destroy", handleDestroy);
105
- return () => {
106
- storageEditor.off("destroy", handleDestroy);
107
- };
108
- }, [storageEditor]);
109
- const editorState = useEditorState({
110
- editor: storageEditor ?? mainEditor,
111
- selector(context) {
112
- if (!context.editor) {
113
- return { editor: null, editorState: void 0, canCommand: void 0 };
114
- }
115
- return {
116
- editor: context.editor,
117
- editorState: context.editor.state,
118
- canCommand: context.editor.can
119
- };
120
- }
121
- });
122
- return editorState ?? { editor: null };
123
- }
124
- var MAX_FILE_SIZE = 5 * 1024 * 1024;
125
- var MAC_SYMBOLS = {
126
- mod: "⌘",
127
- command: "⌘",
128
- meta: "⌘",
129
- ctrl: "⌃",
130
- control: "⌃",
131
- alt: "⌥",
132
- option: "⌥",
133
- shift: "⇧",
134
- backspace: "Del",
135
- delete: "⌦",
136
- enter: "⏎",
137
- escape: "⎋",
138
- capslock: "⇪"
139
- };
140
- var SR_ONLY = {
141
- position: "absolute",
142
- width: "1px",
143
- height: "1px",
144
- padding: 0,
145
- margin: "-1px",
146
- overflow: "hidden",
147
- clip: "rect(0, 0, 0, 0)",
148
- whiteSpace: "nowrap",
149
- borderWidth: 0
150
- };
151
- function cn(...classes) {
152
- return classes.filter(Boolean).join(" ");
153
- }
154
- function isMac() {
155
- return typeof navigator !== "undefined" && navigator.platform.toLowerCase().includes("mac");
156
- }
157
- var formatShortcutKey = (key, isMac2, capitalize = true) => {
158
- if (isMac2) {
159
- const lowerKey = key.toLowerCase();
160
- return MAC_SYMBOLS[lowerKey] || (capitalize ? key.toUpperCase() : key);
161
- }
162
- return capitalize ? key.charAt(0).toUpperCase() + key.slice(1) : key;
163
- };
164
- var parseShortcutKeys = (props) => {
165
- const { shortcutKeys, delimiter = "+", capitalize = true } = props;
166
- if (!shortcutKeys) return [];
167
- return shortcutKeys.split(delimiter).map((key) => key.trim()).map((key) => formatShortcutKey(key, isMac(), capitalize));
168
- };
169
- var isMarkInSchema = (markName, editor) => {
170
- if (!editor?.schema) return false;
171
- return editor.schema.spec.marks.get(markName) !== void 0;
172
- };
173
- var isNodeInSchema = (nodeName, editor) => {
174
- if (!editor?.schema) return false;
175
- return editor.schema.spec.nodes.get(nodeName) !== void 0;
176
- };
177
- function focusNextNode(editor) {
178
- const { state, view } = editor;
179
- const { doc, selection } = state;
180
- const nextSel = Selection.findFrom(selection.$to, 1, true);
181
- if (nextSel) {
182
- view.dispatch(state.tr.setSelection(nextSel).scrollIntoView());
183
- return true;
184
- }
185
- const paragraphType = state.schema.nodes.paragraph;
186
- if (!paragraphType) {
187
- console.warn("No paragraph node type found in schema.");
188
- return false;
189
- }
190
- const end = doc.content.size;
191
- const para = paragraphType.create();
192
- let tr = state.tr.insert(end, para);
193
- const $inside = tr.doc.resolve(end + 1);
194
- tr = tr.setSelection(TextSelection.near($inside)).scrollIntoView();
195
- view.dispatch(tr);
196
- return true;
197
- }
198
- function isValidPosition(pos) {
199
- return typeof pos === "number" && pos >= 0;
200
- }
201
- function isExtensionAvailable(editor, extensionNames) {
202
- if (!editor) return false;
203
- const names = Array.isArray(extensionNames) ? extensionNames : [extensionNames];
204
- const found = names.some(
205
- (name) => editor.extensionManager.extensions.some((ext) => ext.name === name)
206
- );
207
- if (!found) {
208
- console.warn(
209
- `None of the extensions [${names.join(", ")}] were found in the editor schema. Ensure they are included in the editor configuration.`
210
- );
211
- }
212
- return found;
213
- }
214
- function findNodeAtPosition(editor, position) {
215
- try {
216
- const node = editor.state.doc.nodeAt(position);
217
- if (!node) {
218
- console.warn(`No node found at position ${position}`);
219
- return null;
220
- }
221
- return node;
222
- } catch (error) {
223
- console.error(`Error getting node at position ${position}:`, error);
224
- return null;
225
- }
226
- }
227
- function findNodePosition(props) {
228
- const { editor, node, nodePos } = props;
229
- if (!editor || !editor.state?.doc) return null;
230
- const hasValidNode = node !== void 0 && node !== null;
231
- const hasValidPos = isValidPosition(nodePos);
232
- if (!hasValidNode && !hasValidPos) {
233
- return null;
234
- }
235
- if (hasValidNode) {
236
- let foundPos = -1;
237
- let foundNode = null;
238
- editor.state.doc.descendants((currentNode, pos) => {
239
- if (currentNode === node) {
240
- foundPos = pos;
241
- foundNode = currentNode;
242
- return false;
243
- }
244
- return true;
245
- });
246
- if (foundPos !== -1 && foundNode !== null) {
247
- return { pos: foundPos, node: foundNode };
248
- }
249
- }
250
- if (hasValidPos) {
251
- const nodeAtPos = findNodeAtPosition(editor, nodePos);
252
- if (nodeAtPos) {
253
- return { pos: nodePos, node: nodeAtPos };
254
- }
255
- }
256
- return null;
257
- }
258
- function isNodeTypeSelected(editor, nodeTypeNames = [], checkAncestorNodes = false) {
259
- if (!editor || !editor.state.selection) return false;
260
- const { selection } = editor.state;
261
- if (selection.empty) return false;
262
- if (selection instanceof NodeSelection) {
263
- const selectedNode = selection.node;
264
- return selectedNode ? nodeTypeNames.includes(selectedNode.type.name) : false;
265
- }
266
- if (checkAncestorNodes) {
267
- const { $from } = selection;
268
- for (let depth = $from.depth; depth > 0; depth--) {
269
- const ancestorNode = $from.node(depth);
270
- if (nodeTypeNames.includes(ancestorNode.type.name)) {
271
- return true;
272
- }
273
- }
274
- }
275
- return false;
276
- }
277
- function selectionWithinConvertibleTypes(editor, types = []) {
278
- if (!editor || types.length === 0) return false;
279
- const { state } = editor;
280
- const { selection } = state;
281
- const allowed = new Set(types);
282
- if (selection instanceof NodeSelection) {
283
- const nodeType = selection.node?.type?.name;
284
- return !!nodeType && allowed.has(nodeType);
285
- }
286
- if (selection instanceof TextSelection || selection instanceof AllSelection) {
287
- let valid = true;
288
- state.doc.nodesBetween(selection.from, selection.to, (node) => {
289
- if (node.isTextblock && !allowed.has(node.type.name)) {
290
- valid = false;
291
- return false;
292
- }
293
- return valid;
294
- });
295
- return valid;
296
- }
297
- return false;
298
- }
299
- var handleImageUpload = async (file, onProgress, abortSignal) => {
300
- if (!file) {
301
- throw new Error("No file provided");
302
- }
303
- if (file.size > MAX_FILE_SIZE) {
304
- throw new Error(
305
- `File size exceeds maximum allowed (${MAX_FILE_SIZE / (1024 * 1024)}MB)`
306
- );
307
- }
308
- for (let progress = 0; progress <= 100; progress += 10) {
309
- if (abortSignal?.aborted) {
310
- throw new Error("Upload cancelled");
311
- }
312
- await new Promise((resolve) => setTimeout(resolve, 500));
313
- onProgress?.({ progress });
314
- }
315
- return "/images/tiptap-ui-placeholder-image.jpg";
316
- };
317
- var ATTR_WHITESPACE = (
318
- // eslint-disable-next-line no-control-regex
319
- /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
320
- );
321
- function isAllowedUri(uri, protocols) {
322
- const allowedProtocols = [
323
- "http",
324
- "https",
325
- "ftp",
326
- "ftps",
327
- "mailto",
328
- "tel",
329
- "callto",
330
- "sms",
331
- "cid",
332
- "xmpp"
333
- ];
334
- if (protocols) {
335
- protocols.forEach((protocol) => {
336
- const nextProtocol = typeof protocol === "string" ? protocol : protocol.scheme;
337
- if (nextProtocol) {
338
- allowedProtocols.push(nextProtocol);
339
- }
340
- });
341
- }
342
- return !uri || uri.replace(ATTR_WHITESPACE, "").match(
343
- new RegExp(
344
- // eslint-disable-next-line no-useless-escape
345
- `^(?:(?:${allowedProtocols.join("|")}):|[^a-z]|[a-z0-9+.-]+(?:[^a-z+.-:]|$))`,
346
- "i"
347
- )
348
- );
349
- }
350
- function sanitizeUrl(inputUrl, baseUrl, protocols) {
351
- try {
352
- const url = new URL(inputUrl, baseUrl);
353
- if (isAllowedUri(url.href, protocols)) {
354
- return url.href;
355
- }
356
- } catch {
357
- }
358
- return "#";
359
- }
360
- function updateNodesAttr(tr, targets, attrName, next) {
361
- if (!targets.length) return false;
362
- let changed = false;
363
- for (const { pos } of targets) {
364
- const currentNode = tr.doc.nodeAt(pos);
365
- if (!currentNode) continue;
366
- const prevValue = currentNode.attrs[attrName];
367
- const resolvedNext = typeof next === "function" ? next(prevValue) : next;
368
- if (prevValue === resolvedNext) continue;
369
- const nextAttrs = { ...currentNode.attrs };
370
- if (resolvedNext === void 0) {
371
- delete nextAttrs[attrName];
372
- } else {
373
- nextAttrs[attrName] = resolvedNext;
374
- }
375
- tr.setNodeMarkup(pos, void 0, nextAttrs);
376
- changed = true;
377
- }
378
- return changed;
379
- }
380
- function selectCurrentBlockContent(editor) {
381
- const { selection, doc } = editor.state;
382
- if (!selection.empty) return;
383
- const $pos = selection.$from;
384
- let blockNode = null;
385
- let blockPos = -1;
386
- for (let depth = $pos.depth; depth >= 0; depth--) {
387
- const node = $pos.node(depth);
388
- const pos = $pos.start(depth);
389
- if (node.isBlock && node.textContent.trim()) {
390
- blockNode = node;
391
- blockPos = pos;
392
- break;
393
- }
394
- }
395
- if (blockNode && blockPos >= 0) {
396
- const from = blockPos;
397
- const to = blockPos + blockNode.nodeSize - 2;
398
- if (from < to) {
399
- const $from = doc.resolve(from);
400
- const $to = doc.resolve(to);
401
- const newSelection = TextSelection.between($from, $to, 1);
402
- if (newSelection && !selection.eq(newSelection)) {
403
- editor.view.dispatch(editor.state.tr.setSelection(newSelection));
404
- }
405
- }
406
- }
407
- }
408
- function getSelectedNodesOfType(selection, allowedNodeTypes) {
409
- const results = [];
410
- const allowed = new Set(allowedNodeTypes);
411
- if (selection instanceof CellSelection) {
412
- selection.forEachCell((node, pos) => {
413
- if (allowed.has(node.type.name)) {
414
- results.push({ node, pos });
415
- }
416
- });
417
- return results;
418
- }
419
- if (selection instanceof NodeSelection) {
420
- const { node, from: pos } = selection;
421
- if (node && allowed.has(node.type.name)) {
422
- results.push({ node, pos });
423
- }
424
- return results;
425
- }
426
- const { $anchor } = selection;
427
- const cell = cellAround($anchor);
428
- if (cell) {
429
- const cellNode = selection.$anchor.doc.nodeAt(cell.pos);
430
- if (cellNode && allowed.has(cellNode.type.name)) {
431
- results.push({ node: cellNode, pos: cell.pos });
432
- return results;
433
- }
434
- }
435
- const parentNode = findParentNodeClosestToPos(
436
- $anchor,
437
- (node) => allowed.has(node.type.name)
438
- );
439
- if (parentNode) {
440
- results.push({ node: parentNode.node, pos: parentNode.pos });
441
- }
442
- return results;
443
- }
444
- function clamp(value, min, max) {
445
- return Math.max(min, Math.min(value, max));
446
- }
447
- function getSelectedBlockNodes(editor) {
448
- const { doc } = editor.state;
449
- const { from, to } = editor.state.selection;
450
- const blocks = [];
451
- const seen = /* @__PURE__ */ new Set();
452
- doc.nodesBetween(from, to, (node, pos) => {
453
- if (!node.isBlock) return;
454
- if (!seen.has(pos)) {
455
- seen.add(pos);
456
- blocks.push(node);
457
- }
458
- return false;
459
- });
460
- return blocks;
461
- }
462
76
  function chunkArray(array, size4) {
463
77
  return Array.from(
464
78
  { length: Math.ceil(array.length / size4) },
@@ -655,202 +269,6 @@ var UiState = Extension.create({
655
269
  this.storage = { ...defaultUiState };
656
270
  }
657
271
  });
658
- function useTooltip({
659
- initialOpen = false,
660
- placement = "top",
661
- open: controlledOpen,
662
- onOpenChange: setControlledOpen,
663
- delay = 600,
664
- closeDelay = 0
665
- } = {}) {
666
- const [uncontrolledOpen, setUncontrolledOpen] = useState(initialOpen);
667
- const open = controlledOpen ?? uncontrolledOpen;
668
- const setOpen = setControlledOpen ?? setUncontrolledOpen;
669
- const data = useFloating({
670
- placement,
671
- open,
672
- onOpenChange: setOpen,
673
- whileElementsMounted: autoUpdate,
674
- middleware: [
675
- offset(4),
676
- flip({
677
- crossAxis: placement.includes("-"),
678
- fallbackAxisSideDirection: "start",
679
- padding: 4
680
- }),
681
- shift({ padding: 4 })
682
- ]
683
- });
684
- const context = data.context;
685
- const hover = useHover(context, {
686
- mouseOnly: true,
687
- move: false,
688
- restMs: delay,
689
- enabled: controlledOpen == null,
690
- delay: {
691
- close: closeDelay
692
- }
693
- });
694
- const focus = useFocus(context, {
695
- enabled: controlledOpen == null
696
- });
697
- const dismiss = useDismiss(context);
698
- const role = useRole(context, { role: "tooltip" });
699
- const interactions = useInteractions([hover, focus, dismiss, role]);
700
- return useMemo(
701
- () => ({
702
- open,
703
- setOpen,
704
- ...interactions,
705
- ...data
706
- }),
707
- [open, setOpen, interactions, data]
708
- );
709
- }
710
- var TooltipContext = createContext(null);
711
- function useTooltipContext() {
712
- const context = useContext(TooltipContext);
713
- if (context == null) {
714
- throw new Error("Tooltip components must be wrapped in <TooltipProvider />");
715
- }
716
- return context;
717
- }
718
- function Tooltip({ children, ...props }) {
719
- const tooltip = useTooltip(props);
720
- if (!props.useDelayGroup) {
721
- return /* @__PURE__ */ jsx(TooltipContext.Provider, { value: tooltip, children });
722
- }
723
- return /* @__PURE__ */ jsx(
724
- FloatingDelayGroup,
725
- {
726
- delay: { open: props.delay ?? 0, close: props.closeDelay ?? 0 },
727
- timeoutMs: props.timeout,
728
- children: /* @__PURE__ */ jsx(TooltipContext.Provider, { value: tooltip, children })
729
- }
730
- );
731
- }
732
- var TooltipTrigger = forwardRef(
733
- function TooltipTrigger2({ children, asChild = false, ...props }, propRef) {
734
- const context = useTooltipContext();
735
- const childrenRef = isValidElement(children) ? parseInt(version, 10) >= 19 ? (
736
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
737
- children.props.ref
738
- ) : (
739
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
740
- children.ref
741
- ) : void 0;
742
- const ref = useMergeRefs([context.refs.setReference, propRef, childrenRef]);
743
- if (asChild && isValidElement(children)) {
744
- const dataAttributes = {
745
- "data-tooltip-state": context.open ? "open" : "closed"
746
- };
747
- return cloneElement(
748
- children,
749
- context.getReferenceProps({
750
- ref,
751
- ...props,
752
- ...typeof children.props === "object" ? children.props : {},
753
- ...dataAttributes
754
- })
755
- );
756
- }
757
- return /* @__PURE__ */ jsx(
758
- "button",
759
- {
760
- ref,
761
- "data-tooltip-state": context.open ? "open" : "closed",
762
- ...context.getReferenceProps(props),
763
- children
764
- }
765
- );
766
- }
767
- );
768
- var TooltipContent = forwardRef(
769
- function TooltipContent2({ style, children, portal = true, portalProps = {}, ...props }, propRef) {
770
- const context = useTooltipContext();
771
- const ref = useMergeRefs([context.refs.setFloating, propRef]);
772
- if (!context.open) return null;
773
- const content = /* @__PURE__ */ jsx(
774
- "div",
775
- {
776
- ref,
777
- style: {
778
- ...context.floatingStyles,
779
- ...style
780
- },
781
- ...context.getFloatingProps(props),
782
- className: "tiptap-tooltip",
783
- children
784
- }
785
- );
786
- if (portal) {
787
- return /* @__PURE__ */ jsx(FloatingPortal, { ...portalProps, children: content });
788
- }
789
- return content;
790
- }
791
- );
792
- Tooltip.displayName = "Tooltip";
793
- TooltipTrigger.displayName = "TooltipTrigger";
794
- TooltipContent.displayName = "TooltipContent";
795
- var ShortcutDisplay = ({
796
- shortcuts
797
- }) => {
798
- if (shortcuts.length === 0) return null;
799
- return /* @__PURE__ */ jsx("div", { children: shortcuts.map((key, index) => /* @__PURE__ */ jsxs(Fragment$2, { children: [
800
- index > 0 && /* @__PURE__ */ jsx("kbd", { children: "+" }),
801
- /* @__PURE__ */ jsx("kbd", { children: key })
802
- ] }, index)) });
803
- };
804
- var Button = forwardRef(
805
- ({
806
- className,
807
- children,
808
- tooltip,
809
- showTooltip = true,
810
- shortcutKeys,
811
- variant,
812
- size: size4,
813
- ...props
814
- }, ref) => {
815
- const shortcuts = useMemo(
816
- () => parseShortcutKeys({ shortcutKeys }),
817
- [shortcutKeys]
818
- );
819
- if (!tooltip || !showTooltip) {
820
- return /* @__PURE__ */ jsx(
821
- "button",
822
- {
823
- "data-slot": "tiptap-button",
824
- className: cn("tiptap-button", className),
825
- ref,
826
- "data-style": variant,
827
- "data-size": size4,
828
- ...props,
829
- children
830
- }
831
- );
832
- }
833
- return /* @__PURE__ */ jsxs(Tooltip, { delay: 200, children: [
834
- /* @__PURE__ */ jsx(
835
- TooltipTrigger,
836
- {
837
- "data-slot": "tiptap-button",
838
- className: cn("tiptap-button", className),
839
- ref,
840
- "data-style": variant,
841
- "data-size": size4,
842
- ...props,
843
- children
844
- }
845
- ),
846
- /* @__PURE__ */ jsxs(TooltipContent, { children: [
847
- tooltip,
848
- /* @__PURE__ */ jsx(ShortcutDisplay, { shortcuts })
849
- ] })
850
- ] });
851
- }
852
- );
853
- Button.displayName = "Button";
854
272
  var Video = Node.create({
855
273
  name: "video",
856
274
  group: "block",
@@ -2156,32 +1574,6 @@ function useMenuNavigation({
2156
1574
  setSelectedIndex
2157
1575
  };
2158
1576
  }
2159
- function Popover({
2160
- ...props
2161
- }) {
2162
- return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { ...props });
2163
- }
2164
- function PopoverTrigger({
2165
- ...props
2166
- }) {
2167
- return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { ...props });
2168
- }
2169
- function PopoverContent({
2170
- className,
2171
- align = "center",
2172
- sideOffset = 4,
2173
- ...props
2174
- }) {
2175
- return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2176
- PopoverPrimitive.Content,
2177
- {
2178
- align,
2179
- sideOffset,
2180
- className: cn("tiptap-popover", className),
2181
- ...props
2182
- }
2183
- ) });
2184
- }
2185
1577
  function useFloatingElement(show, reference, zIndex, options, autoUpdateOptions) {
2186
1578
  const { dismissOptions, ...floatingOptions } = options || {};
2187
1579
  const { refs, context, floatingStyles } = useFloating({
@@ -2240,97 +1632,6 @@ function useFloatingElement(show, reference, zIndex, options, autoUpdateOptions)
2240
1632
  ]
2241
1633
  );
2242
1634
  }
2243
- var NODE_TYPE_LABELS = {
2244
- paragraph: "Text",
2245
- heading: "Heading",
2246
- blockquote: "Blockquote",
2247
- listItem: "List Item",
2248
- codeBlock: "Code Block",
2249
- table: "Table",
2250
- tocNode: "Table of contents"
2251
- };
2252
- var getUrlParam = (param) => {
2253
- if (typeof window === "undefined") return null;
2254
- const params = new URLSearchParams(window.location.search);
2255
- return params.get(param);
2256
- };
2257
- var getNodeDisplayName = (editor) => {
2258
- if (!editor) return "Node";
2259
- const { selection } = editor.state;
2260
- if (selection instanceof NodeSelection) {
2261
- const nodeType2 = selection.node.type.name;
2262
- return NODE_TYPE_LABELS[nodeType2] || nodeType2.toLowerCase();
2263
- }
2264
- if (selection instanceof CellSelection) {
2265
- return "Table";
2266
- }
2267
- const { $anchor } = selection;
2268
- const nodeType = $anchor.parent.type.name;
2269
- return NODE_TYPE_LABELS[nodeType] || nodeType.toLowerCase();
2270
- };
2271
- var removeEmptyParagraphs = (content) => ({
2272
- ...content,
2273
- content: content.content?.filter(
2274
- (node) => node.type !== "paragraph" || node.content?.some((child) => child.text?.trim() || child.type !== "text")
2275
- )
2276
- });
2277
- function getElementOverflowPosition(targetElement, containerElement) {
2278
- const targetBounds = targetElement.getBoundingClientRect();
2279
- const containerBounds = containerElement.getBoundingClientRect();
2280
- const isOverflowingTop = targetBounds.top < containerBounds.top;
2281
- const isOverflowingBottom = targetBounds.bottom > containerBounds.bottom;
2282
- if (isOverflowingTop && isOverflowingBottom) return "both";
2283
- if (isOverflowingTop) return "top";
2284
- if (isOverflowingBottom) return "bottom";
2285
- return "none";
2286
- }
2287
- var isSelectionValid = (editor, selection, excludedNodeTypes = ["imageUpload", "horizontalRule"]) => {
2288
- if (!editor) return false;
2289
- if (!selection) selection = editor.state.selection;
2290
- const { state } = editor;
2291
- const { doc } = state;
2292
- const { empty, from, to } = selection;
2293
- const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(selection);
2294
- const isCodeBlock = selection.$from.parent.type.spec.code || isNodeSelection(selection) && selection.node.type.spec.code;
2295
- const isExcludedNode = isNodeSelection(selection) && excludedNodeTypes.includes(selection.node.type.name);
2296
- const isTableCell = selection instanceof CellSelection;
2297
- return !empty && !isEmptyTextBlock && !isCodeBlock && !isExcludedNode && !isTableCell;
2298
- };
2299
- var isTextSelectionValid = (editor) => {
2300
- if (!editor) return false;
2301
- const { state } = editor;
2302
- const { selection } = state;
2303
- const isValid = isTextSelection(selection) && !selection.empty && !selection.$from.parent.type.spec.code && !isNodeSelection(selection);
2304
- return isValid;
2305
- };
2306
- var getSelectionBoundingRect = (editor) => {
2307
- const { state } = editor.view;
2308
- const { selection } = state;
2309
- const { ranges } = selection;
2310
- const from = Math.min(...ranges.map((range) => range.$from.pos));
2311
- const to = Math.max(...ranges.map((range) => range.$to.pos));
2312
- if (isNodeSelection(selection)) {
2313
- const node = editor.view.nodeDOM(from);
2314
- if (node) {
2315
- return node.getBoundingClientRect();
2316
- }
2317
- }
2318
- return posToDOMRect(editor.view, from, to);
2319
- };
2320
- var getAvatar = (name) => {
2321
- if (!name) {
2322
- return "/avatars/memoji_01.png";
2323
- }
2324
- let hash = 0;
2325
- for (let i = 0; i < name.length; i++) {
2326
- hash = name.charCodeAt(i) + ((hash << 5) - hash);
2327
- hash = hash & hash;
2328
- }
2329
- const randomFraction = Math.abs(hash) % 1e6 / 1e6;
2330
- const id = 1 + Math.floor(randomFraction * 20);
2331
- const idString = id.toString().padStart(2, "0");
2332
- return `/avatars/memoji_${idString}.png`;
2333
- };
2334
1635
 
2335
1636
  // src/lib/file-picker.ts
2336
1637
  function pickFile(accept, multiple = false) {
@@ -6293,9 +5594,9 @@ var tableDragStart = (orientation, event) => {
6293
5594
  const dragImage = createTableDragImage(editor, orientation, index, blockPos);
6294
5595
  if (event.dataTransfer) {
6295
5596
  const handleRect = event.currentTarget.getBoundingClientRect();
6296
- const offset7 = orientation === "col" ? { x: handleRect.width / 2, y: 0 } : { x: 0, y: handleRect.height / 2 };
5597
+ const offset6 = orientation === "col" ? { x: handleRect.width / 2, y: 0 } : { x: 0, y: handleRect.height / 2 };
6297
5598
  event.dataTransfer.effectAllowed = orientation === "col" ? "move" : "copyMove";
6298
- event.dataTransfer.setDragImage(dragImage, offset7.x, offset7.y);
5599
+ event.dataTransfer.setDragImage(dragImage, offset6.x, offset6.y);
6299
5600
  }
6300
5601
  const cleanup = () => dragImage.parentNode?.removeChild(dragImage);
6301
5602
  document.addEventListener("drop", cleanup, { once: true });
@@ -6579,17 +5880,6 @@ var MoreVerticalIcon = memo(({ className, ...props }) => {
6579
5880
  );
6580
5881
  });
6581
5882
  MoreVerticalIcon.displayName = "MoreVerticalIcon";
6582
- function Input({ className, type, ...props }) {
6583
- return /* @__PURE__ */ jsx(
6584
- "input",
6585
- {
6586
- type,
6587
- "data-slot": "tiptap-input",
6588
- className: cn("tiptap-input", className),
6589
- ...props
6590
- }
6591
- );
6592
- }
6593
5883
  function ComboboxProvider2({ ...props }) {
6594
5884
  return /* @__PURE__ */ jsx(
6595
5885
  Ariakit2.ComboboxProvider,
@@ -9293,69 +8583,6 @@ var ChevronDownIcon = memo(({ className, ...props }) => {
9293
8583
  );
9294
8584
  });
9295
8585
  ChevronDownIcon.displayName = "ChevronDownIcon";
9296
- var Card = forwardRef(
9297
- ({ className, ...props }, ref) => {
9298
- return /* @__PURE__ */ jsx("div", { ref, className: cn("tiptap-card", className), ...props });
9299
- }
9300
- );
9301
- Card.displayName = "Card";
9302
- var CardHeader = forwardRef(
9303
- ({ className, ...props }, ref) => {
9304
- return /* @__PURE__ */ jsx(
9305
- "div",
9306
- {
9307
- ref,
9308
- className: cn("tiptap-card-header", className),
9309
- ...props
9310
- }
9311
- );
9312
- }
9313
- );
9314
- CardHeader.displayName = "CardHeader";
9315
- var CardBody = forwardRef(
9316
- ({ className, ...props }, ref) => {
9317
- return /* @__PURE__ */ jsx("div", { ref, className: cn("tiptap-card-body", className), ...props });
9318
- }
9319
- );
9320
- CardBody.displayName = "CardBody";
9321
- var CardItemGroup = forwardRef(({ className, orientation = "vertical", ...props }, ref) => {
9322
- return /* @__PURE__ */ jsx(
9323
- "div",
9324
- {
9325
- ref,
9326
- "data-orientation": orientation,
9327
- className: cn("tiptap-card-item-group", className),
9328
- ...props
9329
- }
9330
- );
9331
- });
9332
- CardItemGroup.displayName = "CardItemGroup";
9333
- var CardGroupLabel = forwardRef(
9334
- ({ className, ...props }, ref) => {
9335
- return /* @__PURE__ */ jsx(
9336
- "div",
9337
- {
9338
- ref,
9339
- className: cn("tiptap-card-group-label", className),
9340
- ...props
9341
- }
9342
- );
9343
- }
9344
- );
9345
- CardGroupLabel.displayName = "CardGroupLabel";
9346
- var CardFooter = forwardRef(
9347
- ({ className, ...props }, ref) => {
9348
- return /* @__PURE__ */ jsx(
9349
- "div",
9350
- {
9351
- ref,
9352
- className: cn("tiptap-card-footer", className),
9353
- ...props
9354
- }
9355
- );
9356
- }
9357
- );
9358
- CardFooter.displayName = "CardFooter";
9359
8586
  var buttonGroupVariants = cva("tiptap-button-group", {
9360
8587
  variants: {
9361
8588
  orientation: {
@@ -13831,6 +13058,9 @@ function addEmojiTrigger(editor, trigger = ":", node, nodePos) {
13831
13058
  function canInsertMention(editor, node, nodePos) {
13832
13059
  if (!editor || !editor.isEditable) return false;
13833
13060
  if (isNodeTypeSelected(editor, ["image"])) return false;
13061
+ if (isValidPosition(nodePos)) {
13062
+ if (isValidPosition(nodePos) && nodePos >= 0) ;
13063
+ }
13834
13064
  return true;
13835
13065
  }
13836
13066
  function insertTriggerInBlockNode2(editor, trigger, node, nodePos) {
@@ -13888,7 +13118,7 @@ function insertTriggerInTextNode2(editor, trigger, node, nodePos) {
13888
13118
  }
13889
13119
  function addMentionTrigger(editor, trigger = "@", node, nodePos) {
13890
13120
  if (!editor || !editor.isEditable) return false;
13891
- if (!canInsertMention(editor)) return false;
13121
+ if (!canInsertMention(editor, node, nodePos)) return false;
13892
13122
  try {
13893
13123
  const { $from } = editor.state.selection;
13894
13124
  const currentNode = $from.node();
@@ -20278,10 +19508,10 @@ function setImageAlign(editor, align, extensionName = "image", attributeName = "
20278
19508
  }
20279
19509
  try {
20280
19510
  const { selection } = editor.state;
20281
- const isNodeSelection3 = selection instanceof NodeSelection;
20282
- const selectionPosition = isNodeSelection3 ? selection.from : selection.$anchor.pos;
19511
+ const isNodeSelection2 = selection instanceof NodeSelection;
19512
+ const selectionPosition = isNodeSelection2 ? selection.from : selection.$anchor.pos;
20283
19513
  const alignmentUpdated = editor.chain().focus().updateAttributes(extensionName, { [attributeName]: align }).run();
20284
- if (alignmentUpdated && isNodeSelection3) {
19514
+ if (alignmentUpdated && isNodeSelection2) {
20285
19515
  editor.commands.setNodeSelection(selectionPosition);
20286
19516
  }
20287
19517
  return alignmentUpdated;
@@ -20973,359 +20203,6 @@ function MobileToolbar({ editor: providedEditor }) {
20973
20203
  }
20974
20204
  );
20975
20205
  }
20976
- var CONTEXT_WINDOW_SIZE = 300;
20977
- function getNodeTypeAtSelection(editor) {
20978
- const { from } = editor.state.selection;
20979
- const $from = editor.state.doc.resolve(from);
20980
- return $from.parent.type.name;
20981
- }
20982
- function getHeadingLevel(editor) {
20983
- const { from } = editor.state.selection;
20984
- const $from = editor.state.doc.resolve(from);
20985
- for (let d = $from.depth; d > 0; d--) {
20986
- const node = $from.node(d);
20987
- const match = node.type.name.match(/heading(\d)/);
20988
- if (match) {
20989
- return parseInt(match[1], 10);
20990
- }
20991
- }
20992
- return void 0;
20993
- }
20994
- function getFullDocument(editor) {
20995
- return editor.state.doc.textContent;
20996
- }
20997
- function useAIContext(editor) {
20998
- const buildContext = useCallback(
20999
- (prompt) => {
21000
- if (!editor) {
21001
- return null;
21002
- }
21003
- const { from, to } = editor.state.selection;
21004
- const selectedText = editor.state.doc.textBetween(from, to);
21005
- if (!selectedText) {
21006
- return null;
21007
- }
21008
- const textBefore = editor.state.doc.textBetween(0, from);
21009
- const lines = textBefore.split("\n");
21010
- const line = lines.length;
21011
- const column = lines[lines.length - 1].length;
21012
- const precedingPos = Math.max(1, from - CONTEXT_WINDOW_SIZE);
21013
- const followingPos = Math.min(editor.state.doc.content.size, to + CONTEXT_WINDOW_SIZE);
21014
- const precedingText = editor.state.doc.textBetween(precedingPos, from);
21015
- const followingText = editor.state.doc.textBetween(to, followingPos);
21016
- return {
21017
- prompt,
21018
- selectedText,
21019
- position: {
21020
- line,
21021
- column
21022
- },
21023
- precedingText,
21024
- followingText,
21025
- nodeType: getNodeTypeAtSelection(editor),
21026
- currentHeadingLevel: getHeadingLevel(editor),
21027
- fullDocument: getFullDocument(editor),
21028
- documentFormat: "markdown"
21029
- };
21030
- },
21031
- [editor]
21032
- );
21033
- return { buildContext };
21034
- }
21035
- var AIConfigContext = createContext(null);
21036
- function useAIConfig() {
21037
- return useContext(AIConfigContext);
21038
- }
21039
- var SparklesIcon = memo(({ className, ...props }) => {
21040
- return /* @__PURE__ */ jsxs(
21041
- "svg",
21042
- {
21043
- width: "24",
21044
- height: "24",
21045
- className,
21046
- viewBox: "0 0 24 24",
21047
- fill: "currentColor",
21048
- xmlns: "http://www.w3.org/2000/svg",
21049
- ...props,
21050
- children: [
21051
- /* @__PURE__ */ jsx(
21052
- "path",
21053
- {
21054
- d: "M12 2C12.5523 2 13 2.44772 13 3V5C13 5.55228 12.5523 6 12 6C11.4477 6 11 5.55228 11 5V3C11 2.44772 11.4477 2 12 2Z",
21055
- fill: "currentColor"
21056
- }
21057
- ),
21058
- /* @__PURE__ */ jsx(
21059
- "path",
21060
- {
21061
- d: "M19.5 4.5C19.8978 4.10221 20.5244 4.10221 20.9222 4.5C21.32 4.89779 21.32 5.52441 20.9222 5.92221L19.5 7.34442C19.1022 7.74221 18.4756 7.74221 18.0778 7.34442C17.68 6.94663 17.68 6.32001 18.0778 5.92221L19.5 4.5Z",
21062
- fill: "currentColor"
21063
- }
21064
- ),
21065
- /* @__PURE__ */ jsx(
21066
- "path",
21067
- {
21068
- d: "M22 11C22.5523 11 23 11.4477 23 12C23 12.5523 22.5523 13 22 13H20C19.4477 13 19 12.5523 19 12C19 11.4477 19.4477 11 20 11H22Z",
21069
- fill: "currentColor"
21070
- }
21071
- ),
21072
- /* @__PURE__ */ jsx(
21073
- "path",
21074
- {
21075
- d: "M19.5 19.5L20.9222 18.0778C21.32 17.68 21.32 17.0534 20.9222 16.6556C20.5244 16.2578 19.8978 16.2578 19.5 16.6556L18.0778 18.0778C17.68 18.4756 17.68 19.1022 18.0778 19.5C18.4756 19.8978 19.1022 19.8978 19.5 19.5Z",
21076
- fill: "currentColor"
21077
- }
21078
- ),
21079
- /* @__PURE__ */ jsx(
21080
- "path",
21081
- {
21082
- d: "M12 18C12.5523 18 13 18.4477 13 19V21C13 21.5523 12.5523 22 12 22C11.4477 22 11 21.5523 11 21V19C11 18.4477 11.4477 18 12 18Z",
21083
- fill: "currentColor"
21084
- }
21085
- ),
21086
- /* @__PURE__ */ jsx(
21087
- "path",
21088
- {
21089
- d: "M4.5 19.5C4.89779 19.8978 4.89779 20.5244 4.5 20.9222C4.10221 21.32 3.47559 21.32 3.0778 20.9222L1.65558 19.5C1.25779 19.1022 1.25779 18.4756 1.65558 18.0778C2.05337 17.68 2.67999 17.68 3.0778 18.0778L4.5 19.5Z",
21090
- fill: "currentColor"
21091
- }
21092
- ),
21093
- /* @__PURE__ */ jsx(
21094
- "path",
21095
- {
21096
- d: "M2 12C2.55228 12 3 12.4477 3 13C3 13.5523 2.55228 14 2 14H0C-0.552285 14 -1 13.5523 -1 13C-1 12.4477 -0.552285 12 0 12H2Z",
21097
- fill: "currentColor"
21098
- }
21099
- ),
21100
- /* @__PURE__ */ jsx(
21101
- "path",
21102
- {
21103
- d: "M4.5 4.5C4.89779 4.10221 5.52441 4.10221 5.92221 4.5C6.32001 4.89779 6.32001 5.52441 5.92221 5.92221L4.5 7.34442C4.10221 7.74221 3.47559 7.74221 3.0778 7.34442C2.68001 6.94663 2.68001 6.32001 3.0778 5.92221L4.5 4.5Z",
21104
- fill: "currentColor"
21105
- }
21106
- ),
21107
- /* @__PURE__ */ jsx(
21108
- "path",
21109
- {
21110
- d: "M12 8C10.3431 8 9 9.34315 9 11C9 12.6569 10.3431 14 12 14C13.6569 14 15 12.6569 15 11C15 9.34315 13.6569 8 12 8Z",
21111
- fill: "currentColor"
21112
- }
21113
- )
21114
- ]
21115
- }
21116
- );
21117
- });
21118
- SparklesIcon.displayName = "SparklesIcon";
21119
- var SendIcon = memo(({ className, ...props }) => {
21120
- return /* @__PURE__ */ jsx(
21121
- "svg",
21122
- {
21123
- width: "24",
21124
- height: "24",
21125
- className,
21126
- viewBox: "0 0 24 24",
21127
- fill: "currentColor",
21128
- xmlns: "http://www.w3.org/2000/svg",
21129
- ...props,
21130
- children: /* @__PURE__ */ jsx(
21131
- "path",
21132
- {
21133
- d: "M16.6915026,12.4744748 L3.50612381,13.2599618 C3.19218622,13.2599618 3.03521743,13.4170592 3.03521743,13.5741566 L1.15159189,20.0151496 C0.8376543,20.8006365 0.99,21.89 1.77946707,22.52 C2.41,22.99 3.50612381,23.1 4.13399899,22.8429026 L21.714504,14.0454487 C22.6563168,13.5741566 23.1272231,12.6315722 22.9702544,11.6889879 L4.13399899,1.16865248 C3.34915502,0.9115551 2.40734225,1.01399899 1.77946707,1.4852911 C0.994623095,2.1181258 0.837654326,3.20946707 1.15159189,3.99495876 L3.03521743,10.4359518 C3.03521743,10.5930492 3.19218622,10.7501467 3.50612381,10.7501467 L16.6915026,11.5356335 C16.6915026,11.5356335 17.1624089,11.5356335 17.1624089,12.0068766 C17.1624089,12.4781197 16.6915026,12.4744748 16.6915026,12.4744748 Z",
21134
- fill: "currentColor"
21135
- }
21136
- )
21137
- }
21138
- );
21139
- });
21140
- SendIcon.displayName = "SendIcon";
21141
- function AIDialog({
21142
- editor,
21143
- config,
21144
- buildContext,
21145
- onClose
21146
- }) {
21147
- const [prompt, setPrompt] = useState("");
21148
- const [isLoading, setIsLoading] = useState(false);
21149
- const [error, setError] = useState(null);
21150
- const inputRef = useRef(null);
21151
- useEffect(() => {
21152
- inputRef.current?.focus();
21153
- }, []);
21154
- const handleSubmit = async () => {
21155
- if (!prompt.trim()) {
21156
- return;
21157
- }
21158
- setError(null);
21159
- setIsLoading(true);
21160
- try {
21161
- const context = buildContext(prompt);
21162
- if (!context) {
21163
- setError("No text selected");
21164
- setIsLoading(false);
21165
- return;
21166
- }
21167
- const result = await config.plugin.process(context);
21168
- if (result.error) {
21169
- setError(result.error);
21170
- setIsLoading(false);
21171
- return;
21172
- }
21173
- const { from, to } = editor.state.selection;
21174
- const tr = editor.state.tr.replaceWith(from, to, [
21175
- editor.state.schema.text(result.result)
21176
- ]);
21177
- editor.view.dispatch(tr);
21178
- onClose();
21179
- setPrompt("");
21180
- } catch (err) {
21181
- setError(err instanceof Error ? err.message : "An error occurred");
21182
- } finally {
21183
- setIsLoading(false);
21184
- }
21185
- };
21186
- const handleKeyDown = (e) => {
21187
- if (e.key === "Enter" && !e.shiftKey) {
21188
- e.preventDefault();
21189
- handleSubmit();
21190
- }
21191
- };
21192
- return /* @__PURE__ */ jsxs(Card, { className: "ai-dialog", children: [
21193
- /* @__PURE__ */ jsx(CardItemGroup, { children: /* @__PURE__ */ jsxs("div", { className: "ai-dialog-header", children: [
21194
- /* @__PURE__ */ jsx(SparklesIcon, { className: "ai-dialog-icon" }),
21195
- /* @__PURE__ */ jsx("span", { children: "AI Assistant" })
21196
- ] }) }),
21197
- /* @__PURE__ */ jsxs(CardBody, { className: "ai-dialog-body", children: [
21198
- /* @__PURE__ */ jsx("div", { className: "ai-dialog-input-group", children: /* @__PURE__ */ jsx(
21199
- Input,
21200
- {
21201
- ref: inputRef,
21202
- type: "text",
21203
- placeholder: "What would you like me to do with the selected text?",
21204
- value: prompt,
21205
- onChange: (e) => {
21206
- setPrompt(e.target.value);
21207
- setError(null);
21208
- },
21209
- onKeyDown: handleKeyDown,
21210
- disabled: isLoading,
21211
- className: "ai-dialog-input"
21212
- }
21213
- ) }),
21214
- error && /* @__PURE__ */ jsx("div", { className: "ai-dialog-error", children: error }),
21215
- /* @__PURE__ */ jsxs("div", { className: "ai-dialog-actions", children: [
21216
- /* @__PURE__ */ jsx(
21217
- Button,
21218
- {
21219
- type: "button",
21220
- variant: "ghost",
21221
- onClick: onClose,
21222
- disabled: isLoading,
21223
- children: "Cancel"
21224
- }
21225
- ),
21226
- /* @__PURE__ */ jsxs(
21227
- Button,
21228
- {
21229
- type: "button",
21230
- variant: "primary",
21231
- onClick: handleSubmit,
21232
- disabled: isLoading || !prompt.trim(),
21233
- children: [
21234
- isLoading ? "Processing..." : "Send",
21235
- !isLoading && /* @__PURE__ */ jsx(SendIcon, { className: "ai-dialog-button-icon" })
21236
- ]
21237
- }
21238
- )
21239
- ] })
21240
- ] })
21241
- ] });
21242
- }
21243
- var AIButton = forwardRef(
21244
- ({
21245
- editor: providedEditor,
21246
- config: providedConfig,
21247
- hideWhenUnavailable = true,
21248
- onClick,
21249
- ...buttonProps
21250
- }, ref) => {
21251
- const { editor } = useTiptapEditor(providedEditor);
21252
- const { buildContext } = useAIContext(editor);
21253
- const contextConfig = useAIConfig();
21254
- const [isOpen, setIsOpen] = useState(false);
21255
- const [shouldShow, setShouldShow] = useState(false);
21256
- const config = providedConfig || contextConfig;
21257
- const isEnabled = config?.enabled !== false;
21258
- useEffect(() => {
21259
- if (!editor) {
21260
- setShouldShow(false);
21261
- return;
21262
- }
21263
- const updateVisibility = () => {
21264
- const show = isEnabled && !hideWhenUnavailable && isSelectionValid(editor);
21265
- setShouldShow(show);
21266
- };
21267
- updateVisibility();
21268
- editor.on("selectionUpdate", updateVisibility);
21269
- return () => {
21270
- editor.off("selectionUpdate", updateVisibility);
21271
- };
21272
- }, [editor, hideWhenUnavailable, isEnabled]);
21273
- const handleOpenChange = useCallback(
21274
- (open) => {
21275
- setIsOpen(open);
21276
- },
21277
- []
21278
- );
21279
- const handleClick = useCallback(
21280
- (event) => {
21281
- onClick?.(event);
21282
- if (!event.defaultPrevented) {
21283
- setIsOpen(true);
21284
- }
21285
- },
21286
- [onClick]
21287
- );
21288
- if (!shouldShow || !editor || !config) {
21289
- return null;
21290
- }
21291
- return /* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: handleOpenChange, children: [
21292
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
21293
- Button,
21294
- {
21295
- ref,
21296
- type: "button",
21297
- variant: "ghost",
21298
- role: "button",
21299
- tabIndex: -1,
21300
- "aria-label": "AI Assistant",
21301
- tooltip: "AI Assistant",
21302
- onClick: handleClick,
21303
- ...buttonProps,
21304
- children: /* @__PURE__ */ jsx(SparklesIcon, { className: "tiptap-button-icon" })
21305
- }
21306
- ) }),
21307
- /* @__PURE__ */ jsx(
21308
- PopoverContent,
21309
- {
21310
- side: "top",
21311
- align: "start",
21312
- sideOffset: 4,
21313
- asChild: true,
21314
- children: /* @__PURE__ */ jsx(
21315
- AIDialog,
21316
- {
21317
- editor,
21318
- config,
21319
- buildContext,
21320
- onClose: () => handleOpenChange(false)
21321
- }
21322
- )
21323
- }
21324
- )
21325
- ] });
21326
- }
21327
- );
21328
- AIButton.displayName = "AIButton";
21329
20206
  function NotionToolbarFloating() {
21330
20207
  const { editor } = useTiptapEditor();
21331
20208
  const isMobile = useIsBreakpoint("max", 480);
@@ -22291,6 +21168,6 @@ function ArticleViewer({ content, placeholder = "" }) {
22291
21168
  ) }) });
22292
21169
  }
22293
21170
 
22294
- export { ArticleViewer, Audio, Button, CollabContext, CollabProvider, Column, Columns, DEFAULT_MAX_FILE_SIZES, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditorConfigProvider, EditorContentArea, EditorProvider, FileAttachment, FloatingElement, HIDE_FLOATING_META, LoadingSpinner, MAC_SYMBOLS, MAX_FILE_SIZE, MediaUploadButton, MediaUploadPlaceholder, NotionEditor, NotionEditorContent, PasteDropMedia, Popover, PopoverContent, PopoverTrigger, SR_ONLY, Separator, Spacer, Toolbar, ToolbarGroup, ToolbarSeparator, UiState, UserContext, UserProvider, Video, clamp, cn, defaultUiState, detectMediaKind, findNodeAtPosition, findNodePosition, findSelectionPosition, focusNextNode, formatShortcutKey, getAvatar, getElementOverflowPosition, getNodeDisplayName, getSelectedBlockNodes, getSelectedNodesOfType, getSelectionBoundingRect, getUrlParam, handleImageUpload, hasContentAbove, isAllowedUri, isExtensionAvailable, isMac, isMarkInSchema, isNodeInSchema, isNodeTypeSelected, isSelectionValid, isTextSelectionValid, isValidPosition, markHideFloatingOnNext, parseShortcutKeys, pickFile, removeEmptyParagraphs, resolveMaxSize, runMediaUpload, sanitizeUrl, selectCurrentBlockContent, selectNodeAndHideFloating, selectionWithinConvertibleTypes, updateNodesAttr, useCollab, useCollaboration, useComposedRef, useCursorVisibility, useEditorConfig, useElementRect, useFloatingElement, useFloatingToolbarVisibility, useIsBreakpoint, useIsomorphicLayoutEffect, useMenuNavigation, useOnClickOutside, useThrottledCallback, useTiptapEditor, useUiEditorState, useUnmount, useUser, useWindowSize, use_ui_editor_state_default };
22295
- //# sourceMappingURL=chunk-Y2XE4CYZ.js.map
22296
- //# sourceMappingURL=chunk-Y2XE4CYZ.js.map
21171
+ export { ArticleViewer, Audio, CollabContext, CollabProvider, Column, Columns, DEFAULT_MAX_FILE_SIZES, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditorConfigProvider, EditorContentArea, EditorProvider, FileAttachment, FloatingElement, HIDE_FLOATING_META, LoadingSpinner, MediaUploadButton, MediaUploadPlaceholder, NotionEditor, NotionEditorContent, PasteDropMedia, Separator, Spacer, Toolbar, ToolbarGroup, ToolbarSeparator, UiState, UserContext, UserProvider, Video, defaultUiState, detectMediaKind, findSelectionPosition, hasContentAbove, markHideFloatingOnNext, pickFile, resolveMaxSize, runMediaUpload, selectNodeAndHideFloating, useCollab, useCollaboration, useComposedRef, useCursorVisibility, useEditorConfig, useElementRect, useFloatingElement, useFloatingToolbarVisibility, useIsBreakpoint, useIsomorphicLayoutEffect, useMenuNavigation, useOnClickOutside, useThrottledCallback, useUiEditorState, useUnmount, useUser, useWindowSize, use_ui_editor_state_default };
21172
+ //# sourceMappingURL=chunk-BBZGFBWU.js.map
21173
+ //# sourceMappingURL=chunk-BBZGFBWU.js.map