slate-vue3 0.2.2 → 0.2.4
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/README.md +2 -2
- package/dist/dom.js +2 -2
- package/dist/{hotkeys-BwRBmDaN.js → hotkeys-CjSuQvZ2.js} +4 -2
- package/dist/index.js +61 -42
- package/dist/slate-vue/components/string.d.ts +4 -4
- package/dist/slate-vue/components/text.d.ts +2 -2
- package/dist/slate-vue/hooks/use-render.d.ts +6 -1
- package/dist/slate-vue/utils/constants.d.ts +1 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
1. :sparkles: Highly customizable features, use slate core at the bottom level
|
|
23
23
|
2. :zap: Use vue3 for high-performance rendering, and later connect to vapor mode
|
|
24
24
|
3. :coffee: The latest version of the core, design tends to be stable
|
|
25
|
-
4. :point_right: Check out the [**live demo**](https://guan-erjia.github.io/slate-vue3/examples) of all of the examples
|
|
25
|
+
4. :point_right: Check out the [**live demo**](https://guan-erjia.github.io/slate-vue3/examples/rich-text) of all of the examples
|
|
26
26
|
|
|
27
27
|
# How to use?
|
|
28
28
|
|
|
@@ -81,6 +81,6 @@ This ensures that your rich text is as expected, and slate-vue3 provides some de
|
|
|
81
81
|
|
|
82
82
|
Of coures yes, but we do not recommend it unless you have already configured jsx in the project, as a branch, using the h function directly is already simple enough
|
|
83
83
|
|
|
84
|
-
### 3. Why do rendering functions not use
|
|
84
|
+
### 3. Why do rendering functions not use vue components ?
|
|
85
85
|
|
|
86
86
|
Vue uses lazy updates, rendering with components generates additional state, which can cause unexpected results during updates, it would be better to use functions as branches directly
|
package/dist/dom.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DOMEditor, E as EDITOR_TO_KEY_TO_ELEMENT, a as EDITOR_TO_USER_MARKS, b as EDITOR_TO_USER_SELECTION, N as NODE_TO_KEY, i as isDOMText, g as getPlainText, c as getSlateFragmentAttribute, d as EDITOR_TO_ON_CHANGE } from "./hotkeys-
|
|
2
|
-
import { C, F, G, J, H, B, I, u, L, v, w, M, x, O, z, y, A, K, P, Q, R, S, e, f, h, j, k, l, m, o, p, q, r, s, t, n } from "./hotkeys-
|
|
1
|
+
import { D as DOMEditor, E as EDITOR_TO_KEY_TO_ELEMENT, a as EDITOR_TO_USER_MARKS, b as EDITOR_TO_USER_SELECTION, N as NODE_TO_KEY, i as isDOMText, g as getPlainText, c as getSlateFragmentAttribute, d as EDITOR_TO_ON_CHANGE } from "./hotkeys-CjSuQvZ2.js";
|
|
2
|
+
import { C, F, G, J, H, B, I, u, L, v, w, M, x, O, z, y, A, K, P, Q, R, S, e, f, h, j, k, l, m, o, p, q, r, s, t, n } from "./hotkeys-CjSuQvZ2.js";
|
|
3
3
|
import { E as Editor, R as Range, a as Element, c as Transforms, P as Path, N as Node } from "./batch-dirty-paths-X-eP3GRL.js";
|
|
4
4
|
import "vue";
|
|
5
5
|
const doRectsIntersect = (rect, compareRect) => {
|
|
@@ -211,7 +211,9 @@ function getFirefoxNodeEl([node, offset]) {
|
|
|
211
211
|
}
|
|
212
212
|
if (!el) {
|
|
213
213
|
throw new Error(
|
|
214
|
-
`Compact on Firefox: Failed to find adjacent nodes: ${Scrubber.stringify(
|
|
214
|
+
`Compact on Firefox: Failed to find adjacent nodes: ${Scrubber.stringify(
|
|
215
|
+
node
|
|
216
|
+
)}`
|
|
215
217
|
);
|
|
216
218
|
}
|
|
217
219
|
return [el, isLeft ? 0 : ((_a2 = el.textContent) == null ? void 0 : _a2.length) || 0];
|
|
@@ -373,7 +375,7 @@ const DOMEditor = {
|
|
|
373
375
|
const { anchor, focus } = range;
|
|
374
376
|
return Editor.hasPath(editor, anchor.path) && Editor.hasPath(editor, focus.path);
|
|
375
377
|
},
|
|
376
|
-
hasSelectableTarget: (editor, target) => DOMEditor.hasEditableTarget(editor, target)
|
|
378
|
+
hasSelectableTarget: (editor, target) => DOMEditor.hasEditableTarget(editor, target) && !DOMEditor.isTargetInsideNonReadonlyVoid(editor, target),
|
|
377
379
|
hasTarget: (editor, target) => isDOMNode(target) && DOMEditor.hasDOMNode(editor, target),
|
|
378
380
|
insertData: (editor, data) => {
|
|
379
381
|
editor.insertData(data);
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent, provide, ref, computed, onMounted, onUnmounted, renderSlot, inject, h, watch, renderList, Fragment, useAttrs, reactive } from "vue";
|
|
2
|
-
import { N as Node, S as Scrubber,
|
|
2
|
+
import { N as Node, S as Scrubber, R as Range, T as Text, P as Path, E as Editor, a as Element, c as Transforms } from "./batch-dirty-paths-X-eP3GRL.js";
|
|
3
3
|
import { t } from "./batch-dirty-paths-X-eP3GRL.js";
|
|
4
|
-
import { D as DOMEditor,
|
|
4
|
+
import { D as DOMEditor, P as MARK_PLACEHOLDER_SYMBOL, d as EDITOR_TO_ON_CHANGE, I as IS_ANDROID, x as IS_IOS, E as EDITOR_TO_KEY_TO_ELEMENT, J as ELEMENT_TO_NODE, Q as NODE_TO_ELEMENT, R as NODE_TO_INDEX, S as NODE_TO_PARENT, p as isDOMNode, y as IS_WEBKIT, e as applyStringDiff, q as isDOMSelection, n as normalizeStringDiff, O as IS_READ_ONLY, h as getDefaultView, G as EDITOR_TO_WINDOW, F as EDITOR_TO_ELEMENT, H as HAS_BEFORE_INPUT_SUPPORT, C as CAN_USE_DOM, f as getActiveElement, j as getSelection, M as IS_FOCUSED, b as EDITOR_TO_USER_SELECTION, L as IS_COMPOSING, o as isDOMElement, w as IS_FIREFOX_LEGACY, A as IS_WECHATBROWSER, z as IS_UC_MOBILE, a as EDITOR_TO_USER_MARKS, v as IS_FIREFOX, B as Hotkeys, u as IS_CHROME, r as isPlainTextOnlyPaste } from "./hotkeys-CjSuQvZ2.js";
|
|
5
5
|
const SLATE_USE_EDITOR = Symbol("SLATE_USE_EDITOR");
|
|
6
6
|
const SLATE_USE_DECORATE = Symbol("SLATE_USE_DECORATE");
|
|
7
7
|
const SLATE_USE_SELECTED = Symbol("SLATE_USE_SELECTED");
|
|
@@ -13,6 +13,7 @@ const SLATE_INNER_RENDER_ELEMENT = Symbol("SLATE_INNER_RENDER_ELEMENT");
|
|
|
13
13
|
const SLATE_INNER_RENDER_LEAF = Symbol("SLATE_INNER_RENDER_LEAF");
|
|
14
14
|
const SLATE_INNER_RENDER_PLACEHOLDER = Symbol("SLATE_INNER_RENDER_PLACEHOLDER");
|
|
15
15
|
const SLATE_INNER_CHANGE_EFFECT_INJECT = Symbol("SLATE_INNER_CHANGE_EFFECT_INJECT");
|
|
16
|
+
const SLATE_INNER_MARK_PLACEHOLDER = Symbol("SLATE_INNER_MARK_PLACEHOLDER");
|
|
16
17
|
const Slate = defineComponent({
|
|
17
18
|
name: "slate-editor",
|
|
18
19
|
emits: ["change", "selectionchange", "valuechange"],
|
|
@@ -61,6 +62,27 @@ const Slate = defineComponent({
|
|
|
61
62
|
const focusCb = () => isFocus.value = DOMEditor.isFocused(editor);
|
|
62
63
|
const changeEffect = ref(0);
|
|
63
64
|
provide(SLATE_INNER_CHANGE_EFFECT_INJECT, changeEffect);
|
|
65
|
+
const markPlaceholder = computed(() => {
|
|
66
|
+
if (editor.selection && Range.isCollapsed(editor.selection) && editor.marks) {
|
|
67
|
+
const anchor = editor.selection.anchor;
|
|
68
|
+
const leaf = Node.leaf(editor, anchor.path);
|
|
69
|
+
const { text, ...rest } = leaf;
|
|
70
|
+
if (!Text.equals(leaf, editor.marks, { loose: true })) {
|
|
71
|
+
const unset = Object.fromEntries(
|
|
72
|
+
Object.keys(rest).map((mark) => [mark, null])
|
|
73
|
+
);
|
|
74
|
+
return {
|
|
75
|
+
[MARK_PLACEHOLDER_SYMBOL]: true,
|
|
76
|
+
...unset,
|
|
77
|
+
...editor.marks,
|
|
78
|
+
anchor,
|
|
79
|
+
focus: anchor
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
});
|
|
85
|
+
provide(SLATE_INNER_MARK_PLACEHOLDER, markPlaceholder);
|
|
64
86
|
onMounted(() => {
|
|
65
87
|
document.addEventListener("focusin", focusCb);
|
|
66
88
|
document.addEventListener("focusout", focusCb);
|
|
@@ -113,9 +135,9 @@ const useEditor = () => {
|
|
|
113
135
|
};
|
|
114
136
|
const StringComp = defineComponent({
|
|
115
137
|
name: "slate-string",
|
|
116
|
-
props: ["
|
|
138
|
+
props: ["leaf", "text", "element", "isLast"],
|
|
117
139
|
setup(props) {
|
|
118
|
-
const {
|
|
140
|
+
const { leaf, text, element, isLast } = props;
|
|
119
141
|
const editor = useEditor();
|
|
120
142
|
const getTextContent = computed(() => {
|
|
121
143
|
const text2 = leaf.text;
|
|
@@ -123,7 +145,7 @@ const StringComp = defineComponent({
|
|
|
123
145
|
});
|
|
124
146
|
const isLineBreak = computed(() => {
|
|
125
147
|
const pathParent = Path.parent(DOMEditor.findPath(editor, text));
|
|
126
|
-
return leaf.text === "" && element.children
|
|
148
|
+
return leaf.text === "" && element.children.at(-1) === text && !editor.isInline(element) && Editor.string(editor, pathParent) === "";
|
|
127
149
|
});
|
|
128
150
|
const zeroStringAttrs = computed(() => {
|
|
129
151
|
const length = Node.string(element).length || 0;
|
|
@@ -189,6 +211,15 @@ const useChangeEffect = (fn) => {
|
|
|
189
211
|
watch(() => CHANGE_EFFECT_INJECT.value, fn);
|
|
190
212
|
return CHANGE_EFFECT_INJECT;
|
|
191
213
|
};
|
|
214
|
+
const useMarkPlaceholder = () => {
|
|
215
|
+
const MARK_PLACEHOLDER_INJECT = inject(SLATE_INNER_MARK_PLACEHOLDER);
|
|
216
|
+
if (MARK_PLACEHOLDER_INJECT === void 0) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
`The \`useChangeEffect\` hook must be used inside the <Slate> component's context.`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return MARK_PLACEHOLDER_INJECT;
|
|
222
|
+
};
|
|
192
223
|
const TextComp = defineComponent({
|
|
193
224
|
name: "slate-text",
|
|
194
225
|
props: ["text", "element"],
|
|
@@ -197,32 +228,19 @@ const TextComp = defineComponent({
|
|
|
197
228
|
const editor = useEditor();
|
|
198
229
|
const spanRef = ref();
|
|
199
230
|
const decorate = useDecorate();
|
|
231
|
+
const markPlaceholder = useMarkPlaceholder();
|
|
200
232
|
const leaves = computed(() => {
|
|
201
233
|
const elemPath = DOMEditor.findPath(editor, element);
|
|
202
|
-
const elemDs = decorate([element, elemPath]);
|
|
203
|
-
if (editor.selection && Range.isCollapsed(editor.selection) && editor.marks) {
|
|
204
|
-
const anchor = editor.selection.anchor;
|
|
205
|
-
const leaf = Node.leaf(editor, anchor.path);
|
|
206
|
-
const { text: text2, ...rest } = leaf;
|
|
207
|
-
if (!Text.equals(leaf, editor.marks, { loose: true })) {
|
|
208
|
-
const unset = Object.fromEntries(
|
|
209
|
-
Object.keys(rest).map((mark) => [mark, null])
|
|
210
|
-
);
|
|
211
|
-
elemDs.push({
|
|
212
|
-
[MARK_PLACEHOLDER_SYMBOL]: true,
|
|
213
|
-
...unset,
|
|
214
|
-
...editor.marks,
|
|
215
|
-
anchor,
|
|
216
|
-
focus: anchor
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
234
|
const textPath = DOMEditor.findPath(editor, text);
|
|
221
|
-
const range = Editor.range(editor, textPath);
|
|
222
235
|
const textDs = decorate([text, textPath]);
|
|
236
|
+
const elemDs = decorate([element, elemPath]);
|
|
237
|
+
const range = Editor.range(editor, textPath);
|
|
223
238
|
elemDs.forEach((dec) => {
|
|
224
239
|
textDs.push(Range.intersection(dec, range));
|
|
225
240
|
});
|
|
241
|
+
if (markPlaceholder.value) {
|
|
242
|
+
textDs.unshift(markPlaceholder.value);
|
|
243
|
+
}
|
|
226
244
|
const filterDs = textDs.filter(Boolean);
|
|
227
245
|
return Text.decorations(text, filterDs.length ? filterDs : []);
|
|
228
246
|
});
|
|
@@ -257,10 +275,10 @@ const TextComp = defineComponent({
|
|
|
257
275
|
leaf,
|
|
258
276
|
attributes: { "data-slate-leaf": true },
|
|
259
277
|
children: h(StringComp, {
|
|
260
|
-
isLast: isLastText.value && i === leaves.value.length - 1,
|
|
261
|
-
leaf,
|
|
262
|
-
element,
|
|
263
278
|
text,
|
|
279
|
+
element,
|
|
280
|
+
leaf,
|
|
281
|
+
isLast: isLastText.value && i === leaves.value.length - 1,
|
|
264
282
|
key: `${text.text}-${leaf.text}-${i}`
|
|
265
283
|
})
|
|
266
284
|
})
|
|
@@ -1341,21 +1359,22 @@ const Editable = defineComponent({
|
|
|
1341
1359
|
}
|
|
1342
1360
|
};
|
|
1343
1361
|
const onCompositionend = (event) => {
|
|
1344
|
-
if (DOMEditor.hasSelectableTarget(editor, event.target)) {
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1362
|
+
if (!DOMEditor.hasSelectableTarget(editor, event.target)) {
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
if (DOMEditor.isComposing(editor)) {
|
|
1366
|
+
isComposing.value = false;
|
|
1367
|
+
IS_COMPOSING.set(editor, false);
|
|
1368
|
+
}
|
|
1369
|
+
if (IS_ANDROID || isEventHandled(event, attributes.onCompositionend)) {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
if (!IS_WEBKIT && !IS_FIREFOX_LEGACY && !IS_IOS && !IS_WECHATBROWSER && !IS_UC_MOBILE && event.data) {
|
|
1373
|
+
Editor.insertText(editor, event.data);
|
|
1374
|
+
const userMarks = EDITOR_TO_USER_MARKS.get(editor);
|
|
1375
|
+
EDITOR_TO_USER_MARKS.delete(editor);
|
|
1376
|
+
if (userMarks !== void 0) {
|
|
1377
|
+
editor.marks = userMarks;
|
|
1359
1378
|
}
|
|
1360
1379
|
}
|
|
1361
1380
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Element, Text } from '../../slate/index.ts';
|
|
2
2
|
export declare const StringComp: import('vue').DefineComponent<{
|
|
3
|
-
isLast: boolean;
|
|
4
|
-
text: Text;
|
|
5
3
|
leaf: Text;
|
|
4
|
+
text: Text;
|
|
6
5
|
element: Element;
|
|
6
|
+
isLast: boolean;
|
|
7
7
|
}, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
|
|
8
8
|
[key: string]: any;
|
|
9
9
|
}>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
|
|
10
|
-
isLast: boolean;
|
|
11
|
-
text: Text;
|
|
12
10
|
leaf: Text;
|
|
11
|
+
text: Text;
|
|
13
12
|
element: Element;
|
|
13
|
+
isLast: boolean;
|
|
14
14
|
}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Text, Element } from '../../slate/index.ts';
|
|
2
2
|
export declare const TextComp: import('vue').DefineComponent<{
|
|
3
|
-
element: Element;
|
|
4
3
|
text: Text;
|
|
4
|
+
element: Element;
|
|
5
5
|
}, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
|
|
6
6
|
[key: string]: any;
|
|
7
7
|
}>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
|
|
8
|
-
element: Element;
|
|
9
8
|
text: Text;
|
|
9
|
+
element: Element;
|
|
10
10
|
}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { Ref, VNode } from 'vue';
|
|
1
|
+
import { ComputedRef, Ref, VNode } from 'vue';
|
|
2
2
|
import { RenderElementProps, RenderPlaceholderProps, RenderLeafProps } from '../utils/interface';
|
|
3
|
+
import { BasePoint } from '../../slate/index.ts';
|
|
3
4
|
export declare const useRenderElement: () => (props: RenderElementProps) => VNode;
|
|
4
5
|
export declare const useRenderLeaf: () => (props: RenderLeafProps) => VNode;
|
|
5
6
|
export declare const useRenderPlaceholder: () => (props: RenderPlaceholderProps) => VNode;
|
|
6
7
|
export declare const useChangeEffect: (fn: () => void) => Ref<number, number>;
|
|
8
|
+
export declare const useMarkPlaceholder: () => ComputedRef<{
|
|
9
|
+
anchor: BasePoint;
|
|
10
|
+
focus: BasePoint;
|
|
11
|
+
} | null>;
|
|
@@ -10,3 +10,4 @@ export declare const SLATE_INNER_RENDER_ELEMENT: unique symbol;
|
|
|
10
10
|
export declare const SLATE_INNER_RENDER_LEAF: unique symbol;
|
|
11
11
|
export declare const SLATE_INNER_RENDER_PLACEHOLDER: unique symbol;
|
|
12
12
|
export declare const SLATE_INNER_CHANGE_EFFECT_INJECT: unique symbol;
|
|
13
|
+
export declare const SLATE_INNER_MARK_PLACEHOLDER: unique symbol;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slate-vue3",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"@types/node": "^22.13.1",
|
|
79
79
|
"@types/prismjs": "^1.26.5",
|
|
80
80
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
81
|
+
"babel-plugin-transform-regex": "^6.0.1",
|
|
81
82
|
"image-extensions": "^1.1.0",
|
|
82
83
|
"is-url": "^1.2.4",
|
|
83
84
|
"jsdom": "^26.0.0",
|
|
@@ -88,6 +89,7 @@
|
|
|
88
89
|
"typescript": "~5.8.2",
|
|
89
90
|
"unified": "^11.0.5",
|
|
90
91
|
"vite": "^6.2.5",
|
|
92
|
+
"vite-plugin-babel": "^1.3.0",
|
|
91
93
|
"vite-plugin-dts": "^4.5.0",
|
|
92
94
|
"vitest": "^3.0.5",
|
|
93
95
|
"vue-router": "^4.5.0",
|