@fab1o978/react-ui 0.1.3 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/components/ColorPicker/index.cjs +205 -63
  2. package/dist/components/ColorPicker/index.cjs.map +1 -1
  3. package/dist/components/ColorPicker/index.css +200 -42
  4. package/dist/components/ColorPicker/index.css.map +1 -1
  5. package/dist/components/ColorPicker/index.js +205 -63
  6. package/dist/components/ColorPicker/index.js.map +1 -1
  7. package/dist/components/RichTextEditor/index.cjs +3553 -0
  8. package/dist/components/RichTextEditor/index.cjs.map +1 -0
  9. package/dist/components/RichTextEditor/index.css +356 -0
  10. package/dist/components/RichTextEditor/index.css.map +1 -0
  11. package/dist/components/RichTextEditor/index.d.cts +30 -0
  12. package/dist/components/RichTextEditor/index.d.ts +30 -0
  13. package/dist/components/RichTextEditor/index.js +3538 -0
  14. package/dist/components/RichTextEditor/index.js.map +1 -0
  15. package/dist/components/SliderControl/index.cjs +268 -0
  16. package/dist/components/SliderControl/index.cjs.map +1 -0
  17. package/dist/components/SliderControl/index.css +202 -0
  18. package/dist/components/SliderControl/index.css.map +1 -0
  19. package/dist/components/SliderControl/index.d.cts +21 -0
  20. package/dist/components/SliderControl/index.d.ts +21 -0
  21. package/dist/components/SliderControl/index.js +266 -0
  22. package/dist/components/SliderControl/index.js.map +1 -0
  23. package/dist/components/SlidingCounter/index.cjs +181 -0
  24. package/dist/components/SlidingCounter/index.cjs.map +1 -0
  25. package/dist/components/SlidingCounter/index.css +133 -0
  26. package/dist/components/SlidingCounter/index.css.map +1 -0
  27. package/dist/components/SlidingCounter/index.d.cts +19 -0
  28. package/dist/components/SlidingCounter/index.d.ts +19 -0
  29. package/dist/components/SlidingCounter/index.js +179 -0
  30. package/dist/components/SlidingCounter/index.js.map +1 -0
  31. package/dist/index.cjs +3771 -63
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.css +685 -42
  34. package/dist/index.css.map +1 -1
  35. package/dist/index.d.cts +5 -0
  36. package/dist/index.d.ts +5 -0
  37. package/dist/index.js +3760 -65
  38. package/dist/index.js.map +1 -1
  39. package/package.json +8 -1
package/dist/index.cjs CHANGED
@@ -2,10 +2,24 @@
2
2
 
3
3
  var React = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var react = require('@tiptap/react');
6
+ var StarterKit = require('@tiptap/starter-kit');
7
+ var Underline = require('@tiptap/extension-underline');
8
+ var Placeholder = require('@tiptap/extension-placeholder');
9
+ var transform = require('@tiptap/pm/transform');
10
+ var commands = require('@tiptap/pm/commands');
11
+ var state = require('@tiptap/pm/state');
12
+ var model = require('@tiptap/pm/model');
13
+ var schemaList = require('@tiptap/pm/schema-list');
14
+ require('@tiptap/pm/view');
15
+ require('@tiptap/pm/keymap');
5
16
 
6
17
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
18
 
8
19
  var React__default = /*#__PURE__*/_interopDefault(React);
20
+ var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
21
+ var Underline__default = /*#__PURE__*/_interopDefault(Underline);
22
+ var Placeholder__default = /*#__PURE__*/_interopDefault(Placeholder);
9
23
 
10
24
  // src/components/Button/Button.tsx
11
25
 
@@ -593,10 +607,6 @@ var ColorPicker_module_default = {
593
607
  discWrapper: "ColorPicker_module_discWrapper",
594
608
  disc: "ColorPicker_module_disc",
595
609
  dot: "ColorPicker_module_dot",
596
- lSlider: "ColorPicker_module_lSlider",
597
- lThumb: "ColorPicker_module_lThumb",
598
- alphaSlider: "ColorPicker_module_alphaSlider",
599
- alphaThumb: "ColorPicker_module_alphaThumb",
600
610
  previewSwatch: "ColorPicker_module_previewSwatch",
601
611
  eyedropperBtn: "ColorPicker_module_eyedropperBtn",
602
612
  inputSection: "ColorPicker_module_inputSection",
@@ -612,6 +622,190 @@ var ColorPicker_module_default = {
612
622
  swatches: "ColorPicker_module_swatches",
613
623
  recentSwatch: "ColorPicker_module_recentSwatch"
614
624
  };
625
+
626
+ // src/components/SliderControl/SliderControl.module.scss
627
+ var SliderControl_module_default = {
628
+ wrapper: "SliderControl_module_wrapper",
629
+ disabled: "SliderControl_module_disabled",
630
+ icon: "SliderControl_module_icon",
631
+ trackArea: "SliderControl_module_trackArea",
632
+ groove: "SliderControl_module_groove",
633
+ rail: "SliderControl_module_rail",
634
+ fill: "SliderControl_module_fill",
635
+ thumb: "SliderControl_module_thumb",
636
+ thumbDragging: "SliderControl_module_thumbDragging",
637
+ tooltip: "SliderControl_module_tooltip",
638
+ tooltipVisible: "SliderControl_module_tooltipVisible"
639
+ };
640
+ function clamp(v, min, max) {
641
+ return Math.min(Math.max(v, min), max);
642
+ }
643
+ function snapToStep(v, min, step) {
644
+ return Math.round((v - min) / step) * step + min;
645
+ }
646
+ var SliderControl = ({
647
+ value: controlledValue,
648
+ defaultValue = 50,
649
+ min = 0,
650
+ max = 100,
651
+ step = 1,
652
+ onChange,
653
+ showTooltip = "drag",
654
+ leftIcon,
655
+ rightIcon,
656
+ railBackground,
657
+ accent,
658
+ className,
659
+ disabled = false
660
+ }) => {
661
+ const isControlled = controlledValue !== void 0;
662
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
663
+ const [isDragging, setIsDragging] = React.useState(false);
664
+ const [isFocused, setIsFocused] = React.useState(false);
665
+ const trackRef = React.useRef(null);
666
+ const thumbRef = React.useRef(null);
667
+ const value = isControlled ? controlledValue : internalValue;
668
+ const pct = (clamp(value, min, max) - min) / (max - min);
669
+ const accentVars = accent ? accentToCssVars(deriveAccent(accent), "slider") : {};
670
+ const setValue = React.useCallback(
671
+ (next) => {
672
+ const snapped = clamp(snapToStep(next, min, step), min, max);
673
+ if (!isControlled) setInternalValue(snapped);
674
+ onChange?.(snapped);
675
+ },
676
+ [isControlled, min, max, step, onChange]
677
+ );
678
+ const valueFromPointer = React.useCallback(
679
+ (e) => {
680
+ const rect = trackRef.current.getBoundingClientRect();
681
+ const ratio = clamp((e.clientX - rect.left) / rect.width, 0, 1);
682
+ return min + ratio * (max - min);
683
+ },
684
+ [min, max]
685
+ );
686
+ const handlePointerDown = React.useCallback(
687
+ (e) => {
688
+ if (disabled) return;
689
+ e.currentTarget.setPointerCapture(e.pointerId);
690
+ setIsDragging(true);
691
+ thumbRef.current?.focus();
692
+ setValue(valueFromPointer(e.nativeEvent));
693
+ },
694
+ [disabled, setValue, valueFromPointer]
695
+ );
696
+ const handlePointerMove = React.useCallback(
697
+ (e) => {
698
+ if (!isDragging || disabled) return;
699
+ setValue(valueFromPointer(e.nativeEvent));
700
+ },
701
+ [isDragging, disabled, setValue, valueFromPointer]
702
+ );
703
+ const handlePointerUp = React.useCallback(() => {
704
+ setIsDragging(false);
705
+ thumbRef.current?.blur();
706
+ }, []);
707
+ React.useEffect(() => {
708
+ const el = trackRef.current;
709
+ if (!el) return;
710
+ const onWheel = (e) => {
711
+ if (disabled) return;
712
+ e.preventDefault();
713
+ setValue(value + (e.deltaY < 0 ? step : -step));
714
+ };
715
+ el.addEventListener("wheel", onWheel, { passive: false });
716
+ return () => el.removeEventListener("wheel", onWheel);
717
+ }, [disabled, value, step, setValue]);
718
+ const handleKeyDown = React.useCallback(
719
+ (e) => {
720
+ if (disabled) return;
721
+ const map = {
722
+ ArrowRight: step,
723
+ ArrowUp: step,
724
+ ArrowLeft: -step,
725
+ ArrowDown: -step,
726
+ PageUp: step * 10,
727
+ PageDown: -step * 10
728
+ };
729
+ if (e.key === "Home") {
730
+ setValue(min);
731
+ e.preventDefault();
732
+ return;
733
+ }
734
+ if (e.key === "End") {
735
+ setValue(max);
736
+ e.preventDefault();
737
+ return;
738
+ }
739
+ if (map[e.key] !== void 0) {
740
+ setValue(value + map[e.key]);
741
+ e.preventDefault();
742
+ }
743
+ },
744
+ [disabled, step, min, max, value, setValue]
745
+ );
746
+ const tooltipVisible = showTooltip === "always" || showTooltip === "drag" && (isDragging || isFocused);
747
+ const displayValue = `${Math.round(value)}%`;
748
+ const tooltipOffset = `calc(${pct * 100}% + ${(0.5 - pct) * 20}px)`;
749
+ return /* @__PURE__ */ jsxRuntime.jsxs(
750
+ "div",
751
+ {
752
+ className: [SliderControl_module_default.wrapper, disabled ? SliderControl_module_default.disabled : "", className ?? ""].filter(Boolean).join(" "),
753
+ style: accentVars,
754
+ children: [
755
+ leftIcon !== null && leftIcon !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SliderControl_module_default.icon, children: leftIcon }),
756
+ /* @__PURE__ */ jsxRuntime.jsxs(
757
+ "div",
758
+ {
759
+ ref: trackRef,
760
+ className: SliderControl_module_default.trackArea,
761
+ onPointerDown: handlePointerDown,
762
+ onPointerMove: handlePointerMove,
763
+ onPointerUp: handlePointerUp,
764
+ onPointerCancel: handlePointerUp,
765
+ children: [
766
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: SliderControl_module_default.groove, children: /* @__PURE__ */ jsxRuntime.jsx(
767
+ "div",
768
+ {
769
+ className: SliderControl_module_default.rail,
770
+ style: railBackground ? { background: railBackground } : void 0,
771
+ children: !railBackground && /* @__PURE__ */ jsxRuntime.jsx("div", { className: SliderControl_module_default.fill, style: { width: `${pct * 100}%` } })
772
+ }
773
+ ) }),
774
+ /* @__PURE__ */ jsxRuntime.jsx(
775
+ "div",
776
+ {
777
+ ref: thumbRef,
778
+ role: "slider",
779
+ tabIndex: disabled ? -1 : 0,
780
+ "aria-valuenow": Math.round(value),
781
+ "aria-valuemin": min,
782
+ "aria-valuemax": max,
783
+ "aria-disabled": disabled,
784
+ className: [SliderControl_module_default.thumb, isDragging ? SliderControl_module_default.thumbDragging : ""].filter(Boolean).join(" "),
785
+ style: { left: `calc(${pct * 100}% + ${(0.5 - pct) * 24}px)` },
786
+ onKeyDown: handleKeyDown,
787
+ onFocus: () => setIsFocused(true),
788
+ onBlur: () => setIsFocused(false)
789
+ }
790
+ ),
791
+ /* @__PURE__ */ jsxRuntime.jsx(
792
+ "div",
793
+ {
794
+ className: [SliderControl_module_default.tooltip, tooltipVisible ? SliderControl_module_default.tooltipVisible : ""].filter(Boolean).join(" "),
795
+ style: { left: tooltipOffset },
796
+ "aria-hidden": "true",
797
+ children: displayValue
798
+ }
799
+ )
800
+ ]
801
+ }
802
+ ),
803
+ rightIcon !== null && rightIcon !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SliderControl_module_default.icon, children: rightIcon })
804
+ ]
805
+ }
806
+ );
807
+ };
808
+ SliderControl.displayName = "SliderControl";
615
809
  var DISC = 200;
616
810
  var CopyIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
617
811
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "5", y: "5", width: "7", height: "7", rx: "1.5", stroke: "currentColor", strokeWidth: "1.4" }),
@@ -781,50 +975,21 @@ var ColorPicker = ({
781
975
  },
782
976
  [updateDisc]
783
977
  );
784
- const updateL = React.useCallback(
785
- (clientX, rect) => {
786
- const nl = Math.max(0, Math.min(100, (clientX - rect.left) / rect.width * 100));
978
+ const handleLChange = React.useCallback(
979
+ (nl) => {
787
980
  setL(nl);
788
981
  notify(h, s, nl, a);
789
982
  },
790
983
  [h, s, a, notify]
791
984
  );
792
- const handleLPointerDown = React.useCallback(
793
- (e) => {
794
- e.currentTarget.setPointerCapture(e.pointerId);
795
- updateL(e.clientX, e.currentTarget.getBoundingClientRect());
796
- },
797
- [updateL]
798
- );
799
- const handleLPointerMove = React.useCallback(
800
- (e) => {
801
- if (e.buttons === 0) return;
802
- updateL(e.clientX, e.currentTarget.getBoundingClientRect());
803
- },
804
- [updateL]
805
- );
806
- const updateA = React.useCallback(
807
- (clientX, rect) => {
808
- const na = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
985
+ const handleAChange = React.useCallback(
986
+ (val) => {
987
+ const na = val / 100;
809
988
  setA(na);
810
989
  notify(h, s, l, na);
811
990
  },
812
991
  [h, s, l, notify]
813
992
  );
814
- const handleAPointerDown = React.useCallback(
815
- (e) => {
816
- e.currentTarget.setPointerCapture(e.pointerId);
817
- updateA(e.clientX, e.currentTarget.getBoundingClientRect());
818
- },
819
- [updateA]
820
- );
821
- const handleAPointerMove = React.useCallback(
822
- (e) => {
823
- if (e.buttons === 0) return;
824
- updateA(e.clientX, e.currentTarget.getBoundingClientRect());
825
- },
826
- [updateA]
827
- );
828
993
  const { r: rr, g: gg, b: bb } = hslToRgb(h, s, l);
829
994
  const luminance = (0.299 * rr + 0.587 * gg + 0.114 * bb) / 255;
830
995
  const swatchFg = luminance > 0.6 ? "rgba(0,0,0,0.5)" : "rgba(255,255,255,0.9)";
@@ -837,7 +1002,6 @@ var ColorPicker = ({
837
1002
  hsl(${h}, ${s}%, 5%),
838
1003
  hsl(${h}, ${s}%, 50%),
839
1004
  hsl(${h}, ${s}%, 95%))`;
840
- const alphaGradient = `linear-gradient(to right, transparent, ${rgbStr})`;
841
1005
  const handleEyeDropper = async () => {
842
1006
  if (!window.EyeDropper) return;
843
1007
  try {
@@ -898,35 +1062,27 @@ var ColorPicker = ({
898
1062
  )
899
1063
  ] }) }),
900
1064
  /* @__PURE__ */ jsxRuntime.jsx(
901
- "div",
1065
+ SliderControl,
902
1066
  {
903
- className: ColorPicker_module_default.lSlider,
904
- style: { backgroundImage: lGradient },
905
- onPointerDown: handleLPointerDown,
906
- onPointerMove: handleLPointerMove,
907
- children: /* @__PURE__ */ jsxRuntime.jsx(
908
- "div",
909
- {
910
- className: ColorPicker_module_default.lThumb,
911
- style: { left: `${l}%` }
912
- }
913
- )
1067
+ value: l,
1068
+ onChange: handleLChange,
1069
+ min: 0,
1070
+ max: 100,
1071
+ step: 1,
1072
+ showTooltip: "never",
1073
+ railBackground: lGradient
914
1074
  }
915
1075
  ),
916
1076
  showAlpha && /* @__PURE__ */ jsxRuntime.jsx(
917
- "div",
1077
+ SliderControl,
918
1078
  {
919
- className: ColorPicker_module_default.alphaSlider,
920
- style: { backgroundImage: alphaGradient },
921
- onPointerDown: handleAPointerDown,
922
- onPointerMove: handleAPointerMove,
923
- children: /* @__PURE__ */ jsxRuntime.jsx(
924
- "div",
925
- {
926
- className: ColorPicker_module_default.alphaThumb,
927
- style: { left: `${a * 100}%` }
928
- }
929
- )
1079
+ value: Math.round(a * 100),
1080
+ onChange: handleAChange,
1081
+ min: 0,
1082
+ max: 100,
1083
+ step: 1,
1084
+ showTooltip: "never",
1085
+ railBackground: `linear-gradient(to right, transparent, ${rgbStr}), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 0 / 10px 10px`
930
1086
  }
931
1087
  ),
932
1088
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -996,11 +1152,3563 @@ var ColorPicker = ({
996
1152
  );
997
1153
  };
998
1154
 
1155
+ // src/components/SlidingCounter/SlidingCounter.module.scss
1156
+ var SlidingCounter_module_default = {
1157
+ counter: "SlidingCounter_module_counter",
1158
+ sign: "SlidingCounter_module_sign",
1159
+ separator: "SlidingCounter_module_separator",
1160
+ reelWindow: "SlidingCounter_module_reelWindow",
1161
+ sm: "SlidingCounter_module_sm",
1162
+ md: "SlidingCounter_module_md",
1163
+ lg: "SlidingCounter_module_lg",
1164
+ reel: "SlidingCounter_module_reel",
1165
+ digitCell: "SlidingCounter_module_digitCell"
1166
+ };
1167
+ var COPIES = 3;
1168
+ var TOTAL = COPIES * 10;
1169
+ var DigitReel = ({ digit, direction, size }) => {
1170
+ const posRef = React.useRef(10 + digit);
1171
+ const prevDigitRef = React.useRef(digit);
1172
+ const [pos, setPos] = React.useState(10 + digit);
1173
+ const [animate, setAnimate] = React.useState(true);
1174
+ React.useEffect(() => {
1175
+ if (prevDigitRef.current === digit) return;
1176
+ const prev = prevDigitRef.current;
1177
+ let next = posRef.current;
1178
+ if (direction === "up") {
1179
+ next += digit > prev ? digit - prev : 10 - prev + digit;
1180
+ } else {
1181
+ next -= digit < prev ? prev - digit : prev + 10 - digit;
1182
+ }
1183
+ posRef.current = next;
1184
+ prevDigitRef.current = digit;
1185
+ setAnimate(true);
1186
+ setPos(next);
1187
+ }, [digit, direction]);
1188
+ const handleTransitionEnd = () => {
1189
+ const normalized = 10 + (posRef.current % 10 + 10) % 10;
1190
+ posRef.current = normalized;
1191
+ setAnimate(false);
1192
+ setPos(normalized);
1193
+ };
1194
+ const translateY = -(pos / TOTAL) * 100;
1195
+ const cells = Array.from(
1196
+ { length: COPIES },
1197
+ () => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1198
+ ).flat();
1199
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${SlidingCounter_module_default.reelWindow} ${SlidingCounter_module_default[size]}`, children: /* @__PURE__ */ jsxRuntime.jsx(
1200
+ "div",
1201
+ {
1202
+ className: SlidingCounter_module_default.reel,
1203
+ style: {
1204
+ transform: `translateY(${translateY}%)`,
1205
+ transition: animate ? void 0 : "none"
1206
+ },
1207
+ onTransitionEnd: handleTransitionEnd,
1208
+ children: cells.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: SlidingCounter_module_default.digitCell, children: d }, i))
1209
+ }
1210
+ ) });
1211
+ };
1212
+ function splitDigits(value, minDigits, decimals) {
1213
+ const abs = Math.abs(value);
1214
+ const fixed = abs.toFixed(decimals);
1215
+ const [intPart, decPart = ""] = fixed.split(".");
1216
+ const intDigits = intPart.split("").map(Number);
1217
+ const padded = intDigits.length < minDigits ? [...Array(minDigits - intDigits.length).fill(0), ...intDigits] : intDigits;
1218
+ const decDigits = decPart.split("").map(Number);
1219
+ return { intDigits: padded, decDigits };
1220
+ }
1221
+ var SlidingCounter = ({
1222
+ value,
1223
+ minDigits = 1,
1224
+ decimals = 0,
1225
+ decimalSeparator = ".",
1226
+ size = "md",
1227
+ accent,
1228
+ className
1229
+ }) => {
1230
+ const accentVars = accent ? accentToCssVars(deriveAccent(accent), "sliding-counter") : {};
1231
+ const safeValue = isFinite(value) ? value : 0;
1232
+ const prevValueRef = React.useRef(safeValue);
1233
+ const direction = safeValue >= prevValueRef.current ? "up" : "down";
1234
+ prevValueRef.current = safeValue;
1235
+ const { intDigits, decDigits } = splitDigits(safeValue, minDigits, decimals);
1236
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1237
+ "div",
1238
+ {
1239
+ className: [SlidingCounter_module_default.counter, SlidingCounter_module_default[size], className ?? ""].filter(Boolean).join(" "),
1240
+ style: accentVars,
1241
+ "aria-label": safeValue.toFixed(decimals),
1242
+ children: [
1243
+ safeValue < 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SlidingCounter_module_default.sign, children: "\u2212" }),
1244
+ intDigits.map((digit, i) => /* @__PURE__ */ jsxRuntime.jsx(DigitReel, { digit, direction, size }, `int-${intDigits.length - i}`)),
1245
+ decimals > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: SlidingCounter_module_default.separator, children: decimalSeparator }),
1246
+ decDigits.map((digit, i) => /* @__PURE__ */ jsxRuntime.jsx(DigitReel, { digit, direction, size }, `dec-${i}`))
1247
+ ]
1248
+ }
1249
+ );
1250
+ };
1251
+
1252
+ // src/components/RichTextEditor/RichTextEditor.module.scss
1253
+ var RichTextEditor_module_default = {
1254
+ root: "RichTextEditor_module_root",
1255
+ readOnly: "RichTextEditor_module_readOnly",
1256
+ toolbar: "RichTextEditor_module_toolbar",
1257
+ toolbarGroup: "RichTextEditor_module_toolbarGroup",
1258
+ divider: "RichTextEditor_module_divider",
1259
+ toolbarButton: "RichTextEditor_module_toolbarButton",
1260
+ active: "RichTextEditor_module_active",
1261
+ headingButton: "RichTextEditor_module_headingButton",
1262
+ bubbleMenu: "RichTextEditor_module_bubbleMenu",
1263
+ editorContent: "RichTextEditor_module_editorContent"};
1264
+ var BulletListIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
1265
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "2.5", cy: "4", r: "1.5", fill: "currentColor" }),
1266
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "4", x2: "14", y2: "4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1267
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "2.5", cy: "8", r: "1.5", fill: "currentColor" }),
1268
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "8", x2: "14", y2: "8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1269
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "2.5", cy: "12", r: "1.5", fill: "currentColor" }),
1270
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "12", x2: "14", y2: "12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1271
+ ] });
1272
+ var OrderedListIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
1273
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "0.5", y: "5.5", fontSize: "5.5", fill: "currentColor", fontFamily: "system-ui, sans-serif", children: "1." }),
1274
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "7", y1: "4", x2: "14", y2: "4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1275
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "0.5", y: "9.5", fontSize: "5.5", fill: "currentColor", fontFamily: "system-ui, sans-serif", children: "2." }),
1276
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "7", y1: "8", x2: "14", y2: "8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1277
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "0.5", y: "13.5", fontSize: "5.5", fill: "currentColor", fontFamily: "system-ui, sans-serif", children: "3." }),
1278
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "7", y1: "12", x2: "14", y2: "12", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1279
+ ] });
1280
+ var Toolbar = ({ slotBefore }) => {
1281
+ const { editor } = react.useCurrentEditor();
1282
+ if (!editor) return null;
1283
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: RichTextEditor_module_default.toolbar, role: "toolbar", "aria-label": "Text formatting", children: [
1284
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: RichTextEditor_module_default.toolbarGroup, children: [
1285
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "B" }), title: "Bold", action: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold") },
1286
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("em", { children: "I" }), title: "Italic", action: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic") },
1287
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("u", { children: "U" }), title: "Underline", action: () => editor.chain().focus().toggleUnderline().run(), active: editor.isActive("underline") },
1288
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("s", { children: "S" }), title: "Strikethrough", action: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike") }
1289
+ ].map(({ render, title, action, active }) => /* @__PURE__ */ jsxRuntime.jsx(
1290
+ "button",
1291
+ {
1292
+ type: "button",
1293
+ title,
1294
+ "aria-label": title,
1295
+ "aria-pressed": active,
1296
+ className: [RichTextEditor_module_default.toolbarButton, active ? RichTextEditor_module_default.active : ""].filter(Boolean).join(" "),
1297
+ onMouseDown: (e) => {
1298
+ e.preventDefault();
1299
+ action();
1300
+ },
1301
+ children: render()
1302
+ },
1303
+ title
1304
+ )) }),
1305
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: RichTextEditor_module_default.divider, "aria-hidden": "true" }),
1306
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: RichTextEditor_module_default.toolbarGroup, children: [1, 2, 3].map((level) => /* @__PURE__ */ jsxRuntime.jsxs(
1307
+ "button",
1308
+ {
1309
+ type: "button",
1310
+ title: `Heading ${level}`,
1311
+ "aria-label": `Heading ${level}`,
1312
+ "aria-pressed": editor.isActive("heading", { level }),
1313
+ className: [
1314
+ RichTextEditor_module_default.toolbarButton,
1315
+ RichTextEditor_module_default.headingButton,
1316
+ editor.isActive("heading", { level }) ? RichTextEditor_module_default.active : ""
1317
+ ].filter(Boolean).join(" "),
1318
+ onMouseDown: (e) => {
1319
+ e.preventDefault();
1320
+ editor.chain().focus().toggleHeading({ level }).run();
1321
+ },
1322
+ children: [
1323
+ "H",
1324
+ level
1325
+ ]
1326
+ },
1327
+ `h${level}`
1328
+ )) }),
1329
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: RichTextEditor_module_default.divider, "aria-hidden": "true" }),
1330
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: RichTextEditor_module_default.toolbarGroup, children: [
1331
+ { icon: /* @__PURE__ */ jsxRuntime.jsx(BulletListIcon, {}), title: "Bullet list", action: () => editor.chain().focus().toggleBulletList().run(), active: editor.isActive("bulletList") },
1332
+ { icon: /* @__PURE__ */ jsxRuntime.jsx(OrderedListIcon, {}), title: "Ordered list", action: () => editor.chain().focus().toggleOrderedList().run(), active: editor.isActive("orderedList") }
1333
+ ].map(({ icon, title, action, active }) => /* @__PURE__ */ jsxRuntime.jsx(
1334
+ "button",
1335
+ {
1336
+ type: "button",
1337
+ title,
1338
+ "aria-label": title,
1339
+ "aria-pressed": active,
1340
+ className: [RichTextEditor_module_default.toolbarButton, active ? RichTextEditor_module_default.active : ""].filter(Boolean).join(" "),
1341
+ onMouseDown: (e) => {
1342
+ e.preventDefault();
1343
+ action();
1344
+ },
1345
+ children: icon
1346
+ },
1347
+ title
1348
+ )) }),
1349
+ slotBefore && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1350
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: RichTextEditor_module_default.divider, "aria-hidden": "true" }),
1351
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: RichTextEditor_module_default.toolbarGroup, children: slotBefore })
1352
+ ] })
1353
+ ] });
1354
+ };
1355
+ var BubbleMenu = () => {
1356
+ const { editor } = react.useCurrentEditor();
1357
+ const menuRef = React.useRef(null);
1358
+ const [pos, setPos] = React.useState(null);
1359
+ React.useEffect(() => {
1360
+ if (!editor) return;
1361
+ const update = () => {
1362
+ const { selection } = editor.state;
1363
+ if (selection.empty) {
1364
+ setPos(null);
1365
+ return;
1366
+ }
1367
+ const { from, to } = selection;
1368
+ const start = editor.view.coordsAtPos(from);
1369
+ const end = editor.view.coordsAtPos(to);
1370
+ const halfW = (menuRef.current?.offsetWidth ?? 0) / 2;
1371
+ const menuH = menuRef.current?.offsetHeight ?? 0;
1372
+ const rawX = (start.left + end.left) / 2;
1373
+ const clampedX = Math.max(halfW + 8, Math.min(rawX, window.innerWidth - halfW - 8));
1374
+ const toolbarBottom = document.querySelector("[role='toolbar']")?.getBoundingClientRect().bottom ?? 0;
1375
+ const flip = start.top - menuH - 8 < toolbarBottom + 8;
1376
+ setPos({ x: clampedX, y: flip ? start.bottom : start.top, flip });
1377
+ };
1378
+ editor.on("selectionUpdate", update);
1379
+ editor.on("blur", () => setPos(null));
1380
+ return () => {
1381
+ editor.off("selectionUpdate", update);
1382
+ editor.off("blur", () => setPos(null));
1383
+ };
1384
+ }, [editor]);
1385
+ if (!editor) return null;
1386
+ const visible = pos !== null;
1387
+ return /* @__PURE__ */ jsxRuntime.jsx(
1388
+ "div",
1389
+ {
1390
+ ref: menuRef,
1391
+ className: RichTextEditor_module_default.bubbleMenu,
1392
+ "aria-hidden": !visible,
1393
+ style: {
1394
+ position: "fixed",
1395
+ left: pos?.x ?? 0,
1396
+ top: pos?.y ?? 0,
1397
+ transform: pos?.flip ? "translate(-50%, 8px)" : "translate(-50%, calc(-100% - 8px))",
1398
+ zIndex: 50,
1399
+ visibility: visible ? "visible" : "hidden",
1400
+ pointerEvents: visible ? "auto" : "none"
1401
+ },
1402
+ children: [
1403
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "B" }), title: "Bold", action: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold") },
1404
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("em", { children: "I" }), title: "Italic", action: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic") },
1405
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("u", { children: "U" }), title: "Underline", action: () => editor.chain().focus().toggleUnderline().run(), active: editor.isActive("underline") },
1406
+ { render: () => /* @__PURE__ */ jsxRuntime.jsx("s", { children: "S" }), title: "Strikethrough", action: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike") }
1407
+ ].map(({ render, title, action, active }) => /* @__PURE__ */ jsxRuntime.jsx(
1408
+ "button",
1409
+ {
1410
+ type: "button",
1411
+ title,
1412
+ "aria-label": title,
1413
+ "aria-pressed": active,
1414
+ className: [RichTextEditor_module_default.toolbarButton, active ? RichTextEditor_module_default.active : ""].filter(Boolean).join(" "),
1415
+ onMouseDown: (e) => {
1416
+ e.preventDefault();
1417
+ action();
1418
+ },
1419
+ children: render()
1420
+ },
1421
+ title
1422
+ ))
1423
+ }
1424
+ );
1425
+ };
1426
+ var RichTextEditor = ({
1427
+ value,
1428
+ placeholder = "Start writing...",
1429
+ readOnly = false,
1430
+ minHeight = 200,
1431
+ maxHeight,
1432
+ accent,
1433
+ extensions = [],
1434
+ slotBefore,
1435
+ slotAfter,
1436
+ onChangeHTML,
1437
+ onChangeJSON
1438
+ }) => {
1439
+ const accentVars = accent ? accentToCssVars(deriveAccent(accent), "rich-text-editor") : {};
1440
+ const minHeightValue = typeof minHeight === "number" ? `${minHeight}px` : minHeight;
1441
+ const maxHeightValue = maxHeight !== void 0 ? typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight : void 0;
1442
+ return /* @__PURE__ */ jsxRuntime.jsx(
1443
+ "div",
1444
+ {
1445
+ className: [RichTextEditor_module_default.root, readOnly ? RichTextEditor_module_default.readOnly : ""].filter(Boolean).join(" "),
1446
+ style: { ...accentVars, "--rte-min-height": minHeightValue, "--rte-max-height": maxHeightValue },
1447
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1448
+ react.EditorProvider,
1449
+ {
1450
+ extensions: [
1451
+ StarterKit__default.default.configure({ heading: { levels: [1, 2, 3] } }),
1452
+ Underline__default.default,
1453
+ Placeholder__default.default.configure({ placeholder }),
1454
+ ...extensions
1455
+ ],
1456
+ content: value,
1457
+ editable: !readOnly,
1458
+ onUpdate: ({ editor }) => {
1459
+ onChangeHTML?.(editor.getHTML());
1460
+ onChangeJSON?.(editor.getJSON());
1461
+ },
1462
+ slotBefore: !readOnly ? /* @__PURE__ */ jsxRuntime.jsx(Toolbar, { slotBefore }) : void 0,
1463
+ slotAfter,
1464
+ editorContainerProps: { className: RichTextEditor_module_default.editorContent },
1465
+ children: !readOnly && /* @__PURE__ */ jsxRuntime.jsx(BubbleMenu, {})
1466
+ }
1467
+ )
1468
+ }
1469
+ );
1470
+ };
1471
+ var __defProp = Object.defineProperty;
1472
+ var __export = (target, all) => {
1473
+ for (var name in all)
1474
+ __defProp(target, name, { get: all[name], enumerable: true });
1475
+ };
1476
+ function createChainableState(config) {
1477
+ const { state, transaction } = config;
1478
+ let { selection } = transaction;
1479
+ let { doc } = transaction;
1480
+ let { storedMarks } = transaction;
1481
+ return {
1482
+ ...state,
1483
+ apply: state.apply.bind(state),
1484
+ applyTransaction: state.applyTransaction.bind(state),
1485
+ plugins: state.plugins,
1486
+ schema: state.schema,
1487
+ reconfigure: state.reconfigure.bind(state),
1488
+ toJSON: state.toJSON.bind(state),
1489
+ get storedMarks() {
1490
+ return storedMarks;
1491
+ },
1492
+ get selection() {
1493
+ return selection;
1494
+ },
1495
+ get doc() {
1496
+ return doc;
1497
+ },
1498
+ get tr() {
1499
+ selection = transaction.selection;
1500
+ doc = transaction.doc;
1501
+ storedMarks = transaction.storedMarks;
1502
+ return transaction;
1503
+ }
1504
+ };
1505
+ }
1506
+ var CommandManager = class {
1507
+ constructor(props) {
1508
+ this.editor = props.editor;
1509
+ this.rawCommands = this.editor.extensionManager.commands;
1510
+ this.customState = props.state;
1511
+ }
1512
+ get hasCustomState() {
1513
+ return !!this.customState;
1514
+ }
1515
+ get state() {
1516
+ return this.customState || this.editor.state;
1517
+ }
1518
+ get commands() {
1519
+ const { rawCommands, editor, state } = this;
1520
+ const { view } = editor;
1521
+ const { tr } = state;
1522
+ const props = this.buildProps(tr);
1523
+ return Object.fromEntries(
1524
+ Object.entries(rawCommands).map(([name, command2]) => {
1525
+ const method = (...args) => {
1526
+ const callback = command2(...args)(props);
1527
+ if (!tr.getMeta("preventDispatch") && !this.hasCustomState) {
1528
+ view.dispatch(tr);
1529
+ }
1530
+ return callback;
1531
+ };
1532
+ return [name, method];
1533
+ })
1534
+ );
1535
+ }
1536
+ get chain() {
1537
+ return () => this.createChain();
1538
+ }
1539
+ get can() {
1540
+ return () => this.createCan();
1541
+ }
1542
+ createChain(startTr, shouldDispatch = true) {
1543
+ const { rawCommands, editor, state } = this;
1544
+ const { view } = editor;
1545
+ const callbacks = [];
1546
+ const hasStartTransaction = !!startTr;
1547
+ const tr = startTr || state.tr;
1548
+ const run3 = () => {
1549
+ if (!hasStartTransaction && shouldDispatch && !tr.getMeta("preventDispatch") && !this.hasCustomState) {
1550
+ view.dispatch(tr);
1551
+ }
1552
+ return callbacks.every((callback) => callback === true);
1553
+ };
1554
+ const chain = {
1555
+ ...Object.fromEntries(
1556
+ Object.entries(rawCommands).map(([name, command2]) => {
1557
+ const chainedCommand = (...args) => {
1558
+ const props = this.buildProps(tr, shouldDispatch);
1559
+ const callback = command2(...args)(props);
1560
+ callbacks.push(callback);
1561
+ return chain;
1562
+ };
1563
+ return [name, chainedCommand];
1564
+ })
1565
+ ),
1566
+ run: run3
1567
+ };
1568
+ return chain;
1569
+ }
1570
+ createCan(startTr) {
1571
+ const { rawCommands, state } = this;
1572
+ const dispatch = false;
1573
+ const tr = startTr || state.tr;
1574
+ const props = this.buildProps(tr, dispatch);
1575
+ const formattedCommands = Object.fromEntries(
1576
+ Object.entries(rawCommands).map(([name, command2]) => {
1577
+ return [name, (...args) => command2(...args)({ ...props, dispatch: void 0 })];
1578
+ })
1579
+ );
1580
+ return {
1581
+ ...formattedCommands,
1582
+ chain: () => this.createChain(tr, dispatch)
1583
+ };
1584
+ }
1585
+ buildProps(tr, shouldDispatch = true) {
1586
+ const { rawCommands, editor, state } = this;
1587
+ const { view } = editor;
1588
+ const props = {
1589
+ tr,
1590
+ editor,
1591
+ view,
1592
+ state: createChainableState({
1593
+ state,
1594
+ transaction: tr
1595
+ }),
1596
+ dispatch: shouldDispatch ? () => void 0 : void 0,
1597
+ chain: () => this.createChain(tr, shouldDispatch),
1598
+ can: () => this.createCan(tr),
1599
+ get commands() {
1600
+ return Object.fromEntries(
1601
+ Object.entries(rawCommands).map(([name, command2]) => {
1602
+ return [name, (...args) => command2(...args)(props)];
1603
+ })
1604
+ );
1605
+ }
1606
+ };
1607
+ return props;
1608
+ }
1609
+ };
1610
+ var commands_exports = {};
1611
+ __export(commands_exports, {
1612
+ blur: () => blur,
1613
+ clearContent: () => clearContent,
1614
+ clearNodes: () => clearNodes,
1615
+ command: () => command,
1616
+ createParagraphNear: () => createParagraphNear,
1617
+ cut: () => cut,
1618
+ deleteCurrentNode: () => deleteCurrentNode,
1619
+ deleteNode: () => deleteNode,
1620
+ deleteRange: () => deleteRange,
1621
+ deleteSelection: () => deleteSelection,
1622
+ enter: () => enter,
1623
+ exitCode: () => exitCode,
1624
+ extendMarkRange: () => extendMarkRange,
1625
+ first: () => first,
1626
+ focus: () => focus,
1627
+ forEach: () => forEach,
1628
+ insertContent: () => insertContent,
1629
+ insertContentAt: () => insertContentAt,
1630
+ joinBackward: () => joinBackward,
1631
+ joinDown: () => joinDown,
1632
+ joinForward: () => joinForward,
1633
+ joinItemBackward: () => joinItemBackward,
1634
+ joinItemForward: () => joinItemForward,
1635
+ joinTextblockBackward: () => joinTextblockBackward,
1636
+ joinTextblockForward: () => joinTextblockForward,
1637
+ joinUp: () => joinUp,
1638
+ keyboardShortcut: () => keyboardShortcut,
1639
+ lift: () => lift,
1640
+ liftEmptyBlock: () => liftEmptyBlock,
1641
+ liftListItem: () => liftListItem,
1642
+ newlineInCode: () => newlineInCode,
1643
+ resetAttributes: () => resetAttributes,
1644
+ scrollIntoView: () => scrollIntoView,
1645
+ selectAll: () => selectAll,
1646
+ selectNodeBackward: () => selectNodeBackward,
1647
+ selectNodeForward: () => selectNodeForward,
1648
+ selectParentNode: () => selectParentNode,
1649
+ selectTextblockEnd: () => selectTextblockEnd,
1650
+ selectTextblockStart: () => selectTextblockStart,
1651
+ setContent: () => setContent,
1652
+ setMark: () => setMark,
1653
+ setMeta: () => setMeta,
1654
+ setNode: () => setNode,
1655
+ setNodeSelection: () => setNodeSelection,
1656
+ setTextDirection: () => setTextDirection,
1657
+ setTextSelection: () => setTextSelection,
1658
+ sinkListItem: () => sinkListItem,
1659
+ splitBlock: () => splitBlock,
1660
+ splitListItem: () => splitListItem,
1661
+ toggleList: () => toggleList,
1662
+ toggleMark: () => toggleMark,
1663
+ toggleNode: () => toggleNode,
1664
+ toggleWrap: () => toggleWrap,
1665
+ undoInputRule: () => undoInputRule,
1666
+ unsetAllMarks: () => unsetAllMarks,
1667
+ unsetMark: () => unsetMark,
1668
+ unsetTextDirection: () => unsetTextDirection,
1669
+ updateAttributes: () => updateAttributes,
1670
+ wrapIn: () => wrapIn,
1671
+ wrapInList: () => wrapInList
1672
+ });
1673
+ var blur = () => ({ editor, view }) => {
1674
+ requestAnimationFrame(() => {
1675
+ var _a;
1676
+ if (!editor.isDestroyed) {
1677
+ view.dom.blur();
1678
+ (_a = window == null ? void 0 : window.getSelection()) == null ? void 0 : _a.removeAllRanges();
1679
+ }
1680
+ });
1681
+ return true;
1682
+ };
1683
+ var clearContent = (emitUpdate = true) => ({ commands }) => {
1684
+ return commands.setContent("", { emitUpdate });
1685
+ };
1686
+ var clearNodes = () => ({ state, tr, dispatch }) => {
1687
+ const { selection } = tr;
1688
+ const { ranges } = selection;
1689
+ if (!dispatch) {
1690
+ return true;
1691
+ }
1692
+ ranges.forEach(({ $from, $to }) => {
1693
+ state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
1694
+ if (node.type.isText) {
1695
+ return;
1696
+ }
1697
+ const { doc, mapping } = tr;
1698
+ const $mappedFrom = doc.resolve(mapping.map(pos));
1699
+ const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
1700
+ const nodeRange = $mappedFrom.blockRange($mappedTo);
1701
+ if (!nodeRange) {
1702
+ return;
1703
+ }
1704
+ const targetLiftDepth = transform.liftTarget(nodeRange);
1705
+ if (node.type.isTextblock) {
1706
+ const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
1707
+ tr.setNodeMarkup(nodeRange.start, defaultType);
1708
+ }
1709
+ if (targetLiftDepth || targetLiftDepth === 0) {
1710
+ tr.lift(nodeRange, targetLiftDepth);
1711
+ }
1712
+ });
1713
+ });
1714
+ return true;
1715
+ };
1716
+ var command = (fn) => (props) => {
1717
+ return fn(props);
1718
+ };
1719
+ var createParagraphNear = () => ({ state, dispatch }) => {
1720
+ return commands.createParagraphNear(state, dispatch);
1721
+ };
1722
+ var cut = (originRange, targetPos) => ({ editor, tr }) => {
1723
+ const { state: state$1 } = editor;
1724
+ const contentSlice = state$1.doc.slice(originRange.from, originRange.to);
1725
+ tr.deleteRange(originRange.from, originRange.to);
1726
+ const newPos = tr.mapping.map(targetPos);
1727
+ tr.insert(newPos, contentSlice.content);
1728
+ tr.setSelection(new state.TextSelection(tr.doc.resolve(Math.max(newPos - 1, 0))));
1729
+ return true;
1730
+ };
1731
+ var deleteCurrentNode = () => ({ tr, dispatch }) => {
1732
+ const { selection } = tr;
1733
+ const currentNode = selection.$anchor.node();
1734
+ if (currentNode.content.size > 0) {
1735
+ return false;
1736
+ }
1737
+ const $pos = tr.selection.$anchor;
1738
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
1739
+ const node = $pos.node(depth);
1740
+ if (node.type === currentNode.type) {
1741
+ if (dispatch) {
1742
+ const from = $pos.before(depth);
1743
+ const to = $pos.after(depth);
1744
+ tr.delete(from, to).scrollIntoView();
1745
+ }
1746
+ return true;
1747
+ }
1748
+ }
1749
+ return false;
1750
+ };
1751
+ function getNodeType(nameOrType, schema) {
1752
+ if (typeof nameOrType === "string") {
1753
+ if (!schema.nodes[nameOrType]) {
1754
+ throw Error(
1755
+ `There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`
1756
+ );
1757
+ }
1758
+ return schema.nodes[nameOrType];
1759
+ }
1760
+ return nameOrType;
1761
+ }
1762
+ var deleteNode = (typeOrName) => ({ tr, state, dispatch }) => {
1763
+ const type = getNodeType(typeOrName, state.schema);
1764
+ const $pos = tr.selection.$anchor;
1765
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
1766
+ const node = $pos.node(depth);
1767
+ if (node.type === type) {
1768
+ if (dispatch) {
1769
+ const from = $pos.before(depth);
1770
+ const to = $pos.after(depth);
1771
+ tr.delete(from, to).scrollIntoView();
1772
+ }
1773
+ return true;
1774
+ }
1775
+ }
1776
+ return false;
1777
+ };
1778
+ var deleteRange = (range) => ({ tr, dispatch }) => {
1779
+ const { from, to } = range;
1780
+ if (dispatch) {
1781
+ tr.delete(from, to);
1782
+ }
1783
+ return true;
1784
+ };
1785
+ var hasTextContent = (nodeSpec) => {
1786
+ if (!nodeSpec.content) {
1787
+ return false;
1788
+ }
1789
+ const textRegex = /^text(\*|\+)/;
1790
+ return textRegex.test(nodeSpec.content);
1791
+ };
1792
+ var expandSelectionForSide = ($pos, schema, side) => {
1793
+ if (!$pos.parent.isInline) {
1794
+ return $pos.pos;
1795
+ }
1796
+ if (side === "left" && $pos.pos > $pos.start() || side === "right" && $pos.pos < $pos.end()) {
1797
+ return $pos.pos;
1798
+ }
1799
+ const parentContent = schema.nodes[$pos.parent.type.name].spec;
1800
+ if (!hasTextContent(parentContent)) {
1801
+ return $pos.pos;
1802
+ }
1803
+ return side === "left" ? $pos.start() - 1 : $pos.end() + 1;
1804
+ };
1805
+ var expandSelectionForInlineText = ($from, $to, schema) => {
1806
+ const from = expandSelectionForSide($from, schema, "left");
1807
+ const to = expandSelectionForSide($to, schema, "right");
1808
+ return { from, to };
1809
+ };
1810
+ var deleteSelection = () => ({ state, dispatch }) => {
1811
+ const { $from, $to } = state.selection;
1812
+ if (state.selection.empty) {
1813
+ return false;
1814
+ }
1815
+ const { from, to } = expandSelectionForInlineText($from, $to, state.schema);
1816
+ if (dispatch) {
1817
+ state.tr.deleteRange(from, to).scrollIntoView();
1818
+ dispatch(state.tr);
1819
+ }
1820
+ return true;
1821
+ };
1822
+ var enter = () => ({ commands }) => {
1823
+ return commands.keyboardShortcut("Enter");
1824
+ };
1825
+ var exitCode = () => ({ state, dispatch }) => {
1826
+ return commands.exitCode(state, dispatch);
1827
+ };
1828
+ function isRegExp(value) {
1829
+ return Object.prototype.toString.call(value) === "[object RegExp]";
1830
+ }
1831
+ function objectIncludes(object1, object2, options = { strict: true }) {
1832
+ const keys = Object.keys(object2);
1833
+ if (!keys.length) {
1834
+ return true;
1835
+ }
1836
+ return keys.every((key) => {
1837
+ if (options.strict) {
1838
+ return object2[key] === object1[key];
1839
+ }
1840
+ if (isRegExp(object2[key])) {
1841
+ return object2[key].test(object1[key]);
1842
+ }
1843
+ return object2[key] === object1[key];
1844
+ });
1845
+ }
1846
+ function findMarkInSet(marks, type, attributes = {}) {
1847
+ return marks.find((item) => {
1848
+ return item.type === type && objectIncludes(
1849
+ // Only check equality for the attributes that are provided
1850
+ Object.fromEntries(Object.keys(attributes).map((k) => [k, item.attrs[k]])),
1851
+ attributes
1852
+ );
1853
+ });
1854
+ }
1855
+ function isMarkInSet(marks, type, attributes = {}) {
1856
+ return !!findMarkInSet(marks, type, attributes);
1857
+ }
1858
+ function getMarkRange($pos, type, attributes) {
1859
+ if (!$pos || !type) {
1860
+ return;
1861
+ }
1862
+ let start = $pos.parent.childAfter($pos.parentOffset);
1863
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
1864
+ start = $pos.parent.childBefore($pos.parentOffset);
1865
+ }
1866
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
1867
+ return;
1868
+ }
1869
+ if (!attributes) {
1870
+ const firstMark = start.node.marks.find((mark2) => mark2.type === type);
1871
+ if (firstMark) {
1872
+ attributes = firstMark.attrs;
1873
+ }
1874
+ }
1875
+ const mark = findMarkInSet([...start.node.marks], type, attributes);
1876
+ if (!mark) {
1877
+ return;
1878
+ }
1879
+ let startIndex = start.index;
1880
+ let startPos = $pos.start() + start.offset;
1881
+ let endIndex = startIndex + 1;
1882
+ let endPos = startPos + start.node.nodeSize;
1883
+ while (startIndex > 0 && isMarkInSet([...$pos.parent.child(startIndex - 1).marks], type, attributes)) {
1884
+ startIndex -= 1;
1885
+ startPos -= $pos.parent.child(startIndex).nodeSize;
1886
+ }
1887
+ while (endIndex < $pos.parent.childCount && isMarkInSet([...$pos.parent.child(endIndex).marks], type, attributes)) {
1888
+ endPos += $pos.parent.child(endIndex).nodeSize;
1889
+ endIndex += 1;
1890
+ }
1891
+ return {
1892
+ from: startPos,
1893
+ to: endPos
1894
+ };
1895
+ }
1896
+ function getMarkType(nameOrType, schema) {
1897
+ if (typeof nameOrType === "string") {
1898
+ if (!schema.marks[nameOrType]) {
1899
+ throw Error(
1900
+ `There is no mark type named '${nameOrType}'. Maybe you forgot to add the extension?`
1901
+ );
1902
+ }
1903
+ return schema.marks[nameOrType];
1904
+ }
1905
+ return nameOrType;
1906
+ }
1907
+ var extendMarkRange = (typeOrName, attributes) => ({ tr, state: state$1, dispatch }) => {
1908
+ const type = getMarkType(typeOrName, state$1.schema);
1909
+ const { doc, selection } = tr;
1910
+ const { $from, from, to } = selection;
1911
+ if (dispatch) {
1912
+ const range = getMarkRange($from, type, attributes);
1913
+ if (range && range.from <= from && range.to >= to) {
1914
+ const newSelection = state.TextSelection.create(doc, range.from, range.to);
1915
+ tr.setSelection(newSelection);
1916
+ }
1917
+ }
1918
+ return true;
1919
+ };
1920
+ var first = (commands) => (props) => {
1921
+ const items = typeof commands === "function" ? commands(props) : commands;
1922
+ for (let i = 0; i < items.length; i += 1) {
1923
+ if (items[i](props)) {
1924
+ return true;
1925
+ }
1926
+ }
1927
+ return false;
1928
+ };
1929
+ function isTextSelection(value) {
1930
+ return value instanceof state.TextSelection;
1931
+ }
1932
+ function minMax(value = 0, min = 0, max = 0) {
1933
+ return Math.min(Math.max(value, min), max);
1934
+ }
1935
+ function resolveFocusPosition(doc, position = null) {
1936
+ if (!position) {
1937
+ return null;
1938
+ }
1939
+ const selectionAtStart = state.Selection.atStart(doc);
1940
+ const selectionAtEnd = state.Selection.atEnd(doc);
1941
+ if (position === "start" || position === true) {
1942
+ return selectionAtStart;
1943
+ }
1944
+ if (position === "end") {
1945
+ return selectionAtEnd;
1946
+ }
1947
+ const minPos = selectionAtStart.from;
1948
+ const maxPos = selectionAtEnd.to;
1949
+ if (position === "all") {
1950
+ return state.TextSelection.create(
1951
+ doc,
1952
+ minMax(0, minPos, maxPos),
1953
+ minMax(doc.content.size, minPos, maxPos)
1954
+ );
1955
+ }
1956
+ return state.TextSelection.create(
1957
+ doc,
1958
+ minMax(position, minPos, maxPos),
1959
+ minMax(position, minPos, maxPos)
1960
+ );
1961
+ }
1962
+ function isAndroid() {
1963
+ return navigator.platform === "Android" || /android/i.test(navigator.userAgent);
1964
+ }
1965
+ function isiOS() {
1966
+ return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(
1967
+ navigator.platform
1968
+ ) || // iPad on iOS 13 detection
1969
+ navigator.userAgent.includes("Mac") && "ontouchend" in document;
1970
+ }
1971
+ function isSafari() {
1972
+ return typeof navigator !== "undefined" ? /^((?!chrome|android).)*safari/i.test(navigator.userAgent) : false;
1973
+ }
1974
+ var focus = (position = null, options = {}) => ({ editor, view, tr, dispatch }) => {
1975
+ options = {
1976
+ scrollIntoView: true,
1977
+ ...options
1978
+ };
1979
+ const delayedFocus = () => {
1980
+ if (isiOS() || isAndroid()) {
1981
+ view.dom.focus();
1982
+ }
1983
+ if (isSafari() && !isiOS() && !isAndroid()) {
1984
+ view.dom.focus({ preventScroll: true });
1985
+ }
1986
+ requestAnimationFrame(() => {
1987
+ if (!editor.isDestroyed) {
1988
+ view.focus();
1989
+ if (options == null ? void 0 : options.scrollIntoView) {
1990
+ editor.commands.scrollIntoView();
1991
+ }
1992
+ }
1993
+ });
1994
+ };
1995
+ try {
1996
+ if (view.hasFocus() && position === null || position === false) {
1997
+ return true;
1998
+ }
1999
+ } catch {
2000
+ return false;
2001
+ }
2002
+ if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
2003
+ delayedFocus();
2004
+ return true;
2005
+ }
2006
+ const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection;
2007
+ const isSameSelection = editor.state.selection.eq(selection);
2008
+ if (dispatch) {
2009
+ if (!isSameSelection) {
2010
+ tr.setSelection(selection);
2011
+ }
2012
+ if (isSameSelection && tr.storedMarks) {
2013
+ tr.setStoredMarks(tr.storedMarks);
2014
+ }
2015
+ delayedFocus();
2016
+ }
2017
+ return true;
2018
+ };
2019
+ var forEach = (items, fn) => (props) => {
2020
+ return items.every((item, index) => fn(item, { ...props, index }));
2021
+ };
2022
+ var insertContent = (value, options) => ({ tr, commands }) => {
2023
+ return commands.insertContentAt(
2024
+ { from: tr.selection.from, to: tr.selection.to },
2025
+ value,
2026
+ options
2027
+ );
2028
+ };
2029
+ var removeWhitespaces = (node) => {
2030
+ const children = node.childNodes;
2031
+ for (let i = children.length - 1; i >= 0; i -= 1) {
2032
+ const child = children[i];
2033
+ if (child.nodeType === 3 && child.nodeValue && /^(\n\s\s|\n)$/.test(child.nodeValue)) {
2034
+ node.removeChild(child);
2035
+ } else if (child.nodeType === 1) {
2036
+ removeWhitespaces(child);
2037
+ }
2038
+ }
2039
+ return node;
2040
+ };
2041
+ function elementFromString(value) {
2042
+ if (typeof window === "undefined") {
2043
+ throw new Error(
2044
+ "[tiptap error]: there is no window object available, so this function cannot be used"
2045
+ );
2046
+ }
2047
+ const wrappedValue = `<body>${value}</body>`;
2048
+ const html = new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
2049
+ return removeWhitespaces(html);
2050
+ }
2051
+ function createNodeFromContent(content, schema, options) {
2052
+ if (content instanceof model.Node || content instanceof model.Fragment) {
2053
+ return content;
2054
+ }
2055
+ options = {
2056
+ slice: true,
2057
+ parseOptions: {},
2058
+ ...options
2059
+ };
2060
+ const isJSONContent = typeof content === "object" && content !== null;
2061
+ const isTextContent = typeof content === "string";
2062
+ if (isJSONContent) {
2063
+ try {
2064
+ const isArrayContent = Array.isArray(content) && content.length > 0;
2065
+ if (isArrayContent) {
2066
+ return model.Fragment.fromArray(content.map((item) => schema.nodeFromJSON(item)));
2067
+ }
2068
+ const node = schema.nodeFromJSON(content);
2069
+ if (options.errorOnInvalidContent) {
2070
+ node.check();
2071
+ }
2072
+ return node;
2073
+ } catch (error) {
2074
+ if (options.errorOnInvalidContent) {
2075
+ throw new Error("[tiptap error]: Invalid JSON content", { cause: error });
2076
+ }
2077
+ console.warn("[tiptap warn]: Invalid content.", "Passed value:", content, "Error:", error);
2078
+ return createNodeFromContent("", schema, options);
2079
+ }
2080
+ }
2081
+ if (isTextContent) {
2082
+ if (options.errorOnInvalidContent) {
2083
+ let hasInvalidContent = false;
2084
+ let invalidContent = "";
2085
+ const contentCheckSchema = new model.Schema({
2086
+ topNode: schema.spec.topNode,
2087
+ marks: schema.spec.marks,
2088
+ // Prosemirror's schemas are executed such that: the last to execute, matches last
2089
+ // 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
2090
+ nodes: schema.spec.nodes.append({
2091
+ __tiptap__private__unknown__catch__all__node: {
2092
+ content: "inline*",
2093
+ group: "block",
2094
+ parseDOM: [
2095
+ {
2096
+ tag: "*",
2097
+ getAttrs: (e) => {
2098
+ hasInvalidContent = true;
2099
+ invalidContent = typeof e === "string" ? e : e.outerHTML;
2100
+ return null;
2101
+ }
2102
+ }
2103
+ ]
2104
+ }
2105
+ })
2106
+ });
2107
+ if (options.slice) {
2108
+ model.DOMParser.fromSchema(contentCheckSchema).parseSlice(
2109
+ elementFromString(content),
2110
+ options.parseOptions
2111
+ );
2112
+ } else {
2113
+ model.DOMParser.fromSchema(contentCheckSchema).parse(
2114
+ elementFromString(content),
2115
+ options.parseOptions
2116
+ );
2117
+ }
2118
+ if (options.errorOnInvalidContent && hasInvalidContent) {
2119
+ throw new Error("[tiptap error]: Invalid HTML content", {
2120
+ cause: new Error(`Invalid element found: ${invalidContent}`)
2121
+ });
2122
+ }
2123
+ }
2124
+ const parser = model.DOMParser.fromSchema(schema);
2125
+ if (options.slice) {
2126
+ return parser.parseSlice(elementFromString(content), options.parseOptions).content;
2127
+ }
2128
+ return parser.parse(elementFromString(content), options.parseOptions);
2129
+ }
2130
+ return createNodeFromContent("", schema, options);
2131
+ }
2132
+ function selectionToInsertionEnd(tr, startLen, bias) {
2133
+ const last = tr.steps.length - 1;
2134
+ if (last < startLen) {
2135
+ return;
2136
+ }
2137
+ const step = tr.steps[last];
2138
+ if (!(step instanceof transform.ReplaceStep || step instanceof transform.ReplaceAroundStep)) {
2139
+ return;
2140
+ }
2141
+ const map = tr.mapping.maps[last];
2142
+ let end = 0;
2143
+ map.forEach((_from, _to, _newFrom, newTo) => {
2144
+ if (end === 0) {
2145
+ end = newTo;
2146
+ }
2147
+ });
2148
+ tr.setSelection(state.Selection.near(tr.doc.resolve(end), bias));
2149
+ }
2150
+ var isFragment = (nodeOrFragment) => {
2151
+ return !("type" in nodeOrFragment);
2152
+ };
2153
+ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) => {
2154
+ var _a;
2155
+ if (dispatch) {
2156
+ options = {
2157
+ parseOptions: editor.options.parseOptions,
2158
+ updateSelection: true,
2159
+ applyInputRules: false,
2160
+ applyPasteRules: false,
2161
+ ...options
2162
+ };
2163
+ let content;
2164
+ const emitContentError = (error) => {
2165
+ editor.emit("contentError", {
2166
+ editor,
2167
+ error,
2168
+ disableCollaboration: () => {
2169
+ if ("collaboration" in editor.storage && typeof editor.storage.collaboration === "object" && editor.storage.collaboration) {
2170
+ editor.storage.collaboration.isDisabled = true;
2171
+ }
2172
+ }
2173
+ });
2174
+ };
2175
+ const parseOptions = {
2176
+ preserveWhitespace: "full",
2177
+ ...options.parseOptions
2178
+ };
2179
+ if (!options.errorOnInvalidContent && !editor.options.enableContentCheck && editor.options.emitContentError) {
2180
+ try {
2181
+ createNodeFromContent(value, editor.schema, {
2182
+ parseOptions,
2183
+ errorOnInvalidContent: true
2184
+ });
2185
+ } catch (e) {
2186
+ emitContentError(e);
2187
+ }
2188
+ }
2189
+ try {
2190
+ content = createNodeFromContent(value, editor.schema, {
2191
+ parseOptions,
2192
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) != null ? _a : editor.options.enableContentCheck
2193
+ });
2194
+ } catch (e) {
2195
+ emitContentError(e);
2196
+ return false;
2197
+ }
2198
+ let { from, to } = typeof position === "number" ? { from: position, to: position } : { from: position.from, to: position.to };
2199
+ let isOnlyTextContent = true;
2200
+ let isOnlyBlockContent = true;
2201
+ const nodes = isFragment(content) ? content : [content];
2202
+ nodes.forEach((node) => {
2203
+ node.check();
2204
+ isOnlyTextContent = isOnlyTextContent ? node.isText && node.marks.length === 0 : false;
2205
+ isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;
2206
+ });
2207
+ if (from === to && isOnlyBlockContent) {
2208
+ const { parent } = tr.doc.resolve(from);
2209
+ const isEmptyTextBlock = parent.isTextblock && !parent.type.spec.code && !parent.childCount;
2210
+ if (isEmptyTextBlock) {
2211
+ from -= 1;
2212
+ to += 1;
2213
+ }
2214
+ }
2215
+ let newContent;
2216
+ if (isOnlyTextContent) {
2217
+ if (Array.isArray(value)) {
2218
+ newContent = value.map((v) => v.text || "").join("");
2219
+ } else if (value instanceof model.Fragment) {
2220
+ let text = "";
2221
+ value.forEach((node) => {
2222
+ if (node.text) {
2223
+ text += node.text;
2224
+ }
2225
+ });
2226
+ newContent = text;
2227
+ } else if (typeof value === "object" && !!value && !!value.text) {
2228
+ newContent = value.text;
2229
+ } else {
2230
+ newContent = value;
2231
+ }
2232
+ tr.insertText(newContent, from, to);
2233
+ } else {
2234
+ newContent = content;
2235
+ const $from = tr.doc.resolve(from);
2236
+ const $fromNode = $from.node();
2237
+ const fromSelectionAtStart = $from.parentOffset === 0;
2238
+ const isTextSelection2 = $fromNode.isText || $fromNode.isTextblock;
2239
+ const hasContent = $fromNode.content.size > 0;
2240
+ if (fromSelectionAtStart && isTextSelection2 && hasContent && isOnlyBlockContent) {
2241
+ from = Math.max(0, from - 1);
2242
+ }
2243
+ tr.replaceWith(from, to, newContent);
2244
+ }
2245
+ if (options.updateSelection) {
2246
+ selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
2247
+ }
2248
+ if (options.applyInputRules) {
2249
+ tr.setMeta("applyInputRules", { from, text: newContent });
2250
+ }
2251
+ if (options.applyPasteRules) {
2252
+ tr.setMeta("applyPasteRules", { from, text: newContent });
2253
+ }
2254
+ }
2255
+ return true;
2256
+ };
2257
+ var joinUp = () => ({ state, dispatch }) => {
2258
+ return commands.joinUp(state, dispatch);
2259
+ };
2260
+ var joinDown = () => ({ state, dispatch }) => {
2261
+ return commands.joinDown(state, dispatch);
2262
+ };
2263
+ var joinBackward = () => ({ state, dispatch }) => {
2264
+ return commands.joinBackward(state, dispatch);
2265
+ };
2266
+ var joinForward = () => ({ state, dispatch }) => {
2267
+ return commands.joinForward(state, dispatch);
2268
+ };
2269
+ var joinItemBackward = () => ({ state, dispatch, tr }) => {
2270
+ try {
2271
+ const point = transform.joinPoint(state.doc, state.selection.$from.pos, -1);
2272
+ if (point === null || point === void 0) {
2273
+ return false;
2274
+ }
2275
+ tr.join(point, 2);
2276
+ if (dispatch) {
2277
+ dispatch(tr);
2278
+ }
2279
+ return true;
2280
+ } catch {
2281
+ return false;
2282
+ }
2283
+ };
2284
+ var joinItemForward = () => ({ state, dispatch, tr }) => {
2285
+ try {
2286
+ const point = transform.joinPoint(state.doc, state.selection.$from.pos, 1);
2287
+ if (point === null || point === void 0) {
2288
+ return false;
2289
+ }
2290
+ tr.join(point, 2);
2291
+ if (dispatch) {
2292
+ dispatch(tr);
2293
+ }
2294
+ return true;
2295
+ } catch {
2296
+ return false;
2297
+ }
2298
+ };
2299
+ var joinTextblockBackward = () => ({ state, dispatch }) => {
2300
+ return commands.joinTextblockBackward(state, dispatch);
2301
+ };
2302
+ var joinTextblockForward = () => ({ state, dispatch }) => {
2303
+ return commands.joinTextblockForward(state, dispatch);
2304
+ };
2305
+ function isMacOS() {
2306
+ return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
2307
+ }
2308
+ function normalizeKeyName(name) {
2309
+ const parts = name.split(/-(?!$)/);
2310
+ let result = parts[parts.length - 1];
2311
+ if (result === "Space") {
2312
+ result = " ";
2313
+ }
2314
+ let alt;
2315
+ let ctrl;
2316
+ let shift;
2317
+ let meta;
2318
+ for (let i = 0; i < parts.length - 1; i += 1) {
2319
+ const mod = parts[i];
2320
+ if (/^(cmd|meta|m)$/i.test(mod)) {
2321
+ meta = true;
2322
+ } else if (/^a(lt)?$/i.test(mod)) {
2323
+ alt = true;
2324
+ } else if (/^(c|ctrl|control)$/i.test(mod)) {
2325
+ ctrl = true;
2326
+ } else if (/^s(hift)?$/i.test(mod)) {
2327
+ shift = true;
2328
+ } else if (/^mod$/i.test(mod)) {
2329
+ if (isiOS() || isMacOS()) {
2330
+ meta = true;
2331
+ } else {
2332
+ ctrl = true;
2333
+ }
2334
+ } else {
2335
+ throw new Error(`Unrecognized modifier name: ${mod}`);
2336
+ }
2337
+ }
2338
+ if (alt) {
2339
+ result = `Alt-${result}`;
2340
+ }
2341
+ if (ctrl) {
2342
+ result = `Ctrl-${result}`;
2343
+ }
2344
+ if (meta) {
2345
+ result = `Meta-${result}`;
2346
+ }
2347
+ if (shift) {
2348
+ result = `Shift-${result}`;
2349
+ }
2350
+ return result;
2351
+ }
2352
+ var keyboardShortcut = (name) => ({ editor, view, tr, dispatch }) => {
2353
+ const keys = normalizeKeyName(name).split(/-(?!$)/);
2354
+ const key = keys.find((item) => !["Alt", "Ctrl", "Meta", "Shift"].includes(item));
2355
+ const event = new KeyboardEvent("keydown", {
2356
+ key: key === "Space" ? " " : key,
2357
+ altKey: keys.includes("Alt"),
2358
+ ctrlKey: keys.includes("Ctrl"),
2359
+ metaKey: keys.includes("Meta"),
2360
+ shiftKey: keys.includes("Shift"),
2361
+ bubbles: true,
2362
+ cancelable: true
2363
+ });
2364
+ const capturedTransaction = editor.captureTransaction(() => {
2365
+ view.someProp("handleKeyDown", (f) => f(view, event));
2366
+ });
2367
+ capturedTransaction == null ? void 0 : capturedTransaction.steps.forEach((step) => {
2368
+ const newStep = step.map(tr.mapping);
2369
+ if (newStep && dispatch) {
2370
+ tr.maybeStep(newStep);
2371
+ }
2372
+ });
2373
+ return true;
2374
+ };
2375
+ function isNodeActive(state, typeOrName, attributes = {}) {
2376
+ const { from, to, empty } = state.selection;
2377
+ const type = typeOrName ? getNodeType(typeOrName, state.schema) : null;
2378
+ const nodeRanges = [];
2379
+ state.doc.nodesBetween(from, to, (node, pos) => {
2380
+ if (node.isText) {
2381
+ return;
2382
+ }
2383
+ const relativeFrom = Math.max(from, pos);
2384
+ const relativeTo = Math.min(to, pos + node.nodeSize);
2385
+ nodeRanges.push({
2386
+ node,
2387
+ from: relativeFrom,
2388
+ to: relativeTo
2389
+ });
2390
+ });
2391
+ const selectionRange = to - from;
2392
+ const matchedNodeRanges = nodeRanges.filter((nodeRange) => {
2393
+ if (!type) {
2394
+ return true;
2395
+ }
2396
+ return type.name === nodeRange.node.type.name;
2397
+ }).filter((nodeRange) => objectIncludes(nodeRange.node.attrs, attributes, { strict: false }));
2398
+ if (empty) {
2399
+ return !!matchedNodeRanges.length;
2400
+ }
2401
+ const range = matchedNodeRanges.reduce((sum, nodeRange) => sum + nodeRange.to - nodeRange.from, 0);
2402
+ return range >= selectionRange;
2403
+ }
2404
+ var lift = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
2405
+ const type = getNodeType(typeOrName, state.schema);
2406
+ const isActive2 = isNodeActive(state, type, attributes);
2407
+ if (!isActive2) {
2408
+ return false;
2409
+ }
2410
+ return commands.lift(state, dispatch);
2411
+ };
2412
+ var liftEmptyBlock = () => ({ state, dispatch }) => {
2413
+ return commands.liftEmptyBlock(state, dispatch);
2414
+ };
2415
+ var liftListItem = (typeOrName) => ({ state, dispatch }) => {
2416
+ const type = getNodeType(typeOrName, state.schema);
2417
+ return schemaList.liftListItem(type)(state, dispatch);
2418
+ };
2419
+ var newlineInCode = () => ({ state, dispatch }) => {
2420
+ return commands.newlineInCode(state, dispatch);
2421
+ };
2422
+ function getSchemaTypeNameByName(name, schema) {
2423
+ if (schema.nodes[name]) {
2424
+ return "node";
2425
+ }
2426
+ if (schema.marks[name]) {
2427
+ return "mark";
2428
+ }
2429
+ return null;
2430
+ }
2431
+ function deleteProps(obj, propOrProps) {
2432
+ const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
2433
+ return Object.keys(obj).reduce((newObj, prop) => {
2434
+ if (!props.includes(prop)) {
2435
+ newObj[prop] = obj[prop];
2436
+ }
2437
+ return newObj;
2438
+ }, {});
2439
+ }
2440
+ var resetAttributes = (typeOrName, attributes) => ({ tr, state, dispatch }) => {
2441
+ let nodeType = null;
2442
+ let markType = null;
2443
+ const schemaType = getSchemaTypeNameByName(
2444
+ typeof typeOrName === "string" ? typeOrName : typeOrName.name,
2445
+ state.schema
2446
+ );
2447
+ if (!schemaType) {
2448
+ return false;
2449
+ }
2450
+ if (schemaType === "node") {
2451
+ nodeType = getNodeType(typeOrName, state.schema);
2452
+ }
2453
+ if (schemaType === "mark") {
2454
+ markType = getMarkType(typeOrName, state.schema);
2455
+ }
2456
+ let canReset = false;
2457
+ tr.selection.ranges.forEach((range) => {
2458
+ state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
2459
+ if (nodeType && nodeType === node.type) {
2460
+ canReset = true;
2461
+ if (dispatch) {
2462
+ tr.setNodeMarkup(pos, void 0, deleteProps(node.attrs, attributes));
2463
+ }
2464
+ }
2465
+ if (markType && node.marks.length) {
2466
+ node.marks.forEach((mark) => {
2467
+ if (markType === mark.type) {
2468
+ canReset = true;
2469
+ if (dispatch) {
2470
+ tr.addMark(
2471
+ pos,
2472
+ pos + node.nodeSize,
2473
+ markType.create(deleteProps(mark.attrs, attributes))
2474
+ );
2475
+ }
2476
+ }
2477
+ });
2478
+ }
2479
+ });
2480
+ });
2481
+ return canReset;
2482
+ };
2483
+ var scrollIntoView = () => ({ tr, dispatch }) => {
2484
+ if (dispatch) {
2485
+ tr.scrollIntoView();
2486
+ }
2487
+ return true;
2488
+ };
2489
+ var selectAll = () => ({ tr, dispatch }) => {
2490
+ if (dispatch) {
2491
+ const selection = new state.AllSelection(tr.doc);
2492
+ tr.setSelection(selection);
2493
+ }
2494
+ return true;
2495
+ };
2496
+ var selectNodeBackward = () => ({ state, dispatch }) => {
2497
+ return commands.selectNodeBackward(state, dispatch);
2498
+ };
2499
+ var selectNodeForward = () => ({ state, dispatch }) => {
2500
+ return commands.selectNodeForward(state, dispatch);
2501
+ };
2502
+ var selectParentNode = () => ({ state, dispatch }) => {
2503
+ return commands.selectParentNode(state, dispatch);
2504
+ };
2505
+ var selectTextblockEnd = () => ({ state, dispatch }) => {
2506
+ return commands.selectTextblockEnd(state, dispatch);
2507
+ };
2508
+ var selectTextblockStart = () => ({ state, dispatch }) => {
2509
+ return commands.selectTextblockStart(state, dispatch);
2510
+ };
2511
+ function createDocument(content, schema, parseOptions = {}, options = {}) {
2512
+ return createNodeFromContent(content, schema, {
2513
+ slice: false,
2514
+ parseOptions,
2515
+ errorOnInvalidContent: options.errorOnInvalidContent
2516
+ });
2517
+ }
2518
+ var setContent = (content, { errorOnInvalidContent, emitUpdate = true, parseOptions = {} } = {}) => ({ editor, tr, dispatch, commands }) => {
2519
+ const { doc } = tr;
2520
+ if (parseOptions.preserveWhitespace !== "full") {
2521
+ const document2 = createDocument(content, editor.schema, parseOptions, {
2522
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
2523
+ });
2524
+ if (dispatch) {
2525
+ tr.replaceWith(0, doc.content.size, document2).setMeta("preventUpdate", !emitUpdate);
2526
+ }
2527
+ return true;
2528
+ }
2529
+ if (dispatch) {
2530
+ tr.setMeta("preventUpdate", !emitUpdate);
2531
+ }
2532
+ return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
2533
+ parseOptions,
2534
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
2535
+ });
2536
+ };
2537
+ function getMarkAttributes(state, typeOrName) {
2538
+ const type = getMarkType(typeOrName, state.schema);
2539
+ const { from, to, empty } = state.selection;
2540
+ const marks = [];
2541
+ if (empty) {
2542
+ if (state.storedMarks) {
2543
+ marks.push(...state.storedMarks);
2544
+ }
2545
+ marks.push(...state.selection.$head.marks());
2546
+ } else {
2547
+ state.doc.nodesBetween(from, to, (node) => {
2548
+ marks.push(...node.marks);
2549
+ });
2550
+ }
2551
+ const mark = marks.find((markItem) => markItem.type.name === type.name);
2552
+ if (!mark) {
2553
+ return {};
2554
+ }
2555
+ return { ...mark.attrs };
2556
+ }
2557
+ function combineTransactionSteps(oldDoc, transactions) {
2558
+ const transform$1 = new transform.Transform(oldDoc);
2559
+ transactions.forEach((transaction) => {
2560
+ transaction.steps.forEach((step) => {
2561
+ transform$1.step(step);
2562
+ });
2563
+ });
2564
+ return transform$1;
2565
+ }
2566
+ function defaultBlockAt(match) {
2567
+ for (let i = 0; i < match.edgeCount; i += 1) {
2568
+ const { type } = match.edge(i);
2569
+ if (type.isTextblock && !type.hasRequiredAttrs()) {
2570
+ return type;
2571
+ }
2572
+ }
2573
+ return null;
2574
+ }
2575
+ function findParentNodeClosestToPos($pos, predicate) {
2576
+ for (let i = $pos.depth; i > 0; i -= 1) {
2577
+ const node = $pos.node(i);
2578
+ if (predicate(node)) {
2579
+ return {
2580
+ pos: i > 0 ? $pos.before(i) : 0,
2581
+ start: $pos.start(i),
2582
+ depth: i,
2583
+ node
2584
+ };
2585
+ }
2586
+ }
2587
+ }
2588
+ function findParentNode(predicate) {
2589
+ return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
2590
+ }
2591
+ function getExtensionField(extension, field, context) {
2592
+ if (extension.config[field] === void 0 && extension.parent) {
2593
+ return getExtensionField(extension.parent, field, context);
2594
+ }
2595
+ if (typeof extension.config[field] === "function") {
2596
+ const value = extension.config[field].bind({
2597
+ ...context,
2598
+ parent: extension.parent ? getExtensionField(extension.parent, field, context) : null
2599
+ });
2600
+ return value;
2601
+ }
2602
+ return extension.config[field];
2603
+ }
2604
+ function isFunction(value) {
2605
+ return typeof value === "function";
2606
+ }
2607
+ function callOrReturn(value, context = void 0, ...props) {
2608
+ if (isFunction(value)) {
2609
+ if (context) {
2610
+ return value.bind(context)(...props);
2611
+ }
2612
+ return value(...props);
2613
+ }
2614
+ return value;
2615
+ }
2616
+ function splitExtensions(extensions) {
2617
+ const baseExtensions = extensions.filter(
2618
+ (extension) => extension.type === "extension"
2619
+ );
2620
+ const nodeExtensions = extensions.filter((extension) => extension.type === "node");
2621
+ const markExtensions = extensions.filter((extension) => extension.type === "mark");
2622
+ return {
2623
+ baseExtensions,
2624
+ nodeExtensions,
2625
+ markExtensions
2626
+ };
2627
+ }
2628
+ function splitStyleDeclarations(styles) {
2629
+ const result = [];
2630
+ let current = "";
2631
+ let inSingleQuote = false;
2632
+ let inDoubleQuote = false;
2633
+ let parenDepth = 0;
2634
+ const length = styles.length;
2635
+ for (let i = 0; i < length; i += 1) {
2636
+ const char = styles[i];
2637
+ if (char === "'" && !inDoubleQuote) {
2638
+ inSingleQuote = !inSingleQuote;
2639
+ current += char;
2640
+ continue;
2641
+ }
2642
+ if (char === '"' && !inSingleQuote) {
2643
+ inDoubleQuote = !inDoubleQuote;
2644
+ current += char;
2645
+ continue;
2646
+ }
2647
+ if (!inSingleQuote && !inDoubleQuote) {
2648
+ if (char === "(") {
2649
+ parenDepth += 1;
2650
+ current += char;
2651
+ continue;
2652
+ }
2653
+ if (char === ")" && parenDepth > 0) {
2654
+ parenDepth -= 1;
2655
+ current += char;
2656
+ continue;
2657
+ }
2658
+ if (char === ";" && parenDepth === 0) {
2659
+ result.push(current);
2660
+ current = "";
2661
+ continue;
2662
+ }
2663
+ }
2664
+ current += char;
2665
+ }
2666
+ if (current) {
2667
+ result.push(current);
2668
+ }
2669
+ return result;
2670
+ }
2671
+ function parseStyleEntries(styles) {
2672
+ const pairs = [];
2673
+ const declarations = splitStyleDeclarations(styles || "");
2674
+ const numDeclarations = declarations.length;
2675
+ for (let i = 0; i < numDeclarations; i += 1) {
2676
+ const declaration = declarations[i];
2677
+ const firstColonIndex = declaration.indexOf(":");
2678
+ if (firstColonIndex === -1) {
2679
+ continue;
2680
+ }
2681
+ const property = declaration.slice(0, firstColonIndex).trim();
2682
+ const value = declaration.slice(firstColonIndex + 1).trim();
2683
+ if (property && value) {
2684
+ pairs.push([property, value]);
2685
+ }
2686
+ }
2687
+ return pairs;
2688
+ }
2689
+ function mergeAttributes(...objects) {
2690
+ return objects.filter((item) => !!item).reduce((items, item) => {
2691
+ const mergedAttributes = { ...items };
2692
+ Object.entries(item).forEach(([key, value]) => {
2693
+ const exists = mergedAttributes[key];
2694
+ if (!exists) {
2695
+ mergedAttributes[key] = value;
2696
+ return;
2697
+ }
2698
+ if (key === "class") {
2699
+ const valueClasses = value ? String(value).split(" ") : [];
2700
+ const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(" ") : [];
2701
+ const insertClasses = valueClasses.filter(
2702
+ (valueClass) => !existingClasses.includes(valueClass)
2703
+ );
2704
+ mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
2705
+ } else if (key === "style") {
2706
+ const styleMap = new Map([
2707
+ ...parseStyleEntries(mergedAttributes[key]),
2708
+ ...parseStyleEntries(value)
2709
+ ]);
2710
+ mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
2711
+ } else {
2712
+ mergedAttributes[key] = value;
2713
+ }
2714
+ });
2715
+ return mergedAttributes;
2716
+ }, {});
2717
+ }
2718
+ function getTextBetween(startNode, range, options) {
2719
+ const { from, to } = range;
2720
+ const { blockSeparator = "\n\n", textSerializers = {} } = options || {};
2721
+ let text = "";
2722
+ startNode.nodesBetween(from, to, (node, pos, parent, index) => {
2723
+ var _a;
2724
+ if (node.isBlock && pos > from) {
2725
+ text += blockSeparator;
2726
+ }
2727
+ const textSerializer = textSerializers == null ? void 0 : textSerializers[node.type.name];
2728
+ if (textSerializer) {
2729
+ if (parent) {
2730
+ text += textSerializer({
2731
+ node,
2732
+ pos,
2733
+ parent,
2734
+ index,
2735
+ range
2736
+ });
2737
+ }
2738
+ return false;
2739
+ }
2740
+ if (node.isText) {
2741
+ text += (_a = node == null ? void 0 : node.text) == null ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos);
2742
+ }
2743
+ });
2744
+ return text;
2745
+ }
2746
+ function getTextSerializersFromSchema(schema) {
2747
+ return Object.fromEntries(
2748
+ Object.entries(schema.nodes).filter(([, node]) => node.spec.toText).map(([name, node]) => [name, node.spec.toText])
2749
+ );
2750
+ }
2751
+ function removeDuplicates(array, by = JSON.stringify) {
2752
+ const seen = {};
2753
+ return array.filter((item) => {
2754
+ const key = by(item);
2755
+ return Object.prototype.hasOwnProperty.call(seen, key) ? false : seen[key] = true;
2756
+ });
2757
+ }
2758
+ function simplifyChangedRanges(changes) {
2759
+ const uniqueChanges = removeDuplicates(changes);
2760
+ return uniqueChanges.length === 1 ? uniqueChanges : uniqueChanges.filter((change, index) => {
2761
+ const rest = uniqueChanges.filter((_, i) => i !== index);
2762
+ return !rest.some((otherChange) => {
2763
+ 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;
2764
+ });
2765
+ });
2766
+ }
2767
+ function getChangedRanges(transform) {
2768
+ const { mapping, steps } = transform;
2769
+ const changes = [];
2770
+ mapping.maps.forEach((stepMap, index) => {
2771
+ const ranges = [];
2772
+ if (!stepMap.ranges.length) {
2773
+ const { from, to } = steps[index];
2774
+ if (from === void 0 || to === void 0) {
2775
+ return;
2776
+ }
2777
+ ranges.push({ from, to });
2778
+ } else {
2779
+ stepMap.forEach((from, to) => {
2780
+ ranges.push({ from, to });
2781
+ });
2782
+ }
2783
+ ranges.forEach(({ from, to }) => {
2784
+ const newStart = mapping.slice(index).map(from, -1);
2785
+ const newEnd = mapping.slice(index).map(to);
2786
+ const oldStart = mapping.invert().map(newStart, -1);
2787
+ const oldEnd = mapping.invert().map(newEnd);
2788
+ changes.push({
2789
+ oldRange: {
2790
+ from: oldStart,
2791
+ to: oldEnd
2792
+ },
2793
+ newRange: {
2794
+ from: newStart,
2795
+ to: newEnd
2796
+ }
2797
+ });
2798
+ });
2799
+ });
2800
+ return simplifyChangedRanges(changes);
2801
+ }
2802
+ function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2803
+ return Object.fromEntries(
2804
+ Object.entries(attributes).filter(([name]) => {
2805
+ const extensionAttribute = extensionAttributes.find((item) => {
2806
+ return item.type === typeName && item.name === name;
2807
+ });
2808
+ if (!extensionAttribute) {
2809
+ return false;
2810
+ }
2811
+ return extensionAttribute.attribute.keepOnSplit;
2812
+ })
2813
+ );
2814
+ }
2815
+ function isMarkActive(state, typeOrName, attributes = {}) {
2816
+ const { empty, ranges } = state.selection;
2817
+ const type = typeOrName ? getMarkType(typeOrName, state.schema) : null;
2818
+ if (empty) {
2819
+ return !!(state.storedMarks || state.selection.$from.marks()).filter((mark) => {
2820
+ if (!type) {
2821
+ return true;
2822
+ }
2823
+ return type.name === mark.type.name;
2824
+ }).find((mark) => objectIncludes(mark.attrs, attributes, { strict: false }));
2825
+ }
2826
+ let selectionRange = 0;
2827
+ const markRanges = [];
2828
+ ranges.forEach(({ $from, $to }) => {
2829
+ const from = $from.pos;
2830
+ const to = $to.pos;
2831
+ state.doc.nodesBetween(from, to, (node, pos) => {
2832
+ if (type && node.inlineContent && !node.type.allowsMarkType(type)) {
2833
+ return false;
2834
+ }
2835
+ if (!node.isText && !node.marks.length) {
2836
+ return;
2837
+ }
2838
+ const relativeFrom = Math.max(from, pos);
2839
+ const relativeTo = Math.min(to, pos + node.nodeSize);
2840
+ const range2 = relativeTo - relativeFrom;
2841
+ selectionRange += range2;
2842
+ markRanges.push(
2843
+ ...node.marks.map((mark) => ({
2844
+ mark,
2845
+ from: relativeFrom,
2846
+ to: relativeTo
2847
+ }))
2848
+ );
2849
+ });
2850
+ });
2851
+ if (selectionRange === 0) {
2852
+ return false;
2853
+ }
2854
+ const matchedRange = markRanges.filter((markRange) => {
2855
+ if (!type) {
2856
+ return true;
2857
+ }
2858
+ return type.name === markRange.mark.type.name;
2859
+ }).filter((markRange) => objectIncludes(markRange.mark.attrs, attributes, { strict: false })).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
2860
+ const excludedRange = markRanges.filter((markRange) => {
2861
+ if (!type) {
2862
+ return true;
2863
+ }
2864
+ return markRange.mark.type !== type && markRange.mark.type.excludes(type);
2865
+ }).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
2866
+ const range = matchedRange > 0 ? matchedRange + excludedRange : matchedRange;
2867
+ return range >= selectionRange;
2868
+ }
2869
+ function isList(name, extensions) {
2870
+ const { nodeExtensions } = splitExtensions(extensions);
2871
+ const extension = nodeExtensions.find((item) => item.name === name);
2872
+ if (!extension) {
2873
+ return false;
2874
+ }
2875
+ const context = {
2876
+ name: extension.name,
2877
+ options: extension.options,
2878
+ storage: extension.storage
2879
+ };
2880
+ const group = callOrReturn(getExtensionField(extension, "group", context));
2881
+ if (typeof group !== "string") {
2882
+ return false;
2883
+ }
2884
+ return group.split(" ").includes("list");
2885
+ }
2886
+ function isNodeEmpty(node, {
2887
+ checkChildren = true,
2888
+ ignoreWhitespace = false
2889
+ } = {}) {
2890
+ var _a;
2891
+ if (ignoreWhitespace) {
2892
+ if (node.type.name === "hardBreak") {
2893
+ return true;
2894
+ }
2895
+ if (node.isText) {
2896
+ return !/\S/.test((_a = node.text) != null ? _a : "");
2897
+ }
2898
+ }
2899
+ if (node.isText) {
2900
+ return !node.text;
2901
+ }
2902
+ if (node.isAtom || node.isLeaf) {
2903
+ return false;
2904
+ }
2905
+ if (node.content.childCount === 0) {
2906
+ return true;
2907
+ }
2908
+ if (checkChildren) {
2909
+ let isContentEmpty = true;
2910
+ node.content.forEach((childNode) => {
2911
+ if (isContentEmpty === false) {
2912
+ return;
2913
+ }
2914
+ if (!isNodeEmpty(childNode, { ignoreWhitespace, checkChildren })) {
2915
+ isContentEmpty = false;
2916
+ }
2917
+ });
2918
+ return isContentEmpty;
2919
+ }
2920
+ return false;
2921
+ }
2922
+ function canSetMark(state, tr, newMarkType) {
2923
+ var _a;
2924
+ const { selection } = tr;
2925
+ let cursor = null;
2926
+ if (isTextSelection(selection)) {
2927
+ cursor = selection.$cursor;
2928
+ }
2929
+ if (cursor) {
2930
+ const currentMarks = (_a = state.storedMarks) != null ? _a : cursor.marks();
2931
+ const parentAllowsMarkType = cursor.parent.type.allowsMarkType(newMarkType);
2932
+ return parentAllowsMarkType && (!!newMarkType.isInSet(currentMarks) || !currentMarks.some((mark) => mark.type.excludes(newMarkType)));
2933
+ }
2934
+ const { ranges } = selection;
2935
+ return ranges.some(({ $from, $to }) => {
2936
+ let someNodeSupportsMark = $from.depth === 0 ? state.doc.inlineContent && state.doc.type.allowsMarkType(newMarkType) : false;
2937
+ state.doc.nodesBetween($from.pos, $to.pos, (node, _pos, parent) => {
2938
+ if (someNodeSupportsMark) {
2939
+ return false;
2940
+ }
2941
+ if (node.isInline) {
2942
+ const parentAllowsMarkType = !parent || parent.type.allowsMarkType(newMarkType);
2943
+ const currentMarksAllowMarkType = !!newMarkType.isInSet(node.marks) || !node.marks.some((otherMark) => otherMark.type.excludes(newMarkType));
2944
+ someNodeSupportsMark = parentAllowsMarkType && currentMarksAllowMarkType;
2945
+ }
2946
+ return !someNodeSupportsMark;
2947
+ });
2948
+ return someNodeSupportsMark;
2949
+ });
2950
+ }
2951
+ var setMark = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
2952
+ const { selection } = tr;
2953
+ const { empty, ranges } = selection;
2954
+ const type = getMarkType(typeOrName, state.schema);
2955
+ if (dispatch) {
2956
+ if (empty) {
2957
+ const oldAttributes = getMarkAttributes(state, type);
2958
+ tr.addStoredMark(
2959
+ type.create({
2960
+ ...oldAttributes,
2961
+ ...attributes
2962
+ })
2963
+ );
2964
+ } else {
2965
+ ranges.forEach((range) => {
2966
+ const from = range.$from.pos;
2967
+ const to = range.$to.pos;
2968
+ state.doc.nodesBetween(from, to, (node, pos) => {
2969
+ const trimmedFrom = Math.max(pos, from);
2970
+ const trimmedTo = Math.min(pos + node.nodeSize, to);
2971
+ const someHasMark = node.marks.find((mark) => mark.type === type);
2972
+ if (someHasMark) {
2973
+ node.marks.forEach((mark) => {
2974
+ if (type === mark.type) {
2975
+ tr.addMark(
2976
+ trimmedFrom,
2977
+ trimmedTo,
2978
+ type.create({
2979
+ ...mark.attrs,
2980
+ ...attributes
2981
+ })
2982
+ );
2983
+ }
2984
+ });
2985
+ } else {
2986
+ tr.addMark(trimmedFrom, trimmedTo, type.create(attributes));
2987
+ }
2988
+ });
2989
+ });
2990
+ }
2991
+ }
2992
+ return canSetMark(state, tr, type);
2993
+ };
2994
+ var setMeta = (key, value) => ({ tr }) => {
2995
+ tr.setMeta(key, value);
2996
+ return true;
2997
+ };
2998
+ var setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
2999
+ const type = getNodeType(typeOrName, state.schema);
3000
+ let attributesToCopy;
3001
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
3002
+ attributesToCopy = state.selection.$anchor.parent.attrs;
3003
+ }
3004
+ if (!type.isTextblock) {
3005
+ console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
3006
+ return false;
3007
+ }
3008
+ return chain().command(({ commands: commands$1 }) => {
3009
+ const canSetBlock = commands.setBlockType(type, { ...attributesToCopy, ...attributes })(state);
3010
+ if (canSetBlock) {
3011
+ return true;
3012
+ }
3013
+ return commands$1.clearNodes();
3014
+ }).command(({ state: updatedState }) => {
3015
+ return commands.setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch);
3016
+ }).run();
3017
+ };
3018
+ var setNodeSelection = (position) => ({ tr, dispatch }) => {
3019
+ if (dispatch) {
3020
+ const { doc } = tr;
3021
+ const from = minMax(position, 0, doc.content.size);
3022
+ const selection = state.NodeSelection.create(doc, from);
3023
+ tr.setSelection(selection);
3024
+ }
3025
+ return true;
3026
+ };
3027
+ var setTextDirection = (direction, position) => ({ tr, state, dispatch }) => {
3028
+ const { selection } = state;
3029
+ let from;
3030
+ let to;
3031
+ if (typeof position === "number") {
3032
+ from = position;
3033
+ to = position;
3034
+ } else if (position && "from" in position && "to" in position) {
3035
+ from = position.from;
3036
+ to = position.to;
3037
+ } else {
3038
+ from = selection.from;
3039
+ to = selection.to;
3040
+ }
3041
+ if (dispatch) {
3042
+ tr.doc.nodesBetween(from, to, (node, pos) => {
3043
+ if (node.isText) {
3044
+ return;
3045
+ }
3046
+ tr.setNodeMarkup(pos, void 0, {
3047
+ ...node.attrs,
3048
+ dir: direction
3049
+ });
3050
+ });
3051
+ }
3052
+ return true;
3053
+ };
3054
+ var setTextSelection = (position) => ({ tr, dispatch }) => {
3055
+ if (dispatch) {
3056
+ const { doc } = tr;
3057
+ const { from, to } = typeof position === "number" ? { from: position, to: position } : position;
3058
+ const minPos = state.TextSelection.atStart(doc).from;
3059
+ const maxPos = state.TextSelection.atEnd(doc).to;
3060
+ const resolvedFrom = minMax(from, minPos, maxPos);
3061
+ const resolvedEnd = minMax(to, minPos, maxPos);
3062
+ const selection = state.TextSelection.create(doc, resolvedFrom, resolvedEnd);
3063
+ tr.setSelection(selection);
3064
+ }
3065
+ return true;
3066
+ };
3067
+ var sinkListItem = (typeOrName) => ({ state, dispatch }) => {
3068
+ const type = getNodeType(typeOrName, state.schema);
3069
+ return schemaList.sinkListItem(type)(state, dispatch);
3070
+ };
3071
+ function ensureMarks(state, splittableMarks) {
3072
+ const marks = state.storedMarks || state.selection.$to.parentOffset && state.selection.$from.marks();
3073
+ if (marks) {
3074
+ const filteredMarks = marks.filter((mark) => splittableMarks == null ? void 0 : splittableMarks.includes(mark.type.name));
3075
+ state.tr.ensureMarks(filteredMarks);
3076
+ }
3077
+ }
3078
+ var splitBlock = ({ keepMarks = true } = {}) => ({ tr, state: state$1, dispatch, editor }) => {
3079
+ const { selection, doc } = tr;
3080
+ const { $from, $to } = selection;
3081
+ const extensionAttributes = editor.extensionManager.attributes;
3082
+ const newAttributes = getSplittedAttributes(
3083
+ extensionAttributes,
3084
+ $from.node().type.name,
3085
+ $from.node().attrs
3086
+ );
3087
+ if (selection instanceof state.NodeSelection && selection.node.isBlock) {
3088
+ if (!$from.parentOffset || !transform.canSplit(doc, $from.pos)) {
3089
+ return false;
3090
+ }
3091
+ if (dispatch) {
3092
+ if (keepMarks) {
3093
+ ensureMarks(state$1, editor.extensionManager.splittableMarks);
3094
+ }
3095
+ tr.split($from.pos).scrollIntoView();
3096
+ }
3097
+ return true;
3098
+ }
3099
+ if (!$from.parent.isBlock) {
3100
+ return false;
3101
+ }
3102
+ const atEnd = $to.parentOffset === $to.parent.content.size;
3103
+ const deflt = $from.depth === 0 ? void 0 : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
3104
+ let types = atEnd && deflt ? [
3105
+ {
3106
+ type: deflt,
3107
+ attrs: newAttributes
3108
+ }
3109
+ ] : void 0;
3110
+ let can = transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
3111
+ if (!types && !can && transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : void 0)) {
3112
+ can = true;
3113
+ types = deflt ? [
3114
+ {
3115
+ type: deflt,
3116
+ attrs: newAttributes
3117
+ }
3118
+ ] : void 0;
3119
+ }
3120
+ if (dispatch) {
3121
+ if (can) {
3122
+ if (selection instanceof state.TextSelection) {
3123
+ tr.deleteSelection();
3124
+ }
3125
+ tr.split(tr.mapping.map($from.pos), 1, types);
3126
+ if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
3127
+ const first2 = tr.mapping.map($from.before());
3128
+ const $first = tr.doc.resolve(first2);
3129
+ if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
3130
+ tr.setNodeMarkup(tr.mapping.map($from.before()), deflt);
3131
+ }
3132
+ }
3133
+ }
3134
+ if (keepMarks) {
3135
+ ensureMarks(state$1, editor.extensionManager.splittableMarks);
3136
+ }
3137
+ tr.scrollIntoView();
3138
+ }
3139
+ return can;
3140
+ };
3141
+ var splitListItem = (typeOrName, overrideAttrs = {}) => ({ tr, state: state$1, dispatch, editor }) => {
3142
+ var _a;
3143
+ const type = getNodeType(typeOrName, state$1.schema);
3144
+ const { $from, $to } = state$1.selection;
3145
+ const node = state$1.selection.node;
3146
+ if (node && node.isBlock || $from.depth < 2 || !$from.sameParent($to)) {
3147
+ return false;
3148
+ }
3149
+ const grandParent = $from.node(-1);
3150
+ if (grandParent.type !== type) {
3151
+ return false;
3152
+ }
3153
+ const extensionAttributes = editor.extensionManager.attributes;
3154
+ if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
3155
+ if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) {
3156
+ return false;
3157
+ }
3158
+ if (dispatch) {
3159
+ let wrap = model.Fragment.empty;
3160
+ const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
3161
+ for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
3162
+ wrap = model.Fragment.from($from.node(d).copy(wrap));
3163
+ }
3164
+ const depthAfter = (
3165
+ // oxlint-disable-next-line no-nested-ternary
3166
+ $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3
3167
+ );
3168
+ const newNextTypeAttributes2 = {
3169
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
3170
+ ...overrideAttrs
3171
+ };
3172
+ const nextType2 = ((_a = type.contentMatch.defaultType) == null ? void 0 : _a.createAndFill(newNextTypeAttributes2)) || void 0;
3173
+ wrap = wrap.append(model.Fragment.from(type.createAndFill(null, nextType2) || void 0));
3174
+ const start = $from.before($from.depth - (depthBefore - 1));
3175
+ tr.replace(start, $from.after(-depthAfter), new model.Slice(wrap, 4 - depthBefore, 0));
3176
+ let sel = -1;
3177
+ tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
3178
+ if (sel > -1) {
3179
+ return false;
3180
+ }
3181
+ if (n.isTextblock && n.content.size === 0) {
3182
+ sel = pos + 1;
3183
+ }
3184
+ });
3185
+ if (sel > -1) {
3186
+ tr.setSelection(state.TextSelection.near(tr.doc.resolve(sel)));
3187
+ }
3188
+ tr.scrollIntoView();
3189
+ }
3190
+ return true;
3191
+ }
3192
+ const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null;
3193
+ const newTypeAttributes = {
3194
+ ...getSplittedAttributes(extensionAttributes, grandParent.type.name, grandParent.attrs),
3195
+ ...overrideAttrs
3196
+ };
3197
+ const newNextTypeAttributes = {
3198
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
3199
+ ...overrideAttrs
3200
+ };
3201
+ tr.delete($from.pos, $to.pos);
3202
+ const types = nextType ? [
3203
+ { type, attrs: newTypeAttributes },
3204
+ { type: nextType, attrs: newNextTypeAttributes }
3205
+ ] : [{ type, attrs: newTypeAttributes }];
3206
+ if (!transform.canSplit(tr.doc, $from.pos, 2)) {
3207
+ return false;
3208
+ }
3209
+ if (dispatch) {
3210
+ const { selection, storedMarks } = state$1;
3211
+ const { splittableMarks } = editor.extensionManager;
3212
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
3213
+ tr.split($from.pos, 2, types).scrollIntoView();
3214
+ if (!marks || !dispatch) {
3215
+ return true;
3216
+ }
3217
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
3218
+ tr.ensureMarks(filteredMarks);
3219
+ }
3220
+ return true;
3221
+ };
3222
+ var joinListBackwards = (tr, listType) => {
3223
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
3224
+ if (!list) {
3225
+ return true;
3226
+ }
3227
+ const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
3228
+ if (before === void 0) {
3229
+ return true;
3230
+ }
3231
+ const nodeBefore = tr.doc.nodeAt(before);
3232
+ const canJoinBackwards = list.node.type === (nodeBefore == null ? void 0 : nodeBefore.type) && transform.canJoin(tr.doc, list.pos);
3233
+ if (!canJoinBackwards) {
3234
+ return true;
3235
+ }
3236
+ tr.join(list.pos);
3237
+ return true;
3238
+ };
3239
+ var joinListForwards = (tr, listType) => {
3240
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
3241
+ if (!list) {
3242
+ return true;
3243
+ }
3244
+ const after = tr.doc.resolve(list.start).after(list.depth);
3245
+ if (after === void 0) {
3246
+ return true;
3247
+ }
3248
+ const nodeAfter = tr.doc.nodeAt(after);
3249
+ const canJoinForwards = list.node.type === (nodeAfter == null ? void 0 : nodeAfter.type) && transform.canJoin(tr.doc, after);
3250
+ if (!canJoinForwards) {
3251
+ return true;
3252
+ }
3253
+ tr.join(after);
3254
+ return true;
3255
+ };
3256
+ function createInnerSelectionForWholeDocList(tr) {
3257
+ const doc = tr.doc;
3258
+ const list = doc.firstChild;
3259
+ if (!list) {
3260
+ return null;
3261
+ }
3262
+ const $start = doc.resolve(1);
3263
+ const $end = doc.resolve(list.nodeSize - 1);
3264
+ return state.TextSelection.between($start, $end);
3265
+ }
3266
+ var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({ editor, tr, state, dispatch, chain, commands, can }) => {
3267
+ const { extensions, splittableMarks } = editor.extensionManager;
3268
+ const listType = getNodeType(listTypeOrName, state.schema);
3269
+ const itemType = getNodeType(itemTypeOrName, state.schema);
3270
+ const { selection, storedMarks } = state;
3271
+ const { $from, $to } = selection;
3272
+ const range = $from.blockRange($to);
3273
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
3274
+ if (!range) {
3275
+ return false;
3276
+ }
3277
+ const parentList = findParentNode((node) => isList(node.type.name, extensions))(selection);
3278
+ const isAllSelection = selection.from === 0 && selection.to === state.doc.content.size;
3279
+ const topLevelNodes = state.doc.content.content;
3280
+ const soleTopLevelNode = topLevelNodes.length === 1 ? topLevelNodes[0] : null;
3281
+ const allSelectionList = isAllSelection && soleTopLevelNode && isList(soleTopLevelNode.type.name, extensions) ? {
3282
+ node: soleTopLevelNode,
3283
+ pos: 0} : null;
3284
+ const currentList = parentList != null ? parentList : allSelectionList;
3285
+ const isInsideExistingList = !!parentList && range.depth >= 1 && range.depth - parentList.depth <= 1;
3286
+ const hasWholeDocSelectedList = !!allSelectionList;
3287
+ if ((isInsideExistingList || hasWholeDocSelectedList) && currentList) {
3288
+ if (currentList.node.type === listType) {
3289
+ if (isAllSelection && hasWholeDocSelectedList) {
3290
+ return chain().command(({ tr: trx, dispatch: disp }) => {
3291
+ const nextSelection = createInnerSelectionForWholeDocList(trx);
3292
+ if (!nextSelection) {
3293
+ return false;
3294
+ }
3295
+ trx.setSelection(nextSelection);
3296
+ if (disp) {
3297
+ disp(trx);
3298
+ }
3299
+ return true;
3300
+ }).liftListItem(itemType).run();
3301
+ }
3302
+ return commands.liftListItem(itemType);
3303
+ }
3304
+ if (isList(currentList.node.type.name, extensions) && listType.validContent(currentList.node.content)) {
3305
+ return chain().command(() => {
3306
+ tr.setNodeMarkup(currentList.pos, listType);
3307
+ return true;
3308
+ }).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
3309
+ }
3310
+ }
3311
+ if (!keepMarks || !marks || !dispatch) {
3312
+ return chain().command(() => {
3313
+ const canWrapInList = can().wrapInList(listType, attributes);
3314
+ if (canWrapInList) {
3315
+ return true;
3316
+ }
3317
+ return commands.clearNodes();
3318
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
3319
+ }
3320
+ return chain().command(() => {
3321
+ const canWrapInList = can().wrapInList(listType, attributes);
3322
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
3323
+ tr.ensureMarks(filteredMarks);
3324
+ if (canWrapInList) {
3325
+ return true;
3326
+ }
3327
+ return commands.clearNodes();
3328
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
3329
+ };
3330
+ var toggleMark = (typeOrName, attributes = {}, options = {}) => ({ state, commands }) => {
3331
+ const { extendEmptyMarkRange = false } = options;
3332
+ const type = getMarkType(typeOrName, state.schema);
3333
+ const isActive2 = isMarkActive(state, type, attributes);
3334
+ if (isActive2) {
3335
+ return commands.unsetMark(type, { extendEmptyMarkRange });
3336
+ }
3337
+ return commands.setMark(type, attributes);
3338
+ };
3339
+ var toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands }) => {
3340
+ const type = getNodeType(typeOrName, state.schema);
3341
+ const toggleType = getNodeType(toggleTypeOrName, state.schema);
3342
+ const isActive2 = isNodeActive(state, type, attributes);
3343
+ let attributesToCopy;
3344
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
3345
+ attributesToCopy = state.selection.$anchor.parent.attrs;
3346
+ }
3347
+ if (isActive2) {
3348
+ return commands.setNode(toggleType, attributesToCopy);
3349
+ }
3350
+ return commands.setNode(type, { ...attributesToCopy, ...attributes });
3351
+ };
3352
+ var toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
3353
+ const type = getNodeType(typeOrName, state.schema);
3354
+ const isActive2 = isNodeActive(state, type, attributes);
3355
+ if (isActive2) {
3356
+ return commands.lift(type);
3357
+ }
3358
+ return commands.wrapIn(type, attributes);
3359
+ };
3360
+ var undoInputRule = () => ({ state, dispatch }) => {
3361
+ const plugins = state.plugins;
3362
+ for (let i = 0; i < plugins.length; i += 1) {
3363
+ const plugin = plugins[i];
3364
+ let undoable;
3365
+ if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
3366
+ if (dispatch) {
3367
+ const tr = state.tr;
3368
+ const toUndo = undoable.transform;
3369
+ for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
3370
+ tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
3371
+ }
3372
+ if (undoable.text) {
3373
+ const marks = tr.doc.resolve(undoable.from).marks();
3374
+ tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
3375
+ } else {
3376
+ tr.delete(undoable.from, undoable.to);
3377
+ }
3378
+ }
3379
+ return true;
3380
+ }
3381
+ }
3382
+ return false;
3383
+ };
3384
+ var unsetAllMarks = (options = {}) => ({ tr, dispatch, editor }) => {
3385
+ const { ignoreClearable = false } = options;
3386
+ const { selection } = tr;
3387
+ const { empty, ranges } = selection;
3388
+ if (empty) {
3389
+ return true;
3390
+ }
3391
+ const { nonClearableMarks } = editor.extensionManager;
3392
+ if (dispatch) {
3393
+ const clearableMarkTypes = Object.values(editor.schema.marks).filter(
3394
+ (markType) => ignoreClearable || !nonClearableMarks.includes(markType.name)
3395
+ );
3396
+ ranges.forEach((range) => {
3397
+ for (const markType of clearableMarkTypes) {
3398
+ tr.removeMark(range.$from.pos, range.$to.pos, markType);
3399
+ }
3400
+ });
3401
+ }
3402
+ return true;
3403
+ };
3404
+ var unsetMark = (typeOrName, options = {}) => ({ tr, state, dispatch }) => {
3405
+ var _a;
3406
+ const { extendEmptyMarkRange = false } = options;
3407
+ const { selection } = tr;
3408
+ const type = getMarkType(typeOrName, state.schema);
3409
+ const { $from, empty, ranges } = selection;
3410
+ if (!dispatch) {
3411
+ return true;
3412
+ }
3413
+ if (empty && extendEmptyMarkRange) {
3414
+ let { from, to } = selection;
3415
+ const attrs = (_a = $from.marks().find((mark) => mark.type === type)) == null ? void 0 : _a.attrs;
3416
+ const range = getMarkRange($from, type, attrs);
3417
+ if (range) {
3418
+ from = range.from;
3419
+ to = range.to;
3420
+ }
3421
+ tr.removeMark(from, to, type);
3422
+ } else {
3423
+ ranges.forEach((range) => {
3424
+ tr.removeMark(range.$from.pos, range.$to.pos, type);
3425
+ });
3426
+ }
3427
+ tr.removeStoredMark(type);
3428
+ return true;
3429
+ };
3430
+ var unsetTextDirection = (position) => ({ tr, state, dispatch }) => {
3431
+ const { selection } = state;
3432
+ let from;
3433
+ let to;
3434
+ if (typeof position === "number") {
3435
+ from = position;
3436
+ to = position;
3437
+ } else if (position && "from" in position && "to" in position) {
3438
+ from = position.from;
3439
+ to = position.to;
3440
+ } else {
3441
+ from = selection.from;
3442
+ to = selection.to;
3443
+ }
3444
+ if (dispatch) {
3445
+ tr.doc.nodesBetween(from, to, (node, pos) => {
3446
+ if (node.isText) {
3447
+ return;
3448
+ }
3449
+ const newAttrs = { ...node.attrs };
3450
+ delete newAttrs.dir;
3451
+ tr.setNodeMarkup(pos, void 0, newAttrs);
3452
+ });
3453
+ }
3454
+ return true;
3455
+ };
3456
+ var updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
3457
+ let nodeType = null;
3458
+ let markType = null;
3459
+ const schemaType = getSchemaTypeNameByName(
3460
+ typeof typeOrName === "string" ? typeOrName : typeOrName.name,
3461
+ state.schema
3462
+ );
3463
+ if (!schemaType) {
3464
+ return false;
3465
+ }
3466
+ if (schemaType === "node") {
3467
+ nodeType = getNodeType(typeOrName, state.schema);
3468
+ }
3469
+ if (schemaType === "mark") {
3470
+ markType = getMarkType(typeOrName, state.schema);
3471
+ }
3472
+ let canUpdate = false;
3473
+ tr.selection.ranges.forEach((range) => {
3474
+ const from = range.$from.pos;
3475
+ const to = range.$to.pos;
3476
+ let lastPos;
3477
+ let lastNode;
3478
+ let trimmedFrom;
3479
+ let trimmedTo;
3480
+ if (tr.selection.empty) {
3481
+ state.doc.nodesBetween(from, to, (node, pos) => {
3482
+ if (nodeType && nodeType === node.type) {
3483
+ canUpdate = true;
3484
+ trimmedFrom = Math.max(pos, from);
3485
+ trimmedTo = Math.min(pos + node.nodeSize, to);
3486
+ lastPos = pos;
3487
+ lastNode = node;
3488
+ }
3489
+ });
3490
+ } else {
3491
+ state.doc.nodesBetween(from, to, (node, pos) => {
3492
+ if (pos < from && nodeType && nodeType === node.type) {
3493
+ canUpdate = true;
3494
+ trimmedFrom = Math.max(pos, from);
3495
+ trimmedTo = Math.min(pos + node.nodeSize, to);
3496
+ lastPos = pos;
3497
+ lastNode = node;
3498
+ }
3499
+ if (pos >= from && pos <= to) {
3500
+ if (nodeType && nodeType === node.type) {
3501
+ canUpdate = true;
3502
+ if (dispatch) {
3503
+ tr.setNodeMarkup(pos, void 0, {
3504
+ ...node.attrs,
3505
+ ...attributes
3506
+ });
3507
+ }
3508
+ }
3509
+ if (markType && node.marks.length) {
3510
+ node.marks.forEach((mark) => {
3511
+ if (markType === mark.type) {
3512
+ canUpdate = true;
3513
+ if (dispatch) {
3514
+ const trimmedFrom2 = Math.max(pos, from);
3515
+ const trimmedTo2 = Math.min(pos + node.nodeSize, to);
3516
+ tr.addMark(
3517
+ trimmedFrom2,
3518
+ trimmedTo2,
3519
+ markType.create({
3520
+ ...mark.attrs,
3521
+ ...attributes
3522
+ })
3523
+ );
3524
+ }
3525
+ }
3526
+ });
3527
+ }
3528
+ }
3529
+ });
3530
+ }
3531
+ if (lastNode) {
3532
+ if (lastPos !== void 0 && dispatch) {
3533
+ tr.setNodeMarkup(lastPos, void 0, {
3534
+ ...lastNode.attrs,
3535
+ ...attributes
3536
+ });
3537
+ }
3538
+ if (markType && lastNode.marks.length) {
3539
+ lastNode.marks.forEach((mark) => {
3540
+ if (markType === mark.type && dispatch) {
3541
+ tr.addMark(
3542
+ trimmedFrom,
3543
+ trimmedTo,
3544
+ markType.create({
3545
+ ...mark.attrs,
3546
+ ...attributes
3547
+ })
3548
+ );
3549
+ }
3550
+ });
3551
+ }
3552
+ }
3553
+ });
3554
+ return canUpdate;
3555
+ };
3556
+ var wrapIn = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
3557
+ const type = getNodeType(typeOrName, state.schema);
3558
+ return commands.wrapIn(type, attributes)(state, dispatch);
3559
+ };
3560
+ var wrapInList = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
3561
+ const type = getNodeType(typeOrName, state.schema);
3562
+ return schemaList.wrapInList(type, attributes)(state, dispatch);
3563
+ };
3564
+ function getType(value) {
3565
+ return Object.prototype.toString.call(value).slice(8, -1);
3566
+ }
3567
+ function isPlainObject(value) {
3568
+ if (getType(value) !== "Object") {
3569
+ return false;
3570
+ }
3571
+ return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype;
3572
+ }
3573
+ function mergeDeep(target, source) {
3574
+ const output = { ...target };
3575
+ if (isPlainObject(target) && isPlainObject(source)) {
3576
+ Object.keys(source).forEach((key) => {
3577
+ if (isPlainObject(source[key]) && isPlainObject(target[key])) {
3578
+ output[key] = mergeDeep(target[key], source[key]);
3579
+ } else {
3580
+ output[key] = source[key];
3581
+ }
3582
+ });
3583
+ }
3584
+ return output;
3585
+ }
3586
+ var Extendable = class {
3587
+ constructor(config = {}) {
3588
+ this.type = "extendable";
3589
+ this.parent = null;
3590
+ this.child = null;
3591
+ this.name = "";
3592
+ this.config = {
3593
+ name: this.name
3594
+ };
3595
+ this.config = {
3596
+ ...this.config,
3597
+ ...config
3598
+ };
3599
+ this.name = this.config.name;
3600
+ }
3601
+ get options() {
3602
+ return {
3603
+ ...callOrReturn(
3604
+ getExtensionField(this, "addOptions", {
3605
+ name: this.name
3606
+ })
3607
+ )
3608
+ };
3609
+ }
3610
+ get storage() {
3611
+ return {
3612
+ ...callOrReturn(
3613
+ getExtensionField(this, "addStorage", {
3614
+ name: this.name,
3615
+ options: this.options
3616
+ })
3617
+ )
3618
+ };
3619
+ }
3620
+ configure(options = {}) {
3621
+ const extension = this.extend({
3622
+ ...this.config,
3623
+ addOptions: () => {
3624
+ return mergeDeep(this.options, options);
3625
+ }
3626
+ });
3627
+ extension.name = this.name;
3628
+ extension.parent = this.parent;
3629
+ this.child = null;
3630
+ return extension;
3631
+ }
3632
+ extend(extendedConfig = {}) {
3633
+ const extension = new this.constructor({ ...this.config, ...extendedConfig });
3634
+ extension.parent = this;
3635
+ this.child = extension;
3636
+ extension.name = "name" in extendedConfig ? extendedConfig.name : extension.parent.name;
3637
+ return extension;
3638
+ }
3639
+ };
3640
+ var Mark = class _Mark extends Extendable {
3641
+ constructor() {
3642
+ super(...arguments);
3643
+ this.type = "mark";
3644
+ }
3645
+ /**
3646
+ * Create a new Mark instance
3647
+ * @param config - Mark configuration object or a function that returns a configuration object
3648
+ */
3649
+ static create(config = {}) {
3650
+ const resolvedConfig = typeof config === "function" ? config() : config;
3651
+ return new _Mark(resolvedConfig);
3652
+ }
3653
+ static handleExit({ editor, mark }) {
3654
+ const { tr } = editor.state;
3655
+ const currentPos = editor.state.selection.$from;
3656
+ const isAtEnd = currentPos.pos === currentPos.end();
3657
+ if (isAtEnd) {
3658
+ const currentMarks = currentPos.marks();
3659
+ const isInMark = !!currentMarks.find((m) => (m == null ? void 0 : m.type.name) === mark.name);
3660
+ if (!isInMark) {
3661
+ return false;
3662
+ }
3663
+ const removeMark = currentMarks.find((m) => (m == null ? void 0 : m.type.name) === mark.name);
3664
+ if (removeMark) {
3665
+ tr.removeStoredMark(removeMark);
3666
+ }
3667
+ tr.insertText(" ", currentPos.pos);
3668
+ editor.view.dispatch(tr);
3669
+ return true;
3670
+ }
3671
+ return false;
3672
+ }
3673
+ configure(options) {
3674
+ return super.configure(options);
3675
+ }
3676
+ extend(extendedConfig) {
3677
+ const resolvedConfig = typeof extendedConfig === "function" ? extendedConfig() : extendedConfig;
3678
+ return super.extend(resolvedConfig);
3679
+ }
3680
+ };
3681
+ var extensions_exports = {};
3682
+ __export(extensions_exports, {
3683
+ ClipboardTextSerializer: () => ClipboardTextSerializer,
3684
+ Commands: () => Commands,
3685
+ Delete: () => Delete,
3686
+ Drop: () => Drop,
3687
+ Editable: () => Editable,
3688
+ FocusEvents: () => FocusEvents,
3689
+ Keymap: () => Keymap,
3690
+ Paste: () => Paste,
3691
+ Tabindex: () => Tabindex,
3692
+ TextDirection: () => TextDirection,
3693
+ focusEventsPluginKey: () => focusEventsPluginKey
3694
+ });
3695
+ var Extension = class _Extension extends Extendable {
3696
+ constructor() {
3697
+ super(...arguments);
3698
+ this.type = "extension";
3699
+ }
3700
+ /**
3701
+ * Create a new Extension instance
3702
+ * @param config - Extension configuration object or a function that returns a configuration object
3703
+ */
3704
+ static create(config = {}) {
3705
+ const resolvedConfig = typeof config === "function" ? config() : config;
3706
+ return new _Extension(resolvedConfig);
3707
+ }
3708
+ configure(options) {
3709
+ return super.configure(options);
3710
+ }
3711
+ extend(extendedConfig) {
3712
+ const resolvedConfig = typeof extendedConfig === "function" ? extendedConfig() : extendedConfig;
3713
+ return super.extend(resolvedConfig);
3714
+ }
3715
+ };
3716
+ var ClipboardTextSerializer = Extension.create({
3717
+ name: "clipboardTextSerializer",
3718
+ addOptions() {
3719
+ return {
3720
+ blockSeparator: void 0
3721
+ };
3722
+ },
3723
+ addProseMirrorPlugins() {
3724
+ return [
3725
+ new state.Plugin({
3726
+ key: new state.PluginKey("clipboardTextSerializer"),
3727
+ props: {
3728
+ clipboardTextSerializer: () => {
3729
+ const { editor } = this;
3730
+ const { state, schema } = editor;
3731
+ const { doc, selection } = state;
3732
+ const textSerializers = getTextSerializersFromSchema(schema);
3733
+ const { blockSeparator } = this.options;
3734
+ const options = {
3735
+ ...blockSeparator !== void 0 ? { blockSeparator } : {},
3736
+ textSerializers
3737
+ };
3738
+ const sortedRanges = [...selection.ranges].sort((a, b) => a.$from.pos - b.$from.pos);
3739
+ return sortedRanges.map(
3740
+ ({ $from, $to }) => getTextBetween(doc, { from: $from.pos, to: $to.pos }, options)
3741
+ ).join(blockSeparator != null ? blockSeparator : "\n\n");
3742
+ }
3743
+ }
3744
+ })
3745
+ ];
3746
+ }
3747
+ });
3748
+ var Commands = Extension.create({
3749
+ name: "commands",
3750
+ addCommands() {
3751
+ return {
3752
+ ...commands_exports
3753
+ };
3754
+ }
3755
+ });
3756
+ var Delete = Extension.create({
3757
+ name: "delete",
3758
+ onUpdate({ transaction, appendedTransactions }) {
3759
+ var _a, _b, _c;
3760
+ const callback = () => {
3761
+ var _a2, _b2, _c2, _d;
3762
+ 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$")) {
3763
+ return;
3764
+ }
3765
+ const nextTransaction = combineTransactionSteps(transaction.before, [
3766
+ transaction,
3767
+ ...appendedTransactions
3768
+ ]);
3769
+ const changes = getChangedRanges(nextTransaction);
3770
+ changes.forEach((change) => {
3771
+ if (nextTransaction.mapping.mapResult(change.oldRange.from).deletedAfter && nextTransaction.mapping.mapResult(change.oldRange.to).deletedBefore) {
3772
+ nextTransaction.before.nodesBetween(
3773
+ change.oldRange.from,
3774
+ change.oldRange.to,
3775
+ (node, from) => {
3776
+ const to = from + node.nodeSize - 2;
3777
+ const isFullyWithinRange = change.oldRange.from <= from && to <= change.oldRange.to;
3778
+ this.editor.emit("delete", {
3779
+ type: "node",
3780
+ node,
3781
+ from,
3782
+ to,
3783
+ newFrom: nextTransaction.mapping.map(from),
3784
+ newTo: nextTransaction.mapping.map(to),
3785
+ deletedRange: change.oldRange,
3786
+ newRange: change.newRange,
3787
+ partial: !isFullyWithinRange,
3788
+ editor: this.editor,
3789
+ transaction,
3790
+ combinedTransform: nextTransaction
3791
+ });
3792
+ }
3793
+ );
3794
+ }
3795
+ });
3796
+ const mapping = nextTransaction.mapping;
3797
+ nextTransaction.steps.forEach((step, index) => {
3798
+ var _a3, _b3;
3799
+ if (step instanceof transform.RemoveMarkStep) {
3800
+ const newStart = mapping.slice(index).map(step.from, -1);
3801
+ const newEnd = mapping.slice(index).map(step.to);
3802
+ const oldStart = mapping.invert().map(newStart, -1);
3803
+ const oldEnd = mapping.invert().map(newEnd);
3804
+ const foundBeforeMark = newStart > 0 ? (_a3 = nextTransaction.doc.nodeAt(newStart - 1)) == null ? void 0 : _a3.marks.some((mark) => mark.eq(step.mark)) : false;
3805
+ const foundAfterMark = (_b3 = nextTransaction.doc.nodeAt(newEnd)) == null ? void 0 : _b3.marks.some((mark) => mark.eq(step.mark));
3806
+ this.editor.emit("delete", {
3807
+ type: "mark",
3808
+ mark: step.mark,
3809
+ from: step.from,
3810
+ to: step.to,
3811
+ deletedRange: {
3812
+ from: oldStart,
3813
+ to: oldEnd
3814
+ },
3815
+ newRange: {
3816
+ from: newStart,
3817
+ to: newEnd
3818
+ },
3819
+ partial: Boolean(foundAfterMark || foundBeforeMark),
3820
+ editor: this.editor,
3821
+ transaction,
3822
+ combinedTransform: nextTransaction
3823
+ });
3824
+ }
3825
+ });
3826
+ };
3827
+ if ((_c = (_b = (_a = this.editor.options.coreExtensionOptions) == null ? void 0 : _a.delete) == null ? void 0 : _b.async) != null ? _c : true) {
3828
+ setTimeout(callback, 0);
3829
+ } else {
3830
+ callback();
3831
+ }
3832
+ }
3833
+ });
3834
+ var Drop = Extension.create({
3835
+ name: "drop",
3836
+ addProseMirrorPlugins() {
3837
+ return [
3838
+ new state.Plugin({
3839
+ key: new state.PluginKey("tiptapDrop"),
3840
+ props: {
3841
+ handleDrop: (_, e, slice, moved) => {
3842
+ this.editor.emit("drop", {
3843
+ editor: this.editor,
3844
+ event: e,
3845
+ slice,
3846
+ moved
3847
+ });
3848
+ }
3849
+ }
3850
+ })
3851
+ ];
3852
+ }
3853
+ });
3854
+ var Editable = Extension.create({
3855
+ name: "editable",
3856
+ addProseMirrorPlugins() {
3857
+ return [
3858
+ new state.Plugin({
3859
+ key: new state.PluginKey("editable"),
3860
+ props: {
3861
+ editable: () => this.editor.options.editable
3862
+ }
3863
+ })
3864
+ ];
3865
+ }
3866
+ });
3867
+ var focusEventsPluginKey = new state.PluginKey("focusEvents");
3868
+ var FocusEvents = Extension.create({
3869
+ name: "focusEvents",
3870
+ addProseMirrorPlugins() {
3871
+ const { editor } = this;
3872
+ return [
3873
+ new state.Plugin({
3874
+ key: focusEventsPluginKey,
3875
+ props: {
3876
+ handleDOMEvents: {
3877
+ focus: (view, event) => {
3878
+ editor.isFocused = true;
3879
+ const transaction = editor.state.tr.setMeta("focus", { event }).setMeta("addToHistory", false);
3880
+ view.dispatch(transaction);
3881
+ return false;
3882
+ },
3883
+ blur: (view, event) => {
3884
+ editor.isFocused = false;
3885
+ const transaction = editor.state.tr.setMeta("blur", { event }).setMeta("addToHistory", false);
3886
+ view.dispatch(transaction);
3887
+ return false;
3888
+ }
3889
+ }
3890
+ }
3891
+ })
3892
+ ];
3893
+ }
3894
+ });
3895
+ var Keymap = Extension.create({
3896
+ name: "keymap",
3897
+ addKeyboardShortcuts() {
3898
+ const handleBackspace = () => this.editor.commands.first(({ commands }) => [
3899
+ () => commands.undoInputRule(),
3900
+ // maybe convert first text block node to default node
3901
+ () => commands.command(({ tr }) => {
3902
+ const { selection, doc } = tr;
3903
+ const { empty, $anchor } = selection;
3904
+ const { pos, parent } = $anchor;
3905
+ const $parentPos = $anchor.parent.isTextblock && pos > 0 ? tr.doc.resolve(pos - 1) : $anchor;
3906
+ const parentIsIsolating = $parentPos.parent.type.spec.isolating;
3907
+ const parentPos = $anchor.pos - $anchor.parentOffset;
3908
+ const isAtStart = parentIsIsolating && $parentPos.parent.childCount === 1 ? parentPos === $anchor.pos : state.Selection.atStart(doc).from === pos;
3909
+ if (!empty || !parent.type.isTextblock || parent.textContent.length || !isAtStart || isAtStart && $anchor.parent.type.name === "paragraph") {
3910
+ return false;
3911
+ }
3912
+ return commands.clearNodes();
3913
+ }),
3914
+ () => commands.deleteSelection(),
3915
+ () => commands.joinBackward(),
3916
+ () => commands.selectNodeBackward()
3917
+ ]);
3918
+ const handleDelete = () => this.editor.commands.first(({ commands }) => [
3919
+ () => commands.deleteSelection(),
3920
+ () => commands.deleteCurrentNode(),
3921
+ () => commands.joinForward(),
3922
+ () => commands.selectNodeForward()
3923
+ ]);
3924
+ const handleEnter = () => this.editor.commands.first(({ commands }) => [
3925
+ () => commands.newlineInCode(),
3926
+ () => commands.createParagraphNear(),
3927
+ () => commands.liftEmptyBlock(),
3928
+ () => commands.splitBlock()
3929
+ ]);
3930
+ const baseKeymap = {
3931
+ Enter: handleEnter,
3932
+ "Mod-Enter": () => this.editor.commands.exitCode(),
3933
+ Backspace: handleBackspace,
3934
+ "Mod-Backspace": handleBackspace,
3935
+ "Shift-Backspace": handleBackspace,
3936
+ Delete: handleDelete,
3937
+ "Mod-Delete": handleDelete,
3938
+ "Mod-a": () => this.editor.commands.selectAll()
3939
+ };
3940
+ const pcKeymap = {
3941
+ ...baseKeymap
3942
+ };
3943
+ const macKeymap = {
3944
+ ...baseKeymap,
3945
+ "Ctrl-h": handleBackspace,
3946
+ "Alt-Backspace": handleBackspace,
3947
+ "Ctrl-d": handleDelete,
3948
+ "Ctrl-Alt-Backspace": handleDelete,
3949
+ "Alt-Delete": handleDelete,
3950
+ "Alt-d": handleDelete,
3951
+ "Ctrl-a": () => this.editor.commands.selectTextblockStart(),
3952
+ "Ctrl-e": () => this.editor.commands.selectTextblockEnd()
3953
+ };
3954
+ if (isiOS() || isMacOS()) {
3955
+ return macKeymap;
3956
+ }
3957
+ return pcKeymap;
3958
+ },
3959
+ addProseMirrorPlugins() {
3960
+ return [
3961
+ // With this plugin we check if the whole document was selected and deleted.
3962
+ // In this case we will additionally call `clearNodes()` to convert e.g. a heading
3963
+ // to a paragraph if necessary.
3964
+ // This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
3965
+ // with many other commands.
3966
+ new state.Plugin({
3967
+ key: new state.PluginKey("clearDocument"),
3968
+ appendTransaction: (transactions, oldState, newState) => {
3969
+ if (transactions.some((tr2) => tr2.getMeta("composition"))) {
3970
+ return;
3971
+ }
3972
+ const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
3973
+ const ignoreTr = transactions.some(
3974
+ (transaction) => transaction.getMeta("preventClearDocument")
3975
+ );
3976
+ if (!docChanges || ignoreTr) {
3977
+ return;
3978
+ }
3979
+ const { empty, from, to } = oldState.selection;
3980
+ const allFrom = state.Selection.atStart(oldState.doc).from;
3981
+ const allEnd = state.Selection.atEnd(oldState.doc).to;
3982
+ const allWasSelected = from === allFrom && to === allEnd;
3983
+ if (empty || !allWasSelected) {
3984
+ return;
3985
+ }
3986
+ const isEmpty = isNodeEmpty(newState.doc);
3987
+ if (!isEmpty) {
3988
+ return;
3989
+ }
3990
+ const tr = newState.tr;
3991
+ const state$1 = createChainableState({
3992
+ state: newState,
3993
+ transaction: tr
3994
+ });
3995
+ const { commands } = new CommandManager({
3996
+ editor: this.editor,
3997
+ state: state$1
3998
+ });
3999
+ commands.clearNodes();
4000
+ if (!tr.steps.length) {
4001
+ return;
4002
+ }
4003
+ return tr;
4004
+ }
4005
+ })
4006
+ ];
4007
+ }
4008
+ });
4009
+ var Paste = Extension.create({
4010
+ name: "paste",
4011
+ addProseMirrorPlugins() {
4012
+ return [
4013
+ new state.Plugin({
4014
+ key: new state.PluginKey("tiptapPaste"),
4015
+ props: {
4016
+ handlePaste: (_view, e, slice) => {
4017
+ this.editor.emit("paste", {
4018
+ editor: this.editor,
4019
+ event: e,
4020
+ slice
4021
+ });
4022
+ }
4023
+ }
4024
+ })
4025
+ ];
4026
+ }
4027
+ });
4028
+ var Tabindex = Extension.create({
4029
+ name: "tabindex",
4030
+ addOptions() {
4031
+ return {
4032
+ value: void 0
4033
+ };
4034
+ },
4035
+ addProseMirrorPlugins() {
4036
+ return [
4037
+ new state.Plugin({
4038
+ key: new state.PluginKey("tabindex"),
4039
+ props: {
4040
+ attributes: () => {
4041
+ var _a;
4042
+ if (!this.editor.isEditable && this.options.value === void 0) {
4043
+ return {};
4044
+ }
4045
+ return { tabindex: (_a = this.options.value) != null ? _a : "0" };
4046
+ }
4047
+ }
4048
+ })
4049
+ ];
4050
+ }
4051
+ });
4052
+ var TextDirection = Extension.create({
4053
+ name: "textDirection",
4054
+ addOptions() {
4055
+ return {
4056
+ direction: void 0
4057
+ };
4058
+ },
4059
+ addGlobalAttributes() {
4060
+ if (!this.options.direction) {
4061
+ return [];
4062
+ }
4063
+ const { nodeExtensions } = splitExtensions(this.extensions);
4064
+ return [
4065
+ {
4066
+ types: nodeExtensions.filter((extension) => extension.name !== "text").map((extension) => extension.name),
4067
+ attributes: {
4068
+ dir: {
4069
+ default: this.options.direction,
4070
+ parseHTML: (element) => {
4071
+ const dir = element.getAttribute("dir");
4072
+ if (dir && (dir === "ltr" || dir === "rtl" || dir === "auto")) {
4073
+ return dir;
4074
+ }
4075
+ return this.options.direction;
4076
+ },
4077
+ renderHTML: (attributes) => {
4078
+ if (!attributes.dir) {
4079
+ return {};
4080
+ }
4081
+ return {
4082
+ dir: attributes.dir
4083
+ };
4084
+ }
4085
+ }
4086
+ }
4087
+ }
4088
+ ];
4089
+ },
4090
+ addProseMirrorPlugins() {
4091
+ return [
4092
+ new state.Plugin({
4093
+ key: new state.PluginKey("textDirection"),
4094
+ props: {
4095
+ attributes: () => {
4096
+ const direction = this.options.direction;
4097
+ if (!direction) {
4098
+ return {};
4099
+ }
4100
+ return {
4101
+ dir: direction
4102
+ };
4103
+ }
4104
+ }
4105
+ })
4106
+ ];
4107
+ }
4108
+ });
4109
+ var markdown_exports = {};
4110
+ __export(markdown_exports, {
4111
+ createAtomBlockMarkdownSpec: () => createAtomBlockMarkdownSpec,
4112
+ createBlockMarkdownSpec: () => createBlockMarkdownSpec,
4113
+ createInlineMarkdownSpec: () => createInlineMarkdownSpec,
4114
+ parseAttributes: () => parseAttributes,
4115
+ parseIndentedBlocks: () => parseIndentedBlocks,
4116
+ renderNestedMarkdownContent: () => renderNestedMarkdownContent,
4117
+ serializeAttributes: () => serializeAttributes
4118
+ });
4119
+ function parseAttributes(attrString) {
4120
+ if (!(attrString == null ? void 0 : attrString.trim())) {
4121
+ return {};
4122
+ }
4123
+ const attributes = {};
4124
+ const quotedStrings = [];
4125
+ const tempString = attrString.replace(/["']([^"']*)["']/g, (match) => {
4126
+ quotedStrings.push(match);
4127
+ return `__QUOTED_${quotedStrings.length - 1}__`;
4128
+ });
4129
+ const classMatches = tempString.match(/(?:^|\s)\.([a-zA-Z][\w-]*)/g);
4130
+ if (classMatches) {
4131
+ const classes = classMatches.map((match) => match.trim().slice(1));
4132
+ attributes.class = classes.join(" ");
4133
+ }
4134
+ const idMatch = tempString.match(/(?:^|\s)#([a-zA-Z][\w-]*)/);
4135
+ if (idMatch) {
4136
+ attributes.id = idMatch[1];
4137
+ }
4138
+ const kvRegex = /([a-zA-Z][\w-]*)\s*=\s*(__QUOTED_\d+__)/g;
4139
+ const kvMatches = Array.from(tempString.matchAll(kvRegex));
4140
+ kvMatches.forEach(([, key, quotedRef]) => {
4141
+ var _a;
4142
+ const quotedIndex = parseInt(((_a = quotedRef.match(/__QUOTED_(\d+)__/)) == null ? void 0 : _a[1]) || "0", 10);
4143
+ const quotedValue = quotedStrings[quotedIndex];
4144
+ if (quotedValue) {
4145
+ attributes[key] = quotedValue.slice(1, -1);
4146
+ }
4147
+ });
4148
+ 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();
4149
+ if (cleanString) {
4150
+ const booleanAttrs = cleanString.split(/\s+/).filter(Boolean);
4151
+ booleanAttrs.forEach((attr) => {
4152
+ if (attr.match(/^[a-zA-Z][\w-]*$/)) {
4153
+ attributes[attr] = true;
4154
+ }
4155
+ });
4156
+ }
4157
+ return attributes;
4158
+ }
4159
+ function serializeAttributes(attributes) {
4160
+ if (!attributes || Object.keys(attributes).length === 0) {
4161
+ return "";
4162
+ }
4163
+ const parts = [];
4164
+ if (attributes.class) {
4165
+ const classes = String(attributes.class).split(/\s+/).filter(Boolean);
4166
+ classes.forEach((cls) => parts.push(`.${cls}`));
4167
+ }
4168
+ if (attributes.id) {
4169
+ parts.push(`#${attributes.id}`);
4170
+ }
4171
+ Object.entries(attributes).forEach(([key, value]) => {
4172
+ if (key === "class" || key === "id") {
4173
+ return;
4174
+ }
4175
+ if (value === true) {
4176
+ parts.push(key);
4177
+ } else if (value !== false && value != null) {
4178
+ parts.push(`${key}="${String(value)}"`);
4179
+ }
4180
+ });
4181
+ return parts.join(" ");
4182
+ }
4183
+ function createAtomBlockMarkdownSpec(options) {
4184
+ const {
4185
+ nodeName,
4186
+ name: markdownName,
4187
+ parseAttributes: parseAttributes2 = parseAttributes,
4188
+ serializeAttributes: serializeAttributes2 = serializeAttributes,
4189
+ defaultAttributes = {},
4190
+ requiredAttributes = [],
4191
+ allowedAttributes
4192
+ } = options;
4193
+ const blockName = markdownName || nodeName;
4194
+ const filterAttributes = (attrs) => {
4195
+ if (!allowedAttributes) {
4196
+ return attrs;
4197
+ }
4198
+ const filtered = {};
4199
+ allowedAttributes.forEach((key) => {
4200
+ if (key in attrs) {
4201
+ filtered[key] = attrs[key];
4202
+ }
4203
+ });
4204
+ return filtered;
4205
+ };
4206
+ return {
4207
+ parseMarkdown: (token, h2) => {
4208
+ const attrs = { ...defaultAttributes, ...token.attributes };
4209
+ return h2.createNode(nodeName, attrs, []);
4210
+ },
4211
+ markdownTokenizer: {
4212
+ name: nodeName,
4213
+ level: "block",
4214
+ start(src) {
4215
+ var _a;
4216
+ const regex = new RegExp(`^:::${blockName}(?:\\s|$)`, "m");
4217
+ const index = (_a = src.match(regex)) == null ? void 0 : _a.index;
4218
+ return index !== void 0 ? index : -1;
4219
+ },
4220
+ tokenize(src, _tokens, _lexer) {
4221
+ const regex = new RegExp(`^:::${blockName}(?:\\s+\\{([^}]*)\\})?\\s*:::(?:\\n|$)`);
4222
+ const match = src.match(regex);
4223
+ if (!match) {
4224
+ return void 0;
4225
+ }
4226
+ const attrString = match[1] || "";
4227
+ const attributes = parseAttributes2(attrString);
4228
+ const missingRequired = requiredAttributes.find((required) => !(required in attributes));
4229
+ if (missingRequired) {
4230
+ return void 0;
4231
+ }
4232
+ return {
4233
+ type: nodeName,
4234
+ raw: match[0],
4235
+ attributes
4236
+ };
4237
+ }
4238
+ },
4239
+ renderMarkdown: (node) => {
4240
+ const filteredAttrs = filterAttributes(node.attrs || {});
4241
+ const attrs = serializeAttributes2(filteredAttrs);
4242
+ const attrString = attrs ? ` {${attrs}}` : "";
4243
+ return `:::${blockName}${attrString} :::`;
4244
+ }
4245
+ };
4246
+ }
4247
+ function createBlockMarkdownSpec(options) {
4248
+ const {
4249
+ nodeName,
4250
+ name: markdownName,
4251
+ getContent,
4252
+ parseAttributes: parseAttributes2 = parseAttributes,
4253
+ serializeAttributes: serializeAttributes2 = serializeAttributes,
4254
+ defaultAttributes = {},
4255
+ content = "block",
4256
+ allowedAttributes
4257
+ } = options;
4258
+ const blockName = markdownName || nodeName;
4259
+ const filterAttributes = (attrs) => {
4260
+ if (!allowedAttributes) {
4261
+ return attrs;
4262
+ }
4263
+ const filtered = {};
4264
+ allowedAttributes.forEach((key) => {
4265
+ if (key in attrs) {
4266
+ filtered[key] = attrs[key];
4267
+ }
4268
+ });
4269
+ return filtered;
4270
+ };
4271
+ return {
4272
+ parseMarkdown: (token, h2) => {
4273
+ let nodeContent;
4274
+ if (getContent) {
4275
+ const contentResult = getContent(token);
4276
+ nodeContent = typeof contentResult === "string" ? [{ type: "text", text: contentResult }] : contentResult;
4277
+ } else if (content === "block") {
4278
+ nodeContent = h2.parseChildren(token.tokens || []);
4279
+ } else {
4280
+ nodeContent = h2.parseInline(token.tokens || []);
4281
+ }
4282
+ const attrs = { ...defaultAttributes, ...token.attributes };
4283
+ return h2.createNode(nodeName, attrs, nodeContent);
4284
+ },
4285
+ markdownTokenizer: {
4286
+ name: nodeName,
4287
+ level: "block",
4288
+ start(src) {
4289
+ var _a;
4290
+ const regex = new RegExp(`^:::${blockName}`, "m");
4291
+ const index = (_a = src.match(regex)) == null ? void 0 : _a.index;
4292
+ return index !== void 0 ? index : -1;
4293
+ },
4294
+ tokenize(src, _tokens, lexer) {
4295
+ var _a;
4296
+ const openingRegex = new RegExp(`^:::${blockName}(?:\\s+\\{([^}]*)\\})?\\s*\\n`);
4297
+ const openingMatch = src.match(openingRegex);
4298
+ if (!openingMatch) {
4299
+ return void 0;
4300
+ }
4301
+ const [openingTag, attrString = ""] = openingMatch;
4302
+ const attributes = parseAttributes2(attrString);
4303
+ let level = 1;
4304
+ const position = openingTag.length;
4305
+ let matchedContent = "";
4306
+ const blockPattern = /^:::([\w-]*)(\s.*)?/gm;
4307
+ const remaining = src.slice(position);
4308
+ blockPattern.lastIndex = 0;
4309
+ for (; ; ) {
4310
+ const match = blockPattern.exec(remaining);
4311
+ if (match === null) {
4312
+ break;
4313
+ }
4314
+ const matchPos = match.index;
4315
+ const blockType = match[1];
4316
+ if ((_a = match[2]) == null ? void 0 : _a.endsWith(":::")) {
4317
+ continue;
4318
+ }
4319
+ if (blockType) {
4320
+ level += 1;
4321
+ } else {
4322
+ level -= 1;
4323
+ if (level === 0) {
4324
+ const rawContent = remaining.slice(0, matchPos);
4325
+ matchedContent = rawContent.trim();
4326
+ const fullMatch = src.slice(0, position + matchPos + match[0].length);
4327
+ let contentTokens = [];
4328
+ if (matchedContent) {
4329
+ if (content === "block") {
4330
+ contentTokens = lexer.blockTokens(rawContent);
4331
+ contentTokens.forEach((token) => {
4332
+ if (token.text && (!token.tokens || token.tokens.length === 0)) {
4333
+ token.tokens = lexer.inlineTokens(token.text);
4334
+ }
4335
+ });
4336
+ while (contentTokens.length > 0) {
4337
+ const lastToken = contentTokens[contentTokens.length - 1];
4338
+ if (lastToken.type === "paragraph" && (!lastToken.text || lastToken.text.trim() === "")) {
4339
+ contentTokens.pop();
4340
+ } else {
4341
+ break;
4342
+ }
4343
+ }
4344
+ } else {
4345
+ contentTokens = lexer.inlineTokens(matchedContent);
4346
+ }
4347
+ }
4348
+ return {
4349
+ type: nodeName,
4350
+ raw: fullMatch,
4351
+ attributes,
4352
+ content: matchedContent,
4353
+ tokens: contentTokens
4354
+ };
4355
+ }
4356
+ }
4357
+ }
4358
+ return void 0;
4359
+ }
4360
+ },
4361
+ renderMarkdown: (node, h2) => {
4362
+ const filteredAttrs = filterAttributes(node.attrs || {});
4363
+ const attrs = serializeAttributes2(filteredAttrs);
4364
+ const attrString = attrs ? ` {${attrs}}` : "";
4365
+ const renderedContent = h2.renderChildren(node.content || [], "\n\n");
4366
+ return `:::${blockName}${attrString}
4367
+
4368
+ ${renderedContent}
4369
+
4370
+ :::`;
4371
+ }
4372
+ };
4373
+ }
4374
+ function parseShortcodeAttributes(attrString) {
4375
+ if (!attrString.trim()) {
4376
+ return {};
4377
+ }
4378
+ const attributes = {};
4379
+ const regex = /(\w+)=(?:"([^"]*)"|'([^']*)')/g;
4380
+ let match = regex.exec(attrString);
4381
+ while (match !== null) {
4382
+ const [, key, doubleQuoted, singleQuoted] = match;
4383
+ attributes[key] = doubleQuoted || singleQuoted;
4384
+ match = regex.exec(attrString);
4385
+ }
4386
+ return attributes;
4387
+ }
4388
+ function serializeShortcodeAttributes(attrs) {
4389
+ return Object.entries(attrs).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}="${value}"`).join(" ");
4390
+ }
4391
+ function createInlineMarkdownSpec(options) {
4392
+ const {
4393
+ nodeName,
4394
+ name: shortcodeName,
4395
+ getContent,
4396
+ parseAttributes: parseAttributes2 = parseShortcodeAttributes,
4397
+ serializeAttributes: serializeAttributes2 = serializeShortcodeAttributes,
4398
+ defaultAttributes = {},
4399
+ selfClosing = false,
4400
+ allowedAttributes
4401
+ } = options;
4402
+ const shortcode = shortcodeName || nodeName;
4403
+ const filterAttributes = (attrs) => {
4404
+ if (!allowedAttributes) {
4405
+ return attrs;
4406
+ }
4407
+ const filtered = {};
4408
+ allowedAttributes.forEach((attr) => {
4409
+ const attrName = typeof attr === "string" ? attr : attr.name;
4410
+ const skipIfDefault = typeof attr === "string" ? void 0 : attr.skipIfDefault;
4411
+ if (attrName in attrs) {
4412
+ const value = attrs[attrName];
4413
+ if (skipIfDefault !== void 0 && value === skipIfDefault) {
4414
+ return;
4415
+ }
4416
+ filtered[attrName] = value;
4417
+ }
4418
+ });
4419
+ return filtered;
4420
+ };
4421
+ const escapedShortcode = shortcode.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4422
+ return {
4423
+ parseMarkdown: (token, h2) => {
4424
+ const attrs = { ...defaultAttributes, ...token.attributes };
4425
+ if (selfClosing) {
4426
+ return h2.createNode(nodeName, attrs);
4427
+ }
4428
+ const content = getContent ? getContent(token) : token.content || "";
4429
+ if (content) {
4430
+ return h2.createNode(nodeName, attrs, [h2.createTextNode(content)]);
4431
+ }
4432
+ return h2.createNode(nodeName, attrs, []);
4433
+ },
4434
+ markdownTokenizer: {
4435
+ name: nodeName,
4436
+ level: "inline",
4437
+ start(src) {
4438
+ const startPattern = selfClosing ? new RegExp(`\\[${escapedShortcode}\\s*[^\\]]*\\]`) : new RegExp(`\\[${escapedShortcode}\\s*[^\\]]*\\][\\s\\S]*?\\[\\/${escapedShortcode}\\]`);
4439
+ const match = src.match(startPattern);
4440
+ const index = match == null ? void 0 : match.index;
4441
+ return index !== void 0 ? index : -1;
4442
+ },
4443
+ tokenize(src, _tokens, _lexer) {
4444
+ const tokenPattern = selfClosing ? new RegExp(`^\\[${escapedShortcode}\\s*([^\\]]*)\\]`) : new RegExp(
4445
+ `^\\[${escapedShortcode}\\s*([^\\]]*)\\]([\\s\\S]*?)\\[\\/${escapedShortcode}\\]`
4446
+ );
4447
+ const match = src.match(tokenPattern);
4448
+ if (!match) {
4449
+ return void 0;
4450
+ }
4451
+ let content = "";
4452
+ let attrString = "";
4453
+ if (selfClosing) {
4454
+ const [, attrs] = match;
4455
+ attrString = attrs;
4456
+ } else {
4457
+ const [, attrs, contentMatch] = match;
4458
+ attrString = attrs;
4459
+ content = contentMatch || "";
4460
+ }
4461
+ const attributes = parseAttributes2(attrString.trim());
4462
+ return {
4463
+ type: nodeName,
4464
+ raw: match[0],
4465
+ content: content.trim(),
4466
+ attributes
4467
+ };
4468
+ }
4469
+ },
4470
+ renderMarkdown: (node) => {
4471
+ let content = "";
4472
+ if (getContent) {
4473
+ content = getContent(node);
4474
+ } else if (node.content && node.content.length > 0) {
4475
+ content = node.content.filter((child) => child.type === "text").map((child) => child.text).join("");
4476
+ }
4477
+ const filteredAttrs = filterAttributes(node.attrs || {});
4478
+ const attrs = serializeAttributes2(filteredAttrs);
4479
+ const attrString = attrs ? ` ${attrs}` : "";
4480
+ if (selfClosing) {
4481
+ return `[${shortcode}${attrString}]`;
4482
+ }
4483
+ return `[${shortcode}${attrString}]${content}[/${shortcode}]`;
4484
+ }
4485
+ };
4486
+ }
4487
+ function parseIndentedBlocks(src, config, lexer) {
4488
+ var _a, _b, _c, _d;
4489
+ const lines = src.split("\n");
4490
+ const items = [];
4491
+ let totalRaw = "";
4492
+ let i = 0;
4493
+ const baseIndentSize = config.baseIndentSize || 2;
4494
+ while (i < lines.length) {
4495
+ const currentLine = lines[i];
4496
+ const itemMatch = currentLine.match(config.itemPattern);
4497
+ if (!itemMatch) {
4498
+ if (items.length > 0) {
4499
+ break;
4500
+ } else if (currentLine.trim() === "") {
4501
+ i += 1;
4502
+ totalRaw = `${totalRaw}${currentLine}
4503
+ `;
4504
+ continue;
4505
+ } else {
4506
+ return void 0;
4507
+ }
4508
+ }
4509
+ const itemData = config.extractItemData(itemMatch);
4510
+ const { indentLevel, mainContent } = itemData;
4511
+ totalRaw = `${totalRaw}${currentLine}
4512
+ `;
4513
+ const itemContent = [mainContent];
4514
+ i += 1;
4515
+ while (i < lines.length) {
4516
+ const nextLine = lines[i];
4517
+ if (nextLine.trim() === "") {
4518
+ const nextNonEmptyIndex = lines.slice(i + 1).findIndex((l) => l.trim() !== "");
4519
+ if (nextNonEmptyIndex === -1) {
4520
+ break;
4521
+ }
4522
+ const nextNonEmpty = lines[i + 1 + nextNonEmptyIndex];
4523
+ const nextIndent2 = ((_b = (_a = nextNonEmpty.match(/^(\s*)/)) == null ? void 0 : _a[1]) == null ? void 0 : _b.length) || 0;
4524
+ if (nextIndent2 > indentLevel) {
4525
+ itemContent.push(nextLine);
4526
+ totalRaw = `${totalRaw}${nextLine}
4527
+ `;
4528
+ i += 1;
4529
+ continue;
4530
+ } else {
4531
+ break;
4532
+ }
4533
+ }
4534
+ const nextIndent = ((_d = (_c = nextLine.match(/^(\s*)/)) == null ? void 0 : _c[1]) == null ? void 0 : _d.length) || 0;
4535
+ if (nextIndent > indentLevel) {
4536
+ itemContent.push(nextLine);
4537
+ totalRaw = `${totalRaw}${nextLine}
4538
+ `;
4539
+ i += 1;
4540
+ } else {
4541
+ break;
4542
+ }
4543
+ }
4544
+ let nestedTokens;
4545
+ const nestedContent = itemContent.slice(1);
4546
+ if (nestedContent.length > 0) {
4547
+ const dedentedNested = nestedContent.map((nestedLine) => nestedLine.slice(indentLevel + baseIndentSize)).join("\n");
4548
+ if (dedentedNested.trim()) {
4549
+ if (config.customNestedParser) {
4550
+ nestedTokens = config.customNestedParser(dedentedNested);
4551
+ } else {
4552
+ nestedTokens = lexer.blockTokens(dedentedNested);
4553
+ }
4554
+ }
4555
+ }
4556
+ const token = config.createToken(itemData, nestedTokens);
4557
+ items.push(token);
4558
+ }
4559
+ if (items.length === 0) {
4560
+ return void 0;
4561
+ }
4562
+ return {
4563
+ items,
4564
+ raw: totalRaw
4565
+ };
4566
+ }
4567
+ function renderNestedMarkdownContent(node, h2, prefixOrGenerator, ctx) {
4568
+ if (!node || !Array.isArray(node.content)) {
4569
+ return "";
4570
+ }
4571
+ const prefix = typeof prefixOrGenerator === "function" ? prefixOrGenerator(ctx) : prefixOrGenerator;
4572
+ const [content, ...children] = node.content;
4573
+ const mainContent = h2.renderChildren([content]);
4574
+ let output = `${prefix}${mainContent}`;
4575
+ if (children && children.length > 0) {
4576
+ children.forEach((child, index) => {
4577
+ var _a, _b;
4578
+ const childContent = (_b = (_a = h2.renderChild) == null ? void 0 : _a.call(h2, child, index + 1)) != null ? _b : h2.renderChildren([child]);
4579
+ if (childContent !== void 0 && childContent !== null) {
4580
+ const indentedChild = childContent.split("\n").map((line) => line ? h2.indent(line) : h2.indent("")).join("\n");
4581
+ output += child.type === "paragraph" ? `
4582
+
4583
+ ${indentedChild}` : `
4584
+ ${indentedChild}`;
4585
+ }
4586
+ });
4587
+ }
4588
+ return output;
4589
+ }
4590
+ var Node3 = class _Node extends Extendable {
4591
+ constructor() {
4592
+ super(...arguments);
4593
+ this.type = "node";
4594
+ }
4595
+ /**
4596
+ * Create a new Node instance
4597
+ * @param config - Node configuration object or a function that returns a configuration object
4598
+ */
4599
+ static create(config = {}) {
4600
+ const resolvedConfig = typeof config === "function" ? config() : config;
4601
+ return new _Node(resolvedConfig);
4602
+ }
4603
+ configure(options) {
4604
+ return super.configure(options);
4605
+ }
4606
+ extend(extendedConfig) {
4607
+ const resolvedConfig = typeof extendedConfig === "function" ? extendedConfig() : extendedConfig;
4608
+ return super.extend(resolvedConfig);
4609
+ }
4610
+ };
4611
+
4612
+ // src/components/RichTextEditor/extensions/Highlight.ts
4613
+ var Highlight = Mark.create({
4614
+ name: "highlight",
4615
+ renderHTML({ HTMLAttributes }) {
4616
+ return ["mark", { style: "background: #fef08a; border-radius: 2px; padding: 0 2px;", ...HTMLAttributes }, 0];
4617
+ },
4618
+ parseHTML() {
4619
+ return [{ tag: "mark" }];
4620
+ },
4621
+ addKeyboardShortcuts() {
4622
+ return {
4623
+ "Mod-Shift-h": () => this.editor.commands.toggleMark(this.name)
4624
+ };
4625
+ }
4626
+ });
4627
+ var HighlightIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: [
4628
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "1", y: "8", width: "12", height: "3", rx: "1", fill: "#fef08a", stroke: "currentColor", strokeWidth: "1" }),
4629
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 8L5.5 3h3L10 8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }),
4630
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "4.5", y1: "6", x2: "9.5", y2: "6", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" })
4631
+ ] });
4632
+ var HighlightButton = () => {
4633
+ const { editor } = react.useCurrentEditor();
4634
+ if (!editor) return null;
4635
+ const active = editor.isActive("highlight");
4636
+ return /* @__PURE__ */ jsxRuntime.jsx(
4637
+ "button",
4638
+ {
4639
+ type: "button",
4640
+ title: "Highlight (Mod+Shift+H)",
4641
+ "aria-label": "Highlight",
4642
+ "aria-pressed": active,
4643
+ className: [RichTextEditor_module_default.toolbarButton, active ? RichTextEditor_module_default.active : ""].filter(Boolean).join(" "),
4644
+ onMouseDown: (e) => {
4645
+ e.preventDefault();
4646
+ editor.chain().focus().toggleMark("highlight").run();
4647
+ },
4648
+ children: /* @__PURE__ */ jsxRuntime.jsx(HighlightIcon, {})
4649
+ }
4650
+ );
4651
+ };
4652
+
4653
+ // src/components/RichTextEditor/extensions/PageBreak.ts
4654
+ var PageBreak = Node3.create({
4655
+ name: "pageBreak",
4656
+ group: "block",
4657
+ atom: true,
4658
+ parseHTML() {
4659
+ return [{ tag: 'div[data-type="page-break"]' }];
4660
+ },
4661
+ renderHTML({ HTMLAttributes }) {
4662
+ return ["div", mergeAttributes(HTMLAttributes, { "data-type": "page-break" })];
4663
+ },
4664
+ addKeyboardShortcuts() {
4665
+ return {
4666
+ "Mod-Enter": () => this.editor.commands.insertContent({ type: this.name })
4667
+ };
4668
+ }
4669
+ });
4670
+ var PageBreakIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [
4671
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "1", width: "10", height: "6", rx: "1", stroke: "currentColor", strokeWidth: "1.2" }),
4672
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "9", width: "10", height: "6", rx: "1", stroke: "currentColor", strokeWidth: "1.2" }),
4673
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "1", y1: "8", x2: "5", y2: "8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeDasharray: "1.5 1.5" }),
4674
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "7", y1: "8", x2: "9", y2: "8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeDasharray: "1.5 1.5" }),
4675
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "11", y1: "8", x2: "15", y2: "8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeDasharray: "1.5 1.5" })
4676
+ ] });
4677
+ var PageBreakButton = () => {
4678
+ const { editor } = react.useCurrentEditor();
4679
+ if (!editor) return null;
4680
+ return /* @__PURE__ */ jsxRuntime.jsx(
4681
+ "button",
4682
+ {
4683
+ type: "button",
4684
+ title: "Page break (Mod+Enter)",
4685
+ "aria-label": "Insert page break",
4686
+ className: RichTextEditor_module_default.toolbarButton,
4687
+ onMouseDown: (e) => {
4688
+ e.preventDefault();
4689
+ editor.chain().focus().insertContent({ type: "pageBreak" }).run();
4690
+ },
4691
+ children: /* @__PURE__ */ jsxRuntime.jsx(PageBreakIcon, {})
4692
+ }
4693
+ );
4694
+ };
4695
+
4696
+ Object.defineProperty(exports, "useCurrentEditor", {
4697
+ enumerable: true,
4698
+ get: function () { return react.useCurrentEditor; }
4699
+ });
999
4700
  exports.Badge = Badge;
1000
4701
  exports.Button = Button;
1001
4702
  exports.ColorPicker = ColorPicker;
4703
+ exports.Highlight = Highlight;
4704
+ exports.HighlightButton = HighlightButton;
1002
4705
  exports.Input = Input;
4706
+ exports.PageBreak = PageBreak;
4707
+ exports.PageBreakButton = PageBreakButton;
1003
4708
  exports.RainCanvas = RainCanvas;
4709
+ exports.RichTextEditor = RichTextEditor;
4710
+ exports.SliderControl = SliderControl;
4711
+ exports.SlidingCounter = SlidingCounter;
1004
4712
  exports.Timeline = Timeline;
1005
4713
  //# sourceMappingURL=index.cjs.map
1006
4714
  //# sourceMappingURL=index.cjs.map