@kungal/editor-vue 0.24.0 → 0.25.1

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,65 @@
1
1
  # @kungal/editor-vue
2
2
 
3
+ ## 0.25.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 177df55: Fix the cursor jumping to the start when editing the source pane in split mode.
8
+
9
+ Typing a character on an empty line (or deleting the first character of a line)
10
+ in the split-view source editor jumped the caret back to the document start. Cause:
11
+ a feedback loop — the source (CodeMirror) edit updated the shared `v-model`, the
12
+ read-only WYSIWYG preview re-rendered and echoed its _re-serialized_ (normalized)
13
+ markdown back into `v-model`, and CodeMirror then rebuilt its whole state
14
+ (`setState`) to match, resetting the selection.
15
+
16
+ Two fixes:
17
+
18
+ - **MilkdownEditor** no longer echoes changes it applied from an external
19
+ `v-model` update (it only emits genuine user edits), so the preview stops
20
+ feeding normalized markdown back.
21
+ - **MarkdownSource** now re-syncs external changes with a content-replacing
22
+ transaction that preserves (clamps) the selection, instead of a full `setState`
23
+ rebuild — so the caret and undo history survive.
24
+
25
+ Verified in the docs production build (split mode): typing `x y z` on an empty
26
+ line yields `xyz` in order; deleting the first char of a line keeps the caret on
27
+ that line; 0 console errors.
28
+
29
+ - @kungal/editor-core@0.25.1
30
+
31
+ ## 0.25.0
32
+
33
+ ### Minor Changes
34
+
35
+ - a103220: Placeholder: default to `'doc'` mode + expose `placeholderMode`.
36
+
37
+ The placeholder used to appear on **every empty line** (the cursor's empty
38
+ block) — that's the Milkdown/Notion `'block'` behavior, which was the default but
39
+ is surprising for a reply/comment editor. `<KunEditor>` now defaults to `'doc'`:
40
+ the placeholder shows **only while the whole editor is empty** (the conventional
41
+ empty-state hint), and the new `placeholderMode` prop opts back into per-line
42
+ `'block'`:
43
+
44
+ ```vue
45
+ <KunEditor v-model="md" placeholder="写点什么…" />
46
+ <!-- only when empty -->
47
+ <KunEditor v-model="md" placeholder="写点什么…" placeholder-mode="block" />
48
+ <!-- on each empty line -->
49
+ ```
50
+
51
+ (The lower-level `createKunEditorPlugins(..., { placeholderMode })` /
52
+ `createPlaceholderPlugin` still default to `'block'` for parity with Crepe; the
53
+ opinion lives in the `<KunEditor>` component.)
54
+
55
+ Verified in the docs production build: empty editor shows the placeholder; typing
56
+ a line then Enter (an empty line in a non-empty doc) does not; `placeholder-mode="block"`
57
+ brings back the per-line hint. 47 core tests pass (incl. new doc-vs-block cases).
58
+
59
+ ### Patch Changes
60
+
61
+ - @kungal/editor-core@0.25.0
62
+
3
63
  ## 0.24.0
4
64
 
5
65
  ### Minor Changes
@@ -12,8 +12,14 @@ type __VLS_Props = {
12
12
  locale?: KunEditorLocale;
13
13
  /** Read-only render (no editing). */
14
14
  readonly?: boolean;
15
- /** Placeholder text shown while the editor is empty. */
15
+ /** Placeholder text shown while empty. */
16
16
  placeholder?: string;
17
+ /**
18
+ * When the placeholder shows: `'doc'` (default) only while the whole editor
19
+ * is empty (the conventional empty-state hint); `'block'` on any empty block
20
+ * at the cursor (Notion style — a hint on every new empty line).
21
+ */
22
+ placeholderMode?: 'doc' | 'block';
17
23
  /**
18
24
  * Which view modes to offer in the switch. Default all three. Drop `'split'`
19
25
  * (or use just `['wysiwyg']`) for compact editors like a reply/comment box —
@@ -78,6 +84,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, KunEditorEx
78
84
  locale: KunEditorLocale;
79
85
  readonly: boolean;
80
86
  placeholder: string;
87
+ placeholderMode: "doc" | "block";
81
88
  selectionToolbar: boolean | KunSelectionItem[];
82
89
  views: ViewMode[];
83
90
  scrollSync: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"KunEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/KunEditor.vue"],"names":[],"mappings":"AA8VA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAM5B,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AASjE,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,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;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;AA0ZJ,QAAA,IAAI,OAAO;;iBAlWS,QAAQ;;;;;;;;;;;;;CAkWP,EAAE,QAAQ;iEA/c/B,CAjUkC;;;;;;;;;;;;;;;CAgxB8B,CAAE;AAClE,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;AAQhD,QAAA,MAAM,UAAU;;;;;cA9bD,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;iBAEJ,MAAM;sBAgBD,OAAO,GAAG,gBAAgB,EAAE;WAVvC,QAAQ,EAAE;gBAGL,OAAO;6EAkbtB,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":"AAsWA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAM5B,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AASjE,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;AA8ZJ,QAAA,IAAI,OAAO;;iBArWS,QAAQ;;;;;;;;;;;;;CAqWP,EAAE,QAAQ;iEAzd/B,CAzUkC;;;;;;;;;;;;;;;CAkyB8B,CAAE;AAClE,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;AAQhD,QAAA,MAAM,UAAU;;;;;cAxcD,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;iBAEJ,MAAM;qBAMF,KAAK,GAAG,OAAO;sBAgBd,OAAO,GAAG,gBAAgB,EAAE;WAVvC,QAAQ,EAAE;gBAGL,OAAO;6EAsbtB,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 +1 @@
1
- {"version":3,"file":"MarkdownSource.vue.d.ts","sourceRoot":"","sources":["../../src/components/MarkdownSource.vue"],"names":[],"mappings":"AA2FA,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAC;AA2EF,QAAA,MAAM,YAAY;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"MarkdownSource.vue.d.ts","sourceRoot":"","sources":["../../src/components/MarkdownSource.vue"],"names":[],"mappings":"AA2GA,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAC;AA2FF,QAAA,MAAM,YAAY;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -7,6 +7,7 @@ type __VLS_Props = {
7
7
  locale: KunEditorLocale;
8
8
  readonly: boolean;
9
9
  placeholder: string;
10
+ placeholderMode: 'doc' | 'block';
10
11
  selectionToolbar: boolean;
11
12
  };
12
13
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, KunEditorExpose, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
@@ -1 +1 @@
1
- {"version":3,"file":"MilkdownEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/MilkdownEditor.vue"],"names":[],"mappings":"AA4MA,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,gBAAgB,EAAE,OAAO,CAAA;CAC1B,CAAC;AA4JF,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":"AA2NA,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;CAC1B,CAAC;AA0KF,QAAA,MAAM,YAAY;;;;kFAIhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
package/dist/index.js CHANGED
@@ -10,28 +10,28 @@ import { createKunEditorPlugins as G, insertKunSpoilerCommand as K, insertMentio
10
10
  import { TextSelection as ie } from "@milkdown/kit/prose/state";
11
11
  import { createCodeBlockCommand as ae, insertHrCommand as oe, insertImageCommand as se, toggleEmphasisCommand as ce, toggleInlineCodeCommand as le, toggleStrongCommand as ue, wrapInBlockquoteCommand as de, wrapInBulletListCommand as fe, wrapInOrderedListCommand as pe } from "@milkdown/kit/preset/commonmark";
12
12
  import { toggleStrikethroughCommand as me } from "@milkdown/kit/preset/gfm";
13
- import { EditorState as he } from "@codemirror/state";
13
+ import { Annotation as he, EditorState as ge } from "@codemirror/state";
14
14
  import { EditorView as Y } from "@codemirror/view";
15
- import { markdown as ge } from "@codemirror/lang-markdown";
16
- import { basicSetup as _e } from "codemirror";
15
+ import { markdown as _e } from "@codemirror/lang-markdown";
16
+ import { basicSetup as ve } from "codemirror";
17
17
  //#region src/context.ts
18
- var X = Symbol("kun-editor-context"), ve = [
18
+ var X = Symbol("kun-editor-context"), ye = [
19
19
  "data-active",
20
20
  "onMousedown",
21
21
  "onMouseenter"
22
- ], ye = ["src", "alt"], be = {
22
+ ], be = ["src", "alt"], xe = {
23
23
  key: 1,
24
24
  class: "kun-mention-dropdown__avatar kun-mention-dropdown__avatar--fallback"
25
- }, xe = { class: "kun-mention-dropdown__name" }, Se = {
25
+ }, Se = { class: "kun-mention-dropdown__name" }, Ce = {
26
26
  key: 1,
27
27
  class: "kun-mention-dropdown__hint"
28
- }, Ce = {
28
+ }, we = {
29
29
  key: 2,
30
30
  class: "kun-mention-dropdown__hint"
31
- }, we = {
31
+ }, Te = {
32
32
  key: 3,
33
33
  class: "kun-mention-dropdown__hint"
34
- }, Te = /* @__PURE__ */ s({
34
+ }, Ee = /* @__PURE__ */ s({
35
35
  __name: "MentionDropdown",
36
36
  setup(n) {
37
37
  let r = /(?:^|\s)@([^\s@]{0,30})$/, o = l(X), s = o?.adapters.searchMentionUsers, c = t(() => (o?.locale ?? "zh-cn").toLowerCase().startsWith("en")), u = t(() => c.value ? {
@@ -137,7 +137,7 @@ var X = Symbol("kun-editor-context"), ve = [
137
137
  src: e.avatar,
138
138
  alt: e.name,
139
139
  class: "kun-mention-dropdown__avatar"
140
- }, null, 8, ye)) : (m(), i("span", be, y(e.name.charAt(0)), 1)), a("span", xe, y(e.name), 1)], 40, ve))), 128)) : D.value ? (m(), i("div", Se, y(u.value.searching), 1)) : C.value ? (m(), i("div", Ce, y(u.value.empty), 1)) : (m(), i("div", we, y(u.value.prompt), 1))], 512));
140
+ }, null, 8, be)) : (m(), i("span", xe, y(e.name.charAt(0)), 1)), a("span", Se, y(e.name), 1)], 40, ye))), 128)) : D.value ? (m(), i("div", Ce, y(u.value.searching), 1)) : C.value ? (m(), i("div", we, y(u.value.empty), 1)) : (m(), i("div", Te, y(u.value.prompt), 1))], 512));
141
141
  }
142
142
  }), Z = (e) => `<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${e}</svg>`, Q = (e, t = 13) => `<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><text x="12" y="12" dominant-baseline="central" text-anchor="middle" font-size="${t}" font-weight="700" font-family="ui-sans-serif, system-ui, sans-serif" fill="currentColor">${e}</text></svg>`, $ = {
143
143
  bold: Z("<path d=\"M6 4h8a4 4 0 0 1 0 8H6z\"/><path d=\"M6 12h9a4 4 0 0 1 0 8H6z\"/>"),
@@ -156,15 +156,15 @@ var X = Symbol("kun-editor-context"), ve = [
156
156
  spoiler: Z("<path d=\"M9.9 4.24A9.1 9.1 0 0 1 12 4c7 0 10 8 10 8a13.2 13.2 0 0 1-1.67 2.68\"/><path d=\"M6.6 6.6A13.5 13.5 0 0 0 2 12s3 8 10 8a9.7 9.7 0 0 0 5.4-1.6\"/><line x1=\"2\" y1=\"2\" x2=\"22\" y2=\"22\"/>"),
157
157
  latex: Q("Σ", 15),
158
158
  smile: Z("<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M8 14s1.5 2 4 2 4-2 4-2\"/><line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\"/><line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\"/>")
159
- }, Ee = {
159
+ }, De = {
160
160
  key: 0,
161
161
  class: "kun-editor__toolbar-divider",
162
162
  "aria-hidden": "true"
163
- }, De = [
163
+ }, Oe = [
164
164
  "title",
165
165
  "aria-label",
166
166
  "onMousedown"
167
- ], Oe = ["innerHTML"], ke = /* @__PURE__ */ s({
167
+ ], ke = ["innerHTML"], Ae = /* @__PURE__ */ s({
168
168
  __name: "SelectionTooltip",
169
169
  setup(n) {
170
170
  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) => {
@@ -221,7 +221,7 @@ var X = Symbol("kun-editor-context"), ve = [
221
221
  ref: d,
222
222
  class: "kun-editor__bubble",
223
223
  "data-show": "false"
224
- }, [(m(!0), i(e, null, _(b.value, (t, n) => (m(), i(e, { key: n }, [t.divider ? (m(), i("span", Ee)) : (m(), i("button", {
224
+ }, [(m(!0), i(e, null, _(b.value, (t, n) => (m(), i(e, { key: n }, [t.divider ? (m(), i("span", De)) : (m(), i("button", {
225
225
  key: 1,
226
226
  type: "button",
227
227
  class: "kun-editor__bubble-btn",
@@ -231,9 +231,9 @@ var X = Symbol("kun-editor-context"), ve = [
231
231
  }, [a("span", {
232
232
  class: "kun-editor__icon",
233
233
  innerHTML: t.svg
234
- }, null, 8, Oe)], 40, De))], 64))), 128))], 512));
234
+ }, null, 8, ke)], 40, Oe))], 64))), 128))], 512));
235
235
  }
236
- }), Ae = /* @__PURE__ */ s({
236
+ }), je = /* @__PURE__ */ s({
237
237
  __name: "MilkdownEditor",
238
238
  props: {
239
239
  modelValue: {},
@@ -242,60 +242,65 @@ var X = Symbol("kun-editor-context"), ve = [
242
242
  locale: {},
243
243
  readonly: { type: Boolean },
244
244
  placeholder: {},
245
+ placeholderMode: {},
245
246
  selectionToolbar: { type: Boolean }
246
247
  },
247
248
  emits: ["update:modelValue"],
248
249
  setup(e, { expose: t, emit: r }) {
249
- let i = e, a = r, o = i.modelValue, s = M(), c = B("kunMention"), l = i.features.mention !== !1 && !!i.adapters.searchMentionUsers && !!s, u = H("kunSelectionTooltip"), d = i.selectionToolbar && !!s, f = O((e) => {
250
+ 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) => {
250
251
  let t = N.make().config((t) => {
251
252
  t.set(L, e), t.set(P, i.modelValue), t.get(R).markdownUpdated((e, t, n) => {
252
- t !== n && (o = t, a("update:modelValue", t));
253
+ s || t === n || (o = t, a("update:modelValue", t));
253
254
  }), t.update(I, (e) => ({
254
255
  ...e,
255
256
  editable: () => !i.readonly
256
- })), l && t.set(c.key, { view: s({ component: Te }) }), d && t.set(u.key, { view: s({ component: ke }) });
257
+ })), u && t.set(l.key, { view: c({ component: Ee }) }), f && t.set(d.key, { view: c({ component: Ae }) });
257
258
  }).use(G(i.adapters, i.features, {
258
259
  locale: i.locale,
259
- placeholder: i.placeholder
260
+ placeholder: i.placeholder,
261
+ placeholderMode: i.placeholderMode
260
262
  }));
261
- return l && t.use(c), d && t.use(u), t;
263
+ return u && t.use(l), f && t.use(d), t;
262
264
  });
263
265
  S(() => i.modelValue, (e) => {
264
- e !== o && (o = e, f.get()?.action(W(e)));
266
+ if (e === o) return;
267
+ o = e;
268
+ let t = p.get();
269
+ t && (s = !0, t.action(W(e)), s = !1);
265
270
  }), S(() => i.readonly, () => {
266
- f.get()?.action((e) => {
271
+ p.get()?.action((e) => {
267
272
  let t = e.get(F);
268
273
  t.dispatch(t.state.tr);
269
274
  });
270
275
  });
271
- let p = () => {
272
- f.get()?.action((e) => e.get(F).focus());
276
+ let h = () => {
277
+ p.get()?.action((e) => e.get(F).focus());
273
278
  };
274
279
  return t({
275
280
  insertQuote: (e) => {
276
- f.get()?.action(U(J.key, e)), p();
281
+ p.get()?.action(U(J.key, e)), h();
277
282
  },
278
283
  insertMention: (e) => {
279
- f.get()?.action(U(q.key, e)), p();
284
+ p.get()?.action(U(q.key, e)), h();
280
285
  },
281
- focus: p
286
+ focus: h
282
287
  }), (e, t) => (m(), n(b(E)));
283
288
  }
284
- }), je = /* @__PURE__ */ "😀.😃.😄.😁.😆.😅.🤣.😂.🙂.🙃.😉.😊.😇.🥰.😍.🤩.😘.😗.😚.😋.😛.😜.🤪.😝.🤗.🤭.🤔.🤐.😐.😑.😶.😏.😒.🙄.😬.😌.😔.😪.🤤.😴.😷.🤒.🤕.🥵.🥶.🥴.😵.🤯.🤠.🥳.😎.🤓.🧐.😕.😟.🙁.😮.😯.😲.😳.🥺.😦.😧.😨.😰.😥.😢.😭.😱.😖.😣.😞.😓.😩.😫.🥱.😤.😡.😠.🤬.😈.👿.💀.💩.🤡.👻.👽.🤖.😺.😸.👍.👎.👌.🤌.🤏.✌️.🤞.🤟.🤘.👋.🤚.🖐️.✋.👏.🙌.🤝.🙏.💪.👀.👁️.❤️.🧡.💛.💚.💙.💜.🖤.🤍.💔.💕.💞.💓.💗.💖.💘.💝.💯.✨.⭐.🌟.🔥.💥.💫.⚡.☀️.🌈.🎉.🎊.🎁.🏆.🐶.🐱.🐭.🦊.🐻.🐼.🐨.🦄.🐢.🐳.🍎.🍑.🍓.🍉.🍰.🍺.🍵.☕.🍜.🍙.✅.❌.❓.❗.💤.👑.🎮.🎵.📌.🔖".split("."), Me = [
289
+ }), Me = /* @__PURE__ */ "😀.😃.😄.😁.😆.😅.🤣.😂.🙂.🙃.😉.😊.😇.🥰.😍.🤩.😘.😗.😚.😋.😛.😜.🤪.😝.🤗.🤭.🤔.🤐.😐.😑.😶.😏.😒.🙄.😬.😌.😔.😪.🤤.😴.😷.🤒.🤕.🥵.🥶.🥴.😵.🤯.🤠.🥳.😎.🤓.🧐.😕.😟.🙁.😮.😯.😲.😳.🥺.😦.😧.😨.😰.😥.😢.😭.😱.😖.😣.😞.😓.😩.😫.🥱.😤.😡.😠.🤬.😈.👿.💀.💩.🤡.👻.👽.🤖.😺.😸.👍.👎.👌.🤌.🤏.✌️.🤞.🤟.🤘.👋.🤚.🖐️.✋.👏.🙌.🤝.🙏.💪.👀.👁️.❤️.🧡.💛.💚.💙.💜.🖤.🤍.💔.💕.💞.💓.💗.💖.💘.💝.💯.✨.⭐.🌟.🔥.💥.💫.⚡.☀️.🌈.🎉.🎊.🎁.🏆.🐶.🐱.🐭.🦊.🐻.🐼.🐨.🦄.🐢.🐳.🍎.🍑.🍓.🍉.🍰.🍺.🍵.☕.🍜.🍙.✅.❌.❓.❗.💤.👑.🎮.🎵.📌.🔖".split("."), Ne = [
285
290
  "title",
286
291
  "aria-label",
287
292
  "aria-expanded"
288
- ], Ne = ["innerHTML"], Pe = { class: "kun-editor__picker-panel" }, Fe = {
293
+ ], Pe = ["innerHTML"], Fe = { class: "kun-editor__picker-panel" }, Ie = {
289
294
  key: 0,
290
295
  class: "kun-editor__picker-tabs",
291
296
  role: "tablist"
292
- }, Ie = ["data-active"], Le = ["data-active"], Re = { class: "kun-editor__emoji-grid" }, ze = ["onClick"], Be = {
297
+ }, Le = ["data-active"], Re = ["data-active"], ze = { class: "kun-editor__emoji-grid" }, Be = ["onClick"], Ve = {
293
298
  key: 1,
294
299
  class: "kun-editor__sticker-body"
295
- }, Ve = { class: "kun-editor__pack-name" }, He = { class: "kun-editor__sticker-grid" }, Ue = ["title", "onClick"], We = ["src", "alt"], Ge = {
300
+ }, He = { class: "kun-editor__pack-name" }, Ue = { class: "kun-editor__sticker-grid" }, We = ["title", "onClick"], Ge = ["src", "alt"], Ke = {
296
301
  key: 1,
297
302
  class: "kun-editor__picker-hint"
298
- }, Ke = /* @__PURE__ */ s({
303
+ }, qe = /* @__PURE__ */ s({
299
304
  __name: "StickerPicker",
300
305
  setup(n) {
301
306
  let [, o] = k(), s = l(X), c = s?.adapters.stickerSource, u = !!c, d = t(() => (s?.locale ?? "zh-cn").toLowerCase().startsWith("en")), h = t(() => d.value ? {
@@ -351,28 +356,28 @@ var X = Symbol("kun-editor-context"), ve = [
351
356
  }, [a("span", {
352
357
  class: "kun-editor__icon",
353
358
  innerHTML: b($).smile
354
- }, null, 8, Ne)], 8, Me), w(a("div", Pe, [
355
- u ? (m(), i("div", Fe, [a("button", {
359
+ }, null, 8, Pe)], 8, Ne), w(a("div", Fe, [
360
+ u ? (m(), i("div", Ie, [a("button", {
356
361
  type: "button",
357
362
  class: "kun-editor__picker-tab",
358
363
  "data-active": C.value === "emoji",
359
364
  onClick: n[0] ||= (e) => C.value = "emoji"
360
- }, y(h.value.emoji), 9, Ie), a("button", {
365
+ }, y(h.value.emoji), 9, Le), a("button", {
361
366
  type: "button",
362
367
  class: "kun-editor__picker-tab",
363
368
  "data-active": C.value === "sticker",
364
369
  onClick: n[1] ||= (e) => C.value = "sticker"
365
- }, y(h.value.sticker), 9, Le)])) : r("", !0),
366
- w(a("div", Re, [(m(!0), i(e, null, _(b(je), (e, t) => (m(), i("button", {
370
+ }, y(h.value.sticker), 9, Re)])) : r("", !0),
371
+ w(a("div", ze, [(m(!0), i(e, null, _(b(Me), (e, t) => (m(), i("button", {
367
372
  key: t,
368
373
  type: "button",
369
374
  class: "kun-editor__emoji",
370
375
  onClick: (t) => M(e)
371
- }, y(e), 9, ze))), 128))], 512), [[x, !u || C.value === "emoji"]]),
372
- u ? w((m(), i("div", Be, [T.value.length ? (m(!0), i(e, { key: 0 }, _(T.value, (t) => (m(), i("div", {
376
+ }, y(e), 9, Be))), 128))], 512), [[x, !u || C.value === "emoji"]]),
377
+ u ? w((m(), i("div", Ve, [T.value.length ? (m(!0), i(e, { key: 0 }, _(T.value, (t) => (m(), i("div", {
373
378
  key: t.name,
374
379
  class: "kun-editor__pack"
375
- }, [a("div", Ve, y(t.name), 1), a("div", He, [(m(!0), i(e, null, _(t.stickers, (e, t) => (m(), i("button", {
380
+ }, [a("div", He, y(t.name), 1), a("div", Ue, [(m(!0), i(e, null, _(t.stickers, (e, t) => (m(), i("button", {
376
381
  key: t,
377
382
  type: "button",
378
383
  class: "kun-editor__sticker",
@@ -382,21 +387,21 @@ var X = Symbol("kun-editor-context"), ve = [
382
387
  src: e.src,
383
388
  alt: e.name,
384
389
  loading: "lazy"
385
- }, null, 8, We)], 8, Ue))), 128))])]))), 128)) : (m(), i("div", Ge, y(D.value ? h.value.failed : h.value.empty), 1))], 512)), [[x, C.value === "sticker"]]) : r("", !0)
390
+ }, null, 8, Ge)], 8, We))), 128))])]))), 128)) : (m(), i("div", Ke, y(D.value ? h.value.failed : h.value.empty), 1))], 512)), [[x, C.value === "sticker"]]) : r("", !0)
386
391
  ], 512), [[x, v.value]])], 512));
387
392
  }
388
- }), qe = {
393
+ }), Je = {
389
394
  class: "kun-editor__format-toolbar",
390
395
  role: "toolbar"
391
- }, Je = ["aria-label"], Ye = {
396
+ }, Ye = ["aria-label"], Xe = {
392
397
  value: "",
393
398
  disabled: "",
394
399
  selected: ""
395
- }, Xe = ["value"], Ze = [
400
+ }, Ze = ["value"], Qe = [
396
401
  "title",
397
402
  "aria-label",
398
403
  "onClick"
399
- ], Qe = ["innerHTML"], $e = ["title", "aria-label"], et = ["innerHTML"], tt = /* @__PURE__ */ s({
404
+ ], $e = ["innerHTML"], et = ["title", "aria-label"], tt = ["innerHTML"], nt = /* @__PURE__ */ s({
400
405
  __name: "EditorToolbar",
401
406
  setup(n) {
402
407
  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) => {
@@ -501,15 +506,15 @@ var X = Symbol("kun-editor-context"), ve = [
501
506
  });
502
507
  });
503
508
  };
504
- return (t, n) => (m(), i("div", qe, [
509
+ return (t, n) => (m(), i("div", Je, [
505
510
  a("select", {
506
511
  class: "kun-editor__heading-select",
507
512
  "aria-label": h.value.textSize,
508
513
  onChange: x
509
- }, [a("option", Ye, y(h.value.textSize), 1), (m(!0), i(e, null, _(v.value, (e) => (m(), i("option", {
514
+ }, [a("option", Xe, y(h.value.textSize), 1), (m(!0), i(e, null, _(v.value, (e) => (m(), i("option", {
510
515
  key: e.level,
511
516
  value: e.level
512
- }, y(e.label), 9, Xe))), 128))], 40, Je),
517
+ }, y(e.label), 9, Ze))), 128))], 40, Ye),
513
518
  (m(!0), i(e, null, _(S.value, (t, r) => (m(), i(e, { key: r }, [n[0] ||= a("span", {
514
519
  class: "kun-editor__toolbar-divider",
515
520
  "aria-hidden": "true"
@@ -523,7 +528,7 @@ var X = Symbol("kun-editor-context"), ve = [
523
528
  }, [a("span", {
524
529
  class: "kun-editor__icon",
525
530
  innerHTML: e.svg
526
- }, null, 8, Qe)], 8, Ze))), 128))], 64))), 128)),
531
+ }, null, 8, $e)], 8, Qe))), 128))], 64))), 128)),
527
532
  u.value ? (m(), i(e, { key: 0 }, [
528
533
  n[1] ||= a("span", {
529
534
  class: "kun-editor__toolbar-divider",
@@ -538,7 +543,7 @@ var X = Symbol("kun-editor-context"), ve = [
538
543
  }, [a("span", {
539
544
  class: "kun-editor__icon",
540
545
  innerHTML: b($).image
541
- }, null, 8, et)], 8, $e),
546
+ }, null, 8, tt)], 8, et),
542
547
  a("input", {
543
548
  ref_key: "fileInput",
544
549
  ref: C,
@@ -551,10 +556,10 @@ var X = Symbol("kun-editor-context"), ve = [
551
556
  d.value ? (m(), i(e, { key: 1 }, [n[2] ||= a("span", {
552
557
  class: "kun-editor__toolbar-divider",
553
558
  "aria-hidden": "true"
554
- }, null, -1), o(Ke)], 64)) : r("", !0)
559
+ }, null, -1), o(qe)], 64)) : r("", !0)
555
560
  ]));
556
561
  }
557
- }), nt = /* @__PURE__ */ s({
562
+ }), rt = /* @__PURE__ */ s({
558
563
  __name: "ToolbarHost",
559
564
  setup(e) {
560
565
  let [, t] = k(), n = l(X, void 0), r = (e, n) => {
@@ -598,7 +603,7 @@ var X = Symbol("kun-editor-context"), ve = [
598
603
  };
599
604
  return (e, t) => v(e.$slots, "default", d(c(a)));
600
605
  }
601
- }), rt = /* @__PURE__ */ s({
606
+ }), it = /* @__PURE__ */ s({
602
607
  __name: "MarkdownSource",
603
608
  props: {
604
609
  modelValue: {},
@@ -606,47 +611,60 @@ var X = Symbol("kun-editor-context"), ve = [
606
611
  },
607
612
  emits: ["update:modelValue"],
608
613
  setup(e, { emit: t }) {
609
- let n = e, r = t, a = g(null), o = null, s = (e) => he.create({
614
+ let n = e, r = t, a = g(null), o = null, s = he.define(), c = (e) => ge.create({
610
615
  doc: e,
611
616
  extensions: [
612
617
  ee(),
613
618
  Y.lineWrapping,
614
- _e,
615
- ge(),
619
+ ve,
620
+ _e(),
616
621
  Y.editable.of(!n.readonly),
617
622
  Y.updateListener.of((e) => {
618
- e.docChanged && r("update:modelValue", e.state.doc.toString());
623
+ e.docChanged && !e.transactions.some((e) => e.annotation(s)) && r("update:modelValue", e.state.doc.toString());
619
624
  })
620
625
  ]
621
626
  });
622
627
  return p(() => {
623
628
  a.value && (o = new Y({
624
- state: s(n.modelValue),
629
+ state: c(n.modelValue),
625
630
  parent: a.value
626
631
  }));
627
632
  }), f(() => {
628
633
  o?.destroy(), o = null;
629
634
  }), S(() => n.modelValue, (e) => {
630
- o && o.state.doc.toString() !== e && o.setState(s(e));
635
+ if (!o || o.state.doc.toString() === e) return;
636
+ let { anchor: t, head: n } = o.state.selection.main, r = e.length;
637
+ o.dispatch({
638
+ changes: {
639
+ from: 0,
640
+ to: o.state.doc.length,
641
+ insert: e
642
+ },
643
+ selection: {
644
+ anchor: Math.min(t, r),
645
+ head: Math.min(n, r)
646
+ },
647
+ annotations: s.of(!0)
648
+ });
631
649
  }), (e, t) => (m(), i("div", {
632
650
  ref_key: "host",
633
651
  ref: a,
634
652
  class: "kun-editor__source"
635
653
  }, null, 512));
636
654
  }
637
- }), it = ["data-mode"], at = {
655
+ }), at = ["data-mode"], ot = {
638
656
  key: 0,
639
657
  class: "kun-editor__toolbar",
640
658
  role: "tablist"
641
- }, ot = [
659
+ }, st = [
642
660
  "aria-selected",
643
661
  "data-active",
644
662
  "onClick"
645
- ], st = ["title", "aria-label"], ct = [
663
+ ], ct = ["title", "aria-label"], lt = [
646
664
  "data-active",
647
665
  "title",
648
666
  "aria-pressed"
649
- ], lt = ["data-swap"], ut = { class: "kun-editor__wysiwyg kun-editor__pane" }, dt = /* @__PURE__ */ s({
667
+ ], ut = ["data-swap"], dt = { class: "kun-editor__wysiwyg kun-editor__pane" }, ft = /* @__PURE__ */ s({
650
668
  __name: "KunEditor",
651
669
  props: {
652
670
  modelValue: {},
@@ -658,6 +676,7 @@ var X = Symbol("kun-editor-context"), ve = [
658
676
  default: !1
659
677
  },
660
678
  placeholder: { default: "" },
679
+ placeholderMode: { default: "doc" },
661
680
  views: { default: () => [
662
681
  "wysiwyg",
663
682
  "source",
@@ -763,41 +782,41 @@ var X = Symbol("kun-editor-context"), ve = [
763
782
  swap: P,
764
783
  scrollSync: F.value,
765
784
  toggleScrollSync: I
766
- }, () => [s.views.length > 1 ? (m(), i("div", at, [(m(!0), i(e, null, _(s.views, (e) => (m(), i("button", {
785
+ }, () => [s.views.length > 1 ? (m(), i("div", ot, [(m(!0), i(e, null, _(s.views, (e) => (m(), i("button", {
767
786
  key: e,
768
787
  type: "button",
769
788
  class: "kun-editor__tab",
770
789
  "aria-selected": j.value === e,
771
790
  "data-active": j.value === e,
772
791
  onClick: (t) => M(e)
773
- }, y(R.value[e]), 9, ot))), 128)), j.value === "split" ? (m(), i(e, { key: 0 }, [a("button", {
792
+ }, y(R.value[e]), 9, st))), 128)), j.value === "split" ? (m(), i(e, { key: 0 }, [a("button", {
774
793
  type: "button",
775
794
  class: "kun-editor__tab kun-editor__swap",
776
795
  title: R.value.swap,
777
796
  "aria-label": R.value.swap,
778
797
  onClick: l[0] ||= (e) => P()
779
- }, " ⇄ ", 8, st), a("button", {
798
+ }, " ⇄ ", 8, ct), a("button", {
780
799
  type: "button",
781
800
  class: "kun-editor__tab",
782
801
  "data-active": F.value,
783
802
  title: R.value.scrollSync,
784
803
  "aria-pressed": F.value,
785
804
  onClick: l[1] ||= (e) => I()
786
- }, y(R.value.scrollSync), 9, ct)], 64)) : r("", !0)])) : r("", !0)]), o(b(D), null, {
805
+ }, y(R.value.scrollSync), 9, lt)], 64)) : r("", !0)])) : r("", !0)]), o(b(D), null, {
787
806
  default: C(() => [o(b(A), null, {
788
- default: C(() => [w(a("div", null, [o(nt, null, {
789
- default: C((e) => [v(t.$slots, "toolbar", d(c(e)), () => [o(tt)])]),
807
+ default: C(() => [w(a("div", null, [o(rt, null, {
808
+ default: C((e) => [v(t.$slots, "toolbar", d(c(e)), () => [o(nt)])]),
790
809
  _: 3
791
810
  })], 512), [[x, j.value === "wysiwyg" && !s.readonly]]), a("div", {
792
811
  class: "kun-editor__panes",
793
812
  "data-swap": N.value
794
- }, [j.value === "source" || j.value === "split" ? (m(), n(rt, {
813
+ }, [j.value === "source" || j.value === "split" ? (m(), n(it, {
795
814
  key: 0,
796
815
  class: "kun-editor__pane",
797
816
  "model-value": s.modelValue,
798
817
  readonly: s.readonly,
799
818
  "onUpdate:modelValue": K
800
- }, null, 8, ["model-value", "readonly"])) : r("", !0), w(a("div", ut, [o(Ae, {
819
+ }, null, 8, ["model-value", "readonly"])) : r("", !0), w(a("div", dt, [o(je, {
801
820
  ref_key: "inner",
802
821
  ref: q,
803
822
  "model-value": s.modelValue,
@@ -806,6 +825,7 @@ var X = Symbol("kun-editor-context"), ve = [
806
825
  locale: s.locale,
807
826
  readonly: G.value,
808
827
  placeholder: s.placeholder,
828
+ "placeholder-mode": s.placeholderMode,
809
829
  "selection-toolbar": k.value,
810
830
  "onUpdate:modelValue": K
811
831
  }, null, 8, [
@@ -815,15 +835,16 @@ var X = Symbol("kun-editor-context"), ve = [
815
835
  "locale",
816
836
  "readonly",
817
837
  "placeholder",
838
+ "placeholder-mode",
818
839
  "selection-toolbar"
819
- ])], 512), [[x, j.value === "wysiwyg" || j.value === "split"]])], 8, lt)]),
840
+ ])], 512), [[x, j.value === "wysiwyg" || j.value === "split"]])], 8, ut)]),
820
841
  _: 3
821
842
  })]),
822
843
  _: 3
823
- })], 8, it));
844
+ })], 8, at));
824
845
  }
825
- }), ft = { install(e) {
826
- e.component("KunEditor", dt);
846
+ }), pt = { install(e) {
847
+ e.component("KunEditor", ft);
827
848
  } };
828
849
  //#endregion
829
- export { je as EMOJI, dt as KunEditor, ft as KunEditorPlugin };
850
+ export { Me as EMOJI, ft as KunEditor, pt as KunEditorPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungal/editor-vue",
3
- "version": "0.24.0",
3
+ "version": "0.25.1",
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.24.0"
43
+ "@kungal/editor-core": "0.25.1"
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.24.0"
83
+ "@kungal/editor-core": "0.25.1"
84
84
  },
85
85
  "scripts": {
86
86
  "build": "vite build && vue-tsc -p tsconfig.build.json",