hazo_ui 2.2.2 → 2.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
2
- import * as React6 from 'react';
1
+ import * as React14 from 'react';
3
2
  import { useState, useEffect } from 'react';
4
3
  import { Slot } from '@radix-ui/react-slot';
5
4
  import { cva } from 'class-variance-authority';
6
5
  import { clsx } from 'clsx';
7
6
  import { twMerge } from 'tailwind-merge';
7
+ import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
8
8
  import * as DialogPrimitive from '@radix-ui/react-dialog';
9
9
  import { X, ChevronDown, ChevronUp, Check, Circle, Filter, Plus, ChevronsUpDown, ArrowUpDown, Trash2, GripVertical, Calendar as Calendar$1, ChevronRight, ChevronLeft } from 'lucide-react';
10
10
  import * as PopoverPrimitive from '@radix-ui/react-popover';
@@ -19,19 +19,50 @@ import { CSS } from '@dnd-kit/utilities';
19
19
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
20
20
  import * as FaIcons from 'react-icons/fa';
21
21
  import * as MdIcons from 'react-icons/md';
22
+ import { MdFormatClear } from 'react-icons/md';
22
23
  import * as HiIcons from 'react-icons/hi';
23
24
  import * as BiIcons from 'react-icons/bi';
25
+ import { BiBracket } from 'react-icons/bi';
24
26
  import * as AiIcons from 'react-icons/ai';
25
27
  import * as BsIcons from 'react-icons/bs';
26
28
  import * as FiIcons from 'react-icons/fi';
29
+ import { FiMinus, FiPlus, FiChevronDown, FiType, FiList, FiCode, FiBold, FiItalic, FiUnderline, FiAlignLeft, FiAlignCenter, FiAlignRight, FiAlignJustify, FiLink, FiImage, FiPaperclip, FiTable, FiTrash2, FiColumns, FiSearch, FiEye } from 'react-icons/fi';
27
30
  import * as IoIcons from 'react-icons/io5';
28
31
  import * as RiIcons from 'react-icons/ri';
32
+ import { RiInsertRowBottom, RiInsertColumnRight, RiDeleteRow, RiDeleteColumn } from 'react-icons/ri';
29
33
  import * as TbIcons from 'react-icons/tb';
30
34
  import * as CiIcons from 'react-icons/ci';
35
+ import { ReactNodeViewRenderer, NodeViewWrapper, useEditor, EditorContent } from '@tiptap/react';
36
+ import StarterKit from '@tiptap/starter-kit';
37
+ import { Underline } from '@tiptap/extension-underline';
38
+ import { TextStyle } from '@tiptap/extension-text-style';
39
+ import { Color } from '@tiptap/extension-color';
40
+ import { Highlight } from '@tiptap/extension-highlight';
41
+ import { FontFamily } from '@tiptap/extension-font-family';
42
+ import { TextAlign } from '@tiptap/extension-text-align';
43
+ import { Link } from '@tiptap/extension-link';
44
+ import { Image } from '@tiptap/extension-image';
45
+ import { Table } from '@tiptap/extension-table';
46
+ import { TableRow } from '@tiptap/extension-table-row';
47
+ import { TableCell } from '@tiptap/extension-table-cell';
48
+ import { TableHeader } from '@tiptap/extension-table-header';
49
+ import { TaskList } from '@tiptap/extension-task-list';
50
+ import { TaskItem } from '@tiptap/extension-task-item';
51
+ import { Subscript } from '@tiptap/extension-subscript';
52
+ import { Superscript } from '@tiptap/extension-superscript';
53
+ import { Placeholder } from '@tiptap/extension-placeholder';
54
+ import { HexColorPicker } from 'react-colorful';
55
+ import { LuUndo2, LuRedo2, LuHeading1, LuHeading2, LuHeading3, LuListOrdered, LuListTodo, LuQuote, LuStrikethrough, LuSubscript, LuSuperscript, LuHighlighter, LuTableProperties, LuColumns2 } from 'react-icons/lu';
56
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
57
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
58
+ import { RemoveMarkStep, Transform, liftTarget, joinPoint, canSplit, ReplaceStep, ReplaceAroundStep, canJoin } from '@tiptap/pm/transform';
59
+ import { createParagraphNear as createParagraphNear$1, deleteSelection as deleteSelection$1, exitCode as exitCode$1, joinUp as joinUp$1, joinDown as joinDown$1, joinBackward as joinBackward$1, joinForward as joinForward$1, joinTextblockBackward as joinTextblockBackward$1, joinTextblockForward as joinTextblockForward$1, lift as lift$1, liftEmptyBlock as liftEmptyBlock$1, newlineInCode as newlineInCode$1, selectNodeBackward as selectNodeBackward$1, selectNodeForward as selectNodeForward$1, selectParentNode as selectParentNode$1, selectTextblockEnd as selectTextblockEnd$1, selectTextblockStart as selectTextblockStart$1, setBlockType, wrapIn as wrapIn$1 } from '@tiptap/pm/commands';
60
+ import { Plugin, PluginKey, Selection, TextSelection, AllSelection, NodeSelection } from '@tiptap/pm/state';
61
+ import { Fragment, Slice, Node, Schema, DOMParser } from '@tiptap/pm/model';
62
+ import { liftListItem as liftListItem$1, sinkListItem as sinkListItem$1, wrapInList as wrapInList$1 } from '@tiptap/pm/schema-list';
63
+ import '@tiptap/pm/view';
64
+ import '@tiptap/pm/keymap';
31
65
 
32
- var ExampleComponent = ({ children, className = "" }) => {
33
- return /* @__PURE__ */ jsx("div", { className: `cls_example_component ${className}`, children });
34
- };
35
66
  function cn(...inputs) {
36
67
  return twMerge(clsx(inputs));
37
68
  }
@@ -60,7 +91,7 @@ var buttonVariants = cva(
60
91
  }
61
92
  }
62
93
  );
63
- var Button = React6.forwardRef(
94
+ var Button = React14.forwardRef(
64
95
  ({ className, variant, size, asChild = false, ...props }, ref) => {
65
96
  const Comp = asChild ? Slot : "button";
66
97
  return /* @__PURE__ */ jsx(
@@ -77,7 +108,7 @@ Button.displayName = "Button";
77
108
  var Dialog = DialogPrimitive.Root;
78
109
  var DialogTrigger = DialogPrimitive.Trigger;
79
110
  var DialogPortal = DialogPrimitive.Portal;
80
- var DialogOverlay = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
111
+ var DialogOverlay = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
81
112
  DialogPrimitive.Overlay,
82
113
  {
83
114
  ref,
@@ -89,7 +120,7 @@ var DialogOverlay = React6.forwardRef(({ className, ...props }, ref) => /* @__PU
89
120
  }
90
121
  ));
91
122
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
92
- var DialogContent = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
123
+ var DialogContent = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
93
124
  /* @__PURE__ */ jsx(DialogOverlay, {}),
94
125
  /* @__PURE__ */ jsxs(
95
126
  DialogPrimitive.Content,
@@ -139,7 +170,7 @@ var DialogFooter = ({
139
170
  }
140
171
  );
141
172
  DialogFooter.displayName = "DialogFooter";
142
- var DialogTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
173
+ var DialogTitle = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
143
174
  DialogPrimitive.Title,
144
175
  {
145
176
  ref,
@@ -151,7 +182,7 @@ var DialogTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE
151
182
  }
152
183
  ));
153
184
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
154
- var DialogDescription = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
185
+ var DialogDescription = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
155
186
  DialogPrimitive.Description,
156
187
  {
157
188
  ref,
@@ -160,7 +191,7 @@ var DialogDescription = React6.forwardRef(({ className, ...props }, ref) => /* @
160
191
  }
161
192
  ));
162
193
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
163
- var Command = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
194
+ var Command = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
164
195
  "div",
165
196
  {
166
197
  ref,
@@ -172,7 +203,7 @@ var Command = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
172
203
  }
173
204
  ));
174
205
  Command.displayName = "Command";
175
- var CommandInput = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
206
+ var CommandInput = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
176
207
  "input",
177
208
  {
178
209
  ref,
@@ -184,7 +215,7 @@ var CommandInput = React6.forwardRef(({ className, ...props }, ref) => /* @__PUR
184
215
  }
185
216
  ));
186
217
  CommandInput.displayName = "CommandInput";
187
- var CommandList = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
218
+ var CommandList = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
188
219
  "div",
189
220
  {
190
221
  ref,
@@ -193,7 +224,7 @@ var CommandList = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE
193
224
  }
194
225
  ));
195
226
  CommandList.displayName = "CommandList";
196
- var CommandEmpty = React6.forwardRef((props, ref) => /* @__PURE__ */ jsx(
227
+ var CommandEmpty = React14.forwardRef((props, ref) => /* @__PURE__ */ jsx(
197
228
  "div",
198
229
  {
199
230
  ref,
@@ -202,7 +233,7 @@ var CommandEmpty = React6.forwardRef((props, ref) => /* @__PURE__ */ jsx(
202
233
  }
203
234
  ));
204
235
  CommandEmpty.displayName = "CommandEmpty";
205
- var CommandGroup = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
236
+ var CommandGroup = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
206
237
  "div",
207
238
  {
208
239
  ref,
@@ -214,7 +245,7 @@ var CommandGroup = React6.forwardRef(({ className, ...props }, ref) => /* @__PUR
214
245
  }
215
246
  ));
216
247
  CommandGroup.displayName = "CommandGroup";
217
- var CommandItem = React6.forwardRef(({ className, onSelect, value, ...props }, ref) => {
248
+ var CommandItem = React14.forwardRef(({ className, onSelect, value, ...props }, ref) => {
218
249
  const handleClick = () => {
219
250
  if (onSelect && value) {
220
251
  onSelect(value);
@@ -236,7 +267,7 @@ var CommandItem = React6.forwardRef(({ className, onSelect, value, ...props }, r
236
267
  CommandItem.displayName = "CommandItem";
237
268
  var Popover = PopoverPrimitive.Root;
238
269
  var PopoverTrigger = PopoverPrimitive.Trigger;
239
- var PopoverContent = React6.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
270
+ var PopoverContent = React14.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
240
271
  PopoverPrimitive.Content,
241
272
  {
242
273
  ref,
@@ -250,7 +281,7 @@ var PopoverContent = React6.forwardRef(({ className, align = "center", sideOffse
250
281
  }
251
282
  ) }));
252
283
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
253
- var Input = React6.forwardRef(
284
+ var Input = React14.forwardRef(
254
285
  ({ className, type, ...props }, ref) => {
255
286
  return /* @__PURE__ */ jsx(
256
287
  "input",
@@ -269,7 +300,7 @@ var Input = React6.forwardRef(
269
300
  Input.displayName = "Input";
270
301
  var Select = SelectPrimitive.Root;
271
302
  var SelectValue = SelectPrimitive.Value;
272
- var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
303
+ var SelectTrigger = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
273
304
  SelectPrimitive.Trigger,
274
305
  {
275
306
  ref,
@@ -285,7 +316,7 @@ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) =
285
316
  }
286
317
  ));
287
318
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
288
- var SelectScrollUpButton = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
319
+ var SelectScrollUpButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
289
320
  SelectPrimitive.ScrollUpButton,
290
321
  {
291
322
  ref,
@@ -298,7 +329,7 @@ var SelectScrollUpButton = React6.forwardRef(({ className, ...props }, ref) => /
298
329
  }
299
330
  ));
300
331
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
301
- var SelectScrollDownButton = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
332
+ var SelectScrollDownButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
302
333
  SelectPrimitive.ScrollDownButton,
303
334
  {
304
335
  ref,
@@ -311,7 +342,7 @@ var SelectScrollDownButton = React6.forwardRef(({ className, ...props }, ref) =>
311
342
  }
312
343
  ));
313
344
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
314
- var SelectContent = React6.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
345
+ var SelectContent = React14.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
315
346
  SelectPrimitive.Content,
316
347
  {
317
348
  ref,
@@ -339,7 +370,7 @@ var SelectContent = React6.forwardRef(({ className, children, position = "popper
339
370
  }
340
371
  ) }));
341
372
  SelectContent.displayName = SelectPrimitive.Content.displayName;
342
- var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
373
+ var SelectLabel = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
343
374
  SelectPrimitive.Label,
344
375
  {
345
376
  ref,
@@ -348,7 +379,7 @@ var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE
348
379
  }
349
380
  ));
350
381
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
351
- var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
382
+ var SelectItem = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
352
383
  SelectPrimitive.Item,
353
384
  {
354
385
  ref,
@@ -364,7 +395,7 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
364
395
  }
365
396
  ));
366
397
  SelectItem.displayName = SelectPrimitive.Item.displayName;
367
- var SelectSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
398
+ var SelectSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
368
399
  SelectPrimitive.Separator,
369
400
  {
370
401
  ref,
@@ -376,7 +407,7 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
376
407
  var TooltipProvider = TooltipPrimitive.Provider;
377
408
  var Tooltip = TooltipPrimitive.Root;
378
409
  var TooltipTrigger = TooltipPrimitive.Trigger;
379
- var TooltipContent = React6.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
410
+ var TooltipContent = React14.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
380
411
  TooltipPrimitive.Content,
381
412
  {
382
413
  ref,
@@ -847,7 +878,7 @@ function HazoUiMultiFilterDialog({
847
878
  ] })
848
879
  ] });
849
880
  }
850
- var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
881
+ var Switch = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
851
882
  SwitchPrimitives.Root,
852
883
  {
853
884
  className: cn(
@@ -867,7 +898,7 @@ var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
867
898
  }
868
899
  ));
869
900
  Switch.displayName = SwitchPrimitives.Root.displayName;
870
- var Label2 = React6.forwardRef(
901
+ var Label2 = React14.forwardRef(
871
902
  ({ className, ...props }, ref) => {
872
903
  return /* @__PURE__ */ jsx(
873
904
  "label",
@@ -1161,7 +1192,7 @@ function HazoUiMultiSortDialog({
1161
1192
  ] })
1162
1193
  ] });
1163
1194
  }
1164
- var RadioGroup = React6.forwardRef(({ className, ...props }, ref) => {
1195
+ var RadioGroup = React14.forwardRef(({ className, ...props }, ref) => {
1165
1196
  return /* @__PURE__ */ jsx(
1166
1197
  RadioGroupPrimitive.Root,
1167
1198
  {
@@ -1172,7 +1203,7 @@ var RadioGroup = React6.forwardRef(({ className, ...props }, ref) => {
1172
1203
  );
1173
1204
  });
1174
1205
  RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
1175
- var RadioGroupItem = React6.forwardRef(({ className, ...props }, ref) => {
1206
+ var RadioGroupItem = React14.forwardRef(({ className, ...props }, ref) => {
1176
1207
  return /* @__PURE__ */ jsx(
1177
1208
  RadioGroupPrimitive.Item,
1178
1209
  {
@@ -1526,7 +1557,7 @@ function filterInputValue(value, input_type, num_decimals) {
1526
1557
  }
1527
1558
  }
1528
1559
  }
1529
- var HazoUiFlexInput = React6.forwardRef(
1560
+ var HazoUiFlexInput = React14.forwardRef(
1530
1561
  ({
1531
1562
  className,
1532
1563
  input_type = "mixed",
@@ -1543,13 +1574,13 @@ var HazoUiFlexInput = React6.forwardRef(
1543
1574
  onBlur,
1544
1575
  ...props
1545
1576
  }, ref) => {
1546
- const [internalValue, setInternalValue] = React6.useState(
1577
+ const [internalValue, setInternalValue] = React14.useState(
1547
1578
  typeof controlledValue === "string" ? controlledValue : typeof controlledValue === "number" ? String(controlledValue) : ""
1548
1579
  );
1549
- const [errorMessage, setErrorMessage] = React6.useState();
1580
+ const [errorMessage, setErrorMessage] = React14.useState();
1550
1581
  const isControlled = controlledValue !== void 0;
1551
1582
  const currentValue = isControlled ? typeof controlledValue === "string" ? controlledValue : String(controlledValue || "") : internalValue;
1552
- React6.useEffect(() => {
1583
+ React14.useEffect(() => {
1553
1584
  if (isControlled) {
1554
1585
  const newValue = typeof controlledValue === "string" ? controlledValue : String(controlledValue || "");
1555
1586
  if (newValue !== internalValue) {
@@ -1630,6 +1661,4691 @@ var HazoUiFlexInput = React6.forwardRef(
1630
1661
  );
1631
1662
  HazoUiFlexInput.displayName = "HazoUiFlexInput";
1632
1663
 
1633
- export { ExampleComponent, HazoUiFlexInput, HazoUiFlexRadio, HazoUiMultiFilterDialog, HazoUiMultiSortDialog };
1664
+ // src/components/hazo_ui_richtext_editor/constants.ts
1665
+ var FONT_FAMILIES = [
1666
+ { value: "Arial", label: "Arial" },
1667
+ { value: "Verdana", label: "Verdana" },
1668
+ { value: "Times New Roman", label: "Times New Roman" },
1669
+ { value: "Georgia", label: "Georgia" },
1670
+ { value: "Courier New", label: "Courier New" },
1671
+ { value: "Trebuchet MS", label: "Trebuchet MS" }
1672
+ ];
1673
+ var FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72];
1674
+ var DEFAULT_FONT_SIZE = 16;
1675
+ var MIN_FONT_SIZE = 8;
1676
+ var MAX_FONT_SIZE = 72;
1677
+ var PRESET_COLORS = [
1678
+ "#000000",
1679
+ "#ffffff",
1680
+ "#f44336",
1681
+ "#e91e63",
1682
+ "#9c27b0",
1683
+ "#673ab7",
1684
+ "#3f51b5",
1685
+ "#2196f3",
1686
+ "#03a9f4",
1687
+ "#00bcd4",
1688
+ "#009688",
1689
+ "#4caf50",
1690
+ "#8bc34a",
1691
+ "#cddc39",
1692
+ "#ffeb3b",
1693
+ "#ffc107",
1694
+ "#ff9800",
1695
+ "#ff5722",
1696
+ "#795548",
1697
+ "#9e9e9e"
1698
+ ];
1699
+ var DEFAULT_TEXT_COLOR = "#000000";
1700
+ var DEFAULT_HIGHLIGHT_COLOR = "#ffff00";
1701
+ var DEFAULT_MIN_HEIGHT = "200px";
1702
+ var DEFAULT_MAX_HEIGHT = "500px";
1703
+ var DEFAULT_PLACEHOLDER = "Start typing...";
1704
+ function ColorPickerPopover({
1705
+ color,
1706
+ on_color_change,
1707
+ trigger_icon,
1708
+ trigger_label = "Pick color"
1709
+ }) {
1710
+ const [is_open, set_is_open] = React14.useState(false);
1711
+ const [hex_input, set_hex_input] = React14.useState(color);
1712
+ React14.useEffect(() => {
1713
+ set_hex_input(color);
1714
+ }, [color]);
1715
+ const handle_hex_input_change = (e) => {
1716
+ const value = e.target.value;
1717
+ set_hex_input(value);
1718
+ if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
1719
+ on_color_change(value);
1720
+ }
1721
+ };
1722
+ const handle_preset_select = (preset_color) => {
1723
+ on_color_change(preset_color);
1724
+ set_hex_input(preset_color);
1725
+ };
1726
+ return /* @__PURE__ */ jsxs(Popover, { open: is_open, onOpenChange: set_is_open, children: [
1727
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1728
+ Button,
1729
+ {
1730
+ variant: "ghost",
1731
+ size: "sm",
1732
+ className: "cls_color_picker_trigger h-8 w-8 p-0",
1733
+ "aria-label": trigger_label,
1734
+ children: /* @__PURE__ */ jsxs("div", { className: "cls_color_picker_icon_wrapper relative", children: [
1735
+ trigger_icon,
1736
+ /* @__PURE__ */ jsx(
1737
+ "div",
1738
+ {
1739
+ className: "cls_color_picker_indicator absolute -bottom-0.5 left-1/2 -translate-x-1/2 h-1 w-4 rounded-full",
1740
+ style: { backgroundColor: color }
1741
+ }
1742
+ )
1743
+ ] })
1744
+ }
1745
+ ) }),
1746
+ /* @__PURE__ */ jsx(PopoverContent, { className: "cls_color_picker_popover w-64 p-3", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "cls_color_picker_content space-y-3", children: [
1747
+ /* @__PURE__ */ jsx(
1748
+ HexColorPicker,
1749
+ {
1750
+ color,
1751
+ onChange: (new_color) => {
1752
+ on_color_change(new_color);
1753
+ set_hex_input(new_color);
1754
+ },
1755
+ className: "cls_color_picker_main !w-full"
1756
+ }
1757
+ ),
1758
+ /* @__PURE__ */ jsxs("div", { className: "cls_color_picker_hex_input flex items-center gap-2", children: [
1759
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Hex:" }),
1760
+ /* @__PURE__ */ jsx(
1761
+ Input,
1762
+ {
1763
+ value: hex_input,
1764
+ onChange: handle_hex_input_change,
1765
+ className: "h-8 font-mono text-sm",
1766
+ placeholder: "#000000"
1767
+ }
1768
+ )
1769
+ ] }),
1770
+ /* @__PURE__ */ jsxs("div", { className: "cls_color_picker_presets", children: [
1771
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mb-2 block", children: "Presets" }),
1772
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-10 gap-1", children: PRESET_COLORS.map((preset_color) => /* @__PURE__ */ jsx(
1773
+ "button",
1774
+ {
1775
+ onClick: () => handle_preset_select(preset_color),
1776
+ className: cn(
1777
+ "cls_color_preset h-5 w-5 rounded border border-border transition-transform",
1778
+ "hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1",
1779
+ color === preset_color && "ring-2 ring-primary ring-offset-1"
1780
+ ),
1781
+ style: { backgroundColor: preset_color },
1782
+ "aria-label": `Select color ${preset_color}`
1783
+ },
1784
+ preset_color
1785
+ )) })
1786
+ ] })
1787
+ ] }) })
1788
+ ] });
1789
+ }
1790
+ function TableSizePicker({
1791
+ max_rows = 8,
1792
+ max_cols = 8,
1793
+ on_select
1794
+ }) {
1795
+ const [hover_row, set_hover_row] = React14.useState(0);
1796
+ const [hover_col, set_hover_col] = React14.useState(0);
1797
+ return /* @__PURE__ */ jsxs("div", { className: "cls_table_size_picker p-2", children: [
1798
+ /* @__PURE__ */ jsx("div", { className: "cls_table_size_label text-sm text-muted-foreground mb-2 text-center", children: hover_row > 0 && hover_col > 0 ? `${hover_row} x ${hover_col} Table` : "Select table size" }),
1799
+ /* @__PURE__ */ jsx(
1800
+ "div",
1801
+ {
1802
+ className: "cls_table_size_grid grid gap-1",
1803
+ style: {
1804
+ gridTemplateColumns: `repeat(${max_cols}, 1fr)`
1805
+ },
1806
+ onMouseLeave: () => {
1807
+ set_hover_row(0);
1808
+ set_hover_col(0);
1809
+ },
1810
+ children: Array.from({ length: max_rows * max_cols }).map((_, index) => {
1811
+ const row = Math.floor(index / max_cols) + 1;
1812
+ const col = index % max_cols + 1;
1813
+ const is_highlighted = row <= hover_row && col <= hover_col;
1814
+ return /* @__PURE__ */ jsx(
1815
+ "div",
1816
+ {
1817
+ className: cn(
1818
+ "cls_table_size_cell w-4 h-4 border border-border rounded-sm cursor-pointer transition-colors",
1819
+ is_highlighted ? "bg-primary border-primary" : "bg-background hover:bg-muted"
1820
+ ),
1821
+ onMouseEnter: () => {
1822
+ set_hover_row(row);
1823
+ set_hover_col(col);
1824
+ },
1825
+ onClick: () => on_select(row, col)
1826
+ },
1827
+ index
1828
+ );
1829
+ })
1830
+ }
1831
+ )
1832
+ ] });
1833
+ }
1834
+ function ToolbarButton({ icon, label, on_click, is_active, disabled, className }) {
1835
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
1836
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1837
+ Button,
1838
+ {
1839
+ variant: "ghost",
1840
+ size: "sm",
1841
+ onClick: on_click,
1842
+ disabled,
1843
+ className: cn(
1844
+ "cls_toolbar_button h-8 w-8 p-0",
1845
+ is_active && "bg-accent text-accent-foreground",
1846
+ className
1847
+ ),
1848
+ children: icon
1849
+ }
1850
+ ) }),
1851
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: label }) })
1852
+ ] });
1853
+ }
1854
+ function ToolbarDivider() {
1855
+ return /* @__PURE__ */ jsx("div", { className: "cls_toolbar_divider mx-1 h-6 w-px bg-border" });
1856
+ }
1857
+ function get_current_font_size(editor) {
1858
+ if (!editor) return DEFAULT_FONT_SIZE;
1859
+ const attrs = editor.getAttributes("textStyle");
1860
+ if (attrs?.fontSize) {
1861
+ const parsed = parseInt(attrs.fontSize.replace("px", ""), 10);
1862
+ return isNaN(parsed) ? DEFAULT_FONT_SIZE : parsed;
1863
+ }
1864
+ return DEFAULT_FONT_SIZE;
1865
+ }
1866
+ function Toolbar({ editor, on_open_variables_modal, variables, on_image_embed, on_add_attachment }) {
1867
+ const [link_url, set_link_url] = React14.useState("");
1868
+ const [is_link_popover_open, set_is_link_popover_open] = React14.useState(false);
1869
+ const [is_block_type_open, set_is_block_type_open] = React14.useState(false);
1870
+ const [is_table_popover_open, set_is_table_popover_open] = React14.useState(false);
1871
+ const [is_table_controls_open, set_is_table_controls_open] = React14.useState(false);
1872
+ const [is_columns_popover_open, set_is_columns_popover_open] = React14.useState(false);
1873
+ const [is_uploading_image, set_is_uploading_image] = React14.useState(false);
1874
+ const [is_uploading_attachment, set_is_uploading_attachment] = React14.useState(false);
1875
+ const image_input_ref = React14.useRef(null);
1876
+ const attachment_input_ref = React14.useRef(null);
1877
+ if (!editor) {
1878
+ return null;
1879
+ }
1880
+ const is_in_table = editor.isActive("table");
1881
+ const current_font_family = editor.getAttributes("textStyle").fontFamily || "Arial";
1882
+ const current_text_color = editor.getAttributes("textStyle").color || DEFAULT_TEXT_COLOR;
1883
+ const current_highlight_color = editor.getAttributes("highlight").color || DEFAULT_HIGHLIGHT_COLOR;
1884
+ const current_font_size = get_current_font_size(editor);
1885
+ const handle_insert_link = () => {
1886
+ if (link_url) {
1887
+ editor.chain().focus().setLink({ href: link_url }).run();
1888
+ set_link_url("");
1889
+ set_is_link_popover_open(false);
1890
+ }
1891
+ };
1892
+ const handle_image_change = async (e) => {
1893
+ const file = e.target.files?.[0];
1894
+ if (!file || !on_image_embed) return;
1895
+ set_is_uploading_image(true);
1896
+ try {
1897
+ await on_image_embed(file);
1898
+ } catch (error) {
1899
+ console.error("Image embed failed:", error);
1900
+ } finally {
1901
+ set_is_uploading_image(false);
1902
+ if (image_input_ref.current) {
1903
+ image_input_ref.current.value = "";
1904
+ }
1905
+ }
1906
+ };
1907
+ const handle_attachment_change = async (e) => {
1908
+ const file = e.target.files?.[0];
1909
+ if (!file || !on_add_attachment) return;
1910
+ set_is_uploading_attachment(true);
1911
+ try {
1912
+ await on_add_attachment(file);
1913
+ } catch (error) {
1914
+ console.error("Attachment failed:", error);
1915
+ } finally {
1916
+ set_is_uploading_attachment(false);
1917
+ if (attachment_input_ref.current) {
1918
+ attachment_input_ref.current.value = "";
1919
+ }
1920
+ }
1921
+ };
1922
+ const select_block_type = (command2) => {
1923
+ command2();
1924
+ set_is_block_type_open(false);
1925
+ };
1926
+ const handle_insert_table = (rows, cols) => {
1927
+ editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
1928
+ set_is_table_popover_open(false);
1929
+ };
1930
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs("div", { className: "cls_toolbar flex flex-wrap items-center gap-0.5 p-2 border-b border-border bg-muted/30", children: [
1931
+ /* @__PURE__ */ jsx(
1932
+ ToolbarButton,
1933
+ {
1934
+ icon: /* @__PURE__ */ jsx(LuUndo2, { className: "h-4 w-4" }),
1935
+ label: "Undo",
1936
+ on_click: () => editor.chain().focus().undo().run(),
1937
+ disabled: !editor.can().undo()
1938
+ }
1939
+ ),
1940
+ /* @__PURE__ */ jsx(
1941
+ ToolbarButton,
1942
+ {
1943
+ icon: /* @__PURE__ */ jsx(LuRedo2, { className: "h-4 w-4" }),
1944
+ label: "Redo",
1945
+ on_click: () => editor.chain().focus().redo().run(),
1946
+ disabled: !editor.can().redo()
1947
+ }
1948
+ ),
1949
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
1950
+ /* @__PURE__ */ jsxs(
1951
+ Select,
1952
+ {
1953
+ value: current_font_family,
1954
+ onValueChange: (value) => editor.chain().focus().setFontFamily(value).run(),
1955
+ children: [
1956
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "cls_toolbar_font_family h-8 w-32 text-xs", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
1957
+ /* @__PURE__ */ jsx(SelectContent, { children: FONT_FAMILIES.map((font) => /* @__PURE__ */ jsx(SelectItem, { value: font.value, style: { fontFamily: font.value }, children: font.label }, font.value)) })
1958
+ ]
1959
+ }
1960
+ ),
1961
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
1962
+ /* @__PURE__ */ jsx(
1963
+ ToolbarButton,
1964
+ {
1965
+ icon: /* @__PURE__ */ jsx(FiMinus, { className: "h-4 w-4" }),
1966
+ label: "Decrease font size",
1967
+ on_click: () => editor.chain().focus().decreaseFontSize().run()
1968
+ }
1969
+ ),
1970
+ /* @__PURE__ */ jsx("span", { className: "cls_toolbar_font_size w-8 text-center text-xs tabular-nums", children: current_font_size }),
1971
+ /* @__PURE__ */ jsx(
1972
+ ToolbarButton,
1973
+ {
1974
+ icon: /* @__PURE__ */ jsx(FiPlus, { className: "h-4 w-4" }),
1975
+ label: "Increase font size",
1976
+ on_click: () => editor.chain().focus().increaseFontSize().run()
1977
+ }
1978
+ ),
1979
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
1980
+ /* @__PURE__ */ jsxs(Popover, { open: is_block_type_open, onOpenChange: set_is_block_type_open, children: [
1981
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", className: "cls_toolbar_block_type h-8 gap-1 px-2", children: [
1982
+ /* @__PURE__ */ jsx(LuHeading1, { className: "h-4 w-4" }),
1983
+ /* @__PURE__ */ jsx(FiChevronDown, { className: "h-3 w-3" })
1984
+ ] }) }),
1985
+ /* @__PURE__ */ jsx(PopoverContent, { className: "cls_block_type_popover w-48 p-1", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "cls_block_type_list space-y-0.5", children: [
1986
+ /* @__PURE__ */ jsxs(
1987
+ Button,
1988
+ {
1989
+ variant: editor.isActive("paragraph") ? "secondary" : "ghost",
1990
+ size: "sm",
1991
+ className: "w-full justify-start",
1992
+ onClick: () => select_block_type(() => editor.chain().focus().setParagraph().run()),
1993
+ children: [
1994
+ /* @__PURE__ */ jsx(FiType, { className: "mr-2 h-4 w-4" }),
1995
+ "Paragraph"
1996
+ ]
1997
+ }
1998
+ ),
1999
+ /* @__PURE__ */ jsxs(
2000
+ Button,
2001
+ {
2002
+ variant: editor.isActive("heading", { level: 1 }) ? "secondary" : "ghost",
2003
+ size: "sm",
2004
+ className: "w-full justify-start",
2005
+ onClick: () => select_block_type(() => editor.chain().focus().toggleHeading({ level: 1 }).run()),
2006
+ children: [
2007
+ /* @__PURE__ */ jsx(LuHeading1, { className: "mr-2 h-4 w-4" }),
2008
+ "Heading 1"
2009
+ ]
2010
+ }
2011
+ ),
2012
+ /* @__PURE__ */ jsxs(
2013
+ Button,
2014
+ {
2015
+ variant: editor.isActive("heading", { level: 2 }) ? "secondary" : "ghost",
2016
+ size: "sm",
2017
+ className: "w-full justify-start",
2018
+ onClick: () => select_block_type(() => editor.chain().focus().toggleHeading({ level: 2 }).run()),
2019
+ children: [
2020
+ /* @__PURE__ */ jsx(LuHeading2, { className: "mr-2 h-4 w-4" }),
2021
+ "Heading 2"
2022
+ ]
2023
+ }
2024
+ ),
2025
+ /* @__PURE__ */ jsxs(
2026
+ Button,
2027
+ {
2028
+ variant: editor.isActive("heading", { level: 3 }) ? "secondary" : "ghost",
2029
+ size: "sm",
2030
+ className: "w-full justify-start",
2031
+ onClick: () => select_block_type(() => editor.chain().focus().toggleHeading({ level: 3 }).run()),
2032
+ children: [
2033
+ /* @__PURE__ */ jsx(LuHeading3, { className: "mr-2 h-4 w-4" }),
2034
+ "Heading 3"
2035
+ ]
2036
+ }
2037
+ ),
2038
+ /* @__PURE__ */ jsxs(
2039
+ Button,
2040
+ {
2041
+ variant: editor.isActive("bulletList") ? "secondary" : "ghost",
2042
+ size: "sm",
2043
+ className: "w-full justify-start",
2044
+ onClick: () => select_block_type(() => editor.chain().focus().toggleBulletList().run()),
2045
+ children: [
2046
+ /* @__PURE__ */ jsx(FiList, { className: "mr-2 h-4 w-4" }),
2047
+ "Bullet List"
2048
+ ]
2049
+ }
2050
+ ),
2051
+ /* @__PURE__ */ jsxs(
2052
+ Button,
2053
+ {
2054
+ variant: editor.isActive("orderedList") ? "secondary" : "ghost",
2055
+ size: "sm",
2056
+ className: "w-full justify-start",
2057
+ onClick: () => select_block_type(() => editor.chain().focus().toggleOrderedList().run()),
2058
+ children: [
2059
+ /* @__PURE__ */ jsx(LuListOrdered, { className: "mr-2 h-4 w-4" }),
2060
+ "Numbered List"
2061
+ ]
2062
+ }
2063
+ ),
2064
+ /* @__PURE__ */ jsxs(
2065
+ Button,
2066
+ {
2067
+ variant: editor.isActive("taskList") ? "secondary" : "ghost",
2068
+ size: "sm",
2069
+ className: "w-full justify-start",
2070
+ onClick: () => select_block_type(() => editor.chain().focus().toggleTaskList().run()),
2071
+ children: [
2072
+ /* @__PURE__ */ jsx(LuListTodo, { className: "mr-2 h-4 w-4" }),
2073
+ "Task List"
2074
+ ]
2075
+ }
2076
+ ),
2077
+ /* @__PURE__ */ jsxs(
2078
+ Button,
2079
+ {
2080
+ variant: editor.isActive("blockquote") ? "secondary" : "ghost",
2081
+ size: "sm",
2082
+ className: "w-full justify-start",
2083
+ onClick: () => select_block_type(() => editor.chain().focus().toggleBlockquote().run()),
2084
+ children: [
2085
+ /* @__PURE__ */ jsx(LuQuote, { className: "mr-2 h-4 w-4" }),
2086
+ "Quote"
2087
+ ]
2088
+ }
2089
+ ),
2090
+ /* @__PURE__ */ jsxs(
2091
+ Button,
2092
+ {
2093
+ variant: editor.isActive("codeBlock") ? "secondary" : "ghost",
2094
+ size: "sm",
2095
+ className: "w-full justify-start",
2096
+ onClick: () => select_block_type(() => editor.chain().focus().toggleCodeBlock().run()),
2097
+ children: [
2098
+ /* @__PURE__ */ jsx(FiCode, { className: "mr-2 h-4 w-4" }),
2099
+ "Code Block"
2100
+ ]
2101
+ }
2102
+ )
2103
+ ] }) })
2104
+ ] }),
2105
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
2106
+ /* @__PURE__ */ jsx(
2107
+ ToolbarButton,
2108
+ {
2109
+ icon: /* @__PURE__ */ jsx(FiBold, { className: "h-4 w-4" }),
2110
+ label: "Bold",
2111
+ on_click: () => editor.chain().focus().toggleBold().run(),
2112
+ is_active: editor.isActive("bold")
2113
+ }
2114
+ ),
2115
+ /* @__PURE__ */ jsx(
2116
+ ToolbarButton,
2117
+ {
2118
+ icon: /* @__PURE__ */ jsx(FiItalic, { className: "h-4 w-4" }),
2119
+ label: "Italic",
2120
+ on_click: () => editor.chain().focus().toggleItalic().run(),
2121
+ is_active: editor.isActive("italic")
2122
+ }
2123
+ ),
2124
+ /* @__PURE__ */ jsx(
2125
+ ToolbarButton,
2126
+ {
2127
+ icon: /* @__PURE__ */ jsx(FiUnderline, { className: "h-4 w-4" }),
2128
+ label: "Underline",
2129
+ on_click: () => editor.chain().focus().toggleUnderline().run(),
2130
+ is_active: editor.isActive("underline")
2131
+ }
2132
+ ),
2133
+ /* @__PURE__ */ jsx(
2134
+ ToolbarButton,
2135
+ {
2136
+ icon: /* @__PURE__ */ jsx(LuStrikethrough, { className: "h-4 w-4" }),
2137
+ label: "Strikethrough",
2138
+ on_click: () => editor.chain().focus().toggleStrike().run(),
2139
+ is_active: editor.isActive("strike")
2140
+ }
2141
+ ),
2142
+ /* @__PURE__ */ jsx(
2143
+ ToolbarButton,
2144
+ {
2145
+ icon: /* @__PURE__ */ jsx(LuSubscript, { className: "h-4 w-4" }),
2146
+ label: "Subscript",
2147
+ on_click: () => editor.chain().focus().toggleSubscript().run(),
2148
+ is_active: editor.isActive("subscript")
2149
+ }
2150
+ ),
2151
+ /* @__PURE__ */ jsx(
2152
+ ToolbarButton,
2153
+ {
2154
+ icon: /* @__PURE__ */ jsx(LuSuperscript, { className: "h-4 w-4" }),
2155
+ label: "Superscript",
2156
+ on_click: () => editor.chain().focus().toggleSuperscript().run(),
2157
+ is_active: editor.isActive("superscript")
2158
+ }
2159
+ ),
2160
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
2161
+ /* @__PURE__ */ jsx(
2162
+ ColorPickerPopover,
2163
+ {
2164
+ color: current_text_color,
2165
+ on_color_change: (color) => editor.chain().focus().setColor(color).run(),
2166
+ trigger_icon: /* @__PURE__ */ jsx(FiType, { className: "h-4 w-4" }),
2167
+ trigger_label: "Text color"
2168
+ }
2169
+ ),
2170
+ /* @__PURE__ */ jsx(
2171
+ ColorPickerPopover,
2172
+ {
2173
+ color: current_highlight_color,
2174
+ on_color_change: (color) => editor.chain().focus().toggleHighlight({ color }).run(),
2175
+ trigger_icon: /* @__PURE__ */ jsx(LuHighlighter, { className: "h-4 w-4" }),
2176
+ trigger_label: "Highlight color"
2177
+ }
2178
+ ),
2179
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
2180
+ /* @__PURE__ */ jsx(
2181
+ ToolbarButton,
2182
+ {
2183
+ icon: /* @__PURE__ */ jsx(FiAlignLeft, { className: "h-4 w-4" }),
2184
+ label: "Align left",
2185
+ on_click: () => editor.chain().focus().setTextAlign("left").run(),
2186
+ is_active: editor.isActive({ textAlign: "left" })
2187
+ }
2188
+ ),
2189
+ /* @__PURE__ */ jsx(
2190
+ ToolbarButton,
2191
+ {
2192
+ icon: /* @__PURE__ */ jsx(FiAlignCenter, { className: "h-4 w-4" }),
2193
+ label: "Align center",
2194
+ on_click: () => editor.chain().focus().setTextAlign("center").run(),
2195
+ is_active: editor.isActive({ textAlign: "center" })
2196
+ }
2197
+ ),
2198
+ /* @__PURE__ */ jsx(
2199
+ ToolbarButton,
2200
+ {
2201
+ icon: /* @__PURE__ */ jsx(FiAlignRight, { className: "h-4 w-4" }),
2202
+ label: "Align right",
2203
+ on_click: () => editor.chain().focus().setTextAlign("right").run(),
2204
+ is_active: editor.isActive({ textAlign: "right" })
2205
+ }
2206
+ ),
2207
+ /* @__PURE__ */ jsx(
2208
+ ToolbarButton,
2209
+ {
2210
+ icon: /* @__PURE__ */ jsx(FiAlignJustify, { className: "h-4 w-4" }),
2211
+ label: "Justify",
2212
+ on_click: () => editor.chain().focus().setTextAlign("justify").run(),
2213
+ is_active: editor.isActive({ textAlign: "justify" })
2214
+ }
2215
+ ),
2216
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
2217
+ /* @__PURE__ */ jsxs(Popover, { open: is_link_popover_open, onOpenChange: set_is_link_popover_open, children: [
2218
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
2219
+ Button,
2220
+ {
2221
+ variant: "ghost",
2222
+ size: "sm",
2223
+ className: cn(
2224
+ "cls_toolbar_link h-8 w-8 p-0",
2225
+ editor.isActive("link") && "bg-accent text-accent-foreground"
2226
+ ),
2227
+ children: /* @__PURE__ */ jsx(FiLink, { className: "h-4 w-4" })
2228
+ }
2229
+ ) }),
2230
+ /* @__PURE__ */ jsx(PopoverContent, { className: "cls_link_popover w-72 p-3", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "cls_link_form space-y-2", children: [
2231
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Insert Link" }),
2232
+ /* @__PURE__ */ jsx(
2233
+ "input",
2234
+ {
2235
+ type: "url",
2236
+ placeholder: "https://example.com",
2237
+ value: link_url,
2238
+ onChange: (e) => set_link_url(e.target.value),
2239
+ className: "cls_link_input w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
2240
+ onKeyDown: (e) => e.key === "Enter" && handle_insert_link()
2241
+ }
2242
+ ),
2243
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
2244
+ editor.isActive("link") && /* @__PURE__ */ jsx(
2245
+ Button,
2246
+ {
2247
+ variant: "outline",
2248
+ size: "sm",
2249
+ onClick: () => {
2250
+ editor.chain().focus().unsetLink().run();
2251
+ set_is_link_popover_open(false);
2252
+ },
2253
+ children: "Remove"
2254
+ }
2255
+ ),
2256
+ /* @__PURE__ */ jsx(Button, { size: "sm", onClick: handle_insert_link, children: "Insert" })
2257
+ ] })
2258
+ ] }) })
2259
+ ] }),
2260
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
2261
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
2262
+ Button,
2263
+ {
2264
+ variant: "ghost",
2265
+ size: "sm",
2266
+ className: "cls_toolbar_image h-8 w-8 p-0",
2267
+ onClick: () => image_input_ref.current?.click(),
2268
+ disabled: is_uploading_image,
2269
+ children: /* @__PURE__ */ jsx(FiImage, { className: "h-4 w-4" })
2270
+ }
2271
+ ) }),
2272
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: "Insert image" }) })
2273
+ ] }),
2274
+ /* @__PURE__ */ jsx(
2275
+ "input",
2276
+ {
2277
+ ref: image_input_ref,
2278
+ type: "file",
2279
+ accept: "image/*",
2280
+ className: "hidden",
2281
+ onChange: handle_image_change
2282
+ }
2283
+ ),
2284
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
2285
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
2286
+ Button,
2287
+ {
2288
+ variant: "ghost",
2289
+ size: "sm",
2290
+ className: "cls_toolbar_attach h-8 w-8 p-0",
2291
+ onClick: () => attachment_input_ref.current?.click(),
2292
+ disabled: is_uploading_attachment,
2293
+ children: /* @__PURE__ */ jsx(FiPaperclip, { className: "h-4 w-4" })
2294
+ }
2295
+ ) }),
2296
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: "Add attachment" }) })
2297
+ ] }),
2298
+ /* @__PURE__ */ jsx(
2299
+ "input",
2300
+ {
2301
+ ref: attachment_input_ref,
2302
+ type: "file",
2303
+ accept: "image/*,.pdf,.doc,.docx,.xls,.xlsx,.txt,.zip,.rar",
2304
+ className: "hidden",
2305
+ onChange: handle_attachment_change
2306
+ }
2307
+ ),
2308
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
2309
+ /* @__PURE__ */ jsxs(Popover, { open: is_table_popover_open, onOpenChange: set_is_table_popover_open, children: [
2310
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
2311
+ Button,
2312
+ {
2313
+ variant: "ghost",
2314
+ size: "sm",
2315
+ className: cn(
2316
+ "cls_toolbar_table h-8 w-8 p-0",
2317
+ editor.isActive("table") && "bg-accent text-accent-foreground"
2318
+ ),
2319
+ children: /* @__PURE__ */ jsx(FiTable, { className: "h-4 w-4" })
2320
+ }
2321
+ ) }),
2322
+ /* @__PURE__ */ jsx(PopoverContent, { className: "cls_table_popover w-auto p-0", align: "start", children: /* @__PURE__ */ jsx(
2323
+ TableSizePicker,
2324
+ {
2325
+ max_rows: 6,
2326
+ max_cols: 6,
2327
+ on_select: handle_insert_table
2328
+ }
2329
+ ) })
2330
+ ] }),
2331
+ is_in_table && /* @__PURE__ */ jsxs(Popover, { open: is_table_controls_open, onOpenChange: set_is_table_controls_open, children: [
2332
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", className: "cls_toolbar_table_controls h-8 gap-1 px-2", children: [
2333
+ /* @__PURE__ */ jsx(LuTableProperties, { className: "h-4 w-4" }),
2334
+ /* @__PURE__ */ jsx(FiChevronDown, { className: "h-3 w-3" })
2335
+ ] }) }),
2336
+ /* @__PURE__ */ jsx(PopoverContent, { className: "cls_table_controls_popover w-48 p-1", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "cls_table_controls_list space-y-0.5", children: [
2337
+ /* @__PURE__ */ jsxs(
2338
+ Button,
2339
+ {
2340
+ variant: "ghost",
2341
+ size: "sm",
2342
+ className: "w-full justify-start",
2343
+ onClick: () => {
2344
+ editor.chain().focus().addRowAfter().run();
2345
+ set_is_table_controls_open(false);
2346
+ },
2347
+ children: [
2348
+ /* @__PURE__ */ jsx(RiInsertRowBottom, { className: "mr-2 h-4 w-4" }),
2349
+ "Add Row Below"
2350
+ ]
2351
+ }
2352
+ ),
2353
+ /* @__PURE__ */ jsxs(
2354
+ Button,
2355
+ {
2356
+ variant: "ghost",
2357
+ size: "sm",
2358
+ className: "w-full justify-start",
2359
+ onClick: () => {
2360
+ editor.chain().focus().addRowBefore().run();
2361
+ set_is_table_controls_open(false);
2362
+ },
2363
+ children: [
2364
+ /* @__PURE__ */ jsx(RiInsertRowBottom, { className: "mr-2 h-4 w-4 rotate-180" }),
2365
+ "Add Row Above"
2366
+ ]
2367
+ }
2368
+ ),
2369
+ /* @__PURE__ */ jsxs(
2370
+ Button,
2371
+ {
2372
+ variant: "ghost",
2373
+ size: "sm",
2374
+ className: "w-full justify-start",
2375
+ onClick: () => {
2376
+ editor.chain().focus().addColumnAfter().run();
2377
+ set_is_table_controls_open(false);
2378
+ },
2379
+ children: [
2380
+ /* @__PURE__ */ jsx(RiInsertColumnRight, { className: "mr-2 h-4 w-4" }),
2381
+ "Add Column Right"
2382
+ ]
2383
+ }
2384
+ ),
2385
+ /* @__PURE__ */ jsxs(
2386
+ Button,
2387
+ {
2388
+ variant: "ghost",
2389
+ size: "sm",
2390
+ className: "w-full justify-start",
2391
+ onClick: () => {
2392
+ editor.chain().focus().addColumnBefore().run();
2393
+ set_is_table_controls_open(false);
2394
+ },
2395
+ children: [
2396
+ /* @__PURE__ */ jsx(RiInsertColumnRight, { className: "mr-2 h-4 w-4 rotate-180" }),
2397
+ "Add Column Left"
2398
+ ]
2399
+ }
2400
+ ),
2401
+ /* @__PURE__ */ jsx("div", { className: "my-1 h-px bg-border" }),
2402
+ /* @__PURE__ */ jsxs(
2403
+ Button,
2404
+ {
2405
+ variant: "ghost",
2406
+ size: "sm",
2407
+ className: "w-full justify-start text-destructive hover:text-destructive",
2408
+ onClick: () => {
2409
+ editor.chain().focus().deleteRow().run();
2410
+ set_is_table_controls_open(false);
2411
+ },
2412
+ children: [
2413
+ /* @__PURE__ */ jsx(RiDeleteRow, { className: "mr-2 h-4 w-4" }),
2414
+ "Delete Row"
2415
+ ]
2416
+ }
2417
+ ),
2418
+ /* @__PURE__ */ jsxs(
2419
+ Button,
2420
+ {
2421
+ variant: "ghost",
2422
+ size: "sm",
2423
+ className: "w-full justify-start text-destructive hover:text-destructive",
2424
+ onClick: () => {
2425
+ editor.chain().focus().deleteColumn().run();
2426
+ set_is_table_controls_open(false);
2427
+ },
2428
+ children: [
2429
+ /* @__PURE__ */ jsx(RiDeleteColumn, { className: "mr-2 h-4 w-4" }),
2430
+ "Delete Column"
2431
+ ]
2432
+ }
2433
+ ),
2434
+ /* @__PURE__ */ jsxs(
2435
+ Button,
2436
+ {
2437
+ variant: "ghost",
2438
+ size: "sm",
2439
+ className: "w-full justify-start text-destructive hover:text-destructive",
2440
+ onClick: () => {
2441
+ editor.chain().focus().deleteTable().run();
2442
+ set_is_table_controls_open(false);
2443
+ },
2444
+ children: [
2445
+ /* @__PURE__ */ jsx(FiTrash2, { className: "mr-2 h-4 w-4" }),
2446
+ "Delete Table"
2447
+ ]
2448
+ }
2449
+ )
2450
+ ] }) })
2451
+ ] }),
2452
+ /* @__PURE__ */ jsx(
2453
+ ToolbarButton,
2454
+ {
2455
+ icon: /* @__PURE__ */ jsx(FiMinus, { className: "h-4 w-4" }),
2456
+ label: "Horizontal line",
2457
+ on_click: () => editor.chain().focus().setHorizontalRule().run()
2458
+ }
2459
+ ),
2460
+ /* @__PURE__ */ jsxs(Popover, { open: is_columns_popover_open, onOpenChange: set_is_columns_popover_open, children: [
2461
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", className: "cls_toolbar_columns h-8 w-8 p-0", children: /* @__PURE__ */ jsx(FiColumns, { className: "h-4 w-4" }) }) }),
2462
+ /* @__PURE__ */ jsx(PopoverContent, { className: "cls_columns_popover w-36 p-1", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "cls_columns_list space-y-0.5", children: [
2463
+ /* @__PURE__ */ jsxs(
2464
+ Button,
2465
+ {
2466
+ variant: "ghost",
2467
+ size: "sm",
2468
+ className: "w-full justify-start",
2469
+ onClick: () => {
2470
+ editor.chain().focus().insertColumnLayout(2).run();
2471
+ set_is_columns_popover_open(false);
2472
+ },
2473
+ children: [
2474
+ /* @__PURE__ */ jsx(LuColumns2, { className: "mr-2 h-4 w-4" }),
2475
+ "2 Columns"
2476
+ ]
2477
+ }
2478
+ ),
2479
+ /* @__PURE__ */ jsxs(
2480
+ Button,
2481
+ {
2482
+ variant: "ghost",
2483
+ size: "sm",
2484
+ className: "w-full justify-start",
2485
+ onClick: () => {
2486
+ editor.chain().focus().insertColumnLayout(3).run();
2487
+ set_is_columns_popover_open(false);
2488
+ },
2489
+ children: [
2490
+ /* @__PURE__ */ jsx(FiColumns, { className: "mr-2 h-4 w-4" }),
2491
+ "3 Columns"
2492
+ ]
2493
+ }
2494
+ )
2495
+ ] }) })
2496
+ ] }),
2497
+ variables && variables.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [
2498
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
2499
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
2500
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2501
+ Button,
2502
+ {
2503
+ variant: "ghost",
2504
+ size: "sm",
2505
+ onClick: on_open_variables_modal,
2506
+ className: "cls_toolbar_variables h-8 gap-1 px-2",
2507
+ children: [
2508
+ /* @__PURE__ */ jsx(BiBracket, { className: "h-4 w-4" }),
2509
+ /* @__PURE__ */ jsx("span", { className: "text-xs", children: "Variables" })
2510
+ ]
2511
+ }
2512
+ ) }),
2513
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: "Insert variable" }) })
2514
+ ] })
2515
+ ] }),
2516
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
2517
+ /* @__PURE__ */ jsx(
2518
+ ToolbarButton,
2519
+ {
2520
+ icon: /* @__PURE__ */ jsx(MdFormatClear, { className: "h-4 w-4" }),
2521
+ label: "Clear formatting",
2522
+ on_click: () => editor.chain().focus().unsetAllMarks().clearNodes().run()
2523
+ }
2524
+ )
2525
+ ] }) });
2526
+ }
2527
+ var Tabs = TabsPrimitive.Root;
2528
+ var TabsList = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2529
+ TabsPrimitive.List,
2530
+ {
2531
+ ref,
2532
+ className: cn(
2533
+ "cls_tabs_list inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
2534
+ className
2535
+ ),
2536
+ ...props
2537
+ }
2538
+ ));
2539
+ TabsList.displayName = TabsPrimitive.List.displayName;
2540
+ var TabsTrigger = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2541
+ TabsPrimitive.Trigger,
2542
+ {
2543
+ ref,
2544
+ className: cn(
2545
+ "cls_tabs_trigger inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
2546
+ className
2547
+ ),
2548
+ ...props
2549
+ }
2550
+ ));
2551
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
2552
+ var TabsContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2553
+ TabsPrimitive.Content,
2554
+ {
2555
+ ref,
2556
+ className: cn(
2557
+ "cls_tabs_content mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2558
+ className
2559
+ ),
2560
+ ...props
2561
+ }
2562
+ ));
2563
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
2564
+ function HtmlView({
2565
+ html_content,
2566
+ on_html_change,
2567
+ html_view_mode,
2568
+ on_html_view_mode_change,
2569
+ min_height,
2570
+ max_height,
2571
+ read_only
2572
+ }) {
2573
+ return /* @__PURE__ */ jsxs("div", { className: "cls_html_view", children: [
2574
+ /* @__PURE__ */ jsxs("div", { className: "cls_html_view_toggle flex items-center gap-1 p-2 border-b border-border bg-muted/30", children: [
2575
+ /* @__PURE__ */ jsxs(
2576
+ Button,
2577
+ {
2578
+ variant: html_view_mode === "preview" ? "secondary" : "ghost",
2579
+ size: "sm",
2580
+ onClick: () => on_html_view_mode_change("preview"),
2581
+ className: "h-7 gap-1 px-2",
2582
+ children: [
2583
+ /* @__PURE__ */ jsx(FiEye, { className: "h-3.5 w-3.5" }),
2584
+ /* @__PURE__ */ jsx("span", { className: "text-xs", children: "Preview" })
2585
+ ]
2586
+ }
2587
+ ),
2588
+ /* @__PURE__ */ jsxs(
2589
+ Button,
2590
+ {
2591
+ variant: html_view_mode === "code" ? "secondary" : "ghost",
2592
+ size: "sm",
2593
+ onClick: () => on_html_view_mode_change("code"),
2594
+ className: "h-7 gap-1 px-2",
2595
+ children: [
2596
+ /* @__PURE__ */ jsx(FiCode, { className: "h-3.5 w-3.5" }),
2597
+ /* @__PURE__ */ jsx("span", { className: "text-xs", children: "Code" })
2598
+ ]
2599
+ }
2600
+ )
2601
+ ] }),
2602
+ /* @__PURE__ */ jsx(
2603
+ "div",
2604
+ {
2605
+ className: "cls_html_view_content overflow-auto",
2606
+ style: {
2607
+ minHeight: min_height || DEFAULT_MIN_HEIGHT,
2608
+ maxHeight: max_height || DEFAULT_MAX_HEIGHT
2609
+ },
2610
+ children: html_view_mode === "preview" ? /* @__PURE__ */ jsx(
2611
+ "div",
2612
+ {
2613
+ className: "cls_html_preview prose prose-sm max-w-none p-4",
2614
+ dangerouslySetInnerHTML: { __html: html_content }
2615
+ }
2616
+ ) : /* @__PURE__ */ jsx(
2617
+ "textarea",
2618
+ {
2619
+ value: html_content,
2620
+ onChange: (e) => on_html_change(e.target.value),
2621
+ readOnly: read_only,
2622
+ className: cn(
2623
+ "cls_html_code w-full h-full p-4 font-mono text-sm",
2624
+ "bg-muted/20 resize-none border-none outline-none",
2625
+ "focus:ring-0"
2626
+ ),
2627
+ style: {
2628
+ minHeight: min_height || DEFAULT_MIN_HEIGHT
2629
+ },
2630
+ spellCheck: false
2631
+ }
2632
+ )
2633
+ }
2634
+ )
2635
+ ] });
2636
+ }
2637
+ function TextView({
2638
+ text_content,
2639
+ on_text_change,
2640
+ min_height,
2641
+ max_height,
2642
+ read_only
2643
+ }) {
2644
+ return /* @__PURE__ */ jsx(
2645
+ "div",
2646
+ {
2647
+ className: "cls_text_view overflow-auto",
2648
+ style: {
2649
+ minHeight: min_height || DEFAULT_MIN_HEIGHT,
2650
+ maxHeight: max_height || DEFAULT_MAX_HEIGHT
2651
+ },
2652
+ children: /* @__PURE__ */ jsx(
2653
+ "textarea",
2654
+ {
2655
+ value: text_content,
2656
+ onChange: (e) => on_text_change(e.target.value),
2657
+ readOnly: read_only,
2658
+ className: cn(
2659
+ "cls_text_area w-full h-full p-4 text-sm",
2660
+ "bg-background resize-none border-none outline-none",
2661
+ "focus:ring-0"
2662
+ ),
2663
+ style: {
2664
+ minHeight: min_height || DEFAULT_MIN_HEIGHT
2665
+ },
2666
+ spellCheck: true
2667
+ }
2668
+ )
2669
+ }
2670
+ );
2671
+ }
2672
+ function VisualView({ children, min_height, max_height }) {
2673
+ return /* @__PURE__ */ jsx(
2674
+ "div",
2675
+ {
2676
+ className: "cls_visual_view overflow-auto",
2677
+ style: {
2678
+ minHeight: min_height || DEFAULT_MIN_HEIGHT,
2679
+ maxHeight: max_height || DEFAULT_MAX_HEIGHT
2680
+ },
2681
+ children
2682
+ }
2683
+ );
2684
+ }
2685
+ function ViewTabs({
2686
+ active_tab,
2687
+ on_tab_change,
2688
+ // editor is unused but kept in props interface for consistency
2689
+ html_content,
2690
+ text_content,
2691
+ on_html_change,
2692
+ on_text_change,
2693
+ html_view_mode,
2694
+ on_html_view_mode_change,
2695
+ min_height,
2696
+ max_height,
2697
+ read_only,
2698
+ children
2699
+ }) {
2700
+ return /* @__PURE__ */ jsxs(
2701
+ Tabs,
2702
+ {
2703
+ value: active_tab,
2704
+ onValueChange: (value) => on_tab_change(value),
2705
+ className: "cls_view_tabs",
2706
+ children: [
2707
+ /* @__PURE__ */ jsx("div", { className: "cls_view_tabs_header flex items-center justify-between border-b border-border", children: /* @__PURE__ */ jsxs(TabsList, { className: "cls_view_tabs_list h-9 bg-transparent p-0 border-none rounded-none", children: [
2708
+ /* @__PURE__ */ jsx(
2709
+ TabsTrigger,
2710
+ {
2711
+ value: "visual",
2712
+ className: cn(
2713
+ "cls_view_tab_trigger rounded-none border-b-2 border-transparent px-4 py-2",
2714
+ "data-[state=active]:border-primary data-[state=active]:bg-transparent"
2715
+ ),
2716
+ children: "Visual"
2717
+ }
2718
+ ),
2719
+ /* @__PURE__ */ jsx(
2720
+ TabsTrigger,
2721
+ {
2722
+ value: "html",
2723
+ className: cn(
2724
+ "cls_view_tab_trigger rounded-none border-b-2 border-transparent px-4 py-2",
2725
+ "data-[state=active]:border-primary data-[state=active]:bg-transparent"
2726
+ ),
2727
+ children: "HTML"
2728
+ }
2729
+ ),
2730
+ /* @__PURE__ */ jsx(
2731
+ TabsTrigger,
2732
+ {
2733
+ value: "text",
2734
+ className: cn(
2735
+ "cls_view_tab_trigger rounded-none border-b-2 border-transparent px-4 py-2",
2736
+ "data-[state=active]:border-primary data-[state=active]:bg-transparent"
2737
+ ),
2738
+ children: "Text"
2739
+ }
2740
+ )
2741
+ ] }) }),
2742
+ /* @__PURE__ */ jsx(TabsContent, { value: "visual", className: "cls_view_tab_content mt-0", children: /* @__PURE__ */ jsx(VisualView, { min_height, max_height, children }) }),
2743
+ /* @__PURE__ */ jsx(TabsContent, { value: "html", className: "cls_view_tab_content mt-0", children: /* @__PURE__ */ jsx(
2744
+ HtmlView,
2745
+ {
2746
+ html_content,
2747
+ on_html_change,
2748
+ html_view_mode,
2749
+ on_html_view_mode_change,
2750
+ min_height,
2751
+ max_height,
2752
+ read_only
2753
+ }
2754
+ ) }),
2755
+ /* @__PURE__ */ jsx(TabsContent, { value: "text", className: "cls_view_tab_content mt-0", children: /* @__PURE__ */ jsx(
2756
+ TextView,
2757
+ {
2758
+ text_content,
2759
+ on_text_change,
2760
+ min_height,
2761
+ max_height,
2762
+ read_only
2763
+ }
2764
+ ) })
2765
+ ]
2766
+ }
2767
+ );
2768
+ }
2769
+ var ScrollArea = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
2770
+ ScrollAreaPrimitive.Root,
2771
+ {
2772
+ ref,
2773
+ className: cn("cls_scroll_area relative overflow-hidden", className),
2774
+ ...props,
2775
+ children: [
2776
+ /* @__PURE__ */ jsx(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
2777
+ /* @__PURE__ */ jsx(ScrollBar, {}),
2778
+ /* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
2779
+ ]
2780
+ }
2781
+ ));
2782
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
2783
+ var ScrollBar = React14.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
2784
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
2785
+ {
2786
+ ref,
2787
+ orientation,
2788
+ className: cn(
2789
+ "cls_scroll_bar flex touch-none select-none transition-colors",
2790
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
2791
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
2792
+ className
2793
+ ),
2794
+ ...props,
2795
+ children: /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaThumb, { className: "cls_scroll_thumb relative flex-1 rounded-full bg-border" })
2796
+ }
2797
+ ));
2798
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
2799
+ function group_variables_by_category(variables) {
2800
+ const grouped = /* @__PURE__ */ new Map();
2801
+ for (const variable of variables) {
2802
+ const category = variable.category || "General";
2803
+ const existing = grouped.get(category) || [];
2804
+ grouped.set(category, [...existing, variable]);
2805
+ }
2806
+ return grouped;
2807
+ }
2808
+ function VariablesModal({
2809
+ is_open,
2810
+ on_close,
2811
+ variables,
2812
+ on_select_variable
2813
+ }) {
2814
+ const [search_query, set_search_query] = React14.useState("");
2815
+ const filtered_variables = React14.useMemo(() => {
2816
+ if (!search_query.trim()) {
2817
+ return variables;
2818
+ }
2819
+ const query = search_query.toLowerCase();
2820
+ return variables.filter(
2821
+ (v) => v.text.toLowerCase().includes(query) || v.description.toLowerCase().includes(query) || v.category && v.category.toLowerCase().includes(query)
2822
+ );
2823
+ }, [variables, search_query]);
2824
+ const grouped_variables = React14.useMemo(
2825
+ () => group_variables_by_category(filtered_variables),
2826
+ [filtered_variables]
2827
+ );
2828
+ const handle_select = (variable) => {
2829
+ on_select_variable(variable);
2830
+ on_close();
2831
+ set_search_query("");
2832
+ };
2833
+ React14.useEffect(() => {
2834
+ if (!is_open) {
2835
+ set_search_query("");
2836
+ }
2837
+ }, [is_open]);
2838
+ return /* @__PURE__ */ jsx(Dialog, { open: is_open, onOpenChange: (open) => !open && on_close(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "cls_variables_modal sm:max-w-md", children: [
2839
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
2840
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Insert Variable" }),
2841
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Select a variable to insert into the editor. Variables will be replaced with actual values when the content is processed." })
2842
+ ] }),
2843
+ /* @__PURE__ */ jsxs("div", { className: "cls_variables_modal_search relative", children: [
2844
+ /* @__PURE__ */ jsx(FiSearch, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
2845
+ /* @__PURE__ */ jsx(
2846
+ Input,
2847
+ {
2848
+ placeholder: "Search variables...",
2849
+ value: search_query,
2850
+ onChange: (e) => set_search_query(e.target.value),
2851
+ className: "pl-9"
2852
+ }
2853
+ )
2854
+ ] }),
2855
+ /* @__PURE__ */ jsx(ScrollArea, { className: "cls_variables_modal_list h-[300px] pr-4", children: filtered_variables.length === 0 ? /* @__PURE__ */ jsx("div", { className: "cls_variables_modal_empty py-8 text-center text-muted-foreground", children: "No variables found" }) : /* @__PURE__ */ jsx("div", { className: "cls_variables_modal_groups space-y-4", children: Array.from(grouped_variables.entries()).map(([category, vars]) => /* @__PURE__ */ jsxs("div", { className: "cls_variables_modal_group", children: [
2856
+ /* @__PURE__ */ jsx("h4", { className: "cls_variables_modal_category mb-2 text-sm font-medium text-muted-foreground", children: category }),
2857
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: vars.map((variable) => /* @__PURE__ */ jsxs(
2858
+ "button",
2859
+ {
2860
+ onClick: () => handle_select(variable),
2861
+ className: cn(
2862
+ "cls_variable_item w-full text-left px-3 py-2 rounded-md",
2863
+ "hover:bg-accent transition-colors",
2864
+ "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
2865
+ ),
2866
+ children: [
2867
+ /* @__PURE__ */ jsx("div", { className: "cls_variable_item_name font-mono text-sm text-primary", children: `{{${variable.text}}}` }),
2868
+ /* @__PURE__ */ jsx("div", { className: "cls_variable_item_description text-xs text-muted-foreground mt-0.5", children: variable.description })
2869
+ ]
2870
+ },
2871
+ variable.text
2872
+ )) })
2873
+ ] }, category)) }) })
2874
+ ] }) });
2875
+ }
2876
+ var __defProp = Object.defineProperty;
2877
+ var __export = (target, all) => {
2878
+ for (var name in all)
2879
+ __defProp(target, name, { get: all[name], enumerable: true });
2880
+ };
2881
+ function createChainableState(config) {
2882
+ const { state, transaction } = config;
2883
+ let { selection } = transaction;
2884
+ let { doc } = transaction;
2885
+ let { storedMarks } = transaction;
2886
+ return {
2887
+ ...state,
2888
+ apply: state.apply.bind(state),
2889
+ applyTransaction: state.applyTransaction.bind(state),
2890
+ plugins: state.plugins,
2891
+ schema: state.schema,
2892
+ reconfigure: state.reconfigure.bind(state),
2893
+ toJSON: state.toJSON.bind(state),
2894
+ get storedMarks() {
2895
+ return storedMarks;
2896
+ },
2897
+ get selection() {
2898
+ return selection;
2899
+ },
2900
+ get doc() {
2901
+ return doc;
2902
+ },
2903
+ get tr() {
2904
+ selection = transaction.selection;
2905
+ doc = transaction.doc;
2906
+ storedMarks = transaction.storedMarks;
2907
+ return transaction;
2908
+ }
2909
+ };
2910
+ }
2911
+ var CommandManager = class {
2912
+ constructor(props) {
2913
+ this.editor = props.editor;
2914
+ this.rawCommands = this.editor.extensionManager.commands;
2915
+ this.customState = props.state;
2916
+ }
2917
+ get hasCustomState() {
2918
+ return !!this.customState;
2919
+ }
2920
+ get state() {
2921
+ return this.customState || this.editor.state;
2922
+ }
2923
+ get commands() {
2924
+ const { rawCommands, editor, state } = this;
2925
+ const { view } = editor;
2926
+ const { tr } = state;
2927
+ const props = this.buildProps(tr);
2928
+ return Object.fromEntries(
2929
+ Object.entries(rawCommands).map(([name, command2]) => {
2930
+ const method = (...args) => {
2931
+ const callback = command2(...args)(props);
2932
+ if (!tr.getMeta("preventDispatch") && !this.hasCustomState) {
2933
+ view.dispatch(tr);
2934
+ }
2935
+ return callback;
2936
+ };
2937
+ return [name, method];
2938
+ })
2939
+ );
2940
+ }
2941
+ get chain() {
2942
+ return () => this.createChain();
2943
+ }
2944
+ get can() {
2945
+ return () => this.createCan();
2946
+ }
2947
+ createChain(startTr, shouldDispatch = true) {
2948
+ const { rawCommands, editor, state } = this;
2949
+ const { view } = editor;
2950
+ const callbacks = [];
2951
+ const hasStartTransaction = !!startTr;
2952
+ const tr = startTr || state.tr;
2953
+ const run3 = () => {
2954
+ if (!hasStartTransaction && shouldDispatch && !tr.getMeta("preventDispatch") && !this.hasCustomState) {
2955
+ view.dispatch(tr);
2956
+ }
2957
+ return callbacks.every((callback) => callback === true);
2958
+ };
2959
+ const chain = {
2960
+ ...Object.fromEntries(
2961
+ Object.entries(rawCommands).map(([name, command2]) => {
2962
+ const chainedCommand = (...args) => {
2963
+ const props = this.buildProps(tr, shouldDispatch);
2964
+ const callback = command2(...args)(props);
2965
+ callbacks.push(callback);
2966
+ return chain;
2967
+ };
2968
+ return [name, chainedCommand];
2969
+ })
2970
+ ),
2971
+ run: run3
2972
+ };
2973
+ return chain;
2974
+ }
2975
+ createCan(startTr) {
2976
+ const { rawCommands, state } = this;
2977
+ const dispatch = false;
2978
+ const tr = startTr || state.tr;
2979
+ const props = this.buildProps(tr, dispatch);
2980
+ const formattedCommands = Object.fromEntries(
2981
+ Object.entries(rawCommands).map(([name, command2]) => {
2982
+ return [name, (...args) => command2(...args)({ ...props, dispatch: void 0 })];
2983
+ })
2984
+ );
2985
+ return {
2986
+ ...formattedCommands,
2987
+ chain: () => this.createChain(tr, dispatch)
2988
+ };
2989
+ }
2990
+ buildProps(tr, shouldDispatch = true) {
2991
+ const { rawCommands, editor, state } = this;
2992
+ const { view } = editor;
2993
+ const props = {
2994
+ tr,
2995
+ editor,
2996
+ view,
2997
+ state: createChainableState({
2998
+ state,
2999
+ transaction: tr
3000
+ }),
3001
+ dispatch: shouldDispatch ? () => void 0 : void 0,
3002
+ chain: () => this.createChain(tr, shouldDispatch),
3003
+ can: () => this.createCan(tr),
3004
+ get commands() {
3005
+ return Object.fromEntries(
3006
+ Object.entries(rawCommands).map(([name, command2]) => {
3007
+ return [name, (...args) => command2(...args)(props)];
3008
+ })
3009
+ );
3010
+ }
3011
+ };
3012
+ return props;
3013
+ }
3014
+ };
3015
+ var commands_exports = {};
3016
+ __export(commands_exports, {
3017
+ blur: () => blur,
3018
+ clearContent: () => clearContent,
3019
+ clearNodes: () => clearNodes,
3020
+ command: () => command,
3021
+ createParagraphNear: () => createParagraphNear,
3022
+ cut: () => cut,
3023
+ deleteCurrentNode: () => deleteCurrentNode,
3024
+ deleteNode: () => deleteNode,
3025
+ deleteRange: () => deleteRange,
3026
+ deleteSelection: () => deleteSelection,
3027
+ enter: () => enter,
3028
+ exitCode: () => exitCode,
3029
+ extendMarkRange: () => extendMarkRange,
3030
+ first: () => first,
3031
+ focus: () => focus,
3032
+ forEach: () => forEach,
3033
+ insertContent: () => insertContent,
3034
+ insertContentAt: () => insertContentAt,
3035
+ joinBackward: () => joinBackward,
3036
+ joinDown: () => joinDown,
3037
+ joinForward: () => joinForward,
3038
+ joinItemBackward: () => joinItemBackward,
3039
+ joinItemForward: () => joinItemForward,
3040
+ joinTextblockBackward: () => joinTextblockBackward,
3041
+ joinTextblockForward: () => joinTextblockForward,
3042
+ joinUp: () => joinUp,
3043
+ keyboardShortcut: () => keyboardShortcut,
3044
+ lift: () => lift,
3045
+ liftEmptyBlock: () => liftEmptyBlock,
3046
+ liftListItem: () => liftListItem,
3047
+ newlineInCode: () => newlineInCode,
3048
+ resetAttributes: () => resetAttributes,
3049
+ scrollIntoView: () => scrollIntoView,
3050
+ selectAll: () => selectAll,
3051
+ selectNodeBackward: () => selectNodeBackward,
3052
+ selectNodeForward: () => selectNodeForward,
3053
+ selectParentNode: () => selectParentNode,
3054
+ selectTextblockEnd: () => selectTextblockEnd,
3055
+ selectTextblockStart: () => selectTextblockStart,
3056
+ setContent: () => setContent,
3057
+ setMark: () => setMark,
3058
+ setMeta: () => setMeta,
3059
+ setNode: () => setNode,
3060
+ setNodeSelection: () => setNodeSelection,
3061
+ setTextDirection: () => setTextDirection,
3062
+ setTextSelection: () => setTextSelection,
3063
+ sinkListItem: () => sinkListItem,
3064
+ splitBlock: () => splitBlock,
3065
+ splitListItem: () => splitListItem,
3066
+ toggleList: () => toggleList,
3067
+ toggleMark: () => toggleMark,
3068
+ toggleNode: () => toggleNode,
3069
+ toggleWrap: () => toggleWrap,
3070
+ undoInputRule: () => undoInputRule,
3071
+ unsetAllMarks: () => unsetAllMarks,
3072
+ unsetMark: () => unsetMark,
3073
+ unsetTextDirection: () => unsetTextDirection,
3074
+ updateAttributes: () => updateAttributes,
3075
+ wrapIn: () => wrapIn,
3076
+ wrapInList: () => wrapInList
3077
+ });
3078
+ var blur = () => ({ editor, view }) => {
3079
+ requestAnimationFrame(() => {
3080
+ var _a;
3081
+ if (!editor.isDestroyed) {
3082
+ view.dom.blur();
3083
+ (_a = window == null ? void 0 : window.getSelection()) == null ? void 0 : _a.removeAllRanges();
3084
+ }
3085
+ });
3086
+ return true;
3087
+ };
3088
+ var clearContent = (emitUpdate = true) => ({ commands }) => {
3089
+ return commands.setContent("", { emitUpdate });
3090
+ };
3091
+ var clearNodes = () => ({ state, tr, dispatch }) => {
3092
+ const { selection } = tr;
3093
+ const { ranges } = selection;
3094
+ if (!dispatch) {
3095
+ return true;
3096
+ }
3097
+ ranges.forEach(({ $from, $to }) => {
3098
+ state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
3099
+ if (node.type.isText) {
3100
+ return;
3101
+ }
3102
+ const { doc, mapping } = tr;
3103
+ const $mappedFrom = doc.resolve(mapping.map(pos));
3104
+ const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
3105
+ const nodeRange = $mappedFrom.blockRange($mappedTo);
3106
+ if (!nodeRange) {
3107
+ return;
3108
+ }
3109
+ const targetLiftDepth = liftTarget(nodeRange);
3110
+ if (node.type.isTextblock) {
3111
+ const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
3112
+ tr.setNodeMarkup(nodeRange.start, defaultType);
3113
+ }
3114
+ if (targetLiftDepth || targetLiftDepth === 0) {
3115
+ tr.lift(nodeRange, targetLiftDepth);
3116
+ }
3117
+ });
3118
+ });
3119
+ return true;
3120
+ };
3121
+ var command = (fn) => (props) => {
3122
+ return fn(props);
3123
+ };
3124
+ var createParagraphNear = () => ({ state, dispatch }) => {
3125
+ return createParagraphNear$1(state, dispatch);
3126
+ };
3127
+ var cut = (originRange, targetPos) => ({ editor, tr }) => {
3128
+ const { state } = editor;
3129
+ const contentSlice = state.doc.slice(originRange.from, originRange.to);
3130
+ tr.deleteRange(originRange.from, originRange.to);
3131
+ const newPos = tr.mapping.map(targetPos);
3132
+ tr.insert(newPos, contentSlice.content);
3133
+ tr.setSelection(new TextSelection(tr.doc.resolve(Math.max(newPos - 1, 0))));
3134
+ return true;
3135
+ };
3136
+ var deleteCurrentNode = () => ({ tr, dispatch }) => {
3137
+ const { selection } = tr;
3138
+ const currentNode = selection.$anchor.node();
3139
+ if (currentNode.content.size > 0) {
3140
+ return false;
3141
+ }
3142
+ const $pos = tr.selection.$anchor;
3143
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
3144
+ const node = $pos.node(depth);
3145
+ if (node.type === currentNode.type) {
3146
+ if (dispatch) {
3147
+ const from = $pos.before(depth);
3148
+ const to = $pos.after(depth);
3149
+ tr.delete(from, to).scrollIntoView();
3150
+ }
3151
+ return true;
3152
+ }
3153
+ }
3154
+ return false;
3155
+ };
3156
+ function getNodeType(nameOrType, schema) {
3157
+ if (typeof nameOrType === "string") {
3158
+ if (!schema.nodes[nameOrType]) {
3159
+ throw Error(`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`);
3160
+ }
3161
+ return schema.nodes[nameOrType];
3162
+ }
3163
+ return nameOrType;
3164
+ }
3165
+ var deleteNode = (typeOrName) => ({ tr, state, dispatch }) => {
3166
+ const type = getNodeType(typeOrName, state.schema);
3167
+ const $pos = tr.selection.$anchor;
3168
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
3169
+ const node = $pos.node(depth);
3170
+ if (node.type === type) {
3171
+ if (dispatch) {
3172
+ const from = $pos.before(depth);
3173
+ const to = $pos.after(depth);
3174
+ tr.delete(from, to).scrollIntoView();
3175
+ }
3176
+ return true;
3177
+ }
3178
+ }
3179
+ return false;
3180
+ };
3181
+ var deleteRange = (range) => ({ tr, dispatch }) => {
3182
+ const { from, to } = range;
3183
+ if (dispatch) {
3184
+ tr.delete(from, to);
3185
+ }
3186
+ return true;
3187
+ };
3188
+ var deleteSelection = () => ({ state, dispatch }) => {
3189
+ return deleteSelection$1(state, dispatch);
3190
+ };
3191
+ var enter = () => ({ commands }) => {
3192
+ return commands.keyboardShortcut("Enter");
3193
+ };
3194
+ var exitCode = () => ({ state, dispatch }) => {
3195
+ return exitCode$1(state, dispatch);
3196
+ };
3197
+ function isRegExp(value) {
3198
+ return Object.prototype.toString.call(value) === "[object RegExp]";
3199
+ }
3200
+ function objectIncludes(object1, object2, options = { strict: true }) {
3201
+ const keys = Object.keys(object2);
3202
+ if (!keys.length) {
3203
+ return true;
3204
+ }
3205
+ return keys.every((key) => {
3206
+ if (options.strict) {
3207
+ return object2[key] === object1[key];
3208
+ }
3209
+ if (isRegExp(object2[key])) {
3210
+ return object2[key].test(object1[key]);
3211
+ }
3212
+ return object2[key] === object1[key];
3213
+ });
3214
+ }
3215
+ function findMarkInSet(marks, type, attributes = {}) {
3216
+ return marks.find((item) => {
3217
+ return item.type === type && objectIncludes(
3218
+ // Only check equality for the attributes that are provided
3219
+ Object.fromEntries(Object.keys(attributes).map((k) => [k, item.attrs[k]])),
3220
+ attributes
3221
+ );
3222
+ });
3223
+ }
3224
+ function isMarkInSet(marks, type, attributes = {}) {
3225
+ return !!findMarkInSet(marks, type, attributes);
3226
+ }
3227
+ function getMarkRange($pos, type, attributes) {
3228
+ var _a;
3229
+ if (!$pos || !type) {
3230
+ return;
3231
+ }
3232
+ let start = $pos.parent.childAfter($pos.parentOffset);
3233
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
3234
+ start = $pos.parent.childBefore($pos.parentOffset);
3235
+ }
3236
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
3237
+ return;
3238
+ }
3239
+ attributes = attributes || ((_a = start.node.marks[0]) == null ? void 0 : _a.attrs);
3240
+ const mark = findMarkInSet([...start.node.marks], type, attributes);
3241
+ if (!mark) {
3242
+ return;
3243
+ }
3244
+ let startIndex = start.index;
3245
+ let startPos = $pos.start() + start.offset;
3246
+ let endIndex = startIndex + 1;
3247
+ let endPos = startPos + start.node.nodeSize;
3248
+ while (startIndex > 0 && isMarkInSet([...$pos.parent.child(startIndex - 1).marks], type, attributes)) {
3249
+ startIndex -= 1;
3250
+ startPos -= $pos.parent.child(startIndex).nodeSize;
3251
+ }
3252
+ while (endIndex < $pos.parent.childCount && isMarkInSet([...$pos.parent.child(endIndex).marks], type, attributes)) {
3253
+ endPos += $pos.parent.child(endIndex).nodeSize;
3254
+ endIndex += 1;
3255
+ }
3256
+ return {
3257
+ from: startPos,
3258
+ to: endPos
3259
+ };
3260
+ }
3261
+ function getMarkType(nameOrType, schema) {
3262
+ if (typeof nameOrType === "string") {
3263
+ if (!schema.marks[nameOrType]) {
3264
+ throw Error(`There is no mark type named '${nameOrType}'. Maybe you forgot to add the extension?`);
3265
+ }
3266
+ return schema.marks[nameOrType];
3267
+ }
3268
+ return nameOrType;
3269
+ }
3270
+ var extendMarkRange = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
3271
+ const type = getMarkType(typeOrName, state.schema);
3272
+ const { doc, selection } = tr;
3273
+ const { $from, from, to } = selection;
3274
+ if (dispatch) {
3275
+ const range = getMarkRange($from, type, attributes);
3276
+ if (range && range.from <= from && range.to >= to) {
3277
+ const newSelection = TextSelection.create(doc, range.from, range.to);
3278
+ tr.setSelection(newSelection);
3279
+ }
3280
+ }
3281
+ return true;
3282
+ };
3283
+ var first = (commands) => (props) => {
3284
+ const items = typeof commands === "function" ? commands(props) : commands;
3285
+ for (let i = 0; i < items.length; i += 1) {
3286
+ if (items[i](props)) {
3287
+ return true;
3288
+ }
3289
+ }
3290
+ return false;
3291
+ };
3292
+ function isTextSelection(value) {
3293
+ return value instanceof TextSelection;
3294
+ }
3295
+ function minMax(value = 0, min = 0, max = 0) {
3296
+ return Math.min(Math.max(value, min), max);
3297
+ }
3298
+ function resolveFocusPosition(doc, position = null) {
3299
+ if (!position) {
3300
+ return null;
3301
+ }
3302
+ const selectionAtStart = Selection.atStart(doc);
3303
+ const selectionAtEnd = Selection.atEnd(doc);
3304
+ if (position === "start" || position === true) {
3305
+ return selectionAtStart;
3306
+ }
3307
+ if (position === "end") {
3308
+ return selectionAtEnd;
3309
+ }
3310
+ const minPos = selectionAtStart.from;
3311
+ const maxPos = selectionAtEnd.to;
3312
+ if (position === "all") {
3313
+ return TextSelection.create(doc, minMax(0, minPos, maxPos), minMax(doc.content.size, minPos, maxPos));
3314
+ }
3315
+ return TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
3316
+ }
3317
+ function isAndroid() {
3318
+ return navigator.platform === "Android" || /android/i.test(navigator.userAgent);
3319
+ }
3320
+ function isiOS() {
3321
+ return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || // iPad on iOS 13 detection
3322
+ navigator.userAgent.includes("Mac") && "ontouchend" in document;
3323
+ }
3324
+ var focus = (position = null, options = {}) => ({ editor, view, tr, dispatch }) => {
3325
+ options = {
3326
+ scrollIntoView: true,
3327
+ ...options
3328
+ };
3329
+ const delayedFocus = () => {
3330
+ if (isiOS() || isAndroid()) {
3331
+ view.dom.focus();
3332
+ }
3333
+ requestAnimationFrame(() => {
3334
+ if (!editor.isDestroyed) {
3335
+ view.focus();
3336
+ if (options == null ? void 0 : options.scrollIntoView) {
3337
+ editor.commands.scrollIntoView();
3338
+ }
3339
+ }
3340
+ });
3341
+ };
3342
+ if (view.hasFocus() && position === null || position === false) {
3343
+ return true;
3344
+ }
3345
+ if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
3346
+ delayedFocus();
3347
+ return true;
3348
+ }
3349
+ const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection;
3350
+ const isSameSelection = editor.state.selection.eq(selection);
3351
+ if (dispatch) {
3352
+ if (!isSameSelection) {
3353
+ tr.setSelection(selection);
3354
+ }
3355
+ if (isSameSelection && tr.storedMarks) {
3356
+ tr.setStoredMarks(tr.storedMarks);
3357
+ }
3358
+ delayedFocus();
3359
+ }
3360
+ return true;
3361
+ };
3362
+ var forEach = (items, fn) => (props) => {
3363
+ return items.every((item, index) => fn(item, { ...props, index }));
3364
+ };
3365
+ var insertContent = (value, options) => ({ tr, commands }) => {
3366
+ return commands.insertContentAt({ from: tr.selection.from, to: tr.selection.to }, value, options);
3367
+ };
3368
+ var removeWhitespaces = (node) => {
3369
+ const children = node.childNodes;
3370
+ for (let i = children.length - 1; i >= 0; i -= 1) {
3371
+ const child = children[i];
3372
+ if (child.nodeType === 3 && child.nodeValue && /^(\n\s\s|\n)$/.test(child.nodeValue)) {
3373
+ node.removeChild(child);
3374
+ } else if (child.nodeType === 1) {
3375
+ removeWhitespaces(child);
3376
+ }
3377
+ }
3378
+ return node;
3379
+ };
3380
+ function elementFromString(value) {
3381
+ if (typeof window === "undefined") {
3382
+ throw new Error("[tiptap error]: there is no window object available, so this function cannot be used");
3383
+ }
3384
+ const wrappedValue = `<body>${value}</body>`;
3385
+ const html = new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
3386
+ return removeWhitespaces(html);
3387
+ }
3388
+ function createNodeFromContent(content, schema, options) {
3389
+ if (content instanceof Node || content instanceof Fragment) {
3390
+ return content;
3391
+ }
3392
+ options = {
3393
+ slice: true,
3394
+ parseOptions: {},
3395
+ ...options
3396
+ };
3397
+ const isJSONContent = typeof content === "object" && content !== null;
3398
+ const isTextContent = typeof content === "string";
3399
+ if (isJSONContent) {
3400
+ try {
3401
+ const isArrayContent = Array.isArray(content) && content.length > 0;
3402
+ if (isArrayContent) {
3403
+ return Fragment.fromArray(content.map((item) => schema.nodeFromJSON(item)));
3404
+ }
3405
+ const node = schema.nodeFromJSON(content);
3406
+ if (options.errorOnInvalidContent) {
3407
+ node.check();
3408
+ }
3409
+ return node;
3410
+ } catch (error) {
3411
+ if (options.errorOnInvalidContent) {
3412
+ throw new Error("[tiptap error]: Invalid JSON content", { cause: error });
3413
+ }
3414
+ console.warn("[tiptap warn]: Invalid content.", "Passed value:", content, "Error:", error);
3415
+ return createNodeFromContent("", schema, options);
3416
+ }
3417
+ }
3418
+ if (isTextContent) {
3419
+ if (options.errorOnInvalidContent) {
3420
+ let hasInvalidContent = false;
3421
+ let invalidContent = "";
3422
+ const contentCheckSchema = new Schema({
3423
+ topNode: schema.spec.topNode,
3424
+ marks: schema.spec.marks,
3425
+ // Prosemirror's schemas are executed such that: the last to execute, matches last
3426
+ // This means that we can add a catch-all node at the end of the schema to catch any content that we don't know how to handle
3427
+ nodes: schema.spec.nodes.append({
3428
+ __tiptap__private__unknown__catch__all__node: {
3429
+ content: "inline*",
3430
+ group: "block",
3431
+ parseDOM: [
3432
+ {
3433
+ tag: "*",
3434
+ getAttrs: (e) => {
3435
+ hasInvalidContent = true;
3436
+ invalidContent = typeof e === "string" ? e : e.outerHTML;
3437
+ return null;
3438
+ }
3439
+ }
3440
+ ]
3441
+ }
3442
+ })
3443
+ });
3444
+ if (options.slice) {
3445
+ DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
3446
+ } else {
3447
+ DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
3448
+ }
3449
+ if (options.errorOnInvalidContent && hasInvalidContent) {
3450
+ throw new Error("[tiptap error]: Invalid HTML content", {
3451
+ cause: new Error(`Invalid element found: ${invalidContent}`)
3452
+ });
3453
+ }
3454
+ }
3455
+ const parser = DOMParser.fromSchema(schema);
3456
+ if (options.slice) {
3457
+ return parser.parseSlice(elementFromString(content), options.parseOptions).content;
3458
+ }
3459
+ return parser.parse(elementFromString(content), options.parseOptions);
3460
+ }
3461
+ return createNodeFromContent("", schema, options);
3462
+ }
3463
+ function selectionToInsertionEnd(tr, startLen, bias) {
3464
+ const last = tr.steps.length - 1;
3465
+ if (last < startLen) {
3466
+ return;
3467
+ }
3468
+ const step = tr.steps[last];
3469
+ if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) {
3470
+ return;
3471
+ }
3472
+ const map = tr.mapping.maps[last];
3473
+ let end = 0;
3474
+ map.forEach((_from, _to, _newFrom, newTo) => {
3475
+ if (end === 0) {
3476
+ end = newTo;
3477
+ }
3478
+ });
3479
+ tr.setSelection(Selection.near(tr.doc.resolve(end), bias));
3480
+ }
3481
+ var isFragment = (nodeOrFragment) => {
3482
+ return !("type" in nodeOrFragment);
3483
+ };
3484
+ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) => {
3485
+ var _a;
3486
+ if (dispatch) {
3487
+ options = {
3488
+ parseOptions: editor.options.parseOptions,
3489
+ updateSelection: true,
3490
+ applyInputRules: false,
3491
+ applyPasteRules: false,
3492
+ ...options
3493
+ };
3494
+ let content;
3495
+ const emitContentError = (error) => {
3496
+ editor.emit("contentError", {
3497
+ editor,
3498
+ error,
3499
+ disableCollaboration: () => {
3500
+ if ("collaboration" in editor.storage && typeof editor.storage.collaboration === "object" && editor.storage.collaboration) {
3501
+ editor.storage.collaboration.isDisabled = true;
3502
+ }
3503
+ }
3504
+ });
3505
+ };
3506
+ const parseOptions = {
3507
+ preserveWhitespace: "full",
3508
+ ...options.parseOptions
3509
+ };
3510
+ if (!options.errorOnInvalidContent && !editor.options.enableContentCheck && editor.options.emitContentError) {
3511
+ try {
3512
+ createNodeFromContent(value, editor.schema, {
3513
+ parseOptions,
3514
+ errorOnInvalidContent: true
3515
+ });
3516
+ } catch (e) {
3517
+ emitContentError(e);
3518
+ }
3519
+ }
3520
+ try {
3521
+ content = createNodeFromContent(value, editor.schema, {
3522
+ parseOptions,
3523
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) != null ? _a : editor.options.enableContentCheck
3524
+ });
3525
+ } catch (e) {
3526
+ emitContentError(e);
3527
+ return false;
3528
+ }
3529
+ let { from, to } = typeof position === "number" ? { from: position, to: position } : { from: position.from, to: position.to };
3530
+ let isOnlyTextContent = true;
3531
+ let isOnlyBlockContent = true;
3532
+ const nodes = isFragment(content) ? content : [content];
3533
+ nodes.forEach((node) => {
3534
+ node.check();
3535
+ isOnlyTextContent = isOnlyTextContent ? node.isText && node.marks.length === 0 : false;
3536
+ isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;
3537
+ });
3538
+ if (from === to && isOnlyBlockContent) {
3539
+ const { parent } = tr.doc.resolve(from);
3540
+ const isEmptyTextBlock = parent.isTextblock && !parent.type.spec.code && !parent.childCount;
3541
+ if (isEmptyTextBlock) {
3542
+ from -= 1;
3543
+ to += 1;
3544
+ }
3545
+ }
3546
+ let newContent;
3547
+ if (isOnlyTextContent) {
3548
+ if (Array.isArray(value)) {
3549
+ newContent = value.map((v) => v.text || "").join("");
3550
+ } else if (value instanceof Fragment) {
3551
+ let text = "";
3552
+ value.forEach((node) => {
3553
+ if (node.text) {
3554
+ text += node.text;
3555
+ }
3556
+ });
3557
+ newContent = text;
3558
+ } else if (typeof value === "object" && !!value && !!value.text) {
3559
+ newContent = value.text;
3560
+ } else {
3561
+ newContent = value;
3562
+ }
3563
+ tr.insertText(newContent, from, to);
3564
+ } else {
3565
+ newContent = content;
3566
+ const $from = tr.doc.resolve(from);
3567
+ const $fromNode = $from.node();
3568
+ const fromSelectionAtStart = $from.parentOffset === 0;
3569
+ const isTextSelection2 = $fromNode.isText || $fromNode.isTextblock;
3570
+ const hasContent = $fromNode.content.size > 0;
3571
+ if (fromSelectionAtStart && isTextSelection2 && hasContent) {
3572
+ from = Math.max(0, from - 1);
3573
+ }
3574
+ tr.replaceWith(from, to, newContent);
3575
+ }
3576
+ if (options.updateSelection) {
3577
+ selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
3578
+ }
3579
+ if (options.applyInputRules) {
3580
+ tr.setMeta("applyInputRules", { from, text: newContent });
3581
+ }
3582
+ if (options.applyPasteRules) {
3583
+ tr.setMeta("applyPasteRules", { from, text: newContent });
3584
+ }
3585
+ }
3586
+ return true;
3587
+ };
3588
+ var joinUp = () => ({ state, dispatch }) => {
3589
+ return joinUp$1(state, dispatch);
3590
+ };
3591
+ var joinDown = () => ({ state, dispatch }) => {
3592
+ return joinDown$1(state, dispatch);
3593
+ };
3594
+ var joinBackward = () => ({ state, dispatch }) => {
3595
+ return joinBackward$1(state, dispatch);
3596
+ };
3597
+ var joinForward = () => ({ state, dispatch }) => {
3598
+ return joinForward$1(state, dispatch);
3599
+ };
3600
+ var joinItemBackward = () => ({ state, dispatch, tr }) => {
3601
+ try {
3602
+ const point = joinPoint(state.doc, state.selection.$from.pos, -1);
3603
+ if (point === null || point === void 0) {
3604
+ return false;
3605
+ }
3606
+ tr.join(point, 2);
3607
+ if (dispatch) {
3608
+ dispatch(tr);
3609
+ }
3610
+ return true;
3611
+ } catch {
3612
+ return false;
3613
+ }
3614
+ };
3615
+ var joinItemForward = () => ({ state, dispatch, tr }) => {
3616
+ try {
3617
+ const point = joinPoint(state.doc, state.selection.$from.pos, 1);
3618
+ if (point === null || point === void 0) {
3619
+ return false;
3620
+ }
3621
+ tr.join(point, 2);
3622
+ if (dispatch) {
3623
+ dispatch(tr);
3624
+ }
3625
+ return true;
3626
+ } catch {
3627
+ return false;
3628
+ }
3629
+ };
3630
+ var joinTextblockBackward = () => ({ state, dispatch }) => {
3631
+ return joinTextblockBackward$1(state, dispatch);
3632
+ };
3633
+ var joinTextblockForward = () => ({ state, dispatch }) => {
3634
+ return joinTextblockForward$1(state, dispatch);
3635
+ };
3636
+ function isMacOS() {
3637
+ return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
3638
+ }
3639
+ function normalizeKeyName(name) {
3640
+ const parts = name.split(/-(?!$)/);
3641
+ let result = parts[parts.length - 1];
3642
+ if (result === "Space") {
3643
+ result = " ";
3644
+ }
3645
+ let alt;
3646
+ let ctrl;
3647
+ let shift;
3648
+ let meta;
3649
+ for (let i = 0; i < parts.length - 1; i += 1) {
3650
+ const mod = parts[i];
3651
+ if (/^(cmd|meta|m)$/i.test(mod)) {
3652
+ meta = true;
3653
+ } else if (/^a(lt)?$/i.test(mod)) {
3654
+ alt = true;
3655
+ } else if (/^(c|ctrl|control)$/i.test(mod)) {
3656
+ ctrl = true;
3657
+ } else if (/^s(hift)?$/i.test(mod)) {
3658
+ shift = true;
3659
+ } else if (/^mod$/i.test(mod)) {
3660
+ if (isiOS() || isMacOS()) {
3661
+ meta = true;
3662
+ } else {
3663
+ ctrl = true;
3664
+ }
3665
+ } else {
3666
+ throw new Error(`Unrecognized modifier name: ${mod}`);
3667
+ }
3668
+ }
3669
+ if (alt) {
3670
+ result = `Alt-${result}`;
3671
+ }
3672
+ if (ctrl) {
3673
+ result = `Ctrl-${result}`;
3674
+ }
3675
+ if (meta) {
3676
+ result = `Meta-${result}`;
3677
+ }
3678
+ if (shift) {
3679
+ result = `Shift-${result}`;
3680
+ }
3681
+ return result;
3682
+ }
3683
+ var keyboardShortcut = (name) => ({ editor, view, tr, dispatch }) => {
3684
+ const keys = normalizeKeyName(name).split(/-(?!$)/);
3685
+ const key = keys.find((item) => !["Alt", "Ctrl", "Meta", "Shift"].includes(item));
3686
+ const event = new KeyboardEvent("keydown", {
3687
+ key: key === "Space" ? " " : key,
3688
+ altKey: keys.includes("Alt"),
3689
+ ctrlKey: keys.includes("Ctrl"),
3690
+ metaKey: keys.includes("Meta"),
3691
+ shiftKey: keys.includes("Shift"),
3692
+ bubbles: true,
3693
+ cancelable: true
3694
+ });
3695
+ const capturedTransaction = editor.captureTransaction(() => {
3696
+ view.someProp("handleKeyDown", (f) => f(view, event));
3697
+ });
3698
+ capturedTransaction == null ? void 0 : capturedTransaction.steps.forEach((step) => {
3699
+ const newStep = step.map(tr.mapping);
3700
+ if (newStep && dispatch) {
3701
+ tr.maybeStep(newStep);
3702
+ }
3703
+ });
3704
+ return true;
3705
+ };
3706
+ function isNodeActive(state, typeOrName, attributes = {}) {
3707
+ const { from, to, empty } = state.selection;
3708
+ const type = typeOrName ? getNodeType(typeOrName, state.schema) : null;
3709
+ const nodeRanges = [];
3710
+ state.doc.nodesBetween(from, to, (node, pos) => {
3711
+ if (node.isText) {
3712
+ return;
3713
+ }
3714
+ const relativeFrom = Math.max(from, pos);
3715
+ const relativeTo = Math.min(to, pos + node.nodeSize);
3716
+ nodeRanges.push({
3717
+ node,
3718
+ from: relativeFrom,
3719
+ to: relativeTo
3720
+ });
3721
+ });
3722
+ const selectionRange = to - from;
3723
+ const matchedNodeRanges = nodeRanges.filter((nodeRange) => {
3724
+ if (!type) {
3725
+ return true;
3726
+ }
3727
+ return type.name === nodeRange.node.type.name;
3728
+ }).filter((nodeRange) => objectIncludes(nodeRange.node.attrs, attributes, { strict: false }));
3729
+ if (empty) {
3730
+ return !!matchedNodeRanges.length;
3731
+ }
3732
+ const range = matchedNodeRanges.reduce((sum, nodeRange) => sum + nodeRange.to - nodeRange.from, 0);
3733
+ return range >= selectionRange;
3734
+ }
3735
+ var lift = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
3736
+ const type = getNodeType(typeOrName, state.schema);
3737
+ const isActive2 = isNodeActive(state, type, attributes);
3738
+ if (!isActive2) {
3739
+ return false;
3740
+ }
3741
+ return lift$1(state, dispatch);
3742
+ };
3743
+ var liftEmptyBlock = () => ({ state, dispatch }) => {
3744
+ return liftEmptyBlock$1(state, dispatch);
3745
+ };
3746
+ var liftListItem = (typeOrName) => ({ state, dispatch }) => {
3747
+ const type = getNodeType(typeOrName, state.schema);
3748
+ return liftListItem$1(type)(state, dispatch);
3749
+ };
3750
+ var newlineInCode = () => ({ state, dispatch }) => {
3751
+ return newlineInCode$1(state, dispatch);
3752
+ };
3753
+ function getSchemaTypeNameByName(name, schema) {
3754
+ if (schema.nodes[name]) {
3755
+ return "node";
3756
+ }
3757
+ if (schema.marks[name]) {
3758
+ return "mark";
3759
+ }
3760
+ return null;
3761
+ }
3762
+ function deleteProps(obj, propOrProps) {
3763
+ const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
3764
+ return Object.keys(obj).reduce((newObj, prop) => {
3765
+ if (!props.includes(prop)) {
3766
+ newObj[prop] = obj[prop];
3767
+ }
3768
+ return newObj;
3769
+ }, {});
3770
+ }
3771
+ var resetAttributes = (typeOrName, attributes) => ({ tr, state, dispatch }) => {
3772
+ let nodeType = null;
3773
+ let markType = null;
3774
+ const schemaType = getSchemaTypeNameByName(
3775
+ typeof typeOrName === "string" ? typeOrName : typeOrName.name,
3776
+ state.schema
3777
+ );
3778
+ if (!schemaType) {
3779
+ return false;
3780
+ }
3781
+ if (schemaType === "node") {
3782
+ nodeType = getNodeType(typeOrName, state.schema);
3783
+ }
3784
+ if (schemaType === "mark") {
3785
+ markType = getMarkType(typeOrName, state.schema);
3786
+ }
3787
+ let canReset = false;
3788
+ tr.selection.ranges.forEach((range) => {
3789
+ state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
3790
+ if (nodeType && nodeType === node.type) {
3791
+ canReset = true;
3792
+ if (dispatch) {
3793
+ tr.setNodeMarkup(pos, void 0, deleteProps(node.attrs, attributes));
3794
+ }
3795
+ }
3796
+ if (markType && node.marks.length) {
3797
+ node.marks.forEach((mark) => {
3798
+ if (markType === mark.type) {
3799
+ canReset = true;
3800
+ if (dispatch) {
3801
+ tr.addMark(pos, pos + node.nodeSize, markType.create(deleteProps(mark.attrs, attributes)));
3802
+ }
3803
+ }
3804
+ });
3805
+ }
3806
+ });
3807
+ });
3808
+ return canReset;
3809
+ };
3810
+ var scrollIntoView = () => ({ tr, dispatch }) => {
3811
+ if (dispatch) {
3812
+ tr.scrollIntoView();
3813
+ }
3814
+ return true;
3815
+ };
3816
+ var selectAll = () => ({ tr, dispatch }) => {
3817
+ if (dispatch) {
3818
+ const selection = new AllSelection(tr.doc);
3819
+ tr.setSelection(selection);
3820
+ }
3821
+ return true;
3822
+ };
3823
+ var selectNodeBackward = () => ({ state, dispatch }) => {
3824
+ return selectNodeBackward$1(state, dispatch);
3825
+ };
3826
+ var selectNodeForward = () => ({ state, dispatch }) => {
3827
+ return selectNodeForward$1(state, dispatch);
3828
+ };
3829
+ var selectParentNode = () => ({ state, dispatch }) => {
3830
+ return selectParentNode$1(state, dispatch);
3831
+ };
3832
+ var selectTextblockEnd = () => ({ state, dispatch }) => {
3833
+ return selectTextblockEnd$1(state, dispatch);
3834
+ };
3835
+ var selectTextblockStart = () => ({ state, dispatch }) => {
3836
+ return selectTextblockStart$1(state, dispatch);
3837
+ };
3838
+ function createDocument(content, schema, parseOptions = {}, options = {}) {
3839
+ return createNodeFromContent(content, schema, {
3840
+ slice: false,
3841
+ parseOptions,
3842
+ errorOnInvalidContent: options.errorOnInvalidContent
3843
+ });
3844
+ }
3845
+ var setContent = (content, { errorOnInvalidContent, emitUpdate = true, parseOptions = {} } = {}) => ({ editor, tr, dispatch, commands }) => {
3846
+ const { doc } = tr;
3847
+ if (parseOptions.preserveWhitespace !== "full") {
3848
+ const document2 = createDocument(content, editor.schema, parseOptions, {
3849
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
3850
+ });
3851
+ if (dispatch) {
3852
+ tr.replaceWith(0, doc.content.size, document2).setMeta("preventUpdate", !emitUpdate);
3853
+ }
3854
+ return true;
3855
+ }
3856
+ if (dispatch) {
3857
+ tr.setMeta("preventUpdate", !emitUpdate);
3858
+ }
3859
+ return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
3860
+ parseOptions,
3861
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
3862
+ });
3863
+ };
3864
+ function getMarkAttributes(state, typeOrName) {
3865
+ const type = getMarkType(typeOrName, state.schema);
3866
+ const { from, to, empty } = state.selection;
3867
+ const marks = [];
3868
+ if (empty) {
3869
+ if (state.storedMarks) {
3870
+ marks.push(...state.storedMarks);
3871
+ }
3872
+ marks.push(...state.selection.$head.marks());
3873
+ } else {
3874
+ state.doc.nodesBetween(from, to, (node) => {
3875
+ marks.push(...node.marks);
3876
+ });
3877
+ }
3878
+ const mark = marks.find((markItem) => markItem.type.name === type.name);
3879
+ if (!mark) {
3880
+ return {};
3881
+ }
3882
+ return { ...mark.attrs };
3883
+ }
3884
+ function combineTransactionSteps(oldDoc, transactions) {
3885
+ const transform = new Transform(oldDoc);
3886
+ transactions.forEach((transaction) => {
3887
+ transaction.steps.forEach((step) => {
3888
+ transform.step(step);
3889
+ });
3890
+ });
3891
+ return transform;
3892
+ }
3893
+ function defaultBlockAt(match) {
3894
+ for (let i = 0; i < match.edgeCount; i += 1) {
3895
+ const { type } = match.edge(i);
3896
+ if (type.isTextblock && !type.hasRequiredAttrs()) {
3897
+ return type;
3898
+ }
3899
+ }
3900
+ return null;
3901
+ }
3902
+ function findParentNodeClosestToPos($pos, predicate) {
3903
+ for (let i = $pos.depth; i > 0; i -= 1) {
3904
+ const node = $pos.node(i);
3905
+ if (predicate(node)) {
3906
+ return {
3907
+ pos: i > 0 ? $pos.before(i) : 0,
3908
+ start: $pos.start(i),
3909
+ depth: i,
3910
+ node
3911
+ };
3912
+ }
3913
+ }
3914
+ }
3915
+ function findParentNode(predicate) {
3916
+ return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
3917
+ }
3918
+ function getExtensionField(extension, field, context) {
3919
+ if (extension.config[field] === void 0 && extension.parent) {
3920
+ return getExtensionField(extension.parent, field, context);
3921
+ }
3922
+ if (typeof extension.config[field] === "function") {
3923
+ const value = extension.config[field].bind({
3924
+ ...context,
3925
+ parent: extension.parent ? getExtensionField(extension.parent, field, context) : null
3926
+ });
3927
+ return value;
3928
+ }
3929
+ return extension.config[field];
3930
+ }
3931
+ function isFunction(value) {
3932
+ return typeof value === "function";
3933
+ }
3934
+ function callOrReturn(value, context = void 0, ...props) {
3935
+ if (isFunction(value)) {
3936
+ if (context) {
3937
+ return value.bind(context)(...props);
3938
+ }
3939
+ return value(...props);
3940
+ }
3941
+ return value;
3942
+ }
3943
+ function splitExtensions(extensions) {
3944
+ const baseExtensions = extensions.filter((extension) => extension.type === "extension");
3945
+ const nodeExtensions = extensions.filter((extension) => extension.type === "node");
3946
+ const markExtensions = extensions.filter((extension) => extension.type === "mark");
3947
+ return {
3948
+ baseExtensions,
3949
+ nodeExtensions,
3950
+ markExtensions
3951
+ };
3952
+ }
3953
+ function mergeAttributes(...objects) {
3954
+ return objects.filter((item) => !!item).reduce((items, item) => {
3955
+ const mergedAttributes = { ...items };
3956
+ Object.entries(item).forEach(([key, value]) => {
3957
+ const exists = mergedAttributes[key];
3958
+ if (!exists) {
3959
+ mergedAttributes[key] = value;
3960
+ return;
3961
+ }
3962
+ if (key === "class") {
3963
+ const valueClasses = value ? String(value).split(" ") : [];
3964
+ const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(" ") : [];
3965
+ const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
3966
+ mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
3967
+ } else if (key === "style") {
3968
+ const newStyles = value ? value.split(";").map((style2) => style2.trim()).filter(Boolean) : [];
3969
+ const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style2) => style2.trim()).filter(Boolean) : [];
3970
+ const styleMap = /* @__PURE__ */ new Map();
3971
+ existingStyles.forEach((style2) => {
3972
+ const [property, val] = style2.split(":").map((part) => part.trim());
3973
+ styleMap.set(property, val);
3974
+ });
3975
+ newStyles.forEach((style2) => {
3976
+ const [property, val] = style2.split(":").map((part) => part.trim());
3977
+ styleMap.set(property, val);
3978
+ });
3979
+ mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
3980
+ } else {
3981
+ mergedAttributes[key] = value;
3982
+ }
3983
+ });
3984
+ return mergedAttributes;
3985
+ }, {});
3986
+ }
3987
+ function getTextBetween(startNode, range, options) {
3988
+ const { from, to } = range;
3989
+ const { blockSeparator = "\n\n", textSerializers = {} } = options || {};
3990
+ let text = "";
3991
+ startNode.nodesBetween(from, to, (node, pos, parent, index) => {
3992
+ var _a;
3993
+ if (node.isBlock && pos > from) {
3994
+ text += blockSeparator;
3995
+ }
3996
+ const textSerializer = textSerializers == null ? void 0 : textSerializers[node.type.name];
3997
+ if (textSerializer) {
3998
+ if (parent) {
3999
+ text += textSerializer({
4000
+ node,
4001
+ pos,
4002
+ parent,
4003
+ index,
4004
+ range
4005
+ });
4006
+ }
4007
+ return false;
4008
+ }
4009
+ if (node.isText) {
4010
+ text += (_a = node == null ? void 0 : node.text) == null ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos);
4011
+ }
4012
+ });
4013
+ return text;
4014
+ }
4015
+ function getTextSerializersFromSchema(schema) {
4016
+ return Object.fromEntries(
4017
+ Object.entries(schema.nodes).filter(([, node]) => node.spec.toText).map(([name, node]) => [name, node.spec.toText])
4018
+ );
4019
+ }
4020
+ function removeDuplicates(array, by = JSON.stringify) {
4021
+ const seen = {};
4022
+ return array.filter((item) => {
4023
+ const key = by(item);
4024
+ return Object.prototype.hasOwnProperty.call(seen, key) ? false : seen[key] = true;
4025
+ });
4026
+ }
4027
+ function simplifyChangedRanges(changes) {
4028
+ const uniqueChanges = removeDuplicates(changes);
4029
+ return uniqueChanges.length === 1 ? uniqueChanges : uniqueChanges.filter((change, index) => {
4030
+ const rest = uniqueChanges.filter((_, i) => i !== index);
4031
+ return !rest.some((otherChange) => {
4032
+ return change.oldRange.from >= otherChange.oldRange.from && change.oldRange.to <= otherChange.oldRange.to && change.newRange.from >= otherChange.newRange.from && change.newRange.to <= otherChange.newRange.to;
4033
+ });
4034
+ });
4035
+ }
4036
+ function getChangedRanges(transform) {
4037
+ const { mapping, steps } = transform;
4038
+ const changes = [];
4039
+ mapping.maps.forEach((stepMap, index) => {
4040
+ const ranges = [];
4041
+ if (!stepMap.ranges.length) {
4042
+ const { from, to } = steps[index];
4043
+ if (from === void 0 || to === void 0) {
4044
+ return;
4045
+ }
4046
+ ranges.push({ from, to });
4047
+ } else {
4048
+ stepMap.forEach((from, to) => {
4049
+ ranges.push({ from, to });
4050
+ });
4051
+ }
4052
+ ranges.forEach(({ from, to }) => {
4053
+ const newStart = mapping.slice(index).map(from, -1);
4054
+ const newEnd = mapping.slice(index).map(to);
4055
+ const oldStart = mapping.invert().map(newStart, -1);
4056
+ const oldEnd = mapping.invert().map(newEnd);
4057
+ changes.push({
4058
+ oldRange: {
4059
+ from: oldStart,
4060
+ to: oldEnd
4061
+ },
4062
+ newRange: {
4063
+ from: newStart,
4064
+ to: newEnd
4065
+ }
4066
+ });
4067
+ });
4068
+ });
4069
+ return simplifyChangedRanges(changes);
4070
+ }
4071
+ function getSplittedAttributes(extensionAttributes, typeName, attributes) {
4072
+ return Object.fromEntries(
4073
+ Object.entries(attributes).filter(([name]) => {
4074
+ const extensionAttribute = extensionAttributes.find((item) => {
4075
+ return item.type === typeName && item.name === name;
4076
+ });
4077
+ if (!extensionAttribute) {
4078
+ return false;
4079
+ }
4080
+ return extensionAttribute.attribute.keepOnSplit;
4081
+ })
4082
+ );
4083
+ }
4084
+ function isMarkActive(state, typeOrName, attributes = {}) {
4085
+ const { empty, ranges } = state.selection;
4086
+ const type = typeOrName ? getMarkType(typeOrName, state.schema) : null;
4087
+ if (empty) {
4088
+ return !!(state.storedMarks || state.selection.$from.marks()).filter((mark) => {
4089
+ if (!type) {
4090
+ return true;
4091
+ }
4092
+ return type.name === mark.type.name;
4093
+ }).find((mark) => objectIncludes(mark.attrs, attributes, { strict: false }));
4094
+ }
4095
+ let selectionRange = 0;
4096
+ const markRanges = [];
4097
+ ranges.forEach(({ $from, $to }) => {
4098
+ const from = $from.pos;
4099
+ const to = $to.pos;
4100
+ state.doc.nodesBetween(from, to, (node, pos) => {
4101
+ if (!node.isText && !node.marks.length) {
4102
+ return;
4103
+ }
4104
+ const relativeFrom = Math.max(from, pos);
4105
+ const relativeTo = Math.min(to, pos + node.nodeSize);
4106
+ const range2 = relativeTo - relativeFrom;
4107
+ selectionRange += range2;
4108
+ markRanges.push(
4109
+ ...node.marks.map((mark) => ({
4110
+ mark,
4111
+ from: relativeFrom,
4112
+ to: relativeTo
4113
+ }))
4114
+ );
4115
+ });
4116
+ });
4117
+ if (selectionRange === 0) {
4118
+ return false;
4119
+ }
4120
+ const matchedRange = markRanges.filter((markRange) => {
4121
+ if (!type) {
4122
+ return true;
4123
+ }
4124
+ return type.name === markRange.mark.type.name;
4125
+ }).filter((markRange) => objectIncludes(markRange.mark.attrs, attributes, { strict: false })).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
4126
+ const excludedRange = markRanges.filter((markRange) => {
4127
+ if (!type) {
4128
+ return true;
4129
+ }
4130
+ return markRange.mark.type !== type && markRange.mark.type.excludes(type);
4131
+ }).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
4132
+ const range = matchedRange > 0 ? matchedRange + excludedRange : matchedRange;
4133
+ return range >= selectionRange;
4134
+ }
4135
+ function isList(name, extensions) {
4136
+ const { nodeExtensions } = splitExtensions(extensions);
4137
+ const extension = nodeExtensions.find((item) => item.name === name);
4138
+ if (!extension) {
4139
+ return false;
4140
+ }
4141
+ const context = {
4142
+ name: extension.name,
4143
+ options: extension.options,
4144
+ storage: extension.storage
4145
+ };
4146
+ const group = callOrReturn(getExtensionField(extension, "group", context));
4147
+ if (typeof group !== "string") {
4148
+ return false;
4149
+ }
4150
+ return group.split(" ").includes("list");
4151
+ }
4152
+ function isNodeEmpty(node, {
4153
+ checkChildren = true,
4154
+ ignoreWhitespace = false
4155
+ } = {}) {
4156
+ var _a;
4157
+ if (ignoreWhitespace) {
4158
+ if (node.type.name === "hardBreak") {
4159
+ return true;
4160
+ }
4161
+ if (node.isText) {
4162
+ return /^\s*$/m.test((_a = node.text) != null ? _a : "");
4163
+ }
4164
+ }
4165
+ if (node.isText) {
4166
+ return !node.text;
4167
+ }
4168
+ if (node.isAtom || node.isLeaf) {
4169
+ return false;
4170
+ }
4171
+ if (node.content.childCount === 0) {
4172
+ return true;
4173
+ }
4174
+ if (checkChildren) {
4175
+ let isContentEmpty = true;
4176
+ node.content.forEach((childNode) => {
4177
+ if (isContentEmpty === false) {
4178
+ return;
4179
+ }
4180
+ if (!isNodeEmpty(childNode, { ignoreWhitespace, checkChildren })) {
4181
+ isContentEmpty = false;
4182
+ }
4183
+ });
4184
+ return isContentEmpty;
4185
+ }
4186
+ return false;
4187
+ }
4188
+ function canSetMark(state, tr, newMarkType) {
4189
+ var _a;
4190
+ const { selection } = tr;
4191
+ let cursor = null;
4192
+ if (isTextSelection(selection)) {
4193
+ cursor = selection.$cursor;
4194
+ }
4195
+ if (cursor) {
4196
+ const currentMarks = (_a = state.storedMarks) != null ? _a : cursor.marks();
4197
+ const parentAllowsMarkType = cursor.parent.type.allowsMarkType(newMarkType);
4198
+ return parentAllowsMarkType && (!!newMarkType.isInSet(currentMarks) || !currentMarks.some((mark) => mark.type.excludes(newMarkType)));
4199
+ }
4200
+ const { ranges } = selection;
4201
+ return ranges.some(({ $from, $to }) => {
4202
+ let someNodeSupportsMark = $from.depth === 0 ? state.doc.inlineContent && state.doc.type.allowsMarkType(newMarkType) : false;
4203
+ state.doc.nodesBetween($from.pos, $to.pos, (node, _pos, parent) => {
4204
+ if (someNodeSupportsMark) {
4205
+ return false;
4206
+ }
4207
+ if (node.isInline) {
4208
+ const parentAllowsMarkType = !parent || parent.type.allowsMarkType(newMarkType);
4209
+ const currentMarksAllowMarkType = !!newMarkType.isInSet(node.marks) || !node.marks.some((otherMark) => otherMark.type.excludes(newMarkType));
4210
+ someNodeSupportsMark = parentAllowsMarkType && currentMarksAllowMarkType;
4211
+ }
4212
+ return !someNodeSupportsMark;
4213
+ });
4214
+ return someNodeSupportsMark;
4215
+ });
4216
+ }
4217
+ var setMark = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
4218
+ const { selection } = tr;
4219
+ const { empty, ranges } = selection;
4220
+ const type = getMarkType(typeOrName, state.schema);
4221
+ if (dispatch) {
4222
+ if (empty) {
4223
+ const oldAttributes = getMarkAttributes(state, type);
4224
+ tr.addStoredMark(
4225
+ type.create({
4226
+ ...oldAttributes,
4227
+ ...attributes
4228
+ })
4229
+ );
4230
+ } else {
4231
+ ranges.forEach((range) => {
4232
+ const from = range.$from.pos;
4233
+ const to = range.$to.pos;
4234
+ state.doc.nodesBetween(from, to, (node, pos) => {
4235
+ const trimmedFrom = Math.max(pos, from);
4236
+ const trimmedTo = Math.min(pos + node.nodeSize, to);
4237
+ const someHasMark = node.marks.find((mark) => mark.type === type);
4238
+ if (someHasMark) {
4239
+ node.marks.forEach((mark) => {
4240
+ if (type === mark.type) {
4241
+ tr.addMark(
4242
+ trimmedFrom,
4243
+ trimmedTo,
4244
+ type.create({
4245
+ ...mark.attrs,
4246
+ ...attributes
4247
+ })
4248
+ );
4249
+ }
4250
+ });
4251
+ } else {
4252
+ tr.addMark(trimmedFrom, trimmedTo, type.create(attributes));
4253
+ }
4254
+ });
4255
+ });
4256
+ }
4257
+ }
4258
+ return canSetMark(state, tr, type);
4259
+ };
4260
+ var setMeta = (key, value) => ({ tr }) => {
4261
+ tr.setMeta(key, value);
4262
+ return true;
4263
+ };
4264
+ var setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
4265
+ const type = getNodeType(typeOrName, state.schema);
4266
+ let attributesToCopy;
4267
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
4268
+ attributesToCopy = state.selection.$anchor.parent.attrs;
4269
+ }
4270
+ if (!type.isTextblock) {
4271
+ console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
4272
+ return false;
4273
+ }
4274
+ return chain().command(({ commands }) => {
4275
+ const canSetBlock = setBlockType(type, { ...attributesToCopy, ...attributes })(state);
4276
+ if (canSetBlock) {
4277
+ return true;
4278
+ }
4279
+ return commands.clearNodes();
4280
+ }).command(({ state: updatedState }) => {
4281
+ return setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch);
4282
+ }).run();
4283
+ };
4284
+ var setNodeSelection = (position) => ({ tr, dispatch }) => {
4285
+ if (dispatch) {
4286
+ const { doc } = tr;
4287
+ const from = minMax(position, 0, doc.content.size);
4288
+ const selection = NodeSelection.create(doc, from);
4289
+ tr.setSelection(selection);
4290
+ }
4291
+ return true;
4292
+ };
4293
+ var setTextDirection = (direction, position) => ({ tr, state, dispatch }) => {
4294
+ const { selection } = state;
4295
+ let from;
4296
+ let to;
4297
+ if (typeof position === "number") {
4298
+ from = position;
4299
+ to = position;
4300
+ } else if (position && "from" in position && "to" in position) {
4301
+ from = position.from;
4302
+ to = position.to;
4303
+ } else {
4304
+ from = selection.from;
4305
+ to = selection.to;
4306
+ }
4307
+ if (dispatch) {
4308
+ tr.doc.nodesBetween(from, to, (node, pos) => {
4309
+ if (node.isText) {
4310
+ return;
4311
+ }
4312
+ tr.setNodeMarkup(pos, void 0, {
4313
+ ...node.attrs,
4314
+ dir: direction
4315
+ });
4316
+ });
4317
+ }
4318
+ return true;
4319
+ };
4320
+ var setTextSelection = (position) => ({ tr, dispatch }) => {
4321
+ if (dispatch) {
4322
+ const { doc } = tr;
4323
+ const { from, to } = typeof position === "number" ? { from: position, to: position } : position;
4324
+ const minPos = TextSelection.atStart(doc).from;
4325
+ const maxPos = TextSelection.atEnd(doc).to;
4326
+ const resolvedFrom = minMax(from, minPos, maxPos);
4327
+ const resolvedEnd = minMax(to, minPos, maxPos);
4328
+ const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd);
4329
+ tr.setSelection(selection);
4330
+ }
4331
+ return true;
4332
+ };
4333
+ var sinkListItem = (typeOrName) => ({ state, dispatch }) => {
4334
+ const type = getNodeType(typeOrName, state.schema);
4335
+ return sinkListItem$1(type)(state, dispatch);
4336
+ };
4337
+ function ensureMarks(state, splittableMarks) {
4338
+ const marks = state.storedMarks || state.selection.$to.parentOffset && state.selection.$from.marks();
4339
+ if (marks) {
4340
+ const filteredMarks = marks.filter((mark) => splittableMarks == null ? void 0 : splittableMarks.includes(mark.type.name));
4341
+ state.tr.ensureMarks(filteredMarks);
4342
+ }
4343
+ }
4344
+ var splitBlock = ({ keepMarks = true } = {}) => ({ tr, state, dispatch, editor }) => {
4345
+ const { selection, doc } = tr;
4346
+ const { $from, $to } = selection;
4347
+ const extensionAttributes = editor.extensionManager.attributes;
4348
+ const newAttributes = getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs);
4349
+ if (selection instanceof NodeSelection && selection.node.isBlock) {
4350
+ if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
4351
+ return false;
4352
+ }
4353
+ if (dispatch) {
4354
+ if (keepMarks) {
4355
+ ensureMarks(state, editor.extensionManager.splittableMarks);
4356
+ }
4357
+ tr.split($from.pos).scrollIntoView();
4358
+ }
4359
+ return true;
4360
+ }
4361
+ if (!$from.parent.isBlock) {
4362
+ return false;
4363
+ }
4364
+ const atEnd = $to.parentOffset === $to.parent.content.size;
4365
+ const deflt = $from.depth === 0 ? void 0 : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
4366
+ let types = atEnd && deflt ? [
4367
+ {
4368
+ type: deflt,
4369
+ attrs: newAttributes
4370
+ }
4371
+ ] : void 0;
4372
+ let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
4373
+ if (!types && !can && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : void 0)) {
4374
+ can = true;
4375
+ types = deflt ? [
4376
+ {
4377
+ type: deflt,
4378
+ attrs: newAttributes
4379
+ }
4380
+ ] : void 0;
4381
+ }
4382
+ if (dispatch) {
4383
+ if (can) {
4384
+ if (selection instanceof TextSelection) {
4385
+ tr.deleteSelection();
4386
+ }
4387
+ tr.split(tr.mapping.map($from.pos), 1, types);
4388
+ if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
4389
+ const first2 = tr.mapping.map($from.before());
4390
+ const $first = tr.doc.resolve(first2);
4391
+ if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
4392
+ tr.setNodeMarkup(tr.mapping.map($from.before()), deflt);
4393
+ }
4394
+ }
4395
+ }
4396
+ if (keepMarks) {
4397
+ ensureMarks(state, editor.extensionManager.splittableMarks);
4398
+ }
4399
+ tr.scrollIntoView();
4400
+ }
4401
+ return can;
4402
+ };
4403
+ var splitListItem = (typeOrName, overrideAttrs = {}) => ({ tr, state, dispatch, editor }) => {
4404
+ var _a;
4405
+ const type = getNodeType(typeOrName, state.schema);
4406
+ const { $from, $to } = state.selection;
4407
+ const node = state.selection.node;
4408
+ if (node && node.isBlock || $from.depth < 2 || !$from.sameParent($to)) {
4409
+ return false;
4410
+ }
4411
+ const grandParent = $from.node(-1);
4412
+ if (grandParent.type !== type) {
4413
+ return false;
4414
+ }
4415
+ const extensionAttributes = editor.extensionManager.attributes;
4416
+ if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
4417
+ if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) {
4418
+ return false;
4419
+ }
4420
+ if (dispatch) {
4421
+ let wrap = Fragment.empty;
4422
+ const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
4423
+ for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
4424
+ wrap = Fragment.from($from.node(d).copy(wrap));
4425
+ }
4426
+ const depthAfter = (
4427
+ // eslint-disable-next-line no-nested-ternary
4428
+ $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3
4429
+ );
4430
+ const newNextTypeAttributes2 = {
4431
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
4432
+ ...overrideAttrs
4433
+ };
4434
+ const nextType2 = ((_a = type.contentMatch.defaultType) == null ? void 0 : _a.createAndFill(newNextTypeAttributes2)) || void 0;
4435
+ wrap = wrap.append(Fragment.from(type.createAndFill(null, nextType2) || void 0));
4436
+ const start = $from.before($from.depth - (depthBefore - 1));
4437
+ tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0));
4438
+ let sel = -1;
4439
+ tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
4440
+ if (sel > -1) {
4441
+ return false;
4442
+ }
4443
+ if (n.isTextblock && n.content.size === 0) {
4444
+ sel = pos + 1;
4445
+ }
4446
+ });
4447
+ if (sel > -1) {
4448
+ tr.setSelection(TextSelection.near(tr.doc.resolve(sel)));
4449
+ }
4450
+ tr.scrollIntoView();
4451
+ }
4452
+ return true;
4453
+ }
4454
+ const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null;
4455
+ const newTypeAttributes = {
4456
+ ...getSplittedAttributes(extensionAttributes, grandParent.type.name, grandParent.attrs),
4457
+ ...overrideAttrs
4458
+ };
4459
+ const newNextTypeAttributes = {
4460
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
4461
+ ...overrideAttrs
4462
+ };
4463
+ tr.delete($from.pos, $to.pos);
4464
+ const types = nextType ? [
4465
+ { type, attrs: newTypeAttributes },
4466
+ { type: nextType, attrs: newNextTypeAttributes }
4467
+ ] : [{ type, attrs: newTypeAttributes }];
4468
+ if (!canSplit(tr.doc, $from.pos, 2)) {
4469
+ return false;
4470
+ }
4471
+ if (dispatch) {
4472
+ const { selection, storedMarks } = state;
4473
+ const { splittableMarks } = editor.extensionManager;
4474
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
4475
+ tr.split($from.pos, 2, types).scrollIntoView();
4476
+ if (!marks || !dispatch) {
4477
+ return true;
4478
+ }
4479
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
4480
+ tr.ensureMarks(filteredMarks);
4481
+ }
4482
+ return true;
4483
+ };
4484
+ var joinListBackwards = (tr, listType) => {
4485
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
4486
+ if (!list) {
4487
+ return true;
4488
+ }
4489
+ const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
4490
+ if (before === void 0) {
4491
+ return true;
4492
+ }
4493
+ const nodeBefore = tr.doc.nodeAt(before);
4494
+ const canJoinBackwards = list.node.type === (nodeBefore == null ? void 0 : nodeBefore.type) && canJoin(tr.doc, list.pos);
4495
+ if (!canJoinBackwards) {
4496
+ return true;
4497
+ }
4498
+ tr.join(list.pos);
4499
+ return true;
4500
+ };
4501
+ var joinListForwards = (tr, listType) => {
4502
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
4503
+ if (!list) {
4504
+ return true;
4505
+ }
4506
+ const after = tr.doc.resolve(list.start).after(list.depth);
4507
+ if (after === void 0) {
4508
+ return true;
4509
+ }
4510
+ const nodeAfter = tr.doc.nodeAt(after);
4511
+ const canJoinForwards = list.node.type === (nodeAfter == null ? void 0 : nodeAfter.type) && canJoin(tr.doc, after);
4512
+ if (!canJoinForwards) {
4513
+ return true;
4514
+ }
4515
+ tr.join(after);
4516
+ return true;
4517
+ };
4518
+ var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({ editor, tr, state, dispatch, chain, commands, can }) => {
4519
+ const { extensions, splittableMarks } = editor.extensionManager;
4520
+ const listType = getNodeType(listTypeOrName, state.schema);
4521
+ const itemType = getNodeType(itemTypeOrName, state.schema);
4522
+ const { selection, storedMarks } = state;
4523
+ const { $from, $to } = selection;
4524
+ const range = $from.blockRange($to);
4525
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
4526
+ if (!range) {
4527
+ return false;
4528
+ }
4529
+ const parentList = findParentNode((node) => isList(node.type.name, extensions))(selection);
4530
+ if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
4531
+ if (parentList.node.type === listType) {
4532
+ return commands.liftListItem(itemType);
4533
+ }
4534
+ if (isList(parentList.node.type.name, extensions) && listType.validContent(parentList.node.content) && dispatch) {
4535
+ return chain().command(() => {
4536
+ tr.setNodeMarkup(parentList.pos, listType);
4537
+ return true;
4538
+ }).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
4539
+ }
4540
+ }
4541
+ if (!keepMarks || !marks || !dispatch) {
4542
+ return chain().command(() => {
4543
+ const canWrapInList = can().wrapInList(listType, attributes);
4544
+ if (canWrapInList) {
4545
+ return true;
4546
+ }
4547
+ return commands.clearNodes();
4548
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
4549
+ }
4550
+ return chain().command(() => {
4551
+ const canWrapInList = can().wrapInList(listType, attributes);
4552
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
4553
+ tr.ensureMarks(filteredMarks);
4554
+ if (canWrapInList) {
4555
+ return true;
4556
+ }
4557
+ return commands.clearNodes();
4558
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
4559
+ };
4560
+ var toggleMark = (typeOrName, attributes = {}, options = {}) => ({ state, commands }) => {
4561
+ const { extendEmptyMarkRange = false } = options;
4562
+ const type = getMarkType(typeOrName, state.schema);
4563
+ const isActive2 = isMarkActive(state, type, attributes);
4564
+ if (isActive2) {
4565
+ return commands.unsetMark(type, { extendEmptyMarkRange });
4566
+ }
4567
+ return commands.setMark(type, attributes);
4568
+ };
4569
+ var toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands }) => {
4570
+ const type = getNodeType(typeOrName, state.schema);
4571
+ const toggleType = getNodeType(toggleTypeOrName, state.schema);
4572
+ const isActive2 = isNodeActive(state, type, attributes);
4573
+ let attributesToCopy;
4574
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
4575
+ attributesToCopy = state.selection.$anchor.parent.attrs;
4576
+ }
4577
+ if (isActive2) {
4578
+ return commands.setNode(toggleType, attributesToCopy);
4579
+ }
4580
+ return commands.setNode(type, { ...attributesToCopy, ...attributes });
4581
+ };
4582
+ var toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
4583
+ const type = getNodeType(typeOrName, state.schema);
4584
+ const isActive2 = isNodeActive(state, type, attributes);
4585
+ if (isActive2) {
4586
+ return commands.lift(type);
4587
+ }
4588
+ return commands.wrapIn(type, attributes);
4589
+ };
4590
+ var undoInputRule = () => ({ state, dispatch }) => {
4591
+ const plugins = state.plugins;
4592
+ for (let i = 0; i < plugins.length; i += 1) {
4593
+ const plugin = plugins[i];
4594
+ let undoable;
4595
+ if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
4596
+ if (dispatch) {
4597
+ const tr = state.tr;
4598
+ const toUndo = undoable.transform;
4599
+ for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
4600
+ tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
4601
+ }
4602
+ if (undoable.text) {
4603
+ const marks = tr.doc.resolve(undoable.from).marks();
4604
+ tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
4605
+ } else {
4606
+ tr.delete(undoable.from, undoable.to);
4607
+ }
4608
+ }
4609
+ return true;
4610
+ }
4611
+ }
4612
+ return false;
4613
+ };
4614
+ var unsetAllMarks = () => ({ tr, dispatch }) => {
4615
+ const { selection } = tr;
4616
+ const { empty, ranges } = selection;
4617
+ if (empty) {
4618
+ return true;
4619
+ }
4620
+ if (dispatch) {
4621
+ ranges.forEach((range) => {
4622
+ tr.removeMark(range.$from.pos, range.$to.pos);
4623
+ });
4624
+ }
4625
+ return true;
4626
+ };
4627
+ var unsetMark = (typeOrName, options = {}) => ({ tr, state, dispatch }) => {
4628
+ var _a;
4629
+ const { extendEmptyMarkRange = false } = options;
4630
+ const { selection } = tr;
4631
+ const type = getMarkType(typeOrName, state.schema);
4632
+ const { $from, empty, ranges } = selection;
4633
+ if (!dispatch) {
4634
+ return true;
4635
+ }
4636
+ if (empty && extendEmptyMarkRange) {
4637
+ let { from, to } = selection;
4638
+ const attrs = (_a = $from.marks().find((mark) => mark.type === type)) == null ? void 0 : _a.attrs;
4639
+ const range = getMarkRange($from, type, attrs);
4640
+ if (range) {
4641
+ from = range.from;
4642
+ to = range.to;
4643
+ }
4644
+ tr.removeMark(from, to, type);
4645
+ } else {
4646
+ ranges.forEach((range) => {
4647
+ tr.removeMark(range.$from.pos, range.$to.pos, type);
4648
+ });
4649
+ }
4650
+ tr.removeStoredMark(type);
4651
+ return true;
4652
+ };
4653
+ var unsetTextDirection = (position) => ({ tr, state, dispatch }) => {
4654
+ const { selection } = state;
4655
+ let from;
4656
+ let to;
4657
+ if (typeof position === "number") {
4658
+ from = position;
4659
+ to = position;
4660
+ } else if (position && "from" in position && "to" in position) {
4661
+ from = position.from;
4662
+ to = position.to;
4663
+ } else {
4664
+ from = selection.from;
4665
+ to = selection.to;
4666
+ }
4667
+ if (dispatch) {
4668
+ tr.doc.nodesBetween(from, to, (node, pos) => {
4669
+ if (node.isText) {
4670
+ return;
4671
+ }
4672
+ const newAttrs = { ...node.attrs };
4673
+ delete newAttrs.dir;
4674
+ tr.setNodeMarkup(pos, void 0, newAttrs);
4675
+ });
4676
+ }
4677
+ return true;
4678
+ };
4679
+ var updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
4680
+ let nodeType = null;
4681
+ let markType = null;
4682
+ const schemaType = getSchemaTypeNameByName(
4683
+ typeof typeOrName === "string" ? typeOrName : typeOrName.name,
4684
+ state.schema
4685
+ );
4686
+ if (!schemaType) {
4687
+ return false;
4688
+ }
4689
+ if (schemaType === "node") {
4690
+ nodeType = getNodeType(typeOrName, state.schema);
4691
+ }
4692
+ if (schemaType === "mark") {
4693
+ markType = getMarkType(typeOrName, state.schema);
4694
+ }
4695
+ let canUpdate = false;
4696
+ tr.selection.ranges.forEach((range) => {
4697
+ const from = range.$from.pos;
4698
+ const to = range.$to.pos;
4699
+ let lastPos;
4700
+ let lastNode;
4701
+ let trimmedFrom;
4702
+ let trimmedTo;
4703
+ if (tr.selection.empty) {
4704
+ state.doc.nodesBetween(from, to, (node, pos) => {
4705
+ if (nodeType && nodeType === node.type) {
4706
+ canUpdate = true;
4707
+ trimmedFrom = Math.max(pos, from);
4708
+ trimmedTo = Math.min(pos + node.nodeSize, to);
4709
+ lastPos = pos;
4710
+ lastNode = node;
4711
+ }
4712
+ });
4713
+ } else {
4714
+ state.doc.nodesBetween(from, to, (node, pos) => {
4715
+ if (pos < from && nodeType && nodeType === node.type) {
4716
+ canUpdate = true;
4717
+ trimmedFrom = Math.max(pos, from);
4718
+ trimmedTo = Math.min(pos + node.nodeSize, to);
4719
+ lastPos = pos;
4720
+ lastNode = node;
4721
+ }
4722
+ if (pos >= from && pos <= to) {
4723
+ if (nodeType && nodeType === node.type) {
4724
+ canUpdate = true;
4725
+ if (dispatch) {
4726
+ tr.setNodeMarkup(pos, void 0, {
4727
+ ...node.attrs,
4728
+ ...attributes
4729
+ });
4730
+ }
4731
+ }
4732
+ if (markType && node.marks.length) {
4733
+ node.marks.forEach((mark) => {
4734
+ if (markType === mark.type) {
4735
+ canUpdate = true;
4736
+ if (dispatch) {
4737
+ const trimmedFrom2 = Math.max(pos, from);
4738
+ const trimmedTo2 = Math.min(pos + node.nodeSize, to);
4739
+ tr.addMark(
4740
+ trimmedFrom2,
4741
+ trimmedTo2,
4742
+ markType.create({
4743
+ ...mark.attrs,
4744
+ ...attributes
4745
+ })
4746
+ );
4747
+ }
4748
+ }
4749
+ });
4750
+ }
4751
+ }
4752
+ });
4753
+ }
4754
+ if (lastNode) {
4755
+ if (lastPos !== void 0 && dispatch) {
4756
+ tr.setNodeMarkup(lastPos, void 0, {
4757
+ ...lastNode.attrs,
4758
+ ...attributes
4759
+ });
4760
+ }
4761
+ if (markType && lastNode.marks.length) {
4762
+ lastNode.marks.forEach((mark) => {
4763
+ if (markType === mark.type && dispatch) {
4764
+ tr.addMark(
4765
+ trimmedFrom,
4766
+ trimmedTo,
4767
+ markType.create({
4768
+ ...mark.attrs,
4769
+ ...attributes
4770
+ })
4771
+ );
4772
+ }
4773
+ });
4774
+ }
4775
+ }
4776
+ });
4777
+ return canUpdate;
4778
+ };
4779
+ var wrapIn = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
4780
+ const type = getNodeType(typeOrName, state.schema);
4781
+ return wrapIn$1(type, attributes)(state, dispatch);
4782
+ };
4783
+ var wrapInList = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
4784
+ const type = getNodeType(typeOrName, state.schema);
4785
+ return wrapInList$1(type, attributes)(state, dispatch);
4786
+ };
4787
+ function getType(value) {
4788
+ return Object.prototype.toString.call(value).slice(8, -1);
4789
+ }
4790
+ function isPlainObject(value) {
4791
+ if (getType(value) !== "Object") {
4792
+ return false;
4793
+ }
4794
+ return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype;
4795
+ }
4796
+ function mergeDeep(target, source) {
4797
+ const output = { ...target };
4798
+ if (isPlainObject(target) && isPlainObject(source)) {
4799
+ Object.keys(source).forEach((key) => {
4800
+ if (isPlainObject(source[key]) && isPlainObject(target[key])) {
4801
+ output[key] = mergeDeep(target[key], source[key]);
4802
+ } else {
4803
+ output[key] = source[key];
4804
+ }
4805
+ });
4806
+ }
4807
+ return output;
4808
+ }
4809
+ var Extendable = class {
4810
+ constructor(config = {}) {
4811
+ this.type = "extendable";
4812
+ this.parent = null;
4813
+ this.child = null;
4814
+ this.name = "";
4815
+ this.config = {
4816
+ name: this.name
4817
+ };
4818
+ this.config = {
4819
+ ...this.config,
4820
+ ...config
4821
+ };
4822
+ this.name = this.config.name;
4823
+ }
4824
+ get options() {
4825
+ return {
4826
+ ...callOrReturn(
4827
+ getExtensionField(this, "addOptions", {
4828
+ name: this.name
4829
+ })
4830
+ ) || {}
4831
+ };
4832
+ }
4833
+ get storage() {
4834
+ return {
4835
+ ...callOrReturn(
4836
+ getExtensionField(this, "addStorage", {
4837
+ name: this.name,
4838
+ options: this.options
4839
+ })
4840
+ ) || {}
4841
+ };
4842
+ }
4843
+ configure(options = {}) {
4844
+ const extension = this.extend({
4845
+ ...this.config,
4846
+ addOptions: () => {
4847
+ return mergeDeep(this.options, options);
4848
+ }
4849
+ });
4850
+ extension.name = this.name;
4851
+ extension.parent = this.parent;
4852
+ return extension;
4853
+ }
4854
+ extend(extendedConfig = {}) {
4855
+ const extension = new this.constructor({ ...this.config, ...extendedConfig });
4856
+ extension.parent = this;
4857
+ this.child = extension;
4858
+ extension.name = "name" in extendedConfig ? extendedConfig.name : extension.parent.name;
4859
+ return extension;
4860
+ }
4861
+ };
4862
+ var extensions_exports = {};
4863
+ __export(extensions_exports, {
4864
+ ClipboardTextSerializer: () => ClipboardTextSerializer,
4865
+ Commands: () => Commands,
4866
+ Delete: () => Delete,
4867
+ Drop: () => Drop,
4868
+ Editable: () => Editable,
4869
+ FocusEvents: () => FocusEvents,
4870
+ Keymap: () => Keymap,
4871
+ Paste: () => Paste,
4872
+ Tabindex: () => Tabindex,
4873
+ TextDirection: () => TextDirection,
4874
+ focusEventsPluginKey: () => focusEventsPluginKey
4875
+ });
4876
+ var Extension = class _Extension extends Extendable {
4877
+ constructor() {
4878
+ super(...arguments);
4879
+ this.type = "extension";
4880
+ }
4881
+ /**
4882
+ * Create a new Extension instance
4883
+ * @param config - Extension configuration object or a function that returns a configuration object
4884
+ */
4885
+ static create(config = {}) {
4886
+ const resolvedConfig = typeof config === "function" ? config() : config;
4887
+ return new _Extension(resolvedConfig);
4888
+ }
4889
+ configure(options) {
4890
+ return super.configure(options);
4891
+ }
4892
+ extend(extendedConfig) {
4893
+ const resolvedConfig = typeof extendedConfig === "function" ? extendedConfig() : extendedConfig;
4894
+ return super.extend(resolvedConfig);
4895
+ }
4896
+ };
4897
+ var ClipboardTextSerializer = Extension.create({
4898
+ name: "clipboardTextSerializer",
4899
+ addOptions() {
4900
+ return {
4901
+ blockSeparator: void 0
4902
+ };
4903
+ },
4904
+ addProseMirrorPlugins() {
4905
+ return [
4906
+ new Plugin({
4907
+ key: new PluginKey("clipboardTextSerializer"),
4908
+ props: {
4909
+ clipboardTextSerializer: () => {
4910
+ const { editor } = this;
4911
+ const { state, schema } = editor;
4912
+ const { doc, selection } = state;
4913
+ const { ranges } = selection;
4914
+ const from = Math.min(...ranges.map((range2) => range2.$from.pos));
4915
+ const to = Math.max(...ranges.map((range2) => range2.$to.pos));
4916
+ const textSerializers = getTextSerializersFromSchema(schema);
4917
+ const range = { from, to };
4918
+ return getTextBetween(doc, range, {
4919
+ ...this.options.blockSeparator !== void 0 ? { blockSeparator: this.options.blockSeparator } : {},
4920
+ textSerializers
4921
+ });
4922
+ }
4923
+ }
4924
+ })
4925
+ ];
4926
+ }
4927
+ });
4928
+ var Commands = Extension.create({
4929
+ name: "commands",
4930
+ addCommands() {
4931
+ return {
4932
+ ...commands_exports
4933
+ };
4934
+ }
4935
+ });
4936
+ var Delete = Extension.create({
4937
+ name: "delete",
4938
+ onUpdate({ transaction, appendedTransactions }) {
4939
+ var _a, _b, _c;
4940
+ const callback = () => {
4941
+ var _a2, _b2, _c2, _d;
4942
+ if ((_d = (_c2 = (_b2 = (_a2 = this.editor.options.coreExtensionOptions) == null ? void 0 : _a2.delete) == null ? void 0 : _b2.filterTransaction) == null ? void 0 : _c2.call(_b2, transaction)) != null ? _d : transaction.getMeta("y-sync$")) {
4943
+ return;
4944
+ }
4945
+ const nextTransaction = combineTransactionSteps(transaction.before, [transaction, ...appendedTransactions]);
4946
+ const changes = getChangedRanges(nextTransaction);
4947
+ changes.forEach((change) => {
4948
+ if (nextTransaction.mapping.mapResult(change.oldRange.from).deletedAfter && nextTransaction.mapping.mapResult(change.oldRange.to).deletedBefore) {
4949
+ nextTransaction.before.nodesBetween(change.oldRange.from, change.oldRange.to, (node, from) => {
4950
+ const to = from + node.nodeSize - 2;
4951
+ const isFullyWithinRange = change.oldRange.from <= from && to <= change.oldRange.to;
4952
+ this.editor.emit("delete", {
4953
+ type: "node",
4954
+ node,
4955
+ from,
4956
+ to,
4957
+ newFrom: nextTransaction.mapping.map(from),
4958
+ newTo: nextTransaction.mapping.map(to),
4959
+ deletedRange: change.oldRange,
4960
+ newRange: change.newRange,
4961
+ partial: !isFullyWithinRange,
4962
+ editor: this.editor,
4963
+ transaction,
4964
+ combinedTransform: nextTransaction
4965
+ });
4966
+ });
4967
+ }
4968
+ });
4969
+ const mapping = nextTransaction.mapping;
4970
+ nextTransaction.steps.forEach((step, index) => {
4971
+ var _a3, _b3;
4972
+ if (step instanceof RemoveMarkStep) {
4973
+ const newStart = mapping.slice(index).map(step.from, -1);
4974
+ const newEnd = mapping.slice(index).map(step.to);
4975
+ const oldStart = mapping.invert().map(newStart, -1);
4976
+ const oldEnd = mapping.invert().map(newEnd);
4977
+ const foundBeforeMark = (_a3 = nextTransaction.doc.nodeAt(newStart - 1)) == null ? void 0 : _a3.marks.some((mark) => mark.eq(step.mark));
4978
+ const foundAfterMark = (_b3 = nextTransaction.doc.nodeAt(newEnd)) == null ? void 0 : _b3.marks.some((mark) => mark.eq(step.mark));
4979
+ this.editor.emit("delete", {
4980
+ type: "mark",
4981
+ mark: step.mark,
4982
+ from: step.from,
4983
+ to: step.to,
4984
+ deletedRange: {
4985
+ from: oldStart,
4986
+ to: oldEnd
4987
+ },
4988
+ newRange: {
4989
+ from: newStart,
4990
+ to: newEnd
4991
+ },
4992
+ partial: Boolean(foundAfterMark || foundBeforeMark),
4993
+ editor: this.editor,
4994
+ transaction,
4995
+ combinedTransform: nextTransaction
4996
+ });
4997
+ }
4998
+ });
4999
+ };
5000
+ if ((_c = (_b = (_a = this.editor.options.coreExtensionOptions) == null ? void 0 : _a.delete) == null ? void 0 : _b.async) != null ? _c : true) {
5001
+ setTimeout(callback, 0);
5002
+ } else {
5003
+ callback();
5004
+ }
5005
+ }
5006
+ });
5007
+ var Drop = Extension.create({
5008
+ name: "drop",
5009
+ addProseMirrorPlugins() {
5010
+ return [
5011
+ new Plugin({
5012
+ key: new PluginKey("tiptapDrop"),
5013
+ props: {
5014
+ handleDrop: (_, e, slice, moved) => {
5015
+ this.editor.emit("drop", {
5016
+ editor: this.editor,
5017
+ event: e,
5018
+ slice,
5019
+ moved
5020
+ });
5021
+ }
5022
+ }
5023
+ })
5024
+ ];
5025
+ }
5026
+ });
5027
+ var Editable = Extension.create({
5028
+ name: "editable",
5029
+ addProseMirrorPlugins() {
5030
+ return [
5031
+ new Plugin({
5032
+ key: new PluginKey("editable"),
5033
+ props: {
5034
+ editable: () => this.editor.options.editable
5035
+ }
5036
+ })
5037
+ ];
5038
+ }
5039
+ });
5040
+ var focusEventsPluginKey = new PluginKey("focusEvents");
5041
+ var FocusEvents = Extension.create({
5042
+ name: "focusEvents",
5043
+ addProseMirrorPlugins() {
5044
+ const { editor } = this;
5045
+ return [
5046
+ new Plugin({
5047
+ key: focusEventsPluginKey,
5048
+ props: {
5049
+ handleDOMEvents: {
5050
+ focus: (view, event) => {
5051
+ editor.isFocused = true;
5052
+ const transaction = editor.state.tr.setMeta("focus", { event }).setMeta("addToHistory", false);
5053
+ view.dispatch(transaction);
5054
+ return false;
5055
+ },
5056
+ blur: (view, event) => {
5057
+ editor.isFocused = false;
5058
+ const transaction = editor.state.tr.setMeta("blur", { event }).setMeta("addToHistory", false);
5059
+ view.dispatch(transaction);
5060
+ return false;
5061
+ }
5062
+ }
5063
+ }
5064
+ })
5065
+ ];
5066
+ }
5067
+ });
5068
+ var Keymap = Extension.create({
5069
+ name: "keymap",
5070
+ addKeyboardShortcuts() {
5071
+ const handleBackspace = () => this.editor.commands.first(({ commands }) => [
5072
+ () => commands.undoInputRule(),
5073
+ // maybe convert first text block node to default node
5074
+ () => commands.command(({ tr }) => {
5075
+ const { selection, doc } = tr;
5076
+ const { empty, $anchor } = selection;
5077
+ const { pos, parent } = $anchor;
5078
+ const $parentPos = $anchor.parent.isTextblock && pos > 0 ? tr.doc.resolve(pos - 1) : $anchor;
5079
+ const parentIsIsolating = $parentPos.parent.type.spec.isolating;
5080
+ const parentPos = $anchor.pos - $anchor.parentOffset;
5081
+ const isAtStart = parentIsIsolating && $parentPos.parent.childCount === 1 ? parentPos === $anchor.pos : Selection.atStart(doc).from === pos;
5082
+ if (!empty || !parent.type.isTextblock || parent.textContent.length || !isAtStart || isAtStart && $anchor.parent.type.name === "paragraph") {
5083
+ return false;
5084
+ }
5085
+ return commands.clearNodes();
5086
+ }),
5087
+ () => commands.deleteSelection(),
5088
+ () => commands.joinBackward(),
5089
+ () => commands.selectNodeBackward()
5090
+ ]);
5091
+ const handleDelete = () => this.editor.commands.first(({ commands }) => [
5092
+ () => commands.deleteSelection(),
5093
+ () => commands.deleteCurrentNode(),
5094
+ () => commands.joinForward(),
5095
+ () => commands.selectNodeForward()
5096
+ ]);
5097
+ const handleEnter = () => this.editor.commands.first(({ commands }) => [
5098
+ () => commands.newlineInCode(),
5099
+ () => commands.createParagraphNear(),
5100
+ () => commands.liftEmptyBlock(),
5101
+ () => commands.splitBlock()
5102
+ ]);
5103
+ const baseKeymap = {
5104
+ Enter: handleEnter,
5105
+ "Mod-Enter": () => this.editor.commands.exitCode(),
5106
+ Backspace: handleBackspace,
5107
+ "Mod-Backspace": handleBackspace,
5108
+ "Shift-Backspace": handleBackspace,
5109
+ Delete: handleDelete,
5110
+ "Mod-Delete": handleDelete,
5111
+ "Mod-a": () => this.editor.commands.selectAll()
5112
+ };
5113
+ const pcKeymap = {
5114
+ ...baseKeymap
5115
+ };
5116
+ const macKeymap = {
5117
+ ...baseKeymap,
5118
+ "Ctrl-h": handleBackspace,
5119
+ "Alt-Backspace": handleBackspace,
5120
+ "Ctrl-d": handleDelete,
5121
+ "Ctrl-Alt-Backspace": handleDelete,
5122
+ "Alt-Delete": handleDelete,
5123
+ "Alt-d": handleDelete,
5124
+ "Ctrl-a": () => this.editor.commands.selectTextblockStart(),
5125
+ "Ctrl-e": () => this.editor.commands.selectTextblockEnd()
5126
+ };
5127
+ if (isiOS() || isMacOS()) {
5128
+ return macKeymap;
5129
+ }
5130
+ return pcKeymap;
5131
+ },
5132
+ addProseMirrorPlugins() {
5133
+ return [
5134
+ // With this plugin we check if the whole document was selected and deleted.
5135
+ // In this case we will additionally call `clearNodes()` to convert e.g. a heading
5136
+ // to a paragraph if necessary.
5137
+ // This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
5138
+ // with many other commands.
5139
+ new Plugin({
5140
+ key: new PluginKey("clearDocument"),
5141
+ appendTransaction: (transactions, oldState, newState) => {
5142
+ if (transactions.some((tr2) => tr2.getMeta("composition"))) {
5143
+ return;
5144
+ }
5145
+ const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
5146
+ const ignoreTr = transactions.some((transaction) => transaction.getMeta("preventClearDocument"));
5147
+ if (!docChanges || ignoreTr) {
5148
+ return;
5149
+ }
5150
+ const { empty, from, to } = oldState.selection;
5151
+ const allFrom = Selection.atStart(oldState.doc).from;
5152
+ const allEnd = Selection.atEnd(oldState.doc).to;
5153
+ const allWasSelected = from === allFrom && to === allEnd;
5154
+ if (empty || !allWasSelected) {
5155
+ return;
5156
+ }
5157
+ const isEmpty = isNodeEmpty(newState.doc);
5158
+ if (!isEmpty) {
5159
+ return;
5160
+ }
5161
+ const tr = newState.tr;
5162
+ const state = createChainableState({
5163
+ state: newState,
5164
+ transaction: tr
5165
+ });
5166
+ const { commands } = new CommandManager({
5167
+ editor: this.editor,
5168
+ state
5169
+ });
5170
+ commands.clearNodes();
5171
+ if (!tr.steps.length) {
5172
+ return;
5173
+ }
5174
+ return tr;
5175
+ }
5176
+ })
5177
+ ];
5178
+ }
5179
+ });
5180
+ var Paste = Extension.create({
5181
+ name: "paste",
5182
+ addProseMirrorPlugins() {
5183
+ return [
5184
+ new Plugin({
5185
+ key: new PluginKey("tiptapPaste"),
5186
+ props: {
5187
+ handlePaste: (_view, e, slice) => {
5188
+ this.editor.emit("paste", {
5189
+ editor: this.editor,
5190
+ event: e,
5191
+ slice
5192
+ });
5193
+ }
5194
+ }
5195
+ })
5196
+ ];
5197
+ }
5198
+ });
5199
+ var Tabindex = Extension.create({
5200
+ name: "tabindex",
5201
+ addProseMirrorPlugins() {
5202
+ return [
5203
+ new Plugin({
5204
+ key: new PluginKey("tabindex"),
5205
+ props: {
5206
+ attributes: () => this.editor.isEditable ? { tabindex: "0" } : {}
5207
+ }
5208
+ })
5209
+ ];
5210
+ }
5211
+ });
5212
+ var TextDirection = Extension.create({
5213
+ name: "textDirection",
5214
+ addOptions() {
5215
+ return {
5216
+ direction: void 0
5217
+ };
5218
+ },
5219
+ addGlobalAttributes() {
5220
+ if (!this.options.direction) {
5221
+ return [];
5222
+ }
5223
+ const { nodeExtensions } = splitExtensions(this.extensions);
5224
+ return [
5225
+ {
5226
+ types: nodeExtensions.filter((extension) => extension.name !== "text").map((extension) => extension.name),
5227
+ attributes: {
5228
+ dir: {
5229
+ default: this.options.direction,
5230
+ parseHTML: (element) => {
5231
+ const dir = element.getAttribute("dir");
5232
+ if (dir && (dir === "ltr" || dir === "rtl" || dir === "auto")) {
5233
+ return dir;
5234
+ }
5235
+ return this.options.direction;
5236
+ },
5237
+ renderHTML: (attributes) => {
5238
+ if (!attributes.dir) {
5239
+ return {};
5240
+ }
5241
+ return {
5242
+ dir: attributes.dir
5243
+ };
5244
+ }
5245
+ }
5246
+ }
5247
+ }
5248
+ ];
5249
+ },
5250
+ addProseMirrorPlugins() {
5251
+ return [
5252
+ new Plugin({
5253
+ key: new PluginKey("textDirection"),
5254
+ props: {
5255
+ attributes: () => {
5256
+ const direction = this.options.direction;
5257
+ if (!direction) {
5258
+ return {};
5259
+ }
5260
+ return {
5261
+ dir: direction
5262
+ };
5263
+ }
5264
+ }
5265
+ })
5266
+ ];
5267
+ }
5268
+ });
5269
+ var markdown_exports = {};
5270
+ __export(markdown_exports, {
5271
+ createAtomBlockMarkdownSpec: () => createAtomBlockMarkdownSpec,
5272
+ createBlockMarkdownSpec: () => createBlockMarkdownSpec,
5273
+ createInlineMarkdownSpec: () => createInlineMarkdownSpec,
5274
+ parseAttributes: () => parseAttributes,
5275
+ parseIndentedBlocks: () => parseIndentedBlocks,
5276
+ renderNestedMarkdownContent: () => renderNestedMarkdownContent,
5277
+ serializeAttributes: () => serializeAttributes
5278
+ });
5279
+ function parseAttributes(attrString) {
5280
+ if (!(attrString == null ? void 0 : attrString.trim())) {
5281
+ return {};
5282
+ }
5283
+ const attributes = {};
5284
+ const quotedStrings = [];
5285
+ const tempString = attrString.replace(/["']([^"']*)["']/g, (match) => {
5286
+ quotedStrings.push(match);
5287
+ return `__QUOTED_${quotedStrings.length - 1}__`;
5288
+ });
5289
+ const classMatches = tempString.match(/(?:^|\s)\.([a-zA-Z][\w-]*)/g);
5290
+ if (classMatches) {
5291
+ const classes = classMatches.map((match) => match.trim().slice(1));
5292
+ attributes.class = classes.join(" ");
5293
+ }
5294
+ const idMatch = tempString.match(/(?:^|\s)#([a-zA-Z][\w-]*)/);
5295
+ if (idMatch) {
5296
+ attributes.id = idMatch[1];
5297
+ }
5298
+ const kvRegex = /([a-zA-Z][\w-]*)\s*=\s*(__QUOTED_\d+__)/g;
5299
+ const kvMatches = Array.from(tempString.matchAll(kvRegex));
5300
+ kvMatches.forEach(([, key, quotedRef]) => {
5301
+ var _a;
5302
+ const quotedIndex = parseInt(((_a = quotedRef.match(/__QUOTED_(\d+)__/)) == null ? void 0 : _a[1]) || "0", 10);
5303
+ const quotedValue = quotedStrings[quotedIndex];
5304
+ if (quotedValue) {
5305
+ attributes[key] = quotedValue.slice(1, -1);
5306
+ }
5307
+ });
5308
+ const cleanString = tempString.replace(/(?:^|\s)\.([a-zA-Z][\w-]*)/g, "").replace(/(?:^|\s)#([a-zA-Z][\w-]*)/g, "").replace(/([a-zA-Z][\w-]*)\s*=\s*__QUOTED_\d+__/g, "").trim();
5309
+ if (cleanString) {
5310
+ const booleanAttrs = cleanString.split(/\s+/).filter(Boolean);
5311
+ booleanAttrs.forEach((attr) => {
5312
+ if (attr.match(/^[a-zA-Z][\w-]*$/)) {
5313
+ attributes[attr] = true;
5314
+ }
5315
+ });
5316
+ }
5317
+ return attributes;
5318
+ }
5319
+ function serializeAttributes(attributes) {
5320
+ if (!attributes || Object.keys(attributes).length === 0) {
5321
+ return "";
5322
+ }
5323
+ const parts = [];
5324
+ if (attributes.class) {
5325
+ const classes = String(attributes.class).split(/\s+/).filter(Boolean);
5326
+ classes.forEach((cls) => parts.push(`.${cls}`));
5327
+ }
5328
+ if (attributes.id) {
5329
+ parts.push(`#${attributes.id}`);
5330
+ }
5331
+ Object.entries(attributes).forEach(([key, value]) => {
5332
+ if (key === "class" || key === "id") {
5333
+ return;
5334
+ }
5335
+ if (value === true) {
5336
+ parts.push(key);
5337
+ } else if (value !== false && value != null) {
5338
+ parts.push(`${key}="${String(value)}"`);
5339
+ }
5340
+ });
5341
+ return parts.join(" ");
5342
+ }
5343
+ function createAtomBlockMarkdownSpec(options) {
5344
+ const {
5345
+ nodeName,
5346
+ name: markdownName,
5347
+ parseAttributes: parseAttributes2 = parseAttributes,
5348
+ serializeAttributes: serializeAttributes2 = serializeAttributes,
5349
+ defaultAttributes = {},
5350
+ requiredAttributes = [],
5351
+ allowedAttributes
5352
+ } = options;
5353
+ const blockName = markdownName || nodeName;
5354
+ const filterAttributes = (attrs) => {
5355
+ if (!allowedAttributes) {
5356
+ return attrs;
5357
+ }
5358
+ const filtered = {};
5359
+ allowedAttributes.forEach((key) => {
5360
+ if (key in attrs) {
5361
+ filtered[key] = attrs[key];
5362
+ }
5363
+ });
5364
+ return filtered;
5365
+ };
5366
+ return {
5367
+ parseMarkdown: (token, h2) => {
5368
+ const attrs = { ...defaultAttributes, ...token.attributes };
5369
+ return h2.createNode(nodeName, attrs, []);
5370
+ },
5371
+ markdownTokenizer: {
5372
+ name: nodeName,
5373
+ level: "block",
5374
+ start(src) {
5375
+ var _a;
5376
+ const regex = new RegExp(`^:::${blockName}(?:\\s|$)`, "m");
5377
+ const index = (_a = src.match(regex)) == null ? void 0 : _a.index;
5378
+ return index !== void 0 ? index : -1;
5379
+ },
5380
+ tokenize(src, _tokens, _lexer) {
5381
+ const regex = new RegExp(`^:::${blockName}(?:\\s+\\{([^}]*)\\})?\\s*:::(?:\\n|$)`);
5382
+ const match = src.match(regex);
5383
+ if (!match) {
5384
+ return void 0;
5385
+ }
5386
+ const attrString = match[1] || "";
5387
+ const attributes = parseAttributes2(attrString);
5388
+ const missingRequired = requiredAttributes.find((required) => !(required in attributes));
5389
+ if (missingRequired) {
5390
+ return void 0;
5391
+ }
5392
+ return {
5393
+ type: nodeName,
5394
+ raw: match[0],
5395
+ attributes
5396
+ };
5397
+ }
5398
+ },
5399
+ renderMarkdown: (node) => {
5400
+ const filteredAttrs = filterAttributes(node.attrs || {});
5401
+ const attrs = serializeAttributes2(filteredAttrs);
5402
+ const attrString = attrs ? ` {${attrs}}` : "";
5403
+ return `:::${blockName}${attrString} :::`;
5404
+ }
5405
+ };
5406
+ }
5407
+ function createBlockMarkdownSpec(options) {
5408
+ const {
5409
+ nodeName,
5410
+ name: markdownName,
5411
+ getContent,
5412
+ parseAttributes: parseAttributes2 = parseAttributes,
5413
+ serializeAttributes: serializeAttributes2 = serializeAttributes,
5414
+ defaultAttributes = {},
5415
+ content = "block",
5416
+ allowedAttributes
5417
+ } = options;
5418
+ const blockName = markdownName || nodeName;
5419
+ const filterAttributes = (attrs) => {
5420
+ if (!allowedAttributes) {
5421
+ return attrs;
5422
+ }
5423
+ const filtered = {};
5424
+ allowedAttributes.forEach((key) => {
5425
+ if (key in attrs) {
5426
+ filtered[key] = attrs[key];
5427
+ }
5428
+ });
5429
+ return filtered;
5430
+ };
5431
+ return {
5432
+ parseMarkdown: (token, h2) => {
5433
+ let nodeContent;
5434
+ if (getContent) {
5435
+ const contentResult = getContent(token);
5436
+ nodeContent = typeof contentResult === "string" ? [{ type: "text", text: contentResult }] : contentResult;
5437
+ } else if (content === "block") {
5438
+ nodeContent = h2.parseChildren(token.tokens || []);
5439
+ } else {
5440
+ nodeContent = h2.parseInline(token.tokens || []);
5441
+ }
5442
+ const attrs = { ...defaultAttributes, ...token.attributes };
5443
+ return h2.createNode(nodeName, attrs, nodeContent);
5444
+ },
5445
+ markdownTokenizer: {
5446
+ name: nodeName,
5447
+ level: "block",
5448
+ start(src) {
5449
+ var _a;
5450
+ const regex = new RegExp(`^:::${blockName}`, "m");
5451
+ const index = (_a = src.match(regex)) == null ? void 0 : _a.index;
5452
+ return index !== void 0 ? index : -1;
5453
+ },
5454
+ tokenize(src, _tokens, lexer) {
5455
+ var _a;
5456
+ const openingRegex = new RegExp(`^:::${blockName}(?:\\s+\\{([^}]*)\\})?\\s*\\n`);
5457
+ const openingMatch = src.match(openingRegex);
5458
+ if (!openingMatch) {
5459
+ return void 0;
5460
+ }
5461
+ const [openingTag, attrString = ""] = openingMatch;
5462
+ const attributes = parseAttributes2(attrString);
5463
+ let level = 1;
5464
+ const position = openingTag.length;
5465
+ let matchedContent = "";
5466
+ const blockPattern = /^:::([\w-]*)(\s.*)?/gm;
5467
+ const remaining = src.slice(position);
5468
+ blockPattern.lastIndex = 0;
5469
+ for (; ; ) {
5470
+ const match = blockPattern.exec(remaining);
5471
+ if (match === null) {
5472
+ break;
5473
+ }
5474
+ const matchPos = match.index;
5475
+ const blockType = match[1];
5476
+ if ((_a = match[2]) == null ? void 0 : _a.endsWith(":::")) {
5477
+ continue;
5478
+ }
5479
+ if (blockType) {
5480
+ level += 1;
5481
+ } else {
5482
+ level -= 1;
5483
+ if (level === 0) {
5484
+ const rawContent = remaining.slice(0, matchPos);
5485
+ matchedContent = rawContent.trim();
5486
+ const fullMatch = src.slice(0, position + matchPos + match[0].length);
5487
+ let contentTokens = [];
5488
+ if (matchedContent) {
5489
+ if (content === "block") {
5490
+ contentTokens = lexer.blockTokens(rawContent);
5491
+ contentTokens.forEach((token) => {
5492
+ if (token.text && (!token.tokens || token.tokens.length === 0)) {
5493
+ token.tokens = lexer.inlineTokens(token.text);
5494
+ }
5495
+ });
5496
+ while (contentTokens.length > 0) {
5497
+ const lastToken = contentTokens[contentTokens.length - 1];
5498
+ if (lastToken.type === "paragraph" && (!lastToken.text || lastToken.text.trim() === "")) {
5499
+ contentTokens.pop();
5500
+ } else {
5501
+ break;
5502
+ }
5503
+ }
5504
+ } else {
5505
+ contentTokens = lexer.inlineTokens(matchedContent);
5506
+ }
5507
+ }
5508
+ return {
5509
+ type: nodeName,
5510
+ raw: fullMatch,
5511
+ attributes,
5512
+ content: matchedContent,
5513
+ tokens: contentTokens
5514
+ };
5515
+ }
5516
+ }
5517
+ }
5518
+ return void 0;
5519
+ }
5520
+ },
5521
+ renderMarkdown: (node, h2) => {
5522
+ const filteredAttrs = filterAttributes(node.attrs || {});
5523
+ const attrs = serializeAttributes2(filteredAttrs);
5524
+ const attrString = attrs ? ` {${attrs}}` : "";
5525
+ const renderedContent = h2.renderChildren(node.content || [], "\n\n");
5526
+ return `:::${blockName}${attrString}
5527
+
5528
+ ${renderedContent}
5529
+
5530
+ :::`;
5531
+ }
5532
+ };
5533
+ }
5534
+ function parseShortcodeAttributes(attrString) {
5535
+ if (!attrString.trim()) {
5536
+ return {};
5537
+ }
5538
+ const attributes = {};
5539
+ const regex = /(\w+)=(?:"([^"]*)"|'([^']*)')/g;
5540
+ let match = regex.exec(attrString);
5541
+ while (match !== null) {
5542
+ const [, key, doubleQuoted, singleQuoted] = match;
5543
+ attributes[key] = doubleQuoted || singleQuoted;
5544
+ match = regex.exec(attrString);
5545
+ }
5546
+ return attributes;
5547
+ }
5548
+ function serializeShortcodeAttributes(attrs) {
5549
+ return Object.entries(attrs).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}="${value}"`).join(" ");
5550
+ }
5551
+ function createInlineMarkdownSpec(options) {
5552
+ const {
5553
+ nodeName,
5554
+ name: shortcodeName,
5555
+ getContent,
5556
+ parseAttributes: parseAttributes2 = parseShortcodeAttributes,
5557
+ serializeAttributes: serializeAttributes2 = serializeShortcodeAttributes,
5558
+ defaultAttributes = {},
5559
+ selfClosing = false,
5560
+ allowedAttributes
5561
+ } = options;
5562
+ const shortcode = shortcodeName || nodeName;
5563
+ const filterAttributes = (attrs) => {
5564
+ if (!allowedAttributes) {
5565
+ return attrs;
5566
+ }
5567
+ const filtered = {};
5568
+ allowedAttributes.forEach((attr) => {
5569
+ const attrName = typeof attr === "string" ? attr : attr.name;
5570
+ const skipIfDefault = typeof attr === "string" ? void 0 : attr.skipIfDefault;
5571
+ if (attrName in attrs) {
5572
+ const value = attrs[attrName];
5573
+ if (skipIfDefault !== void 0 && value === skipIfDefault) {
5574
+ return;
5575
+ }
5576
+ filtered[attrName] = value;
5577
+ }
5578
+ });
5579
+ return filtered;
5580
+ };
5581
+ const escapedShortcode = shortcode.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5582
+ return {
5583
+ parseMarkdown: (token, h2) => {
5584
+ const attrs = { ...defaultAttributes, ...token.attributes };
5585
+ if (selfClosing) {
5586
+ return h2.createNode(nodeName, attrs);
5587
+ }
5588
+ const content = getContent ? getContent(token) : token.content || "";
5589
+ if (content) {
5590
+ return h2.createNode(nodeName, attrs, [h2.createTextNode(content)]);
5591
+ }
5592
+ return h2.createNode(nodeName, attrs, []);
5593
+ },
5594
+ markdownTokenizer: {
5595
+ name: nodeName,
5596
+ level: "inline",
5597
+ start(src) {
5598
+ const startPattern = selfClosing ? new RegExp(`\\[${escapedShortcode}\\s*[^\\]]*\\]`) : new RegExp(`\\[${escapedShortcode}\\s*[^\\]]*\\][\\s\\S]*?\\[\\/${escapedShortcode}\\]`);
5599
+ const match = src.match(startPattern);
5600
+ const index = match == null ? void 0 : match.index;
5601
+ return index !== void 0 ? index : -1;
5602
+ },
5603
+ tokenize(src, _tokens, _lexer) {
5604
+ const tokenPattern = selfClosing ? new RegExp(`^\\[${escapedShortcode}\\s*([^\\]]*)\\]`) : new RegExp(`^\\[${escapedShortcode}\\s*([^\\]]*)\\]([\\s\\S]*?)\\[\\/${escapedShortcode}\\]`);
5605
+ const match = src.match(tokenPattern);
5606
+ if (!match) {
5607
+ return void 0;
5608
+ }
5609
+ let content = "";
5610
+ let attrString = "";
5611
+ if (selfClosing) {
5612
+ const [, attrs] = match;
5613
+ attrString = attrs;
5614
+ } else {
5615
+ const [, attrs, contentMatch] = match;
5616
+ attrString = attrs;
5617
+ content = contentMatch || "";
5618
+ }
5619
+ const attributes = parseAttributes2(attrString.trim());
5620
+ return {
5621
+ type: nodeName,
5622
+ raw: match[0],
5623
+ content: content.trim(),
5624
+ attributes
5625
+ };
5626
+ }
5627
+ },
5628
+ renderMarkdown: (node) => {
5629
+ let content = "";
5630
+ if (getContent) {
5631
+ content = getContent(node);
5632
+ } else if (node.content && node.content.length > 0) {
5633
+ content = node.content.filter((child) => child.type === "text").map((child) => child.text).join("");
5634
+ }
5635
+ const filteredAttrs = filterAttributes(node.attrs || {});
5636
+ const attrs = serializeAttributes2(filteredAttrs);
5637
+ const attrString = attrs ? ` ${attrs}` : "";
5638
+ if (selfClosing) {
5639
+ return `[${shortcode}${attrString}]`;
5640
+ }
5641
+ return `[${shortcode}${attrString}]${content}[/${shortcode}]`;
5642
+ }
5643
+ };
5644
+ }
5645
+ function parseIndentedBlocks(src, config, lexer) {
5646
+ var _a, _b, _c, _d;
5647
+ const lines = src.split("\n");
5648
+ const items = [];
5649
+ let totalRaw = "";
5650
+ let i = 0;
5651
+ const baseIndentSize = config.baseIndentSize || 2;
5652
+ while (i < lines.length) {
5653
+ const currentLine = lines[i];
5654
+ const itemMatch = currentLine.match(config.itemPattern);
5655
+ if (!itemMatch) {
5656
+ if (items.length > 0) {
5657
+ break;
5658
+ } else if (currentLine.trim() === "") {
5659
+ i += 1;
5660
+ totalRaw = `${totalRaw}${currentLine}
5661
+ `;
5662
+ continue;
5663
+ } else {
5664
+ return void 0;
5665
+ }
5666
+ }
5667
+ const itemData = config.extractItemData(itemMatch);
5668
+ const { indentLevel, mainContent } = itemData;
5669
+ totalRaw = `${totalRaw}${currentLine}
5670
+ `;
5671
+ const itemContent = [mainContent];
5672
+ i += 1;
5673
+ while (i < lines.length) {
5674
+ const nextLine = lines[i];
5675
+ if (nextLine.trim() === "") {
5676
+ const nextNonEmptyIndex = lines.slice(i + 1).findIndex((l) => l.trim() !== "");
5677
+ if (nextNonEmptyIndex === -1) {
5678
+ break;
5679
+ }
5680
+ const nextNonEmpty = lines[i + 1 + nextNonEmptyIndex];
5681
+ const nextIndent2 = ((_b = (_a = nextNonEmpty.match(/^(\s*)/)) == null ? void 0 : _a[1]) == null ? void 0 : _b.length) || 0;
5682
+ if (nextIndent2 > indentLevel) {
5683
+ itemContent.push(nextLine);
5684
+ totalRaw = `${totalRaw}${nextLine}
5685
+ `;
5686
+ i += 1;
5687
+ continue;
5688
+ } else {
5689
+ break;
5690
+ }
5691
+ }
5692
+ const nextIndent = ((_d = (_c = nextLine.match(/^(\s*)/)) == null ? void 0 : _c[1]) == null ? void 0 : _d.length) || 0;
5693
+ if (nextIndent > indentLevel) {
5694
+ itemContent.push(nextLine);
5695
+ totalRaw = `${totalRaw}${nextLine}
5696
+ `;
5697
+ i += 1;
5698
+ } else {
5699
+ break;
5700
+ }
5701
+ }
5702
+ let nestedTokens;
5703
+ const nestedContent = itemContent.slice(1);
5704
+ if (nestedContent.length > 0) {
5705
+ const dedentedNested = nestedContent.map((nestedLine) => nestedLine.slice(indentLevel + baseIndentSize)).join("\n");
5706
+ if (dedentedNested.trim()) {
5707
+ if (config.customNestedParser) {
5708
+ nestedTokens = config.customNestedParser(dedentedNested);
5709
+ } else {
5710
+ nestedTokens = lexer.blockTokens(dedentedNested);
5711
+ }
5712
+ }
5713
+ }
5714
+ const token = config.createToken(itemData, nestedTokens);
5715
+ items.push(token);
5716
+ }
5717
+ if (items.length === 0) {
5718
+ return void 0;
5719
+ }
5720
+ return {
5721
+ items,
5722
+ raw: totalRaw
5723
+ };
5724
+ }
5725
+ function renderNestedMarkdownContent(node, h2, prefixOrGenerator, ctx) {
5726
+ if (!node || !Array.isArray(node.content)) {
5727
+ return "";
5728
+ }
5729
+ const prefix = typeof prefixOrGenerator === "function" ? prefixOrGenerator(ctx) : prefixOrGenerator;
5730
+ const [content, ...children] = node.content;
5731
+ const mainContent = h2.renderChildren([content]);
5732
+ const output = [`${prefix}${mainContent}`];
5733
+ if (children && children.length > 0) {
5734
+ children.forEach((child) => {
5735
+ const childContent = h2.renderChildren([child]);
5736
+ if (childContent) {
5737
+ const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : "").join("\n");
5738
+ output.push(indentedChild);
5739
+ }
5740
+ });
5741
+ }
5742
+ return output.join("\n");
5743
+ }
5744
+ var Node3 = class _Node extends Extendable {
5745
+ constructor() {
5746
+ super(...arguments);
5747
+ this.type = "node";
5748
+ }
5749
+ /**
5750
+ * Create a new Node instance
5751
+ * @param config - Node configuration object or a function that returns a configuration object
5752
+ */
5753
+ static create(config = {}) {
5754
+ const resolvedConfig = typeof config === "function" ? config() : config;
5755
+ return new _Node(resolvedConfig);
5756
+ }
5757
+ configure(options) {
5758
+ return super.configure(options);
5759
+ }
5760
+ extend(extendedConfig) {
5761
+ const resolvedConfig = typeof extendedConfig === "function" ? extendedConfig() : extendedConfig;
5762
+ return super.extend(resolvedConfig);
5763
+ }
5764
+ };
5765
+ function get_current_font_size2(editor) {
5766
+ const attrs = editor.getAttributes("textStyle");
5767
+ if (attrs?.fontSize) {
5768
+ const parsed = parseInt(attrs.fontSize.replace("px", ""), 10);
5769
+ return isNaN(parsed) ? DEFAULT_FONT_SIZE : parsed;
5770
+ }
5771
+ return DEFAULT_FONT_SIZE;
5772
+ }
5773
+ function get_next_font_size(current, direction) {
5774
+ let index = FONT_SIZES.findIndex((s) => s >= current);
5775
+ if (index === -1) {
5776
+ index = FONT_SIZES.length - 1;
5777
+ }
5778
+ if (direction === "increase") {
5779
+ if (FONT_SIZES[index] === current) {
5780
+ return Math.min(FONT_SIZES[index + 1] ?? MAX_FONT_SIZE, MAX_FONT_SIZE);
5781
+ }
5782
+ return Math.min(FONT_SIZES[index], MAX_FONT_SIZE);
5783
+ } else {
5784
+ if (FONT_SIZES[index] === current && index > 0) {
5785
+ return Math.max(FONT_SIZES[index - 1], MIN_FONT_SIZE);
5786
+ }
5787
+ const prev_index = index > 0 ? index - 1 : 0;
5788
+ return Math.max(FONT_SIZES[prev_index], MIN_FONT_SIZE);
5789
+ }
5790
+ }
5791
+ var FontSizeExtension = Extension.create({
5792
+ name: "hazoFontSize",
5793
+ addOptions() {
5794
+ return {
5795
+ types: ["textStyle"]
5796
+ };
5797
+ },
5798
+ addGlobalAttributes() {
5799
+ return [
5800
+ {
5801
+ types: this.options.types,
5802
+ attributes: {
5803
+ fontSize: {
5804
+ default: null,
5805
+ parseHTML: (element) => element.style.fontSize?.replace(/['"]+/g, ""),
5806
+ renderHTML: (attributes) => {
5807
+ if (!attributes.fontSize) {
5808
+ return {};
5809
+ }
5810
+ return {
5811
+ style: `font-size: ${attributes.fontSize}`
5812
+ };
5813
+ }
5814
+ }
5815
+ }
5816
+ }
5817
+ ];
5818
+ },
5819
+ addCommands() {
5820
+ return {
5821
+ setFontSize: (size) => ({ chain }) => {
5822
+ return chain().setMark("textStyle", { fontSize: size }).run();
5823
+ },
5824
+ unsetFontSize: () => ({ chain }) => {
5825
+ return chain().setMark("textStyle", { fontSize: null }).removeEmptyTextStyle().run();
5826
+ },
5827
+ increaseFontSize: () => ({ chain, editor }) => {
5828
+ const current_size = get_current_font_size2(editor);
5829
+ const next_size = get_next_font_size(current_size, "increase");
5830
+ return chain().setMark("textStyle", { fontSize: `${next_size}px` }).run();
5831
+ },
5832
+ decreaseFontSize: () => ({ chain, editor }) => {
5833
+ const current_size = get_current_font_size2(editor);
5834
+ const next_size = get_next_font_size(current_size, "decrease");
5835
+ return chain().setMark("textStyle", { fontSize: `${next_size}px` }).run();
5836
+ }
5837
+ };
5838
+ }
5839
+ });
5840
+ function VariableChipNodeView({ node }) {
5841
+ const { variable_name, variable_text } = node.attrs;
5842
+ return /* @__PURE__ */ jsxs(
5843
+ NodeViewWrapper,
5844
+ {
5845
+ as: "span",
5846
+ className: "cls_variable_chip inline-flex items-center px-2 py-0.5 mx-0.5 rounded-md bg-primary/10 text-primary text-sm font-medium border border-primary/20 cursor-default select-none",
5847
+ contentEditable: false,
5848
+ children: [
5849
+ /* @__PURE__ */ jsx("span", { className: "cls_variable_chip_icon mr-1 text-xs opacity-70", children: "{" }),
5850
+ /* @__PURE__ */ jsx("span", { className: "cls_variable_chip_text", children: variable_text || variable_name }),
5851
+ /* @__PURE__ */ jsx("span", { className: "cls_variable_chip_icon ml-1 text-xs opacity-70", children: "}" })
5852
+ ]
5853
+ }
5854
+ );
5855
+ }
5856
+ var variable_chip_default = VariableChipNodeView;
5857
+
5858
+ // src/components/hazo_ui_richtext_editor/extensions/variable_extension.ts
5859
+ var VariableExtension = Node3.create({
5860
+ name: "variable",
5861
+ group: "inline",
5862
+ inline: true,
5863
+ // Atomic means it's not editable directly
5864
+ atom: true,
5865
+ addOptions() {
5866
+ return {
5867
+ HTMLAttributes: {}
5868
+ };
5869
+ },
5870
+ addAttributes() {
5871
+ return {
5872
+ variable_name: {
5873
+ default: null,
5874
+ parseHTML: (element) => element.getAttribute("data-variable-name"),
5875
+ renderHTML: (attributes) => ({
5876
+ "data-variable-name": attributes.variable_name
5877
+ })
5878
+ },
5879
+ variable_text: {
5880
+ default: null,
5881
+ parseHTML: (element) => element.getAttribute("data-variable-text"),
5882
+ renderHTML: (attributes) => ({
5883
+ "data-variable-text": attributes.variable_text
5884
+ })
5885
+ }
5886
+ };
5887
+ },
5888
+ parseHTML() {
5889
+ return [
5890
+ {
5891
+ tag: 'span[data-type="variable"]'
5892
+ }
5893
+ ];
5894
+ },
5895
+ renderHTML({ node, HTMLAttributes }) {
5896
+ return [
5897
+ "span",
5898
+ mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
5899
+ "data-type": "variable",
5900
+ class: "cls_variable_chip_output"
5901
+ }),
5902
+ `{{${node.attrs.variable_name}}}`
5903
+ ];
5904
+ },
5905
+ // Include variable placeholder in plain text output
5906
+ renderText({ node }) {
5907
+ return `{{${node.attrs.variable_name}}}`;
5908
+ },
5909
+ addNodeView() {
5910
+ return ReactNodeViewRenderer(variable_chip_default);
5911
+ },
5912
+ addCommands() {
5913
+ return {
5914
+ insertVariable: (variable_name, variable_text) => ({ commands }) => {
5915
+ return commands.insertContent({
5916
+ type: this.name,
5917
+ attrs: { variable_name, variable_text }
5918
+ });
5919
+ }
5920
+ };
5921
+ }
5922
+ });
5923
+
5924
+ // src/components/hazo_ui_richtext_editor/extensions/column_layout_extension.ts
5925
+ var ColumnLayoutExtension = Node3.create({
5926
+ name: "columnLayout",
5927
+ group: "block",
5928
+ content: "column+",
5929
+ defining: true,
5930
+ addOptions() {
5931
+ return {
5932
+ HTMLAttributes: {}
5933
+ };
5934
+ },
5935
+ addAttributes() {
5936
+ return {
5937
+ columns: {
5938
+ default: 2,
5939
+ parseHTML: (element) => parseInt(element.getAttribute("data-columns") || "2", 10),
5940
+ renderHTML: (attributes) => ({
5941
+ "data-columns": attributes.columns
5942
+ })
5943
+ }
5944
+ };
5945
+ },
5946
+ parseHTML() {
5947
+ return [
5948
+ {
5949
+ tag: 'div[data-type="column-layout"]'
5950
+ }
5951
+ ];
5952
+ },
5953
+ renderHTML({ HTMLAttributes }) {
5954
+ const columns = HTMLAttributes.columns || 2;
5955
+ return [
5956
+ "div",
5957
+ mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
5958
+ "data-type": "column-layout",
5959
+ class: `cls_column_layout cls_columns_${columns}`,
5960
+ style: `display: grid; grid-template-columns: repeat(${columns}, 1fr); gap: 1rem;`
5961
+ }),
5962
+ 0
5963
+ ];
5964
+ },
5965
+ addCommands() {
5966
+ return {
5967
+ insertColumnLayout: (columns) => ({ commands }) => {
5968
+ const column_content = Array(columns).fill(null).map(() => ({
5969
+ type: "column",
5970
+ content: [{ type: "paragraph" }]
5971
+ }));
5972
+ return commands.insertContent({
5973
+ type: this.name,
5974
+ attrs: { columns },
5975
+ content: column_content
5976
+ });
5977
+ }
5978
+ };
5979
+ }
5980
+ });
5981
+ var ColumnExtension = Node3.create({
5982
+ name: "column",
5983
+ group: "column",
5984
+ content: "block+",
5985
+ defining: true,
5986
+ parseHTML() {
5987
+ return [
5988
+ {
5989
+ tag: 'div[data-type="column"]'
5990
+ }
5991
+ ];
5992
+ },
5993
+ renderHTML({ HTMLAttributes }) {
5994
+ return [
5995
+ "div",
5996
+ mergeAttributes(HTMLAttributes, {
5997
+ "data-type": "column",
5998
+ class: "cls_column",
5999
+ style: "min-width: 0;"
6000
+ }),
6001
+ 0
6002
+ ];
6003
+ }
6004
+ });
6005
+ function format_file_size(bytes) {
6006
+ if (bytes === 0) return "0 B";
6007
+ const k = 1024;
6008
+ const sizes = ["B", "KB", "MB", "GB"];
6009
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
6010
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
6011
+ }
6012
+ function HazoRichtextEditor({
6013
+ initial_html = "",
6014
+ initial_text = "",
6015
+ variables = [],
6016
+ initial_attachments = [],
6017
+ on_save,
6018
+ on_change,
6019
+ on_attachments_change,
6020
+ on_file_attach,
6021
+ placeholder = DEFAULT_PLACEHOLDER,
6022
+ min_height = DEFAULT_MIN_HEIGHT,
6023
+ max_height = DEFAULT_MAX_HEIGHT,
6024
+ read_only = false,
6025
+ show_save_button = true,
6026
+ save_button_text = "Save",
6027
+ className
6028
+ }) {
6029
+ const [state, set_state] = React14.useState({
6030
+ active_tab: "visual",
6031
+ html_view_mode: "preview",
6032
+ html_content: initial_html,
6033
+ text_content: initial_text,
6034
+ is_variables_modal_open: false
6035
+ });
6036
+ const [attachments, set_attachments] = React14.useState(initial_attachments);
6037
+ const editor = useEditor({
6038
+ extensions: [
6039
+ StarterKit.configure({
6040
+ heading: {
6041
+ levels: [1, 2, 3]
6042
+ }
6043
+ }),
6044
+ Underline,
6045
+ TextStyle,
6046
+ Color,
6047
+ Highlight.configure({
6048
+ multicolor: true
6049
+ }),
6050
+ FontFamily,
6051
+ FontSizeExtension,
6052
+ TextAlign.configure({
6053
+ types: ["heading", "paragraph"]
6054
+ }),
6055
+ Link.configure({
6056
+ openOnClick: false,
6057
+ HTMLAttributes: {
6058
+ class: "cls_editor_link text-primary underline cursor-pointer"
6059
+ }
6060
+ }),
6061
+ Image.configure({
6062
+ HTMLAttributes: {
6063
+ class: "cls_editor_image max-w-full h-auto rounded-md"
6064
+ }
6065
+ }),
6066
+ Table.configure({
6067
+ resizable: true,
6068
+ HTMLAttributes: {
6069
+ class: "cls_editor_table border-collapse w-full"
6070
+ }
6071
+ }),
6072
+ TableRow,
6073
+ TableCell.configure({
6074
+ HTMLAttributes: {
6075
+ class: "cls_editor_table_cell border border-border p-2"
6076
+ }
6077
+ }),
6078
+ TableHeader.configure({
6079
+ HTMLAttributes: {
6080
+ class: "cls_editor_table_header border border-border p-2 bg-muted font-medium"
6081
+ }
6082
+ }),
6083
+ TaskList.configure({
6084
+ HTMLAttributes: {
6085
+ class: "cls_editor_task_list"
6086
+ }
6087
+ }),
6088
+ TaskItem.configure({
6089
+ nested: true,
6090
+ HTMLAttributes: {
6091
+ class: "cls_editor_task_item"
6092
+ }
6093
+ }),
6094
+ Subscript,
6095
+ Superscript,
6096
+ Placeholder.configure({
6097
+ placeholder,
6098
+ emptyEditorClass: "cls_editor_empty"
6099
+ }),
6100
+ VariableExtension,
6101
+ ColumnLayoutExtension,
6102
+ ColumnExtension
6103
+ ],
6104
+ content: initial_html || `<p>${initial_text}</p>`,
6105
+ editable: !read_only,
6106
+ immediatelyRender: false,
6107
+ onUpdate: ({ editor: editor2 }) => {
6108
+ const html = editor2.getHTML();
6109
+ const text = editor2.getText();
6110
+ set_state((prev) => ({
6111
+ ...prev,
6112
+ html_content: html,
6113
+ text_content: text
6114
+ }));
6115
+ on_change?.(html, text);
6116
+ }
6117
+ });
6118
+ React14.useEffect(() => {
6119
+ if (editor && state.active_tab === "visual") {
6120
+ const current_html = editor.getHTML();
6121
+ if (current_html !== state.html_content && state.html_content) {
6122
+ editor.commands.setContent(state.html_content);
6123
+ }
6124
+ }
6125
+ }, [state.active_tab, editor, state.html_content]);
6126
+ const handle_tab_change = (tab) => {
6127
+ if (editor && tab !== "visual" && state.active_tab === "visual") {
6128
+ set_state((prev) => ({
6129
+ ...prev,
6130
+ active_tab: tab,
6131
+ html_content: editor.getHTML(),
6132
+ text_content: editor.getText()
6133
+ }));
6134
+ } else {
6135
+ set_state((prev) => ({
6136
+ ...prev,
6137
+ active_tab: tab
6138
+ }));
6139
+ }
6140
+ };
6141
+ const handle_html_change = (html) => {
6142
+ set_state((prev) => ({
6143
+ ...prev,
6144
+ html_content: html
6145
+ }));
6146
+ };
6147
+ const handle_text_change = (text) => {
6148
+ set_state((prev) => ({
6149
+ ...prev,
6150
+ text_content: text
6151
+ }));
6152
+ };
6153
+ const handle_html_view_mode_change = (mode) => {
6154
+ set_state((prev) => ({
6155
+ ...prev,
6156
+ html_view_mode: mode
6157
+ }));
6158
+ };
6159
+ const handle_variable_select = (variable) => {
6160
+ if (editor) {
6161
+ editor.chain().focus().insertVariable(variable.text, variable.description).run();
6162
+ }
6163
+ };
6164
+ const handle_save = () => {
6165
+ const html = editor?.getHTML() || state.html_content;
6166
+ const text = editor?.getText() || state.text_content;
6167
+ on_save?.(html, text, attachments);
6168
+ };
6169
+ const open_variables_modal = () => {
6170
+ set_state((prev) => ({
6171
+ ...prev,
6172
+ is_variables_modal_open: true
6173
+ }));
6174
+ };
6175
+ const close_variables_modal = () => {
6176
+ set_state((prev) => ({
6177
+ ...prev,
6178
+ is_variables_modal_open: false
6179
+ }));
6180
+ };
6181
+ const generate_attachment_id = () => {
6182
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
6183
+ };
6184
+ const handle_add_attachment = async (file) => {
6185
+ return new Promise((resolve, reject) => {
6186
+ const reader = new FileReader();
6187
+ reader.onload = () => {
6188
+ const new_attachment = {
6189
+ id: generate_attachment_id(),
6190
+ name: file.name,
6191
+ type: file.type,
6192
+ size: file.size,
6193
+ data: reader.result
6194
+ };
6195
+ const updated_attachments = [...attachments, new_attachment];
6196
+ set_attachments(updated_attachments);
6197
+ on_attachments_change?.(updated_attachments);
6198
+ resolve();
6199
+ };
6200
+ reader.onerror = reject;
6201
+ reader.readAsDataURL(file);
6202
+ });
6203
+ };
6204
+ const handle_remove_attachment = (id) => {
6205
+ const updated_attachments = attachments.filter((a) => a.id !== id);
6206
+ set_attachments(updated_attachments);
6207
+ on_attachments_change?.(updated_attachments);
6208
+ };
6209
+ const handle_image_embed = async (file) => {
6210
+ let url;
6211
+ let base64_data;
6212
+ if (on_file_attach) {
6213
+ url = await on_file_attach(file);
6214
+ base64_data = await new Promise((resolve, reject) => {
6215
+ const reader = new FileReader();
6216
+ reader.onload = () => resolve(reader.result);
6217
+ reader.onerror = reject;
6218
+ reader.readAsDataURL(file);
6219
+ });
6220
+ } else {
6221
+ base64_data = await new Promise((resolve, reject) => {
6222
+ const reader = new FileReader();
6223
+ reader.onload = () => resolve(reader.result);
6224
+ reader.onerror = reject;
6225
+ reader.readAsDataURL(file);
6226
+ });
6227
+ url = base64_data;
6228
+ }
6229
+ if (editor) {
6230
+ editor.chain().focus().setImage({ src: url, alt: file.name }).run();
6231
+ }
6232
+ const new_attachment = {
6233
+ id: generate_attachment_id(),
6234
+ name: file.name,
6235
+ type: file.type,
6236
+ size: file.size,
6237
+ data: base64_data
6238
+ };
6239
+ const updated_attachments = [...attachments, new_attachment];
6240
+ set_attachments(updated_attachments);
6241
+ on_attachments_change?.(updated_attachments);
6242
+ return url;
6243
+ };
6244
+ return /* @__PURE__ */ jsxs(
6245
+ "div",
6246
+ {
6247
+ className: cn(
6248
+ "cls_richtext_editor border border-border rounded-lg overflow-hidden bg-background",
6249
+ className
6250
+ ),
6251
+ children: [
6252
+ state.active_tab === "visual" && !read_only && /* @__PURE__ */ jsx(
6253
+ Toolbar,
6254
+ {
6255
+ editor,
6256
+ on_open_variables_modal: open_variables_modal,
6257
+ variables,
6258
+ on_image_embed: handle_image_embed,
6259
+ on_add_attachment: handle_add_attachment
6260
+ }
6261
+ ),
6262
+ /* @__PURE__ */ jsx(
6263
+ ViewTabs,
6264
+ {
6265
+ active_tab: state.active_tab,
6266
+ on_tab_change: handle_tab_change,
6267
+ editor,
6268
+ html_content: state.html_content,
6269
+ text_content: state.text_content,
6270
+ on_html_change: handle_html_change,
6271
+ on_text_change: handle_text_change,
6272
+ html_view_mode: state.html_view_mode,
6273
+ on_html_view_mode_change: handle_html_view_mode_change,
6274
+ min_height,
6275
+ max_height,
6276
+ read_only,
6277
+ children: /* @__PURE__ */ jsx(
6278
+ EditorContent,
6279
+ {
6280
+ editor,
6281
+ className: cn(
6282
+ "cls_editor_content prose prose-sm max-w-none p-4",
6283
+ "focus-within:outline-none",
6284
+ "[&_.ProseMirror]:outline-none [&_.ProseMirror]:min-h-[inherit]",
6285
+ "[&_.ProseMirror_p.is-editor-empty:first-child::before]:text-muted-foreground",
6286
+ "[&_.ProseMirror_p.is-editor-empty:first-child::before]:content-[attr(data-placeholder)]",
6287
+ "[&_.ProseMirror_p.is-editor-empty:first-child::before]:float-left",
6288
+ "[&_.ProseMirror_p.is-editor-empty:first-child::before]:h-0",
6289
+ "[&_.ProseMirror_p.is-editor-empty:first-child::before]:pointer-events-none"
6290
+ )
6291
+ }
6292
+ )
6293
+ }
6294
+ ),
6295
+ attachments.length > 0 && /* @__PURE__ */ jsxs("div", { className: "cls_attachments_section border-t border-border p-3 bg-muted/20", children: [
6296
+ /* @__PURE__ */ jsxs("div", { className: "cls_attachments_header text-xs font-medium text-muted-foreground mb-2", children: [
6297
+ "Attachments (",
6298
+ attachments.length,
6299
+ ")"
6300
+ ] }),
6301
+ /* @__PURE__ */ jsx("div", { className: "cls_attachments_list flex flex-wrap gap-2", children: attachments.map((attachment) => /* @__PURE__ */ jsxs(
6302
+ "div",
6303
+ {
6304
+ className: "cls_attachment_item flex items-center gap-2 px-2 py-1 rounded-md bg-background border border-border text-sm",
6305
+ children: [
6306
+ attachment.type.startsWith("image/") ? /* @__PURE__ */ jsx(
6307
+ "img",
6308
+ {
6309
+ src: attachment.data,
6310
+ alt: attachment.name,
6311
+ className: "cls_attachment_thumbnail h-6 w-6 object-cover rounded"
6312
+ }
6313
+ ) : /* @__PURE__ */ jsx("span", { className: "cls_attachment_icon text-muted-foreground", children: "\u{1F4CE}" }),
6314
+ /* @__PURE__ */ jsx("span", { className: "cls_attachment_name max-w-[150px] truncate", children: attachment.name }),
6315
+ /* @__PURE__ */ jsxs("span", { className: "cls_attachment_size text-xs text-muted-foreground", children: [
6316
+ "(",
6317
+ format_file_size(attachment.size),
6318
+ ")"
6319
+ ] }),
6320
+ !read_only && /* @__PURE__ */ jsx(
6321
+ "button",
6322
+ {
6323
+ onClick: () => handle_remove_attachment(attachment.id),
6324
+ className: "cls_attachment_remove ml-1 text-muted-foreground hover:text-destructive",
6325
+ "aria-label": "Remove attachment",
6326
+ children: "\xD7"
6327
+ }
6328
+ )
6329
+ ]
6330
+ },
6331
+ attachment.id
6332
+ )) })
6333
+ ] }),
6334
+ show_save_button && on_save && /* @__PURE__ */ jsx("div", { className: "cls_richtext_editor_footer flex items-center justify-end p-3 border-t border-border bg-muted/30", children: /* @__PURE__ */ jsx(Button, { onClick: handle_save, size: "sm", children: save_button_text }) }),
6335
+ /* @__PURE__ */ jsx(
6336
+ VariablesModal,
6337
+ {
6338
+ is_open: state.is_variables_modal_open,
6339
+ on_close: close_variables_modal,
6340
+ variables,
6341
+ on_select_variable: handle_variable_select
6342
+ }
6343
+ )
6344
+ ]
6345
+ }
6346
+ );
6347
+ }
6348
+
6349
+ export { HazoRichtextEditor, HazoUiFlexInput, HazoUiFlexRadio, HazoUiMultiFilterDialog, HazoUiMultiSortDialog };
1634
6350
  //# sourceMappingURL=index.js.map
1635
6351
  //# sourceMappingURL=index.js.map