@kungal/editor-vue 0.5.0 → 0.7.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,51 @@
1
1
  # @kungal/editor-vue
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 4968c96: P3 (complete) — replace the source-mode `<textarea>` with a CodeMirror editor.
8
+
9
+ The "Markdown" tab is now a real CodeMirror editor with markdown syntax
10
+ highlighting, reusing the code block's `kunCM` theme (from
11
+ `@kungal/editor-core`) so the source view and code blocks match. Edits sync back
12
+ through `v-model` to the WYSIWYG view; the view is mounted on demand (CodeMirror
13
+ measures poorly while hidden).
14
+
15
+ Adds `@codemirror/lang-markdown` alongside the CodeMirror packages the editor
16
+ already needs (declared as optional peers; externalized from the build so the
17
+ host dedupes them). This finishes the P3 dual-view editor: WYSIWYG + toolbar +
18
+ @mention dropdown + sticker/emoji picker + CodeMirror source.
19
+
20
+ ### Patch Changes
21
+
22
+ - @kungal/editor-core@0.7.0
23
+
24
+ ## 0.6.0
25
+
26
+ ### Minor Changes
27
+
28
+ - a4cbd3a: P3 — add the sticker / emoji picker to the toolbar.
29
+
30
+ A merged popover (ported from the forum's sticker + emoji Containers):
31
+
32
+ - **Emoji tab** — a built-in curated unicode set, inserted as plain text. No
33
+ adapter, always available.
34
+ - **Sticker tab** — appears only when the host supplies the `stickerSource`
35
+ adapter; loads packs lazily on first open and inserts each sticker as an image
36
+ node (`insertImageCommand`). Stickers are images, so an image-free editor gets
37
+ emoji only.
38
+
39
+ Self-contained (no `@kungal/ui-vue`): a plain trigger button + a click-outside
40
+ popover, themed via CSS variables. Gated by `features.sticker` (default on). The
41
+ `KunEditorContext` now also carries `features` so views can read the flags.
42
+ Verified end-to-end in a browser via `apps/playground` (emoji → text; sticker →
43
+ image node in the v-model markdown).
44
+
45
+ ### Patch Changes
46
+
47
+ - @kungal/editor-core@0.6.0
48
+
3
49
  ## 0.5.0
4
50
 
5
51
  ### Minor Changes
package/README.md CHANGED
@@ -48,11 +48,11 @@ Enable optional plugins by also installing their peers: `katex` (LaTeX),
48
48
 
49
49
  ## Status
50
50
 
51
- **P3 in progress.** `<KunEditor>` now renders a **real Milkdown dual-view
52
- editor**: a WYSIWYG view built from `@kungal/editor-core/preset`
53
- (`createKunEditorPlugins` — spoiler / katex / code-block / mention / upload /
54
- …), plus a markdown-source view, over one `v-model`. The prop/emit surface
55
- (`v-model`, `adapters`, `features`, `locale`, `readonly`) is stable.
51
+ **P3 complete.** `<KunEditor>` is a **real Milkdown dual-view editor**: a WYSIWYG
52
+ view built from `@kungal/editor-core/preset` (`createKunEditorPlugins` — spoiler /
53
+ katex / code-block / mention / upload / …) and a CodeMirror markdown-source view,
54
+ over one `v-model`. The prop/emit surface (`v-model`, `adapters`, `features`,
55
+ `locale`, `readonly`) is stable.
56
56
 
57
57
  A **formatting toolbar** is wired: bold / italic / strikethrough / inline code,
58
58
  H1–H3, bullet & ordered lists, blockquote, code block, divider, spoiler, LaTeX —
@@ -65,8 +65,17 @@ supplies `searchMentionUsers` — a debounced, keyboard-navigable dropdown offer
65
65
  users and inserts a mention chip (`[@name](kungal-user:id)`). Without the adapter
66
66
  the mention schema still round-trips; there's just no autocomplete.
67
67
 
68
- Still to come in P3: the sticker/emoji picker (over `stickerSource`) and the
69
- CodeMirror markdown-source view (currently a `<textarea>`). See
68
+ The **sticker / emoji picker** is a toolbar popover: a built-in emoji tab
69
+ (unicode, inserted as text no adapter) plus a sticker tab that appears when the
70
+ host supplies `stickerSource`, inserting each sticker as an image node. Turn the
71
+ whole picker off with `features.sticker: false`.
72
+
73
+ The **markdown-source view** (the "Markdown" tab) is a CodeMirror editor with
74
+ markdown highlighting, sharing the code block's `kunCM` theme. Edits sync back
75
+ through `v-model` to the WYSIWYG view.
76
+
77
+ Next: **P4** — adopt in the forum, replacing its in-repo `components/kun/milkdown`
78
+ with real adapters. See
70
79
  [`../../docs/architecture.md`](../../docs/architecture.md) § migration.
71
80
 
72
81
  ## Build
@@ -1 +1 @@
1
- {"version":3,"file":"EditorToolbar.vue.d.ts","sourceRoot":"","sources":["../../src/components/EditorToolbar.vue"],"names":[],"mappings":"AA0ZA,QAAA,MAAM,YAAY,+QAChB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"EditorToolbar.vue.d.ts","sourceRoot":"","sources":["../../src/components/EditorToolbar.vue"],"names":[],"mappings":"AAqbA,QAAA,MAAM,YAAY,+QAChB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"KunEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/KunEditor.vue"],"names":[],"mappings":"AAiNA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAK5B,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;CACnB,CAAC;AA4LJ,QAAA,MAAM,YAAY;;;;;cAnMH,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;6EAiMpB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"KunEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/KunEditor.vue"],"names":[],"mappings":"AAuMA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAM5B,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;CACnB,CAAC;AAuMJ,QAAA,MAAM,YAAY;;;;;cA9MH,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;6EA4MpB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -0,0 +1,12 @@
1
+ type __VLS_Props = {
2
+ modelValue: string;
3
+ readonly: boolean;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ "update:modelValue": (markdown: string) => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
+ "onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
9
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
12
+ //# sourceMappingURL=MarkdownSource.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownSource.vue.d.ts","sourceRoot":"","sources":["../../src/components/MarkdownSource.vue"],"names":[],"mappings":"AAkGA,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"}
@@ -0,0 +1,4 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
4
+ //# sourceMappingURL=StickerPicker.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StickerPicker.vue.d.ts","sourceRoot":"","sources":["../../src/components/StickerPicker.vue"],"names":[],"mappings":"AAyhBA,QAAA,MAAM,YAAY,+QAChB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
package/dist/context.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import type { InjectionKey } from 'vue';
2
- import type { KunEditorAdapters, KunEditorLocale } from '@kungal/editor-core';
2
+ import type { KunEditorAdapters, KunEditorFeatures, KunEditorLocale } from '@kungal/editor-core';
3
3
  export interface KunEditorContext {
4
4
  /** The host policy bundle (searchMentionUsers, stickerSource, notify, …). */
5
5
  readonly adapters: KunEditorAdapters;
6
- /** UI language, for view chrome (dropdown hints, etc.). */
6
+ /** Which optional plugins/views are enabled. */
7
+ readonly features: KunEditorFeatures;
8
+ /** UI language, for view chrome (dropdown hints, picker tabs, etc.). */
7
9
  readonly locale: KunEditorLocale;
8
10
  }
9
11
  export declare const KUN_EDITOR_CONTEXT: InjectionKey<KunEditorContext>;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAA;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE7E,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;IACpC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CACjC;AAED,eAAO,MAAM,kBAAkB,EAAE,YAAY,CAAC,gBAAgB,CAChC,CAAA"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAA;AACvC,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAE5B,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;IACpC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;IACpC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CACjC;AAED,eAAO,MAAM,kBAAkB,EAAE,YAAY,CAAC,gBAAgB,CAChC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const EMOJI: readonly string[];
2
+ //# sourceMappingURL=emoji.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emoji.d.ts","sourceRoot":"","sources":["../src/emoji.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,KAAK,EAAE,SAAS,MAAM,EAsBlC,CAAA"}
package/dist/index.js CHANGED
@@ -1,32 +1,36 @@
1
1
  import { Fragment as e, computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createVNode as o, defineComponent as s, inject as c, onBeforeUnmount as l, onMounted as u, openBlock as d, provide as f, ref as p, renderList as m, toDisplayString as h, unref as g, vShow as _, watch as v, withCtx as y, withDirectives as b, withModifiers as x } from "vue";
2
2
  import { Milkdown as S, MilkdownProvider as C, useEditor as w, useInstance as T } from "@milkdown/vue";
3
3
  import { ProsemirrorAdapterProvider as E, usePluginViewContext as D, usePluginViewFactory as O } from "@prosemirror-adapter/vue";
4
- import { Editor as k, defaultValueCtx as A, editorViewOptionsCtx as j, rootCtx as M } from "@milkdown/kit/core";
5
- import { listenerCtx as N } from "@milkdown/kit/plugin/listener";
6
- import { SlashProvider as P, slashFactory as F } from "@milkdown/kit/plugin/slash";
4
+ import { Editor as k, defaultValueCtx as A, editorViewCtx as j, editorViewOptionsCtx as M, rootCtx as N } from "@milkdown/kit/core";
5
+ import { listenerCtx as P } from "@milkdown/kit/plugin/listener";
6
+ import { SlashProvider as ee, slashFactory as F } from "@milkdown/kit/plugin/slash";
7
7
  import { callCommand as I, replaceAll as L } from "@milkdown/kit/utils";
8
- import { createKunEditorPlugins as R, insertKunSpoilerCommand as ee, mentionId as te, toggleLatexCommand as ne } from "@kungal/editor-core/preset";
9
- import { TextSelection as re } from "@milkdown/kit/prose/state";
10
- import { createCodeBlockCommand as ie, insertHrCommand as ae, insertImageCommand as z, toggleEmphasisCommand as B, toggleInlineCodeCommand as V, toggleStrongCommand as H, wrapInBlockquoteCommand as U, wrapInBulletListCommand as W, wrapInHeadingCommand as G, wrapInOrderedListCommand as K } from "@milkdown/kit/preset/commonmark";
11
- import { toggleStrikethroughCommand as q } from "@milkdown/kit/preset/gfm";
8
+ import { createKunEditorPlugins as R, insertKunSpoilerCommand as te, kunCM as ne, mentionId as re, toggleLatexCommand as ie } from "@kungal/editor-core/preset";
9
+ import { TextSelection as ae } from "@milkdown/kit/prose/state";
10
+ import { createCodeBlockCommand as oe, insertHrCommand as se, insertImageCommand as z, toggleEmphasisCommand as B, toggleInlineCodeCommand as V, toggleStrongCommand as H, wrapInBlockquoteCommand as U, wrapInBulletListCommand as W, wrapInHeadingCommand as G, wrapInOrderedListCommand as K } from "@milkdown/kit/preset/commonmark";
11
+ import { toggleStrikethroughCommand as ce } from "@milkdown/kit/preset/gfm";
12
+ import { EditorState as le } from "@codemirror/state";
13
+ import { EditorView as q } from "@codemirror/view";
14
+ import { markdown as ue } from "@codemirror/lang-markdown";
15
+ import { basicSetup as de } from "codemirror";
12
16
  //#region src/context.ts
13
- var J = Symbol("kun-editor-context"), oe = [
17
+ var J = Symbol("kun-editor-context"), fe = [
14
18
  "data-active",
15
19
  "onMousedown",
16
20
  "onMouseenter"
17
- ], se = ["src", "alt"], ce = {
21
+ ], pe = ["src", "alt"], me = {
18
22
  key: 1,
19
23
  class: "kun-mention-dropdown__avatar kun-mention-dropdown__avatar--fallback"
20
- }, le = { class: "kun-mention-dropdown__name" }, ue = {
24
+ }, he = { class: "kun-mention-dropdown__name" }, ge = {
21
25
  key: 1,
22
26
  class: "kun-mention-dropdown__hint"
23
- }, de = {
27
+ }, _e = {
24
28
  key: 2,
25
29
  class: "kun-mention-dropdown__hint"
26
- }, fe = {
30
+ }, ve = {
27
31
  key: 3,
28
32
  class: "kun-mention-dropdown__hint"
29
- }, pe = /* @__PURE__ */ s({
33
+ }, ye = /* @__PURE__ */ s({
30
34
  __name: "MentionDropdown",
31
35
  setup(n) {
32
36
  let r = /(?:^|\s)@([^\s@]{0,30})$/, o = c(J), s = o?.adapters.searchMentionUsers, f = t(() => (o?.locale ?? "zh-cn").toLowerCase().startsWith("en")), g = t(() => f.value ? {
@@ -53,30 +57,30 @@ var J = Symbol("kun-editor-context"), oe = [
53
57
  }
54
58
  t === A && (T.value = n ?? [], E.value = 0, O.value = !1);
55
59
  }, 180);
56
- }, F = (e) => {
60
+ }, P = (e) => {
57
61
  let { selection: t } = e.state;
58
62
  if (!t.empty) return null;
59
63
  let { $from: n } = t, i = n.parent.textBetween(Math.max(0, n.parentOffset - 100), n.parentOffset, void 0, "").match(r);
60
64
  return i ? i[1] ?? "" : null;
61
- }, I = (e) => {
62
- let t = F(e);
65
+ }, F = (e) => {
66
+ let t = P(e);
63
67
  if (t === null) return !1;
64
68
  let n = e.state.selection.$from.pos;
65
69
  return k = {
66
70
  from: n - (t.length + 1),
67
71
  to: n
68
72
  }, t !== w.value && (w.value = t, N(t)), !0;
69
- }, L = (e) => {
73
+ }, I = (e) => {
70
74
  let t = _.value;
71
75
  if (!t || !k) return;
72
- let n = t.state.schema.nodes[te];
76
+ let n = t.state.schema.nodes[re];
73
77
  if (!n) return;
74
78
  let r = n.create({
75
79
  userId: e.id,
76
80
  name: e.name
77
81
  }), { from: i, to: a } = k, o = t.state.tr.replaceWith(i, a, r), s = i + r.nodeSize;
78
- o.insertText(" ", s), o.setSelection(re.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), S.hide();
79
- }, R = (e) => {
82
+ o.insertText(" ", s), o.setSelection(ae.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), S.hide();
83
+ }, L = (e) => {
80
84
  if (!C.value || !T.value.length) {
81
85
  C.value && e.key === "Escape" && (e.preventDefault(), S.hide());
82
86
  return;
@@ -92,7 +96,7 @@ var J = Symbol("kun-editor-context"), oe = [
92
96
  case "Enter":
93
97
  case "Tab": {
94
98
  let t = T.value[E.value];
95
- t && (e.preventDefault(), e.stopPropagation(), L(t));
99
+ t && (e.preventDefault(), e.stopPropagation(), I(t));
96
100
  break;
97
101
  }
98
102
  case "Escape":
@@ -101,20 +105,20 @@ var J = Symbol("kun-editor-context"), oe = [
101
105
  }
102
106
  };
103
107
  return u(() => {
104
- S = new P({
108
+ S = new ee({
105
109
  content: b.value,
106
110
  trigger: "@",
107
- shouldShow: I,
111
+ shouldShow: F,
108
112
  debounce: 0
109
113
  }), S.onShow = () => {
110
114
  C.value = !0;
111
115
  }, S.onHide = () => {
112
116
  C.value = !1, M();
113
- }, S.update(_.value, y.value), window.addEventListener("keydown", R, !0);
117
+ }, S.update(_.value, y.value), window.addEventListener("keydown", L, !0);
114
118
  }), v([_, y], () => {
115
119
  S?.update(_.value, y.value);
116
120
  }), l(() => {
117
- j && clearTimeout(j), window.removeEventListener("keydown", R, !0), S?.destroy();
121
+ j && clearTimeout(j), window.removeEventListener("keydown", L, !0), S?.destroy();
118
122
  }), (t, n) => (d(), i("div", {
119
123
  ref_key: "divRef",
120
124
  ref: b,
@@ -125,16 +129,16 @@ var J = Symbol("kun-editor-context"), oe = [
125
129
  type: "button",
126
130
  class: "kun-mention-dropdown__item",
127
131
  "data-active": t === E.value,
128
- onMousedown: x((t) => L(e), ["prevent"]),
132
+ onMousedown: x((t) => I(e), ["prevent"]),
129
133
  onMouseenter: (e) => E.value = t
130
134
  }, [e.avatar ? (d(), i("img", {
131
135
  key: 0,
132
136
  src: e.avatar,
133
137
  alt: e.name,
134
138
  class: "kun-mention-dropdown__avatar"
135
- }, null, 8, se)) : (d(), i("span", ce, h(e.name.charAt(0)), 1)), a("span", le, h(e.name), 1)], 40, oe))), 128)) : O.value ? (d(), i("div", ue, h(g.value.searching), 1)) : w.value ? (d(), i("div", de, h(g.value.empty), 1)) : (d(), i("div", fe, h(g.value.prompt), 1))], 512));
139
+ }, null, 8, pe)) : (d(), i("span", me, h(e.name.charAt(0)), 1)), a("span", he, h(e.name), 1)], 40, fe))), 128)) : O.value ? (d(), i("div", ge, h(g.value.searching), 1)) : w.value ? (d(), i("div", _e, h(g.value.empty), 1)) : (d(), i("div", ve, h(g.value.prompt), 1))], 512));
136
140
  }
137
- }), me = /* @__PURE__ */ s({
141
+ }), be = /* @__PURE__ */ s({
138
142
  __name: "MilkdownEditor",
139
143
  props: {
140
144
  modelValue: {},
@@ -147,12 +151,12 @@ var J = Symbol("kun-editor-context"), oe = [
147
151
  setup(e, { emit: t }) {
148
152
  let r = e, i = t, a = r.modelValue, o = O(), s = F("kunMention"), c = r.features.mention !== !1 && !!r.adapters.searchMentionUsers && !!o, l = w((e) => {
149
153
  let t = k.make().config((t) => {
150
- t.set(M, e), t.set(A, r.modelValue), t.get(N).markdownUpdated((e, t, n) => {
154
+ t.set(N, e), t.set(A, r.modelValue), t.get(P).markdownUpdated((e, t, n) => {
151
155
  t !== n && (a = t, i("update:modelValue", t));
152
- }), t.update(j, (e) => ({
156
+ }), t.update(M, (e) => ({
153
157
  ...e,
154
158
  editable: () => !r.readonly
155
- })), c && t.set(s.key, { view: o({ component: pe }) });
159
+ })), c && t.set(s.key, { view: o({ component: ye }) });
156
160
  }).use(R(r.adapters, r.features, { locale: r.locale }));
157
161
  return c && t.use(s), t;
158
162
  });
@@ -175,25 +179,130 @@ var J = Symbol("kun-editor-context"), oe = [
175
179
  hr: Y("<line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\"/>"),
176
180
  image: Y("<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"1.8\" fill=\"currentColor\" stroke=\"none\"/><path d=\"m21 15-4.5-4.5a2 2 0 0 0-2.8 0L5 19\"/>"),
177
181
  spoiler: Y("<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\"/>"),
178
- latex: X("Σ", 15)
179
- }, he = {
182
+ latex: X("Σ", 15),
183
+ smile: Y("<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\"/>")
184
+ }, xe = /* @__PURE__ */ "😀.😃.😄.😁.😆.😅.🤣.😂.🙂.🙃.😉.😊.😇.🥰.😍.🤩.😘.😗.😚.😋.😛.😜.🤪.😝.🤗.🤭.🤔.🤐.😐.😑.😶.😏.😒.🙄.😬.😌.😔.😪.🤤.😴.😷.🤒.🤕.🥵.🥶.🥴.😵.🤯.🤠.🥳.😎.🤓.🧐.😕.😟.🙁.😮.😯.😲.😳.🥺.😦.😧.😨.😰.😥.😢.😭.😱.😖.😣.😞.😓.😩.😫.🥱.😤.😡.😠.🤬.😈.👿.💀.💩.🤡.👻.👽.🤖.😺.😸.👍.👎.👌.🤌.🤏.✌️.🤞.🤟.🤘.👋.🤚.🖐️.✋.👏.🙌.🤝.🙏.💪.👀.👁️.❤️.🧡.💛.💚.💙.💜.🖤.🤍.💔.💕.💞.💓.💗.💖.💘.💝.💯.✨.⭐.🌟.🔥.💥.💫.⚡.☀️.🌈.🎉.🎊.🎁.🏆.🐶.🐱.🐭.🦊.🐻.🐼.🐨.🦄.🐢.🐳.🍎.🍑.🍓.🍉.🍰.🍺.🍵.☕.🍜.🍙.✅.❌.❓.❗.💤.👑.🎮.🎵.📌.🔖".split("."), Se = [
185
+ "title",
186
+ "aria-label",
187
+ "aria-expanded"
188
+ ], Ce = ["innerHTML"], we = { class: "kun-editor__picker-panel" }, Te = {
189
+ key: 0,
190
+ class: "kun-editor__picker-tabs",
191
+ role: "tablist"
192
+ }, Ee = ["data-active"], De = ["data-active"], Oe = { class: "kun-editor__emoji-grid" }, ke = ["onClick"], Ae = {
193
+ key: 1,
194
+ class: "kun-editor__sticker-body"
195
+ }, je = { class: "kun-editor__pack-name" }, Me = { class: "kun-editor__sticker-grid" }, Ne = ["title", "onClick"], Pe = ["src", "alt"], Fe = {
196
+ key: 1,
197
+ class: "kun-editor__picker-hint"
198
+ }, Ie = /* @__PURE__ */ s({
199
+ __name: "StickerPicker",
200
+ setup(n) {
201
+ let [, o] = T(), s = c(J), f = s?.adapters.stickerSource, v = !!f, y = t(() => (s?.locale ?? "zh-cn").toLowerCase().startsWith("en")), x = t(() => y.value ? {
202
+ trigger: "Emoji & stickers",
203
+ emoji: "Emoji",
204
+ sticker: "Stickers",
205
+ empty: "No stickers",
206
+ failed: "Failed to load stickers"
207
+ } : {
208
+ trigger: "表情与贴纸",
209
+ emoji: "表情",
210
+ sticker: "贴纸",
211
+ empty: "暂无贴纸",
212
+ failed: "贴纸加载失败"
213
+ }), S = p(!1), C = p(null), w = p("emoji"), E = p([]), D = p(!1), O = p(!1), k = async () => {
214
+ if (!(D.value || !f)) {
215
+ D.value = !0;
216
+ try {
217
+ E.value = await f();
218
+ } catch {
219
+ O.value = !0;
220
+ }
221
+ }
222
+ }, A = () => {
223
+ S.value = !S.value, S.value && v && k();
224
+ }, M = (e) => {
225
+ S.value && C.value && !C.value.contains(e.target) && (S.value = !1);
226
+ };
227
+ u(() => document.addEventListener("click", M)), l(() => document.removeEventListener("click", M));
228
+ let N = (e) => {
229
+ o()?.action((t) => {
230
+ let n = t.get(j), { state: r } = n;
231
+ n.dispatch(r.tr.insertText(e, r.selection.from));
232
+ });
233
+ }, P = (e, t) => {
234
+ o()?.action(I(z.key, {
235
+ src: e,
236
+ title: t,
237
+ alt: t
238
+ }));
239
+ };
240
+ return (t, n) => (d(), i("div", {
241
+ ref_key: "rootRef",
242
+ ref: C,
243
+ class: "kun-editor__picker"
244
+ }, [a("button", {
245
+ type: "button",
246
+ class: "kun-editor__tool",
247
+ title: x.value.trigger,
248
+ "aria-label": x.value.trigger,
249
+ "aria-expanded": S.value,
250
+ onClick: A
251
+ }, [a("span", {
252
+ class: "kun-editor__icon",
253
+ innerHTML: g(Z).smile
254
+ }, null, 8, Ce)], 8, Se), b(a("div", we, [
255
+ v ? (d(), i("div", Te, [a("button", {
256
+ type: "button",
257
+ class: "kun-editor__picker-tab",
258
+ "data-active": w.value === "emoji",
259
+ onClick: n[0] ||= (e) => w.value = "emoji"
260
+ }, h(x.value.emoji), 9, Ee), a("button", {
261
+ type: "button",
262
+ class: "kun-editor__picker-tab",
263
+ "data-active": w.value === "sticker",
264
+ onClick: n[1] ||= (e) => w.value = "sticker"
265
+ }, h(x.value.sticker), 9, De)])) : r("", !0),
266
+ b(a("div", Oe, [(d(!0), i(e, null, m(g(xe), (e, t) => (d(), i("button", {
267
+ key: t,
268
+ type: "button",
269
+ class: "kun-editor__emoji",
270
+ onClick: (t) => N(e)
271
+ }, h(e), 9, ke))), 128))], 512), [[_, !v || w.value === "emoji"]]),
272
+ v ? b((d(), i("div", Ae, [E.value.length ? (d(!0), i(e, { key: 0 }, m(E.value, (t) => (d(), i("div", {
273
+ key: t.name,
274
+ class: "kun-editor__pack"
275
+ }, [a("div", je, h(t.name), 1), a("div", Me, [(d(!0), i(e, null, m(t.stickers, (e, t) => (d(), i("button", {
276
+ key: t,
277
+ type: "button",
278
+ class: "kun-editor__sticker",
279
+ title: e.name,
280
+ onClick: (t) => P(e.src, e.name)
281
+ }, [a("img", {
282
+ src: e.src,
283
+ alt: e.name,
284
+ loading: "lazy"
285
+ }, null, 8, Pe)], 8, Ne))), 128))])]))), 128)) : (d(), i("div", Fe, h(O.value ? x.value.failed : x.value.empty), 1))], 512)), [[_, w.value === "sticker"]]) : r("", !0)
286
+ ], 512), [[_, S.value]])], 512));
287
+ }
288
+ }), Le = {
180
289
  class: "kun-editor__format-toolbar",
181
290
  role: "toolbar"
182
- }, ge = {
291
+ }, Re = {
183
292
  key: 0,
184
293
  class: "kun-editor__toolbar-divider",
185
294
  "aria-hidden": "true"
186
- }, _e = [
295
+ }, ze = [
187
296
  "title",
188
297
  "aria-label",
189
298
  "onClick"
190
- ], ve = ["innerHTML"], ye = ["title", "aria-label"], be = ["innerHTML"], xe = /* @__PURE__ */ s({
299
+ ], Be = ["innerHTML"], Ve = ["title", "aria-label"], He = ["innerHTML"], Q = /* @__PURE__ */ s({
191
300
  __name: "EditorToolbar",
192
301
  setup(n) {
193
- let [, o] = T(), s = c(J), l = t(() => s?.adapters.uploadImage), u = () => s?.adapters.notify, f = t(() => (s?.locale ?? "zh-cn").toLowerCase().startsWith("en")), h = (e, t) => {
194
- o()?.action(I(e, t));
195
- }, _ = t(() => {
196
- let e = f.value;
302
+ let [, s] = T(), l = c(J), u = t(() => l?.adapters.uploadImage), f = () => l?.adapters.notify, h = t(() => l?.features.sticker !== !1), _ = t(() => (l?.locale ?? "zh-cn").toLowerCase().startsWith("en")), v = (e, t) => {
303
+ s()?.action(I(e, t));
304
+ }, y = t(() => {
305
+ let e = _.value;
197
306
  return {
198
307
  bold: e ? "Bold" : "加粗",
199
308
  italic: e ? "Italic" : "斜体",
@@ -211,143 +320,182 @@ var J = Symbol("kun-editor-context"), oe = [
211
320
  latex: e ? "Math (LaTeX)" : "公式",
212
321
  image: e ? "Upload image" : "上传图片"
213
322
  };
214
- }), v = t(() => [
323
+ }), b = t(() => [
215
324
  [
216
325
  {
217
326
  svg: Z.bold,
218
- title: _.value.bold,
219
- run: () => h(H.key)
327
+ title: y.value.bold,
328
+ run: () => v(H.key)
220
329
  },
221
330
  {
222
331
  svg: Z.italic,
223
- title: _.value.italic,
224
- run: () => h(B.key)
332
+ title: y.value.italic,
333
+ run: () => v(B.key)
225
334
  },
226
335
  {
227
336
  svg: Z.strike,
228
- title: _.value.strike,
229
- run: () => h(q.key)
337
+ title: y.value.strike,
338
+ run: () => v(ce.key)
230
339
  },
231
340
  {
232
341
  svg: Z.code,
233
- title: _.value.code,
234
- run: () => h(V.key)
342
+ title: y.value.code,
343
+ run: () => v(V.key)
235
344
  }
236
345
  ],
237
346
  [
238
347
  {
239
348
  svg: Z.h1,
240
- title: _.value.h1,
241
- run: () => h(G.key, 1)
349
+ title: y.value.h1,
350
+ run: () => v(G.key, 1)
242
351
  },
243
352
  {
244
353
  svg: Z.h2,
245
- title: _.value.h2,
246
- run: () => h(G.key, 2)
354
+ title: y.value.h2,
355
+ run: () => v(G.key, 2)
247
356
  },
248
357
  {
249
358
  svg: Z.h3,
250
- title: _.value.h3,
251
- run: () => h(G.key, 3)
359
+ title: y.value.h3,
360
+ run: () => v(G.key, 3)
252
361
  }
253
362
  ],
254
363
  [
255
364
  {
256
365
  svg: Z.bulletList,
257
- title: _.value.bulletList,
258
- run: () => h(W.key)
366
+ title: y.value.bulletList,
367
+ run: () => v(W.key)
259
368
  },
260
369
  {
261
370
  svg: Z.orderedList,
262
- title: _.value.orderedList,
263
- run: () => h(K.key)
371
+ title: y.value.orderedList,
372
+ run: () => v(K.key)
264
373
  },
265
374
  {
266
375
  svg: Z.quote,
267
- title: _.value.quote,
268
- run: () => h(U.key)
376
+ title: y.value.quote,
377
+ run: () => v(U.key)
269
378
  },
270
379
  {
271
380
  svg: Z.codeBlock,
272
- title: _.value.codeBlock,
273
- run: () => h(ie.key, "")
381
+ title: y.value.codeBlock,
382
+ run: () => v(oe.key, "")
274
383
  },
275
384
  {
276
385
  svg: Z.hr,
277
- title: _.value.hr,
278
- run: () => h(ae.key)
386
+ title: y.value.hr,
387
+ run: () => v(se.key)
279
388
  }
280
389
  ],
281
390
  [{
282
391
  svg: Z.spoiler,
283
- title: _.value.spoiler,
284
- run: () => h(ee.key)
392
+ title: y.value.spoiler,
393
+ run: () => v(te.key)
285
394
  }, {
286
395
  svg: Z.latex,
287
- title: _.value.latex,
288
- run: () => h(ne.key)
396
+ title: y.value.latex,
397
+ run: () => v(ie.key)
289
398
  }]
290
- ]), y = p(null), b = () => y.value?.click(), x = async (e) => {
399
+ ]), x = p(null), S = () => x.value?.click(), C = async (e) => {
291
400
  let t = e.target, n = t.files?.[0];
292
401
  t.value = "";
293
- let r = l.value;
402
+ let r = u.value;
294
403
  if (!(!n || !r)) try {
295
404
  let e = await r(n);
296
- h(z.key, {
405
+ v(z.key, {
297
406
  src: e,
298
407
  title: n.name,
299
408
  alt: n.name
300
409
  });
301
410
  } catch {
302
- u()?.(f.value ? "Image upload failed" : "图片上传失败", "error");
411
+ f()?.(_.value ? "Image upload failed" : "图片上传失败", "error");
303
412
  }
304
413
  };
305
- return (t, n) => (d(), i("div", he, [(d(!0), i(e, null, m(v.value, (t, n) => (d(), i(e, { key: n }, [n > 0 ? (d(), i("span", ge)) : r("", !0), (d(!0), i(e, null, m(t, (e, t) => (d(), i("button", {
306
- key: t,
307
- type: "button",
308
- class: "kun-editor__tool",
309
- title: e.title,
310
- "aria-label": e.title,
311
- onClick: (t) => e.run()
312
- }, [a("span", {
313
- class: "kun-editor__icon",
314
- innerHTML: e.svg
315
- }, null, 8, ve)], 8, _e))), 128))], 64))), 128)), l.value ? (d(), i(e, { key: 0 }, [
316
- n[0] ||= a("span", {
317
- class: "kun-editor__toolbar-divider",
318
- "aria-hidden": "true"
319
- }, null, -1),
320
- a("button", {
414
+ return (t, n) => (d(), i("div", Le, [
415
+ (d(!0), i(e, null, m(b.value, (t, n) => (d(), i(e, { key: n }, [n > 0 ? (d(), i("span", Re)) : r("", !0), (d(!0), i(e, null, m(t, (e, t) => (d(), i("button", {
416
+ key: t,
321
417
  type: "button",
322
418
  class: "kun-editor__tool",
323
- title: _.value.image,
324
- "aria-label": _.value.image,
325
- onClick: b
419
+ title: e.title,
420
+ "aria-label": e.title,
421
+ onClick: (t) => e.run()
326
422
  }, [a("span", {
327
423
  class: "kun-editor__icon",
328
- innerHTML: g(Z).image
329
- }, null, 8, be)], 8, ye),
330
- a("input", {
331
- ref_key: "fileInput",
332
- ref: y,
333
- type: "file",
334
- accept: ".jpg,.jpeg,.png,.webp,.gif",
335
- hidden: "",
336
- onChange: x
337
- }, null, 544)
338
- ], 64)) : r("", !0)]));
424
+ innerHTML: e.svg
425
+ }, null, 8, Be)], 8, ze))), 128))], 64))), 128)),
426
+ u.value ? (d(), i(e, { key: 0 }, [
427
+ n[0] ||= a("span", {
428
+ class: "kun-editor__toolbar-divider",
429
+ "aria-hidden": "true"
430
+ }, null, -1),
431
+ a("button", {
432
+ type: "button",
433
+ class: "kun-editor__tool",
434
+ title: y.value.image,
435
+ "aria-label": y.value.image,
436
+ onClick: S
437
+ }, [a("span", {
438
+ class: "kun-editor__icon",
439
+ innerHTML: g(Z).image
440
+ }, null, 8, He)], 8, Ve),
441
+ a("input", {
442
+ ref_key: "fileInput",
443
+ ref: x,
444
+ type: "file",
445
+ accept: ".jpg,.jpeg,.png,.webp,.gif",
446
+ hidden: "",
447
+ onChange: C
448
+ }, null, 544)
449
+ ], 64)) : r("", !0),
450
+ h.value ? (d(), i(e, { key: 1 }, [n[1] ||= a("span", {
451
+ class: "kun-editor__toolbar-divider",
452
+ "aria-hidden": "true"
453
+ }, null, -1), o(Ie)], 64)) : r("", !0)
454
+ ]));
455
+ }
456
+ }), Ue = /* @__PURE__ */ s({
457
+ __name: "MarkdownSource",
458
+ props: {
459
+ modelValue: {},
460
+ readonly: { type: Boolean }
461
+ },
462
+ emits: ["update:modelValue"],
463
+ setup(e, { emit: t }) {
464
+ let n = e, r = t, a = p(null), o = null, s = (e) => le.create({
465
+ doc: e,
466
+ extensions: [
467
+ ne(),
468
+ q.lineWrapping,
469
+ de,
470
+ ue(),
471
+ q.editable.of(!n.readonly),
472
+ q.updateListener.of((e) => {
473
+ e.docChanged && r("update:modelValue", e.state.doc.toString());
474
+ })
475
+ ]
476
+ });
477
+ return u(() => {
478
+ a.value && (o = new q({
479
+ state: s(n.modelValue),
480
+ parent: a.value
481
+ }));
482
+ }), l(() => {
483
+ o?.destroy(), o = null;
484
+ }), v(() => n.modelValue, (e) => {
485
+ o && o.state.doc.toString() !== e && o.setState(s(e));
486
+ }), (e, t) => (d(), i("div", {
487
+ ref_key: "host",
488
+ ref: a,
489
+ class: "kun-editor__source"
490
+ }, null, 512));
339
491
  }
340
- }), Q = {
492
+ }), We = {
341
493
  class: "kun-editor",
342
494
  "data-kun-editor": ""
343
- }, Se = {
495
+ }, Ge = {
344
496
  class: "kun-editor__toolbar",
345
497
  role: "tablist"
346
- }, Ce = ["aria-selected", "data-active"], we = ["aria-selected", "data-active"], Te = { class: "kun-editor__wysiwyg" }, Ee = [
347
- "value",
348
- "readonly",
349
- "lang"
350
- ], $ = /* @__PURE__ */ s({
498
+ }, Ke = ["aria-selected", "data-active"], qe = ["aria-selected", "data-active"], Je = { class: "kun-editor__wysiwyg" }, $ = /* @__PURE__ */ s({
351
499
  __name: "KunEditor",
352
500
  props: {
353
501
  modelValue: {},
@@ -360,69 +508,70 @@ var J = Symbol("kun-editor-context"), oe = [
360
508
  }
361
509
  },
362
510
  emits: ["update:modelValue"],
363
- setup(e, { emit: n }) {
364
- let r = e, s = n;
511
+ setup(e, { emit: s }) {
512
+ let c = e, l = s;
365
513
  f(J, {
366
514
  get adapters() {
367
- return r.adapters;
515
+ return c.adapters;
516
+ },
517
+ get features() {
518
+ return c.features;
368
519
  },
369
520
  get locale() {
370
- return r.locale;
521
+ return c.locale;
371
522
  }
372
523
  });
373
- let c = p("wysiwyg"), l = t(() => r.locale.toLowerCase().startsWith("en")), u = t(() => l.value ? {
524
+ let u = p("wysiwyg"), m = t(() => c.locale.toLowerCase().startsWith("en")), v = t(() => m.value ? {
374
525
  wysiwyg: "Preview",
375
526
  source: "Markdown"
376
527
  } : {
377
528
  wysiwyg: "预览",
378
529
  source: "Markdown"
379
- }), m = (e) => s("update:modelValue", e), v = (e) => s("update:modelValue", e.target.value);
380
- return (t, n) => (d(), i("div", Q, [
381
- a("div", Se, [a("button", {
530
+ }), x = (e) => l("update:modelValue", e);
531
+ return (t, s) => (d(), i("div", We, [
532
+ a("div", Ge, [a("button", {
382
533
  type: "button",
383
534
  class: "kun-editor__tab",
384
- "aria-selected": c.value === "wysiwyg",
385
- "data-active": c.value === "wysiwyg",
386
- onClick: n[0] ||= (e) => c.value = "wysiwyg"
387
- }, h(u.value.wysiwyg), 9, Ce), a("button", {
535
+ "aria-selected": u.value === "wysiwyg",
536
+ "data-active": u.value === "wysiwyg",
537
+ onClick: s[0] ||= (e) => u.value = "wysiwyg"
538
+ }, h(v.value.wysiwyg), 9, Ke), a("button", {
388
539
  type: "button",
389
540
  class: "kun-editor__tab",
390
- "aria-selected": c.value === "source",
391
- "data-active": c.value === "source",
392
- onClick: n[1] ||= (e) => c.value = "source"
393
- }, h(u.value.source), 9, we)]),
541
+ "aria-selected": u.value === "source",
542
+ "data-active": u.value === "source",
543
+ onClick: s[1] ||= (e) => u.value = "source"
544
+ }, h(v.value.source), 9, qe)]),
394
545
  o(g(C), null, {
395
546
  default: y(() => [o(g(E), null, {
396
- default: y(() => [b(o(xe, null, null, 512), [[_, c.value === "wysiwyg" && !e.readonly]]), b(a("div", Te, [o(me, {
547
+ default: y(() => [b(o(Q, null, null, 512), [[_, u.value === "wysiwyg" && !e.readonly]]), b(a("div", Je, [o(be, {
397
548
  "model-value": e.modelValue,
398
549
  adapters: e.adapters,
399
550
  features: e.features,
400
551
  locale: e.locale,
401
552
  readonly: e.readonly,
402
- "onUpdate:modelValue": m
553
+ "onUpdate:modelValue": x
403
554
  }, null, 8, [
404
555
  "model-value",
405
556
  "adapters",
406
557
  "features",
407
558
  "locale",
408
559
  "readonly"
409
- ])], 512), [[_, c.value === "wysiwyg"]])]),
560
+ ])], 512), [[_, u.value === "wysiwyg"]])]),
410
561
  _: 1
411
562
  })]),
412
563
  _: 1
413
564
  }),
414
- b(a("textarea", {
415
- class: "kun-editor__source",
416
- value: e.modelValue,
565
+ u.value === "source" ? (d(), n(Ue, {
566
+ key: 0,
567
+ "model-value": e.modelValue,
417
568
  readonly: e.readonly,
418
- lang: e.locale,
419
- spellcheck: "false",
420
- onInput: v
421
- }, null, 40, Ee), [[_, c.value === "source"]])
569
+ "onUpdate:modelValue": x
570
+ }, null, 8, ["model-value", "readonly"])) : r("", !0)
422
571
  ]));
423
572
  }
424
- }), De = { install(e) {
573
+ }), Ye = { install(e) {
425
574
  e.component("KunEditor", $);
426
575
  } };
427
576
  //#endregion
428
- export { $ as KunEditor, De as KunEditorPlugin };
577
+ export { $ as KunEditor, Ye as KunEditorPlugin };
package/dist/style.css CHANGED
@@ -1,2 +1,2 @@
1
- .kun-mention-dropdown{z-index:30;background:var(--color-background,#fff);border:1px solid var(--color-default-200,#e4e4e7);border-radius:.5rem;min-width:12rem;max-width:20rem;max-height:16rem;padding:.25rem;display:none;position:absolute;overflow-y:auto;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.kun-mention-dropdown[data-show=true]{display:block}.kun-mention-dropdown__item{width:100%;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:.375rem;align-items:center;gap:.5rem;padding:.375rem .5rem;display:flex}.kun-mention-dropdown__item:hover,.kun-mention-dropdown__item[data-active=true]{background:var(--color-default-100,#f4f4f5)}.kun-mention-dropdown__avatar{object-fit:cover;border-radius:9999px;flex-shrink:0;width:1.5rem;height:1.5rem}.kun-mention-dropdown__avatar--fallback{background:var(--color-default-200,#e4e4e7);color:var(--color-default-600,#52525b);justify-content:center;align-items:center;font-size:.75rem;display:flex}.kun-mention-dropdown__name{text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;overflow:hidden}.kun-mention-dropdown__hint{color:var(--color-default-400,#a1a1aa);padding:.375rem .5rem;font-size:.875rem}.kun-editor__format-toolbar{flex-wrap:wrap;align-items:center;gap:.125rem;display:flex}.kun-editor__toolbar-divider{background:var(--color-default-200,#e4e4e7);align-self:stretch;width:1px;margin:.25rem}.kun-editor__tool{width:1.75rem;height:1.75rem;color:var(--color-foreground,#27272a);cursor:pointer;background:0 0;border:none;border-radius:.375rem;justify-content:center;align-items:center;padding:0;display:inline-flex}.kun-editor__tool:hover{background:var(--color-default-100,#f4f4f5)}.kun-editor__icon{display:inline-flex}.kun-editor{flex-direction:column;gap:.5rem;display:flex}.kun-editor__toolbar{gap:.25rem;display:flex}.kun-editor__tab{border:1px solid var(--color-default-200,#e4e4e7);font:inherit;cursor:pointer;background:0 0;border-radius:.5rem;padding:.25rem .75rem}.kun-editor__tab[data-active=true]{background:var(--color-primary,#006fee);border-color:var(--color-primary,#006fee);color:#fff}.kun-editor__wysiwyg .milkdown{outline:none}.kun-editor__wysiwyg .ProseMirror{border:1px solid var(--color-default-200,#e4e4e7);white-space:pre-wrap;word-wrap:break-word;border-radius:.5rem;outline:none;min-height:8rem;padding:.75rem}.kun-editor__source{border:1px solid var(--color-default-200,#e4e4e7);resize:vertical;border-radius:.5rem;width:100%;min-height:8rem;padding:.75rem;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.875rem}
1
+ .kun-mention-dropdown{z-index:30;background:var(--color-background,#fff);border:1px solid var(--color-default-200,#e4e4e7);border-radius:.5rem;min-width:12rem;max-width:20rem;max-height:16rem;padding:.25rem;display:none;position:absolute;overflow-y:auto;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.kun-mention-dropdown[data-show=true]{display:block}.kun-mention-dropdown__item{width:100%;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:.375rem;align-items:center;gap:.5rem;padding:.375rem .5rem;display:flex}.kun-mention-dropdown__item:hover,.kun-mention-dropdown__item[data-active=true]{background:var(--color-default-100,#f4f4f5)}.kun-mention-dropdown__avatar{object-fit:cover;border-radius:9999px;flex-shrink:0;width:1.5rem;height:1.5rem}.kun-mention-dropdown__avatar--fallback{background:var(--color-default-200,#e4e4e7);color:var(--color-default-600,#52525b);justify-content:center;align-items:center;font-size:.75rem;display:flex}.kun-mention-dropdown__name{text-overflow:ellipsis;white-space:nowrap;font-size:.875rem;overflow:hidden}.kun-mention-dropdown__hint{color:var(--color-default-400,#a1a1aa);padding:.375rem .5rem;font-size:.875rem}.kun-editor__picker{display:inline-flex;position:relative}.kun-editor__picker-panel{z-index:30;background:var(--color-background,#fff);border:1px solid var(--color-default-200,#e4e4e7);border-radius:.5rem;width:18rem;padding:.5rem;position:absolute;top:calc(100% + .25rem);left:0;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.kun-editor__picker-tabs{gap:.25rem;margin-bottom:.5rem;display:flex}.kun-editor__picker-tab{font:inherit;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;flex:1;padding:.25rem .5rem}.kun-editor__picker-tab[data-active=true]{border-bottom-color:var(--color-primary,#006fee);color:var(--color-primary,#006fee)}.kun-editor__emoji-grid{grid-template-columns:repeat(8,1fr);gap:.125rem;max-height:16rem;display:grid;overflow-y:auto}.kun-editor__emoji{aspect-ratio:1;cursor:pointer;background:0 0;border:none;border-radius:.375rem;font-size:1.25rem;line-height:1}.kun-editor__emoji:hover{background:var(--color-default-100,#f4f4f5)}.kun-editor__sticker-body{max-height:16rem;overflow-y:auto}.kun-editor__pack-name{color:var(--color-default-500,#71717a);padding:.25rem .125rem;font-size:.75rem}.kun-editor__sticker-grid{grid-template-columns:repeat(5,1fr);gap:.25rem;display:grid}.kun-editor__sticker{aspect-ratio:1;cursor:pointer;background:0 0;border:none;border-radius:.375rem;padding:.125rem}.kun-editor__sticker:hover{background:var(--color-default-100,#f4f4f5)}.kun-editor__sticker img{object-fit:contain;width:100%;height:100%}.kun-editor__picker-hint{color:var(--color-default-400,#a1a1aa);text-align:center;padding:1rem;font-size:.875rem}.kun-editor__format-toolbar{flex-wrap:wrap;align-items:center;gap:.125rem;display:flex}.kun-editor__toolbar-divider{background:var(--color-default-200,#e4e4e7);align-self:stretch;width:1px;margin:.25rem}.kun-editor__tool{width:1.75rem;height:1.75rem;color:var(--color-foreground,#27272a);cursor:pointer;background:0 0;border:none;border-radius:.375rem;justify-content:center;align-items:center;padding:0;display:inline-flex}.kun-editor__tool:hover{background:var(--color-default-100,#f4f4f5)}.kun-editor__icon{display:inline-flex}.kun-editor__source .cm-editor{border:1px solid var(--color-default-200,#e4e4e7);border-radius:.5rem;overflow:hidden}.kun-editor{flex-direction:column;gap:.5rem;display:flex}.kun-editor__toolbar{gap:.25rem;display:flex}.kun-editor__tab{border:1px solid var(--color-default-200,#e4e4e7);font:inherit;cursor:pointer;background:0 0;border-radius:.5rem;padding:.25rem .75rem}.kun-editor__tab[data-active=true]{background:var(--color-primary,#006fee);border-color:var(--color-primary,#006fee);color:#fff}.kun-editor__wysiwyg .milkdown{outline:none}.kun-editor__wysiwyg .ProseMirror{border:1px solid var(--color-default-200,#e4e4e7);white-space:pre-wrap;word-wrap:break-word;border-radius:.5rem;outline:none;min-height:8rem;padding:.75rem}
2
2
  /*$vite$:1*/
@@ -14,5 +14,6 @@ export declare const TOOLBAR_ICONS: {
14
14
  readonly image: string;
15
15
  readonly spoiler: string;
16
16
  readonly latex: string;
17
+ readonly smile: string;
17
18
  };
18
19
  //# sourceMappingURL=toolbar-icons.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar-icons.d.ts","sourceRoot":"","sources":["../src/toolbar-icons.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;CAgBhB,CAAA"}
1
+ {"version":3,"file":"toolbar-icons.d.ts","sourceRoot":"","sources":["../src/toolbar-icons.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;CAiBhB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungal/editor-vue",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "KunEditor Vue 3 layer — the <KunEditor> component (dual WYSIWYG / markdown-source), toolbar and plugin views. Consumes @kungal/editor-core; pairs with @kungal/ui-vue.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -44,26 +44,48 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@prosemirror-adapter/vue": "^0.4.6",
47
- "@kungal/editor-core": "0.5.0"
47
+ "@kungal/editor-core": "0.7.0"
48
48
  },
49
49
  "peerDependencies": {
50
+ "@codemirror/lang-markdown": "^6.0.0",
51
+ "@codemirror/state": "^6.0.0",
52
+ "@codemirror/view": "^6.0.0",
50
53
  "@kungal/ui-vue": "^2.7.0",
51
54
  "@milkdown/kit": "^7.21.2",
52
55
  "@milkdown/prose": "^7.21.2",
53
56
  "@milkdown/vue": "^7.21.2",
57
+ "codemirror": "^6.0.0",
54
58
  "vue": "^3.5.0"
55
59
  },
60
+ "peerDependenciesMeta": {
61
+ "@codemirror/lang-markdown": {
62
+ "optional": true
63
+ },
64
+ "@codemirror/state": {
65
+ "optional": true
66
+ },
67
+ "@codemirror/view": {
68
+ "optional": true
69
+ },
70
+ "codemirror": {
71
+ "optional": true
72
+ }
73
+ },
56
74
  "devDependencies": {
75
+ "@codemirror/lang-markdown": "^6.5.0",
76
+ "@codemirror/state": "^6.5.2",
77
+ "@codemirror/view": "^6.39.4",
57
78
  "@milkdown/kit": "^7.21.2",
58
79
  "@milkdown/prose": "^7.21.2",
59
80
  "@milkdown/vue": "7.21.2",
60
81
  "@types/node": "^22.10.0",
61
82
  "@vitejs/plugin-vue": "^6.0.7",
83
+ "codemirror": "^6.0.2",
62
84
  "typescript": "^5.7.0",
63
85
  "vite": "^8.0.16",
64
86
  "vue": "^3.5.35",
65
87
  "vue-tsc": "^3.3.3",
66
- "@kungal/editor-core": "0.5.0"
88
+ "@kungal/editor-core": "0.7.0"
67
89
  },
68
90
  "scripts": {
69
91
  "build": "vite build && vue-tsc -p tsconfig.build.json",