@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.mjs
CHANGED
|
@@ -4423,6 +4423,56 @@ function ListDropdownMenu({
|
|
|
4423
4423
|
|
|
4424
4424
|
// src/components/tiptap-ui/blockquote-button/blockquote-button.tsx
|
|
4425
4425
|
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
|
|
4426
4476
|
import { Fragment as Fragment7, jsx as jsx45, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4427
4477
|
function BlockquoteShortcutBadge({
|
|
4428
4478
|
shortcutKeys = BLOCKQUOTE_SHORTCUT_KEY
|
|
@@ -4458,10 +4508,15 @@ var BlockquoteButton = forwardRef12(
|
|
|
4458
4508
|
(event) => {
|
|
4459
4509
|
onClick?.(event);
|
|
4460
4510
|
if (event.defaultPrevented) return;
|
|
4511
|
+
MarkPreserver.preserve(editor);
|
|
4461
4512
|
handleToggle();
|
|
4513
|
+
MarkPreserver.restore(editor, 10);
|
|
4462
4514
|
},
|
|
4463
|
-
[handleToggle, onClick]
|
|
4515
|
+
[handleToggle, onClick, editor]
|
|
4464
4516
|
);
|
|
4517
|
+
const handlePointerDown = useCallback16(() => {
|
|
4518
|
+
MarkPreserver.preserve(editor);
|
|
4519
|
+
}, [editor]);
|
|
4465
4520
|
if (!isVisible) {
|
|
4466
4521
|
return null;
|
|
4467
4522
|
}
|
|
@@ -4478,6 +4533,7 @@ var BlockquoteButton = forwardRef12(
|
|
|
4478
4533
|
"aria-label": label,
|
|
4479
4534
|
"aria-pressed": isActive,
|
|
4480
4535
|
tooltip: `${label}${shortcutKeys ? ` (${String(parseShortcutKeys({ shortcutKeys })).replace(/Mod/i, "Ctrl").replace(/,/g, " + ")})` : ""}`,
|
|
4536
|
+
onPointerDown: handlePointerDown,
|
|
4481
4537
|
onClick: handleClick,
|
|
4482
4538
|
...buttonProps,
|
|
4483
4539
|
ref,
|
|
@@ -7065,7 +7121,15 @@ function ColorPicker({ type = "text" }) {
|
|
|
7065
7121
|
const [tempHex, setTempHex] = useState29("#000000");
|
|
7066
7122
|
const [canApply, setCanApply] = useState29(false);
|
|
7067
7123
|
useEffect19(() => {
|
|
7068
|
-
|
|
7124
|
+
if (!editor) return;
|
|
7125
|
+
let current = editor.getAttributes("textStyle").color;
|
|
7126
|
+
if (!current) {
|
|
7127
|
+
const { $from } = editor.state.selection;
|
|
7128
|
+
current = $from.parent.attrs.color;
|
|
7129
|
+
}
|
|
7130
|
+
if (!current) {
|
|
7131
|
+
current = type === "text" ? "#000000" : "#FFFF00";
|
|
7132
|
+
}
|
|
7069
7133
|
setColor(current);
|
|
7070
7134
|
setTempHex(current);
|
|
7071
7135
|
}, [editor, type]);
|
|
@@ -7088,14 +7152,37 @@ function ColorPicker({ type = "text" }) {
|
|
|
7088
7152
|
const applyColor = React4.useCallback(
|
|
7089
7153
|
(value) => {
|
|
7090
7154
|
if (!editor) return;
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7155
|
+
const { state } = editor;
|
|
7156
|
+
const { $from, $to, empty } = state.selection;
|
|
7157
|
+
editor.chain().focus().setColor(value).run();
|
|
7158
|
+
const depth = $from.depth;
|
|
7159
|
+
const nodePos = $from.before(depth);
|
|
7160
|
+
const node = $from.node(depth);
|
|
7161
|
+
const supportsColor = [
|
|
7162
|
+
"paragraph",
|
|
7163
|
+
"heading",
|
|
7164
|
+
"listItem",
|
|
7165
|
+
"taskItem",
|
|
7166
|
+
"blockquote"
|
|
7167
|
+
].includes(node.type.name);
|
|
7168
|
+
if (supportsColor) {
|
|
7169
|
+
const tr = state.tr.setNodeMarkup(nodePos, void 0, {
|
|
7170
|
+
...node.attrs,
|
|
7171
|
+
color: value
|
|
7172
|
+
});
|
|
7173
|
+
editor.view.dispatch(tr);
|
|
7096
7174
|
}
|
|
7097
7175
|
setTimeout(() => {
|
|
7098
|
-
editor.
|
|
7176
|
+
const newState = editor.state;
|
|
7177
|
+
const storedMarks = newState.storedMarks || newState.selection.$from.marks();
|
|
7178
|
+
const filteredMarks = storedMarks.filter((mark) => mark.type.name !== "textStyle");
|
|
7179
|
+
const newMarks = [
|
|
7180
|
+
...filteredMarks,
|
|
7181
|
+
newState.schema.marks.textStyle.create({ color: value })
|
|
7182
|
+
];
|
|
7183
|
+
editor.view.dispatch(
|
|
7184
|
+
newState.tr.setStoredMarks(newMarks)
|
|
7185
|
+
);
|
|
7099
7186
|
setColor(value);
|
|
7100
7187
|
}, 0);
|
|
7101
7188
|
},
|
|
@@ -7140,7 +7227,7 @@ function ColorPicker({ type = "text" }) {
|
|
|
7140
7227
|
applyColor(c);
|
|
7141
7228
|
setOpen(false);
|
|
7142
7229
|
},
|
|
7143
|
-
className: "w-5 h-5 rounded-lg cursor-pointer border border-black/10
|
|
7230
|
+
className: "w-5 h-5 rounded-lg cursor-pointer border border-black/10 hover:scale-105 transition",
|
|
7144
7231
|
style: { backgroundColor: c }
|
|
7145
7232
|
},
|
|
7146
7233
|
c
|
|
@@ -7158,8 +7245,7 @@ function ColorPicker({ type = "text" }) {
|
|
|
7158
7245
|
}
|
|
7159
7246
|
)
|
|
7160
7247
|
] }),
|
|
7161
|
-
showCustom &&
|
|
7162
|
-
/* @__PURE__ */ jsxs46(
|
|
7248
|
+
showCustom && /* @__PURE__ */ jsxs46(
|
|
7163
7249
|
"div",
|
|
7164
7250
|
{
|
|
7165
7251
|
className: "flex flex-col gap-3",
|
|
@@ -7601,150 +7687,71 @@ var StylePersistence = Extension2.create({
|
|
|
7601
7687
|
};
|
|
7602
7688
|
},
|
|
7603
7689
|
onSelectionUpdate({ editor }) {
|
|
7604
|
-
const { state } = editor;
|
|
7605
7690
|
const excludedMarks = this.options.excludedMarks;
|
|
7606
|
-
|
|
7607
|
-
const { $from } = state.selection;
|
|
7608
|
-
const marks = $from.marks();
|
|
7609
|
-
return marks.some((mark) => excludedMarks.includes(mark.type.name));
|
|
7610
|
-
};
|
|
7611
|
-
const isInCodeBlock = () => {
|
|
7612
|
-
const { $from } = state.selection;
|
|
7613
|
-
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7614
|
-
const node = $from.node(depth);
|
|
7615
|
-
if (node.type.name === "codeBlock") {
|
|
7616
|
-
return true;
|
|
7617
|
-
}
|
|
7618
|
-
}
|
|
7619
|
-
return false;
|
|
7620
|
-
};
|
|
7621
|
-
if (hasExcludedMarks() || isInCodeBlock()) {
|
|
7622
|
-
return;
|
|
7623
|
-
}
|
|
7624
|
-
const blockFont = state.selection.$from.parent.attrs.fontFamily;
|
|
7625
|
-
const blockColor = state.selection.$from.parent.attrs.color;
|
|
7626
|
-
const existingTextStyleMark = state.selection.$from.marks().find(
|
|
7627
|
-
(mark) => mark.type.name === "textStyle"
|
|
7628
|
-
);
|
|
7629
|
-
const markFont = existingTextStyleMark?.attrs.fontFamily;
|
|
7630
|
-
const markColor = existingTextStyleMark?.attrs.color;
|
|
7631
|
-
const finalFont = markFont || blockFont;
|
|
7632
|
-
const finalColor = markColor || blockColor;
|
|
7633
|
-
if (!finalFont && !finalColor) return;
|
|
7634
|
-
const storedMarks = state.storedMarks || state.selection.$from.marks();
|
|
7635
|
-
const filteredMarks = storedMarks.filter(
|
|
7636
|
-
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7637
|
-
);
|
|
7638
|
-
const textStyleAttrs = {};
|
|
7639
|
-
if (finalFont) textStyleAttrs.fontFamily = finalFont;
|
|
7640
|
-
if (finalColor) textStyleAttrs.color = finalColor;
|
|
7641
|
-
const newMarks = [
|
|
7642
|
-
...filteredMarks,
|
|
7643
|
-
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7644
|
-
];
|
|
7645
|
-
editor.view.dispatch(
|
|
7646
|
-
state.tr.setStoredMarks(newMarks)
|
|
7647
|
-
);
|
|
7691
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7648
7692
|
},
|
|
7649
7693
|
onFocus({ editor }) {
|
|
7650
|
-
const { state } = editor;
|
|
7651
7694
|
const excludedMarks = this.options.excludedMarks;
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
const isInCodeBlock = () => {
|
|
7658
|
-
const { $from } = state.selection;
|
|
7659
|
-
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7660
|
-
const node = $from.node(depth);
|
|
7661
|
-
if (node.type.name === "codeBlock") {
|
|
7662
|
-
return true;
|
|
7663
|
-
}
|
|
7664
|
-
}
|
|
7665
|
-
return false;
|
|
7666
|
-
};
|
|
7667
|
-
if (hasExcludedMarks() || isInCodeBlock()) {
|
|
7668
|
-
return;
|
|
7669
|
-
}
|
|
7670
|
-
const blockFont = state.selection.$from.parent.attrs.fontFamily;
|
|
7671
|
-
const blockColor = state.selection.$from.parent.attrs.color;
|
|
7672
|
-
const existingTextStyleMark = state.selection.$from.marks().find(
|
|
7673
|
-
(mark) => mark.type.name === "textStyle"
|
|
7674
|
-
);
|
|
7675
|
-
const markFont = existingTextStyleMark?.attrs.fontFamily;
|
|
7676
|
-
const markColor = existingTextStyleMark?.attrs.color;
|
|
7677
|
-
const finalFont = markFont || blockFont;
|
|
7678
|
-
const finalColor = markColor || blockColor;
|
|
7679
|
-
if (!finalFont && !finalColor) return;
|
|
7680
|
-
const storedMarks = state.storedMarks || state.selection.$from.marks();
|
|
7681
|
-
const filteredMarks = storedMarks.filter(
|
|
7682
|
-
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7683
|
-
);
|
|
7684
|
-
const textStyleAttrs = {};
|
|
7685
|
-
if (finalFont) textStyleAttrs.fontFamily = finalFont;
|
|
7686
|
-
if (finalColor) textStyleAttrs.color = finalColor;
|
|
7687
|
-
const newMarks = [
|
|
7688
|
-
...filteredMarks,
|
|
7689
|
-
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7690
|
-
];
|
|
7691
|
-
editor.view.dispatch(
|
|
7692
|
-
state.tr.setStoredMarks(newMarks)
|
|
7693
|
-
);
|
|
7695
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7696
|
+
},
|
|
7697
|
+
onCreate({ editor }) {
|
|
7698
|
+
const excludedMarks = this.options.excludedMarks;
|
|
7699
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7694
7700
|
},
|
|
7695
|
-
// CRITICAL: Handle transaction updates to catch any textStyle changes
|
|
7696
7701
|
onTransaction({ editor, transaction }) {
|
|
7697
7702
|
if (!transaction.selectionSet && !transaction.docChanged) return;
|
|
7698
|
-
const { state } = editor;
|
|
7699
7703
|
const excludedMarks = this.options.excludedMarks;
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
return marks.some((mark) => excludedMarks.includes(mark.type.name));
|
|
7704
|
-
};
|
|
7705
|
-
const isInCodeBlock = () => {
|
|
7706
|
-
const { $from } = state.selection;
|
|
7707
|
-
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7708
|
-
const node = $from.node(depth);
|
|
7709
|
-
if (node.type.name === "codeBlock") {
|
|
7710
|
-
return true;
|
|
7711
|
-
}
|
|
7704
|
+
requestAnimationFrame(() => {
|
|
7705
|
+
if (!editor.isDestroyed) {
|
|
7706
|
+
syncStoredMarks(editor, excludedMarks);
|
|
7712
7707
|
}
|
|
7713
|
-
|
|
7714
|
-
};
|
|
7715
|
-
if (hasExcludedMarks() || isInCodeBlock()) {
|
|
7716
|
-
return;
|
|
7717
|
-
}
|
|
7718
|
-
const blockFont = state.selection.$from.parent.attrs.fontFamily;
|
|
7719
|
-
const blockColor = state.selection.$from.parent.attrs.color;
|
|
7720
|
-
const existingTextStyleMark = state.selection.$from.marks().find(
|
|
7721
|
-
(mark) => mark.type.name === "textStyle"
|
|
7722
|
-
);
|
|
7723
|
-
const markFont = existingTextStyleMark?.attrs.fontFamily;
|
|
7724
|
-
const markColor = existingTextStyleMark?.attrs.color;
|
|
7725
|
-
const finalFont = markFont || blockFont;
|
|
7726
|
-
const finalColor = markColor || blockColor;
|
|
7727
|
-
if (!finalFont && !finalColor) return;
|
|
7728
|
-
const storedMarks = state.storedMarks || state.selection.$from.marks();
|
|
7729
|
-
const existingStoredTextStyle = storedMarks.find((mark) => mark.type.name === "textStyle");
|
|
7730
|
-
const hasCorrectFont = !finalFont || existingStoredTextStyle?.attrs.fontFamily === finalFont;
|
|
7731
|
-
const hasCorrectColor = !finalColor || existingStoredTextStyle?.attrs.color === finalColor;
|
|
7732
|
-
if (hasCorrectFont && hasCorrectColor && existingStoredTextStyle) return;
|
|
7733
|
-
const filteredMarks = storedMarks.filter(
|
|
7734
|
-
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7735
|
-
);
|
|
7736
|
-
const textStyleAttrs = {};
|
|
7737
|
-
if (finalFont) textStyleAttrs.fontFamily = finalFont;
|
|
7738
|
-
if (finalColor) textStyleAttrs.color = finalColor;
|
|
7739
|
-
const newMarks = [
|
|
7740
|
-
...filteredMarks,
|
|
7741
|
-
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7742
|
-
];
|
|
7743
|
-
editor.view.dispatch(
|
|
7744
|
-
state.tr.setStoredMarks(newMarks)
|
|
7745
|
-
);
|
|
7708
|
+
});
|
|
7746
7709
|
}
|
|
7747
7710
|
});
|
|
7711
|
+
function syncStoredMarks(editor, excludedMarks) {
|
|
7712
|
+
const { state } = editor;
|
|
7713
|
+
const { $from } = state.selection;
|
|
7714
|
+
const marks = $from.marks();
|
|
7715
|
+
const hasExcludedMarks = marks.some(
|
|
7716
|
+
(mark) => excludedMarks.includes(mark.type.name)
|
|
7717
|
+
);
|
|
7718
|
+
let isInCodeBlock = false;
|
|
7719
|
+
for (let depth = $from.depth; depth > 0; depth--) {
|
|
7720
|
+
const node = $from.node(depth);
|
|
7721
|
+
if (node.type.name === "codeBlock") {
|
|
7722
|
+
isInCodeBlock = true;
|
|
7723
|
+
break;
|
|
7724
|
+
}
|
|
7725
|
+
}
|
|
7726
|
+
if (hasExcludedMarks || isInCodeBlock) {
|
|
7727
|
+
return;
|
|
7728
|
+
}
|
|
7729
|
+
const parentNode = $from.parent;
|
|
7730
|
+
const blockFont = parentNode.attrs.fontFamily;
|
|
7731
|
+
const blockColor = parentNode.attrs.color;
|
|
7732
|
+
if (!blockFont && !blockColor) {
|
|
7733
|
+
return;
|
|
7734
|
+
}
|
|
7735
|
+
const storedMarks = state.storedMarks || $from.marks();
|
|
7736
|
+
const existingTextStyle = storedMarks.find((mark) => mark.type.name === "textStyle");
|
|
7737
|
+
const needsUpdate = !existingTextStyle || blockFont && existingTextStyle.attrs.fontFamily !== blockFont || blockColor && existingTextStyle.attrs.color !== blockColor;
|
|
7738
|
+
if (!needsUpdate) {
|
|
7739
|
+
return;
|
|
7740
|
+
}
|
|
7741
|
+
const filteredMarks = storedMarks.filter(
|
|
7742
|
+
(mark) => mark.type.name !== "textStyle" && !excludedMarks.includes(mark.type.name)
|
|
7743
|
+
);
|
|
7744
|
+
const textStyleAttrs = {};
|
|
7745
|
+
if (blockFont) textStyleAttrs.fontFamily = blockFont;
|
|
7746
|
+
if (blockColor) textStyleAttrs.color = blockColor;
|
|
7747
|
+
const newMarks = [
|
|
7748
|
+
...filteredMarks,
|
|
7749
|
+
state.schema.marks.textStyle.create(textStyleAttrs)
|
|
7750
|
+
];
|
|
7751
|
+
editor.view.dispatch(
|
|
7752
|
+
state.tr.setStoredMarks(newMarks)
|
|
7753
|
+
);
|
|
7754
|
+
}
|
|
7748
7755
|
|
|
7749
7756
|
// src/components/tiptap-templates/simple/simple-editor.tsx
|
|
7750
7757
|
import { Fragment as Fragment12, jsx as jsx81, jsxs as jsxs48 } from "react/jsx-runtime";
|