@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.
Files changed (40) hide show
  1. package/.nuxt/cms/editor/callout.ts +21 -0
  2. package/.nuxt/cms/editor/index.ts +2 -0
  3. package/.nuxt/cms/editor/uplora-image.ts +5 -0
  4. package/cli/templates.mjs +1 -1
  5. package/dist/module.json +1 -1
  6. package/dist/module.mjs +60 -8
  7. package/dist/runtime/components/ButtonDelete.vue +12 -5
  8. package/dist/runtime/components/ButtonDelete.vue.d.ts +8 -2
  9. package/dist/runtime/components/InputSlug.vue +6 -2
  10. package/dist/runtime/components/InputSlug.vue.d.ts +3 -1
  11. package/dist/runtime/components/ModalConfirm.vue +12 -7
  12. package/dist/runtime/components/ModalConfirm.vue.d.ts +8 -2
  13. package/dist/runtime/components/TablePanel.vue +1 -1
  14. package/dist/runtime/composables/useAdmin.d.ts +6 -0
  15. package/dist/runtime/composables/useAdmin.js +14 -0
  16. package/dist/runtime/composables/useDeleteConfirm.js +1 -3
  17. package/dist/runtime/editor/extensions/callout/CalloutView.vue +79 -0
  18. package/dist/runtime/editor/extensions/callout/CalloutView.vue.d.ts +7 -0
  19. package/dist/runtime/editor/extensions/callout/extension.d.ts +13 -0
  20. package/dist/runtime/editor/extensions/callout/extension.js +48 -0
  21. package/dist/runtime/editor/extensions/callout/index.d.ts +2 -0
  22. package/dist/runtime/editor/extensions/callout/index.js +2 -0
  23. package/dist/runtime/editor/extensions/callout/types.d.ts +3 -0
  24. package/dist/runtime/editor/extensions/callout/types.js +0 -0
  25. package/dist/runtime/editor/extensions/index.d.ts +26 -0
  26. package/dist/runtime/editor/extensions/index.js +85 -0
  27. package/dist/runtime/editor/extensions/uplora-image/UploraImageView.vue +26 -0
  28. package/dist/runtime/editor/extensions/uplora-image/UploraImageView.vue.d.ts +7 -0
  29. package/dist/runtime/editor/extensions/uplora-image/extension.d.ts +13 -0
  30. package/dist/runtime/editor/extensions/uplora-image/extension.js +60 -0
  31. package/dist/runtime/editor/extensions/uplora-image/index.d.ts +2 -0
  32. package/dist/runtime/editor/extensions/uplora-image/index.js +2 -0
  33. package/dist/runtime/editor/extensions/uplora-image/types.d.ts +5 -0
  34. package/dist/runtime/editor/extensions/uplora-image/types.js +0 -0
  35. package/dist/runtime/server/api/uplora/[id].delete.d.ts +2 -0
  36. package/dist/runtime/server/api/uplora/[id].delete.js +4 -0
  37. package/dist/runtime/server/api/uplora/index.post.d.ts +2 -0
  38. package/dist/runtime/server/api/uplora/index.post.js +4 -0
  39. package/dist/runtime/types/tv.d.ts +9 -3
  40. 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
+ }
@@ -0,0 +1,2 @@
1
+ export { default as callout } from './callout'
2
+ export { default as uploraImage } from './uplora-image'
@@ -0,0 +1,5 @@
1
+ export default {
2
+ "slots": {
3
+ "root": "rounded-md overflow-hidden"
4
+ }
5
+ }
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hywax/cms",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "configKey": "cms",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.1",
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.5";
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
- function getDefaultCMSConfig() {
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$1 = {
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 || {}, getDefaultCMSConfig());
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
- v-bind="buttonProps"
11
- color="error"
12
- auto-loading
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
- confirmButton: { color: "error", label: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" },
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
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
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
- v-bind="inputProps"
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
- inputProps: { type: null, required: false },
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
- inputProps?: InputProps;
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="lg"
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
- size="lg"
46
+ :label="confirmLabel"
48
47
  :disabled="state.confirmTextValue !== confirmText"
49
48
  :loading="form?.loading"
50
- v-bind="confirmButton"
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
- v-bind="confirmButton"
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
- confirmButton: { type: null, required: false },
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
- confirmButton?: ButtonProps;
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
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
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="lucide:loader" :class="ui.loaderIcon({ class: props.ui?.loaderIcon })" />
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,6 @@
1
+ import type { Ref } from 'vue';
2
+ export interface UseAdminReturn {
3
+ isSidebarOpen: Ref<boolean>;
4
+ isSidebarCollapsed: Ref<boolean>;
5
+ }
6
+ export declare const useAdmin: () => UseAdminReturn;
@@ -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
- confirmButton: {
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
+ }
@@ -0,0 +1,2 @@
1
+ export * from './extension';
2
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ export * from "./extension.js";
2
+ export * from "./types.js";
@@ -0,0 +1,3 @@
1
+ export interface CalloutAttrs {
2
+ type: 'caution' | 'note' | 'warning' | 'tip';
3
+ }
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ export * from './extension';
2
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ export * from "./extension.js";
2
+ export * from "./types.js";
@@ -0,0 +1,5 @@
1
+ export interface UploraImageAttrs {
2
+ image: string;
3
+ alt: string;
4
+ lqip?: string;
5
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{}>>;
2
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import { defineHttpHandler } from "../../utils/httpHandler.js";
2
+ export default defineHttpHandler(() => {
3
+ return {};
4
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{}>>;
2
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import { defineHttpHandler } from "../../utils/httpHandler.js";
2
+ export default defineHttpHandler(() => {
3
+ return {};
4
+ });
@@ -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>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hywax/cms",
3
3
  "type": "module",
4
- "version": "0.0.5",
4
+ "version": "0.0.6",
5
5
  "description": "Hywax CMS. ⚠️ This package is intended for internal use only.",
6
6
  "repository": {
7
7
  "type": "git",