@mhamz.01/easyflow-texteditor 0.1.149 → 0.1.151

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2900,6 +2900,54 @@ function useTiptapEditor(providedEditor) {
2900
2900
  return editorState || { editor: null };
2901
2901
  }
2902
2902
 
2903
+ // src/hooks/mark-preservers/mark-preserver.ts
2904
+ var MarkPreserver = class {
2905
+ static preservedMarks = /* @__PURE__ */ new Map();
2906
+ /**
2907
+ * Preserve marks before an action that will cause blur
2908
+ * Call this in onMouseDown or onPointerDown events
2909
+ */
2910
+ static preserve(editor) {
2911
+ if (!editor) return;
2912
+ const { state } = editor;
2913
+ const { $from } = state.selection;
2914
+ const currentMarks = state.storedMarks || $from.marks();
2915
+ if (currentMarks.length > 0) {
2916
+ this.preservedMarks.set(editor, [...currentMarks]);
2917
+ }
2918
+ }
2919
+ /**
2920
+ * Restore marks after an action completes
2921
+ * Call this after the editor action in onClick or in a setTimeout
2922
+ */
2923
+ static restore(editor, delay = 0) {
2924
+ if (!editor) return;
2925
+ const marks = this.preservedMarks.get(editor);
2926
+ if (!marks) return;
2927
+ const restoreFn = () => {
2928
+ if (editor.isDestroyed) {
2929
+ this.preservedMarks.delete(editor);
2930
+ return;
2931
+ }
2932
+ const { state } = editor;
2933
+ editor.view.dispatch(state.tr.setStoredMarks(marks));
2934
+ this.preservedMarks.delete(editor);
2935
+ editor.commands.focus();
2936
+ };
2937
+ if (delay > 0) {
2938
+ setTimeout(restoreFn, delay);
2939
+ } else {
2940
+ restoreFn();
2941
+ }
2942
+ }
2943
+ /**
2944
+ * Clear preserved marks for an editor
2945
+ */
2946
+ static clear(editor) {
2947
+ this.preservedMarks.delete(editor);
2948
+ }
2949
+ };
2950
+
2903
2951
  // src/components/tiptap-ui/heading-button/heading-button.tsx
2904
2952
  var import_react28 = require("react");
2905
2953
 
@@ -3504,9 +3552,15 @@ var HeadingDropdownMenu = (0, import_react38.forwardRef)(
3504
3552
  if (!editor || !canToggle2) return;
3505
3553
  setIsOpen(open);
3506
3554
  onOpenChange?.(open);
3555
+ if (!open) {
3556
+ MarkPreserver.restore(editor, 10);
3557
+ }
3507
3558
  },
3508
3559
  [canToggle2, editor, onOpenChange]
3509
3560
  );
3561
+ const handlePointerDown = (0, import_react38.useCallback)(() => {
3562
+ MarkPreserver.preserve(editor);
3563
+ }, [editor]);
3510
3564
  if (!isVisible) {
3511
3565
  return null;
3512
3566
  }
@@ -3522,6 +3576,7 @@ var HeadingDropdownMenu = (0, import_react38.forwardRef)(
3522
3576
  "aria-label": "Format text as heading",
3523
3577
  "aria-pressed": isActive,
3524
3578
  tooltip: "Heading",
3579
+ onPointerDown: handlePointerDown,
3525
3580
  ...buttonProps,
3526
3581
  ref,
3527
3582
  children: [
@@ -4409,9 +4464,15 @@ function ListDropdownMenu({
4409
4464
  (open) => {
4410
4465
  setIsOpen(open);
4411
4466
  onOpenChange?.(open);
4467
+ if (!open) {
4468
+ MarkPreserver.restore(editor, 10);
4469
+ }
4412
4470
  },
4413
- [onOpenChange]
4471
+ [onOpenChange, editor]
4414
4472
  );
4473
+ const handlePointerDown = (0, import_react51.useCallback)(() => {
4474
+ MarkPreserver.preserve(editor);
4475
+ }, [editor]);
4415
4476
  if (!isVisible) {
4416
4477
  return null;
4417
4478
  }
@@ -4428,6 +4489,7 @@ function ListDropdownMenu({
4428
4489
  "data-disabled": !canToggle2,
4429
4490
  "aria-label": "List options",
4430
4491
  tooltip: "List",
4492
+ onPointerDown: handlePointerDown,
4431
4493
  ...props,
4432
4494
  children: [
4433
4495
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Icon, { className: "tiptap-button-icon" }),
@@ -4449,56 +4511,6 @@ function ListDropdownMenu({
4449
4511
 
4450
4512
  // src/components/tiptap-ui/blockquote-button/blockquote-button.tsx
4451
4513
  var import_react52 = require("react");
4452
-
4453
- // src/hooks/mark-preservers/mark-preserver.ts
4454
- var MarkPreserver = class {
4455
- static preservedMarks = /* @__PURE__ */ new Map();
4456
- /**
4457
- * Preserve marks before an action that will cause blur
4458
- * Call this in onMouseDown or onPointerDown events
4459
- */
4460
- static preserve(editor) {
4461
- if (!editor) return;
4462
- const { state } = editor;
4463
- const { $from } = state.selection;
4464
- const currentMarks = state.storedMarks || $from.marks();
4465
- if (currentMarks.length > 0) {
4466
- this.preservedMarks.set(editor, [...currentMarks]);
4467
- }
4468
- }
4469
- /**
4470
- * Restore marks after an action completes
4471
- * Call this after the editor action in onClick or in a setTimeout
4472
- */
4473
- static restore(editor, delay = 0) {
4474
- if (!editor) return;
4475
- const marks = this.preservedMarks.get(editor);
4476
- if (!marks) return;
4477
- const restoreFn = () => {
4478
- if (editor.isDestroyed) {
4479
- this.preservedMarks.delete(editor);
4480
- return;
4481
- }
4482
- const { state } = editor;
4483
- editor.view.dispatch(state.tr.setStoredMarks(marks));
4484
- this.preservedMarks.delete(editor);
4485
- editor.commands.focus();
4486
- };
4487
- if (delay > 0) {
4488
- setTimeout(restoreFn, delay);
4489
- } else {
4490
- restoreFn();
4491
- }
4492
- }
4493
- /**
4494
- * Clear preserved marks for an editor
4495
- */
4496
- static clear(editor) {
4497
- this.preservedMarks.delete(editor);
4498
- }
4499
- };
4500
-
4501
- // src/components/tiptap-ui/blockquote-button/blockquote-button.tsx
4502
4514
  var import_jsx_runtime45 = require("react/jsx-runtime");
4503
4515
  function BlockquoteShortcutBadge({
4504
4516
  shortcutKeys = BLOCKQUOTE_SHORTCUT_KEY
@@ -7712,29 +7724,80 @@ var StylePersistence = import_core4.Extension.create({
7712
7724
  excludedMarks: ["code", "codeBlock"]
7713
7725
  };
7714
7726
  },
7727
+ addStorage() {
7728
+ return {
7729
+ // Store marks temporarily when editor loses focus
7730
+ preservedMarks: null,
7731
+ // Store marks from the previous node (for Enter key handling)
7732
+ previousNodeMarks: null
7733
+ };
7734
+ },
7735
+ addKeyboardShortcuts() {
7736
+ return {
7737
+ // Handle Enter key to preserve marks when creating new paragraphs
7738
+ "Enter": ({ editor }) => {
7739
+ const { state } = editor;
7740
+ const { $from } = state.selection;
7741
+ const currentNode = $from.parent;
7742
+ const blockFont = currentNode.attrs.fontFamily;
7743
+ const blockColor = currentNode.attrs.color;
7744
+ if (blockFont || blockColor) {
7745
+ this.storage.previousNodeMarks = { blockFont, blockColor };
7746
+ }
7747
+ return false;
7748
+ },
7749
+ // Handle Shift+Enter (soft break) - same logic
7750
+ "Shift-Enter": ({ editor }) => {
7751
+ const { state } = editor;
7752
+ const { $from } = state.selection;
7753
+ const currentNode = $from.parent;
7754
+ const blockFont = currentNode.attrs.fontFamily;
7755
+ const blockColor = currentNode.attrs.color;
7756
+ if (blockFont || blockColor) {
7757
+ this.storage.previousNodeMarks = { blockFont, blockColor };
7758
+ }
7759
+ return false;
7760
+ }
7761
+ };
7762
+ },
7715
7763
  onSelectionUpdate({ editor }) {
7716
7764
  const excludedMarks = this.options.excludedMarks;
7717
- syncStoredMarks(editor, excludedMarks);
7765
+ syncStoredMarks(editor, excludedMarks, this.storage);
7718
7766
  },
7719
7767
  onFocus({ editor }) {
7720
7768
  const excludedMarks = this.options.excludedMarks;
7721
- syncStoredMarks(editor, excludedMarks);
7769
+ if (this.storage.preservedMarks) {
7770
+ editor.view.dispatch(
7771
+ editor.state.tr.setStoredMarks(this.storage.preservedMarks)
7772
+ );
7773
+ this.storage.preservedMarks = null;
7774
+ }
7775
+ syncStoredMarks(editor, excludedMarks, this.storage);
7776
+ },
7777
+ onBlur({ editor }) {
7778
+ const { state } = editor;
7779
+ const { $from } = state.selection;
7780
+ const currentMarks = state.storedMarks || $from.marks();
7781
+ const hasTextStyle = currentMarks.some((mark) => mark.type.name === "textStyle");
7782
+ if (hasTextStyle) {
7783
+ this.storage.preservedMarks = currentMarks;
7784
+ }
7722
7785
  },
7723
7786
  onCreate({ editor }) {
7724
7787
  const excludedMarks = this.options.excludedMarks;
7725
- syncStoredMarks(editor, excludedMarks);
7788
+ syncStoredMarks(editor, excludedMarks, this.storage);
7726
7789
  },
7727
7790
  onTransaction({ editor, transaction }) {
7728
7791
  if (!transaction.selectionSet && !transaction.docChanged) return;
7729
7792
  const excludedMarks = this.options.excludedMarks;
7730
7793
  requestAnimationFrame(() => {
7731
7794
  if (!editor.isDestroyed) {
7732
- syncStoredMarks(editor, excludedMarks);
7795
+ syncStoredMarks(editor, excludedMarks, this.storage);
7733
7796
  }
7734
7797
  });
7735
7798
  }
7736
7799
  });
7737
- function syncStoredMarks(editor, excludedMarks) {
7800
+ function syncStoredMarks(editor, excludedMarks, storage) {
7738
7801
  const { state } = editor;
7739
7802
  const { $from } = state.selection;
7740
7803
  const marks = $from.marks();
@@ -7753,8 +7816,27 @@ function syncStoredMarks(editor, excludedMarks) {
7753
7816
  return;
7754
7817
  }
7755
7818
  const parentNode = $from.parent;
7756
- const blockFont = parentNode.attrs.fontFamily;
7757
- const blockColor = parentNode.attrs.color;
7819
+ let blockFont = parentNode.attrs.fontFamily;
7820
+ let blockColor = parentNode.attrs.color;
7821
+ if ((!blockFont || !blockColor) && storage?.previousNodeMarks) {
7822
+ if (!blockFont && storage.previousNodeMarks.blockFont) {
7823
+ blockFont = storage.previousNodeMarks.blockFont;
7824
+ }
7825
+ if (!blockColor && storage.previousNodeMarks.blockColor) {
7826
+ blockColor = storage.previousNodeMarks.blockColor;
7827
+ }
7828
+ if (blockFont || blockColor) {
7829
+ const depth = $from.depth;
7830
+ const nodePos = $from.before(depth);
7831
+ const node = $from.node(depth);
7832
+ const newAttrs = { ...node.attrs };
7833
+ if (blockFont) newAttrs.fontFamily = blockFont;
7834
+ if (blockColor) newAttrs.color = blockColor;
7835
+ const tr = state.tr.setNodeMarkup(nodePos, void 0, newAttrs);
7836
+ editor.view.dispatch(tr);
7837
+ }
7838
+ storage.previousNodeMarks = null;
7839
+ }
7758
7840
  if (!blockFont && !blockColor) {
7759
7841
  return;
7760
7842
  }