@kungal/editor-vue 0.30.0 → 0.31.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @kungal/editor-vue
2
2
 
3
+ ## 0.31.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6b3a2f7: Add a loading placeholder and make `<KunEditor>` SSR-safe.
8
+
9
+ Under SSR the editor area went blank for a moment while Milkdown hydrated (and it
10
+ could throw a hydration mismatch, since Milkdown/CodeMirror need the DOM). Now:
11
+
12
+ - The editor body mounts **client-side only**; the server and the first client
13
+ paint render just a **skeleton placeholder**, which hydrates cleanly before the
14
+ editor swaps in — no mismatch, and the area never collapses to nothing. So
15
+ `<KunEditor>` no longer needs to be wrapped in `<ClientOnly>`.
16
+ - The placeholder also covers Milkdown's own create gap, using its `loading` state
17
+ (`useEditor().loading`), then disappears when the editor is ready.
18
+ - **`@update:loading`** event — so a host can react (e.g. disable a submit button
19
+ until ready).
20
+ - **`#loading` slot** to supply your own placeholder (e.g. a `<KunSkeleton>`), or
21
+ restyle the default via the `.kun-editor__loading` / `.kun-editor__skeleton`
22
+ class hooks (a shimmer added to the reference stylesheet).
23
+
24
+ Verified in the docs production build: the server HTML contains only the skeleton
25
+ (no editor DOM); the page hydrates with 0 console errors (mismatch gone); the
26
+ placeholder shows on first paint and on every remount and is removed once the
27
+ editor is ready.
28
+
29
+ ### Patch Changes
30
+
31
+ - @kungal/editor-core@0.31.0
32
+
3
33
  ## 0.30.0
4
34
 
5
35
  ### Patch Changes
@@ -77,17 +77,21 @@ declare var __VLS_1: {
77
77
  adapters: KunEditorAdapters;
78
78
  features: KunEditorFeatures;
79
79
  locale: KunEditorLocale;
80
- };
80
+ }, __VLS_48: {};
81
81
  type __VLS_Slots = {} & {
82
82
  'view-switch'?: (props: typeof __VLS_1) => any;
83
83
  } & {
84
84
  toolbar?: (props: typeof __VLS_22) => any;
85
+ } & {
86
+ loading?: (props: typeof __VLS_48) => any;
85
87
  };
86
88
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, KunEditorExpose, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
87
89
  "update:modelValue": (markdown: string) => any;
90
+ "update:loading": (loading: boolean) => any;
88
91
  "update:headings": (headings: KunHeading[]) => any;
89
92
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
90
93
  "onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
94
+ "onUpdate:loading"?: ((loading: boolean) => any) | undefined;
91
95
  "onUpdate:headings"?: ((headings: KunHeading[]) => any) | undefined;
92
96
  }>, {
93
97
  adapters: KunEditorAdapters;
@@ -1 +1 @@
1
- {"version":3,"file":"KunEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/KunEditor.vue"],"names":[],"mappings":"AAkYA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACX,MAAM,qBAAqB,CAAA;AAO5B,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAUjE,KAAK,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE9C,KAAK,WAAW,GAAG;IACf,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,qDAAqD;IACrD,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,eAAe,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;IAClB;oEACgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAAA;CAChD,CAAC;AA0bJ,QAAA,IAAI,OAAO;;iBAtXS,QAAQ;;;;;;;;;;;;;CAsXP,EAAE,QAAQ;iEAxf/B,CAnWE;;;;;WAmWF,CA5UQ;aA4UR,CA5UwB;;;;YA4UxB,CAxUkD;;;;;;;;;;;;;;CAg0BmC,CAAE;AACvF,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAClD;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAShD,QAAA,MAAM,UAAU;;;;;;;cAreD,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;iBAEJ,MAAM;qBAMF,KAAK,GAAG,OAAO;sBAgBd,OAAO,GAAG,gBAAgB,EAAE;WAVvC,QAAQ,EAAE;gBAGL,OAAO;6EAmdtB,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"KunEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/KunEditor.vue"],"names":[],"mappings":"AAsbA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACX,MAAM,qBAAqB,CAAA;AAO5B,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAUjE,KAAK,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE9C,KAAK,WAAW,GAAG;IACf,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,qDAAqD;IACrD,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,eAAe,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;IAClB;oEACgE;IAChE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAAA;CAChD,CAAC;AAgfJ,QAAA,IAAI,OAAO;;iBAzZS,QAAQ;;;;;;;;;;;;;CAyZP,EAAE,QAAQ;iEAtjB/B,CAzY4C;;;;;WAyY5C,CAjX8B;aAiX9B,CAjX8C;;;;YAiX9C,CA5WyB;;;;;;;;;;;;;;CAk6BiB,EAA4C,QAAQ,IAAY,CAAE;AAC5G,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAClD;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC7C;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAShD,QAAA,MAAM,UAAU;;;;;;;;;cA5hBD,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;iBAEJ,MAAM;qBAMF,KAAK,GAAG,OAAO;sBAgBd,OAAO,GAAG,gBAAgB,EAAE;WAVvC,QAAQ,EAAE;gBAGL,OAAO;6EA0gBtB,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -18,8 +18,10 @@ type __VLS_Props = {
18
18
  };
19
19
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, KunEditorExpose, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
20
20
  "update:modelValue": (markdown: string) => any;
21
+ "update:loading": (loading: boolean) => any;
21
22
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
22
23
  "onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
24
+ "onUpdate:loading"?: ((loading: boolean) => any) | undefined;
23
25
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
26
  declare const _default: typeof __VLS_export;
25
27
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"MilkdownEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/MilkdownEditor.vue"],"names":[],"mappings":"AAwSA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAI5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE/C,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,MAAM,EAAE,eAAe,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,KAAK,GAAG,OAAO,CAAA;IAChC,gBAAgB,EAAE,OAAO,CAAA;IACzB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAA;CAChB,CAAC;AA2OF,QAAA,MAAM,YAAY;;;;kFAIhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"MilkdownEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/MilkdownEditor.vue"],"names":[],"mappings":"AA+SA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAI5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE/C,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,MAAM,EAAE,eAAe,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,KAAK,GAAG,OAAO,CAAA;IAChC,gBAAgB,EAAE,OAAO,CAAA;IACzB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAA;CAChB,CAAC;AAkPF,QAAA,MAAM,YAAY;;;;;;kFAIhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
package/dist/index.js CHANGED
@@ -2,14 +2,14 @@ import { Fragment as e, computed as t, createBlock as n, createCommentVNode as r
2
2
  import { Milkdown as E, MilkdownProvider as D, useEditor as O, useInstance as k } from "@milkdown/vue";
3
3
  import { ProsemirrorAdapterProvider as A, usePluginViewContext as j, usePluginViewFactory as M } from "@prosemirror-adapter/vue";
4
4
  import { parseHeadings as N, parseHeadings as ee } from "@kungal/editor-core";
5
- import { Editor as P, defaultValueCtx as F, editorViewCtx as I, editorViewOptionsCtx as te, rootCtx as L } from "@milkdown/kit/core";
5
+ import { Editor as te, defaultValueCtx as P, editorViewCtx as F, editorViewOptionsCtx as I, rootCtx as L } from "@milkdown/kit/core";
6
6
  import { listenerCtx as R } from "@milkdown/kit/plugin/listener";
7
- import { SlashProvider as z, slashFactory as B } from "@milkdown/kit/plugin/slash";
8
- import { TooltipProvider as V, tooltipFactory as H } from "@milkdown/kit/plugin/tooltip";
9
- import { callCommand as U, replaceAll as ne } from "@milkdown/kit/utils";
10
- import { TextSelection as W } from "@milkdown/kit/prose/state";
11
- import { createCodeBlockCommand as G, insertHrCommand as K, insertImageCommand as q, toggleEmphasisCommand as re, toggleInlineCodeCommand as ie, toggleStrongCommand as ae, wrapInBlockquoteCommand as oe, wrapInBulletListCommand as se, wrapInOrderedListCommand as ce } from "@milkdown/kit/preset/commonmark";
12
- import { createKunEditorPlugins as le, insertKunSpoilerCommand as ue, insertLinkCommand as J, insertMentionCommand as de, insertQuoteCommand as fe, kunCM as pe, mentionId as me, setHeadingCommand as he, startImageUpload as ge } from "@kungal/editor-core/preset";
7
+ import { SlashProvider as z, slashFactory as ne } from "@milkdown/kit/plugin/slash";
8
+ import { TooltipProvider as B, tooltipFactory as re } from "@milkdown/kit/plugin/tooltip";
9
+ import { callCommand as V, replaceAll as H } from "@milkdown/kit/utils";
10
+ import { TextSelection as U } from "@milkdown/kit/prose/state";
11
+ import { createCodeBlockCommand as W, insertHrCommand as ie, insertImageCommand as G, toggleEmphasisCommand as K, toggleInlineCodeCommand as q, toggleStrongCommand as J, wrapInBlockquoteCommand as ae, wrapInBulletListCommand as oe, wrapInOrderedListCommand as se } from "@milkdown/kit/preset/commonmark";
12
+ import { createKunEditorPlugins as ce, insertKunSpoilerCommand as le, insertLinkCommand as ue, insertMentionCommand as de, insertQuoteCommand as fe, kunCM as pe, mentionId as me, setHeadingCommand as he, startImageUpload as ge } from "@kungal/editor-core/preset";
13
13
  import { toggleStrikethroughCommand as _e } from "@milkdown/kit/preset/gfm";
14
14
  import { Annotation as ve, EditorState as ye } from "@codemirror/state";
15
15
  import { EditorView as Y } from "@codemirror/view";
@@ -64,7 +64,7 @@ var X = Symbol("kun-editor-context"), Se = [
64
64
  if (!t.empty) return null;
65
65
  let { $from: n } = t, i = n.parent.textBetween(Math.max(0, n.parentOffset - 100), n.parentOffset, void 0, "").match(r);
66
66
  return i ? i[1] ?? "" : null;
67
- }, P = (e) => {
67
+ }, te = (e) => {
68
68
  let t = ee(e);
69
69
  if (t === null) return !1;
70
70
  let n = e.state.selection.$from.pos;
@@ -72,7 +72,7 @@ var X = Symbol("kun-editor-context"), Se = [
72
72
  from: n - (t.length + 1),
73
73
  to: n
74
74
  }, t !== C.value && (C.value = t, N(t)), !0;
75
- }, F = (e) => {
75
+ }, P = (e) => {
76
76
  let t = d.value;
77
77
  if (!t || !O) return;
78
78
  let n = t.state.schema.nodes[me];
@@ -81,8 +81,8 @@ var X = Symbol("kun-editor-context"), Se = [
81
81
  userId: e.id,
82
82
  name: e.name
83
83
  }), { from: i, to: a } = O, o = t.state.tr.replaceWith(i, a, r), s = i + r.nodeSize;
84
- o.insertText(" ", s), o.setSelection(W.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), b.hide();
85
- }, I = (e) => {
84
+ o.insertText(" ", s), o.setSelection(U.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), b.hide();
85
+ }, F = (e) => {
86
86
  if (!x.value || !w.value.length) {
87
87
  x.value && e.key === "Escape" && (e.preventDefault(), b.hide());
88
88
  return;
@@ -98,7 +98,7 @@ var X = Symbol("kun-editor-context"), Se = [
98
98
  case "Enter":
99
99
  case "Tab": {
100
100
  let t = w.value[E.value];
101
- t && (e.preventDefault(), e.stopPropagation(), F(t));
101
+ t && (e.preventDefault(), e.stopPropagation(), P(t));
102
102
  break;
103
103
  }
104
104
  case "Escape":
@@ -110,17 +110,17 @@ var X = Symbol("kun-editor-context"), Se = [
110
110
  b = new z({
111
111
  content: v.value,
112
112
  trigger: "@",
113
- shouldShow: P,
113
+ shouldShow: te,
114
114
  debounce: 0
115
115
  }), b.onShow = () => {
116
116
  x.value = !0;
117
117
  }, b.onHide = () => {
118
118
  x.value = !1, M();
119
- }, b.update(d.value, h.value), window.addEventListener("keydown", I, !0);
119
+ }, b.update(d.value, h.value), window.addEventListener("keydown", F, !0);
120
120
  }), S([d, h], () => {
121
121
  b?.update(d.value, h.value);
122
122
  }), f(() => {
123
- A && clearTimeout(A), window.removeEventListener("keydown", I, !0), b?.destroy();
123
+ A && clearTimeout(A), window.removeEventListener("keydown", F, !0), b?.destroy();
124
124
  }), (t, n) => (m(), i("div", {
125
125
  ref_key: "divRef",
126
126
  ref: v,
@@ -131,7 +131,7 @@ var X = Symbol("kun-editor-context"), Se = [
131
131
  type: "button",
132
132
  class: "kun-mention-dropdown__item",
133
133
  "data-active": t === E.value,
134
- onMousedown: T((t) => F(e), ["prevent"]),
134
+ onMousedown: T((t) => P(e), ["prevent"]),
135
135
  onMouseenter: (e) => E.value = t
136
136
  }, [e.avatar ? (m(), i("img", {
137
137
  key: 0,
@@ -170,25 +170,25 @@ var X = Symbol("kun-editor-context"), Se = [
170
170
  __name: "SelectionTooltip",
171
171
  setup(n) {
172
172
  let { view: r, prevState: o } = j(), [, s] = k(), c = l(X), u = t(() => (c?.locale ?? "zh-cn").toLowerCase().startsWith("en")), d = g(null), h, v = (e, t) => {
173
- s()?.action(U(e, t));
173
+ s()?.action(V(e, t));
174
174
  }, y = async () => {
175
175
  let e = r.value, { from: t, to: n } = e?.state.selection ?? {
176
176
  from: 0,
177
177
  to: 0
178
178
  }, i = e ? e.state.doc.textBetween(t, n, " ") : "", a = c?.adapters.linkPrompt, o = (a ? await a({ text: i }) : window.prompt(u.value ? "Link URL" : "链接 URL"))?.trim();
179
- o && v(J.key, { href: o });
179
+ o && v(ue.key, { href: o });
180
180
  }, b = t(() => {
181
181
  let e = u.value;
182
182
  return {
183
183
  bold: {
184
184
  svg: $.bold,
185
185
  title: e ? "Bold" : "加粗",
186
- run: () => v(ae.key)
186
+ run: () => v(J.key)
187
187
  },
188
188
  italic: {
189
189
  svg: $.italic,
190
190
  title: e ? "Italic" : "斜体",
191
- run: () => v(re.key)
191
+ run: () => v(K.key)
192
192
  },
193
193
  strike: {
194
194
  svg: $.strike,
@@ -198,7 +198,7 @@ var X = Symbol("kun-editor-context"), Se = [
198
198
  code: {
199
199
  svg: $.code,
200
200
  title: e ? "Inline code" : "行内代码",
201
- run: () => v(ie.key)
201
+ run: () => v(q.key)
202
202
  },
203
203
  link: {
204
204
  svg: $.link,
@@ -222,7 +222,7 @@ var X = Symbol("kun-editor-context"), Se = [
222
222
  return n;
223
223
  });
224
224
  return p(() => {
225
- h = new V({
225
+ h = new B({
226
226
  content: d.value,
227
227
  offset: 8
228
228
  }), h.update(r.value, o.value);
@@ -260,46 +260,46 @@ var X = Symbol("kun-editor-context"), Se = [
260
260
  selectionToolbar: { type: Boolean },
261
261
  active: { type: Boolean }
262
262
  },
263
- emits: ["update:modelValue"],
263
+ emits: ["update:modelValue", "update:loading"],
264
264
  setup(e, { expose: t, emit: r }) {
265
- let i = e, a = r, o = i.modelValue, s = !1, c = M(), l = B("kunMention"), u = i.features.mention !== !1 && !!i.adapters.searchMentionUsers && !!c, d = H("kunSelectionTooltip"), f = i.selectionToolbar && !!c, p = O((e) => {
266
- let t = P.make().config((t) => {
267
- t.set(L, e), t.set(F, i.modelValue), t.get(R).markdownUpdated((e, t, n) => {
265
+ let i = e, a = r, o = i.modelValue, s = !1, c = M(), l = ne("kunMention"), u = i.features.mention !== !1 && !!i.adapters.searchMentionUsers && !!c, d = re("kunSelectionTooltip"), f = i.selectionToolbar && !!c, p = O((e) => {
266
+ let t = te.make().config((t) => {
267
+ t.set(L, e), t.set(P, i.modelValue), t.get(R).markdownUpdated((e, t, n) => {
268
268
  !i.active || s || t === n || (o = t, a("update:modelValue", t));
269
- }), t.update(te, (e) => ({
269
+ }), t.update(I, (e) => ({
270
270
  ...e,
271
271
  editable: () => !i.readonly
272
272
  })), u && t.set(l.key, { view: c({ component: ke }) }), f && t.set(d.key, { view: c({ component: Ne }) });
273
- }).use(le(i.adapters, i.features, {
273
+ }).use(ce(i.adapters, i.features, {
274
274
  locale: i.locale,
275
275
  placeholder: i.placeholder,
276
276
  placeholderMode: i.placeholderMode
277
277
  }));
278
278
  return u && t.use(l), f && t.use(d), t;
279
279
  });
280
- S(() => i.modelValue, (e) => {
280
+ S(p.loading, (e) => a("update:loading", e), { immediate: !0 }), S(() => i.modelValue, (e) => {
281
281
  if (e === o) return;
282
282
  o = e;
283
283
  let t = p.get();
284
- t && (s = !0, t.action(ne(e)), s = !1);
284
+ t && (s = !0, t.action(H(e)), s = !1);
285
285
  }), S(() => i.readonly, () => {
286
286
  p.get()?.action((e) => {
287
- let t = e.get(I);
287
+ let t = e.get(F);
288
288
  t.dispatch(t.state.tr);
289
289
  });
290
290
  });
291
291
  let h = () => {
292
- p.get()?.action((e) => e.get(I).focus());
292
+ p.get()?.action((e) => e.get(F).focus());
293
293
  };
294
294
  return t({
295
295
  insertQuote: (e) => {
296
- p.get()?.action(U(fe.key, e)), h();
296
+ p.get()?.action(V(fe.key, e)), h();
297
297
  },
298
298
  insertMention: (e) => {
299
- p.get()?.action(U(de.key, e)), h();
299
+ p.get()?.action(V(de.key, e)), h();
300
300
  },
301
301
  insertImage: (e) => {
302
- p.get()?.action(U(q.key, {
302
+ p.get()?.action(V(G.key, {
303
303
  src: e.src,
304
304
  alt: e.alt ?? "",
305
305
  title: e.title ?? ""
@@ -308,7 +308,7 @@ var X = Symbol("kun-editor-context"), Se = [
308
308
  uploadImage: (e) => {
309
309
  let t = i.adapters.uploadImage, n = p.get();
310
310
  !t || !n || n.action((n) => {
311
- ge(n.get(I), e, {
311
+ ge(n.get(F), e, {
312
312
  uploadImage: t,
313
313
  notify: i.adapters.notify,
314
314
  locale: i.locale
@@ -318,14 +318,14 @@ var X = Symbol("kun-editor-context"), Se = [
318
318
  focus: h,
319
319
  scrollToHeading: (e) => {
320
320
  p.get()?.action((t) => {
321
- let n = t.get(I), r = 0, i = -1;
321
+ let n = t.get(F), r = 0, i = -1;
322
322
  if (n.state.doc.forEach((t, n) => {
323
323
  t.type.name === "heading" && (r === e && (i = n), r += 1);
324
324
  }), !(i < 0) && (n.nodeDOM(i)?.scrollIntoView({
325
325
  behavior: "smooth",
326
326
  block: "start"
327
327
  }), n.editable)) {
328
- let e = W.near(n.state.doc.resolve(i + 1));
328
+ let e = U.near(n.state.doc.resolve(i + 1));
329
329
  n.dispatch(n.state.tr.setSelection(e)), n.focus();
330
330
  }
331
331
  });
@@ -378,11 +378,11 @@ var X = Symbol("kun-editor-context"), Se = [
378
378
  p(() => document.addEventListener("click", j)), f(() => document.removeEventListener("click", j));
379
379
  let M = (e) => {
380
380
  o()?.action((t) => {
381
- let n = t.get(I), { state: r } = n;
381
+ let n = t.get(F), { state: r } = n;
382
382
  n.dispatch(r.tr.insertText(e, r.selection.from));
383
383
  });
384
384
  }, N = (e, t) => {
385
- o()?.action(U(q.key, {
385
+ o()?.action(V(G.key, {
386
386
  src: e,
387
387
  title: t,
388
388
  alt: t
@@ -451,15 +451,15 @@ var X = Symbol("kun-editor-context"), Se = [
451
451
  __name: "EditorToolbar",
452
452
  setup(n) {
453
453
  let [, s] = k(), c = l(X), u = t(() => c?.adapters.uploadImage), d = t(() => c?.features.sticker !== !1), f = t(() => (c?.locale ?? "zh-cn").toLowerCase().startsWith("en")), p = (e, t) => {
454
- s()?.action(U(e, t));
454
+ s()?.action(V(e, t));
455
455
  }, h = async () => {
456
456
  let e = "";
457
457
  s()?.action((t) => {
458
- let n = t.get(I), { from: r, to: i } = n.state.selection;
458
+ let n = t.get(F), { from: r, to: i } = n.state.selection;
459
459
  e = n.state.doc.textBetween(r, i, " ");
460
460
  });
461
461
  let t = c?.adapters.linkPrompt, n = (t ? await t({ text: e }) : window.prompt(f.value ? "Link URL" : "链接 URL"))?.trim();
462
- n && p(J.key, { href: n });
462
+ n && p(ue.key, { href: n });
463
463
  }, v = t(() => {
464
464
  let e = f.value;
465
465
  return {
@@ -499,12 +499,12 @@ var X = Symbol("kun-editor-context"), Se = [
499
499
  {
500
500
  svg: $.bold,
501
501
  title: v.value.bold,
502
- run: () => p(ae.key)
502
+ run: () => p(J.key)
503
503
  },
504
504
  {
505
505
  svg: $.italic,
506
506
  title: v.value.italic,
507
- run: () => p(re.key)
507
+ run: () => p(K.key)
508
508
  },
509
509
  {
510
510
  svg: $.strike,
@@ -514,7 +514,7 @@ var X = Symbol("kun-editor-context"), Se = [
514
514
  {
515
515
  svg: $.code,
516
516
  title: v.value.code,
517
- run: () => p(ie.key)
517
+ run: () => p(q.key)
518
518
  },
519
519
  {
520
520
  svg: $.link,
@@ -526,40 +526,40 @@ var X = Symbol("kun-editor-context"), Se = [
526
526
  {
527
527
  svg: $.bulletList,
528
528
  title: v.value.bulletList,
529
- run: () => p(se.key)
529
+ run: () => p(oe.key)
530
530
  },
531
531
  {
532
532
  svg: $.orderedList,
533
533
  title: v.value.orderedList,
534
- run: () => p(ce.key)
534
+ run: () => p(se.key)
535
535
  },
536
536
  {
537
537
  svg: $.quote,
538
538
  title: v.value.quote,
539
- run: () => p(oe.key)
539
+ run: () => p(ae.key)
540
540
  },
541
541
  {
542
542
  svg: $.codeBlock,
543
543
  title: v.value.codeBlock,
544
- run: () => p(G.key, "")
544
+ run: () => p(W.key, "")
545
545
  },
546
546
  {
547
547
  svg: $.hr,
548
548
  title: v.value.hr,
549
- run: () => p(K.key)
549
+ run: () => p(ie.key)
550
550
  }
551
551
  ],
552
552
  [{
553
553
  svg: $.spoiler,
554
554
  title: v.value.spoiler,
555
- run: () => p(ue.key)
555
+ run: () => p(le.key)
556
556
  }]
557
557
  ]), w = g(null), T = () => w.value?.click(), E = (e) => {
558
558
  let t = e.target, n = t.files?.[0];
559
559
  t.value = "";
560
560
  let r = u.value;
561
561
  !n || !r || s()?.action((e) => {
562
- ge(e.get(I), n, {
562
+ ge(e.get(F), n, {
563
563
  uploadImage: r,
564
564
  notify: c?.adapters.notify,
565
565
  locale: c?.locale
@@ -623,21 +623,21 @@ var X = Symbol("kun-editor-context"), Se = [
623
623
  __name: "ToolbarHost",
624
624
  setup(e) {
625
625
  let [, t] = k(), n = l(X, void 0), r = (e, n) => {
626
- t()?.action(U(e, n));
626
+ t()?.action(V(e, n));
627
627
  }, i = () => {
628
- t()?.action((e) => e.get(I).focus());
628
+ t()?.action((e) => e.get(F).focus());
629
629
  }, a = {
630
630
  run: r,
631
631
  insertText: (e) => {
632
632
  t()?.action((t) => {
633
- let n = t.get(I);
633
+ let n = t.get(F);
634
634
  n.dispatch(n.state.tr.insertText(e));
635
635
  }), i();
636
636
  },
637
637
  uploadImage: (e) => {
638
638
  let r = n?.adapters.uploadImage, i = t();
639
639
  !r || !i || i.action((t) => {
640
- ge(t.get(I), e, {
640
+ ge(t.get(F), e, {
641
641
  uploadImage: r,
642
642
  notify: n?.adapters.notify,
643
643
  locale: n?.locale
@@ -645,10 +645,10 @@ var X = Symbol("kun-editor-context"), Se = [
645
645
  });
646
646
  },
647
647
  insertLink: (e) => {
648
- r(J.key, e), i();
648
+ r(ue.key, e), i();
649
649
  },
650
650
  insertImage: (e) => {
651
- r(q.key, {
651
+ r(G.key, {
652
652
  src: e.src,
653
653
  alt: e.alt ?? "",
654
654
  title: e.title ?? ""
@@ -757,7 +757,11 @@ var X = Symbol("kun-editor-context"), Se = [
757
757
  "data-active",
758
758
  "title",
759
759
  "aria-pressed"
760
- ], pt = ["data-swap"], mt = { class: "kun-editor__wysiwyg kun-editor__pane" }, ht = /* @__PURE__ */ s({
760
+ ], pt = ["data-swap"], mt = { class: "kun-editor__wysiwyg kun-editor__pane" }, ht = {
761
+ key: 1,
762
+ class: "kun-editor__loading",
763
+ "aria-hidden": "true"
764
+ }, gt = /* @__PURE__ */ s({
761
765
  __name: "KunEditor",
762
766
  props: {
763
767
  modelValue: {},
@@ -784,44 +788,54 @@ var X = Symbol("kun-editor-context"), Se = [
784
788
  default: !0
785
789
  }
786
790
  },
787
- emits: ["update:modelValue", "update:headings"],
788
- setup(s, { expose: l, emit: p }) {
789
- let T = [
791
+ emits: [
792
+ "update:modelValue",
793
+ "update:headings",
794
+ "update:loading"
795
+ ],
796
+ setup(s, { expose: l, emit: T }) {
797
+ let E = [
790
798
  "bold",
791
799
  "italic",
792
800
  "strike",
793
801
  "code",
794
802
  "link"
795
- ], E = s, O = p;
796
- S(() => E.modelValue, (e) => O("update:headings", ee(e)), { immediate: !0 }), h(X, {
803
+ ], O = s, k = T, j = g(!1);
804
+ p(() => {
805
+ j.value = !0;
806
+ });
807
+ let M = g(!0), N = (e) => {
808
+ M.value = e, k("update:loading", e);
809
+ };
810
+ S(() => O.modelValue, (e) => k("update:headings", ee(e)), { immediate: !0 }), h(X, {
797
811
  get adapters() {
798
- return E.adapters;
812
+ return O.adapters;
799
813
  },
800
814
  get features() {
801
- return E.features;
815
+ return O.features;
802
816
  },
803
817
  get locale() {
804
- return E.locale;
818
+ return O.locale;
805
819
  },
806
820
  get selectionToolbarItems() {
807
- return Array.isArray(E.selectionToolbar) ? E.selectionToolbar : T;
821
+ return Array.isArray(O.selectionToolbar) ? O.selectionToolbar : E;
808
822
  }
809
823
  });
810
- let k = t(() => E.selectionToolbar !== !1), j = g(E.views.includes("wysiwyg") ? "wysiwyg" : E.views[0] ?? "wysiwyg"), M = (e) => {
811
- j.value = e;
824
+ let te = t(() => O.selectionToolbar !== !1), P = g(O.views.includes("wysiwyg") ? "wysiwyg" : O.views[0] ?? "wysiwyg"), F = (e) => {
825
+ P.value = e;
812
826
  };
813
- S(() => E.views, (e) => {
814
- e.includes(j.value) || (j.value = e[0] ?? "wysiwyg");
827
+ S(() => O.views, (e) => {
828
+ e.includes(P.value) || (P.value = e[0] ?? "wysiwyg");
815
829
  });
816
- let N = g(!1), P = () => {
817
- N.value = !N.value;
818
- }, F = g(E.scrollSync);
819
- S(() => E.scrollSync, (e) => {
820
- F.value = e;
830
+ let I = g(!1), L = () => {
831
+ I.value = !I.value;
832
+ }, R = g(O.scrollSync);
833
+ S(() => O.scrollSync, (e) => {
834
+ R.value = e;
821
835
  });
822
- let I = () => {
823
- F.value = !F.value;
824
- }, te = t(() => E.locale.toLowerCase().startsWith("en")), L = t(() => te.value ? {
836
+ let z = () => {
837
+ R.value = !R.value;
838
+ }, ne = t(() => O.locale.toLowerCase().startsWith("en")), B = t(() => ne.value ? {
825
839
  wysiwyg: "Preview",
826
840
  source: "Markdown",
827
841
  split: "Split",
@@ -833,103 +847,104 @@ var X = Symbol("kun-editor-context"), Se = [
833
847
  split: "分栏",
834
848
  swap: "左右互换",
835
849
  scrollSync: "同步滚动"
836
- }), R = g(null), z = null, B = null, V = null, H = () => {
837
- z?.(), z = null, B = null;
838
- }, U = () => {
839
- H();
840
- let e = R.value;
850
+ }), re = g(null), V = null, H = null, U = null, W = () => {
851
+ V?.(), V = null, H = null;
852
+ }, ie = () => {
853
+ W();
854
+ let e = re.value;
841
855
  if (!e) return;
842
856
  let t = e.querySelector(".cm-scroller"), n = e.querySelector(".kun-editor__wysiwyg");
843
857
  if (!t || !n) return;
844
858
  let r = (e, t) => () => {
845
- if (B && B !== e) return;
846
- B = e;
859
+ if (H && H !== e) return;
860
+ H = e;
847
861
  let n = e.scrollHeight - e.clientHeight, r = n > 0 ? e.scrollTop / n : 0, i = t.scrollHeight - t.clientHeight;
848
- t.scrollTop = r * (i > 0 ? i : 0), V && clearTimeout(V), V = setTimeout(() => {
849
- B = null;
862
+ t.scrollTop = r * (i > 0 ? i : 0), U && clearTimeout(U), U = setTimeout(() => {
863
+ H = null;
850
864
  }, 120);
851
865
  }, i = r(t, n), a = r(n, t);
852
- t.addEventListener("scroll", i, { passive: !0 }), n.addEventListener("scroll", a, { passive: !0 }), z = () => {
866
+ t.addEventListener("scroll", i, { passive: !0 }), n.addEventListener("scroll", a, { passive: !0 }), V = () => {
853
867
  t.removeEventListener("scroll", i), n.removeEventListener("scroll", a);
854
868
  };
855
869
  };
856
- S([j, F], ([e, t]) => {
857
- H(), e === "split" && t && u(U);
858
- }), f(H);
859
- let ne = t(() => E.readonly || j.value === "split"), W = (e) => O("update:modelValue", e), G = g(null), K = g(null);
870
+ S([P, R], ([e, t]) => {
871
+ W(), e === "split" && t && u(ie);
872
+ }), f(W);
873
+ let G = t(() => O.readonly || P.value === "split"), K = (e) => k("update:modelValue", e), q = g(null), J = g(null);
860
874
  return l({
861
- insertQuote: (e) => G.value?.insertQuote(e),
862
- insertMention: (e) => G.value?.insertMention(e),
863
- insertImage: (e) => G.value?.insertImage(e),
864
- uploadImage: (e) => G.value?.uploadImage(e),
865
- focus: () => G.value?.focus(),
875
+ insertQuote: (e) => q.value?.insertQuote(e),
876
+ insertMention: (e) => q.value?.insertMention(e),
877
+ insertImage: (e) => q.value?.insertImage(e),
878
+ uploadImage: (e) => q.value?.uploadImage(e),
879
+ focus: () => q.value?.focus(),
866
880
  scrollToHeading: (e) => {
867
- j.value === "source" || j.value === "split" ? K.value?.scrollToHeading(e) : G.value?.scrollToHeading(e);
881
+ P.value === "source" || P.value === "split" ? J.value?.scrollToHeading(e) : q.value?.scrollToHeading(e);
868
882
  }
869
883
  }), (t, l) => (m(), i("div", {
870
884
  ref_key: "rootEl",
871
- ref: R,
885
+ ref: re,
872
886
  class: "kun-editor",
873
887
  "data-kun-editor": "",
874
- "data-mode": j.value
875
- }, [v(t.$slots, "view-switch", {
876
- mode: j.value,
877
- setMode: M,
878
- labels: L.value,
888
+ "data-mode": P.value
889
+ }, [j.value ? (m(), i(e, { key: 0 }, [v(t.$slots, "view-switch", {
890
+ mode: P.value,
891
+ setMode: F,
892
+ labels: B.value,
879
893
  views: s.views,
880
- swapped: N.value,
881
- swap: P,
882
- scrollSync: F.value,
883
- toggleScrollSync: I
894
+ swapped: I.value,
895
+ swap: L,
896
+ scrollSync: R.value,
897
+ toggleScrollSync: z
884
898
  }, () => [s.views.length > 1 ? (m(), i("div", lt, [(m(!0), i(e, null, _(s.views, (e) => (m(), i("button", {
885
899
  key: e,
886
900
  type: "button",
887
901
  class: "kun-editor__tab",
888
- "aria-selected": j.value === e,
889
- "data-active": j.value === e,
890
- onClick: (t) => M(e)
891
- }, y(L.value[e]), 9, ut))), 128)), j.value === "split" ? (m(), i(e, { key: 0 }, [a("button", {
902
+ "aria-selected": P.value === e,
903
+ "data-active": P.value === e,
904
+ onClick: (t) => F(e)
905
+ }, y(B.value[e]), 9, ut))), 128)), P.value === "split" ? (m(), i(e, { key: 0 }, [a("button", {
892
906
  type: "button",
893
907
  class: "kun-editor__tab kun-editor__swap",
894
- title: L.value.swap,
895
- "aria-label": L.value.swap,
896
- onClick: l[0] ||= (e) => P()
908
+ title: B.value.swap,
909
+ "aria-label": B.value.swap,
910
+ onClick: l[0] ||= (e) => L()
897
911
  }, " ⇄ ", 8, dt), a("button", {
898
912
  type: "button",
899
913
  class: "kun-editor__tab",
900
- "data-active": F.value,
901
- title: L.value.scrollSync,
902
- "aria-pressed": F.value,
903
- onClick: l[1] ||= (e) => I()
904
- }, y(L.value.scrollSync), 9, ft)], 64)) : r("", !0)])) : r("", !0)]), o(b(D), null, {
914
+ "data-active": R.value,
915
+ title: B.value.scrollSync,
916
+ "aria-pressed": R.value,
917
+ onClick: l[1] ||= (e) => z()
918
+ }, y(B.value.scrollSync), 9, ft)], 64)) : r("", !0)])) : r("", !0)]), o(b(D), null, {
905
919
  default: C(() => [o(b(A), null, {
906
920
  default: C(() => [w(a("div", null, [o(ot, null, {
907
921
  default: C((e) => [v(t.$slots, "toolbar", d(c(e)), () => [o(at)])]),
908
922
  _: 3
909
- })], 512), [[x, j.value === "wysiwyg" && !s.readonly]]), a("div", {
923
+ })], 512), [[x, P.value === "wysiwyg" && !s.readonly]]), a("div", {
910
924
  class: "kun-editor__panes",
911
- "data-swap": N.value
912
- }, [j.value === "source" || j.value === "split" ? (m(), n(st, {
925
+ "data-swap": I.value
926
+ }, [P.value === "source" || P.value === "split" ? (m(), n(st, {
913
927
  key: 0,
914
928
  ref_key: "source",
915
- ref: K,
929
+ ref: J,
916
930
  class: "kun-editor__pane",
917
931
  "model-value": s.modelValue,
918
932
  readonly: s.readonly,
919
- "onUpdate:modelValue": W
933
+ "onUpdate:modelValue": K
920
934
  }, null, 8, ["model-value", "readonly"])) : r("", !0), w(a("div", mt, [o(Pe, {
921
935
  ref_key: "inner",
922
- ref: G,
936
+ ref: q,
923
937
  "model-value": s.modelValue,
924
938
  adapters: s.adapters,
925
939
  features: s.features,
926
940
  locale: s.locale,
927
- readonly: ne.value,
941
+ readonly: G.value,
928
942
  placeholder: s.placeholder,
929
943
  "placeholder-mode": s.placeholderMode,
930
- active: j.value === "wysiwyg" && !s.readonly,
931
- "selection-toolbar": k.value,
932
- "onUpdate:modelValue": W
944
+ active: P.value === "wysiwyg" && !s.readonly,
945
+ "selection-toolbar": te.value,
946
+ "onUpdate:modelValue": K,
947
+ "onUpdate:loading": N
933
948
  }, null, 8, [
934
949
  "model-value",
935
950
  "adapters",
@@ -940,14 +955,18 @@ var X = Symbol("kun-editor-context"), Se = [
940
955
  "placeholder-mode",
941
956
  "active",
942
957
  "selection-toolbar"
943
- ])], 512), [[x, j.value === "wysiwyg" || j.value === "split"]])], 8, pt)]),
958
+ ])], 512), [[x, P.value === "wysiwyg" || P.value === "split"]])], 8, pt)]),
944
959
  _: 3
945
960
  })]),
946
961
  _: 3
947
- })], 8, ct));
962
+ })], 64)) : r("", !0), !j.value || M.value ? (m(), i("div", ht, [v(t.$slots, "loading", {}, () => [
963
+ l[2] ||= a("div", { class: "kun-editor__skeleton" }, null, -1),
964
+ l[3] ||= a("div", { class: "kun-editor__skeleton" }, null, -1),
965
+ l[4] ||= a("div", { class: "kun-editor__skeleton" }, null, -1)
966
+ ])])) : r("", !0)], 8, ct));
948
967
  }
949
- }), gt = { install(e) {
950
- e.component("KunEditor", ht);
968
+ }), _t = { install(e) {
969
+ e.component("KunEditor", gt);
951
970
  } };
952
971
  //#endregion
953
- export { Fe as EMOJI, ht as KunEditor, gt as KunEditorPlugin, N as parseHeadings };
972
+ export { Fe as EMOJI, gt as KunEditor, _t as KunEditorPlugin, N as parseHeadings };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungal/editor-vue",
3
- "version": "0.30.0",
3
+ "version": "0.31.0",
4
4
  "description": "KunEditor Vue 3 layer — the headless <KunEditor> component (dual WYSIWYG / markdown-source), toolbar and plugin views. Ships zero CSS and no UI-kit dependency; consumes @kungal/editor-core, and pairs with @kungal/editor-nuxt for optional KunUI chrome.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@prosemirror-adapter/vue": "^0.4.6",
43
- "@kungal/editor-core": "0.30.0"
43
+ "@kungal/editor-core": "0.31.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@codemirror/lang-markdown": "^6.0.0",
@@ -80,7 +80,7 @@
80
80
  "vite": "^8.0.16",
81
81
  "vue": "^3.5.35",
82
82
  "vue-tsc": "^3.3.3",
83
- "@kungal/editor-core": "0.30.0"
83
+ "@kungal/editor-core": "0.31.0"
84
84
  },
85
85
  "scripts": {
86
86
  "build": "vite build && vue-tsc -p tsconfig.build.json",