vuewrite 0.0.5 → 0.0.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.
- package/dist/vuewrite.d.ts +33 -5
- package/dist/vuewrite.js +82 -34
- package/package.json +1 -1
package/dist/vuewrite.d.ts
CHANGED
|
@@ -43,9 +43,14 @@ export declare type Style = {
|
|
|
43
43
|
export declare const TextEditor: __VLS_WithTemplateSlots<DefineComponent<__VLS_TypePropsToRuntimeProps<{
|
|
44
44
|
decorator?: Decorator | undefined;
|
|
45
45
|
single?: boolean | undefined;
|
|
46
|
-
modelValue?: string |
|
|
47
|
-
|
|
46
|
+
modelValue?: string | {
|
|
47
|
+
text: string;
|
|
48
|
+
styles?: Style[] | undefined;
|
|
49
|
+
type?: string | undefined;
|
|
50
|
+
}[] | undefined;
|
|
51
|
+
styles?: Style[] | undefined;
|
|
48
52
|
autofocus?: boolean | undefined;
|
|
53
|
+
autoselect?: boolean | undefined;
|
|
49
54
|
}>, {
|
|
50
55
|
currentStyles: ComputedRef<Map<string, Style>>;
|
|
51
56
|
currentBlock: ComputedRef< {
|
|
@@ -75,7 +80,11 @@ toggleStyle: (style: string) => void;
|
|
|
75
80
|
applyStyle: (_style: string, meta?: any) => void;
|
|
76
81
|
removeStyle: (_style: string) => void;
|
|
77
82
|
insertText: (data: string) => void;
|
|
83
|
+
insertBlock: (blockData: Partial<Block>) => void;
|
|
84
|
+
addNewLine: () => void;
|
|
85
|
+
removeNewLine: () => void;
|
|
78
86
|
selectAll: () => void;
|
|
87
|
+
getClientRects: (selection: TextEditorSelection) => DOMRectList;
|
|
79
88
|
}, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
|
|
80
89
|
keydown: (...args: any[]) => void;
|
|
81
90
|
"update:modelValue": (...args: any[]) => void;
|
|
@@ -83,9 +92,14 @@ keydown: (...args: any[]) => void;
|
|
|
83
92
|
}, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
|
|
84
93
|
decorator?: Decorator | undefined;
|
|
85
94
|
single?: boolean | undefined;
|
|
86
|
-
modelValue?: string |
|
|
87
|
-
|
|
95
|
+
modelValue?: string | {
|
|
96
|
+
text: string;
|
|
97
|
+
styles?: Style[] | undefined;
|
|
98
|
+
type?: string | undefined;
|
|
99
|
+
}[] | undefined;
|
|
100
|
+
styles?: Style[] | undefined;
|
|
88
101
|
autofocus?: boolean | undefined;
|
|
102
|
+
autoselect?: boolean | undefined;
|
|
89
103
|
}>>> & {
|
|
90
104
|
onKeydown?: ((...args: any[]) => any) | undefined;
|
|
91
105
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
@@ -94,8 +108,20 @@ onKeydown?: ((...args: any[]) => any) | undefined;
|
|
|
94
108
|
placeholder?(_: {}): any;
|
|
95
109
|
}>;
|
|
96
110
|
|
|
97
|
-
export declare type TextEditorRef = Pick<TextEditorStore, "currentStyles" | "currentBlock" | "isCollapsed" | "selection" | "toggleStyle" | "applyStyle" | "removeStyle" | "insertText" | "selectAll"> & {
|
|
111
|
+
export declare type TextEditorRef = Pick<TextEditorStore, "currentStyles" | "currentBlock" | "isCollapsed" | "selection" | "toggleStyle" | "applyStyle" | "removeStyle" | "insertText" | "insertBlock" | "addNewLine" | "removeNewLine" | "selectAll"> & {
|
|
98
112
|
isFocused: boolean;
|
|
113
|
+
getClientRects: (selection: TextEditorSelection) => DOMRectList;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
declare type TextEditorSelection = {
|
|
117
|
+
anchor: {
|
|
118
|
+
blockId: string;
|
|
119
|
+
offset: number;
|
|
120
|
+
};
|
|
121
|
+
focus: {
|
|
122
|
+
blockId: string;
|
|
123
|
+
offset: number;
|
|
124
|
+
};
|
|
99
125
|
};
|
|
100
126
|
|
|
101
127
|
declare class TextEditorStore {
|
|
@@ -148,9 +174,11 @@ declare class TextEditorStore {
|
|
|
148
174
|
_selectedText: ComputedRef<string>;
|
|
149
175
|
get selectedText(): string;
|
|
150
176
|
moveOffset(newOffset: number): void;
|
|
177
|
+
removeNewLine(): void;
|
|
151
178
|
onInput(_e: Event): void;
|
|
152
179
|
addNewLine(): void;
|
|
153
180
|
insertText(data: string): void;
|
|
181
|
+
insertBlock(blockData: Partial<Block>): void;
|
|
154
182
|
get startAndEnd(): [{
|
|
155
183
|
blockId: string;
|
|
156
184
|
offset: number;
|
package/dist/vuewrite.js
CHANGED
|
@@ -202,6 +202,16 @@ class TextEditorStore {
|
|
|
202
202
|
this.selection.anchor.offset = newOffset;
|
|
203
203
|
this.selection.focus.offset = newOffset;
|
|
204
204
|
}
|
|
205
|
+
removeNewLine() {
|
|
206
|
+
const blockIndex = this.blocks.findIndex((item) => item.id === this.selection.anchor.blockId);
|
|
207
|
+
if (blockIndex < 1)
|
|
208
|
+
return;
|
|
209
|
+
this.selection.anchor.blockId = this.blocks[blockIndex - 1].id;
|
|
210
|
+
this.selection.focus.blockId = this.blocks[blockIndex - 1].id;
|
|
211
|
+
this.selection.anchor.offset = this.blocks[blockIndex - 1].text.length;
|
|
212
|
+
this.selection.focus.offset = this.blocks[blockIndex - 1].text.length;
|
|
213
|
+
this.blocks.splice(blockIndex, 1);
|
|
214
|
+
}
|
|
205
215
|
onInput(_e) {
|
|
206
216
|
const ev = _e;
|
|
207
217
|
ev.preventDefault();
|
|
@@ -212,16 +222,9 @@ class TextEditorStore {
|
|
|
212
222
|
if (!block)
|
|
213
223
|
return;
|
|
214
224
|
if ((ev.inputType === "deleteContentBackward" || ev.inputType === "deleteContentForward") && collapsed) {
|
|
215
|
-
const blockIndex = this.blocks.findIndex((item) => item.id === this.selection.anchor.blockId);
|
|
216
225
|
if (ev.inputType === "deleteContentBackward") {
|
|
217
226
|
if (this.selection.anchor.offset === 0) {
|
|
218
|
-
|
|
219
|
-
this.selection.anchor.blockId = this.blocks[blockIndex - 1].id;
|
|
220
|
-
this.selection.focus.blockId = this.blocks[blockIndex - 1].id;
|
|
221
|
-
this.selection.anchor.offset = this.blocks[blockIndex - 1].text.length;
|
|
222
|
-
this.selection.focus.offset = this.blocks[blockIndex - 1].text.length;
|
|
223
|
-
this.blocks.splice(blockIndex, 1);
|
|
224
|
-
}
|
|
227
|
+
this.removeNewLine();
|
|
225
228
|
} else {
|
|
226
229
|
const offset = Math.max(0, this.selection.focus.offset - 1);
|
|
227
230
|
block.text = block.text.slice(0, offset) + block.text.slice(this.selection.focus.offset);
|
|
@@ -229,6 +232,7 @@ class TextEditorStore {
|
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
234
|
if (ev.inputType === "deleteContentForward") {
|
|
235
|
+
const blockIndex = this.blocks.findIndex((item) => item.id === this.selection.anchor.blockId);
|
|
232
236
|
if (this.selection.anchor.offset === this.blocks[blockIndex].text.length) {
|
|
233
237
|
this.blocks.splice(blockIndex + 1, 1);
|
|
234
238
|
} else {
|
|
@@ -260,6 +264,20 @@ class TextEditorStore {
|
|
|
260
264
|
block.text = block.text.slice(0, this.selection.focus.offset) + data + block.text.slice(this.selection.focus.offset);
|
|
261
265
|
this.moveOffset(clamp(this.selection.focus.offset + data.length, 0, block.text.length));
|
|
262
266
|
}
|
|
267
|
+
insertBlock(blockData) {
|
|
268
|
+
if (!this.currentBlock)
|
|
269
|
+
return;
|
|
270
|
+
this.deleteSelected();
|
|
271
|
+
if (this.currentBlock.text !== "") {
|
|
272
|
+
this.addNewLine();
|
|
273
|
+
}
|
|
274
|
+
if (this.currentBlock.text !== "") {
|
|
275
|
+
const selection = JSON.parse(JSON.stringify(this.selection));
|
|
276
|
+
this.addNewLine();
|
|
277
|
+
Object.assign(this.selection, selection);
|
|
278
|
+
}
|
|
279
|
+
Object.assign(this.currentBlock, blockData);
|
|
280
|
+
}
|
|
263
281
|
get startAndEnd() {
|
|
264
282
|
const a = this.blocks.findIndex((block) => block.id === this.selection.anchor.blockId);
|
|
265
283
|
const f = this.blocks.findIndex((block) => block.id === this.selection.focus.blockId);
|
|
@@ -415,7 +433,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
415
433
|
return props.slots[props.block.type] ?? null;
|
|
416
434
|
});
|
|
417
435
|
const blockProps = {
|
|
418
|
-
"data-block-id": props.block.id
|
|
436
|
+
"data-vw-block-id": props.block.id
|
|
419
437
|
};
|
|
420
438
|
const renderBlockPart = (text, styles) => {
|
|
421
439
|
if (!props.decorator)
|
|
@@ -543,7 +561,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
543
561
|
single: { type: Boolean },
|
|
544
562
|
modelValue: {},
|
|
545
563
|
styles: {},
|
|
546
|
-
autofocus: { type: Boolean }
|
|
564
|
+
autofocus: { type: Boolean },
|
|
565
|
+
autoselect: { type: Boolean }
|
|
547
566
|
},
|
|
548
567
|
emits: ["keydown", "update:modelValue", "update:styles"],
|
|
549
568
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
@@ -565,7 +584,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
565
584
|
}
|
|
566
585
|
store.blocks.length = newValue.length;
|
|
567
586
|
for (let i = 0; i < newValue.length; i++) {
|
|
568
|
-
store.blocks[i].text = newValue[i];
|
|
587
|
+
store.blocks[i].text = newValue[i].text;
|
|
588
|
+
store.blocks[i].type = newValue[i].type;
|
|
589
|
+
store.blocks[i].text = newValue[i].text;
|
|
569
590
|
}
|
|
570
591
|
}
|
|
571
592
|
}, { immediate: true });
|
|
@@ -576,20 +597,23 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
576
597
|
for (let i = 0; i < store.blocks.length; i++) {
|
|
577
598
|
if (newStyles.length <= i)
|
|
578
599
|
break;
|
|
579
|
-
|
|
580
|
-
store.blocks[i].styles = style;
|
|
600
|
+
store.blocks[i].styles = newStyles;
|
|
581
601
|
}
|
|
582
602
|
}, { immediate: true });
|
|
583
603
|
watch(() => store.blocks, () => {
|
|
584
604
|
if (props.single) {
|
|
585
605
|
modelValue = store.blocks[0].text;
|
|
586
606
|
styles = store.blocks[0].styles;
|
|
607
|
+
emit("update:styles", styles);
|
|
608
|
+
emit("update:modelValue", modelValue);
|
|
587
609
|
} else {
|
|
588
|
-
modelValue = store.blocks.map((item) =>
|
|
589
|
-
|
|
610
|
+
modelValue = store.blocks.map((item) => ({
|
|
611
|
+
type: item.type,
|
|
612
|
+
text: item.text,
|
|
613
|
+
styles: item.styles.length === 0 ? void 0 : item.styles
|
|
614
|
+
}));
|
|
615
|
+
emit("update:modelValue", modelValue);
|
|
590
616
|
}
|
|
591
|
-
emit("update:modelValue", modelValue);
|
|
592
|
-
emit("update:styles", styles);
|
|
593
617
|
}, { deep: true });
|
|
594
618
|
const onKeyDown = (e) => {
|
|
595
619
|
emit("keydown", e);
|
|
@@ -604,8 +628,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
604
628
|
}
|
|
605
629
|
}
|
|
606
630
|
if (e.code === "Backspace") {
|
|
607
|
-
if (store.isCollapsed && store.
|
|
631
|
+
if (store.isCollapsed && store.selection.anchor.offset === 0) {
|
|
608
632
|
e.preventDefault();
|
|
633
|
+
if (store.currentBlock && store.currentBlock.type) {
|
|
634
|
+
delete store.currentBlock.type;
|
|
635
|
+
} else {
|
|
636
|
+
store.removeNewLine();
|
|
637
|
+
}
|
|
609
638
|
}
|
|
610
639
|
}
|
|
611
640
|
if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {
|
|
@@ -617,15 +646,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
617
646
|
let cachedSelection = {};
|
|
618
647
|
useEventListener(document, "selectionchange", () => {
|
|
619
648
|
const sel = window.getSelection();
|
|
620
|
-
const anchor = findParent(sel.anchorNode, (el) => el.hasAttribute("data-block-id"));
|
|
649
|
+
const anchor = findParent(sel.anchorNode, (el) => el.hasAttribute("data-vw-block-id"));
|
|
621
650
|
if (anchor) {
|
|
622
651
|
const offset = anchor === sel.anchorNode ? 0 : calcOffsetToNode(anchor, sel.anchorNode) + sel.anchorOffset;
|
|
623
|
-
store.selection.anchor = { blockId: anchor.getAttribute("data-block-id"), offset };
|
|
652
|
+
store.selection.anchor = { blockId: anchor.getAttribute("data-vw-block-id"), offset };
|
|
624
653
|
}
|
|
625
|
-
const focus = findParent(sel.focusNode, (el) => el.hasAttribute("data-block-id"));
|
|
654
|
+
const focus = findParent(sel.focusNode, (el) => el.hasAttribute("data-vw-block-id"));
|
|
626
655
|
if (focus) {
|
|
627
656
|
const offset = anchor === sel.focusNode ? 0 : calcOffsetToNode(focus, sel.focusNode) + sel.focusOffset;
|
|
628
|
-
store.selection.focus = { blockId: focus.getAttribute("data-block-id"), offset };
|
|
657
|
+
store.selection.focus = { blockId: focus.getAttribute("data-vw-block-id"), offset };
|
|
629
658
|
}
|
|
630
659
|
if (store.isFocused.value !== !!focus || !!anchor) {
|
|
631
660
|
store.isFocused.value = !!focus || !!anchor;
|
|
@@ -644,6 +673,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
644
673
|
postRendered = false;
|
|
645
674
|
});
|
|
646
675
|
};
|
|
676
|
+
const getNode = (blockId) => {
|
|
677
|
+
for (let item of textEditorRef.value.children) {
|
|
678
|
+
if (item.getAttribute("data-vw-block-id") === blockId) {
|
|
679
|
+
return item;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return null;
|
|
683
|
+
};
|
|
647
684
|
const applySelection = () => {
|
|
648
685
|
if (!store.isFocused.value) {
|
|
649
686
|
cachedSelection = JSON.parse(JSON.stringify(store.selection));
|
|
@@ -651,17 +688,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
651
688
|
}
|
|
652
689
|
if (isEqual(store.selection, cachedSelection))
|
|
653
690
|
return;
|
|
691
|
+
const anchor = getNode(store.selection.anchor.blockId);
|
|
692
|
+
const focus = getNode(store.selection.focus.blockId);
|
|
654
693
|
const nativeSelection = window.getSelection();
|
|
655
|
-
let anchor = null;
|
|
656
|
-
let focus = null;
|
|
657
|
-
for (let item of textEditorRef.value.children) {
|
|
658
|
-
if (item.getAttribute("data-block-id") === store.selection.anchor.blockId) {
|
|
659
|
-
anchor = item;
|
|
660
|
-
}
|
|
661
|
-
if (item.getAttribute("data-block-id") === store.selection.focus.blockId) {
|
|
662
|
-
focus = item;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
694
|
if (anchor && focus) {
|
|
666
695
|
nativeSelection.setBaseAndExtent(
|
|
667
696
|
...calcNodeByOffset(anchor, store.selection.anchor.offset),
|
|
@@ -672,11 +701,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
672
701
|
};
|
|
673
702
|
watch(() => store.selection, applySelection, { deep: true, flush: "post" });
|
|
674
703
|
onMounted(() => {
|
|
675
|
-
var _a;
|
|
704
|
+
var _a, _b;
|
|
676
705
|
if (props.autofocus) {
|
|
677
706
|
(_a = textEditorRef.value) == null ? void 0 : _a.focus();
|
|
678
707
|
applySelection();
|
|
679
708
|
}
|
|
709
|
+
if (props.autoselect) {
|
|
710
|
+
(_b = textEditorRef.value) == null ? void 0 : _b.focus();
|
|
711
|
+
store.selectAll();
|
|
712
|
+
}
|
|
680
713
|
});
|
|
681
714
|
const onCopy = (e) => {
|
|
682
715
|
e.preventDefault();
|
|
@@ -695,6 +728,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
695
728
|
return;
|
|
696
729
|
store.insertText(text);
|
|
697
730
|
};
|
|
731
|
+
const getClientRects = (selection) => {
|
|
732
|
+
const anchor = getNode(selection.anchor.blockId);
|
|
733
|
+
const focus = getNode(selection.focus.blockId);
|
|
734
|
+
if (anchor && focus) {
|
|
735
|
+
const range = new Range();
|
|
736
|
+
range.setStart(...calcNodeByOffset(anchor, selection.anchor.offset));
|
|
737
|
+
range.setEnd(...calcNodeByOffset(focus, selection.focus.offset));
|
|
738
|
+
return range.getClientRects();
|
|
739
|
+
}
|
|
740
|
+
return new DOMRectList();
|
|
741
|
+
};
|
|
698
742
|
__expose({
|
|
699
743
|
currentStyles: store._currentStyles,
|
|
700
744
|
currentBlock: store._currentBlock,
|
|
@@ -705,7 +749,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
705
749
|
applyStyle: store.applyStyle.bind(store),
|
|
706
750
|
removeStyle: store.removeStyle.bind(store),
|
|
707
751
|
insertText: store.insertText.bind(store),
|
|
708
|
-
|
|
752
|
+
insertBlock: store.insertBlock.bind(store),
|
|
753
|
+
addNewLine: store.addNewLine.bind(store),
|
|
754
|
+
removeNewLine: store.removeNewLine.bind(store),
|
|
755
|
+
selectAll: store.selectAll.bind(store),
|
|
756
|
+
getClientRects
|
|
709
757
|
});
|
|
710
758
|
return (_ctx, _cache) => {
|
|
711
759
|
return openBlock(), createElementBlock("div", {
|