@kungal/editor-nuxt 0.14.0 → 0.16.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 +53 -0
- package/nuxt.config.ts +6 -6
- package/package.json +4 -3
- package/runtime/KunEditorToolbar.vue +62 -32
- package/tailwind.css +17 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# @kungal/editor-nuxt
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4e160ee: `<KunEditorToolbar>`: the emoji/sticker picker tabs are now a
|
|
8
|
+
`<KunTab variant="underlined" full-width>` instead of two `<KunButton>`s —
|
|
9
|
+
matching `<KunEditorViewSwitch>` and the forum's picker (keyboard nav, sliding
|
|
10
|
+
indicator, a11y). Only shown when a `stickerSource` adapter is present.
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- @kungal/editor-core@0.16.0
|
|
15
|
+
- @kungal/editor-vue@0.16.0
|
|
16
|
+
|
|
17
|
+
## 0.15.0
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- a7273bb: Ship `tailwind.css` so the KunUI toolbar/picker/tabs styles render drop-in.
|
|
22
|
+
|
|
23
|
+
`<KunEditorToolbar>` / `<KunEditorViewSwitch>` use Tailwind utility classes
|
|
24
|
+
(grids, aspect, sizes, dividers, menu items). Tailwind v4 doesn't scan
|
|
25
|
+
`node_modules`, so without registration the sticker/emoji grid collapsed (huge
|
|
26
|
+
stickers). The package now ships `tailwind.css` containing a path-relative
|
|
27
|
+
`@source "./runtime"` — the Tailwind-team-recommended pattern for a
|
|
28
|
+
Tailwind-based library, and pnpm-layout-safe (resolved relative to the file, not
|
|
29
|
+
the app's `node_modules`). Consumers add one line to their Tailwind entry:
|
|
30
|
+
|
|
31
|
+
```css
|
|
32
|
+
@import "@kungal/ui-vue/style.css";
|
|
33
|
+
@import "@kungal/editor-nuxt/tailwind.css";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- a7273bb: Toolbar: headings become one "text size" dropdown; remove the formula button.
|
|
37
|
+
|
|
38
|
+
- **Headings → a single "text size" control** (Paragraph / H1–H6) instead of
|
|
39
|
+
three H1/H2/H3 buttons — the modern standard, and it can set Paragraph (reset),
|
|
40
|
+
which the old toggle buttons couldn't. The headless `EditorToolbar` uses a
|
|
41
|
+
native `<select>` (new `.kun-editor__heading-select` class hook); the KunUI
|
|
42
|
+
`<KunEditorToolbar>` uses a `<KunPopover>` with each level shown at its own size
|
|
43
|
+
(like the forum). Both drive `setHeadingCommand`.
|
|
44
|
+
- **Remove the math/formula button.** With no selection it inserted an empty
|
|
45
|
+
inline-math node (a broken formula box). Math is entered via the existing
|
|
46
|
+
`$…$` / `$$` input rules instead — the ecosystem norm (prosemirror-math). The
|
|
47
|
+
spoiler button stays.
|
|
48
|
+
|
|
49
|
+
### Patch Changes
|
|
50
|
+
|
|
51
|
+
- Updated dependencies [a7273bb]
|
|
52
|
+
- Updated dependencies [a7273bb]
|
|
53
|
+
- @kungal/editor-core@0.15.0
|
|
54
|
+
- @kungal/editor-vue@0.15.0
|
|
55
|
+
|
|
3
56
|
## 0.14.0
|
|
4
57
|
|
|
5
58
|
### Minor Changes
|
package/nuxt.config.ts
CHANGED
|
@@ -64,9 +64,9 @@ export default defineNuxtConfig({
|
|
|
64
64
|
}
|
|
65
65
|
})
|
|
66
66
|
|
|
67
|
-
// NOTE: this layer
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
//
|
|
67
|
+
// NOTE: this layer assumes @kungal/ui-nuxt is already extended (its components
|
|
68
|
+
// render KunUI chrome). For the KunUI toolbar/picker/tabs utility classes to be
|
|
69
|
+
// generated, the consuming app @imports this package's shipped `tailwind.css`
|
|
70
|
+
// (which `@source`s the layer's components, path-relative so it's pnpm-safe) in
|
|
71
|
+
// its Tailwind entry — alongside `@import '@kungal/ui-vue/style.css'`. The
|
|
72
|
+
// headless editor itself is still styled by the app's own stylesheet. See README.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungal/editor-nuxt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "KunEditor Nuxt Layer — wraps @kungal/editor-vue and auto-imports <KunEditor> so an existing Nuxt app keeps its exact DX (no import needed).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -27,11 +27,12 @@
|
|
|
27
27
|
"CHANGELOG.md",
|
|
28
28
|
"app",
|
|
29
29
|
"runtime",
|
|
30
|
+
"tailwind.css",
|
|
30
31
|
"nuxt.config.ts"
|
|
31
32
|
],
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@kungal/editor-
|
|
34
|
-
"@kungal/editor-
|
|
34
|
+
"@kungal/editor-vue": "0.16.0",
|
|
35
|
+
"@kungal/editor-core": "0.16.0"
|
|
35
36
|
},
|
|
36
37
|
"peerDependencies": {
|
|
37
38
|
"@kungal/ui-vue": "^2.7.0",
|
|
@@ -11,8 +11,18 @@
|
|
|
11
11
|
// KunButton / KunIcon / KunTooltip / KunPopover chrome. It drives the editor
|
|
12
12
|
// purely through the slot API props (KunEditorToolbarApi) — no useInstance.
|
|
13
13
|
//
|
|
14
|
-
//
|
|
14
|
+
// Headings are ONE "text size" KunPopover (Paragraph / H1–H6, each shown at its
|
|
15
|
+
// own size — like the forum's header menu), driven by setHeadingCommand (absolute
|
|
16
|
+
// set). There is deliberately NO math button — an empty inline-math atom is a
|
|
17
|
+
// broken node; math is entered via the `$…$` / `$$` input rules.
|
|
18
|
+
//
|
|
19
|
+
// The emoji/sticker picker switches tabs with a <KunTab variant="underlined">
|
|
20
|
+
// (matching <KunEditorViewSwitch> and the forum's picker).
|
|
21
|
+
//
|
|
22
|
+
// KunButton/KunIcon/KunTooltip/KunPopover/KunTab are auto-imported by ui-nuxt in
|
|
15
23
|
// the consuming app; icons use the app's iconify set (e.g. lucide via @nuxt/icon).
|
|
24
|
+
// The container/menu utility classes are generated via @kungal/editor-nuxt's
|
|
25
|
+
// shipped tailwind.css (@source) — the consumer @imports it once.
|
|
16
26
|
import { computed, ref } from 'vue'
|
|
17
27
|
import {
|
|
18
28
|
createCodeBlockCommand,
|
|
@@ -23,13 +33,12 @@ import {
|
|
|
23
33
|
toggleStrongCommand,
|
|
24
34
|
wrapInBlockquoteCommand,
|
|
25
35
|
wrapInBulletListCommand,
|
|
26
|
-
wrapInHeadingCommand,
|
|
27
36
|
wrapInOrderedListCommand
|
|
28
37
|
} from '@milkdown/kit/preset/commonmark'
|
|
29
38
|
import { toggleStrikethroughCommand } from '@milkdown/kit/preset/gfm'
|
|
30
39
|
import {
|
|
31
40
|
insertKunSpoilerCommand,
|
|
32
|
-
|
|
41
|
+
setHeadingCommand
|
|
33
42
|
} from '@kungal/editor-core/preset'
|
|
34
43
|
import { EMOJI } from '@kungal/editor-vue'
|
|
35
44
|
import type { KunEditorToolbarApi, StickerPack } from '@kungal/editor-vue'
|
|
@@ -38,20 +47,17 @@ const props = defineProps<KunEditorToolbarApi>()
|
|
|
38
47
|
|
|
39
48
|
const en = computed(() => props.locale.toLowerCase().startsWith('en'))
|
|
40
49
|
const t = computed(() => ({
|
|
50
|
+
textSize: en.value ? 'Text size' : '文本大小',
|
|
41
51
|
bold: en.value ? 'Bold' : '加粗',
|
|
42
52
|
italic: en.value ? 'Italic' : '斜体',
|
|
43
53
|
strike: en.value ? 'Strikethrough' : '删除线',
|
|
44
54
|
code: en.value ? 'Inline code' : '行内代码',
|
|
45
|
-
h1: en.value ? 'Heading 1' : '一级标题',
|
|
46
|
-
h2: en.value ? 'Heading 2' : '二级标题',
|
|
47
|
-
h3: en.value ? 'Heading 3' : '三级标题',
|
|
48
55
|
bulletList: en.value ? 'Bullet list' : '无序列表',
|
|
49
56
|
orderedList: en.value ? 'Ordered list' : '有序列表',
|
|
50
57
|
quote: en.value ? 'Blockquote' : '引用块',
|
|
51
58
|
codeBlock: en.value ? 'Code block' : '代码块',
|
|
52
59
|
hr: en.value ? 'Divider' : '分隔线',
|
|
53
60
|
spoiler: en.value ? 'Spoiler' : '隐藏文本',
|
|
54
|
-
latex: en.value ? 'Math (LaTeX)' : '公式',
|
|
55
61
|
image: en.value ? 'Upload image' : '上传图片',
|
|
56
62
|
picker: en.value ? 'Emoji & stickers' : '表情与贴纸',
|
|
57
63
|
emoji: en.value ? 'Emoji' : '表情',
|
|
@@ -60,14 +66,27 @@ const t = computed(() => ({
|
|
|
60
66
|
failed: en.value ? 'Failed to load stickers' : '贴纸加载失败'
|
|
61
67
|
}))
|
|
62
68
|
|
|
69
|
+
// Paragraph (level 0) + H1–H6, each rendered at its own size in the menu.
|
|
70
|
+
const headingOptions = computed(() => {
|
|
71
|
+
const labels = en.value
|
|
72
|
+
? ['Paragraph', 'Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6']
|
|
73
|
+
: ['正文', '一级标题', '二级标题', '三级标题', '四级标题', '五级标题', '六级标题']
|
|
74
|
+
const sizes = ['1rem', '1.6rem', '1.4rem', '1.25rem', '1.1rem', '1rem', '0.9rem']
|
|
75
|
+
return labels.map((label, level) => ({ level, label, size: sizes[level] }))
|
|
76
|
+
})
|
|
77
|
+
const headingPopover = ref<{ close: () => void } | null>(null)
|
|
78
|
+
const setHeading = (level: number) => {
|
|
79
|
+
props.run(setHeadingCommand.key, level)
|
|
80
|
+
headingPopover.value?.close()
|
|
81
|
+
}
|
|
82
|
+
|
|
63
83
|
interface Tool {
|
|
64
84
|
icon: string
|
|
65
85
|
title: string
|
|
66
86
|
run: () => void
|
|
67
87
|
}
|
|
68
88
|
|
|
69
|
-
//
|
|
70
|
-
// time via api.run (populated once the editor is created).
|
|
89
|
+
// `.key` is read at click time via props.run (populated once the editor exists).
|
|
71
90
|
const groups = computed<Tool[][]>(() => [
|
|
72
91
|
[
|
|
73
92
|
{ icon: 'lucide:bold', title: t.value.bold, run: () => props.run(toggleStrongCommand.key) },
|
|
@@ -75,11 +94,6 @@ const groups = computed<Tool[][]>(() => [
|
|
|
75
94
|
{ icon: 'lucide:strikethrough', title: t.value.strike, run: () => props.run(toggleStrikethroughCommand.key) },
|
|
76
95
|
{ icon: 'lucide:code', title: t.value.code, run: () => props.run(toggleInlineCodeCommand.key) }
|
|
77
96
|
],
|
|
78
|
-
[
|
|
79
|
-
{ icon: 'lucide:heading-1', title: t.value.h1, run: () => props.run(wrapInHeadingCommand.key, 1) },
|
|
80
|
-
{ icon: 'lucide:heading-2', title: t.value.h2, run: () => props.run(wrapInHeadingCommand.key, 2) },
|
|
81
|
-
{ icon: 'lucide:heading-3', title: t.value.h3, run: () => props.run(wrapInHeadingCommand.key, 3) }
|
|
82
|
-
],
|
|
83
97
|
[
|
|
84
98
|
{ icon: 'lucide:list', title: t.value.bulletList, run: () => props.run(wrapInBulletListCommand.key) },
|
|
85
99
|
{ icon: 'lucide:list-ordered', title: t.value.orderedList, run: () => props.run(wrapInOrderedListCommand.key) },
|
|
@@ -88,8 +102,7 @@ const groups = computed<Tool[][]>(() => [
|
|
|
88
102
|
{ icon: 'lucide:minus', title: t.value.hr, run: () => props.run(insertHrCommand.key) }
|
|
89
103
|
],
|
|
90
104
|
[
|
|
91
|
-
{ icon: 'lucide:eye-off', title: t.value.spoiler, run: () => props.run(insertKunSpoilerCommand.key) }
|
|
92
|
-
{ icon: 'lucide:sigma', title: t.value.latex, run: () => props.run(toggleLatexCommand.key) }
|
|
105
|
+
{ icon: 'lucide:eye-off', title: t.value.spoiler, run: () => props.run(insertKunSpoilerCommand.key) }
|
|
93
106
|
]
|
|
94
107
|
])
|
|
95
108
|
|
|
@@ -116,7 +129,7 @@ const onFileChange = async (e: Event) => {
|
|
|
116
129
|
const showPicker = computed(() => props.features.sticker !== false)
|
|
117
130
|
const stickerSource = computed(() => props.adapters.stickerSource)
|
|
118
131
|
const hasSticker = computed(() => !!stickerSource.value)
|
|
119
|
-
const tab = ref
|
|
132
|
+
const tab = ref('emoji') // 'emoji' | 'sticker' — widened to string for KunTab v-model
|
|
120
133
|
const packs = ref<StickerPack[]>([])
|
|
121
134
|
const loaded = ref(false)
|
|
122
135
|
const loadFailed = ref(false)
|
|
@@ -136,8 +149,27 @@ const insertSticker = (src: string, name: string) =>
|
|
|
136
149
|
|
|
137
150
|
<template>
|
|
138
151
|
<div class="flex flex-wrap items-center gap-0.5">
|
|
152
|
+
<KunPopover ref="headingPopover" position="bottom-start" :opaque="true" inner-class="min-w-40 p-1">
|
|
153
|
+
<template #trigger>
|
|
154
|
+
<KunButton variant="light" size="sm" :aria-label="t.textSize">
|
|
155
|
+
{{ t.textSize }}
|
|
156
|
+
<KunIcon name="lucide:chevron-down" />
|
|
157
|
+
</KunButton>
|
|
158
|
+
</template>
|
|
159
|
+
<button
|
|
160
|
+
v-for="o in headingOptions"
|
|
161
|
+
:key="o.level"
|
|
162
|
+
type="button"
|
|
163
|
+
class="hover:bg-default-100 flex w-full items-center rounded px-3 py-1.5 text-left leading-tight"
|
|
164
|
+
:style="{ fontSize: o.size }"
|
|
165
|
+
@click="setHeading(o.level)"
|
|
166
|
+
>
|
|
167
|
+
{{ o.label }}
|
|
168
|
+
</button>
|
|
169
|
+
</KunPopover>
|
|
170
|
+
|
|
139
171
|
<template v-for="(group, gi) in groups" :key="gi">
|
|
140
|
-
<span
|
|
172
|
+
<span class="bg-default-200 mx-1 h-5 w-px" aria-hidden="true" />
|
|
141
173
|
<KunTooltip v-for="(b, bi) in group" :key="bi" :text="b.title" :delay-show="300">
|
|
142
174
|
<KunButton
|
|
143
175
|
variant="light"
|
|
@@ -188,20 +220,18 @@ const insertSticker = (src: string, name: string) =>
|
|
|
188
220
|
</KunButton>
|
|
189
221
|
</template>
|
|
190
222
|
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
>
|
|
204
|
-
</div>
|
|
223
|
+
<KunTab
|
|
224
|
+
v-if="hasSticker"
|
|
225
|
+
v-model="tab"
|
|
226
|
+
:items="[
|
|
227
|
+
{ value: 'emoji', textValue: t.emoji },
|
|
228
|
+
{ value: 'sticker', textValue: t.sticker }
|
|
229
|
+
]"
|
|
230
|
+
variant="underlined"
|
|
231
|
+
color="primary"
|
|
232
|
+
:full-width="true"
|
|
233
|
+
class="mb-2"
|
|
234
|
+
/>
|
|
205
235
|
|
|
206
236
|
<div
|
|
207
237
|
v-show="!hasSticker || tab === 'emoji'"
|
package/tailwind.css
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @kungal/editor-nuxt — Tailwind source registration.
|
|
3
|
+
*
|
|
4
|
+
* <KunEditorToolbar> / <KunEditorViewSwitch> are built with Tailwind utility
|
|
5
|
+
* classes (grids, aspect, sizes, dividers, menu items…). Tailwind v4 does NOT
|
|
6
|
+
* scan node_modules by default, so without this those classes aren't generated
|
|
7
|
+
* and the toolbar / sticker grid render broken (collapsed cells, huge stickers).
|
|
8
|
+
*
|
|
9
|
+
* `@source` resolves relative to THIS file, so it registers the layer's own
|
|
10
|
+
* components regardless of the consumer's node_modules layout (pnpm-safe). Import
|
|
11
|
+
* it ONCE in your Tailwind entry, next to `@import '@kungal/ui-vue/style.css'`:
|
|
12
|
+
*
|
|
13
|
+
* @import 'tailwindcss';
|
|
14
|
+
* @import '@kungal/ui-vue/style.css';
|
|
15
|
+
* @import '@kungal/editor-nuxt/tailwind.css';
|
|
16
|
+
*/
|
|
17
|
+
@source "./runtime";
|