slate-vue3 0.2.2 → 0.2.3

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 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 Vue components ?
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/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, P as Path, E as Editor, R as Range, T as Text, a as Element, c as Transforms } from "./batch-dirty-paths-X-eP3GRL.js";
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, d as EDITOR_TO_ON_CHANGE, P as MARK_PLACEHOLDER_SYMBOL, 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-BwRBmDaN.js";
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-BwRBmDaN.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: ["isLast", "leaf", "element", "text"],
138
+ props: ["leaf", "text", "element", "isLast"],
117
139
  setup(props) {
118
- const { isLast, leaf, element, text } = props;
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[element.children.length - 1] === text && !editor.isInline(element) && Editor.string(editor, pathParent) === "";
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
  })
@@ -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.2",
3
+ "version": "0.2.3",
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",