hazo_ui 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import * as React23 from 'react';
2
- import React23__default, { useRef, useState, useCallback, useEffect, useMemo, Fragment } from 'react';
1
+ import * as React27 from 'react';
2
+ import React27__default, { useRef, useState, useCallback, useEffect, useMemo, Fragment } from 'react';
3
3
  import { Slot } from '@radix-ui/react-slot';
4
4
  import { cva } from 'class-variance-authority';
5
5
  import { clsx } from 'clsx';
@@ -52,6 +52,8 @@ import { LuUndo2, LuRedo2, LuMinus, LuPlus, LuBold, LuItalic, LuUnderline, LuStr
52
52
  import { RxDividerHorizontal } from 'react-icons/rx';
53
53
  import { Extension, Node, mergeAttributes } from '@tiptap/core';
54
54
  import * as TabsPrimitive from '@radix-ui/react-tabs';
55
+ import Suggestion from '@tiptap/suggestion';
56
+ import { createPortal } from 'react-dom';
55
57
 
56
58
  var __create = Object.create;
57
59
  var __defProp = Object.defineProperty;
@@ -138,7 +140,7 @@ var buttonVariants = cva(
138
140
  }
139
141
  }
140
142
  );
141
- var Button = React23.forwardRef(
143
+ var Button = React27.forwardRef(
142
144
  ({ className, variant, size, asChild = false, ...props }, ref) => {
143
145
  const Comp = asChild ? Slot : "button";
144
146
  return /* @__PURE__ */ jsx(
@@ -155,7 +157,7 @@ Button.displayName = "Button";
155
157
  var Dialog = DialogPrimitive.Root;
156
158
  var DialogTrigger = DialogPrimitive.Trigger;
157
159
  var DialogPortal = DialogPrimitive.Portal;
158
- var DialogOverlay = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
160
+ var DialogOverlay = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
159
161
  DialogPrimitive.Overlay,
160
162
  {
161
163
  ref,
@@ -167,7 +169,7 @@ var DialogOverlay = React23.forwardRef(({ className, ...props }, ref) => /* @__P
167
169
  }
168
170
  ));
169
171
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
170
- var DialogContent = React23.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
172
+ var DialogContent = React27.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
171
173
  /* @__PURE__ */ jsx(DialogOverlay, {}),
172
174
  /* @__PURE__ */ jsxs(
173
175
  DialogPrimitive.Content,
@@ -217,7 +219,7 @@ var DialogFooter = ({
217
219
  }
218
220
  );
219
221
  DialogFooter.displayName = "DialogFooter";
220
- var DialogTitle = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
222
+ var DialogTitle = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
221
223
  DialogPrimitive.Title,
222
224
  {
223
225
  ref,
@@ -229,7 +231,7 @@ var DialogTitle = React23.forwardRef(({ className, ...props }, ref) => /* @__PUR
229
231
  }
230
232
  ));
231
233
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
232
- var DialogDescription = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
234
+ var DialogDescription = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
233
235
  DialogPrimitive.Description,
234
236
  {
235
237
  ref,
@@ -238,7 +240,7 @@ var DialogDescription = React23.forwardRef(({ className, ...props }, ref) => /*
238
240
  }
239
241
  ));
240
242
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
241
- var Command = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
243
+ var Command = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
242
244
  "div",
243
245
  {
244
246
  ref,
@@ -250,7 +252,7 @@ var Command = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__
250
252
  }
251
253
  ));
252
254
  Command.displayName = "Command";
253
- var CommandInput = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
255
+ var CommandInput = React27.forwardRef(({ className, onValueChange, onChange, ...props }, ref) => /* @__PURE__ */ jsx(
254
256
  "input",
255
257
  {
256
258
  ref,
@@ -258,11 +260,15 @@ var CommandInput = React23.forwardRef(({ className, ...props }, ref) => /* @__PU
258
260
  "flex h-11 w-full rounded-md border border-input bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 px-3",
259
261
  className
260
262
  ),
263
+ onChange: (e) => {
264
+ onChange?.(e);
265
+ onValueChange?.(e.target.value);
266
+ },
261
267
  ...props
262
268
  }
263
269
  ));
264
270
  CommandInput.displayName = "CommandInput";
265
- var CommandList = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
271
+ var CommandList = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
266
272
  "div",
267
273
  {
268
274
  ref,
@@ -271,7 +277,7 @@ var CommandList = React23.forwardRef(({ className, ...props }, ref) => /* @__PUR
271
277
  }
272
278
  ));
273
279
  CommandList.displayName = "CommandList";
274
- var CommandEmpty = React23.forwardRef((props, ref) => /* @__PURE__ */ jsx(
280
+ var CommandEmpty = React27.forwardRef((props, ref) => /* @__PURE__ */ jsx(
275
281
  "div",
276
282
  {
277
283
  ref,
@@ -280,19 +286,23 @@ var CommandEmpty = React23.forwardRef((props, ref) => /* @__PURE__ */ jsx(
280
286
  }
281
287
  ));
282
288
  CommandEmpty.displayName = "CommandEmpty";
283
- var CommandGroup = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
289
+ var CommandGroup = React27.forwardRef(({ className, heading, children, ...props }, ref) => /* @__PURE__ */ jsxs(
284
290
  "div",
285
291
  {
286
292
  ref,
287
293
  className: cn(
288
- "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
294
+ "overflow-hidden p-1 text-foreground",
289
295
  className
290
296
  ),
291
- ...props
297
+ ...props,
298
+ children: [
299
+ heading && /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs font-medium text-muted-foreground", children: heading }),
300
+ children
301
+ ]
292
302
  }
293
303
  ));
294
304
  CommandGroup.displayName = "CommandGroup";
295
- var CommandItem = React23.forwardRef(({ className, onSelect, value, ...props }, ref) => {
305
+ var CommandItem = React27.forwardRef(({ className, onSelect, value, ...props }, ref) => {
296
306
  const handleClick = () => {
297
307
  if (onSelect && value) {
298
308
  onSelect(value);
@@ -314,7 +324,7 @@ var CommandItem = React23.forwardRef(({ className, onSelect, value, ...props },
314
324
  CommandItem.displayName = "CommandItem";
315
325
  var Popover = PopoverPrimitive.Root;
316
326
  var PopoverTrigger = PopoverPrimitive.Trigger;
317
- var PopoverContent = React23.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
327
+ var PopoverContent = React27.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
318
328
  PopoverPrimitive.Content,
319
329
  {
320
330
  ref,
@@ -328,7 +338,7 @@ var PopoverContent = React23.forwardRef(({ className, align = "center", sideOffs
328
338
  }
329
339
  ) }));
330
340
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
331
- var Input = React23.forwardRef(
341
+ var Input = React27.forwardRef(
332
342
  ({ className, type, ...props }, ref) => {
333
343
  return /* @__PURE__ */ jsx(
334
344
  "input",
@@ -347,7 +357,7 @@ var Input = React23.forwardRef(
347
357
  Input.displayName = "Input";
348
358
  var Select = SelectPrimitive.Root;
349
359
  var SelectValue = SelectPrimitive.Value;
350
- var SelectTrigger = React23.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
360
+ var SelectTrigger = React27.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
351
361
  SelectPrimitive.Trigger,
352
362
  {
353
363
  ref,
@@ -363,7 +373,7 @@ var SelectTrigger = React23.forwardRef(({ className, children, ...props }, ref)
363
373
  }
364
374
  ));
365
375
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
366
- var SelectScrollUpButton = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
376
+ var SelectScrollUpButton = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
367
377
  SelectPrimitive.ScrollUpButton,
368
378
  {
369
379
  ref,
@@ -376,7 +386,7 @@ var SelectScrollUpButton = React23.forwardRef(({ className, ...props }, ref) =>
376
386
  }
377
387
  ));
378
388
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
379
- var SelectScrollDownButton = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
389
+ var SelectScrollDownButton = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
380
390
  SelectPrimitive.ScrollDownButton,
381
391
  {
382
392
  ref,
@@ -389,7 +399,7 @@ var SelectScrollDownButton = React23.forwardRef(({ className, ...props }, ref) =
389
399
  }
390
400
  ));
391
401
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
392
- var SelectContent = React23.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
402
+ var SelectContent = React27.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
393
403
  SelectPrimitive.Content,
394
404
  {
395
405
  ref,
@@ -417,7 +427,7 @@ var SelectContent = React23.forwardRef(({ className, children, position = "poppe
417
427
  }
418
428
  ) }));
419
429
  SelectContent.displayName = SelectPrimitive.Content.displayName;
420
- var SelectLabel = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
430
+ var SelectLabel = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
421
431
  SelectPrimitive.Label,
422
432
  {
423
433
  ref,
@@ -426,7 +436,7 @@ var SelectLabel = React23.forwardRef(({ className, ...props }, ref) => /* @__PUR
426
436
  }
427
437
  ));
428
438
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
429
- var SelectItem = React23.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
439
+ var SelectItem = React27.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
430
440
  SelectPrimitive.Item,
431
441
  {
432
442
  ref,
@@ -442,7 +452,7 @@ var SelectItem = React23.forwardRef(({ className, children, ...props }, ref) =>
442
452
  }
443
453
  ));
444
454
  SelectItem.displayName = SelectPrimitive.Item.displayName;
445
- var SelectSeparator = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
455
+ var SelectSeparator = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
446
456
  SelectPrimitive.Separator,
447
457
  {
448
458
  ref,
@@ -454,7 +464,7 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
454
464
  var TooltipProvider = TooltipPrimitive.Provider;
455
465
  var Tooltip = TooltipPrimitive.Root;
456
466
  var TooltipTrigger = TooltipPrimitive.Trigger;
457
- var TooltipContent = React23.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
467
+ var TooltipContent = React27.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
458
468
  TooltipPrimitive.Content,
459
469
  {
460
470
  ref,
@@ -925,7 +935,7 @@ function HazoUiMultiFilterDialog({
925
935
  ] })
926
936
  ] });
927
937
  }
928
- var Switch = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
938
+ var Switch = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
929
939
  SwitchPrimitives.Root,
930
940
  {
931
941
  className: cn(
@@ -945,7 +955,7 @@ var Switch = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
945
955
  }
946
956
  ));
947
957
  Switch.displayName = SwitchPrimitives.Root.displayName;
948
- var Label2 = React23.forwardRef(
958
+ var Label2 = React27.forwardRef(
949
959
  ({ className, ...props }, ref) => {
950
960
  return /* @__PURE__ */ jsx(
951
961
  "label",
@@ -1239,7 +1249,7 @@ function HazoUiMultiSortDialog({
1239
1249
  ] })
1240
1250
  ] });
1241
1251
  }
1242
- var RadioGroup = React23.forwardRef(({ className, ...props }, ref) => {
1252
+ var RadioGroup = React27.forwardRef(({ className, ...props }, ref) => {
1243
1253
  return /* @__PURE__ */ jsx(
1244
1254
  RadioGroupPrimitive.Root,
1245
1255
  {
@@ -1250,7 +1260,7 @@ var RadioGroup = React23.forwardRef(({ className, ...props }, ref) => {
1250
1260
  );
1251
1261
  });
1252
1262
  RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
1253
- var RadioGroupItem = React23.forwardRef(({ className, ...props }, ref) => {
1263
+ var RadioGroupItem = React27.forwardRef(({ className, ...props }, ref) => {
1254
1264
  return /* @__PURE__ */ jsx(
1255
1265
  RadioGroupPrimitive.Item,
1256
1266
  {
@@ -1604,7 +1614,7 @@ function filterInputValue(value, input_type, num_decimals) {
1604
1614
  }
1605
1615
  }
1606
1616
  }
1607
- var HazoUiFlexInput = React23.forwardRef(
1617
+ var HazoUiFlexInput = React27.forwardRef(
1608
1618
  ({
1609
1619
  className,
1610
1620
  input_type = "mixed",
@@ -1621,13 +1631,13 @@ var HazoUiFlexInput = React23.forwardRef(
1621
1631
  onBlur,
1622
1632
  ...props
1623
1633
  }, ref) => {
1624
- const [internalValue, setInternalValue] = React23.useState(
1634
+ const [internalValue, setInternalValue] = React27.useState(
1625
1635
  typeof controlledValue === "string" ? controlledValue : typeof controlledValue === "number" ? String(controlledValue) : ""
1626
1636
  );
1627
- const [errorMessage, setErrorMessage] = React23.useState();
1637
+ const [errorMessage, setErrorMessage] = React27.useState();
1628
1638
  const isControlled = controlledValue !== void 0;
1629
1639
  const currentValue = isControlled ? typeof controlledValue === "string" ? controlledValue : String(controlledValue || "") : internalValue;
1630
- React23.useEffect(() => {
1640
+ React27.useEffect(() => {
1631
1641
  if (isControlled) {
1632
1642
  const newValue = typeof controlledValue === "string" ? controlledValue : String(controlledValue || "");
1633
1643
  if (newValue !== internalValue) {
@@ -1707,7 +1717,7 @@ var HazoUiFlexInput = React23.forwardRef(
1707
1717
  }
1708
1718
  );
1709
1719
  HazoUiFlexInput.displayName = "HazoUiFlexInput";
1710
- var ToolbarButton = React23.forwardRef(
1720
+ var ToolbarButton = React27.forwardRef(
1711
1721
  ({ onClick, is_active = false, disabled = false, tooltip, className, children }, ref) => {
1712
1722
  const button = /* @__PURE__ */ jsx(
1713
1723
  "button",
@@ -2026,7 +2036,7 @@ var getRelativePosition = (node, event) => {
2026
2036
  };
2027
2037
  };
2028
2038
  var _excluded = ["prefixCls", "className", "onMove", "onDown"];
2029
- var Interactive = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2039
+ var Interactive = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2030
2040
  var {
2031
2041
  prefixCls = "w-color-interactive",
2032
2042
  className,
@@ -2125,7 +2135,7 @@ var Pointer = (_ref) => {
2125
2135
  }), [top, left, color2, className, prefixCls]);
2126
2136
  };
2127
2137
  var _excluded2 = ["prefixCls", "radius", "pointer", "className", "hue", "style", "hsva", "onChange"];
2128
- var Saturation = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2138
+ var Saturation = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2129
2139
  var _hsva$h;
2130
2140
  var {
2131
2141
  prefixCls = "w-color-saturation",
@@ -2277,7 +2287,7 @@ var Pointer2 = (_ref) => {
2277
2287
  };
2278
2288
  var _excluded4 = ["prefixCls", "className", "hsva", "background", "bgProps", "innerProps", "pointerProps", "radius", "width", "height", "direction", "style", "onChange", "pointer"];
2279
2289
  var BACKGROUND_IMG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==";
2280
- var Alpha = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2290
+ var Alpha = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2281
2291
  var {
2282
2292
  prefixCls = "w-color-alpha",
2283
2293
  className,
@@ -2411,7 +2421,7 @@ var import_objectWithoutPropertiesLoose5 = __toESM(require_objectWithoutProperti
2411
2421
  var _excluded5 = ["prefixCls", "placement", "label", "value", "className", "style", "labelStyle", "inputStyle", "onChange", "onBlur", "renderInput"];
2412
2422
  var validHex2 = (hex) => /^#?([A-Fa-f0-9]{3,4}){1,2}$/.test(hex);
2413
2423
  var getNumberValue = (value) => Number(String(value).replace(/%/g, ""));
2414
- var EditableInput = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2424
+ var EditableInput = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2415
2425
  var {
2416
2426
  prefixCls = "w-color-editable-input",
2417
2427
  placement = "bottom",
@@ -2516,7 +2526,7 @@ var esm_default4 = EditableInput;
2516
2526
  var import_extends7 = __toESM(require_extends());
2517
2527
  var import_objectWithoutPropertiesLoose6 = __toESM(require_objectWithoutPropertiesLoose());
2518
2528
  var _excluded6 = ["prefixCls", "hsva", "placement", "rProps", "gProps", "bProps", "aProps", "className", "style", "onChange"];
2519
- var EditableInputRGBA = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2529
+ var EditableInputRGBA = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2520
2530
  var {
2521
2531
  prefixCls = "w-color-editable-input-rgba",
2522
2532
  hsva,
@@ -2639,7 +2649,7 @@ var esm_default5 = EditableInputRGBA;
2639
2649
  var import_extends8 = __toESM(require_extends());
2640
2650
  var import_objectWithoutPropertiesLoose7 = __toESM(require_objectWithoutPropertiesLoose());
2641
2651
  var _excluded7 = ["prefixCls", "className", "hue", "onChange", "direction"];
2642
- var Hue = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2652
+ var Hue = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2643
2653
  var {
2644
2654
  prefixCls = "w-color-hue",
2645
2655
  className,
@@ -2673,7 +2683,7 @@ var esm_default6 = Hue;
2673
2683
  var import_extends9 = __toESM(require_extends());
2674
2684
  var import_objectWithoutPropertiesLoose8 = __toESM(require_objectWithoutPropertiesLoose());
2675
2685
  var _excluded8 = ["prefixCls", "className", "color", "colors", "style", "rectProps", "onChange", "addonAfter", "addonBefore", "rectRender"];
2676
- var Swatch = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2686
+ var Swatch = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2677
2687
  var {
2678
2688
  prefixCls = "w-color-swatch",
2679
2689
  className,
@@ -2710,7 +2720,7 @@ var Swatch = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2710
2720
  flexWrap: "wrap",
2711
2721
  position: "relative"
2712
2722
  }, style),
2713
- children: [addonBefore && /* @__PURE__ */ React23__default.isValidElement(addonBefore) && addonBefore, colors && Array.isArray(colors) && colors.map((item, idx) => {
2723
+ children: [addonBefore && /* @__PURE__ */ React27__default.isValidElement(addonBefore) && addonBefore, colors && Array.isArray(colors) && colors.map((item, idx) => {
2714
2724
  var title = "";
2715
2725
  var background = "";
2716
2726
  if (typeof item === "string") {
@@ -2736,7 +2746,7 @@ var Swatch = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2736
2746
  children: render
2737
2747
  }, idx);
2738
2748
  }
2739
- var child = rectProps.children && /* @__PURE__ */ React23__default.isValidElement(rectProps.children) ? /* @__PURE__ */ React23__default.cloneElement(rectProps.children, {
2749
+ var child = rectProps.children && /* @__PURE__ */ React27__default.isValidElement(rectProps.children) ? /* @__PURE__ */ React27__default.cloneElement(rectProps.children, {
2740
2750
  color: background,
2741
2751
  checked
2742
2752
  }) : null;
@@ -2750,7 +2760,7 @@ var Swatch = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2750
2760
  background
2751
2761
  })
2752
2762
  }), idx);
2753
- }), addonAfter && /* @__PURE__ */ React23__default.isValidElement(addonAfter) && addonAfter]
2763
+ }), addonAfter && /* @__PURE__ */ React27__default.isValidElement(addonAfter) && addonAfter]
2754
2764
  }));
2755
2765
  });
2756
2766
  Swatch.displayName = "Swatch";
@@ -2769,7 +2779,7 @@ var Bar = (props) => /* @__PURE__ */ jsx("div", {
2769
2779
  backgroundColor: "#fff"
2770
2780
  }
2771
2781
  });
2772
- var Sketch = /* @__PURE__ */ React23__default.forwardRef((props, ref) => {
2782
+ var Sketch = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
2773
2783
  var {
2774
2784
  prefixCls = "w-color-sketch",
2775
2785
  className,
@@ -3020,19 +3030,19 @@ var Toolbar = ({
3020
3030
  on_attachments_change,
3021
3031
  disabled = false
3022
3032
  }) => {
3023
- const [link_url, set_link_url] = React23.useState("https://");
3024
- const [link_popover_open, set_link_popover_open] = React23.useState(false);
3025
- const [text_color_open, set_text_color_open] = React23.useState(false);
3026
- const [highlight_color_open, set_highlight_color_open] = React23.useState(false);
3027
- const [variables_menu_open, set_variables_menu_open] = React23.useState(false);
3028
- const [table_menu_open, set_table_menu_open] = React23.useState(false);
3029
- const [text_color, set_text_color] = React23.useState("#000000");
3030
- const [highlight_color, set_highlight_color] = React23.useState("#ffff00");
3031
- const [table_rows, set_table_rows] = React23.useState(3);
3032
- const [table_cols, set_table_cols] = React23.useState(3);
3033
- const [hovered_cell, set_hovered_cell] = React23.useState(null);
3034
- const file_input_ref = React23.useRef(null);
3035
- const image_input_ref = React23.useRef(null);
3033
+ const [link_url, set_link_url] = React27.useState("https://");
3034
+ const [link_popover_open, set_link_popover_open] = React27.useState(false);
3035
+ const [text_color_open, set_text_color_open] = React27.useState(false);
3036
+ const [highlight_color_open, set_highlight_color_open] = React27.useState(false);
3037
+ const [variables_menu_open, set_variables_menu_open] = React27.useState(false);
3038
+ const [table_menu_open, set_table_menu_open] = React27.useState(false);
3039
+ const [text_color, set_text_color] = React27.useState("#000000");
3040
+ const [highlight_color, set_highlight_color] = React27.useState("#ffff00");
3041
+ const [table_rows, set_table_rows] = React27.useState(3);
3042
+ const [table_cols, set_table_cols] = React27.useState(3);
3043
+ const [hovered_cell, set_hovered_cell] = React27.useState(null);
3044
+ const file_input_ref = React27.useRef(null);
3045
+ const image_input_ref = React27.useRef(null);
3036
3046
  if (!editor) {
3037
3047
  return null;
3038
3048
  }
@@ -3965,7 +3975,7 @@ var VariableExtension = Node.create({
3965
3975
  }
3966
3976
  });
3967
3977
  var Tabs = TabsPrimitive.Root;
3968
- var TabsList = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3978
+ var TabsList = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3969
3979
  TabsPrimitive.List,
3970
3980
  {
3971
3981
  ref,
@@ -3977,7 +3987,7 @@ var TabsList = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__
3977
3987
  }
3978
3988
  ));
3979
3989
  TabsList.displayName = TabsPrimitive.List.displayName;
3980
- var TabsTrigger = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3990
+ var TabsTrigger = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3981
3991
  TabsPrimitive.Trigger,
3982
3992
  {
3983
3993
  ref,
@@ -3989,7 +3999,7 @@ var TabsTrigger = React23.forwardRef(({ className, ...props }, ref) => /* @__PUR
3989
3999
  }
3990
4000
  ));
3991
4001
  TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
3992
- var TabsContent = React23.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4002
+ var TabsContent = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3993
4003
  TabsPrimitive.Content,
3994
4004
  {
3995
4005
  ref,
@@ -4024,14 +4034,14 @@ var HazoUiRte = ({
4024
4034
  className,
4025
4035
  show_output_viewer = false
4026
4036
  }) => {
4027
- const [attachments, set_attachments] = React23.useState(
4037
+ const [attachments, set_attachments] = React27.useState(
4028
4038
  initial_attachments
4029
4039
  );
4030
- const [active_tab, set_active_tab] = React23.useState("html");
4040
+ const [active_tab, set_active_tab] = React27.useState("html");
4031
4041
  const is_view_only = active_tab !== "html";
4032
- const attachments_ref = React23.useRef(attachments);
4042
+ const attachments_ref = React27.useRef(attachments);
4033
4043
  attachments_ref.current = attachments;
4034
- const debounced_on_change = React23.useMemo(
4044
+ const debounced_on_change = React27.useMemo(
4035
4045
  () => debounce_fn((output) => {
4036
4046
  if (on_change) {
4037
4047
  on_change(output);
@@ -4130,7 +4140,7 @@ var HazoUiRte = ({
4130
4140
  debounced_on_change(output);
4131
4141
  }
4132
4142
  });
4133
- React23.useEffect(() => {
4143
+ React27.useEffect(() => {
4134
4144
  if (editor && html !== void 0) {
4135
4145
  const current_html = editor.getHTML();
4136
4146
  if (html !== current_html && !editor.isFocused) {
@@ -4138,21 +4148,21 @@ var HazoUiRte = ({
4138
4148
  }
4139
4149
  }
4140
4150
  }, [html, editor]);
4141
- React23.useEffect(() => {
4151
+ React27.useEffect(() => {
4142
4152
  if (editor) {
4143
4153
  editor.setEditable(!disabled);
4144
4154
  }
4145
4155
  }, [disabled, editor]);
4146
- const attachments_from_props_ref = React23.useRef(false);
4147
- const prev_initial_attachments_ref = React23.useRef(initial_attachments);
4148
- React23.useEffect(() => {
4156
+ const attachments_from_props_ref = React27.useRef(false);
4157
+ const prev_initial_attachments_ref = React27.useRef(initial_attachments);
4158
+ React27.useEffect(() => {
4149
4159
  if (JSON.stringify(initial_attachments) !== JSON.stringify(prev_initial_attachments_ref.current)) {
4150
4160
  prev_initial_attachments_ref.current = initial_attachments;
4151
4161
  attachments_from_props_ref.current = true;
4152
4162
  set_attachments(initial_attachments);
4153
4163
  }
4154
4164
  }, [initial_attachments]);
4155
- React23.useEffect(() => {
4165
+ React27.useEffect(() => {
4156
4166
  if (attachments_from_props_ref.current) {
4157
4167
  attachments_from_props_ref.current = false;
4158
4168
  return;
@@ -4246,7 +4256,1594 @@ var HazoUiRte = ({
4246
4256
  );
4247
4257
  };
4248
4258
  HazoUiRte.displayName = "HazoUiRte";
4259
+ var generate_command_id = () => {
4260
+ return `cmd_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
4261
+ };
4262
+ var get_variant_classes = (variant = "default") => {
4263
+ switch (variant) {
4264
+ case "outline":
4265
+ return "bg-transparent border-primary/40 text-primary";
4266
+ case "subtle":
4267
+ return "bg-muted border-transparent text-muted-foreground";
4268
+ case "default":
4269
+ default:
4270
+ return "bg-primary/10 text-primary border-primary/20";
4271
+ }
4272
+ };
4273
+ var CommandPillView = ({ node, selected, editor }) => {
4274
+ const { prefix, action, action_label, id, variant } = node.attrs;
4275
+ const handle_click = () => {
4276
+ const event = new CustomEvent("command-pill-click", {
4277
+ detail: {
4278
+ id,
4279
+ prefix,
4280
+ action,
4281
+ action_label,
4282
+ node_pos: editor.state.selection.from - 1
4283
+ },
4284
+ bubbles: true
4285
+ });
4286
+ document.dispatchEvent(event);
4287
+ };
4288
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { as: "span", className: "inline", children: /* @__PURE__ */ jsxs(
4289
+ "span",
4290
+ {
4291
+ className: cn(
4292
+ "cls_command_pill",
4293
+ "inline-flex items-center",
4294
+ "px-1.5 py-0.5 mx-0.5",
4295
+ "rounded-md",
4296
+ "text-sm font-medium",
4297
+ "border",
4298
+ "cursor-pointer select-none",
4299
+ "transition-all duration-150",
4300
+ get_variant_classes(variant),
4301
+ selected && "ring-2 ring-ring ring-offset-1",
4302
+ "hover:opacity-80"
4303
+ ),
4304
+ contentEditable: false,
4305
+ "data-command-id": id,
4306
+ "data-command-prefix": prefix,
4307
+ "data-command-action": action,
4308
+ onClick: handle_click,
4309
+ children: [
4310
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground opacity-70", children: prefix }),
4311
+ /* @__PURE__ */ jsx("span", { children: action_label })
4312
+ ]
4313
+ }
4314
+ ) });
4315
+ };
4316
+ var CommandNodeExtension = Node.create({
4317
+ name: "commandNode",
4318
+ group: "inline",
4319
+ inline: true,
4320
+ // Atomic means the node cannot be split or merged
4321
+ atom: true,
4322
+ // Draggable in the editor
4323
+ draggable: true,
4324
+ // Selectable as a whole unit
4325
+ selectable: true,
4326
+ addAttributes() {
4327
+ return {
4328
+ id: {
4329
+ default: null,
4330
+ parseHTML: (element) => element.getAttribute("data-command-id"),
4331
+ renderHTML: (attributes) => ({
4332
+ "data-command-id": attributes.id
4333
+ })
4334
+ },
4335
+ prefix: {
4336
+ default: "",
4337
+ parseHTML: (element) => element.getAttribute("data-command-prefix"),
4338
+ renderHTML: (attributes) => ({
4339
+ "data-command-prefix": attributes.prefix
4340
+ })
4341
+ },
4342
+ action: {
4343
+ default: "",
4344
+ parseHTML: (element) => element.getAttribute("data-command-action"),
4345
+ renderHTML: (attributes) => ({
4346
+ "data-command-action": attributes.action
4347
+ })
4348
+ },
4349
+ action_label: {
4350
+ default: "",
4351
+ parseHTML: (element) => element.getAttribute("data-command-label"),
4352
+ renderHTML: (attributes) => ({
4353
+ "data-command-label": attributes.action_label
4354
+ })
4355
+ },
4356
+ variant: {
4357
+ default: "default",
4358
+ parseHTML: (element) => element.getAttribute("data-command-variant") || "default",
4359
+ renderHTML: (attributes) => ({
4360
+ "data-command-variant": attributes.variant
4361
+ })
4362
+ }
4363
+ };
4364
+ },
4365
+ parseHTML() {
4366
+ return [
4367
+ {
4368
+ tag: "span[data-command-id]"
4369
+ }
4370
+ ];
4371
+ },
4372
+ renderHTML({ HTMLAttributes }) {
4373
+ return [
4374
+ "span",
4375
+ mergeAttributes(HTMLAttributes, {
4376
+ class: "cls_command_pill",
4377
+ contenteditable: "false"
4378
+ }),
4379
+ `${HTMLAttributes["data-command-prefix"]}${HTMLAttributes["data-command-label"]}`
4380
+ ];
4381
+ },
4382
+ // Output format: prefix + action (e.g., "@user_123", "/due_date")
4383
+ renderText({ node }) {
4384
+ return `${node.attrs.prefix}${node.attrs.action}`;
4385
+ },
4386
+ addNodeView() {
4387
+ return ReactNodeViewRenderer(CommandPillView);
4388
+ },
4389
+ addCommands() {
4390
+ return {
4391
+ insertCommand: (attrs) => ({ commands }) => {
4392
+ return commands.insertContent({
4393
+ type: this.name,
4394
+ attrs: {
4395
+ ...attrs,
4396
+ id: generate_command_id()
4397
+ }
4398
+ });
4399
+ },
4400
+ updateCommand: (id, attrs) => ({ tr, state }) => {
4401
+ let updated = false;
4402
+ state.doc.descendants((node, pos) => {
4403
+ if (node.type.name === this.name && node.attrs.id === id) {
4404
+ tr.setNodeMarkup(pos, void 0, {
4405
+ ...node.attrs,
4406
+ ...attrs
4407
+ });
4408
+ updated = true;
4409
+ return false;
4410
+ }
4411
+ });
4412
+ return updated;
4413
+ }
4414
+ };
4415
+ },
4416
+ // Keyboard behavior - delete entire node on backspace
4417
+ addKeyboardShortcuts() {
4418
+ return {
4419
+ Backspace: () => this.editor.commands.command(({ tr, state }) => {
4420
+ let is_command = false;
4421
+ const { selection } = state;
4422
+ const { empty, anchor } = selection;
4423
+ if (!empty) {
4424
+ return false;
4425
+ }
4426
+ state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
4427
+ if (node.type.name === this.name) {
4428
+ is_command = true;
4429
+ tr.insertText("", pos, pos + node.nodeSize);
4430
+ return false;
4431
+ }
4432
+ });
4433
+ return is_command;
4434
+ })
4435
+ };
4436
+ }
4437
+ });
4438
+ var create_suggestion_config = (prefix_config, on_suggestion_change, on_insert_command) => {
4439
+ return {
4440
+ char: prefix_config.char,
4441
+ allowSpaces: false,
4442
+ startOfLine: false,
4443
+ items: ({ query }) => {
4444
+ if (!query) return prefix_config.commands;
4445
+ const lower_query = query.toLowerCase();
4446
+ return prefix_config.commands.filter(
4447
+ (cmd) => cmd.action_label.toLowerCase().includes(lower_query) || cmd.action.toLowerCase().includes(lower_query) || cmd.action_description?.toLowerCase().includes(lower_query)
4448
+ );
4449
+ },
4450
+ render: () => {
4451
+ return {
4452
+ onStart: (props) => {
4453
+ on_suggestion_change({
4454
+ is_active: true,
4455
+ query: props.query,
4456
+ prefix: prefix_config.char,
4457
+ client_rect: props.clientRect,
4458
+ commands: prefix_config.commands,
4459
+ range: props.range
4460
+ });
4461
+ },
4462
+ onUpdate: (props) => {
4463
+ on_suggestion_change({
4464
+ is_active: true,
4465
+ query: props.query,
4466
+ prefix: prefix_config.char,
4467
+ client_rect: props.clientRect,
4468
+ commands: prefix_config.commands,
4469
+ range: props.range
4470
+ });
4471
+ },
4472
+ onKeyDown: (props) => {
4473
+ if (props.event.key === "Escape") {
4474
+ on_suggestion_change(null);
4475
+ return true;
4476
+ }
4477
+ if (props.event.key === "ArrowUp" || props.event.key === "ArrowDown" || props.event.key === "Enter") {
4478
+ return true;
4479
+ }
4480
+ return false;
4481
+ },
4482
+ onExit: () => {
4483
+ on_suggestion_change(null);
4484
+ }
4485
+ };
4486
+ },
4487
+ command: ({ range, props }) => {
4488
+ const command = props;
4489
+ on_insert_command(command, prefix_config.char, range);
4490
+ }
4491
+ };
4492
+ };
4493
+ var create_command_suggestion_extension = (config) => {
4494
+ const { prefixes, on_suggestion_change, on_insert_command } = config;
4495
+ return prefixes.map((prefix_config, index) => {
4496
+ return Extension.create({
4497
+ name: `commandSuggestion_${prefix_config.char}_${index}`,
4498
+ addProseMirrorPlugins() {
4499
+ return [
4500
+ Suggestion({
4501
+ editor: this.editor,
4502
+ ...create_suggestion_config(
4503
+ prefix_config,
4504
+ on_suggestion_change,
4505
+ on_insert_command
4506
+ )
4507
+ })
4508
+ ];
4509
+ }
4510
+ });
4511
+ });
4512
+ };
4513
+ var insert_command_at_position = (editor, command, prefix, range, variant = "default") => {
4514
+ editor.chain().focus().deleteRange(range).insertCommand({
4515
+ prefix,
4516
+ action: command.action,
4517
+ action_label: command.action_label,
4518
+ variant
4519
+ }).run();
4520
+ };
4521
+ var get_variant_classes2 = (variant = "default") => {
4522
+ switch (variant) {
4523
+ case "outline":
4524
+ return "bg-transparent border-primary/40 text-primary hover:bg-primary/5";
4525
+ case "subtle":
4526
+ return "bg-muted border-transparent text-muted-foreground hover:bg-muted/80";
4527
+ case "default":
4528
+ default:
4529
+ return "bg-primary/10 text-primary border-primary/20 hover:bg-primary/15";
4530
+ }
4531
+ };
4532
+ var CommandPill = ({
4533
+ prefix,
4534
+ action,
4535
+ action_label,
4536
+ id,
4537
+ selected = false,
4538
+ variant = "default",
4539
+ on_click
4540
+ }) => {
4541
+ return /* @__PURE__ */ jsxs(
4542
+ "span",
4543
+ {
4544
+ className: cn(
4545
+ "cls_command_pill_standalone",
4546
+ "inline-flex items-center",
4547
+ "px-1.5 py-0.5",
4548
+ "rounded-md",
4549
+ "text-sm font-medium",
4550
+ "border",
4551
+ "transition-all duration-150",
4552
+ get_variant_classes2(variant),
4553
+ selected && "ring-2 ring-ring ring-offset-1",
4554
+ on_click && "cursor-pointer"
4555
+ ),
4556
+ "data-command-id": id,
4557
+ "data-command-prefix": prefix,
4558
+ "data-command-action": action,
4559
+ onClick: on_click,
4560
+ role: on_click ? "button" : void 0,
4561
+ tabIndex: on_click ? 0 : void 0,
4562
+ onKeyDown: (e) => {
4563
+ if (on_click && (e.key === "Enter" || e.key === " ")) {
4564
+ e.preventDefault();
4565
+ on_click();
4566
+ }
4567
+ },
4568
+ children: [
4569
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground opacity-70", children: prefix }),
4570
+ /* @__PURE__ */ jsx("span", { children: action_label })
4571
+ ]
4572
+ }
4573
+ );
4574
+ };
4575
+ CommandPill.displayName = "CommandPill";
4576
+ var group_commands = (commands) => {
4577
+ const groups = /* @__PURE__ */ new Map();
4578
+ for (const cmd of commands) {
4579
+ const group_name = cmd.group || "";
4580
+ if (!groups.has(group_name)) {
4581
+ groups.set(group_name, []);
4582
+ }
4583
+ groups.get(group_name).push(cmd);
4584
+ }
4585
+ return groups;
4586
+ };
4587
+ var CommandPopover = ({
4588
+ is_open,
4589
+ commands,
4590
+ prefix,
4591
+ query,
4592
+ selected_index,
4593
+ position,
4594
+ on_select,
4595
+ on_close,
4596
+ on_selection_change: _on_selection_change
4597
+ }) => {
4598
+ const container_ref = React27.useRef(null);
4599
+ const grouped_commands = React27.useMemo(
4600
+ () => group_commands(commands),
4601
+ [commands]
4602
+ );
4603
+ React27.useEffect(() => {
4604
+ const handle_click_outside = (e) => {
4605
+ if (container_ref.current && !container_ref.current.contains(e.target)) {
4606
+ on_close();
4607
+ }
4608
+ };
4609
+ if (is_open) {
4610
+ document.addEventListener("mousedown", handle_click_outside);
4611
+ return () => {
4612
+ document.removeEventListener("mousedown", handle_click_outside);
4613
+ };
4614
+ }
4615
+ }, [is_open, on_close]);
4616
+ const [mounted, set_mounted] = React27.useState(false);
4617
+ React27.useEffect(() => {
4618
+ set_mounted(true);
4619
+ }, []);
4620
+ if (!is_open || !mounted) return null;
4621
+ const popover_content = /* @__PURE__ */ jsx(
4622
+ "div",
4623
+ {
4624
+ ref: container_ref,
4625
+ className: cn(
4626
+ "cls_command_popover",
4627
+ "fixed z-[9999]",
4628
+ "w-64 min-w-[200px] max-w-[300px]",
4629
+ "rounded-md border bg-popover text-popover-foreground shadow-lg",
4630
+ "animate-in fade-in-0 zoom-in-95"
4631
+ ),
4632
+ style: {
4633
+ top: position.top,
4634
+ left: position.left
4635
+ },
4636
+ children: /* @__PURE__ */ jsxs(Command, { className: "rounded-md", children: [
4637
+ query && /* @__PURE__ */ jsxs("div", { className: "px-3 py-2 text-xs text-muted-foreground border-b", children: [
4638
+ "Searching: ",
4639
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
4640
+ prefix,
4641
+ query
4642
+ ] })
4643
+ ] }),
4644
+ /* @__PURE__ */ jsxs(CommandList, { className: "max-h-[200px]", children: [
4645
+ commands.length === 0 && /* @__PURE__ */ jsx(CommandEmpty, { children: "No commands found." }),
4646
+ Array.from(grouped_commands.entries()).map(([group_name, group_commands2]) => /* @__PURE__ */ jsx(
4647
+ CommandGroup,
4648
+ {
4649
+ heading: group_name || void 0,
4650
+ children: group_commands2.map((cmd, idx) => {
4651
+ let flat_idx = 0;
4652
+ for (const [g, cmds] of grouped_commands.entries()) {
4653
+ if (g === group_name) {
4654
+ flat_idx += idx;
4655
+ break;
4656
+ }
4657
+ flat_idx += cmds.length;
4658
+ }
4659
+ return /* @__PURE__ */ jsx(
4660
+ CommandItem,
4661
+ {
4662
+ value: cmd.action,
4663
+ onSelect: () => on_select(cmd),
4664
+ className: cn(
4665
+ flat_idx === selected_index && "bg-accent"
4666
+ ),
4667
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 w-full", children: [
4668
+ cmd.icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-muted-foreground", children: cmd.icon }),
4669
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
4670
+ /* @__PURE__ */ jsxs("div", { className: "font-medium truncate", children: [
4671
+ prefix,
4672
+ cmd.action_label
4673
+ ] }),
4674
+ cmd.action_description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground truncate", children: cmd.action_description })
4675
+ ] })
4676
+ ] })
4677
+ },
4678
+ cmd.action
4679
+ );
4680
+ })
4681
+ },
4682
+ group_name || "default"
4683
+ ))
4684
+ ] })
4685
+ ] })
4686
+ }
4687
+ );
4688
+ return createPortal(popover_content, document.body);
4689
+ };
4690
+ CommandPopover.displayName = "CommandPopover";
4691
+
4692
+ // src/components/hazo_ui_command/index.tsx
4693
+ var parse_commands_from_text = (text, prefixes) => {
4694
+ const result = [];
4695
+ const action_to_label = /* @__PURE__ */ new Map();
4696
+ for (const prefix_config of prefixes) {
4697
+ for (const cmd of prefix_config.commands) {
4698
+ action_to_label.set(`${prefix_config.char}${cmd.action}`, {
4699
+ label: cmd.action_label,
4700
+ prefix: prefix_config.char
4701
+ });
4702
+ }
4703
+ }
4704
+ const prefix_chars = prefixes.map((p) => escape_regex(p.char)).join("|");
4705
+ const pattern = new RegExp(`(${prefix_chars})(\\w+)`, "g");
4706
+ let match;
4707
+ while ((match = pattern.exec(text)) !== null) {
4708
+ const full_match = match[0];
4709
+ const prefix = match[1];
4710
+ const action = match[2];
4711
+ const lookup_key = `${prefix}${action}`;
4712
+ const info = action_to_label.get(lookup_key);
4713
+ if (info) {
4714
+ result.push({
4715
+ action,
4716
+ action_label: info.label,
4717
+ prefix,
4718
+ position: match.index,
4719
+ length: full_match.length
4720
+ });
4721
+ }
4722
+ }
4723
+ return result;
4724
+ };
4725
+ var escape_regex = (str) => {
4726
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4727
+ };
4728
+ var text_to_tiptap_content = (text, prefixes, variant = "default") => {
4729
+ const commands = parse_commands_from_text(text, prefixes);
4730
+ if (commands.length === 0) {
4731
+ return {
4732
+ type: "doc",
4733
+ content: [
4734
+ {
4735
+ type: "paragraph",
4736
+ content: text ? [{ type: "text", text }] : []
4737
+ }
4738
+ ]
4739
+ };
4740
+ }
4741
+ commands.sort((a, b) => a.position - b.position);
4742
+ const content = [];
4743
+ let last_end = 0;
4744
+ for (const cmd of commands) {
4745
+ if (cmd.position > last_end) {
4746
+ content.push({
4747
+ type: "text",
4748
+ text: text.slice(last_end, cmd.position)
4749
+ });
4750
+ }
4751
+ content.push({
4752
+ type: "commandNode",
4753
+ attrs: {
4754
+ id: `cmd_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
4755
+ prefix: cmd.prefix,
4756
+ action: cmd.action,
4757
+ action_label: cmd.action_label,
4758
+ variant
4759
+ }
4760
+ });
4761
+ last_end = cmd.position + cmd.length;
4762
+ }
4763
+ if (last_end < text.length) {
4764
+ content.push({
4765
+ type: "text",
4766
+ text: text.slice(last_end)
4767
+ });
4768
+ }
4769
+ return {
4770
+ type: "doc",
4771
+ content: [
4772
+ {
4773
+ type: "paragraph",
4774
+ content
4775
+ }
4776
+ ]
4777
+ };
4778
+ };
4779
+ var Document = Node.create({
4780
+ name: "doc",
4781
+ topNode: true,
4782
+ content: "block+",
4783
+ renderMarkdown: (node, h) => {
4784
+ if (!node.content) {
4785
+ return "";
4786
+ }
4787
+ return h.renderChildren(node.content, "\n\n");
4788
+ }
4789
+ });
4790
+ var index_default = Document;
4791
+ var Paragraph = Node.create({
4792
+ name: "paragraph",
4793
+ priority: 1e3,
4794
+ addOptions() {
4795
+ return {
4796
+ HTMLAttributes: {}
4797
+ };
4798
+ },
4799
+ group: "block",
4800
+ content: "inline*",
4801
+ parseHTML() {
4802
+ return [{ tag: "p" }];
4803
+ },
4804
+ renderHTML({ HTMLAttributes }) {
4805
+ return ["p", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
4806
+ },
4807
+ parseMarkdown: (token, helpers) => {
4808
+ const tokens = token.tokens || [];
4809
+ if (tokens.length === 1 && tokens[0].type === "image") {
4810
+ return helpers.parseChildren([tokens[0]]);
4811
+ }
4812
+ return helpers.createNode(
4813
+ "paragraph",
4814
+ void 0,
4815
+ // no attributes for paragraph
4816
+ helpers.parseInline(tokens)
4817
+ );
4818
+ },
4819
+ renderMarkdown: (node, h) => {
4820
+ if (!node || !Array.isArray(node.content)) {
4821
+ return "";
4822
+ }
4823
+ return h.renderChildren(node.content);
4824
+ },
4825
+ addCommands() {
4826
+ return {
4827
+ setParagraph: () => ({ commands }) => {
4828
+ return commands.setNode(this.name);
4829
+ }
4830
+ };
4831
+ },
4832
+ addKeyboardShortcuts() {
4833
+ return {
4834
+ "Mod-Alt-0": () => this.editor.commands.setParagraph()
4835
+ };
4836
+ }
4837
+ });
4838
+ var index_default2 = Paragraph;
4839
+ var Text = Node.create({
4840
+ name: "text",
4841
+ group: "inline",
4842
+ parseMarkdown: (token) => {
4843
+ return {
4844
+ type: "text",
4845
+ text: token.text || ""
4846
+ };
4847
+ },
4848
+ renderMarkdown: (node) => node.text || ""
4849
+ });
4850
+ var index_default3 = Text;
4851
+ var SingleLineDocument = index_default.extend({
4852
+ content: "paragraph"
4853
+ });
4854
+ var get_editor_output = (editor) => {
4855
+ if (!editor) {
4856
+ return { plain_text: "", display_text: "", commands: [] };
4857
+ }
4858
+ const plain_text = editor.getText();
4859
+ const commands = [];
4860
+ let display_text = "";
4861
+ let position = 0;
4862
+ editor.state.doc.descendants((node, _pos) => {
4863
+ if (node.type.name === "text") {
4864
+ display_text += node.text || "";
4865
+ position += (node.text || "").length;
4866
+ } else if (node.type.name === "commandNode") {
4867
+ const { id, prefix, action, action_label } = node.attrs;
4868
+ const cmd_plain_text = `${prefix}${action}`;
4869
+ const cmd_display_text = `${prefix}${action_label}`;
4870
+ commands.push({
4871
+ id,
4872
+ prefix,
4873
+ action,
4874
+ action_label,
4875
+ position,
4876
+ length: cmd_plain_text.length
4877
+ });
4878
+ display_text += cmd_display_text;
4879
+ position += cmd_plain_text.length;
4880
+ }
4881
+ });
4882
+ return { plain_text, display_text, commands };
4883
+ };
4884
+ var HazoUiTextbox = ({
4885
+ value,
4886
+ default_value,
4887
+ prefixes,
4888
+ placeholder = "Type here...",
4889
+ disabled = false,
4890
+ className,
4891
+ pill_variant = "default",
4892
+ on_change,
4893
+ on_submit,
4894
+ on_command_insert,
4895
+ on_command_change,
4896
+ on_command_remove
4897
+ }) => {
4898
+ const [suggestion_state, set_suggestion_state] = React27.useState(null);
4899
+ const [selected_index, set_selected_index] = React27.useState(0);
4900
+ const [popover_position, set_popover_position] = React27.useState({ top: 0, left: 0 });
4901
+ const [edit_context, set_edit_context] = React27.useState(null);
4902
+ const [edit_selected_index, set_edit_selected_index] = React27.useState(0);
4903
+ const is_controlled = value !== void 0;
4904
+ const editor_container_ref = React27.useRef(null);
4905
+ const edit_popover_ref = React27.useRef(null);
4906
+ const [mounted, set_mounted] = React27.useState(false);
4907
+ React27.useEffect(() => {
4908
+ set_mounted(true);
4909
+ }, []);
4910
+ const suggestion_extensions = React27.useMemo(() => {
4911
+ return create_command_suggestion_extension({
4912
+ prefixes,
4913
+ on_suggestion_change: (state) => {
4914
+ set_suggestion_state(state);
4915
+ set_selected_index(0);
4916
+ },
4917
+ on_insert_command: (_command, _prefix, _range) => {
4918
+ }
4919
+ });
4920
+ }, [prefixes]);
4921
+ const editor = useEditor({
4922
+ extensions: [
4923
+ SingleLineDocument,
4924
+ index_default2,
4925
+ index_default3,
4926
+ Placeholder.configure({
4927
+ placeholder
4928
+ }),
4929
+ CommandNodeExtension.configure({}),
4930
+ ...suggestion_extensions
4931
+ ],
4932
+ content: is_controlled ? text_to_tiptap_content(value || "", prefixes, pill_variant) : text_to_tiptap_content(default_value || "", prefixes, pill_variant),
4933
+ editable: !disabled,
4934
+ immediatelyRender: false,
4935
+ editorProps: {
4936
+ attributes: {
4937
+ class: cn(
4938
+ "cls_textbox_editor",
4939
+ "w-full outline-none",
4940
+ "whitespace-nowrap overflow-x-auto"
4941
+ )
4942
+ },
4943
+ handleKeyDown: (_view, event) => {
4944
+ if (event.key === "Enter" && !suggestion_state?.is_active) {
4945
+ event.preventDefault();
4946
+ if (on_submit && editor) {
4947
+ on_submit(get_editor_output(editor));
4948
+ }
4949
+ return true;
4950
+ }
4951
+ return false;
4952
+ }
4953
+ },
4954
+ onUpdate: ({ editor: editor2 }) => {
4955
+ if (on_change) {
4956
+ on_change(get_editor_output(editor2));
4957
+ }
4958
+ }
4959
+ });
4960
+ React27.useEffect(() => {
4961
+ if (suggestion_state?.is_active && editor) {
4962
+ requestAnimationFrame(() => {
4963
+ const { from } = suggestion_state.range;
4964
+ try {
4965
+ const coords = editor.view.coordsAtPos(from);
4966
+ if (coords) {
4967
+ set_popover_position({
4968
+ top: coords.bottom + 4,
4969
+ left: coords.left
4970
+ });
4971
+ }
4972
+ } catch {
4973
+ const rect = suggestion_state.client_rect?.();
4974
+ if (rect) {
4975
+ set_popover_position({
4976
+ top: rect.bottom + 4,
4977
+ left: rect.left
4978
+ });
4979
+ }
4980
+ }
4981
+ });
4982
+ }
4983
+ }, [suggestion_state, editor]);
4984
+ React27.useEffect(() => {
4985
+ if (is_controlled && editor && !editor.isFocused) {
4986
+ const current_text = editor.getText();
4987
+ if (value !== current_text) {
4988
+ const content = text_to_tiptap_content(value || "", prefixes, pill_variant);
4989
+ editor.commands.setContent(content, { emitUpdate: false });
4990
+ }
4991
+ }
4992
+ }, [value, editor, is_controlled, prefixes, pill_variant]);
4993
+ React27.useEffect(() => {
4994
+ if (editor) {
4995
+ editor.setEditable(!disabled);
4996
+ }
4997
+ }, [disabled, editor]);
4998
+ const handle_command_select = React27.useCallback(
4999
+ (command) => {
5000
+ if (!editor || !suggestion_state) return;
5001
+ insert_command_at_position(
5002
+ editor,
5003
+ command,
5004
+ suggestion_state.prefix,
5005
+ suggestion_state.range,
5006
+ pill_variant
5007
+ );
5008
+ if (on_command_insert) {
5009
+ on_command_insert(command, suggestion_state.prefix);
5010
+ }
5011
+ set_suggestion_state(null);
5012
+ },
5013
+ [editor, suggestion_state, pill_variant, on_command_insert]
5014
+ );
5015
+ const handle_popover_close = React27.useCallback(() => {
5016
+ set_suggestion_state(null);
5017
+ editor?.commands.focus();
5018
+ }, [editor]);
5019
+ const handle_edit_close = React27.useCallback(() => {
5020
+ set_edit_context(null);
5021
+ editor?.commands.focus();
5022
+ }, [editor]);
5023
+ const handle_command_update = React27.useCallback(
5024
+ (new_command) => {
5025
+ if (!editor || !edit_context) return;
5026
+ const old_command = edit_context.command;
5027
+ editor.commands.updateCommand(old_command.id, {
5028
+ action: new_command.action,
5029
+ action_label: new_command.action_label
5030
+ });
5031
+ if (on_command_change) {
5032
+ on_command_change(old_command, new_command);
5033
+ }
5034
+ set_edit_context(null);
5035
+ editor.commands.focus();
5036
+ },
5037
+ [editor, edit_context, on_command_change]
5038
+ );
5039
+ const handle_command_remove = React27.useCallback(() => {
5040
+ if (!editor || !edit_context) return;
5041
+ const command = edit_context.command;
5042
+ editor.state.doc.descendants((node, pos) => {
5043
+ if (node.type.name === "commandNode" && node.attrs.id === command.id) {
5044
+ editor.chain().focus().deleteRange({ from: pos, to: pos + node.nodeSize }).run();
5045
+ return false;
5046
+ }
5047
+ });
5048
+ if (on_command_remove) {
5049
+ on_command_remove(command);
5050
+ }
5051
+ set_edit_context(null);
5052
+ }, [editor, edit_context, on_command_remove]);
5053
+ const filtered_commands = React27.useMemo(() => {
5054
+ if (!suggestion_state) return [];
5055
+ const query = suggestion_state.query.toLowerCase();
5056
+ if (!query) return suggestion_state.commands;
5057
+ return suggestion_state.commands.filter(
5058
+ (cmd) => cmd.action_label.toLowerCase().includes(query) || cmd.action.toLowerCase().includes(query) || cmd.action_description?.toLowerCase().includes(query)
5059
+ );
5060
+ }, [suggestion_state]);
5061
+ React27.useEffect(() => {
5062
+ if (!suggestion_state?.is_active) return;
5063
+ const handle_keydown = (e) => {
5064
+ switch (e.key) {
5065
+ case "ArrowDown":
5066
+ e.preventDefault();
5067
+ set_selected_index(
5068
+ (prev) => Math.min(prev + 1, filtered_commands.length - 1)
5069
+ );
5070
+ break;
5071
+ case "ArrowUp":
5072
+ e.preventDefault();
5073
+ set_selected_index((prev) => Math.max(prev - 1, 0));
5074
+ break;
5075
+ case "Enter":
5076
+ e.preventDefault();
5077
+ if (filtered_commands[selected_index]) {
5078
+ handle_command_select(filtered_commands[selected_index]);
5079
+ }
5080
+ break;
5081
+ case "Escape":
5082
+ e.preventDefault();
5083
+ handle_popover_close();
5084
+ break;
5085
+ }
5086
+ };
5087
+ window.addEventListener("keydown", handle_keydown);
5088
+ return () => window.removeEventListener("keydown", handle_keydown);
5089
+ }, [
5090
+ suggestion_state?.is_active,
5091
+ filtered_commands,
5092
+ selected_index,
5093
+ handle_command_select,
5094
+ handle_popover_close
5095
+ ]);
5096
+ React27.useEffect(() => {
5097
+ if (!edit_context) return;
5098
+ const handle_click_outside = (e) => {
5099
+ if (edit_popover_ref.current && !edit_popover_ref.current.contains(e.target)) {
5100
+ set_edit_context(null);
5101
+ }
5102
+ };
5103
+ const timeout = setTimeout(() => {
5104
+ document.addEventListener("mousedown", handle_click_outside);
5105
+ }, 100);
5106
+ return () => {
5107
+ clearTimeout(timeout);
5108
+ document.removeEventListener("mousedown", handle_click_outside);
5109
+ };
5110
+ }, [edit_context]);
5111
+ const edit_commands = React27.useMemo(() => {
5112
+ if (!edit_context) return [];
5113
+ const prefix_config = prefixes.find((p) => p.char === edit_context.command.prefix);
5114
+ return prefix_config?.commands || [];
5115
+ }, [edit_context, prefixes]);
5116
+ React27.useEffect(() => {
5117
+ if (!edit_context) return;
5118
+ const handle_keydown = (e) => {
5119
+ switch (e.key) {
5120
+ case "ArrowDown":
5121
+ e.preventDefault();
5122
+ set_edit_selected_index(
5123
+ (prev) => Math.min(prev + 1, edit_commands.length)
5124
+ );
5125
+ break;
5126
+ case "ArrowUp":
5127
+ e.preventDefault();
5128
+ set_edit_selected_index((prev) => Math.max(prev - 1, 0));
5129
+ break;
5130
+ case "Enter":
5131
+ e.preventDefault();
5132
+ if (edit_selected_index === edit_commands.length) {
5133
+ handle_command_remove();
5134
+ } else if (edit_commands[edit_selected_index]) {
5135
+ handle_command_update(edit_commands[edit_selected_index]);
5136
+ }
5137
+ break;
5138
+ case "Escape":
5139
+ e.preventDefault();
5140
+ handle_edit_close();
5141
+ break;
5142
+ }
5143
+ };
5144
+ window.addEventListener("keydown", handle_keydown);
5145
+ return () => window.removeEventListener("keydown", handle_keydown);
5146
+ }, [
5147
+ edit_context,
5148
+ edit_commands,
5149
+ edit_selected_index,
5150
+ handle_command_update,
5151
+ handle_command_remove,
5152
+ handle_edit_close
5153
+ ]);
5154
+ React27.useEffect(() => {
5155
+ const handle_pill_click = (e) => {
5156
+ const detail = e.detail;
5157
+ const { id, prefix, action, action_label, node_pos } = detail;
5158
+ if (editor) {
5159
+ try {
5160
+ const coords = editor.view.coordsAtPos(node_pos);
5161
+ if (coords) {
5162
+ const prefix_config = prefixes.find((p) => p.char === prefix);
5163
+ const current_index = prefix_config?.commands.findIndex(
5164
+ (cmd) => cmd.action === action
5165
+ ) ?? 0;
5166
+ set_edit_context({
5167
+ command: {
5168
+ id,
5169
+ prefix,
5170
+ action,
5171
+ action_label,
5172
+ position: node_pos,
5173
+ length: 0
5174
+ },
5175
+ node_pos,
5176
+ rect: new DOMRect(
5177
+ coords.left,
5178
+ coords.bottom + 4,
5179
+ 0,
5180
+ 0
5181
+ )
5182
+ });
5183
+ set_edit_selected_index(Math.max(0, current_index));
5184
+ }
5185
+ } catch {
5186
+ }
5187
+ }
5188
+ };
5189
+ document.addEventListener("command-pill-click", handle_pill_click);
5190
+ return () => document.removeEventListener("command-pill-click", handle_pill_click);
5191
+ }, [editor, prefixes]);
5192
+ return /* @__PURE__ */ jsxs(
5193
+ "div",
5194
+ {
5195
+ ref: editor_container_ref,
5196
+ className: cn(
5197
+ "cls_hazo_ui_textbox",
5198
+ "relative flex h-10 w-full rounded-md border border-input bg-background px-3 py-2",
5199
+ "text-sm ring-offset-background",
5200
+ "focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
5201
+ disabled && "cursor-not-allowed opacity-50",
5202
+ className
5203
+ ),
5204
+ children: [
5205
+ /* @__PURE__ */ jsx(
5206
+ EditorContent,
5207
+ {
5208
+ editor,
5209
+ className: cn(
5210
+ "cls_textbox_content",
5211
+ "flex-1 min-w-0",
5212
+ "[&_.ProseMirror]:outline-none",
5213
+ "[&_.ProseMirror_p]:m-0",
5214
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:content-[attr(data-placeholder)]",
5215
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:text-muted-foreground",
5216
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:pointer-events-none",
5217
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:float-left",
5218
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:h-0"
5219
+ )
5220
+ }
5221
+ ),
5222
+ suggestion_state?.is_active && /* @__PURE__ */ jsx(
5223
+ CommandPopover,
5224
+ {
5225
+ is_open: true,
5226
+ commands: filtered_commands,
5227
+ prefix: suggestion_state.prefix,
5228
+ query: suggestion_state.query,
5229
+ selected_index,
5230
+ position: popover_position,
5231
+ on_query_change: () => {
5232
+ },
5233
+ on_select: handle_command_select,
5234
+ on_close: handle_popover_close,
5235
+ on_selection_change: set_selected_index
5236
+ }
5237
+ ),
5238
+ edit_context && mounted && createPortal(
5239
+ /* @__PURE__ */ jsx(
5240
+ "div",
5241
+ {
5242
+ ref: edit_popover_ref,
5243
+ className: cn(
5244
+ "cls_edit_popover",
5245
+ "fixed z-[9999]",
5246
+ "w-64 min-w-[200px] max-w-[300px]",
5247
+ "rounded-md border bg-popover text-popover-foreground shadow-lg",
5248
+ "animate-in fade-in-0 zoom-in-95"
5249
+ ),
5250
+ style: {
5251
+ top: edit_context.rect.y,
5252
+ left: edit_context.rect.x
5253
+ },
5254
+ children: /* @__PURE__ */ jsxs("div", { className: "py-1", children: [
5255
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs text-muted-foreground border-b", children: "Change command" }),
5256
+ /* @__PURE__ */ jsxs("div", { className: "max-h-[200px] overflow-y-auto", children: [
5257
+ edit_commands.map((cmd, idx) => /* @__PURE__ */ jsxs(
5258
+ "div",
5259
+ {
5260
+ className: cn(
5261
+ "px-3 py-2 cursor-pointer flex items-center gap-2",
5262
+ "hover:bg-accent",
5263
+ idx === edit_selected_index && "bg-accent",
5264
+ cmd.action === edit_context.command.action && "font-medium"
5265
+ ),
5266
+ onClick: () => handle_command_update(cmd),
5267
+ children: [
5268
+ cmd.icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-muted-foreground", children: cmd.icon }),
5269
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
5270
+ /* @__PURE__ */ jsxs("div", { className: "truncate", children: [
5271
+ edit_context.command.prefix,
5272
+ cmd.action_label
5273
+ ] }),
5274
+ cmd.action_description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground truncate", children: cmd.action_description })
5275
+ ] }),
5276
+ cmd.action === edit_context.command.action && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "current" })
5277
+ ]
5278
+ },
5279
+ cmd.action
5280
+ )),
5281
+ /* @__PURE__ */ jsx(
5282
+ "div",
5283
+ {
5284
+ className: cn(
5285
+ "px-3 py-2 cursor-pointer flex items-center gap-2 text-destructive border-t",
5286
+ "hover:bg-destructive/10",
5287
+ edit_selected_index === edit_commands.length && "bg-destructive/10"
5288
+ ),
5289
+ onClick: handle_command_remove,
5290
+ children: /* @__PURE__ */ jsx("span", { children: "Remove" })
5291
+ }
5292
+ )
5293
+ ] })
5294
+ ] })
5295
+ }
5296
+ ),
5297
+ document.body
5298
+ )
5299
+ ]
5300
+ }
5301
+ );
5302
+ };
5303
+ HazoUiTextbox.displayName = "HazoUiTextbox";
5304
+ var HardBreak = Node.create({
5305
+ name: "hardBreak",
5306
+ markdownTokenName: "br",
5307
+ addOptions() {
5308
+ return {
5309
+ keepMarks: true,
5310
+ HTMLAttributes: {}
5311
+ };
5312
+ },
5313
+ inline: true,
5314
+ group: "inline",
5315
+ selectable: false,
5316
+ linebreakReplacement: true,
5317
+ parseHTML() {
5318
+ return [{ tag: "br" }];
5319
+ },
5320
+ renderHTML({ HTMLAttributes }) {
5321
+ return ["br", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
5322
+ },
5323
+ renderText() {
5324
+ return "\n";
5325
+ },
5326
+ renderMarkdown: () => `
5327
+ `,
5328
+ parseMarkdown: () => {
5329
+ return {
5330
+ type: "hardBreak"
5331
+ };
5332
+ },
5333
+ addCommands() {
5334
+ return {
5335
+ setHardBreak: () => ({ commands, chain, state, editor }) => {
5336
+ return commands.first([
5337
+ () => commands.exitCode(),
5338
+ () => commands.command(() => {
5339
+ const { selection, storedMarks } = state;
5340
+ if (selection.$from.parent.type.spec.isolating) {
5341
+ return false;
5342
+ }
5343
+ const { keepMarks } = this.options;
5344
+ const { splittableMarks } = editor.extensionManager;
5345
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
5346
+ return chain().insertContent({ type: this.name }).command(({ tr, dispatch }) => {
5347
+ if (dispatch && marks && keepMarks) {
5348
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
5349
+ tr.ensureMarks(filteredMarks);
5350
+ }
5351
+ return true;
5352
+ }).run();
5353
+ })
5354
+ ]);
5355
+ }
5356
+ };
5357
+ },
5358
+ addKeyboardShortcuts() {
5359
+ return {
5360
+ "Mod-Enter": () => this.editor.commands.setHardBreak(),
5361
+ "Shift-Enter": () => this.editor.commands.setHardBreak()
5362
+ };
5363
+ }
5364
+ });
5365
+ var index_default4 = HardBreak;
5366
+ var get_editor_output2 = (editor) => {
5367
+ if (!editor) {
5368
+ return { plain_text: "", display_text: "", commands: [] };
5369
+ }
5370
+ const plain_text = editor.getText();
5371
+ const commands = [];
5372
+ let display_text = "";
5373
+ let position = 0;
5374
+ editor.state.doc.descendants((node, _pos) => {
5375
+ if (node.type.name === "text") {
5376
+ display_text += node.text || "";
5377
+ position += (node.text || "").length;
5378
+ } else if (node.type.name === "commandNode") {
5379
+ const { id, prefix, action, action_label } = node.attrs;
5380
+ const cmd_plain_text = `${prefix}${action}`;
5381
+ const cmd_display_text = `${prefix}${action_label}`;
5382
+ commands.push({
5383
+ id,
5384
+ prefix,
5385
+ action,
5386
+ action_label,
5387
+ position,
5388
+ length: cmd_plain_text.length
5389
+ });
5390
+ display_text += cmd_display_text;
5391
+ position += cmd_plain_text.length;
5392
+ } else if (node.type.name === "hardBreak") {
5393
+ display_text += "\n";
5394
+ position += 1;
5395
+ }
5396
+ });
5397
+ return { plain_text, display_text, commands };
5398
+ };
5399
+ var multiline_text_to_tiptap_content = (text, prefixes, variant = "default") => {
5400
+ const lines = text.split("\n");
5401
+ const paragraphs = [];
5402
+ for (const line of lines) {
5403
+ const line_content = text_to_tiptap_content(line, prefixes, variant);
5404
+ const para = line_content.content?.[0];
5405
+ if (para) {
5406
+ paragraphs.push(para);
5407
+ } else {
5408
+ paragraphs.push({ type: "paragraph", content: [] });
5409
+ }
5410
+ }
5411
+ return {
5412
+ type: "doc",
5413
+ content: paragraphs.length > 0 ? paragraphs : [{ type: "paragraph", content: [] }]
5414
+ };
5415
+ };
5416
+ var HazoUiTextarea = ({
5417
+ value,
5418
+ default_value,
5419
+ prefixes,
5420
+ placeholder = "Type here...",
5421
+ disabled = false,
5422
+ className,
5423
+ pill_variant = "default",
5424
+ min_height = "80px",
5425
+ max_height = "200px",
5426
+ rows,
5427
+ on_change,
5428
+ on_submit,
5429
+ on_command_insert,
5430
+ on_command_change,
5431
+ on_command_remove
5432
+ }) => {
5433
+ const [suggestion_state, set_suggestion_state] = React27.useState(null);
5434
+ const [selected_index, set_selected_index] = React27.useState(0);
5435
+ const [popover_position, set_popover_position] = React27.useState({ top: 0, left: 0 });
5436
+ const [edit_context, set_edit_context] = React27.useState(null);
5437
+ const [edit_selected_index, set_edit_selected_index] = React27.useState(0);
5438
+ const is_controlled = value !== void 0;
5439
+ const editor_container_ref = React27.useRef(null);
5440
+ const edit_popover_ref = React27.useRef(null);
5441
+ const [mounted, set_mounted] = React27.useState(false);
5442
+ React27.useEffect(() => {
5443
+ set_mounted(true);
5444
+ }, []);
5445
+ const calculated_min_height = rows ? `${rows * 1.5}em` : min_height;
5446
+ const suggestion_extensions = React27.useMemo(() => {
5447
+ return create_command_suggestion_extension({
5448
+ prefixes,
5449
+ on_suggestion_change: (state) => {
5450
+ set_suggestion_state(state);
5451
+ set_selected_index(0);
5452
+ },
5453
+ on_insert_command: (_command, _prefix, _range) => {
5454
+ }
5455
+ });
5456
+ }, [prefixes]);
5457
+ const editor = useEditor({
5458
+ extensions: [
5459
+ index_default,
5460
+ index_default2,
5461
+ index_default3,
5462
+ index_default4,
5463
+ Placeholder.configure({
5464
+ placeholder
5465
+ }),
5466
+ CommandNodeExtension.configure({}),
5467
+ ...suggestion_extensions
5468
+ ],
5469
+ content: is_controlled ? multiline_text_to_tiptap_content(value || "", prefixes, pill_variant) : multiline_text_to_tiptap_content(default_value || "", prefixes, pill_variant),
5470
+ editable: !disabled,
5471
+ immediatelyRender: false,
5472
+ editorProps: {
5473
+ attributes: {
5474
+ class: cn("cls_textarea_editor", "w-full outline-none"),
5475
+ style: `min-height: ${calculated_min_height}; max-height: ${max_height}`
5476
+ },
5477
+ handleKeyDown: (_view, event) => {
5478
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey) && !suggestion_state?.is_active) {
5479
+ event.preventDefault();
5480
+ if (on_submit && editor) {
5481
+ on_submit(get_editor_output2(editor));
5482
+ }
5483
+ return true;
5484
+ }
5485
+ return false;
5486
+ }
5487
+ },
5488
+ onUpdate: ({ editor: editor2 }) => {
5489
+ if (on_change) {
5490
+ on_change(get_editor_output2(editor2));
5491
+ }
5492
+ }
5493
+ });
5494
+ React27.useEffect(() => {
5495
+ if (suggestion_state?.is_active && editor) {
5496
+ requestAnimationFrame(() => {
5497
+ const { from } = suggestion_state.range;
5498
+ try {
5499
+ const coords = editor.view.coordsAtPos(from);
5500
+ if (coords) {
5501
+ set_popover_position({
5502
+ top: coords.bottom + 4,
5503
+ left: coords.left
5504
+ });
5505
+ }
5506
+ } catch {
5507
+ const rect = suggestion_state.client_rect?.();
5508
+ if (rect) {
5509
+ set_popover_position({
5510
+ top: rect.bottom + 4,
5511
+ left: rect.left
5512
+ });
5513
+ }
5514
+ }
5515
+ });
5516
+ }
5517
+ }, [suggestion_state, editor]);
5518
+ React27.useEffect(() => {
5519
+ if (is_controlled && editor && !editor.isFocused) {
5520
+ const current_text = editor.getText();
5521
+ if (value !== current_text) {
5522
+ const content = multiline_text_to_tiptap_content(
5523
+ value || "",
5524
+ prefixes,
5525
+ pill_variant
5526
+ );
5527
+ editor.commands.setContent(content, { emitUpdate: false });
5528
+ }
5529
+ }
5530
+ }, [value, editor, is_controlled, prefixes, pill_variant]);
5531
+ React27.useEffect(() => {
5532
+ if (editor) {
5533
+ editor.setEditable(!disabled);
5534
+ }
5535
+ }, [disabled, editor]);
5536
+ const handle_command_select = React27.useCallback(
5537
+ (command) => {
5538
+ if (!editor || !suggestion_state) return;
5539
+ insert_command_at_position(
5540
+ editor,
5541
+ command,
5542
+ suggestion_state.prefix,
5543
+ suggestion_state.range,
5544
+ pill_variant
5545
+ );
5546
+ if (on_command_insert) {
5547
+ on_command_insert(command, suggestion_state.prefix);
5548
+ }
5549
+ set_suggestion_state(null);
5550
+ },
5551
+ [editor, suggestion_state, pill_variant, on_command_insert]
5552
+ );
5553
+ const handle_popover_close = React27.useCallback(() => {
5554
+ set_suggestion_state(null);
5555
+ editor?.commands.focus();
5556
+ }, [editor]);
5557
+ const handle_edit_close = React27.useCallback(() => {
5558
+ set_edit_context(null);
5559
+ editor?.commands.focus();
5560
+ }, [editor]);
5561
+ const handle_command_update = React27.useCallback(
5562
+ (new_command) => {
5563
+ if (!editor || !edit_context) return;
5564
+ const old_command = edit_context.command;
5565
+ editor.commands.updateCommand(old_command.id, {
5566
+ action: new_command.action,
5567
+ action_label: new_command.action_label
5568
+ });
5569
+ if (on_command_change) {
5570
+ on_command_change(old_command, new_command);
5571
+ }
5572
+ set_edit_context(null);
5573
+ editor.commands.focus();
5574
+ },
5575
+ [editor, edit_context, on_command_change]
5576
+ );
5577
+ const handle_command_remove = React27.useCallback(() => {
5578
+ if (!editor || !edit_context) return;
5579
+ const command = edit_context.command;
5580
+ editor.state.doc.descendants((node, pos) => {
5581
+ if (node.type.name === "commandNode" && node.attrs.id === command.id) {
5582
+ editor.chain().focus().deleteRange({ from: pos, to: pos + node.nodeSize }).run();
5583
+ return false;
5584
+ }
5585
+ });
5586
+ if (on_command_remove) {
5587
+ on_command_remove(command);
5588
+ }
5589
+ set_edit_context(null);
5590
+ }, [editor, edit_context, on_command_remove]);
5591
+ const filtered_commands = React27.useMemo(() => {
5592
+ if (!suggestion_state) return [];
5593
+ const query = suggestion_state.query.toLowerCase();
5594
+ if (!query) return suggestion_state.commands;
5595
+ return suggestion_state.commands.filter(
5596
+ (cmd) => cmd.action_label.toLowerCase().includes(query) || cmd.action.toLowerCase().includes(query) || cmd.action_description?.toLowerCase().includes(query)
5597
+ );
5598
+ }, [suggestion_state]);
5599
+ React27.useEffect(() => {
5600
+ if (!suggestion_state?.is_active) return;
5601
+ const handle_keydown = (e) => {
5602
+ switch (e.key) {
5603
+ case "ArrowDown":
5604
+ e.preventDefault();
5605
+ set_selected_index(
5606
+ (prev) => Math.min(prev + 1, filtered_commands.length - 1)
5607
+ );
5608
+ break;
5609
+ case "ArrowUp":
5610
+ e.preventDefault();
5611
+ set_selected_index((prev) => Math.max(prev - 1, 0));
5612
+ break;
5613
+ case "Enter":
5614
+ e.preventDefault();
5615
+ if (filtered_commands[selected_index]) {
5616
+ handle_command_select(filtered_commands[selected_index]);
5617
+ }
5618
+ break;
5619
+ case "Escape":
5620
+ e.preventDefault();
5621
+ handle_popover_close();
5622
+ break;
5623
+ }
5624
+ };
5625
+ window.addEventListener("keydown", handle_keydown);
5626
+ return () => window.removeEventListener("keydown", handle_keydown);
5627
+ }, [
5628
+ suggestion_state?.is_active,
5629
+ filtered_commands,
5630
+ selected_index,
5631
+ handle_command_select,
5632
+ handle_popover_close
5633
+ ]);
5634
+ React27.useEffect(() => {
5635
+ if (!edit_context) return;
5636
+ const handle_click_outside = (e) => {
5637
+ if (edit_popover_ref.current && !edit_popover_ref.current.contains(e.target)) {
5638
+ set_edit_context(null);
5639
+ }
5640
+ };
5641
+ const timeout = setTimeout(() => {
5642
+ document.addEventListener("mousedown", handle_click_outside);
5643
+ }, 100);
5644
+ return () => {
5645
+ clearTimeout(timeout);
5646
+ document.removeEventListener("mousedown", handle_click_outside);
5647
+ };
5648
+ }, [edit_context]);
5649
+ const edit_commands = React27.useMemo(() => {
5650
+ if (!edit_context) return [];
5651
+ const prefix_config = prefixes.find((p) => p.char === edit_context.command.prefix);
5652
+ return prefix_config?.commands || [];
5653
+ }, [edit_context, prefixes]);
5654
+ React27.useEffect(() => {
5655
+ if (!edit_context) return;
5656
+ const handle_keydown = (e) => {
5657
+ switch (e.key) {
5658
+ case "ArrowDown":
5659
+ e.preventDefault();
5660
+ set_edit_selected_index(
5661
+ (prev) => Math.min(prev + 1, edit_commands.length)
5662
+ );
5663
+ break;
5664
+ case "ArrowUp":
5665
+ e.preventDefault();
5666
+ set_edit_selected_index((prev) => Math.max(prev - 1, 0));
5667
+ break;
5668
+ case "Enter":
5669
+ e.preventDefault();
5670
+ if (edit_selected_index === edit_commands.length) {
5671
+ handle_command_remove();
5672
+ } else if (edit_commands[edit_selected_index]) {
5673
+ handle_command_update(edit_commands[edit_selected_index]);
5674
+ }
5675
+ break;
5676
+ case "Escape":
5677
+ e.preventDefault();
5678
+ handle_edit_close();
5679
+ break;
5680
+ }
5681
+ };
5682
+ window.addEventListener("keydown", handle_keydown);
5683
+ return () => window.removeEventListener("keydown", handle_keydown);
5684
+ }, [
5685
+ edit_context,
5686
+ edit_commands,
5687
+ edit_selected_index,
5688
+ handle_command_update,
5689
+ handle_command_remove,
5690
+ handle_edit_close
5691
+ ]);
5692
+ React27.useEffect(() => {
5693
+ const handle_pill_click = (e) => {
5694
+ const detail = e.detail;
5695
+ const { id, prefix, action, action_label, node_pos } = detail;
5696
+ if (editor) {
5697
+ try {
5698
+ const coords = editor.view.coordsAtPos(node_pos);
5699
+ if (coords) {
5700
+ const prefix_config = prefixes.find((p) => p.char === prefix);
5701
+ const current_index = prefix_config?.commands.findIndex(
5702
+ (cmd) => cmd.action === action
5703
+ ) ?? 0;
5704
+ set_edit_context({
5705
+ command: {
5706
+ id,
5707
+ prefix,
5708
+ action,
5709
+ action_label,
5710
+ position: node_pos,
5711
+ length: 0
5712
+ },
5713
+ node_pos,
5714
+ rect: new DOMRect(
5715
+ coords.left,
5716
+ coords.bottom + 4,
5717
+ 0,
5718
+ 0
5719
+ )
5720
+ });
5721
+ set_edit_selected_index(Math.max(0, current_index));
5722
+ }
5723
+ } catch {
5724
+ }
5725
+ }
5726
+ };
5727
+ document.addEventListener("command-pill-click", handle_pill_click);
5728
+ return () => document.removeEventListener("command-pill-click", handle_pill_click);
5729
+ }, [editor, prefixes]);
5730
+ return /* @__PURE__ */ jsxs(
5731
+ "div",
5732
+ {
5733
+ ref: editor_container_ref,
5734
+ className: cn(
5735
+ "cls_hazo_ui_textarea",
5736
+ "relative flex w-full rounded-md border border-input bg-background px-3 py-2",
5737
+ "text-sm ring-offset-background",
5738
+ "focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
5739
+ disabled && "cursor-not-allowed opacity-50",
5740
+ className
5741
+ ),
5742
+ style: {
5743
+ minHeight: calculated_min_height,
5744
+ maxHeight: max_height
5745
+ },
5746
+ children: [
5747
+ /* @__PURE__ */ jsx(
5748
+ EditorContent,
5749
+ {
5750
+ editor,
5751
+ className: cn(
5752
+ "cls_textarea_content",
5753
+ "flex-1 min-w-0 overflow-y-auto",
5754
+ "[&_.ProseMirror]:outline-none",
5755
+ "[&_.ProseMirror_p]:m-0 [&_.ProseMirror_p]:mb-1",
5756
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:content-[attr(data-placeholder)]",
5757
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:text-muted-foreground",
5758
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:pointer-events-none",
5759
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:float-left",
5760
+ "[&_.ProseMirror_.is-editor-empty:first-child::before]:h-0"
5761
+ )
5762
+ }
5763
+ ),
5764
+ suggestion_state?.is_active && /* @__PURE__ */ jsx(
5765
+ CommandPopover,
5766
+ {
5767
+ is_open: true,
5768
+ commands: filtered_commands,
5769
+ prefix: suggestion_state.prefix,
5770
+ query: suggestion_state.query,
5771
+ selected_index,
5772
+ position: popover_position,
5773
+ on_query_change: () => {
5774
+ },
5775
+ on_select: handle_command_select,
5776
+ on_close: handle_popover_close,
5777
+ on_selection_change: set_selected_index
5778
+ }
5779
+ ),
5780
+ edit_context && mounted && createPortal(
5781
+ /* @__PURE__ */ jsx(
5782
+ "div",
5783
+ {
5784
+ ref: edit_popover_ref,
5785
+ className: cn(
5786
+ "cls_edit_popover",
5787
+ "fixed z-[9999]",
5788
+ "w-64 min-w-[200px] max-w-[300px]",
5789
+ "rounded-md border bg-popover text-popover-foreground shadow-lg",
5790
+ "animate-in fade-in-0 zoom-in-95"
5791
+ ),
5792
+ style: {
5793
+ top: edit_context.rect.y,
5794
+ left: edit_context.rect.x
5795
+ },
5796
+ children: /* @__PURE__ */ jsxs("div", { className: "py-1", children: [
5797
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs text-muted-foreground border-b", children: "Change command" }),
5798
+ /* @__PURE__ */ jsxs("div", { className: "max-h-[200px] overflow-y-auto", children: [
5799
+ edit_commands.map((cmd, idx) => /* @__PURE__ */ jsxs(
5800
+ "div",
5801
+ {
5802
+ className: cn(
5803
+ "px-3 py-2 cursor-pointer flex items-center gap-2",
5804
+ "hover:bg-accent",
5805
+ idx === edit_selected_index && "bg-accent",
5806
+ cmd.action === edit_context.command.action && "font-medium"
5807
+ ),
5808
+ onClick: () => handle_command_update(cmd),
5809
+ children: [
5810
+ cmd.icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-muted-foreground", children: cmd.icon }),
5811
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
5812
+ /* @__PURE__ */ jsxs("div", { className: "truncate", children: [
5813
+ edit_context.command.prefix,
5814
+ cmd.action_label
5815
+ ] }),
5816
+ cmd.action_description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground truncate", children: cmd.action_description })
5817
+ ] }),
5818
+ cmd.action === edit_context.command.action && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "current" })
5819
+ ]
5820
+ },
5821
+ cmd.action
5822
+ )),
5823
+ /* @__PURE__ */ jsx(
5824
+ "div",
5825
+ {
5826
+ className: cn(
5827
+ "px-3 py-2 cursor-pointer flex items-center gap-2 text-destructive border-t",
5828
+ "hover:bg-destructive/10",
5829
+ edit_selected_index === edit_commands.length && "bg-destructive/10"
5830
+ ),
5831
+ onClick: handle_command_remove,
5832
+ children: /* @__PURE__ */ jsx("span", { children: "Remove" })
5833
+ }
5834
+ )
5835
+ ] })
5836
+ ] })
5837
+ }
5838
+ ),
5839
+ document.body
5840
+ )
5841
+ ]
5842
+ }
5843
+ );
5844
+ };
5845
+ HazoUiTextarea.displayName = "HazoUiTextarea";
4249
5846
 
4250
- export { HazoUiFlexInput, HazoUiFlexRadio, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, HazoUiRte };
5847
+ export { CommandNodeExtension, CommandPill, CommandPopover, HazoUiFlexInput, HazoUiFlexRadio, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, HazoUiRte, HazoUiTextarea, HazoUiTextbox, create_command_suggestion_extension, parse_commands_from_text, text_to_tiptap_content };
4251
5848
  //# sourceMappingURL=index.js.map
4252
5849
  //# sourceMappingURL=index.js.map