@kungal/editor-vue 0.4.0 → 0.6.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,52 @@
1
1
  # @kungal/editor-vue
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a4cbd3a: P3 — add the sticker / emoji picker to the toolbar.
8
+
9
+ A merged popover (ported from the forum's sticker + emoji Containers):
10
+
11
+ - **Emoji tab** — a built-in curated unicode set, inserted as plain text. No
12
+ adapter, always available.
13
+ - **Sticker tab** — appears only when the host supplies the `stickerSource`
14
+ adapter; loads packs lazily on first open and inserts each sticker as an image
15
+ node (`insertImageCommand`). Stickers are images, so an image-free editor gets
16
+ emoji only.
17
+
18
+ Self-contained (no `@kungal/ui-vue`): a plain trigger button + a click-outside
19
+ popover, themed via CSS variables. Gated by `features.sticker` (default on). The
20
+ `KunEditorContext` now also carries `features` so views can read the flags.
21
+ Verified end-to-end in a browser via `apps/playground` (emoji → text; sticker →
22
+ image node in the v-model markdown).
23
+
24
+ ### Patch Changes
25
+
26
+ - @kungal/editor-core@0.6.0
27
+
28
+ ## 0.5.0
29
+
30
+ ### Minor Changes
31
+
32
+ - 53a2769: P3 — add the formatting toolbar to `<KunEditor>`.
33
+
34
+ A self-contained `EditorToolbar` (WYSIWYG mode, hidden when read-only) with:
35
+ bold / italic / strikethrough / inline code, H1–H3, bullet & ordered lists,
36
+ blockquote, code block, divider, spoiler and LaTeX — plus an image-upload button
37
+ that appears only when the host supplies `uploadImage`.
38
+
39
+ Ported from the forum's `Menu.vue` + `_buttonList.ts`, but kept dependency-free:
40
+ inline SVG icons (no `@kungal/ui-vue`), themed via CSS variables so a KunUI host
41
+ still gets matching colours. It reaches the editor with `useInstance()` and fires
42
+ commands via `callCommand`; command keys are read at click time (they're only
43
+ populated once the editor is created). Verified end-to-end in a browser via
44
+ `apps/playground`.
45
+
46
+ ### Patch Changes
47
+
48
+ - @kungal/editor-core@0.5.0
49
+
3
50
  ## 0.4.0
4
51
 
5
52
  ### Minor Changes
package/README.md CHANGED
@@ -54,14 +54,24 @@ editor**: a WYSIWYG view built from `@kungal/editor-core/preset`
54
54
  …), plus a markdown-source view, over one `v-model`. The prop/emit surface
55
55
  (`v-model`, `adapters`, `features`, `locale`, `readonly`) is stable.
56
56
 
57
+ A **formatting toolbar** is wired: bold / italic / strikethrough / inline code,
58
+ H1–H3, bullet & ordered lists, blockquote, code block, divider, spoiler, LaTeX —
59
+ plus an image-upload button when `uploadImage` is supplied. It's self-contained
60
+ (inline SVG, no `@kungal/ui-vue` dependency), themed through CSS variables so a
61
+ KunUI host still gets matching colours.
62
+
57
63
  The **`@mention` autocomplete dropdown** is wired: type `@`, and — when the host
58
64
  supplies `searchMentionUsers` — a debounced, keyboard-navigable dropdown offers
59
65
  users and inserts a mention chip (`[@name](kungal-user:id)`). Without the adapter
60
66
  the mention schema still round-trips; there's just no autocomplete.
61
67
 
62
- Still to come in P3 (they build on `@kungal/ui-vue`, hence staged): the rich
63
- formatting toolbar, the sticker/emoji picker, and the CodeMirror markdown-source
64
- 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
+ Still to come in P3: the CodeMirror markdown-source view (currently a
74
+ `<textarea>`). See
65
75
  [`../../docs/architecture.md`](../../docs/architecture.md) § migration.
66
76
 
67
77
  ## Build
@@ -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=EditorToolbar.vue.d.ts.map
@@ -0,0 +1 @@
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":"AA0MA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAI5B,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;AAqLJ,QAAA,MAAM,YAAY;;;;;cA5LH,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;6EA0LpB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"KunEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/KunEditor.vue"],"names":[],"mappings":"AAoNA,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;AA+LJ,QAAA,MAAM,YAAY;;;;;cAtMH,iBAAiB;cAEjB,iBAAiB;YAEnB,eAAe;cAEb,OAAO;6EAoMpB,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,33 +1,35 @@
1
- import { Fragment as e, computed as t, createBlock as n, createElementBlock as r, createElementVNode as i, createVNode as a, defineComponent as o, inject as s, onBeforeUnmount as c, onMounted as l, openBlock as u, provide as d, ref as f, renderList as p, toDisplayString as m, unref as h, vShow as g, watch as _, withCtx as v, withDirectives as y, withModifiers as b } from "vue";
2
- import { Milkdown as x, MilkdownProvider as S, useEditor as C } from "@milkdown/vue";
3
- import { ProsemirrorAdapterProvider as w, usePluginViewContext as T, usePluginViewFactory as E } from "@prosemirror-adapter/vue";
4
- import { Editor as D, defaultValueCtx as O, editorViewOptionsCtx as k, rootCtx as A } from "@milkdown/kit/core";
5
- import { listenerCtx as j } from "@milkdown/kit/plugin/listener";
6
- import { SlashProvider as M, slashFactory as N } from "@milkdown/kit/plugin/slash";
7
- import { replaceAll as P } from "@milkdown/kit/utils";
8
- import { createKunEditorPlugins as F, mentionId as I } from "@kungal/editor-core/preset";
9
- import { TextSelection as L } from "@milkdown/kit/prose/state";
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
+ import { Milkdown as S, MilkdownProvider as C, useEditor as w, useInstance as T } from "@milkdown/vue";
3
+ import { ProsemirrorAdapterProvider as E, usePluginViewContext as D, usePluginViewFactory as O } from "@prosemirror-adapter/vue";
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
+ import { callCommand as I, replaceAll as L } from "@milkdown/kit/utils";
8
+ import { createKunEditorPlugins as te, insertKunSpoilerCommand as R, mentionId as ne, toggleLatexCommand as re } from "@kungal/editor-core/preset";
9
+ import { TextSelection as ie } from "@milkdown/kit/prose/state";
10
+ import { createCodeBlockCommand as ae, insertHrCommand as oe, 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";
10
12
  //#region src/context.ts
11
- var R = Symbol("kun-editor-context"), z = [
13
+ var J = Symbol("kun-editor-context"), se = [
12
14
  "data-active",
13
15
  "onMousedown",
14
16
  "onMouseenter"
15
- ], B = ["src", "alt"], V = {
17
+ ], ce = ["src", "alt"], le = {
16
18
  key: 1,
17
19
  class: "kun-mention-dropdown__avatar kun-mention-dropdown__avatar--fallback"
18
- }, H = { class: "kun-mention-dropdown__name" }, U = {
20
+ }, ue = { class: "kun-mention-dropdown__name" }, de = {
19
21
  key: 1,
20
22
  class: "kun-mention-dropdown__hint"
21
- }, W = {
23
+ }, fe = {
22
24
  key: 2,
23
25
  class: "kun-mention-dropdown__hint"
24
- }, G = {
26
+ }, pe = {
25
27
  key: 3,
26
28
  class: "kun-mention-dropdown__hint"
27
- }, K = /* @__PURE__ */ o({
29
+ }, me = /* @__PURE__ */ s({
28
30
  __name: "MentionDropdown",
29
31
  setup(n) {
30
- let a = /(?:^|\s)@([^\s@]{0,30})$/, o = s(R), d = o?.adapters.searchMentionUsers, h = t(() => (o?.locale ?? "zh-cn").toLowerCase().startsWith("en")), g = t(() => h.value ? {
32
+ 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 ? {
31
33
  searching: "Searching…",
32
34
  empty: "No matching users",
33
35
  prompt: "Type a username to search"
@@ -35,62 +37,62 @@ var R = Symbol("kun-editor-context"), z = [
35
37
  searching: "搜索中…",
36
38
  empty: "无匹配用户",
37
39
  prompt: "输入用户名以搜索"
38
- }), { view: v, prevState: y } = T(), x = f(null), S, C = f(!1), w = f(""), E = f([]), D = f(0), O = f(!1), k = null, A = 0, j = null, N = () => {
39
- j &&= (clearTimeout(j), null), w.value = "", E.value = [], D.value = 0, O.value = !1, k = null;
40
- }, P = (e) => {
41
- if (j &&= (clearTimeout(j), null), !e || !d) {
42
- E.value = [], O.value = !1;
40
+ }), { view: _, prevState: y } = D(), b = p(null), S, C = p(!1), w = p(""), T = p([]), E = p(0), O = p(!1), k = null, A = 0, j = null, M = () => {
41
+ j &&= (clearTimeout(j), null), w.value = "", T.value = [], E.value = 0, O.value = !1, k = null;
42
+ }, N = (e) => {
43
+ if (j &&= (clearTimeout(j), null), !e || !s) {
44
+ T.value = [], O.value = !1;
43
45
  return;
44
46
  }
45
47
  O.value = !0, j = setTimeout(async () => {
46
48
  let t = ++A, n = [];
47
49
  try {
48
- n = await d(e);
50
+ n = await s(e);
49
51
  } catch {
50
52
  n = [];
51
53
  }
52
- t === A && (E.value = n ?? [], D.value = 0, O.value = !1);
54
+ t === A && (T.value = n ?? [], E.value = 0, O.value = !1);
53
55
  }, 180);
54
- }, F = (e) => {
56
+ }, P = (e) => {
55
57
  let { selection: t } = e.state;
56
58
  if (!t.empty) return null;
57
- let { $from: n } = t, r = n.parent.textBetween(Math.max(0, n.parentOffset - 100), n.parentOffset, void 0, "").match(a);
58
- return r ? r[1] ?? "" : null;
59
- }, K = (e) => {
60
- let t = F(e);
59
+ let { $from: n } = t, i = n.parent.textBetween(Math.max(0, n.parentOffset - 100), n.parentOffset, void 0, "").match(r);
60
+ return i ? i[1] ?? "" : null;
61
+ }, F = (e) => {
62
+ let t = P(e);
61
63
  if (t === null) return !1;
62
64
  let n = e.state.selection.$from.pos;
63
65
  return k = {
64
66
  from: n - (t.length + 1),
65
67
  to: n
66
- }, t !== w.value && (w.value = t, P(t)), !0;
67
- }, q = (e) => {
68
- let t = v.value;
68
+ }, t !== w.value && (w.value = t, N(t)), !0;
69
+ }, I = (e) => {
70
+ let t = _.value;
69
71
  if (!t || !k) return;
70
- let n = t.state.schema.nodes[I];
72
+ let n = t.state.schema.nodes[ne];
71
73
  if (!n) return;
72
74
  let r = n.create({
73
75
  userId: e.id,
74
76
  name: e.name
75
77
  }), { from: i, to: a } = k, o = t.state.tr.replaceWith(i, a, r), s = i + r.nodeSize;
76
- o.insertText(" ", s), o.setSelection(L.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), S.hide();
77
- }, J = (e) => {
78
- if (!C.value || !E.value.length) {
78
+ o.insertText(" ", s), o.setSelection(ie.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), S.hide();
79
+ }, L = (e) => {
80
+ if (!C.value || !T.value.length) {
79
81
  C.value && e.key === "Escape" && (e.preventDefault(), S.hide());
80
82
  return;
81
83
  }
82
- let t = E.value.length - 1;
84
+ let t = T.value.length - 1;
83
85
  switch (e.key) {
84
86
  case "ArrowDown":
85
- e.preventDefault(), e.stopPropagation(), D.value = D.value >= t ? 0 : D.value + 1;
87
+ e.preventDefault(), e.stopPropagation(), E.value = E.value >= t ? 0 : E.value + 1;
86
88
  break;
87
89
  case "ArrowUp":
88
- e.preventDefault(), e.stopPropagation(), D.value = D.value <= 0 ? t : D.value - 1;
90
+ e.preventDefault(), e.stopPropagation(), E.value = E.value <= 0 ? t : E.value - 1;
89
91
  break;
90
92
  case "Enter":
91
93
  case "Tab": {
92
- let t = E.value[D.value];
93
- t && (e.preventDefault(), e.stopPropagation(), q(t));
94
+ let t = T.value[E.value];
95
+ t && (e.preventDefault(), e.stopPropagation(), I(t));
94
96
  break;
95
97
  }
96
98
  case "Escape":
@@ -98,41 +100,41 @@ var R = Symbol("kun-editor-context"), z = [
98
100
  break;
99
101
  }
100
102
  };
101
- return l(() => {
102
- S = new M({
103
- content: x.value,
103
+ return u(() => {
104
+ S = new ee({
105
+ content: b.value,
104
106
  trigger: "@",
105
- shouldShow: K,
107
+ shouldShow: F,
106
108
  debounce: 0
107
109
  }), S.onShow = () => {
108
110
  C.value = !0;
109
111
  }, S.onHide = () => {
110
- C.value = !1, N();
111
- }, S.update(v.value, y.value), window.addEventListener("keydown", J, !0);
112
- }), _([v, y], () => {
113
- S?.update(v.value, y.value);
114
- }), c(() => {
115
- j && clearTimeout(j), window.removeEventListener("keydown", J, !0), S?.destroy();
116
- }), (t, n) => (u(), r("div", {
112
+ C.value = !1, M();
113
+ }, S.update(_.value, y.value), window.addEventListener("keydown", L, !0);
114
+ }), v([_, y], () => {
115
+ S?.update(_.value, y.value);
116
+ }), l(() => {
117
+ j && clearTimeout(j), window.removeEventListener("keydown", L, !0), S?.destroy();
118
+ }), (t, n) => (d(), i("div", {
117
119
  ref_key: "divRef",
118
- ref: x,
120
+ ref: b,
119
121
  class: "kun-mention-dropdown",
120
122
  "data-show": "false"
121
- }, [E.value.length ? (u(!0), r(e, { key: 0 }, p(E.value, (e, t) => (u(), r("button", {
123
+ }, [T.value.length ? (d(!0), i(e, { key: 0 }, m(T.value, (e, t) => (d(), i("button", {
122
124
  key: e.id,
123
125
  type: "button",
124
126
  class: "kun-mention-dropdown__item",
125
- "data-active": t === D.value,
126
- onMousedown: b((t) => q(e), ["prevent"]),
127
- onMouseenter: (e) => D.value = t
128
- }, [e.avatar ? (u(), r("img", {
127
+ "data-active": t === E.value,
128
+ onMousedown: x((t) => I(e), ["prevent"]),
129
+ onMouseenter: (e) => E.value = t
130
+ }, [e.avatar ? (d(), i("img", {
129
131
  key: 0,
130
132
  src: e.avatar,
131
133
  alt: e.name,
132
134
  class: "kun-mention-dropdown__avatar"
133
- }, null, 8, B)) : (u(), r("span", V, m(e.name.charAt(0)), 1)), i("span", H, m(e.name), 1)], 40, z))), 128)) : O.value ? (u(), r("div", U, m(g.value.searching), 1)) : w.value ? (u(), r("div", W, m(g.value.empty), 1)) : (u(), r("div", G, m(g.value.prompt), 1))], 512));
135
+ }, null, 8, ce)) : (d(), i("span", le, h(e.name.charAt(0)), 1)), a("span", ue, h(e.name), 1)], 40, se))), 128)) : O.value ? (d(), i("div", de, h(g.value.searching), 1)) : w.value ? (d(), i("div", fe, h(g.value.empty), 1)) : (d(), i("div", pe, h(g.value.prompt), 1))], 512));
134
136
  }
135
- }), q = /* @__PURE__ */ o({
137
+ }), he = /* @__PURE__ */ s({
136
138
  __name: "MilkdownEditor",
137
139
  props: {
138
140
  modelValue: {},
@@ -143,32 +145,321 @@ var R = Symbol("kun-editor-context"), z = [
143
145
  },
144
146
  emits: ["update:modelValue"],
145
147
  setup(e, { emit: t }) {
146
- let r = e, i = t, a = r.modelValue, o = E(), s = N("kunMention"), c = r.features.mention !== !1 && !!r.adapters.searchMentionUsers && !!o, l = C((e) => {
147
- let t = D.make().config((t) => {
148
- t.set(A, e), t.set(O, r.modelValue), t.get(j).markdownUpdated((e, t, n) => {
148
+ 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
+ let t = k.make().config((t) => {
150
+ t.set(N, e), t.set(A, r.modelValue), t.get(P).markdownUpdated((e, t, n) => {
149
151
  t !== n && (a = t, i("update:modelValue", t));
150
- }), t.update(k, (e) => ({
152
+ }), t.update(M, (e) => ({
151
153
  ...e,
152
154
  editable: () => !r.readonly
153
- })), c && t.set(s.key, { view: o({ component: K }) });
154
- }).use(F(r.adapters, r.features, { locale: r.locale }));
155
+ })), c && t.set(s.key, { view: o({ component: me }) });
156
+ }).use(te(r.adapters, r.features, { locale: r.locale }));
155
157
  return c && t.use(s), t;
156
158
  });
157
- return _(() => r.modelValue, (e) => {
158
- e !== a && (a = e, l.get()?.action(P(e)));
159
- }), (e, t) => (u(), n(h(x)));
159
+ return v(() => r.modelValue, (e) => {
160
+ e !== a && (a = e, l.get()?.action(L(e)));
161
+ }), (e, t) => (d(), n(g(S)));
160
162
  }
161
- }), J = {
163
+ }), Y = (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>`, X = (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>`, Z = {
164
+ bold: Y("<path d=\"M6 4h8a4 4 0 0 1 0 8H6z\"/><path d=\"M6 12h9a4 4 0 0 1 0 8H6z\"/>"),
165
+ italic: Y("<line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/>"),
166
+ strike: Y("<path d=\"M16 4H9a3 3 0 0 0-2.83 4\"/><path d=\"M14 12a4 4 0 0 1 0 8H6\"/><line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\"/>"),
167
+ code: Y("<path d=\"m18 16 4-4-4-4\"/><path d=\"m6 8-4 4 4 4\"/><path d=\"m14.5 4-5 16\"/>"),
168
+ h1: X("H1", 11),
169
+ h2: X("H2", 11),
170
+ h3: X("H3", 11),
171
+ bulletList: Y("<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"/><circle cx=\"3.5\" cy=\"6\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"3.5\" cy=\"12\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"3.5\" cy=\"18\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/>"),
172
+ orderedList: Y("<line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/><path d=\"M4 6h1v4\"/><path d=\"M4 10h2\"/><path d=\"M6 18H4c0-1 2-1.5 2-2.5S5 14 4 14.5\"/>"),
173
+ quote: Y("<path d=\"M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z\" fill=\"currentColor\" stroke=\"none\"/>"),
174
+ codeBlock: Y("<rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"2\"/><path d=\"m9 10-2 2 2 2\"/><path d=\"m15 10 2 2-2 2\"/>"),
175
+ hr: Y("<line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\"/>"),
176
+ 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
+ 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
+ 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\"/>")
180
+ }, ge = /* @__PURE__ */ "😀.😃.😄.😁.😆.😅.🤣.😂.🙂.🙃.😉.😊.😇.🥰.😍.🤩.😘.😗.😚.😋.😛.😜.🤪.😝.🤗.🤭.🤔.🤐.😐.😑.😶.😏.😒.🙄.😬.😌.😔.😪.🤤.😴.😷.🤒.🤕.🥵.🥶.🥴.😵.🤯.🤠.🥳.😎.🤓.🧐.😕.😟.🙁.😮.😯.😲.😳.🥺.😦.😧.😨.😰.😥.😢.😭.😱.😖.😣.😞.😓.😩.😫.🥱.😤.😡.😠.🤬.😈.👿.💀.💩.🤡.👻.👽.🤖.😺.😸.👍.👎.👌.🤌.🤏.✌️.🤞.🤟.🤘.👋.🤚.🖐️.✋.👏.🙌.🤝.🙏.💪.👀.👁️.❤️.🧡.💛.💚.💙.💜.🖤.🤍.💔.💕.💞.💓.💗.💖.💘.💝.💯.✨.⭐.🌟.🔥.💥.💫.⚡.☀️.🌈.🎉.🎊.🎁.🏆.🐶.🐱.🐭.🦊.🐻.🐼.🐨.🦄.🐢.🐳.🍎.🍑.🍓.🍉.🍰.🍺.🍵.☕.🍜.🍙.✅.❌.❓.❗.💤.👑.🎮.🎵.📌.🔖".split("."), _e = [
181
+ "title",
182
+ "aria-label",
183
+ "aria-expanded"
184
+ ], ve = ["innerHTML"], Q = { class: "kun-editor__picker-panel" }, ye = {
185
+ key: 0,
186
+ class: "kun-editor__picker-tabs",
187
+ role: "tablist"
188
+ }, be = ["data-active"], xe = ["data-active"], Se = { class: "kun-editor__emoji-grid" }, Ce = ["onClick"], we = {
189
+ key: 1,
190
+ class: "kun-editor__sticker-body"
191
+ }, Te = { class: "kun-editor__pack-name" }, Ee = { class: "kun-editor__sticker-grid" }, De = ["title", "onClick"], Oe = ["src", "alt"], ke = {
192
+ key: 1,
193
+ class: "kun-editor__picker-hint"
194
+ }, Ae = /* @__PURE__ */ s({
195
+ __name: "StickerPicker",
196
+ setup(n) {
197
+ 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 ? {
198
+ trigger: "Emoji & stickers",
199
+ emoji: "Emoji",
200
+ sticker: "Stickers",
201
+ empty: "No stickers",
202
+ failed: "Failed to load stickers"
203
+ } : {
204
+ trigger: "表情与贴纸",
205
+ emoji: "表情",
206
+ sticker: "贴纸",
207
+ empty: "暂无贴纸",
208
+ failed: "贴纸加载失败"
209
+ }), S = p(!1), C = p(null), w = p("emoji"), E = p([]), D = p(!1), O = p(!1), k = async () => {
210
+ if (!(D.value || !f)) {
211
+ D.value = !0;
212
+ try {
213
+ E.value = await f();
214
+ } catch {
215
+ O.value = !0;
216
+ }
217
+ }
218
+ }, A = () => {
219
+ S.value = !S.value, S.value && v && k();
220
+ }, M = (e) => {
221
+ S.value && C.value && !C.value.contains(e.target) && (S.value = !1);
222
+ };
223
+ u(() => document.addEventListener("click", M)), l(() => document.removeEventListener("click", M));
224
+ let N = (e) => {
225
+ o()?.action((t) => {
226
+ let n = t.get(j), { state: r } = n;
227
+ n.dispatch(r.tr.insertText(e, r.selection.from));
228
+ });
229
+ }, P = (e, t) => {
230
+ o()?.action(I(z.key, {
231
+ src: e,
232
+ title: t,
233
+ alt: t
234
+ }));
235
+ };
236
+ return (t, n) => (d(), i("div", {
237
+ ref_key: "rootRef",
238
+ ref: C,
239
+ class: "kun-editor__picker"
240
+ }, [a("button", {
241
+ type: "button",
242
+ class: "kun-editor__tool",
243
+ title: x.value.trigger,
244
+ "aria-label": x.value.trigger,
245
+ "aria-expanded": S.value,
246
+ onClick: A
247
+ }, [a("span", {
248
+ class: "kun-editor__icon",
249
+ innerHTML: g(Z).smile
250
+ }, null, 8, ve)], 8, _e), b(a("div", Q, [
251
+ v ? (d(), i("div", ye, [a("button", {
252
+ type: "button",
253
+ class: "kun-editor__picker-tab",
254
+ "data-active": w.value === "emoji",
255
+ onClick: n[0] ||= (e) => w.value = "emoji"
256
+ }, h(x.value.emoji), 9, be), a("button", {
257
+ type: "button",
258
+ class: "kun-editor__picker-tab",
259
+ "data-active": w.value === "sticker",
260
+ onClick: n[1] ||= (e) => w.value = "sticker"
261
+ }, h(x.value.sticker), 9, xe)])) : r("", !0),
262
+ b(a("div", Se, [(d(!0), i(e, null, m(g(ge), (e, t) => (d(), i("button", {
263
+ key: t,
264
+ type: "button",
265
+ class: "kun-editor__emoji",
266
+ onClick: (t) => N(e)
267
+ }, h(e), 9, Ce))), 128))], 512), [[_, !v || w.value === "emoji"]]),
268
+ v ? b((d(), i("div", we, [E.value.length ? (d(!0), i(e, { key: 0 }, m(E.value, (t) => (d(), i("div", {
269
+ key: t.name,
270
+ class: "kun-editor__pack"
271
+ }, [a("div", Te, h(t.name), 1), a("div", Ee, [(d(!0), i(e, null, m(t.stickers, (e, t) => (d(), i("button", {
272
+ key: t,
273
+ type: "button",
274
+ class: "kun-editor__sticker",
275
+ title: e.name,
276
+ onClick: (t) => P(e.src, e.name)
277
+ }, [a("img", {
278
+ src: e.src,
279
+ alt: e.name,
280
+ loading: "lazy"
281
+ }, null, 8, Oe)], 8, De))), 128))])]))), 128)) : (d(), i("div", ke, h(O.value ? x.value.failed : x.value.empty), 1))], 512)), [[_, w.value === "sticker"]]) : r("", !0)
282
+ ], 512), [[_, S.value]])], 512));
283
+ }
284
+ }), je = {
285
+ class: "kun-editor__format-toolbar",
286
+ role: "toolbar"
287
+ }, Me = {
288
+ key: 0,
289
+ class: "kun-editor__toolbar-divider",
290
+ "aria-hidden": "true"
291
+ }, Ne = [
292
+ "title",
293
+ "aria-label",
294
+ "onClick"
295
+ ], Pe = ["innerHTML"], Fe = ["title", "aria-label"], Ie = ["innerHTML"], Le = /* @__PURE__ */ s({
296
+ __name: "EditorToolbar",
297
+ setup(n) {
298
+ 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) => {
299
+ s()?.action(I(e, t));
300
+ }, y = t(() => {
301
+ let e = _.value;
302
+ return {
303
+ bold: e ? "Bold" : "加粗",
304
+ italic: e ? "Italic" : "斜体",
305
+ strike: e ? "Strikethrough" : "删除线",
306
+ code: e ? "Inline code" : "行内代码",
307
+ h1: e ? "Heading 1" : "一级标题",
308
+ h2: e ? "Heading 2" : "二级标题",
309
+ h3: e ? "Heading 3" : "三级标题",
310
+ bulletList: e ? "Bullet list" : "无序列表",
311
+ orderedList: e ? "Ordered list" : "有序列表",
312
+ quote: e ? "Blockquote" : "引用块",
313
+ codeBlock: e ? "Code block" : "代码块",
314
+ hr: e ? "Divider" : "分隔线",
315
+ spoiler: e ? "Spoiler" : "隐藏文本",
316
+ latex: e ? "Math (LaTeX)" : "公式",
317
+ image: e ? "Upload image" : "上传图片"
318
+ };
319
+ }), b = t(() => [
320
+ [
321
+ {
322
+ svg: Z.bold,
323
+ title: y.value.bold,
324
+ run: () => v(H.key)
325
+ },
326
+ {
327
+ svg: Z.italic,
328
+ title: y.value.italic,
329
+ run: () => v(B.key)
330
+ },
331
+ {
332
+ svg: Z.strike,
333
+ title: y.value.strike,
334
+ run: () => v(q.key)
335
+ },
336
+ {
337
+ svg: Z.code,
338
+ title: y.value.code,
339
+ run: () => v(V.key)
340
+ }
341
+ ],
342
+ [
343
+ {
344
+ svg: Z.h1,
345
+ title: y.value.h1,
346
+ run: () => v(G.key, 1)
347
+ },
348
+ {
349
+ svg: Z.h2,
350
+ title: y.value.h2,
351
+ run: () => v(G.key, 2)
352
+ },
353
+ {
354
+ svg: Z.h3,
355
+ title: y.value.h3,
356
+ run: () => v(G.key, 3)
357
+ }
358
+ ],
359
+ [
360
+ {
361
+ svg: Z.bulletList,
362
+ title: y.value.bulletList,
363
+ run: () => v(W.key)
364
+ },
365
+ {
366
+ svg: Z.orderedList,
367
+ title: y.value.orderedList,
368
+ run: () => v(K.key)
369
+ },
370
+ {
371
+ svg: Z.quote,
372
+ title: y.value.quote,
373
+ run: () => v(U.key)
374
+ },
375
+ {
376
+ svg: Z.codeBlock,
377
+ title: y.value.codeBlock,
378
+ run: () => v(ae.key, "")
379
+ },
380
+ {
381
+ svg: Z.hr,
382
+ title: y.value.hr,
383
+ run: () => v(oe.key)
384
+ }
385
+ ],
386
+ [{
387
+ svg: Z.spoiler,
388
+ title: y.value.spoiler,
389
+ run: () => v(R.key)
390
+ }, {
391
+ svg: Z.latex,
392
+ title: y.value.latex,
393
+ run: () => v(re.key)
394
+ }]
395
+ ]), x = p(null), S = () => x.value?.click(), C = async (e) => {
396
+ let t = e.target, n = t.files?.[0];
397
+ t.value = "";
398
+ let r = u.value;
399
+ if (!(!n || !r)) try {
400
+ let e = await r(n);
401
+ v(z.key, {
402
+ src: e,
403
+ title: n.name,
404
+ alt: n.name
405
+ });
406
+ } catch {
407
+ f()?.(_.value ? "Image upload failed" : "图片上传失败", "error");
408
+ }
409
+ };
410
+ return (t, n) => (d(), i("div", je, [
411
+ (d(!0), i(e, null, m(b.value, (t, n) => (d(), i(e, { key: n }, [n > 0 ? (d(), i("span", Me)) : r("", !0), (d(!0), i(e, null, m(t, (e, t) => (d(), i("button", {
412
+ key: t,
413
+ type: "button",
414
+ class: "kun-editor__tool",
415
+ title: e.title,
416
+ "aria-label": e.title,
417
+ onClick: (t) => e.run()
418
+ }, [a("span", {
419
+ class: "kun-editor__icon",
420
+ innerHTML: e.svg
421
+ }, null, 8, Pe)], 8, Ne))), 128))], 64))), 128)),
422
+ u.value ? (d(), i(e, { key: 0 }, [
423
+ n[0] ||= a("span", {
424
+ class: "kun-editor__toolbar-divider",
425
+ "aria-hidden": "true"
426
+ }, null, -1),
427
+ a("button", {
428
+ type: "button",
429
+ class: "kun-editor__tool",
430
+ title: y.value.image,
431
+ "aria-label": y.value.image,
432
+ onClick: S
433
+ }, [a("span", {
434
+ class: "kun-editor__icon",
435
+ innerHTML: g(Z).image
436
+ }, null, 8, Ie)], 8, Fe),
437
+ a("input", {
438
+ ref_key: "fileInput",
439
+ ref: x,
440
+ type: "file",
441
+ accept: ".jpg,.jpeg,.png,.webp,.gif",
442
+ hidden: "",
443
+ onChange: C
444
+ }, null, 544)
445
+ ], 64)) : r("", !0),
446
+ h.value ? (d(), i(e, { key: 1 }, [n[1] ||= a("span", {
447
+ class: "kun-editor__toolbar-divider",
448
+ "aria-hidden": "true"
449
+ }, null, -1), o(Ae)], 64)) : r("", !0)
450
+ ]));
451
+ }
452
+ }), Re = {
162
453
  class: "kun-editor",
163
454
  "data-kun-editor": ""
164
- }, Y = {
455
+ }, ze = {
165
456
  class: "kun-editor__toolbar",
166
457
  role: "tablist"
167
- }, X = ["aria-selected", "data-active"], Z = ["aria-selected", "data-active"], Q = { class: "kun-editor__wysiwyg" }, ee = [
458
+ }, Be = ["aria-selected", "data-active"], Ve = ["aria-selected", "data-active"], He = { class: "kun-editor__wysiwyg" }, Ue = [
168
459
  "value",
169
460
  "readonly",
170
461
  "lang"
171
- ], $ = /* @__PURE__ */ o({
462
+ ], $ = /* @__PURE__ */ s({
172
463
  __name: "KunEditor",
173
464
  props: {
174
465
  modelValue: {},
@@ -182,68 +473,71 @@ var R = Symbol("kun-editor-context"), z = [
182
473
  },
183
474
  emits: ["update:modelValue"],
184
475
  setup(e, { emit: n }) {
185
- let o = e, s = n;
186
- d(R, {
476
+ let r = e, s = n;
477
+ f(J, {
187
478
  get adapters() {
188
- return o.adapters;
479
+ return r.adapters;
480
+ },
481
+ get features() {
482
+ return r.features;
189
483
  },
190
484
  get locale() {
191
- return o.locale;
485
+ return r.locale;
192
486
  }
193
487
  });
194
- let c = f("wysiwyg"), l = t(() => o.locale.toLowerCase().startsWith("en")), p = t(() => l.value ? {
488
+ let c = p("wysiwyg"), l = t(() => r.locale.toLowerCase().startsWith("en")), u = t(() => l.value ? {
195
489
  wysiwyg: "Preview",
196
490
  source: "Markdown"
197
491
  } : {
198
492
  wysiwyg: "预览",
199
493
  source: "Markdown"
200
- }), _ = (e) => s("update:modelValue", e), b = (e) => s("update:modelValue", e.target.value);
201
- return (t, n) => (u(), r("div", J, [
202
- i("div", Y, [i("button", {
494
+ }), m = (e) => s("update:modelValue", e), v = (e) => s("update:modelValue", e.target.value);
495
+ return (t, n) => (d(), i("div", Re, [
496
+ a("div", ze, [a("button", {
203
497
  type: "button",
204
498
  class: "kun-editor__tab",
205
499
  "aria-selected": c.value === "wysiwyg",
206
500
  "data-active": c.value === "wysiwyg",
207
501
  onClick: n[0] ||= (e) => c.value = "wysiwyg"
208
- }, m(p.value.wysiwyg), 9, X), i("button", {
502
+ }, h(u.value.wysiwyg), 9, Be), a("button", {
209
503
  type: "button",
210
504
  class: "kun-editor__tab",
211
505
  "aria-selected": c.value === "source",
212
506
  "data-active": c.value === "source",
213
507
  onClick: n[1] ||= (e) => c.value = "source"
214
- }, m(p.value.source), 9, Z)]),
215
- a(h(S), null, {
216
- default: v(() => [a(h(w), null, {
217
- default: v(() => [y(i("div", Q, [a(q, {
508
+ }, h(u.value.source), 9, Ve)]),
509
+ o(g(C), null, {
510
+ default: y(() => [o(g(E), null, {
511
+ default: y(() => [b(o(Le, null, null, 512), [[_, c.value === "wysiwyg" && !e.readonly]]), b(a("div", He, [o(he, {
218
512
  "model-value": e.modelValue,
219
513
  adapters: e.adapters,
220
514
  features: e.features,
221
515
  locale: e.locale,
222
516
  readonly: e.readonly,
223
- "onUpdate:modelValue": _
517
+ "onUpdate:modelValue": m
224
518
  }, null, 8, [
225
519
  "model-value",
226
520
  "adapters",
227
521
  "features",
228
522
  "locale",
229
523
  "readonly"
230
- ])], 512), [[g, c.value === "wysiwyg"]])]),
524
+ ])], 512), [[_, c.value === "wysiwyg"]])]),
231
525
  _: 1
232
526
  })]),
233
527
  _: 1
234
528
  }),
235
- y(i("textarea", {
529
+ b(a("textarea", {
236
530
  class: "kun-editor__source",
237
531
  value: e.modelValue,
238
532
  readonly: e.readonly,
239
533
  lang: e.locale,
240
534
  spellcheck: "false",
241
- onInput: b
242
- }, null, 40, ee), [[g, c.value === "source"]])
535
+ onInput: v
536
+ }, null, 40, Ue), [[_, c.value === "source"]])
243
537
  ]));
244
538
  }
245
- }), te = { install(e) {
539
+ }), We = { install(e) {
246
540
  e.component("KunEditor", $);
247
541
  } };
248
542
  //#endregion
249
- export { $ as KunEditor, te as KunEditorPlugin };
543
+ export { $ as KunEditor, We 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{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);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{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}
2
2
  /*$vite$:1*/
@@ -0,0 +1,19 @@
1
+ export declare const TOOLBAR_ICONS: {
2
+ readonly bold: string;
3
+ readonly italic: string;
4
+ readonly strike: string;
5
+ readonly code: string;
6
+ readonly h1: string;
7
+ readonly h2: string;
8
+ readonly h3: string;
9
+ readonly bulletList: string;
10
+ readonly orderedList: string;
11
+ readonly quote: string;
12
+ readonly codeBlock: string;
13
+ readonly hr: string;
14
+ readonly image: string;
15
+ readonly spoiler: string;
16
+ readonly latex: string;
17
+ readonly smile: string;
18
+ };
19
+ //# sourceMappingURL=toolbar-icons.d.ts.map
@@ -0,0 +1 @@
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.4.0",
3
+ "version": "0.6.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,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@prosemirror-adapter/vue": "^0.4.6",
47
- "@kungal/editor-core": "0.4.0"
47
+ "@kungal/editor-core": "0.6.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "@kungal/ui-vue": "^2.7.0",
@@ -63,7 +63,7 @@
63
63
  "vite": "^8.0.16",
64
64
  "vue": "^3.5.35",
65
65
  "vue-tsc": "^3.3.3",
66
- "@kungal/editor-core": "0.4.0"
66
+ "@kungal/editor-core": "0.6.0"
67
67
  },
68
68
  "scripts": {
69
69
  "build": "vite build && vue-tsc -p tsconfig.build.json",