@kungal/editor-vue 0.6.0 → 0.8.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,50 @@
1
1
  # @kungal/editor-vue
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c0908c5: Make `<KunEditor>` headless — ship zero CSS.
8
+
9
+ **BREAKING** (pre-1.0): the `@kungal/editor-vue/style.css` export is removed. The
10
+ component now renders only stable class hooks (`.kun-editor__*`,
11
+ `.kun-mention-dropdown*`) and `data-*` state; all styling is the host's.
12
+
13
+ Migration: copy the reference stylesheet
14
+ `apps/docs/app/assets/css/kun-editor.css` (themed with KunUI tokens) into your
15
+ app and import it, or write your own targeting the same hooks. Also import each
16
+ enabled peer's CSS (e.g. `katex/dist/katex.min.css`). The reference stylesheet
17
+ carries the two structural rules the editor needs (ProseMirror `white-space`,
18
+ popover positioning / show-hide).
19
+
20
+ Also drops the unused `@kungal/ui-vue` peer dependency — the editor no longer
21
+ references any UI kit, so it installs in any Vue 3 app.
22
+
23
+ ### Patch Changes
24
+
25
+ - @kungal/editor-core@0.8.0
26
+
27
+ ## 0.7.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 4968c96: P3 (complete) — replace the source-mode `<textarea>` with a CodeMirror editor.
32
+
33
+ The "Markdown" tab is now a real CodeMirror editor with markdown syntax
34
+ highlighting, reusing the code block's `kunCM` theme (from
35
+ `@kungal/editor-core`) so the source view and code blocks match. Edits sync back
36
+ through `v-model` to the WYSIWYG view; the view is mounted on demand (CodeMirror
37
+ measures poorly while hidden).
38
+
39
+ Adds `@codemirror/lang-markdown` alongside the CodeMirror packages the editor
40
+ already needs (declared as optional peers; externalized from the build so the
41
+ host dedupes them). This finishes the P3 dual-view editor: WYSIWYG + toolbar +
42
+ @mention dropdown + sticker/emoji picker + CodeMirror source.
43
+
44
+ ### Patch Changes
45
+
46
+ - @kungal/editor-core@0.7.0
47
+
3
48
  ## 0.6.0
4
49
 
5
50
  ### Minor Changes
package/README.md CHANGED
@@ -2,18 +2,22 @@
2
2
 
3
3
  The **Vue 3 render layer** of KunEditor: the `<KunEditor>` component (dual
4
4
  WYSIWYG preview + markdown-source), its toolbar and the Vue plugin views
5
- (mention dropdown, tooltip, sticker/emoji picker). Consumes
6
- [`@kungal/editor-core`](../editor-core) for the plugin brain and pairs with
7
- [`@kungal/ui-vue`](https://github.com/kungal/kun-ui) for the chrome.
5
+ (mention dropdown, sticker/emoji picker). Consumes
6
+ [`@kungal/editor-core`](../editor-core) for the plugin brain.
8
7
 
9
- Works in any Vue 3 app; `@kungal/editor-nuxt` adds Nuxt auto-import sugar.
8
+ **Headless ships zero CSS.** The component only renders stable class hooks
9
+ (`.kun-editor__*`, `.kun-mention-dropdown*`) + `data-*` state; you own the look.
10
+ Copy the reference stylesheet [`apps/docs/app/assets/css/kun-editor.css`](../../apps/docs/app/assets/css/kun-editor.css)
11
+ (themed with KunUI tokens), or write your own. It works in any Vue 3 app;
12
+ `@kungal/editor-nuxt` adds Nuxt auto-import sugar.
10
13
 
11
14
  ## Usage
12
15
 
13
16
  ```vue
14
17
  <script setup lang="ts">
15
18
  import { KunEditor, type KunEditorAdapters } from '@kungal/editor-vue'
16
- import '@kungal/editor-vue/style.css'
19
+ // Headless: bring your own styles. See apps/docs for the KunUI-themed reference.
20
+ import '~/assets/kun-editor.css'
17
21
 
18
22
  const markdown = ref('')
19
23
 
@@ -38,21 +42,21 @@ no other config.
38
42
  Install the Milkdown stack **once in the host** (single ProseMirror instance):
39
43
 
40
44
  ```bash
41
- pnpm add @kungal/editor-vue @kungal/editor-core \
42
- @kungal/ui-vue vue \
45
+ pnpm add @kungal/editor-vue @kungal/editor-core vue \
43
46
  @milkdown/kit @milkdown/prose @milkdown/vue
44
47
  ```
45
48
 
46
- Enable optional plugins by also installing their peers: `katex` (LaTeX),
47
- `codemirror` + `@codemirror/view` + `@codemirror/language-data` (code blocks).
49
+ Enable optional plugins by also installing their peers: `katex` (LaTeX, also
50
+ import `katex/dist/katex.min.css`), the `@codemirror/*` packages + `codemirror`
51
+ (code blocks and the markdown-source view).
48
52
 
49
53
  ## Status
50
54
 
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.
55
+ **P3 complete.** `<KunEditor>` is a **real Milkdown dual-view editor**: a WYSIWYG
56
+ view built from `@kungal/editor-core/preset` (`createKunEditorPlugins` — spoiler /
57
+ katex / code-block / mention / upload / …) and a CodeMirror markdown-source view,
58
+ over one `v-model`. The prop/emit surface (`v-model`, `adapters`, `features`,
59
+ `locale`, `readonly`) is stable.
56
60
 
57
61
  A **formatting toolbar** is wired: bold / italic / strikethrough / inline code,
58
62
  H1–H3, bullet & ordered lists, blockquote, code block, divider, spoiler, LaTeX —
@@ -70,8 +74,12 @@ The **sticker / emoji picker** is a toolbar popover: a built-in emoji tab
70
74
  host supplies `stickerSource`, inserting each sticker as an image node. Turn the
71
75
  whole picker off with `features.sticker: false`.
72
76
 
73
- Still to come in P3: the CodeMirror markdown-source view (currently a
74
- `<textarea>`). See
77
+ The **markdown-source view** (the "Markdown" tab) is a CodeMirror editor with
78
+ markdown highlighting, sharing the code block's `kunCM` theme. Edits sync back
79
+ through `v-model` to the WYSIWYG view.
80
+
81
+ Next: **P4** — adopt in the forum, replacing its in-repo `components/kun/milkdown`
82
+ with real adapters. See
75
83
  [`../../docs/architecture.md`](../../docs/architecture.md) § migration.
76
84
 
77
85
  ## Build
@@ -1 +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
+ {"version":3,"file":"EditorToolbar.vue.d.ts","sourceRoot":"","sources":["../../src/components/EditorToolbar.vue"],"names":[],"mappings":"AAgZA,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":"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"}
1
+ {"version":3,"file":"KunEditor.vue.d.ts","sourceRoot":"","sources":["../../src/components/KunEditor.vue"],"names":[],"mappings":"AA6JA,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":"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 +1 @@
1
- {"version":3,"file":"MentionDropdown.vue.d.ts","sourceRoot":"","sources":["../../src/components/MentionDropdown.vue"],"names":[],"mappings":"AA8pBA,QAAA,MAAM,YAAY,+QAChB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"MentionDropdown.vue.d.ts","sourceRoot":"","sources":["../../src/components/MentionDropdown.vue"],"names":[],"mappings":"AAulBA,QAAA,MAAM,YAAY,+QAChB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +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"}
1
+ {"version":3,"file":"StickerPicker.vue.d.ts","sourceRoot":"","sources":["../../src/components/StickerPicker.vue"],"names":[],"mappings":"AA8aA,QAAA,MAAM,YAAY,+QAChB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
package/dist/index.js CHANGED
@@ -5,28 +5,32 @@ import { Editor as k, defaultValueCtx as A, editorViewCtx as j, editorViewOption
5
5
  import { listenerCtx as P } from "@milkdown/kit/plugin/listener";
6
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 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";
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"), se = [
17
+ var J = Symbol("kun-editor-context"), fe = [
14
18
  "data-active",
15
19
  "onMousedown",
16
20
  "onMouseenter"
17
- ], ce = ["src", "alt"], le = {
21
+ ], pe = ["src", "alt"], me = {
18
22
  key: 1,
19
23
  class: "kun-mention-dropdown__avatar kun-mention-dropdown__avatar--fallback"
20
- }, ue = { class: "kun-mention-dropdown__name" }, de = {
24
+ }, he = { class: "kun-mention-dropdown__name" }, ge = {
21
25
  key: 1,
22
26
  class: "kun-mention-dropdown__hint"
23
- }, fe = {
27
+ }, _e = {
24
28
  key: 2,
25
29
  class: "kun-mention-dropdown__hint"
26
- }, pe = {
30
+ }, ve = {
27
31
  key: 3,
28
32
  class: "kun-mention-dropdown__hint"
29
- }, me = /* @__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 ? {
@@ -69,13 +73,13 @@ var J = Symbol("kun-editor-context"), se = [
69
73
  }, I = (e) => {
70
74
  let t = _.value;
71
75
  if (!t || !k) return;
72
- let n = t.state.schema.nodes[ne];
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(ie.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), S.hide();
82
+ o.insertText(" ", s), o.setSelection(ae.create(o.doc, s + 1)), t.dispatch(o.scrollIntoView()), t.focus(), S.hide();
79
83
  }, L = (e) => {
80
84
  if (!C.value || !T.value.length) {
81
85
  C.value && e.key === "Escape" && (e.preventDefault(), S.hide());
@@ -132,9 +136,9 @@ var J = Symbol("kun-editor-context"), se = [
132
136
  src: e.avatar,
133
137
  alt: e.name,
134
138
  class: "kun-mention-dropdown__avatar"
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));
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
- }), he = /* @__PURE__ */ s({
141
+ }), be = /* @__PURE__ */ s({
138
142
  __name: "MilkdownEditor",
139
143
  props: {
140
144
  modelValue: {},
@@ -152,8 +156,8 @@ var J = Symbol("kun-editor-context"), se = [
152
156
  }), t.update(M, (e) => ({
153
157
  ...e,
154
158
  editable: () => !r.readonly
155
- })), c && t.set(s.key, { view: o({ component: me }) });
156
- }).use(te(r.adapters, r.features, { locale: r.locale }));
159
+ })), c && t.set(s.key, { view: o({ component: ye }) });
160
+ }).use(R(r.adapters, r.features, { locale: r.locale }));
157
161
  return c && t.use(s), t;
158
162
  });
159
163
  return v(() => r.modelValue, (e) => {
@@ -177,21 +181,21 @@ var J = Symbol("kun-editor-context"), se = [
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
182
  latex: X("Σ", 15),
179
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\"/>")
180
- }, ge = /* @__PURE__ */ "😀.😃.😄.😁.😆.😅.🤣.😂.🙂.🙃.😉.😊.😇.🥰.😍.🤩.😘.😗.😚.😋.😛.😜.🤪.😝.🤗.🤭.🤔.🤐.😐.😑.😶.😏.😒.🙄.😬.😌.😔.😪.🤤.😴.😷.🤒.🤕.🥵.🥶.🥴.😵.🤯.🤠.🥳.😎.🤓.🧐.😕.😟.🙁.😮.😯.😲.😳.🥺.😦.😧.😨.😰.😥.😢.😭.😱.😖.😣.😞.😓.😩.😫.🥱.😤.😡.😠.🤬.😈.👿.💀.💩.🤡.👻.👽.🤖.😺.😸.👍.👎.👌.🤌.🤏.✌️.🤞.🤟.🤘.👋.🤚.🖐️.✋.👏.🙌.🤝.🙏.💪.👀.👁️.❤️.🧡.💛.💚.💙.💜.🖤.🤍.💔.💕.💞.💓.💗.💖.💘.💝.💯.✨.⭐.🌟.🔥.💥.💫.⚡.☀️.🌈.🎉.🎊.🎁.🏆.🐶.🐱.🐭.🦊.🐻.🐼.🐨.🦄.🐢.🐳.🍎.🍑.🍓.🍉.🍰.🍺.🍵.☕.🍜.🍙.✅.❌.❓.❗.💤.👑.🎮.🎵.📌.🔖".split("."), _e = [
184
+ }, xe = /* @__PURE__ */ "😀.😃.😄.😁.😆.😅.🤣.😂.🙂.🙃.😉.😊.😇.🥰.😍.🤩.😘.😗.😚.😋.😛.😜.🤪.😝.🤗.🤭.🤔.🤐.😐.😑.😶.😏.😒.🙄.😬.😌.😔.😪.🤤.😴.😷.🤒.🤕.🥵.🥶.🥴.😵.🤯.🤠.🥳.😎.🤓.🧐.😕.😟.🙁.😮.😯.😲.😳.🥺.😦.😧.😨.😰.😥.😢.😭.😱.😖.😣.😞.😓.😩.😫.🥱.😤.😡.😠.🤬.😈.👿.💀.💩.🤡.👻.👽.🤖.😺.😸.👍.👎.👌.🤌.🤏.✌️.🤞.🤟.🤘.👋.🤚.🖐️.✋.👏.🙌.🤝.🙏.💪.👀.👁️.❤️.🧡.💛.💚.💙.💜.🖤.🤍.💔.💕.💞.💓.💗.💖.💘.💝.💯.✨.⭐.🌟.🔥.💥.💫.⚡.☀️.🌈.🎉.🎊.🎁.🏆.🐶.🐱.🐭.🦊.🐻.🐼.🐨.🦄.🐢.🐳.🍎.🍑.🍓.🍉.🍰.🍺.🍵.☕.🍜.🍙.✅.❌.❓.❗.💤.👑.🎮.🎵.📌.🔖".split("."), Se = [
181
185
  "title",
182
186
  "aria-label",
183
187
  "aria-expanded"
184
- ], ve = ["innerHTML"], Q = { class: "kun-editor__picker-panel" }, ye = {
188
+ ], Ce = ["innerHTML"], we = { class: "kun-editor__picker-panel" }, Te = {
185
189
  key: 0,
186
190
  class: "kun-editor__picker-tabs",
187
191
  role: "tablist"
188
- }, be = ["data-active"], xe = ["data-active"], Se = { class: "kun-editor__emoji-grid" }, Ce = ["onClick"], we = {
192
+ }, Ee = ["data-active"], De = ["data-active"], Oe = { class: "kun-editor__emoji-grid" }, ke = ["onClick"], Ae = {
189
193
  key: 1,
190
194
  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 = {
195
+ }, je = { class: "kun-editor__pack-name" }, Me = { class: "kun-editor__sticker-grid" }, Ne = ["title", "onClick"], Pe = ["src", "alt"], Fe = {
192
196
  key: 1,
193
197
  class: "kun-editor__picker-hint"
194
- }, Ae = /* @__PURE__ */ s({
198
+ }, Ie = /* @__PURE__ */ s({
195
199
  __name: "StickerPicker",
196
200
  setup(n) {
197
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 ? {
@@ -247,28 +251,28 @@ var J = Symbol("kun-editor-context"), se = [
247
251
  }, [a("span", {
248
252
  class: "kun-editor__icon",
249
253
  innerHTML: g(Z).smile
250
- }, null, 8, ve)], 8, _e), b(a("div", Q, [
251
- v ? (d(), i("div", ye, [a("button", {
254
+ }, null, 8, Ce)], 8, Se), b(a("div", we, [
255
+ v ? (d(), i("div", Te, [a("button", {
252
256
  type: "button",
253
257
  class: "kun-editor__picker-tab",
254
258
  "data-active": w.value === "emoji",
255
259
  onClick: n[0] ||= (e) => w.value = "emoji"
256
- }, h(x.value.emoji), 9, be), a("button", {
260
+ }, h(x.value.emoji), 9, Ee), a("button", {
257
261
  type: "button",
258
262
  class: "kun-editor__picker-tab",
259
263
  "data-active": w.value === "sticker",
260
264
  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", {
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", {
263
267
  key: t,
264
268
  type: "button",
265
269
  class: "kun-editor__emoji",
266
270
  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", {
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", {
269
273
  key: t.name,
270
274
  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", {
275
+ }, [a("div", je, h(t.name), 1), a("div", Me, [(d(!0), i(e, null, m(t.stickers, (e, t) => (d(), i("button", {
272
276
  key: t,
273
277
  type: "button",
274
278
  class: "kun-editor__sticker",
@@ -278,21 +282,21 @@ var J = Symbol("kun-editor-context"), se = [
278
282
  src: e.src,
279
283
  alt: e.name,
280
284
  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)
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)
282
286
  ], 512), [[_, S.value]])], 512));
283
287
  }
284
- }), je = {
288
+ }), Le = {
285
289
  class: "kun-editor__format-toolbar",
286
290
  role: "toolbar"
287
- }, Me = {
291
+ }, Re = {
288
292
  key: 0,
289
293
  class: "kun-editor__toolbar-divider",
290
294
  "aria-hidden": "true"
291
- }, Ne = [
295
+ }, ze = [
292
296
  "title",
293
297
  "aria-label",
294
298
  "onClick"
295
- ], Pe = ["innerHTML"], Fe = ["title", "aria-label"], Ie = ["innerHTML"], Le = /* @__PURE__ */ s({
299
+ ], Be = ["innerHTML"], Ve = ["title", "aria-label"], He = ["innerHTML"], Q = /* @__PURE__ */ s({
296
300
  __name: "EditorToolbar",
297
301
  setup(n) {
298
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) => {
@@ -331,7 +335,7 @@ var J = Symbol("kun-editor-context"), se = [
331
335
  {
332
336
  svg: Z.strike,
333
337
  title: y.value.strike,
334
- run: () => v(q.key)
338
+ run: () => v(ce.key)
335
339
  },
336
340
  {
337
341
  svg: Z.code,
@@ -375,22 +379,22 @@ var J = Symbol("kun-editor-context"), se = [
375
379
  {
376
380
  svg: Z.codeBlock,
377
381
  title: y.value.codeBlock,
378
- run: () => v(ae.key, "")
382
+ run: () => v(oe.key, "")
379
383
  },
380
384
  {
381
385
  svg: Z.hr,
382
386
  title: y.value.hr,
383
- run: () => v(oe.key)
387
+ run: () => v(se.key)
384
388
  }
385
389
  ],
386
390
  [{
387
391
  svg: Z.spoiler,
388
392
  title: y.value.spoiler,
389
- run: () => v(R.key)
393
+ run: () => v(te.key)
390
394
  }, {
391
395
  svg: Z.latex,
392
396
  title: y.value.latex,
393
- run: () => v(re.key)
397
+ run: () => v(ie.key)
394
398
  }]
395
399
  ]), x = p(null), S = () => x.value?.click(), C = async (e) => {
396
400
  let t = e.target, n = t.files?.[0];
@@ -407,8 +411,8 @@ var J = Symbol("kun-editor-context"), se = [
407
411
  f()?.(_.value ? "Image upload failed" : "图片上传失败", "error");
408
412
  }
409
413
  };
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", {
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", {
412
416
  key: t,
413
417
  type: "button",
414
418
  class: "kun-editor__tool",
@@ -418,7 +422,7 @@ var J = Symbol("kun-editor-context"), se = [
418
422
  }, [a("span", {
419
423
  class: "kun-editor__icon",
420
424
  innerHTML: e.svg
421
- }, null, 8, Pe)], 8, Ne))), 128))], 64))), 128)),
425
+ }, null, 8, Be)], 8, ze))), 128))], 64))), 128)),
422
426
  u.value ? (d(), i(e, { key: 0 }, [
423
427
  n[0] ||= a("span", {
424
428
  class: "kun-editor__toolbar-divider",
@@ -433,7 +437,7 @@ var J = Symbol("kun-editor-context"), se = [
433
437
  }, [a("span", {
434
438
  class: "kun-editor__icon",
435
439
  innerHTML: g(Z).image
436
- }, null, 8, Ie)], 8, Fe),
440
+ }, null, 8, He)], 8, Ve),
437
441
  a("input", {
438
442
  ref_key: "fileInput",
439
443
  ref: x,
@@ -446,20 +450,52 @@ var J = Symbol("kun-editor-context"), se = [
446
450
  h.value ? (d(), i(e, { key: 1 }, [n[1] ||= a("span", {
447
451
  class: "kun-editor__toolbar-divider",
448
452
  "aria-hidden": "true"
449
- }, null, -1), o(Ae)], 64)) : r("", !0)
453
+ }, null, -1), o(Ie)], 64)) : r("", !0)
450
454
  ]));
451
455
  }
452
- }), Re = {
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));
491
+ }
492
+ }), We = {
453
493
  class: "kun-editor",
454
494
  "data-kun-editor": ""
455
- }, ze = {
495
+ }, Ge = {
456
496
  class: "kun-editor__toolbar",
457
497
  role: "tablist"
458
- }, Be = ["aria-selected", "data-active"], Ve = ["aria-selected", "data-active"], He = { class: "kun-editor__wysiwyg" }, Ue = [
459
- "value",
460
- "readonly",
461
- "lang"
462
- ], $ = /* @__PURE__ */ s({
498
+ }, Ke = ["aria-selected", "data-active"], qe = ["aria-selected", "data-active"], Je = { class: "kun-editor__wysiwyg" }, $ = /* @__PURE__ */ s({
463
499
  __name: "KunEditor",
464
500
  props: {
465
501
  modelValue: {},
@@ -472,72 +508,70 @@ var J = Symbol("kun-editor-context"), se = [
472
508
  }
473
509
  },
474
510
  emits: ["update:modelValue"],
475
- setup(e, { emit: n }) {
476
- let r = e, s = n;
511
+ setup(e, { emit: s }) {
512
+ let c = e, l = s;
477
513
  f(J, {
478
514
  get adapters() {
479
- return r.adapters;
515
+ return c.adapters;
480
516
  },
481
517
  get features() {
482
- return r.features;
518
+ return c.features;
483
519
  },
484
520
  get locale() {
485
- return r.locale;
521
+ return c.locale;
486
522
  }
487
523
  });
488
- 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 ? {
489
525
  wysiwyg: "Preview",
490
526
  source: "Markdown"
491
527
  } : {
492
528
  wysiwyg: "预览",
493
529
  source: "Markdown"
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", {
530
+ }), x = (e) => l("update:modelValue", e);
531
+ return (t, s) => (d(), i("div", We, [
532
+ a("div", Ge, [a("button", {
497
533
  type: "button",
498
534
  class: "kun-editor__tab",
499
- "aria-selected": c.value === "wysiwyg",
500
- "data-active": c.value === "wysiwyg",
501
- onClick: n[0] ||= (e) => c.value = "wysiwyg"
502
- }, h(u.value.wysiwyg), 9, Be), 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", {
503
539
  type: "button",
504
540
  class: "kun-editor__tab",
505
- "aria-selected": c.value === "source",
506
- "data-active": c.value === "source",
507
- onClick: n[1] ||= (e) => c.value = "source"
508
- }, h(u.value.source), 9, Ve)]),
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)]),
509
545
  o(g(C), null, {
510
546
  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, {
547
+ default: y(() => [b(o(Q, null, null, 512), [[_, u.value === "wysiwyg" && !e.readonly]]), b(a("div", Je, [o(be, {
512
548
  "model-value": e.modelValue,
513
549
  adapters: e.adapters,
514
550
  features: e.features,
515
551
  locale: e.locale,
516
552
  readonly: e.readonly,
517
- "onUpdate:modelValue": m
553
+ "onUpdate:modelValue": x
518
554
  }, null, 8, [
519
555
  "model-value",
520
556
  "adapters",
521
557
  "features",
522
558
  "locale",
523
559
  "readonly"
524
- ])], 512), [[_, c.value === "wysiwyg"]])]),
560
+ ])], 512), [[_, u.value === "wysiwyg"]])]),
525
561
  _: 1
526
562
  })]),
527
563
  _: 1
528
564
  }),
529
- b(a("textarea", {
530
- class: "kun-editor__source",
531
- value: e.modelValue,
565
+ u.value === "source" ? (d(), n(Ue, {
566
+ key: 0,
567
+ "model-value": e.modelValue,
532
568
  readonly: e.readonly,
533
- lang: e.locale,
534
- spellcheck: "false",
535
- onInput: v
536
- }, null, 40, Ue), [[_, c.value === "source"]])
569
+ "onUpdate:modelValue": x
570
+ }, null, 8, ["model-value", "readonly"])) : r("", !0)
537
571
  ]));
538
572
  }
539
- }), We = { install(e) {
573
+ }), Ye = { install(e) {
540
574
  e.component("KunEditor", $);
541
575
  } };
542
576
  //#endregion
543
- export { $ as KunEditor, We as KunEditorPlugin };
577
+ export { $ as KunEditor, Ye as KunEditorPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungal/editor-vue",
3
- "version": "0.6.0",
3
+ "version": "0.8.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": [
@@ -24,10 +24,7 @@
24
24
  "publishConfig": {
25
25
  "access": "public"
26
26
  },
27
- "sideEffects": [
28
- "*.css",
29
- "*.vue"
30
- ],
27
+ "sideEffects": false,
31
28
  "files": [
32
29
  "CHANGELOG.md",
33
30
  "dist"
@@ -39,31 +36,51 @@
39
36
  ".": {
40
37
  "types": "./dist/index.d.ts",
41
38
  "import": "./dist/index.js"
42
- },
43
- "./style.css": "./dist/style.css"
39
+ }
44
40
  },
45
41
  "dependencies": {
46
42
  "@prosemirror-adapter/vue": "^0.4.6",
47
- "@kungal/editor-core": "0.6.0"
43
+ "@kungal/editor-core": "0.8.0"
48
44
  },
49
45
  "peerDependencies": {
50
- "@kungal/ui-vue": "^2.7.0",
46
+ "@codemirror/lang-markdown": "^6.0.0",
47
+ "@codemirror/state": "^6.0.0",
48
+ "@codemirror/view": "^6.0.0",
51
49
  "@milkdown/kit": "^7.21.2",
52
50
  "@milkdown/prose": "^7.21.2",
53
51
  "@milkdown/vue": "^7.21.2",
52
+ "codemirror": "^6.0.0",
54
53
  "vue": "^3.5.0"
55
54
  },
55
+ "peerDependenciesMeta": {
56
+ "@codemirror/lang-markdown": {
57
+ "optional": true
58
+ },
59
+ "@codemirror/state": {
60
+ "optional": true
61
+ },
62
+ "@codemirror/view": {
63
+ "optional": true
64
+ },
65
+ "codemirror": {
66
+ "optional": true
67
+ }
68
+ },
56
69
  "devDependencies": {
70
+ "@codemirror/lang-markdown": "^6.5.0",
71
+ "@codemirror/state": "^6.5.2",
72
+ "@codemirror/view": "^6.39.4",
57
73
  "@milkdown/kit": "^7.21.2",
58
74
  "@milkdown/prose": "^7.21.2",
59
75
  "@milkdown/vue": "7.21.2",
60
76
  "@types/node": "^22.10.0",
61
77
  "@vitejs/plugin-vue": "^6.0.7",
78
+ "codemirror": "^6.0.2",
62
79
  "typescript": "^5.7.0",
63
80
  "vite": "^8.0.16",
64
81
  "vue": "^3.5.35",
65
82
  "vue-tsc": "^3.3.3",
66
- "@kungal/editor-core": "0.6.0"
83
+ "@kungal/editor-core": "0.8.0"
67
84
  },
68
85
  "scripts": {
69
86
  "build": "vite build && vue-tsc -p tsconfig.build.json",
package/dist/style.css DELETED
@@ -1,2 +0,0 @@
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
- /*$vite$:1*/