@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.css +24 -24
- package/dist/index.css.map +1 -1
- package/dist/index.js +140 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +140 -58
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2874,6 +2874,54 @@ function useTiptapEditor(providedEditor) {
|
|
|
2874
2874
|
return editorState || { editor: null };
|
|
2875
2875
|
}
|
|
2876
2876
|
|
|
2877
|
+
// src/hooks/mark-preservers/mark-preserver.ts
|
|
2878
|
+
var MarkPreserver = class {
|
|
2879
|
+
static preservedMarks = /* @__PURE__ */ new Map();
|
|
2880
|
+
/**
|
|
2881
|
+
* Preserve marks before an action that will cause blur
|
|
2882
|
+
* Call this in onMouseDown or onPointerDown events
|
|
2883
|
+
*/
|
|
2884
|
+
static preserve(editor) {
|
|
2885
|
+
if (!editor) return;
|
|
2886
|
+
const { state } = editor;
|
|
2887
|
+
const { $from } = state.selection;
|
|
2888
|
+
const currentMarks = state.storedMarks || $from.marks();
|
|
2889
|
+
if (currentMarks.length > 0) {
|
|
2890
|
+
this.preservedMarks.set(editor, [...currentMarks]);
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
/**
|
|
2894
|
+
* Restore marks after an action completes
|
|
2895
|
+
* Call this after the editor action in onClick or in a setTimeout
|
|
2896
|
+
*/
|
|
2897
|
+
static restore(editor, delay = 0) {
|
|
2898
|
+
if (!editor) return;
|
|
2899
|
+
const marks = this.preservedMarks.get(editor);
|
|
2900
|
+
if (!marks) return;
|
|
2901
|
+
const restoreFn = () => {
|
|
2902
|
+
if (editor.isDestroyed) {
|
|
2903
|
+
this.preservedMarks.delete(editor);
|
|
2904
|
+
return;
|
|
2905
|
+
}
|
|
2906
|
+
const { state } = editor;
|
|
2907
|
+
editor.view.dispatch(state.tr.setStoredMarks(marks));
|
|
2908
|
+
this.preservedMarks.delete(editor);
|
|
2909
|
+
editor.commands.focus();
|
|
2910
|
+
};
|
|
2911
|
+
if (delay > 0) {
|
|
2912
|
+
setTimeout(restoreFn, delay);
|
|
2913
|
+
} else {
|
|
2914
|
+
restoreFn();
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
/**
|
|
2918
|
+
* Clear preserved marks for an editor
|
|
2919
|
+
*/
|
|
2920
|
+
static clear(editor) {
|
|
2921
|
+
this.preservedMarks.delete(editor);
|
|
2922
|
+
}
|
|
2923
|
+
};
|
|
2924
|
+
|
|
2877
2925
|
// src/components/tiptap-ui/heading-button/heading-button.tsx
|
|
2878
2926
|
import { forwardRef as forwardRef6, useCallback as useCallback8 } from "react";
|
|
2879
2927
|
|
|
@@ -3478,9 +3526,15 @@ var HeadingDropdownMenu = forwardRef9(
|
|
|
3478
3526
|
if (!editor || !canToggle2) return;
|
|
3479
3527
|
setIsOpen(open);
|
|
3480
3528
|
onOpenChange?.(open);
|
|
3529
|
+
if (!open) {
|
|
3530
|
+
MarkPreserver.restore(editor, 10);
|
|
3531
|
+
}
|
|
3481
3532
|
},
|
|
3482
3533
|
[canToggle2, editor, onOpenChange]
|
|
3483
3534
|
);
|
|
3535
|
+
const handlePointerDown = useCallback10(() => {
|
|
3536
|
+
MarkPreserver.preserve(editor);
|
|
3537
|
+
}, [editor]);
|
|
3484
3538
|
if (!isVisible) {
|
|
3485
3539
|
return null;
|
|
3486
3540
|
}
|
|
@@ -3496,6 +3550,7 @@ var HeadingDropdownMenu = forwardRef9(
|
|
|
3496
3550
|
"aria-label": "Format text as heading",
|
|
3497
3551
|
"aria-pressed": isActive,
|
|
3498
3552
|
tooltip: "Heading",
|
|
3553
|
+
onPointerDown: handlePointerDown,
|
|
3499
3554
|
...buttonProps,
|
|
3500
3555
|
ref,
|
|
3501
3556
|
children: [
|
|
@@ -4383,9 +4438,15 @@ function ListDropdownMenu({
|
|
|
4383
4438
|
(open) => {
|
|
4384
4439
|
setIsOpen(open);
|
|
4385
4440
|
onOpenChange?.(open);
|
|
4441
|
+
if (!open) {
|
|
4442
|
+
MarkPreserver.restore(editor, 10);
|
|
4443
|
+
}
|
|
4386
4444
|
},
|
|
4387
|
-
[onOpenChange]
|
|
4445
|
+
[onOpenChange, editor]
|
|
4388
4446
|
);
|
|
4447
|
+
const handlePointerDown = useCallback15(() => {
|
|
4448
|
+
MarkPreserver.preserve(editor);
|
|
4449
|
+
}, [editor]);
|
|
4389
4450
|
if (!isVisible) {
|
|
4390
4451
|
return null;
|
|
4391
4452
|
}
|
|
@@ -4402,6 +4463,7 @@ function ListDropdownMenu({
|
|
|
4402
4463
|
"data-disabled": !canToggle2,
|
|
4403
4464
|
"aria-label": "List options",
|
|
4404
4465
|
tooltip: "List",
|
|
4466
|
+
onPointerDown: handlePointerDown,
|
|
4405
4467
|
...props,
|
|
4406
4468
|
children: [
|
|
4407
4469
|
/* @__PURE__ */ jsx44(Icon, { className: "tiptap-button-icon" }),
|
|
@@ -4423,56 +4485,6 @@ function ListDropdownMenu({
|
|
|
4423
4485
|
|
|
4424
4486
|
// src/components/tiptap-ui/blockquote-button/blockquote-button.tsx
|
|
4425
4487
|
import { forwardRef as forwardRef12, useCallback as useCallback16 } from "react";
|
|
4426
|
-
|
|
4427
|
-
// src/hooks/mark-preservers/mark-preserver.ts
|
|
4428
|
-
var MarkPreserver = class {
|
|
4429
|
-
static preservedMarks = /* @__PURE__ */ new Map();
|
|
4430
|
-
/**
|
|
4431
|
-
* Preserve marks before an action that will cause blur
|
|
4432
|
-
* Call this in onMouseDown or onPointerDown events
|
|
4433
|
-
*/
|
|
4434
|
-
static preserve(editor) {
|
|
4435
|
-
if (!editor) return;
|
|
4436
|
-
const { state } = editor;
|
|
4437
|
-
const { $from } = state.selection;
|
|
4438
|
-
const currentMarks = state.storedMarks || $from.marks();
|
|
4439
|
-
if (currentMarks.length > 0) {
|
|
4440
|
-
this.preservedMarks.set(editor, [...currentMarks]);
|
|
4441
|
-
}
|
|
4442
|
-
}
|
|
4443
|
-
/**
|
|
4444
|
-
* Restore marks after an action completes
|
|
4445
|
-
* Call this after the editor action in onClick or in a setTimeout
|
|
4446
|
-
*/
|
|
4447
|
-
static restore(editor, delay = 0) {
|
|
4448
|
-
if (!editor) return;
|
|
4449
|
-
const marks = this.preservedMarks.get(editor);
|
|
4450
|
-
if (!marks) return;
|
|
4451
|
-
const restoreFn = () => {
|
|
4452
|
-
if (editor.isDestroyed) {
|
|
4453
|
-
this.preservedMarks.delete(editor);
|
|
4454
|
-
return;
|
|
4455
|
-
}
|
|
4456
|
-
const { state } = editor;
|
|
4457
|
-
editor.view.dispatch(state.tr.setStoredMarks(marks));
|
|
4458
|
-
this.preservedMarks.delete(editor);
|
|
4459
|
-
editor.commands.focus();
|
|
4460
|
-
};
|
|
4461
|
-
if (delay > 0) {
|
|
4462
|
-
setTimeout(restoreFn, delay);
|
|
4463
|
-
} else {
|
|
4464
|
-
restoreFn();
|
|
4465
|
-
}
|
|
4466
|
-
}
|
|
4467
|
-
/**
|
|
4468
|
-
* Clear preserved marks for an editor
|
|
4469
|
-
*/
|
|
4470
|
-
static clear(editor) {
|
|
4471
|
-
this.preservedMarks.delete(editor);
|
|
4472
|
-
}
|
|
4473
|
-
};
|
|
4474
|
-
|
|
4475
|
-
// src/components/tiptap-ui/blockquote-button/blockquote-button.tsx
|
|
4476
4488
|
import { Fragment as Fragment7, jsx as jsx45, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4477
4489
|
function BlockquoteShortcutBadge({
|
|
4478
4490
|
shortcutKeys = BLOCKQUOTE_SHORTCUT_KEY
|
|
@@ -7686,29 +7698,80 @@ var StylePersistence = Extension2.create({
|
|
|
7686
7698
|
excludedMarks: ["code", "codeBlock"]
|
|
7687
7699
|
};
|
|
7688
7700
|
},
|
|
7701
|
+
addStorage() {
|
|
7702
|
+
return {
|
|
7703
|
+
// Store marks temporarily when editor loses focus
|
|
7704
|
+
preservedMarks: null,
|
|
7705
|
+
// Store marks from the previous node (for Enter key handling)
|
|
7706
|
+
previousNodeMarks: null
|
|
7707
|
+
};
|
|
7708
|
+
},
|
|
7709
|
+
addKeyboardShortcuts() {
|
|
7710
|
+
return {
|
|
7711
|
+
// Handle Enter key to preserve marks when creating new paragraphs
|
|
7712
|
+
"Enter": ({ editor }) => {
|
|
7713
|
+
const { state } = editor;
|
|
7714
|
+
const { $from } = state.selection;
|
|
7715
|
+
const currentNode = $from.parent;
|
|
7716
|
+
const blockFont = currentNode.attrs.fontFamily;
|
|
7717
|
+
const blockColor = currentNode.attrs.color;
|
|
7718
|
+
if (blockFont || blockColor) {
|
|
7719
|
+
this.storage.previousNodeMarks = { blockFont, blockColor };
|
|
7720
|
+
}
|
|
7721
|
+
return false;
|
|
7722
|
+
},
|
|
7723
|
+
// Handle Shift+Enter (soft break) - same logic
|
|
7724
|
+
"Shift-Enter": ({ editor }) => {
|
|
7725
|
+
const { state } = editor;
|
|
7726
|
+
const { $from } = state.selection;
|
|
7727
|
+
const currentNode = $from.parent;
|
|
7728
|
+
const blockFont = currentNode.attrs.fontFamily;
|
|
7729
|
+
const blockColor = currentNode.attrs.color;
|
|
7730
|
+
if (blockFont || blockColor) {
|
|
7731
|
+
this.storage.previousNodeMarks = { blockFont, blockColor };
|
|
7732
|
+
}
|
|
7733
|
+
return false;
|
|
7734
|
+
}
|
|
7735
|
+
};
|
|
7736
|
+
},
|
|
7689
7737
|
onSelectionUpdate({ editor }) {
|
|
7690
7738
|
const excludedMarks = this.options.excludedMarks;
|
|
7691
|
-
syncStoredMarks(editor, excludedMarks);
|
|
7739
|
+
syncStoredMarks(editor, excludedMarks, this.storage);
|
|
7692
7740
|
},
|
|
7693
7741
|
onFocus({ editor }) {
|
|
7694
7742
|
const excludedMarks = this.options.excludedMarks;
|
|
7695
|
-
|
|
7743
|
+
if (this.storage.preservedMarks) {
|
|
7744
|
+
editor.view.dispatch(
|
|
7745
|
+
editor.state.tr.setStoredMarks(this.storage.preservedMarks)
|
|
7746
|
+
);
|
|
7747
|
+
this.storage.preservedMarks = null;
|
|
7748
|
+
}
|
|
7749
|
+
syncStoredMarks(editor, excludedMarks, this.storage);
|
|
7750
|
+
},
|
|
7751
|
+
onBlur({ editor }) {
|
|
7752
|
+
const { state } = editor;
|
|
7753
|
+
const { $from } = state.selection;
|
|
7754
|
+
const currentMarks = state.storedMarks || $from.marks();
|
|
7755
|
+
const hasTextStyle = currentMarks.some((mark) => mark.type.name === "textStyle");
|
|
7756
|
+
if (hasTextStyle) {
|
|
7757
|
+
this.storage.preservedMarks = currentMarks;
|
|
7758
|
+
}
|
|
7696
7759
|
},
|
|
7697
7760
|
onCreate({ editor }) {
|
|
7698
7761
|
const excludedMarks = this.options.excludedMarks;
|
|
7699
|
-
syncStoredMarks(editor, excludedMarks);
|
|
7762
|
+
syncStoredMarks(editor, excludedMarks, this.storage);
|
|
7700
7763
|
},
|
|
7701
7764
|
onTransaction({ editor, transaction }) {
|
|
7702
7765
|
if (!transaction.selectionSet && !transaction.docChanged) return;
|
|
7703
7766
|
const excludedMarks = this.options.excludedMarks;
|
|
7704
7767
|
requestAnimationFrame(() => {
|
|
7705
7768
|
if (!editor.isDestroyed) {
|
|
7706
|
-
syncStoredMarks(editor, excludedMarks);
|
|
7769
|
+
syncStoredMarks(editor, excludedMarks, this.storage);
|
|
7707
7770
|
}
|
|
7708
7771
|
});
|
|
7709
7772
|
}
|
|
7710
7773
|
});
|
|
7711
|
-
function syncStoredMarks(editor, excludedMarks) {
|
|
7774
|
+
function syncStoredMarks(editor, excludedMarks, storage) {
|
|
7712
7775
|
const { state } = editor;
|
|
7713
7776
|
const { $from } = state.selection;
|
|
7714
7777
|
const marks = $from.marks();
|
|
@@ -7727,8 +7790,27 @@ function syncStoredMarks(editor, excludedMarks) {
|
|
|
7727
7790
|
return;
|
|
7728
7791
|
}
|
|
7729
7792
|
const parentNode = $from.parent;
|
|
7730
|
-
|
|
7731
|
-
|
|
7793
|
+
let blockFont = parentNode.attrs.fontFamily;
|
|
7794
|
+
let blockColor = parentNode.attrs.color;
|
|
7795
|
+
if ((!blockFont || !blockColor) && storage?.previousNodeMarks) {
|
|
7796
|
+
if (!blockFont && storage.previousNodeMarks.blockFont) {
|
|
7797
|
+
blockFont = storage.previousNodeMarks.blockFont;
|
|
7798
|
+
}
|
|
7799
|
+
if (!blockColor && storage.previousNodeMarks.blockColor) {
|
|
7800
|
+
blockColor = storage.previousNodeMarks.blockColor;
|
|
7801
|
+
}
|
|
7802
|
+
if (blockFont || blockColor) {
|
|
7803
|
+
const depth = $from.depth;
|
|
7804
|
+
const nodePos = $from.before(depth);
|
|
7805
|
+
const node = $from.node(depth);
|
|
7806
|
+
const newAttrs = { ...node.attrs };
|
|
7807
|
+
if (blockFont) newAttrs.fontFamily = blockFont;
|
|
7808
|
+
if (blockColor) newAttrs.color = blockColor;
|
|
7809
|
+
const tr = state.tr.setNodeMarkup(nodePos, void 0, newAttrs);
|
|
7810
|
+
editor.view.dispatch(tr);
|
|
7811
|
+
}
|
|
7812
|
+
storage.previousNodeMarks = null;
|
|
7813
|
+
}
|
|
7732
7814
|
if (!blockFont && !blockColor) {
|
|
7733
7815
|
return;
|
|
7734
7816
|
}
|