@hywax/cms 0.0.4 → 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/autocomplete-select.ts +5 -0
- package/.nuxt/cms/button-copy.ts +5 -0
- package/.nuxt/cms/button-delete.ts +5 -0
- 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/.nuxt/cms/form-panel-aside-section.ts +9 -0
- package/.nuxt/cms/form-panel-section.ts +8 -0
- package/.nuxt/cms/form-panel.ts +15 -0
- package/.nuxt/cms/index.ts +16 -0
- package/.nuxt/cms/input-seo.ts +5 -0
- package/.nuxt/cms/input-slug.ts +5 -0
- package/.nuxt/cms/modal-confirm.ts +5 -0
- package/.nuxt/cms/table-cell-preview.ts +9 -0
- package/.nuxt/cms/table-cell-seo.ts +5 -0
- package/.nuxt/cms/table-cell-user.ts +5 -0
- package/.nuxt/cms/table-panel-column-sorting.ts +5 -0
- package/.nuxt/cms/table-panel-column-visibility.ts +5 -0
- package/.nuxt/cms/table-panel-filters.ts +5 -0
- package/.nuxt/cms/table-panel.ts +8 -0
- package/cli/templates.mjs +4 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +213 -11
- package/dist/runtime/components/AutocompleteSelect.vue +170 -0
- package/dist/runtime/components/AutocompleteSelect.vue.d.ts +42 -0
- package/dist/runtime/components/ButtonCopy.vue +40 -0
- package/dist/runtime/components/ButtonCopy.vue.d.ts +23 -0
- package/dist/runtime/components/ButtonDelete.vue +59 -0
- package/dist/runtime/components/ButtonDelete.vue.d.ts +34 -0
- package/dist/runtime/components/FormPanel.vue +70 -0
- package/dist/runtime/components/FormPanel.vue.d.ts +41 -0
- package/dist/runtime/components/FormPanelAsideSection.vue +41 -0
- package/dist/runtime/components/FormPanelAsideSection.vue.d.ts +23 -0
- package/dist/runtime/components/FormPanelSection.vue +31 -0
- package/dist/runtime/components/FormPanelSection.vue.d.ts +20 -0
- package/dist/runtime/components/InputSeo.vue +73 -0
- package/dist/runtime/components/InputSeo.vue.d.ts +19 -0
- package/dist/runtime/components/InputSlug.vue +74 -0
- package/dist/runtime/components/InputSlug.vue.d.ts +31 -0
- package/dist/runtime/components/ModalConfirm.vue +96 -0
- package/dist/runtime/components/ModalConfirm.vue.d.ts +32 -0
- package/dist/runtime/components/TableCellPreview.vue +40 -0
- package/dist/runtime/components/TableCellPreview.vue.d.ts +18 -0
- package/dist/runtime/components/TableCellSeo.vue +34 -0
- package/dist/runtime/components/TableCellSeo.vue.d.ts +13 -0
- package/dist/runtime/components/TableCellUser.vue +33 -0
- package/dist/runtime/components/TableCellUser.vue.d.ts +15 -0
- package/dist/runtime/components/TablePanel.vue +153 -0
- package/dist/runtime/components/TablePanel.vue.d.ts +50 -0
- package/dist/runtime/components/TablePanelColumnSorting.vue +72 -0
- package/dist/runtime/components/TablePanelColumnSorting.vue.d.ts +20 -0
- package/dist/runtime/components/TablePanelColumnVisibility.vue +49 -0
- package/dist/runtime/components/TablePanelColumnVisibility.vue.d.ts +20 -0
- package/dist/runtime/components/TablePanelFilters.vue +79 -0
- package/dist/runtime/components/TablePanelFilters.vue.d.ts +34 -0
- package/dist/runtime/components/prose/UploraImage.vue +8 -3
- package/dist/runtime/composables/useAdmin.d.ts +6 -0
- package/dist/runtime/composables/useAdmin.js +14 -0
- package/dist/runtime/composables/useDeleteConfirm.d.ts +15 -0
- package/dist/runtime/composables/useDeleteConfirm.js +27 -0
- package/dist/runtime/composables/useSeoStats.d.ts +2 -2
- package/dist/runtime/composables/useSeoStats.js +1 -1
- package/dist/runtime/composables/useTable.d.ts +19 -0
- package/dist/runtime/composables/useTable.js +90 -0
- 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/editor/markdown/index.d.ts +3 -0
- package/dist/runtime/editor/markdown/index.js +47 -0
- package/dist/runtime/editor/markdown/nodes/callout.d.ts +2 -0
- package/dist/runtime/editor/markdown/nodes/callout.js +21 -0
- package/dist/runtime/editor/markdown/nodes/uploraImage.d.ts +2 -0
- package/dist/runtime/editor/markdown/nodes/uploraImage.js +31 -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/server/utils/validation.d.ts +2 -2
- package/dist/runtime/types/index.d.ts +16 -0
- package/dist/runtime/types/index.js +16 -0
- package/dist/runtime/types/query.d.ts +3 -1
- package/dist/runtime/types/tv.d.ts +9 -3
- package/package.json +5 -5
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { ComponentConfig, SEO } from '../types';
|
|
3
|
+
import theme from '#build/cms/input-seo';
|
|
4
|
+
type InputSeo = ComponentConfig<typeof theme, AppConfig, 'inputSeo'>;
|
|
5
|
+
export interface InputSeoProps {
|
|
6
|
+
as?: any;
|
|
7
|
+
class?: any;
|
|
8
|
+
ui?: InputSeo['slots'];
|
|
9
|
+
}
|
|
10
|
+
declare const _default: import("vue").DefineComponent<InputSeoProps & {
|
|
11
|
+
modelValue?: SEO;
|
|
12
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
"update:modelValue": (value: SEO) => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<InputSeoProps & {
|
|
15
|
+
modelValue?: SEO;
|
|
16
|
+
}> & Readonly<{
|
|
17
|
+
"onUpdate:modelValue"?: ((value: SEO) => any) | undefined;
|
|
18
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
3
|
+
<UFormField
|
|
4
|
+
:label="label"
|
|
5
|
+
:name="titleKey"
|
|
6
|
+
>
|
|
7
|
+
<UInput
|
|
8
|
+
v-model="title"
|
|
9
|
+
:color="color"
|
|
10
|
+
:variant="variant"
|
|
11
|
+
:size="size"
|
|
12
|
+
class="w-full"
|
|
13
|
+
/>
|
|
14
|
+
</UFormField>
|
|
15
|
+
<UFormField :name="slugKey" class="-mt-3" eager-validation>
|
|
16
|
+
<UInput
|
|
17
|
+
v-model="slug"
|
|
18
|
+
class="w-full"
|
|
19
|
+
size="xs"
|
|
20
|
+
variant="none"
|
|
21
|
+
:placeholder="isRegenerate ? '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A' : '\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0441\u043B\u0430\u0433'"
|
|
22
|
+
:disabled="isRegenerate"
|
|
23
|
+
:ui="{
|
|
24
|
+
base: 'text-muted'
|
|
25
|
+
}"
|
|
26
|
+
>
|
|
27
|
+
<template #leading>
|
|
28
|
+
<UButton
|
|
29
|
+
size="xs"
|
|
30
|
+
variant="link"
|
|
31
|
+
:icon="appConfig.ui.icons.link"
|
|
32
|
+
class="p-0"
|
|
33
|
+
:color="isRegenerate ? 'success' : 'neutral'"
|
|
34
|
+
@click="isRegenerate = !isRegenerate"
|
|
35
|
+
/>
|
|
36
|
+
</template>
|
|
37
|
+
</UInput>
|
|
38
|
+
</UFormField>
|
|
39
|
+
</Primitive>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script>
|
|
43
|
+
import theme from "#build/cms/input-slug";
|
|
44
|
+
import { computed, ref, useAppConfig, watch } from "#imports";
|
|
45
|
+
import { Primitive } from "reka-ui";
|
|
46
|
+
import { slugify } from "../utils/slugify";
|
|
47
|
+
import { tv } from "../utils/tv";
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<script setup>
|
|
51
|
+
const props = defineProps({
|
|
52
|
+
regenerate: { type: Boolean, required: false },
|
|
53
|
+
label: { type: String, required: false },
|
|
54
|
+
titleKey: { type: String, required: false },
|
|
55
|
+
slugKey: { type: String, required: false },
|
|
56
|
+
color: { type: null, required: false },
|
|
57
|
+
variant: { type: null, required: false },
|
|
58
|
+
size: { type: null, required: false },
|
|
59
|
+
as: { type: null, required: false },
|
|
60
|
+
class: { type: null, required: false },
|
|
61
|
+
ui: { type: null, required: false }
|
|
62
|
+
});
|
|
63
|
+
const title = defineModel("title", { type: String });
|
|
64
|
+
const slug = defineModel("slug", { type: String });
|
|
65
|
+
const appConfig = useAppConfig();
|
|
66
|
+
const isRegenerate = ref(props.regenerate);
|
|
67
|
+
watch(title, () => {
|
|
68
|
+
if (!isRegenerate.value) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
slug.value = slugify(title.value);
|
|
72
|
+
});
|
|
73
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.inputSlug || {} })());
|
|
74
|
+
</script>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { InputProps } from '@nuxt/ui';
|
|
3
|
+
import type { ComponentConfig } from '../types';
|
|
4
|
+
import theme from '#build/cms/input-slug';
|
|
5
|
+
type InputSlug = ComponentConfig<typeof theme, AppConfig, 'inputSlug'>;
|
|
6
|
+
export interface InputSlugProps {
|
|
7
|
+
regenerate?: boolean;
|
|
8
|
+
label?: string;
|
|
9
|
+
titleKey?: string;
|
|
10
|
+
slugKey?: string;
|
|
11
|
+
color?: InputProps['color'];
|
|
12
|
+
variant?: InputProps['variant'];
|
|
13
|
+
size?: InputProps['size'];
|
|
14
|
+
as?: any;
|
|
15
|
+
class?: any;
|
|
16
|
+
ui?: InputSlug['slots'];
|
|
17
|
+
}
|
|
18
|
+
declare const _default: import("vue").DefineComponent<InputSlugProps & {
|
|
19
|
+
title?: string;
|
|
20
|
+
slug?: string;
|
|
21
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
22
|
+
"update:title": (value: string | undefined) => any;
|
|
23
|
+
"update:slug": (value: string | undefined) => any;
|
|
24
|
+
}, string, import("vue").PublicProps, Readonly<InputSlugProps & {
|
|
25
|
+
title?: string;
|
|
26
|
+
slug?: string;
|
|
27
|
+
}> & Readonly<{
|
|
28
|
+
"onUpdate:title"?: ((value: string | undefined) => any) | undefined;
|
|
29
|
+
"onUpdate:slug"?: ((value: string | undefined) => any) | undefined;
|
|
30
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UModal
|
|
3
|
+
:title="title"
|
|
4
|
+
:ui="{
|
|
5
|
+
content: 'divide-y-0',
|
|
6
|
+
body: 'py-0! text-sm',
|
|
7
|
+
description: 'hidden'
|
|
8
|
+
}"
|
|
9
|
+
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
10
|
+
>
|
|
11
|
+
<template #description />
|
|
12
|
+
<template #body>
|
|
13
|
+
{{ message }}
|
|
14
|
+
|
|
15
|
+
<UForm
|
|
16
|
+
v-if="confirmText"
|
|
17
|
+
id="confirm-form"
|
|
18
|
+
ref="form"
|
|
19
|
+
class="pt-3"
|
|
20
|
+
:state="state"
|
|
21
|
+
@submit="handleConfirmClick()"
|
|
22
|
+
>
|
|
23
|
+
<UFormField name="confirmTextValue">
|
|
24
|
+
<template #label>
|
|
25
|
+
Введите <strong class="text-highlighted">{{ confirmText }}</strong> для подтверждения
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<UInput v-model="state.confirmTextValue" class="w-full" />
|
|
29
|
+
</UFormField>
|
|
30
|
+
</UForm>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<template #footer>
|
|
34
|
+
<UButton
|
|
35
|
+
color="neutral"
|
|
36
|
+
label="Закрыть"
|
|
37
|
+
variant="ghost"
|
|
38
|
+
:size="size"
|
|
39
|
+
@click="emit('close')"
|
|
40
|
+
/>
|
|
41
|
+
|
|
42
|
+
<UButton
|
|
43
|
+
v-if="confirmText"
|
|
44
|
+
form="confirm-form"
|
|
45
|
+
type="submit"
|
|
46
|
+
:label="confirmLabel"
|
|
47
|
+
:disabled="state.confirmTextValue !== confirmText"
|
|
48
|
+
:loading="form?.loading"
|
|
49
|
+
:color="color"
|
|
50
|
+
:variant="variant"
|
|
51
|
+
:size="size"
|
|
52
|
+
/>
|
|
53
|
+
<UButton
|
|
54
|
+
v-else
|
|
55
|
+
label="Подтвердить"
|
|
56
|
+
loading-auto
|
|
57
|
+
:color="color"
|
|
58
|
+
:variant="variant"
|
|
59
|
+
:size="size"
|
|
60
|
+
@click="handleConfirmClick()"
|
|
61
|
+
/>
|
|
62
|
+
</template>
|
|
63
|
+
</UModal>
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<script>
|
|
67
|
+
import theme from "#build/cms/modal-confirm";
|
|
68
|
+
import { computed, reactive, useAppConfig, useTemplateRef } from "#imports";
|
|
69
|
+
import { tv } from "../utils/tv";
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<script setup>
|
|
73
|
+
const props = defineProps({
|
|
74
|
+
title: { type: String, required: false },
|
|
75
|
+
message: { type: String, required: true },
|
|
76
|
+
confirmText: { type: String, 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" },
|
|
81
|
+
onConfirm: { type: Function, required: false },
|
|
82
|
+
class: { type: null, required: false },
|
|
83
|
+
ui: { type: null, required: false }
|
|
84
|
+
});
|
|
85
|
+
const emit = defineEmits(["confirm", "close"]);
|
|
86
|
+
const appConfig = useAppConfig();
|
|
87
|
+
const form = useTemplateRef("form");
|
|
88
|
+
const state = reactive({
|
|
89
|
+
confirmTextValue: ""
|
|
90
|
+
});
|
|
91
|
+
async function handleConfirmClick() {
|
|
92
|
+
await props.onConfirm?.();
|
|
93
|
+
emit("close");
|
|
94
|
+
}
|
|
95
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.modalConfirm || {} })());
|
|
96
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { ButtonProps } from '@nuxt/ui';
|
|
3
|
+
import type { ComponentConfig } from '../types';
|
|
4
|
+
import theme from '#build/cms/modal-confirm';
|
|
5
|
+
type ModalConfirm = ComponentConfig<typeof theme, AppConfig, 'modalConfirm'>;
|
|
6
|
+
export interface ModalConfirmProps {
|
|
7
|
+
title?: string;
|
|
8
|
+
message: string;
|
|
9
|
+
confirmText?: string;
|
|
10
|
+
confirmLabel?: string;
|
|
11
|
+
color?: ButtonProps['color'];
|
|
12
|
+
variant?: ButtonProps['variant'];
|
|
13
|
+
size?: ButtonProps['size'];
|
|
14
|
+
onConfirm?: () => Promise<any> | any;
|
|
15
|
+
class?: any;
|
|
16
|
+
ui?: ModalConfirm['slots'];
|
|
17
|
+
}
|
|
18
|
+
export interface ModalConfirmEmits {
|
|
19
|
+
confirm: [];
|
|
20
|
+
close: [];
|
|
21
|
+
}
|
|
22
|
+
declare const _default: import("vue").DefineComponent<ModalConfirmProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
23
|
+
close: () => any;
|
|
24
|
+
confirm: () => any;
|
|
25
|
+
}, string, import("vue").PublicProps, Readonly<ModalConfirmProps> & Readonly<{
|
|
26
|
+
onClose?: (() => any) | undefined;
|
|
27
|
+
onConfirm?: (() => any) | undefined;
|
|
28
|
+
}>, {
|
|
29
|
+
size: "xs" | "sm" | "md" | "lg" | "xl";
|
|
30
|
+
confirmLabel: string;
|
|
31
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
32
|
+
export default _default;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ULink :to="to" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
3
|
+
<UploraImage
|
|
4
|
+
v-if="thumbnail"
|
|
5
|
+
:id="thumbnail.id"
|
|
6
|
+
:alt="title"
|
|
7
|
+
:lqip="thumbnail.lqip"
|
|
8
|
+
:sizes="[{ width: 30, height: 30, descriptor: '1x' }]"
|
|
9
|
+
:ui="{ picture: 'aspect-square' }"
|
|
10
|
+
:class="ui.image({ class: props.ui?.image })"
|
|
11
|
+
/>
|
|
12
|
+
<div :class="ui.container({ class: props.ui?.container })">
|
|
13
|
+
<p :class="ui.title({ class: props.ui?.title })">
|
|
14
|
+
{{ title }}
|
|
15
|
+
</p>
|
|
16
|
+
<p v-if="description" :class="ui.description({ class: props.ui?.description })">
|
|
17
|
+
{{ description }}
|
|
18
|
+
</p>
|
|
19
|
+
</div>
|
|
20
|
+
</ULink>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script>
|
|
24
|
+
import theme from "#build/cms/table-cell-preview";
|
|
25
|
+
import { computed, useAppConfig } from "#imports";
|
|
26
|
+
import { tv } from "../utils/tv";
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<script setup>
|
|
30
|
+
const props = defineProps({
|
|
31
|
+
title: { type: String, required: true },
|
|
32
|
+
description: { type: String, required: false },
|
|
33
|
+
thumbnail: { type: Object, required: false },
|
|
34
|
+
to: { type: null, required: false },
|
|
35
|
+
class: { type: null, required: false },
|
|
36
|
+
ui: { type: null, required: false }
|
|
37
|
+
});
|
|
38
|
+
const appConfig = useAppConfig();
|
|
39
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.tableCellPreview || {} })());
|
|
40
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { RouteLocationRaw } from 'vue-router';
|
|
3
|
+
import type { ComponentConfig } from '../types';
|
|
4
|
+
import theme from '#build/cms/table-cell-preview';
|
|
5
|
+
type TableCellPreview = ComponentConfig<typeof theme, AppConfig, 'tableCellPreview'>;
|
|
6
|
+
export interface TableCellPreviewProps {
|
|
7
|
+
title: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
thumbnail?: {
|
|
10
|
+
id: string;
|
|
11
|
+
lqip?: string;
|
|
12
|
+
};
|
|
13
|
+
to?: RouteLocationRaw;
|
|
14
|
+
class?: any;
|
|
15
|
+
ui?: TableCellPreview['slots'];
|
|
16
|
+
}
|
|
17
|
+
declare const _default: import("vue").DefineComponent<TableCellPreviewProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<TableCellPreviewProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
3
|
+
<UBadge
|
|
4
|
+
:label="title.progress"
|
|
5
|
+
:color="title.color"
|
|
6
|
+
variant="subtle"
|
|
7
|
+
/>
|
|
8
|
+
<UBadge
|
|
9
|
+
:label="description.progress"
|
|
10
|
+
:color="description.color"
|
|
11
|
+
variant="subtle"
|
|
12
|
+
/>
|
|
13
|
+
</Primitive>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script>
|
|
17
|
+
import theme from "#build/cms/table-cell-seo";
|
|
18
|
+
import { computed, useAppConfig } from "#imports";
|
|
19
|
+
import { Primitive } from "reka-ui";
|
|
20
|
+
import { useSeoStats } from "../composables/useSeoStats";
|
|
21
|
+
import { tv } from "../utils/tv";
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script setup>
|
|
25
|
+
const props = defineProps({
|
|
26
|
+
seo: { type: Object, required: true },
|
|
27
|
+
as: { type: null, required: false },
|
|
28
|
+
class: { type: null, required: false },
|
|
29
|
+
ui: { type: null, required: false }
|
|
30
|
+
});
|
|
31
|
+
const appConfig = useAppConfig();
|
|
32
|
+
const { title, description } = useSeoStats(props.seo);
|
|
33
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.tableCellSeo || {} })());
|
|
34
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { ComponentConfig } from '../types';
|
|
3
|
+
import type { SEO } from '../types/seo';
|
|
4
|
+
import theme from '#build/cms/table-cell-seo';
|
|
5
|
+
type TableCellSeo = ComponentConfig<typeof theme, AppConfig, 'tableCellSeo'>;
|
|
6
|
+
export interface TableCellSeoProps {
|
|
7
|
+
seo: SEO;
|
|
8
|
+
as?: any;
|
|
9
|
+
class?: any;
|
|
10
|
+
ui?: TableCellSeo['slots'];
|
|
11
|
+
}
|
|
12
|
+
declare const _default: import("vue").DefineComponent<TableCellSeoProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<TableCellSeoProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UUser
|
|
3
|
+
:name="name"
|
|
4
|
+
:description="description"
|
|
5
|
+
:to="to"
|
|
6
|
+
:avatar="{
|
|
7
|
+
src: createAvatarByName(name)
|
|
8
|
+
}"
|
|
9
|
+
size="sm"
|
|
10
|
+
:as="as"
|
|
11
|
+
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
12
|
+
/>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script>
|
|
16
|
+
import theme from "#build/cms/table-cell-user";
|
|
17
|
+
import { computed, useAppConfig } from "#imports";
|
|
18
|
+
import { createAvatarByName } from "../utils/avatar";
|
|
19
|
+
import { tv } from "../utils/tv";
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<script setup>
|
|
23
|
+
const props = defineProps({
|
|
24
|
+
name: { type: String, required: true },
|
|
25
|
+
description: { type: String, required: false },
|
|
26
|
+
to: { type: null, required: false },
|
|
27
|
+
as: { type: null, required: false },
|
|
28
|
+
class: { type: null, required: false },
|
|
29
|
+
ui: { type: null, required: false }
|
|
30
|
+
});
|
|
31
|
+
const appConfig = useAppConfig();
|
|
32
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.tableCellUser || {} })());
|
|
33
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { RouteLocationRaw } from 'vue-router';
|
|
3
|
+
import type { ComponentConfig } from '../types';
|
|
4
|
+
import theme from '#build/cms/table-cell-user';
|
|
5
|
+
type TableCellUser = ComponentConfig<typeof theme, AppConfig, 'tableCellUser'>;
|
|
6
|
+
export interface TableCellUserProps {
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
to?: RouteLocationRaw;
|
|
10
|
+
as?: any;
|
|
11
|
+
class?: any;
|
|
12
|
+
ui?: TableCellUser['slots'];
|
|
13
|
+
}
|
|
14
|
+
declare const _default: import("vue").DefineComponent<TableCellUserProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<TableCellUserProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UDashboardPanel
|
|
3
|
+
:ui="{ body: 'border-b border-default relative' }"
|
|
4
|
+
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
5
|
+
>
|
|
6
|
+
<template #header>
|
|
7
|
+
<UDashboardNavbar :title="title">
|
|
8
|
+
<template #right>
|
|
9
|
+
<slot name="navbar-right" />
|
|
10
|
+
</template>
|
|
11
|
+
</UDashboardNavbar>
|
|
12
|
+
<UDashboardToolbar>
|
|
13
|
+
<template #left>
|
|
14
|
+
<slot name="toolbar-left" />
|
|
15
|
+
</template>
|
|
16
|
+
<template #right>
|
|
17
|
+
<slot name="toolbar-right" />
|
|
18
|
+
|
|
19
|
+
<TablePanelColumnSorting
|
|
20
|
+
:model-value="sorting"
|
|
21
|
+
:table="tableRef?.tableApi"
|
|
22
|
+
@update:model-value="emit('update:sorting', $event)"
|
|
23
|
+
/>
|
|
24
|
+
<TablePanelColumnVisibility
|
|
25
|
+
v-if="props.columnVisibility"
|
|
26
|
+
v-model="columnVisibility"
|
|
27
|
+
:table="tableRef?.tableApi"
|
|
28
|
+
/>
|
|
29
|
+
</template>
|
|
30
|
+
</UDashboardToolbar>
|
|
31
|
+
</template>
|
|
32
|
+
<template #body>
|
|
33
|
+
<div v-show="loading" :class="ui.loader({ class: props.ui?.loader })">
|
|
34
|
+
<UIcon :name="appConfig.ui.icons.loading" :class="ui.loaderIcon({ class: props.ui?.loaderIcon })" />
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<UTable
|
|
38
|
+
ref="table"
|
|
39
|
+
v-model:column-visibility="columnVisibility"
|
|
40
|
+
:class="ui.table({ class: props.ui?.table })"
|
|
41
|
+
:column-pinning="columnPinning"
|
|
42
|
+
:columns="tableColumns"
|
|
43
|
+
:data="data"
|
|
44
|
+
:sorting-options="{ manualSorting: hasPagination }"
|
|
45
|
+
:sticky="sticky"
|
|
46
|
+
:ui="{
|
|
47
|
+
base: 'table-fixed border-separate border-spacing-0',
|
|
48
|
+
thead: '[&>tr]:bg-elevated/50 [&>tr]:after:content-none',
|
|
49
|
+
tbody: '[&>tr]:last:[&>td]:border-b-0',
|
|
50
|
+
th: 'py-2 first:rounded-l-lg last:rounded-r-lg border-y border-default first:border-l last:border-r',
|
|
51
|
+
td: 'border-b border-default'
|
|
52
|
+
}"
|
|
53
|
+
>
|
|
54
|
+
<template v-for="(_, name) in tableProxySlots" #[name]="slotData">
|
|
55
|
+
<slot :name="name" v-bind="slotData" />
|
|
56
|
+
</template>
|
|
57
|
+
</UTable>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<template v-if="hasPagination" #footer>
|
|
61
|
+
<div class="flex justify-between items-center py-3 px-4">
|
|
62
|
+
<div>
|
|
63
|
+
<span class="text-sm text-muted">
|
|
64
|
+
Всего: {{ total ?? 0 }}
|
|
65
|
+
</span>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="flex items-center gap-2">
|
|
68
|
+
<span class="text-sm text-muted">
|
|
69
|
+
Строк на странице:
|
|
70
|
+
</span>
|
|
71
|
+
<USelect
|
|
72
|
+
:model-value="paginationProps.itemsPerPage"
|
|
73
|
+
:items="itemsPerPageList"
|
|
74
|
+
class="w-18"
|
|
75
|
+
@update:model-value="emit('update:itemsPerPage', Number($event))"
|
|
76
|
+
/>
|
|
77
|
+
<UPagination
|
|
78
|
+
v-bind="paginationProps"
|
|
79
|
+
:sibling-count="1"
|
|
80
|
+
variant="ghost"
|
|
81
|
+
show-edges
|
|
82
|
+
@update:page="emit('update:page', $event)"
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</template>
|
|
87
|
+
</UDashboardPanel>
|
|
88
|
+
</template>
|
|
89
|
+
|
|
90
|
+
<script>
|
|
91
|
+
import theme from "#build/cms/table-panel";
|
|
92
|
+
import { UButton, UDropdownMenu } from "#components";
|
|
93
|
+
import { computed, h, ref, useAppConfig, useTemplateRef } from "#imports";
|
|
94
|
+
import { objectOmit, reactivePick } from "@vueuse/core";
|
|
95
|
+
import { useForwardProps } from "reka-ui";
|
|
96
|
+
import { tv } from "../utils/tv";
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<script setup>
|
|
100
|
+
const props = defineProps({
|
|
101
|
+
title: { type: String, required: false },
|
|
102
|
+
page: { type: Number, required: false },
|
|
103
|
+
itemsPerPage: { type: Number, required: false },
|
|
104
|
+
total: { type: Number, required: false },
|
|
105
|
+
data: { type: Array, required: false },
|
|
106
|
+
columns: { type: null, required: false },
|
|
107
|
+
sticky: { type: Boolean, required: false, default: true },
|
|
108
|
+
columnPinning: { type: Object, required: false },
|
|
109
|
+
columnVisibility: { type: Boolean, required: false, default: true },
|
|
110
|
+
defaultHiddenColumns: { type: Array, required: false, default: () => [] },
|
|
111
|
+
sorting: { type: Array, required: false },
|
|
112
|
+
loading: { type: Boolean, required: false },
|
|
113
|
+
actions: { type: Function, required: false },
|
|
114
|
+
class: { type: null, required: false },
|
|
115
|
+
ui: { type: null, required: false }
|
|
116
|
+
});
|
|
117
|
+
const emit = defineEmits(["update:sorting", "update:page", "update:itemsPerPage"]);
|
|
118
|
+
const slots = defineSlots();
|
|
119
|
+
const appConfig = useAppConfig();
|
|
120
|
+
const tableColumns = computed(() => [
|
|
121
|
+
...props.columns ?? [],
|
|
122
|
+
...props.actions ? [{
|
|
123
|
+
id: "actions",
|
|
124
|
+
meta: { class: { td: "w-20" } },
|
|
125
|
+
enableHiding: false,
|
|
126
|
+
cell: ({ row }) => h(
|
|
127
|
+
"div",
|
|
128
|
+
{ class: "text-right" },
|
|
129
|
+
h(
|
|
130
|
+
UDropdownMenu,
|
|
131
|
+
{
|
|
132
|
+
content: { align: "end" },
|
|
133
|
+
items: props.actions?.(row.original) ?? []
|
|
134
|
+
},
|
|
135
|
+
() => h(UButton, {
|
|
136
|
+
icon: "lucide:ellipsis-vertical",
|
|
137
|
+
color: "neutral",
|
|
138
|
+
variant: "ghost",
|
|
139
|
+
class: "ml-auto"
|
|
140
|
+
})
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
}] : []
|
|
144
|
+
]);
|
|
145
|
+
const paginationProps = useForwardProps(reactivePick(props, "page", "itemsPerPage", "total"));
|
|
146
|
+
const tableProxySlots = objectOmit(slots, ["toolbar-left", "toolbar-right", "navbar-right"]);
|
|
147
|
+
const tableRef = useTemplateRef("table");
|
|
148
|
+
const initialVisibilityState = Object.fromEntries(props.defaultHiddenColumns.map((column) => [column, false]));
|
|
149
|
+
const columnVisibility = ref(initialVisibilityState);
|
|
150
|
+
const hasPagination = computed(() => props.page !== void 0);
|
|
151
|
+
const itemsPerPageList = [10, 20, 50, 100];
|
|
152
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.tablePanel || {} })());
|
|
153
|
+
</script>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
+
import type { DropdownMenuItem, TableProps, TableSlots } from '@nuxt/ui';
|
|
3
|
+
import type { ColumnPinningState, SortingState } from '@tanstack/vue-table';
|
|
4
|
+
import type { ComponentConfig } from '../types';
|
|
5
|
+
import theme from '#build/cms/table-panel';
|
|
6
|
+
type TablePanel = ComponentConfig<typeof theme, AppConfig, 'tablePanel'>;
|
|
7
|
+
export interface TablePanelProps<T> {
|
|
8
|
+
title?: string;
|
|
9
|
+
page?: number;
|
|
10
|
+
itemsPerPage?: number;
|
|
11
|
+
total?: number;
|
|
12
|
+
data?: T[];
|
|
13
|
+
columns?: TableProps<T>['columns'];
|
|
14
|
+
sticky?: boolean;
|
|
15
|
+
columnPinning?: ColumnPinningState;
|
|
16
|
+
columnVisibility?: boolean;
|
|
17
|
+
defaultHiddenColumns?: string[];
|
|
18
|
+
sorting?: SortingState;
|
|
19
|
+
loading?: boolean;
|
|
20
|
+
actions?: (row: T) => DropdownMenuItem[];
|
|
21
|
+
class?: any;
|
|
22
|
+
ui?: TablePanel['slots'];
|
|
23
|
+
}
|
|
24
|
+
export interface TablePanelEmits {
|
|
25
|
+
'update:sorting': [value: SortingState];
|
|
26
|
+
'update:page': [value: number];
|
|
27
|
+
'update:itemsPerPage': [value: number];
|
|
28
|
+
}
|
|
29
|
+
export type TablePanelSlots<T> = Omit<TableSlots<T>, 'toolbar-left' | 'toolbar-right' | 'navbar-right'> & {
|
|
30
|
+
'toolbar-left'?: () => any;
|
|
31
|
+
'navbar-right'?: () => any;
|
|
32
|
+
'toolbar-right'?: () => any;
|
|
33
|
+
};
|
|
34
|
+
declare const _default: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
35
|
+
props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{
|
|
36
|
+
readonly "onUpdate:sorting"?: ((value: SortingState) => any) | undefined;
|
|
37
|
+
readonly "onUpdate:page"?: ((value: number) => any) | undefined;
|
|
38
|
+
readonly "onUpdate:itemsPerPage"?: ((value: number) => any) | undefined;
|
|
39
|
+
} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onUpdate:sorting" | "onUpdate:page" | "onUpdate:itemsPerPage"> & TablePanelProps<T> & Partial<{}>> & import("vue").PublicProps;
|
|
40
|
+
expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
|
|
41
|
+
attrs: any;
|
|
42
|
+
slots: TablePanelSlots<T>;
|
|
43
|
+
emit: ((evt: "update:sorting", value: SortingState) => void) & ((evt: "update:page", value: number) => void) & ((evt: "update:itemsPerPage", value: number) => void);
|
|
44
|
+
}>) => import("vue").VNode & {
|
|
45
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
46
|
+
};
|
|
47
|
+
export default _default;
|
|
48
|
+
type __VLS_PrettifyLocal<T> = {
|
|
49
|
+
[K in keyof T]: T[K];
|
|
50
|
+
} & {};
|