@mhamz.01/easyflow-texteditor 0.1.145 → 0.1.147
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 +27 -24
- package/dist/index.css.map +1 -1
- package/dist/index.js +151 -144
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +151 -144
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4449,6 +4449,56 @@ function ListDropdownMenu({
|
|
|
4449
4449
|
|
|
4450
4450
|
// src/components/tiptap-ui/blockquote-button/blockquote-button.tsx
|
|
4451
4451
|
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
|
|
4452
4502
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
4453
4503
|
function BlockquoteShortcutBadge({
|
|
4454
4504
|
shortcutKeys = BLOCKQUOTE_SHORTCUT_KEY
|
|
@@ -4484,10 +4534,15 @@ var BlockquoteButton = (0, import_react52.forwardRef)(
|
|
|
4484
4534
|
(event) => {
|
|
4485
4535
|
onClick?.(event);
|
|
4486
4536
|
if (event.defaultPrevented) return;
|
|
4537
|
+
MarkPreserver.preserve(editor);
|
|
4487
4538
|
handleToggle();
|
|
4539
|
+
MarkPreserver.restore(editor, 10);
|
|
4488
4540
|
},
|
|
4489
|
-
[handleToggle, onClick]
|
|
4541
|
+
[handleToggle, onClick, editor]
|
|
4490
4542
|
);
|
|
4543
|
+
const handlePointerDown = (0, import_react52.useCallback)(() => {
|
|
4544
|
+
MarkPreserver.preserve(editor);
|
|
4545
|
+
}, [editor]);
|
|
4491
4546
|
if (!isVisible) {
|
|
4492
4547
|
return null;
|
|
4493
4548
|
}
|
|
@@ -4504,6 +4559,7 @@ var BlockquoteButton = (0, import_react52.forwardRef)(
|
|
|
4504
4559
|
"aria-label": label,
|
|
4505
4560
|
"aria-pressed": isActive,
|
|
4506
4561
|
tooltip: `${label}${shortcutKeys ? ` (${String(parseShortcutKeys({ shortcutKeys })).replace(/Mod/i, "Ctrl").replace(/,/g, " + ")})` : ""}`,
|
|
4562
|
+
onPointerDown: handlePointerDown,
|
|
4507
4563
|
onClick: handleClick,
|
|
4508
4564
|
...buttonProps,
|
|
4509
4565
|
ref,
|
|
@@ -7091,7 +7147,15 @@ function ColorPicker({ type = "text" }) {
|
|
|
7091
7147
|
const [tempHex, setTempHex] = (0, import_react87.useState)("#000000");
|
|
7092
7148
|
const [canApply, setCanApply] = (0, import_react87.useState)(false);
|
|
7093
7149
|
(0, import_react87.useEffect)(() => {
|
|
7094
|
-
|
|
7150
|
+
if (!editor) return;
|
|
7151
|
+
let current = editor.getAttributes("textStyle").color;
|
|
7152
|
+
if (!current) {
|
|
7153
|
+
const { $from } = editor.state.selection;
|
|
7154
|
+
current = $from.parent.attrs.color;
|
|
7155
|
+
}
|
|
7156
|
+
if (!current) {
|
|
7157
|
+
current = type === "text" ? "#000000" : "#FFFF00";
|
|
7158
|
+
}
|
|
7095
7159
|
setColor(current);
|
|
7096
7160
|
setTempHex(current);
|
|
7097
7161
|
}, [editor, type]);
|
|
@@ -7114,14 +7178,37 @@ function ColorPicker({ type = "text" }) {
|
|
|
7114
7178
|
const applyColor = import_react89.default.useCallback(
|
|
7115
7179
|
(value) => {
|
|
7116
7180
|
if (!editor) return;
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7181
|
+
const { state } = editor;
|
|
7182
|
+
const { $from, $to, empty } = state.selection;
|
|
7183
|
+
editor.chain().focus().setColor(value).run();
|
|
7184
|
+
const depth = $from.depth;
|
|
7185
|
+
const nodePos = $from.before(depth);
|
|
7186
|
+
const node = $from.node(depth);
|
|
7187
|
+
const supportsColor = [
|
|
7188
|
+
"paragraph",
|
|
7189
|
+
"heading",
|
|
7190
|
+
"listItem",
|
|
7191
|
+
"taskItem",
|
|
7192
|
+
"blockquote"
|
|
7193
|
+
].includes(node.type.name);
|
|
7194
|
+
if (supportsColor) {
|
|
7195
|
+
const tr = state.tr.setNodeMarkup(nodePos, void 0, {
|
|
7196
|
+
...node.attrs,
|
|
7197
|
+
color: value
|
|
7198
|
+
});
|
|
7199
|
+
editor.view.dispatch(tr);
|
|
7122
7200
|
}
|
|
7123
7201
|
setTimeout(() => {
|
|
7124
|
-
editor.
|
|
7202
|
+
const newState = editor.state;
|
|
7203
|
+
const storedMarks = newState.storedMarks || newState.selection.$from.marks();
|
|
7204
|
+
const filteredMarks = storedMarks.filter((mark) => mark.type.name !== "textStyle");
|
|
7205
|
+
const newMarks = [
|
|
7206
|
+
...filteredMarks,
|
|
7207
|
+
newState.schema.marks.textStyle.create({ color: value })
|
|
7208
|
+
];
|
|
7209
|
+
editor.view.dispatch(
|
|
7210
|
+
newState.tr.setStoredMarks(newMarks)
|
|
7211
|
+
);
|
|
7125
7212
|
setColor(value);
|
|
7126
7213
|
}, 0);
|
|
7127
7214
|
},
|
|
@@ -7166,7 +7253,7 @@ function ColorPicker({ type = "text" }) {
|
|
|
7166
7253
|
applyColor(c);
|
|
7167
7254
|
setOpen(false);
|
|
7168
7255
|
},
|
|
7169
|
-
className: "w-5 h-5 rounded-lg cursor-pointer border border-black/10
|
|
7256
|
+
className: "w-5 h-5 rounded-lg cursor-pointer border border-black/10 hover:scale-105 transition",
|
|
7170
7257
|
style: { backgroundColor: c }
|
|
7171
7258
|
},
|
|
7172
7259
|
c
|
|
@@ -7184,8 +7271,7 @@ function ColorPicker({ type = "text" }) {
|
|
|
7184
7271
|
}
|
|
7185
7272
|
)
|
|
7186
7273
|
] }),
|
|
7187
|
-
showCustom &&
|
|
7188
|
-
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
7274
|
+
showCustom && /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
7189
7275
|
"div",
|
|
7190
7276
|
{
|
|
7191
7277
|
className: "flex flex-col gap-3",
|
|
@@ -7627,150 +7713,71 @@ var StylePersistence = import_core4.Extension.create({
|
|
|
7627
7713
|
};
|
|
7628
7714
|
},
|
|
7629
7715
|
onSelectionUpdate({ editor }) {
|
|
7630
|
-
const { state } = editor;
|
|
7631
7716
|
const excludedMarks = this.options.excludedMarks;
|
|
7632
|
-
|
|
7633
|
-
const { $from } = state.selection;
|
|
7634
|
-
const marks = $from.marks();
|
|
7635
|
-
return marks.some((mark) => excludedMarks.includes(mark.type.name));
|
|
7636
|
-
};
|
|
7637
|
-
const isInCodeBlock = () => {
|
|
7638
|
-
const { $from } = state.selection;
|
|
7639
|
-
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7640
|
-
const node = $from.node(depth);
|
|
7641
|
-
if (node.type.name === "codeBlock") {
|
|
7642
|
-
return true;
|
|
7643
|
-
}
|
|
7644
|
-
}
|
|
7645
|
-
return false;
|
|
7646
|
-
};
|
|
7647
|
-
if (hasExcludedMarks() || isInCodeBlock()) {
|
|
7648
|
-
return;
|
|
7649
|
-
}
|
|
7650
|
-
const blockFont = state.selection.$from.parent.attrs.fontFamily;
|
|
7651
|
-
const blockColor = state.selection.$from.parent.attrs.color;
|
|
7652
|
-
const existingTextStyleMark = state.selection.$from.marks().find(
|
|
7653
|
-
(mark) => mark.type.name === "textStyle"
|
|
7654
|
-
);
|
|
7655
|
-
const markFont = existingTextStyleMark?.attrs.fontFamily;
|
|
7656
|
-
const markColor = existingTextStyleMark?.attrs.color;
|
|
7657
|
-
const finalFont = markFont || blockFont;
|
|
7658
|
-
const finalColor = markColor || blockColor;
|
|
7659
|
-
if (!finalFont && !finalColor) return;
|
|
7660
|
-
const storedMarks = state.storedMarks || state.selection.$from.marks();
|
|
7661
|
-
const filteredMarks = storedMarks.filter(
|
|
7662
|
-
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7663
|
-
);
|
|
7664
|
-
const textStyleAttrs = {};
|
|
7665
|
-
if (finalFont) textStyleAttrs.fontFamily = finalFont;
|
|
7666
|
-
if (finalColor) textStyleAttrs.color = finalColor;
|
|
7667
|
-
const newMarks = [
|
|
7668
|
-
...filteredMarks,
|
|
7669
|
-
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7670
|
-
];
|
|
7671
|
-
editor.view.dispatch(
|
|
7672
|
-
state.tr.setStoredMarks(newMarks)
|
|
7673
|
-
);
|
|
7717
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7674
7718
|
},
|
|
7675
7719
|
onFocus({ editor }) {
|
|
7676
|
-
const { state } = editor;
|
|
7677
7720
|
const excludedMarks = this.options.excludedMarks;
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
const isInCodeBlock = () => {
|
|
7684
|
-
const { $from } = state.selection;
|
|
7685
|
-
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7686
|
-
const node = $from.node(depth);
|
|
7687
|
-
if (node.type.name === "codeBlock") {
|
|
7688
|
-
return true;
|
|
7689
|
-
}
|
|
7690
|
-
}
|
|
7691
|
-
return false;
|
|
7692
|
-
};
|
|
7693
|
-
if (hasExcludedMarks() || isInCodeBlock()) {
|
|
7694
|
-
return;
|
|
7695
|
-
}
|
|
7696
|
-
const blockFont = state.selection.$from.parent.attrs.fontFamily;
|
|
7697
|
-
const blockColor = state.selection.$from.parent.attrs.color;
|
|
7698
|
-
const existingTextStyleMark = state.selection.$from.marks().find(
|
|
7699
|
-
(mark) => mark.type.name === "textStyle"
|
|
7700
|
-
);
|
|
7701
|
-
const markFont = existingTextStyleMark?.attrs.fontFamily;
|
|
7702
|
-
const markColor = existingTextStyleMark?.attrs.color;
|
|
7703
|
-
const finalFont = markFont || blockFont;
|
|
7704
|
-
const finalColor = markColor || blockColor;
|
|
7705
|
-
if (!finalFont && !finalColor) return;
|
|
7706
|
-
const storedMarks = state.storedMarks || state.selection.$from.marks();
|
|
7707
|
-
const filteredMarks = storedMarks.filter(
|
|
7708
|
-
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7709
|
-
);
|
|
7710
|
-
const textStyleAttrs = {};
|
|
7711
|
-
if (finalFont) textStyleAttrs.fontFamily = finalFont;
|
|
7712
|
-
if (finalColor) textStyleAttrs.color = finalColor;
|
|
7713
|
-
const newMarks = [
|
|
7714
|
-
...filteredMarks,
|
|
7715
|
-
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7716
|
-
];
|
|
7717
|
-
editor.view.dispatch(
|
|
7718
|
-
state.tr.setStoredMarks(newMarks)
|
|
7719
|
-
);
|
|
7721
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7722
|
+
},
|
|
7723
|
+
onCreate({ editor }) {
|
|
7724
|
+
const excludedMarks = this.options.excludedMarks;
|
|
7725
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7720
7726
|
},
|
|
7721
|
-
// CRITICAL: Handle transaction updates to catch any textStyle changes
|
|
7722
7727
|
onTransaction({ editor, transaction }) {
|
|
7723
7728
|
if (!transaction.selectionSet && !transaction.docChanged) return;
|
|
7724
|
-
const { state } = editor;
|
|
7725
7729
|
const excludedMarks = this.options.excludedMarks;
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
return marks.some((mark) => excludedMarks.includes(mark.type.name));
|
|
7730
|
-
};
|
|
7731
|
-
const isInCodeBlock = () => {
|
|
7732
|
-
const { $from } = state.selection;
|
|
7733
|
-
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7734
|
-
const node = $from.node(depth);
|
|
7735
|
-
if (node.type.name === "codeBlock") {
|
|
7736
|
-
return true;
|
|
7737
|
-
}
|
|
7730
|
+
requestAnimationFrame(() => {
|
|
7731
|
+
if (!editor.isDestroyed) {
|
|
7732
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7738
7733
|
}
|
|
7739
|
-
|
|
7740
|
-
};
|
|
7741
|
-
if (hasExcludedMarks() || isInCodeBlock()) {
|
|
7742
|
-
return;
|
|
7743
|
-
}
|
|
7744
|
-
const blockFont = state.selection.$from.parent.attrs.fontFamily;
|
|
7745
|
-
const blockColor = state.selection.$from.parent.attrs.color;
|
|
7746
|
-
const existingTextStyleMark = state.selection.$from.marks().find(
|
|
7747
|
-
(mark) => mark.type.name === "textStyle"
|
|
7748
|
-
);
|
|
7749
|
-
const markFont = existingTextStyleMark?.attrs.fontFamily;
|
|
7750
|
-
const markColor = existingTextStyleMark?.attrs.color;
|
|
7751
|
-
const finalFont = markFont || blockFont;
|
|
7752
|
-
const finalColor = markColor || blockColor;
|
|
7753
|
-
if (!finalFont && !finalColor) return;
|
|
7754
|
-
const storedMarks = state.storedMarks || state.selection.$from.marks();
|
|
7755
|
-
const existingStoredTextStyle = storedMarks.find((mark) => mark.type.name === "textStyle");
|
|
7756
|
-
const hasCorrectFont = !finalFont || existingStoredTextStyle?.attrs.fontFamily === finalFont;
|
|
7757
|
-
const hasCorrectColor = !finalColor || existingStoredTextStyle?.attrs.color === finalColor;
|
|
7758
|
-
if (hasCorrectFont && hasCorrectColor && existingStoredTextStyle) return;
|
|
7759
|
-
const filteredMarks = storedMarks.filter(
|
|
7760
|
-
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7761
|
-
);
|
|
7762
|
-
const textStyleAttrs = {};
|
|
7763
|
-
if (finalFont) textStyleAttrs.fontFamily = finalFont;
|
|
7764
|
-
if (finalColor) textStyleAttrs.color = finalColor;
|
|
7765
|
-
const newMarks = [
|
|
7766
|
-
...filteredMarks,
|
|
7767
|
-
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7768
|
-
];
|
|
7769
|
-
editor.view.dispatch(
|
|
7770
|
-
state.tr.setStoredMarks(newMarks)
|
|
7771
|
-
);
|
|
7734
|
+
});
|
|
7772
7735
|
}
|
|
7773
7736
|
});
|
|
7737
|
+
function syncStoredMarks(editor, excludedMarks) {
|
|
7738
|
+
const { state } = editor;
|
|
7739
|
+
const { $from } = state.selection;
|
|
7740
|
+
const marks = $from.marks();
|
|
7741
|
+
const hasExcludedMarks = marks.some(
|
|
7742
|
+
(mark) => excludedMarks.includes(mark.type.name)
|
|
7743
|
+
);
|
|
7744
|
+
let isInCodeBlock = false;
|
|
7745
|
+
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7746
|
+
const node = $from.node(depth);
|
|
7747
|
+
if (node.type.name === "codeBlock") {
|
|
7748
|
+
isInCodeBlock = true;
|
|
7749
|
+
break;
|
|
7750
|
+
}
|
|
7751
|
+
}
|
|
7752
|
+
if (hasExcludedMarks || isInCodeBlock) {
|
|
7753
|
+
return;
|
|
7754
|
+
}
|
|
7755
|
+
const parentNode = $from.parent;
|
|
7756
|
+
const blockFont = parentNode.attrs.fontFamily;
|
|
7757
|
+
const blockColor = parentNode.attrs.color;
|
|
7758
|
+
if (!blockFont && !blockColor) {
|
|
7759
|
+
return;
|
|
7760
|
+
}
|
|
7761
|
+
const storedMarks = state.storedMarks || $from.marks();
|
|
7762
|
+
const existingTextStyle = storedMarks.find((mark) => mark.type.name === "textStyle");
|
|
7763
|
+
const needsUpdate = !existingTextStyle || blockFont && existingTextStyle.attrs.fontFamily !== blockFont || blockColor && existingTextStyle.attrs.color !== blockColor;
|
|
7764
|
+
if (!needsUpdate) {
|
|
7765
|
+
return;
|
|
7766
|
+
}
|
|
7767
|
+
const filteredMarks = storedMarks.filter(
|
|
7768
|
+
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7769
|
+
);
|
|
7770
|
+
const textStyleAttrs = {};
|
|
7771
|
+
if (blockFont) textStyleAttrs.fontFamily = blockFont;
|
|
7772
|
+
if (blockColor) textStyleAttrs.color = blockColor;
|
|
7773
|
+
const newMarks = [
|
|
7774
|
+
...filteredMarks,
|
|
7775
|
+
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7776
|
+
];
|
|
7777
|
+
editor.view.dispatch(
|
|
7778
|
+
state.tr.setStoredMarks(newMarks)
|
|
7779
|
+
);
|
|
7780
|
+
}
|
|
7774
7781
|
|
|
7775
7782
|
// src/components/tiptap-templates/simple/simple-editor.tsx
|
|
7776
7783
|
var import_jsx_runtime81 = require("react/jsx-runtime");
|