@hywax/cms 0.0.5 → 0.0.6
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/.nuxt/cms/editor/callout.ts +21 -0
- package/.nuxt/cms/editor/index.ts +2 -0
- package/.nuxt/cms/editor/uplora-image.ts +5 -0
- package/cli/templates.mjs +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +60 -8
- package/dist/runtime/components/ButtonDelete.vue +12 -5
- package/dist/runtime/components/ButtonDelete.vue.d.ts +8 -2
- package/dist/runtime/components/InputSlug.vue +6 -2
- package/dist/runtime/components/InputSlug.vue.d.ts +3 -1
- package/dist/runtime/components/ModalConfirm.vue +12 -7
- package/dist/runtime/components/ModalConfirm.vue.d.ts +8 -2
- package/dist/runtime/components/TablePanel.vue +1 -1
- package/dist/runtime/composables/useAdmin.d.ts +6 -0
- package/dist/runtime/composables/useAdmin.js +14 -0
- package/dist/runtime/composables/useDeleteConfirm.js +1 -3
- package/dist/runtime/editor/extensions/callout/CalloutView.vue +79 -0
- package/dist/runtime/editor/extensions/callout/CalloutView.vue.d.ts +7 -0
- package/dist/runtime/editor/extensions/callout/extension.d.ts +13 -0
- package/dist/runtime/editor/extensions/callout/extension.js +48 -0
- package/dist/runtime/editor/extensions/callout/index.d.ts +2 -0
- package/dist/runtime/editor/extensions/callout/index.js +2 -0
- package/dist/runtime/editor/extensions/callout/types.d.ts +3 -0
- package/dist/runtime/editor/extensions/callout/types.js +0 -0
- package/dist/runtime/editor/extensions/index.d.ts +26 -0
- package/dist/runtime/editor/extensions/index.js +85 -0
- package/dist/runtime/editor/extensions/uplora-image/UploraImageView.vue +26 -0
- package/dist/runtime/editor/extensions/uplora-image/UploraImageView.vue.d.ts +7 -0
- package/dist/runtime/editor/extensions/uplora-image/extension.d.ts +13 -0
- package/dist/runtime/editor/extensions/uplora-image/extension.js +60 -0
- package/dist/runtime/editor/extensions/uplora-image/index.d.ts +2 -0
- package/dist/runtime/editor/extensions/uplora-image/index.js +2 -0
- package/dist/runtime/editor/extensions/uplora-image/types.d.ts +5 -0
- package/dist/runtime/editor/extensions/uplora-image/types.js +0 -0
- package/dist/runtime/server/api/uplora/[id].delete.d.ts +2 -0
- package/dist/runtime/server/api/uplora/[id].delete.js +4 -0
- package/dist/runtime/server/api/uplora/index.post.d.ts +2 -0
- package/dist/runtime/server/api/uplora/index.post.js +4 -0
- package/dist/runtime/types/tv.d.ts +9 -3
- package/package.json +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"slots": {
|
|
3
|
+
"root": "px-4 py-3 text-sm/6 rounded-md border flex gap-2"
|
|
4
|
+
},
|
|
5
|
+
"variants": {
|
|
6
|
+
"type": {
|
|
7
|
+
"caution": {
|
|
8
|
+
"root": "border border-error/25 bg-error/10 text-error-600 dark:text-error-300"
|
|
9
|
+
},
|
|
10
|
+
"note": {
|
|
11
|
+
"root": "border border-info/25 bg-info/10 text-info-600 dark:text-info-300"
|
|
12
|
+
},
|
|
13
|
+
"warning": {
|
|
14
|
+
"root": "border border-warning/25 bg-warning/10 text-warning-600 dark:text-warning-300"
|
|
15
|
+
},
|
|
16
|
+
"tip": {
|
|
17
|
+
"root": "border border-success/25 bg-success/10 text-success-600 dark:text-success-300"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/cli/templates.mjs
CHANGED
|
@@ -66,7 +66,7 @@ import { describe, expect, it } from 'vitest'
|
|
|
66
66
|
import ${upperName} from '../../../src/runtime/components/${upperName}.vue'
|
|
67
67
|
import ComponentRender from '../../component-render'
|
|
68
68
|
|
|
69
|
-
describe('${upperName}', () => {
|
|
69
|
+
describe('${upperName}.vue', () => {
|
|
70
70
|
it.each([
|
|
71
71
|
// Props
|
|
72
72
|
['базовый компонент', { props: {} }],
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { createResolver, addComponentsDir, addImportsDir, addPlugin, addImports, addServerImports, addServerImportsDir, addTypeTemplate, addTemplate, addServerTemplate, defineNuxtModule, hasNuxtModule, installModule } from '@nuxt/kit';
|
|
1
|
+
import { createResolver, addComponentsDir, addImportsDir, addPlugin, addImports, addServerImports, addServerImportsDir, addServerHandler, addTypeTemplate, addTemplate, addServerTemplate, defineNuxtModule, hasNuxtModule, installModule } from '@nuxt/kit';
|
|
2
2
|
import { defu } from 'defu';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname } from 'pathe';
|
|
5
5
|
import { snakeCase, kebabCase } from 'scule';
|
|
6
6
|
|
|
7
7
|
const name = "@hywax/cms";
|
|
8
|
-
const version = "0.0.
|
|
8
|
+
const version = "0.0.6";
|
|
9
9
|
|
|
10
10
|
function createContext(options, nuxt) {
|
|
11
11
|
const { resolve } = createResolver(import.meta.url);
|
|
@@ -20,9 +20,7 @@ function createContext(options, nuxt) {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
23
|
+
const defaultCMSConfig = {};
|
|
26
24
|
const defaultModuleOptions = {
|
|
27
25
|
name: "cms",
|
|
28
26
|
prefix: "C",
|
|
@@ -54,7 +52,7 @@ function prepareAutoImports({ resolve, options, nuxt }) {
|
|
|
54
52
|
path: resolve("./runtime/components"),
|
|
55
53
|
pathPrefix: false,
|
|
56
54
|
prefix: options?.prefix,
|
|
57
|
-
ignore: ["prose/**"]
|
|
55
|
+
ignore: ["prose/**", "editor/**"]
|
|
58
56
|
});
|
|
59
57
|
addComponentsDir({
|
|
60
58
|
path: resolve("./runtime/components/prose"),
|
|
@@ -79,6 +77,19 @@ function prepareAutoImports({ resolve, options, nuxt }) {
|
|
|
79
77
|
nuxt.options.nitro.alias["#cms/http-codes"] = httpCodesPath;
|
|
80
78
|
}
|
|
81
79
|
|
|
80
|
+
function prepareServerRoutes({ resolve }) {
|
|
81
|
+
addServerHandler({
|
|
82
|
+
route: "/api/_uplora",
|
|
83
|
+
method: "post",
|
|
84
|
+
handler: resolve("./runtime/server/api/uplora/index.post.ts")
|
|
85
|
+
});
|
|
86
|
+
addServerHandler({
|
|
87
|
+
route: "/api/_uplora/:id",
|
|
88
|
+
method: "delete",
|
|
89
|
+
handler: resolve("./runtime/server/api/uplora/[id].delete.ts")
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
82
93
|
const autocompleteSelect = {
|
|
83
94
|
slots: {
|
|
84
95
|
root: ""
|
|
@@ -205,7 +216,7 @@ const tablePanelFilters = {
|
|
|
205
216
|
}
|
|
206
217
|
};
|
|
207
218
|
|
|
208
|
-
const uploraImage$
|
|
219
|
+
const uploraImage$2 = {
|
|
209
220
|
slots: {
|
|
210
221
|
root: "relative grid grid-cols-[100%] grid-rows-[100%] overflow-hidden",
|
|
211
222
|
lqip: "bg-cover bg-no-repeat bg-center col-[1] row-[1]",
|
|
@@ -233,6 +244,40 @@ const theme = {
|
|
|
233
244
|
tablePanelColumnSorting: tablePanelColumnSorting,
|
|
234
245
|
tablePanelColumnVisibility: tablePanelColumnVisibility,
|
|
235
246
|
tablePanelFilters: tablePanelFilters,
|
|
247
|
+
uploraImage: uploraImage$2
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const callout = {
|
|
251
|
+
slots: {
|
|
252
|
+
root: "px-4 py-3 text-sm/6 rounded-md border flex gap-2"
|
|
253
|
+
},
|
|
254
|
+
variants: {
|
|
255
|
+
type: {
|
|
256
|
+
caution: {
|
|
257
|
+
root: "border border-error/25 bg-error/10 text-error-600 dark:text-error-300"
|
|
258
|
+
},
|
|
259
|
+
note: {
|
|
260
|
+
root: "border border-info/25 bg-info/10 text-info-600 dark:text-info-300"
|
|
261
|
+
},
|
|
262
|
+
warning: {
|
|
263
|
+
root: "border border-warning/25 bg-warning/10 text-warning-600 dark:text-warning-300"
|
|
264
|
+
},
|
|
265
|
+
tip: {
|
|
266
|
+
root: "border border-success/25 bg-success/10 text-success-600 dark:text-success-300"
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const uploraImage$1 = {
|
|
273
|
+
slots: {
|
|
274
|
+
root: "rounded-md overflow-hidden"
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const themeEditor = {
|
|
279
|
+
__proto__: null,
|
|
280
|
+
callout: callout,
|
|
236
281
|
uploraImage: uploraImage$1
|
|
237
282
|
};
|
|
238
283
|
|
|
@@ -284,12 +329,18 @@ function getAppTemplates({ options }) {
|
|
|
284
329
|
}
|
|
285
330
|
}
|
|
286
331
|
writeThemeTemplate(themeProse, "prose");
|
|
332
|
+
writeThemeTemplate(themeEditor, "editor");
|
|
287
333
|
writeThemeTemplate(theme);
|
|
288
334
|
templates.push({
|
|
289
335
|
filename: `cms/prose/index.ts`,
|
|
290
336
|
write: true,
|
|
291
337
|
getContents: () => Object.keys(themeProse).map((component) => `export { default as ${component} } from './${kebabCase(component)}'`).join("\n")
|
|
292
338
|
});
|
|
339
|
+
templates.push({
|
|
340
|
+
filename: `cms/editor/index.ts`,
|
|
341
|
+
write: true,
|
|
342
|
+
getContents: () => Object.keys(themeEditor).map((component) => `export { default as ${component} } from './${kebabCase(component)}'`).join("\n")
|
|
343
|
+
});
|
|
293
344
|
templates.push({
|
|
294
345
|
filename: "cms.css",
|
|
295
346
|
write: true,
|
|
@@ -415,9 +466,10 @@ const module = defineNuxtModule({
|
|
|
415
466
|
await installModule("nuxt-auth-utils");
|
|
416
467
|
}
|
|
417
468
|
nuxt.options.alias["#cms"] = context.resolve("./runtime");
|
|
418
|
-
nuxt.options.appConfig.cms = defu(nuxt.options.appConfig.cms || {},
|
|
469
|
+
nuxt.options.appConfig.cms = defu(nuxt.options.appConfig.cms || {}, defaultCMSConfig);
|
|
419
470
|
prepareAutoImports(context);
|
|
420
471
|
prepareTemplates(context);
|
|
472
|
+
prepareServerRoutes(context);
|
|
421
473
|
}
|
|
422
474
|
});
|
|
423
475
|
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
disable-closing-trigger
|
|
8
8
|
>
|
|
9
9
|
<UButton
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
:color="color"
|
|
11
|
+
:variant="variant"
|
|
12
|
+
:size="size"
|
|
13
13
|
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
14
|
+
auto-loading
|
|
14
15
|
@click="handleDeleteClick()"
|
|
15
16
|
/>
|
|
16
17
|
</UTooltip>
|
|
@@ -26,11 +27,14 @@ import ModalConfirm from "./ModalConfirm.vue";
|
|
|
26
27
|
<script setup>
|
|
27
28
|
const props = defineProps({
|
|
28
29
|
modalProps: { type: Object, required: false },
|
|
29
|
-
buttonProps: { type: Object, required: false },
|
|
30
30
|
confirmText: { type: String, required: false },
|
|
31
|
+
confirmLabel: { type: String, required: false, default: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" },
|
|
31
32
|
title: { type: String, required: false },
|
|
32
33
|
message: { type: String, required: false },
|
|
33
34
|
tooltipText: { type: String, required: false },
|
|
35
|
+
color: { type: null, required: false, default: "error" },
|
|
36
|
+
variant: { type: null, required: false },
|
|
37
|
+
size: { type: null, required: false },
|
|
34
38
|
class: { type: null, required: false },
|
|
35
39
|
ui: { type: null, required: false },
|
|
36
40
|
onConfirm: { type: Function, required: false }
|
|
@@ -43,7 +47,10 @@ function handleDeleteClick() {
|
|
|
43
47
|
...props.modalProps,
|
|
44
48
|
title: props.title ?? "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435",
|
|
45
49
|
message: props.message ?? "\u0412\u044B \u0434\u0435\u0438\u0306\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0445\u043E\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043B\u0438\u0442\u044C?",
|
|
46
|
-
|
|
50
|
+
color: props.color,
|
|
51
|
+
variant: props.variant,
|
|
52
|
+
size: props.size,
|
|
53
|
+
confirmLabel: props.confirmLabel,
|
|
47
54
|
confirmText: props.confirmText,
|
|
48
55
|
onConfirm: props.onConfirm
|
|
49
56
|
});
|
|
@@ -8,11 +8,14 @@ import ModalConfirm from './ModalConfirm.vue';
|
|
|
8
8
|
type ButtonDelete = ComponentConfig<typeof theme, AppConfig, 'buttonDelete'>;
|
|
9
9
|
export interface ButtonDeleteProps extends Pick<ModalConfirmProps, 'onConfirm'> {
|
|
10
10
|
modalProps?: Omit<ModalProps & ComponentProps<typeof ModalConfirm>, 'title' | 'message' | 'onConfirm' | 'confirmButton'>;
|
|
11
|
-
buttonProps?: Omit<ButtonProps, 'color'>;
|
|
12
11
|
confirmText?: string;
|
|
12
|
+
confirmLabel?: string;
|
|
13
13
|
title?: string;
|
|
14
14
|
message?: string;
|
|
15
15
|
tooltipText?: string;
|
|
16
|
+
color?: ButtonProps['color'];
|
|
17
|
+
variant?: ButtonProps['variant'];
|
|
18
|
+
size?: ButtonProps['size'];
|
|
16
19
|
class?: any;
|
|
17
20
|
ui?: ButtonDelete['slots'];
|
|
18
21
|
}
|
|
@@ -24,5 +27,8 @@ declare const _default: import("vue").DefineComponent<ButtonDeleteProps, {}, {},
|
|
|
24
27
|
}, string, import("vue").PublicProps, Readonly<ButtonDeleteProps> & Readonly<{
|
|
25
28
|
onClose?: (() => any) | undefined;
|
|
26
29
|
onConfirm?: (() => any) | undefined;
|
|
27
|
-
}>, {
|
|
30
|
+
}>, {
|
|
31
|
+
color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
|
|
32
|
+
confirmLabel: string;
|
|
33
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
34
|
export default _default;
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
>
|
|
7
7
|
<UInput
|
|
8
8
|
v-model="title"
|
|
9
|
-
|
|
9
|
+
:color="color"
|
|
10
|
+
:variant="variant"
|
|
11
|
+
:size="size"
|
|
10
12
|
class="w-full"
|
|
11
13
|
/>
|
|
12
14
|
</UFormField>
|
|
@@ -51,7 +53,9 @@ const props = defineProps({
|
|
|
51
53
|
label: { type: String, required: false },
|
|
52
54
|
titleKey: { type: String, required: false },
|
|
53
55
|
slugKey: { type: String, required: false },
|
|
54
|
-
|
|
56
|
+
color: { type: null, required: false },
|
|
57
|
+
variant: { type: null, required: false },
|
|
58
|
+
size: { type: null, required: false },
|
|
55
59
|
as: { type: null, required: false },
|
|
56
60
|
class: { type: null, required: false },
|
|
57
61
|
ui: { type: null, required: false }
|
|
@@ -8,7 +8,9 @@ export interface InputSlugProps {
|
|
|
8
8
|
label?: string;
|
|
9
9
|
titleKey?: string;
|
|
10
10
|
slugKey?: string;
|
|
11
|
-
|
|
11
|
+
color?: InputProps['color'];
|
|
12
|
+
variant?: InputProps['variant'];
|
|
13
|
+
size?: InputProps['size'];
|
|
12
14
|
as?: any;
|
|
13
15
|
class?: any;
|
|
14
16
|
ui?: InputSlug['slots'];
|
|
@@ -35,26 +35,28 @@
|
|
|
35
35
|
color="neutral"
|
|
36
36
|
label="Закрыть"
|
|
37
37
|
variant="ghost"
|
|
38
|
-
size="
|
|
38
|
+
:size="size"
|
|
39
39
|
@click="emit('close')"
|
|
40
40
|
/>
|
|
41
41
|
|
|
42
42
|
<UButton
|
|
43
43
|
v-if="confirmText"
|
|
44
44
|
form="confirm-form"
|
|
45
|
-
label="Подтвердить"
|
|
46
45
|
type="submit"
|
|
47
|
-
|
|
46
|
+
:label="confirmLabel"
|
|
48
47
|
:disabled="state.confirmTextValue !== confirmText"
|
|
49
48
|
:loading="form?.loading"
|
|
50
|
-
|
|
49
|
+
:color="color"
|
|
50
|
+
:variant="variant"
|
|
51
|
+
:size="size"
|
|
51
52
|
/>
|
|
52
53
|
<UButton
|
|
53
54
|
v-else
|
|
54
55
|
label="Подтвердить"
|
|
55
|
-
size="lg"
|
|
56
56
|
loading-auto
|
|
57
|
-
|
|
57
|
+
:color="color"
|
|
58
|
+
:variant="variant"
|
|
59
|
+
:size="size"
|
|
58
60
|
@click="handleConfirmClick()"
|
|
59
61
|
/>
|
|
60
62
|
</template>
|
|
@@ -72,7 +74,10 @@ const props = defineProps({
|
|
|
72
74
|
title: { type: String, required: false },
|
|
73
75
|
message: { type: String, required: true },
|
|
74
76
|
confirmText: { type: String, required: false },
|
|
75
|
-
|
|
77
|
+
confirmLabel: { type: String, required: false, default: "\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C" },
|
|
78
|
+
color: { type: null, required: false },
|
|
79
|
+
variant: { type: null, required: false },
|
|
80
|
+
size: { type: null, required: false, default: "lg" },
|
|
76
81
|
onConfirm: { type: Function, required: false },
|
|
77
82
|
class: { type: null, required: false },
|
|
78
83
|
ui: { type: null, required: false }
|
|
@@ -7,7 +7,10 @@ export interface ModalConfirmProps {
|
|
|
7
7
|
title?: string;
|
|
8
8
|
message: string;
|
|
9
9
|
confirmText?: string;
|
|
10
|
-
|
|
10
|
+
confirmLabel?: string;
|
|
11
|
+
color?: ButtonProps['color'];
|
|
12
|
+
variant?: ButtonProps['variant'];
|
|
13
|
+
size?: ButtonProps['size'];
|
|
11
14
|
onConfirm?: () => Promise<any> | any;
|
|
12
15
|
class?: any;
|
|
13
16
|
ui?: ModalConfirm['slots'];
|
|
@@ -22,5 +25,8 @@ declare const _default: import("vue").DefineComponent<ModalConfirmProps, {}, {},
|
|
|
22
25
|
}, string, import("vue").PublicProps, Readonly<ModalConfirmProps> & Readonly<{
|
|
23
26
|
onClose?: (() => any) | undefined;
|
|
24
27
|
onConfirm?: (() => any) | undefined;
|
|
25
|
-
}>, {
|
|
28
|
+
}>, {
|
|
29
|
+
size: "xs" | "sm" | "md" | "lg" | "xl";
|
|
30
|
+
confirmLabel: string;
|
|
31
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
26
32
|
export default _default;
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
</template>
|
|
32
32
|
<template #body>
|
|
33
33
|
<div v-show="loading" :class="ui.loader({ class: props.ui?.loader })">
|
|
34
|
-
<UIcon name="
|
|
34
|
+
<UIcon :name="appConfig.ui.icons.loading" :class="ui.loaderIcon({ class: props.ui?.loaderIcon })" />
|
|
35
35
|
</div>
|
|
36
36
|
|
|
37
37
|
<UTable
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ref, useRoute, watch } from "#imports";
|
|
2
|
+
import { createSharedComposable } from "@vueuse/shared";
|
|
3
|
+
export const useAdmin = createSharedComposable(() => {
|
|
4
|
+
const route = useRoute();
|
|
5
|
+
const isSidebarOpen = ref(false);
|
|
6
|
+
const isSidebarCollapsed = ref(false);
|
|
7
|
+
watch(() => route.path, () => {
|
|
8
|
+
isSidebarOpen.value = false;
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
isSidebarOpen,
|
|
12
|
+
isSidebarCollapsed
|
|
13
|
+
};
|
|
14
|
+
});
|
|
@@ -16,9 +16,7 @@ export function useDeleteConfirm(options) {
|
|
|
16
16
|
modal.open({
|
|
17
17
|
title: options.title || "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
|
|
18
18
|
message: options.message || "\u0412\u044B \u0443\u0432\u0435\u0440\u0435\u043D\u044B, \u0447\u0442\u043E \u0445\u043E\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043B\u0438\u0442\u044C? \u0412\u044B \u043D\u0435 \u0441\u043C\u043E\u0436\u0435\u0442\u0435 \u043E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u044D\u0442\u043E \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435.",
|
|
19
|
-
|
|
20
|
-
color: "error"
|
|
21
|
-
},
|
|
19
|
+
color: "error",
|
|
22
20
|
onConfirm: () => _execute()
|
|
23
21
|
});
|
|
24
22
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="ui.root()">
|
|
3
|
+
<div contenteditable="false" class="shrink-0">
|
|
4
|
+
<UDropdownMenu :items="typeItems">
|
|
5
|
+
<UButton
|
|
6
|
+
:icon="iconTypeMap[type]"
|
|
7
|
+
:color="iconColorMap[type]"
|
|
8
|
+
size="xs"
|
|
9
|
+
variant="soft"
|
|
10
|
+
/>
|
|
11
|
+
</UDropdownMenu>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div :ref="props.contentRef" />
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script>
|
|
19
|
+
import theme from "#build/cms/editor/callout";
|
|
20
|
+
import { computed, ref, useAppConfig } from "#imports";
|
|
21
|
+
import { tv } from "../../../utils/tv";
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script setup>
|
|
25
|
+
const props = defineProps({
|
|
26
|
+
contentRef: { type: [String, Object, Function], required: true },
|
|
27
|
+
view: { type: Object, required: true },
|
|
28
|
+
getPos: { type: Function, required: true },
|
|
29
|
+
setAttrs: { type: Function, required: true },
|
|
30
|
+
node: { type: null, required: true },
|
|
31
|
+
selected: { type: null, required: true },
|
|
32
|
+
decorations: { type: null, required: true },
|
|
33
|
+
innerDecorations: { type: null, required: true }
|
|
34
|
+
});
|
|
35
|
+
const appConfig = useAppConfig();
|
|
36
|
+
const iconColorMap = {
|
|
37
|
+
caution: "error",
|
|
38
|
+
note: "info",
|
|
39
|
+
warning: "warning",
|
|
40
|
+
tip: "success"
|
|
41
|
+
};
|
|
42
|
+
const iconTypeMap = {
|
|
43
|
+
caution: appConfig.ui.icons.caution,
|
|
44
|
+
note: appConfig.ui.icons.info,
|
|
45
|
+
warning: appConfig.ui.icons.warning,
|
|
46
|
+
tip: appConfig.ui.icons.tip
|
|
47
|
+
};
|
|
48
|
+
const type = computed({
|
|
49
|
+
get() {
|
|
50
|
+
return props.node.value.attrs.type;
|
|
51
|
+
},
|
|
52
|
+
set(value) {
|
|
53
|
+
props.setAttrs({ type: value });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const typeItems = ref([
|
|
57
|
+
{
|
|
58
|
+
icon: iconTypeMap.caution,
|
|
59
|
+
color: iconColorMap.caution,
|
|
60
|
+
onSelect: () => type.value = "caution"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
icon: iconTypeMap.note,
|
|
64
|
+
color: iconColorMap.note,
|
|
65
|
+
onSelect: () => type.value = "note"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
icon: iconTypeMap.warning,
|
|
69
|
+
color: iconColorMap.warning,
|
|
70
|
+
onSelect: () => type.value = "warning"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
icon: iconTypeMap.tip,
|
|
74
|
+
color: iconColorMap.tip,
|
|
75
|
+
onSelect: () => type.value = "tip"
|
|
76
|
+
}
|
|
77
|
+
]);
|
|
78
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.editor?.callout || {} })());
|
|
79
|
+
</script>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { VueNodeViewProps } from 'prosekit/vue';
|
|
3
|
+
import type { ComponentConfig } from '../../../types';
|
|
4
|
+
import theme from '#build/cms/editor/callout';
|
|
5
|
+
export type ProseCallout = ComponentConfig<typeof theme, AppConfig, 'callout', 'cms.editor'>;
|
|
6
|
+
declare const _default: import("vue").DefineComponent<VueNodeViewProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<VueNodeViewProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CalloutAttrs } from './types';
|
|
2
|
+
export declare function defineCallout(): import("prosekit/core").Union<readonly [import("prosekit/core").Extension<{
|
|
3
|
+
Nodes: {
|
|
4
|
+
callout: CalloutAttrs;
|
|
5
|
+
};
|
|
6
|
+
}>, import("prosekit/core").Extension<import("prosekit/core").ExtensionTyping<any, any, any>>, import("prosekit/core").Extension<{
|
|
7
|
+
Commands: {
|
|
8
|
+
setCallout: [attrs?: CalloutAttrs | undefined];
|
|
9
|
+
insertCallout: [attrs?: CalloutAttrs | undefined];
|
|
10
|
+
toggleCallout: [attrs?: CalloutAttrs | undefined];
|
|
11
|
+
setCalloutAttrs: [attrs: CalloutAttrs];
|
|
12
|
+
};
|
|
13
|
+
}>]>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { defineCommands, defineNodeSpec, insertNode, setBlockType, setNodeAttrs, toggleWrap, union } from "prosekit/core";
|
|
2
|
+
import { defineVueNodeView } from "prosekit/vue";
|
|
3
|
+
import CalloutView from "./CalloutView.vue";
|
|
4
|
+
function defineCalloutSpec() {
|
|
5
|
+
return defineNodeSpec({
|
|
6
|
+
name: "callout",
|
|
7
|
+
group: "block",
|
|
8
|
+
content: "block+",
|
|
9
|
+
defining: true,
|
|
10
|
+
draggable: true,
|
|
11
|
+
attrs: {
|
|
12
|
+
type: { default: "note" }
|
|
13
|
+
},
|
|
14
|
+
parseDOM: [{ tag: 'div[data-type="callout"]' }],
|
|
15
|
+
toDOM({ attrs }) {
|
|
16
|
+
return ["div", { "data-type": "callout", ...attrs }];
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function defineCalloutView() {
|
|
21
|
+
return defineVueNodeView({
|
|
22
|
+
name: "callout",
|
|
23
|
+
component: CalloutView
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function defineCalloutCommands() {
|
|
27
|
+
return defineCommands({
|
|
28
|
+
setCallout: (attrs) => {
|
|
29
|
+
return setBlockType({ type: "callout", attrs });
|
|
30
|
+
},
|
|
31
|
+
insertCallout: (attrs) => {
|
|
32
|
+
return insertNode({ type: "callout", attrs });
|
|
33
|
+
},
|
|
34
|
+
toggleCallout: (attrs) => {
|
|
35
|
+
return toggleWrap({ type: "callout", attrs });
|
|
36
|
+
},
|
|
37
|
+
setCalloutAttrs: (attrs) => {
|
|
38
|
+
return setNodeAttrs({ type: "callout", attrs });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export function defineCallout() {
|
|
43
|
+
return union([
|
|
44
|
+
defineCalloutSpec(),
|
|
45
|
+
defineCalloutView(),
|
|
46
|
+
defineCalloutCommands()
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type DefineFullExtension = ReturnType<typeof defineFullExtension>;
|
|
2
|
+
export type DefineLightExtension = ReturnType<typeof defineLightExtension>;
|
|
3
|
+
export declare function defineFullExtension(): import("prosekit/core").Union<readonly [import("prosekit/extensions/doc").DocExtension, import("prosekit/extensions/text").TextExtension, import("prosekit/extensions/paragraph").ParagraphExtension, import("prosekit/extensions/heading").HeadingExtension, import("prosekit/extensions/list").ListExtension, import("prosekit/extensions/blockquote").BlockquoteExtension, import("prosekit/extensions/image").ImageExtension, import("prosekit/extensions/horizontal-rule").HorizontalRuleExtension, import("prosekit/extensions/table").TableExtension, import("prosekit/extensions/code-block").CodeBlockExtension, import("prosekit/extensions/italic").ItalicExtension, import("prosekit/extensions/bold").BoldExtension, import("prosekit/extensions/underline").UnderlineExtension, import("prosekit/extensions/strike").StrikeExtension, import("prosekit/extensions/code").CodeExtension, import("prosekit/extensions/link").LinkExtension, import("prosekit/core").PlainExtension, import("prosekit/core").BaseCommandsExtension, import("prosekit/core").HistoryExtension, import("prosekit/core").PlainExtension, import("prosekit/core").PlainExtension, import("prosekit/core").PlainExtension, import("prosekit/core").PlainExtension, import("prosekit/core").PlainExtension, import("prosekit/core").Union<readonly [import("prosekit/core").Extension<{
|
|
4
|
+
Nodes: {
|
|
5
|
+
uploraImage: import("./uplora-image").UploraImageAttrs;
|
|
6
|
+
};
|
|
7
|
+
}>, import("prosekit/core").Extension<import("prosekit/core").ExtensionTyping<any, any, any>>, import("prosekit/core").Extension<{
|
|
8
|
+
Commands: {
|
|
9
|
+
setUploraImage: [attrs?: import("./uplora-image").UploraImageAttrs | undefined];
|
|
10
|
+
insertUploraImage: [attrs?: import("./uplora-image").UploraImageAttrs | undefined];
|
|
11
|
+
toggleUploraImage: [attrs?: import("./uplora-image").UploraImageAttrs | undefined];
|
|
12
|
+
setUploraAttrs: [attrs: import("./uplora-image").UploraImageAttrs];
|
|
13
|
+
};
|
|
14
|
+
}>]>, import("prosekit/core").Union<readonly [import("prosekit/core").Extension<{
|
|
15
|
+
Nodes: {
|
|
16
|
+
callout: import("./callout").CalloutAttrs;
|
|
17
|
+
};
|
|
18
|
+
}>, import("prosekit/core").Extension<import("prosekit/core").ExtensionTyping<any, any, any>>, import("prosekit/core").Extension<{
|
|
19
|
+
Commands: {
|
|
20
|
+
setCallout: [attrs?: import("./callout").CalloutAttrs | undefined];
|
|
21
|
+
insertCallout: [attrs?: import("./callout").CalloutAttrs | undefined];
|
|
22
|
+
toggleCallout: [attrs?: import("./callout").CalloutAttrs | undefined];
|
|
23
|
+
setCalloutAttrs: [attrs: import("./callout").CalloutAttrs];
|
|
24
|
+
};
|
|
25
|
+
}>]>]>;
|
|
26
|
+
export declare function defineLightExtension(): import("prosekit/core").Union<readonly [import("prosekit/extensions/doc").DocExtension, import("prosekit/extensions/text").TextExtension, import("prosekit/extensions/paragraph").ParagraphExtension, import("prosekit/extensions/list").ListExtension, import("prosekit/extensions/blockquote").BlockquoteExtension, import("prosekit/extensions/code-block").CodeBlockExtension, import("prosekit/extensions/italic").ItalicExtension, import("prosekit/extensions/bold").BoldExtension, import("prosekit/extensions/underline").UnderlineExtension, import("prosekit/extensions/strike").StrikeExtension, import("prosekit/extensions/code").CodeExtension, import("prosekit/extensions/link").LinkExtension, import("prosekit/core").PlainExtension, import("prosekit/core").BaseCommandsExtension, import("prosekit/core").HistoryExtension, import("prosekit/core").PlainExtension, import("prosekit/core").PlainExtension]>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { defineBaseCommands, defineBaseKeymap, defineHistory, union } from "prosekit/core";
|
|
2
|
+
import { defineBlockquote } from "prosekit/extensions/blockquote";
|
|
3
|
+
import { defineBold } from "prosekit/extensions/bold";
|
|
4
|
+
import { defineCode } from "prosekit/extensions/code";
|
|
5
|
+
import { defineCodeBlock } from "prosekit/extensions/code-block";
|
|
6
|
+
import { defineDoc } from "prosekit/extensions/doc";
|
|
7
|
+
import { defineDropCursor } from "prosekit/extensions/drop-cursor";
|
|
8
|
+
import { defineGapCursor } from "prosekit/extensions/gap-cursor";
|
|
9
|
+
import { defineHeading } from "prosekit/extensions/heading";
|
|
10
|
+
import { defineHorizontalRule } from "prosekit/extensions/horizontal-rule";
|
|
11
|
+
import { defineImage } from "prosekit/extensions/image";
|
|
12
|
+
import { defineItalic } from "prosekit/extensions/italic";
|
|
13
|
+
import { defineLink } from "prosekit/extensions/link";
|
|
14
|
+
import { defineList } from "prosekit/extensions/list";
|
|
15
|
+
import { defineModClickPrevention } from "prosekit/extensions/mod-click-prevention";
|
|
16
|
+
import { defineParagraph } from "prosekit/extensions/paragraph";
|
|
17
|
+
import { definePlaceholder } from "prosekit/extensions/placeholder";
|
|
18
|
+
import { defineStrike } from "prosekit/extensions/strike";
|
|
19
|
+
import { defineTable } from "prosekit/extensions/table";
|
|
20
|
+
import { defineText } from "prosekit/extensions/text";
|
|
21
|
+
import { defineUnderline } from "prosekit/extensions/underline";
|
|
22
|
+
import { defineVirtualSelection } from "prosekit/extensions/virtual-selection";
|
|
23
|
+
import { defineCallout } from "./callout/index.js";
|
|
24
|
+
import { defineUploraImage } from "./uplora-image/index.js";
|
|
25
|
+
export function defineFullExtension() {
|
|
26
|
+
return union([
|
|
27
|
+
// Nodes
|
|
28
|
+
defineDoc(),
|
|
29
|
+
defineText(),
|
|
30
|
+
defineParagraph(),
|
|
31
|
+
defineHeading(),
|
|
32
|
+
defineList(),
|
|
33
|
+
defineBlockquote(),
|
|
34
|
+
defineImage(),
|
|
35
|
+
defineHorizontalRule(),
|
|
36
|
+
defineTable(),
|
|
37
|
+
defineCodeBlock(),
|
|
38
|
+
// Marks
|
|
39
|
+
defineItalic(),
|
|
40
|
+
defineBold(),
|
|
41
|
+
defineUnderline(),
|
|
42
|
+
defineStrike(),
|
|
43
|
+
defineCode(),
|
|
44
|
+
defineLink(),
|
|
45
|
+
// Others
|
|
46
|
+
defineBaseKeymap(),
|
|
47
|
+
defineBaseCommands(),
|
|
48
|
+
defineHistory(),
|
|
49
|
+
defineDropCursor(),
|
|
50
|
+
defineGapCursor(),
|
|
51
|
+
defineVirtualSelection(),
|
|
52
|
+
defineModClickPrevention(),
|
|
53
|
+
definePlaceholder({
|
|
54
|
+
placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 '/' \u0434\u043B\u044F \u043A\u043E\u043C\u0430\u043D\u0434"
|
|
55
|
+
}),
|
|
56
|
+
defineUploraImage(),
|
|
57
|
+
defineCallout()
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
export function defineLightExtension() {
|
|
61
|
+
return union([
|
|
62
|
+
// Nodes
|
|
63
|
+
defineDoc(),
|
|
64
|
+
defineText(),
|
|
65
|
+
defineParagraph(),
|
|
66
|
+
defineList(),
|
|
67
|
+
defineBlockquote(),
|
|
68
|
+
defineCodeBlock(),
|
|
69
|
+
// Marks
|
|
70
|
+
defineItalic(),
|
|
71
|
+
defineBold(),
|
|
72
|
+
defineUnderline(),
|
|
73
|
+
defineStrike(),
|
|
74
|
+
defineCode(),
|
|
75
|
+
defineLink(),
|
|
76
|
+
// Others
|
|
77
|
+
defineBaseKeymap(),
|
|
78
|
+
defineBaseCommands(),
|
|
79
|
+
defineHistory(),
|
|
80
|
+
defineModClickPrevention(),
|
|
81
|
+
definePlaceholder({
|
|
82
|
+
placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442..."
|
|
83
|
+
})
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="ui.root()">
|
|
3
|
+
...
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
import theme from "#build/cms/editor/uplora-image";
|
|
9
|
+
import { computed, useAppConfig } from "#imports";
|
|
10
|
+
import { tv } from "../../../utils/tv";
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script setup>
|
|
14
|
+
const _props = defineProps({
|
|
15
|
+
contentRef: { type: [String, Object, Function], required: true },
|
|
16
|
+
view: { type: Object, required: true },
|
|
17
|
+
getPos: { type: Function, required: true },
|
|
18
|
+
setAttrs: { type: Function, required: true },
|
|
19
|
+
node: { type: null, required: true },
|
|
20
|
+
selected: { type: null, required: true },
|
|
21
|
+
decorations: { type: null, required: true },
|
|
22
|
+
innerDecorations: { type: null, required: true }
|
|
23
|
+
});
|
|
24
|
+
const appConfig = useAppConfig();
|
|
25
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.editor?.uploraImage || {} })());
|
|
26
|
+
</script>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { VueNodeViewProps } from 'prosekit/vue';
|
|
3
|
+
import type { ComponentConfig } from '../../../types';
|
|
4
|
+
import theme from '#build/cms/editor/uplora-image';
|
|
5
|
+
export type ProseUploraImage = ComponentConfig<typeof theme, AppConfig, 'uploraImage', 'cms.editor'>;
|
|
6
|
+
declare const _default: import("vue").DefineComponent<VueNodeViewProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<VueNodeViewProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { UploraImageAttrs } from './types';
|
|
2
|
+
export declare function defineUploraImage(): import("prosekit/core").Union<readonly [import("prosekit/core").Extension<{
|
|
3
|
+
Nodes: {
|
|
4
|
+
uploraImage: UploraImageAttrs;
|
|
5
|
+
};
|
|
6
|
+
}>, import("prosekit/core").Extension<import("prosekit/core").ExtensionTyping<any, any, any>>, import("prosekit/core").Extension<{
|
|
7
|
+
Commands: {
|
|
8
|
+
setUploraImage: [attrs?: UploraImageAttrs | undefined];
|
|
9
|
+
insertUploraImage: [attrs?: UploraImageAttrs | undefined];
|
|
10
|
+
toggleUploraImage: [attrs?: UploraImageAttrs | undefined];
|
|
11
|
+
setUploraAttrs: [attrs: UploraImageAttrs];
|
|
12
|
+
};
|
|
13
|
+
}>]>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Fragment, Slice } from "@prosekit/pm/model";
|
|
2
|
+
import { defineCommands, defineNodeSpec, getNodeType, insertNode, setNodeAttrs, toggleWrap, union } from "prosekit/core";
|
|
3
|
+
import { defineVueNodeView } from "prosekit/vue";
|
|
4
|
+
import UploraImageView from "./UploraImageView.vue";
|
|
5
|
+
function defineUploraImageSpec() {
|
|
6
|
+
return defineNodeSpec({
|
|
7
|
+
name: "uploraImage",
|
|
8
|
+
group: "block",
|
|
9
|
+
atom: true,
|
|
10
|
+
attrs: {
|
|
11
|
+
image: { default: "" },
|
|
12
|
+
alt: { default: "" },
|
|
13
|
+
lqip: { default: "" }
|
|
14
|
+
},
|
|
15
|
+
parseDOM: [{ tag: 'div[data-type="uplora-image"]' }],
|
|
16
|
+
toDOM({ attrs }) {
|
|
17
|
+
return ["div", { "data-type": "uplora-image", ...attrs }];
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function defineUploraImageView() {
|
|
22
|
+
return defineVueNodeView({
|
|
23
|
+
name: "uploraImage",
|
|
24
|
+
component: UploraImageView
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function defineUploraImageCommands() {
|
|
28
|
+
return defineCommands({
|
|
29
|
+
setUploraImage: (attrs) => {
|
|
30
|
+
return (state, dispatch) => {
|
|
31
|
+
if (!dispatch) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
const { schema, tr } = state;
|
|
35
|
+
const type = getNodeType(schema, "uploraImage");
|
|
36
|
+
const node = type.create(attrs);
|
|
37
|
+
const pos = tr.selection.anchor;
|
|
38
|
+
tr.replaceRange(pos, pos, new Slice(Fragment.from(node), 0, 0));
|
|
39
|
+
dispatch(tr);
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
insertUploraImage: (attrs) => {
|
|
44
|
+
return insertNode({ type: "uploraImage", attrs });
|
|
45
|
+
},
|
|
46
|
+
toggleUploraImage: (attrs) => {
|
|
47
|
+
return toggleWrap({ type: "uploraImage", attrs });
|
|
48
|
+
},
|
|
49
|
+
setUploraAttrs: (attrs) => {
|
|
50
|
+
return setNodeAttrs({ type: "uploraImage", attrs });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export function defineUploraImage() {
|
|
55
|
+
return union([
|
|
56
|
+
defineUploraImageSpec(),
|
|
57
|
+
defineUploraImageView(),
|
|
58
|
+
defineUploraImageCommands()
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
File without changes
|
|
@@ -27,14 +27,20 @@ type ComponentSlots<T extends {
|
|
|
27
27
|
[K in keyof T['slots']]?: ClassValue;
|
|
28
28
|
}>;
|
|
29
29
|
type GetComponentAppConfig<A, U extends string, K extends string> = A extends Record<U, Record<K, any>> ? A[U][K] : object;
|
|
30
|
-
type ComponentAppConfig<T, A extends Record<string, any>, K extends string, U extends string = 'cms' | 'cms.prose'> = A & (U extends 'cms.prose' ? {
|
|
30
|
+
type ComponentAppConfig<T, A extends Record<string, any>, K extends string, U extends string = 'cms' | 'cms.prose' | 'cms.editor'> = A & (U extends 'cms.prose' ? {
|
|
31
31
|
cms?: {
|
|
32
32
|
prose?: {
|
|
33
33
|
[k in K]?: Partial<T>;
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
|
+
} : U extends 'cms.editor' ? {
|
|
37
|
+
cms?: {
|
|
38
|
+
editor?: {
|
|
39
|
+
[k in K]?: Partial<T>;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
36
42
|
} : {
|
|
37
|
-
[key in Exclude<U, 'cms.prose'>]?: {
|
|
43
|
+
[key in Exclude<U, 'cms.prose' | 'cms.editor'>]?: {
|
|
38
44
|
[k in K]?: Partial<T>;
|
|
39
45
|
};
|
|
40
46
|
});
|
|
@@ -45,7 +51,7 @@ type ComponentAppConfig<T, A extends Record<string, any>, K extends string, U ex
|
|
|
45
51
|
* @template K The key identifying the component (e.g., 'badge').
|
|
46
52
|
* @template U The top-level key in AppConfig ('cms' or 'cms.prose').
|
|
47
53
|
*/
|
|
48
|
-
export type ComponentConfig<T extends Record<string, any>, A extends Record<string, any>, K extends string, U extends 'cms' | 'cms.prose' = 'cms'> = {
|
|
54
|
+
export type ComponentConfig<T extends Record<string, any>, A extends Record<string, any>, K extends string, U extends 'cms' | 'cms.prose' | 'cms.editor' = 'cms'> = {
|
|
49
55
|
AppConfig: ComponentAppConfig<T, A, K, U>;
|
|
50
56
|
variants: ComponentVariants<T & GetComponentAppConfig<A, U, K>>;
|
|
51
57
|
slots: ComponentSlots<T>;
|