@hywax/cms-console 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nuxt/cms-console/button-copy-text.ts +19 -0
- package/.nuxt/cms-console/button-delete-confirm.ts +5 -0
- package/.nuxt/cms-console/editor/index.ts +0 -0
- package/.nuxt/cms-console/form-panel-aside-section.ts +9 -0
- package/.nuxt/cms-console/form-panel-section.ts +8 -0
- package/.nuxt/cms-console/form-panel.ts +15 -0
- package/.nuxt/cms-console/index.ts +11 -0
- package/.nuxt/cms-console/input-seo.ts +5 -0
- package/.nuxt/cms-console/input-slug.ts +5 -0
- package/.nuxt/cms-console/input-uplora-image.ts +27 -0
- package/.nuxt/cms-console/modal-confirm.ts +5 -0
- package/.nuxt/cms-console/table-panel.ts +8 -0
- package/.nuxt/cms-console/table-search-input.ts +6 -0
- package/.nuxt/cms-console.css +31 -0
- package/dist/module.d.mts +11 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +387 -0
- package/dist/runtime/components/AutocompleteSelect.d.vue.ts +56 -0
- package/dist/runtime/components/AutocompleteSelect.vue +225 -0
- package/dist/runtime/components/AutocompleteSelect.vue.d.ts +56 -0
- package/dist/runtime/components/ButtonCopyText.d.vue.ts +28 -0
- package/dist/runtime/components/ButtonCopyText.vue +70 -0
- package/dist/runtime/components/ButtonCopyText.vue.d.ts +28 -0
- package/dist/runtime/components/ButtonDeleteConfirm.d.vue.ts +38 -0
- package/dist/runtime/components/ButtonDeleteConfirm.vue +62 -0
- package/dist/runtime/components/ButtonDeleteConfirm.vue.d.ts +38 -0
- package/dist/runtime/components/DatePicker.d.vue.ts +43 -0
- package/dist/runtime/components/DatePicker.vue +232 -0
- package/dist/runtime/components/DatePicker.vue.d.ts +43 -0
- package/dist/runtime/components/EditorFull.d.vue.ts +13 -0
- package/dist/runtime/components/EditorFull.vue +139 -0
- package/dist/runtime/components/EditorFull.vue.d.ts +13 -0
- package/dist/runtime/components/EditorLinkPopover.d.vue.ts +8 -0
- package/dist/runtime/components/EditorLinkPopover.vue +137 -0
- package/dist/runtime/components/EditorLinkPopover.vue.d.ts +8 -0
- package/dist/runtime/components/FormPanel.d.vue.ts +47 -0
- package/dist/runtime/components/FormPanel.vue +73 -0
- package/dist/runtime/components/FormPanel.vue.d.ts +47 -0
- package/dist/runtime/components/FormPanelAsideSection.d.vue.ts +24 -0
- package/dist/runtime/components/FormPanelAsideSection.vue +41 -0
- package/dist/runtime/components/FormPanelAsideSection.vue.d.ts +24 -0
- package/dist/runtime/components/FormPanelSection.d.vue.ts +21 -0
- package/dist/runtime/components/FormPanelSection.vue +31 -0
- package/dist/runtime/components/FormPanelSection.vue.d.ts +21 -0
- package/dist/runtime/components/InputSeo.d.vue.ts +21 -0
- package/dist/runtime/components/InputSeo.vue +73 -0
- package/dist/runtime/components/InputSeo.vue.d.ts +21 -0
- package/dist/runtime/components/InputSlug.d.vue.ts +30 -0
- package/dist/runtime/components/InputSlug.vue +70 -0
- package/dist/runtime/components/InputSlug.vue.d.ts +30 -0
- package/dist/runtime/components/InputUploraImage.d.vue.ts +39 -0
- package/dist/runtime/components/InputUploraImage.vue +163 -0
- package/dist/runtime/components/InputUploraImage.vue.d.ts +39 -0
- package/dist/runtime/components/Layout.d.vue.ts +30 -0
- package/dist/runtime/components/Layout.vue +82 -0
- package/dist/runtime/components/Layout.vue.d.ts +30 -0
- package/dist/runtime/components/ModalConfirm.d.vue.ts +33 -0
- package/dist/runtime/components/ModalConfirm.vue +97 -0
- package/dist/runtime/components/ModalConfirm.vue.d.ts +33 -0
- package/dist/runtime/components/TableColumnSorting.d.vue.ts +17 -0
- package/dist/runtime/components/TableColumnSorting.vue +81 -0
- package/dist/runtime/components/TableColumnSorting.vue.d.ts +17 -0
- package/dist/runtime/components/TableColumnVisibility.d.vue.ts +24 -0
- package/dist/runtime/components/TableColumnVisibility.vue +110 -0
- package/dist/runtime/components/TableColumnVisibility.vue.d.ts +24 -0
- package/dist/runtime/components/TableFilters.d.vue.ts +90 -0
- package/dist/runtime/components/TableFilters.vue +199 -0
- package/dist/runtime/components/TableFilters.vue.d.ts +90 -0
- package/dist/runtime/components/TablePanel.d.vue.ts +95 -0
- package/dist/runtime/components/TablePanel.vue +297 -0
- package/dist/runtime/components/TablePanel.vue.d.ts +95 -0
- package/dist/runtime/components/TableSearchInput.d.vue.ts +33 -0
- package/dist/runtime/components/TableSearchInput.vue +97 -0
- package/dist/runtime/components/TableSearchInput.vue.d.ts +33 -0
- package/dist/runtime/composables/useAdmin.d.ts +6 -0
- package/dist/runtime/composables/useAdmin.js +14 -0
- package/dist/runtime/composables/useEditorDragHandle.d.ts +17 -0
- package/dist/runtime/composables/useEditorDragHandle.js +95 -0
- package/dist/runtime/composables/useEditorSuggestions.d.ts +74 -0
- package/dist/runtime/composables/useEditorSuggestions.js +25 -0
- package/dist/runtime/composables/useEditorToolbar.d.ts +121 -0
- package/dist/runtime/composables/useEditorToolbar.js +87 -0
- package/dist/runtime/composables/useQueryState.d.ts +28 -0
- package/dist/runtime/composables/useQueryState.js +105 -0
- package/dist/runtime/composables/useRouteQuery.d.ts +37 -0
- package/dist/runtime/composables/useRouteQuery.js +81 -0
- package/dist/runtime/composables/useSeoStats.d.ts +12 -0
- package/dist/runtime/composables/useSeoStats.js +44 -0
- package/dist/runtime/composables/useTable.d.ts +25 -0
- package/dist/runtime/composables/useTable.js +84 -0
- package/dist/runtime/composables/useTableColumns.d.ts +28 -0
- package/dist/runtime/composables/useTableColumns.js +54 -0
- package/dist/runtime/editor/uplora-image/EditorUploraImage.d.ts +18 -0
- package/dist/runtime/editor/uplora-image/EditorUploraImage.js +42 -0
- package/dist/runtime/editor/uplora-image/EditorUploraImageNode.d.vue.ts +4 -0
- package/dist/runtime/editor/uplora-image/EditorUploraImageNode.vue +23 -0
- package/dist/runtime/editor/uplora-image/EditorUploraImageNode.vue.d.ts +4 -0
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/tv.d.ts +1 -0
- package/dist/runtime/tv.js +4 -0
- package/dist/runtime/types/app.config.d.ts +6 -0
- package/dist/runtime/types/date.d.ts +5 -0
- package/dist/runtime/types/date.js +0 -0
- package/dist/runtime/types/dictionaries.d.ts +1 -0
- package/dist/runtime/types/dictionaries.js +0 -0
- package/dist/runtime/types/index.d.ts +30 -0
- package/dist/runtime/types/index.js +30 -0
- package/dist/runtime/types/seo.d.ts +4 -0
- package/dist/runtime/types/seo.js +0 -0
- package/dist/runtime/utils/auth.d.ts +2 -0
- package/dist/runtime/utils/auth.js +5 -0
- package/dist/runtime/utils/date.d.ts +5 -0
- package/dist/runtime/utils/date.js +15 -0
- package/dist/runtime/utils/formatters.d.ts +5 -0
- package/dist/runtime/utils/formatters.js +24 -0
- package/dist/runtime/utils/index.d.ts +4 -0
- package/dist/runtime/utils/index.js +4 -0
- package/dist/runtime/utils/slugify.d.ts +1 -0
- package/dist/runtime/utils/slugify.js +11 -0
- package/dist/types.d.mts +11 -0
- package/package.json +89 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ClientOnly>
|
|
3
|
+
<USelectMenu
|
|
4
|
+
v-model:search-term="searchTerm"
|
|
5
|
+
v-model:open="isOpen"
|
|
6
|
+
:model-value="modelValue"
|
|
7
|
+
:items="items"
|
|
8
|
+
ignore-filter
|
|
9
|
+
:value-key="valueKey"
|
|
10
|
+
:label-key="labelKey"
|
|
11
|
+
:placeholder="placeholder"
|
|
12
|
+
:multiple="multiple"
|
|
13
|
+
:ui="{ viewport: viewportId }"
|
|
14
|
+
@update:model-value="$emit('update:modelValue', $event)"
|
|
15
|
+
>
|
|
16
|
+
<template v-if="props.multiple ? modelValue?.length : modelValue">
|
|
17
|
+
<span class="truncate pointer-events-none">
|
|
18
|
+
{{ cachedLabel }}
|
|
19
|
+
</span>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<template v-if="slots['item-label']" #item-label="{ item }">
|
|
23
|
+
<slot name="item-label" :item="item" />
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<template #trailing>
|
|
27
|
+
<UIcon v-if="isLoading" :name="appConfig.ui.icons.loading" class="shrink-0 text-dimmed size-5 animate-spin" />
|
|
28
|
+
<template v-else>
|
|
29
|
+
<UButton
|
|
30
|
+
v-if="props.multiple ? modelValue?.length : modelValue"
|
|
31
|
+
:icon="appConfig.ui.icons.close"
|
|
32
|
+
variant="link"
|
|
33
|
+
size="sm"
|
|
34
|
+
color="neutral"
|
|
35
|
+
class="px-0"
|
|
36
|
+
@click="$emit('update:modelValue', void 0)"
|
|
37
|
+
/>
|
|
38
|
+
</template>
|
|
39
|
+
</template>
|
|
40
|
+
</USelectMenu>
|
|
41
|
+
|
|
42
|
+
<template #placeholder>
|
|
43
|
+
<USkeleton class="w-full h-8" />
|
|
44
|
+
</template>
|
|
45
|
+
</ClientOnly>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<script>
|
|
49
|
+
import { useAppConfig, useAsyncData, useNuxtData } from "#imports";
|
|
50
|
+
import { refDebounced, useInfiniteScroll, useOffsetPagination } from "@vueuse/core";
|
|
51
|
+
import { computed, ref, shallowRef, toRaw, triggerRef, useId, watch } from "vue";
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<script setup>
|
|
55
|
+
const props = defineProps({
|
|
56
|
+
modelValue: { type: null, required: false },
|
|
57
|
+
cacheKey: { type: String, required: true },
|
|
58
|
+
handler: { type: Function, required: true },
|
|
59
|
+
valueKey: { type: null, required: false, default: "id" },
|
|
60
|
+
labelKey: { type: null, required: false, default: "name" },
|
|
61
|
+
multiple: { type: Boolean, required: false },
|
|
62
|
+
placeholder: { type: String, required: false },
|
|
63
|
+
initSelected: { type: Boolean, required: false }
|
|
64
|
+
});
|
|
65
|
+
defineEmits(["update:modelValue"]);
|
|
66
|
+
const slots = defineSlots();
|
|
67
|
+
const appConfig = useAppConfig();
|
|
68
|
+
const autocompleteSelectKey = `autocomplete-select:${props.cacheKey}`;
|
|
69
|
+
const autocompleteSelectId = `${autocompleteSelectKey}:${useId()}`;
|
|
70
|
+
const viewportId = `autocomplete-select-viewport-${useId()}`;
|
|
71
|
+
const {
|
|
72
|
+
initialPagination,
|
|
73
|
+
initialData,
|
|
74
|
+
initialStatus,
|
|
75
|
+
initSelected,
|
|
76
|
+
initSelectedStatus
|
|
77
|
+
} = useInitialData();
|
|
78
|
+
const { fetchPage, nextPage, isLastPage, pageDataStatus, allPagesData } = usePageData({
|
|
79
|
+
pagination: initialPagination,
|
|
80
|
+
total: () => initialData.value?.pagination.total ?? 0
|
|
81
|
+
});
|
|
82
|
+
const { searchTerm, searchData, searchStatus } = useSearch({ pagination: initialPagination });
|
|
83
|
+
const { isOpen } = useInfiniteScrollData({ nextPage, isLastPage, fetchPage, searchTerm });
|
|
84
|
+
const isLoading = computed(() => [
|
|
85
|
+
initialStatus.value,
|
|
86
|
+
pageDataStatus.value,
|
|
87
|
+
searchStatus.value,
|
|
88
|
+
initSelectedStatus.value
|
|
89
|
+
].includes("pending"));
|
|
90
|
+
const items = computed(() => {
|
|
91
|
+
if (searchTerm.value) {
|
|
92
|
+
return searchData.value?.items ?? [];
|
|
93
|
+
}
|
|
94
|
+
return [
|
|
95
|
+
...initialData.value?.items ?? [],
|
|
96
|
+
...allPagesData.value
|
|
97
|
+
];
|
|
98
|
+
});
|
|
99
|
+
const { cachedLabel } = useAutocompleteCache({ items, initSelected });
|
|
100
|
+
function useInitialData() {
|
|
101
|
+
const initialPagination2 = { page: "1", perPage: "25" };
|
|
102
|
+
const { data: initialData2, status: initialStatus2 } = useAsyncData(
|
|
103
|
+
autocompleteSelectKey,
|
|
104
|
+
() => props.handler({ ...initialPagination2, search: "" }),
|
|
105
|
+
{
|
|
106
|
+
lazy: true,
|
|
107
|
+
getCachedData: (key) => useNuxtData(key).data.value,
|
|
108
|
+
dedupe: "defer"
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
const { data: initSelected2, status: initSelectedStatus2 } = useAsyncData(
|
|
112
|
+
`${autocompleteSelectId}:initial-value`,
|
|
113
|
+
async () => {
|
|
114
|
+
const result = await props.handler({
|
|
115
|
+
...initialPagination2,
|
|
116
|
+
search: "",
|
|
117
|
+
ids: Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]
|
|
118
|
+
});
|
|
119
|
+
return result.items;
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
lazy: true,
|
|
123
|
+
immediate: props.initSelected && (Array.isArray(props.modelValue) ? props.modelValue.length > 0 : !!props.modelValue),
|
|
124
|
+
default: () => []
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
return {
|
|
128
|
+
initialPagination: initialPagination2,
|
|
129
|
+
initialData: initialData2,
|
|
130
|
+
initialStatus: initialStatus2,
|
|
131
|
+
initSelected: initSelected2,
|
|
132
|
+
initSelectedStatus: initSelectedStatus2
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function usePageData(options) {
|
|
136
|
+
const { currentPage, currentPageSize, next, isLastPage: isLastPage2 } = useOffsetPagination({
|
|
137
|
+
total: options.total,
|
|
138
|
+
pageSize: Number(options.pagination.perPage),
|
|
139
|
+
page: Number(options.pagination.page)
|
|
140
|
+
});
|
|
141
|
+
const { execute: fetchPage2, data: pageData, status: pageDataStatus2 } = useAsyncData(
|
|
142
|
+
`${autocompleteSelectId}:page-data`,
|
|
143
|
+
() => {
|
|
144
|
+
return props.handler({
|
|
145
|
+
page: currentPage.value.toString(),
|
|
146
|
+
perPage: currentPageSize.value.toString(),
|
|
147
|
+
search: ""
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
{ immediate: false }
|
|
151
|
+
);
|
|
152
|
+
const allPagesData2 = shallowRef([]);
|
|
153
|
+
watch(pageData, (value) => {
|
|
154
|
+
if (value?.items) {
|
|
155
|
+
allPagesData2.value.push(...value.items);
|
|
156
|
+
triggerRef(allPagesData2);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return { fetchPage: fetchPage2, pageData, nextPage: next, isLastPage: isLastPage2, pageDataStatus: pageDataStatus2, allPagesData: allPagesData2 };
|
|
160
|
+
}
|
|
161
|
+
function useInfiniteScrollData(options) {
|
|
162
|
+
const isOpen2 = ref(false);
|
|
163
|
+
const contentDiv = shallowRef(null);
|
|
164
|
+
watch(isOpen2, (value) => {
|
|
165
|
+
if (value) {
|
|
166
|
+
contentDiv.value = document.querySelector(`.${viewportId}`) ?? null;
|
|
167
|
+
}
|
|
168
|
+
}, { flush: "post" });
|
|
169
|
+
useInfiniteScroll(contentDiv, () => {
|
|
170
|
+
options.nextPage();
|
|
171
|
+
return fetchPage();
|
|
172
|
+
}, { distance: 10, canLoadMore: () => !searchTerm.value && !isLastPage.value });
|
|
173
|
+
return { isOpen: isOpen2 };
|
|
174
|
+
}
|
|
175
|
+
function useSearch(options) {
|
|
176
|
+
const searchKey = `${autocompleteSelectId}:search`;
|
|
177
|
+
const searchTerm2 = ref("");
|
|
178
|
+
const searchTermDebounced = refDebounced(searchTerm2, 500);
|
|
179
|
+
const { data: searchData2, status: searchStatus2, execute: search } = useAsyncData(searchKey, (_, { signal }) => {
|
|
180
|
+
return props.handler({
|
|
181
|
+
...options.pagination,
|
|
182
|
+
search: searchTermDebounced.value
|
|
183
|
+
}, signal);
|
|
184
|
+
}, { lazy: true, immediate: false });
|
|
185
|
+
watch(searchTermDebounced, (value) => {
|
|
186
|
+
value && search();
|
|
187
|
+
});
|
|
188
|
+
return { searchData: searchData2, searchStatus: searchStatus2, searchTerm: searchTerm2 };
|
|
189
|
+
}
|
|
190
|
+
function useAutocompleteCache(options) {
|
|
191
|
+
const selectedItemCache = shallowRef(/* @__PURE__ */ new Map());
|
|
192
|
+
const updateCache = (value) => {
|
|
193
|
+
if (!value || selectedItemCache.value.has(value)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const item = options.initSelected.value.find((item2) => item2[props.valueKey] === value) || options.items.value.find((item2) => item2[props.valueKey] === value);
|
|
197
|
+
if (item) {
|
|
198
|
+
selectedItemCache.value.set(value, structuredClone(toRaw(item)));
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
watch(
|
|
202
|
+
() => [props.modelValue, options.items.value, options.initSelected.value],
|
|
203
|
+
([value]) => {
|
|
204
|
+
const cacheSize = selectedItemCache.value.size;
|
|
205
|
+
if (Array.isArray(value)) {
|
|
206
|
+
value.forEach(updateCache);
|
|
207
|
+
} else {
|
|
208
|
+
updateCache(value);
|
|
209
|
+
}
|
|
210
|
+
cacheSize !== selectedItemCache.value.size && triggerRef(selectedItemCache);
|
|
211
|
+
},
|
|
212
|
+
{ immediate: true }
|
|
213
|
+
);
|
|
214
|
+
const getCachedLabel = (value) => {
|
|
215
|
+
if (Array.isArray(value)) {
|
|
216
|
+
return value.map(getCachedLabel).join(", ");
|
|
217
|
+
}
|
|
218
|
+
return selectedItemCache.value.get(value)?.[props.labelKey] ?? value;
|
|
219
|
+
};
|
|
220
|
+
const cachedLabel2 = computed(() => {
|
|
221
|
+
return props.modelValue && getCachedLabel(props.modelValue);
|
|
222
|
+
});
|
|
223
|
+
return { selectedItemCache, getCachedLabel, cachedLabel: cachedLabel2 };
|
|
224
|
+
}
|
|
225
|
+
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Pagination, PaginationQueryRaw } from '@hywax/cms-runtime';
|
|
2
|
+
import type { InputMenuItem } from '@nuxt/ui';
|
|
3
|
+
type PaginationQuery = Required<PaginationQueryRaw>;
|
|
4
|
+
export type AutocompleteSelectItem = Extract<InputMenuItem, object> & {
|
|
5
|
+
id?: string | number;
|
|
6
|
+
name?: string;
|
|
7
|
+
};
|
|
8
|
+
type GetModelValue<T extends AutocompleteSelectItem, VK extends keyof T, M extends boolean> = M extends true ? (T[VK][] | undefined) : (T[VK] | undefined);
|
|
9
|
+
export type HandlerParams = PaginationQuery & {
|
|
10
|
+
search: string;
|
|
11
|
+
ids?: string[] | number[];
|
|
12
|
+
};
|
|
13
|
+
export type Handler<T extends AutocompleteSelectItem = AutocompleteSelectItem> = (params: HandlerParams, signal?: AbortSignal) => Promise<{
|
|
14
|
+
items: T[];
|
|
15
|
+
pagination: Pagination;
|
|
16
|
+
}>;
|
|
17
|
+
export interface AutocompleteSelectProps<T extends AutocompleteSelectItem = AutocompleteSelectItem, VK extends keyof T = 'id', M extends boolean = false> {
|
|
18
|
+
modelValue?: GetModelValue<T, VK, M>;
|
|
19
|
+
cacheKey: string;
|
|
20
|
+
handler: Handler<T>;
|
|
21
|
+
/** @defaultValue 'id' */
|
|
22
|
+
valueKey?: VK;
|
|
23
|
+
/** @defaultValue 'name' */
|
|
24
|
+
labelKey?: keyof T;
|
|
25
|
+
multiple?: M & boolean;
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
initSelected?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface AutocompleteSelectEmits<T extends AutocompleteSelectItem = AutocompleteSelectItem, VK extends keyof T = 'id', M extends boolean = false> {
|
|
30
|
+
'update:modelValue': [payload: GetModelValue<T, VK, M>];
|
|
31
|
+
}
|
|
32
|
+
export interface Slots<T extends AutocompleteSelectItem = AutocompleteSelectItem> {
|
|
33
|
+
'item-label': (props: {
|
|
34
|
+
item: T;
|
|
35
|
+
}) => any;
|
|
36
|
+
}
|
|
37
|
+
declare const _default: typeof __VLS_export;
|
|
38
|
+
export default _default;
|
|
39
|
+
declare const __VLS_export: <T extends AutocompleteSelectItem, VK extends keyof T = "id", M extends boolean = false>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
40
|
+
props: import("vue").PublicProps & __VLS_PrettifyLocal<AutocompleteSelectProps<T, VK, M> & {
|
|
41
|
+
"onUpdate:modelValue"?: ((payload: GetModelValue<T, VK, M>) => any) | undefined;
|
|
42
|
+
}> & (typeof globalThis extends {
|
|
43
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
44
|
+
} ? P : {});
|
|
45
|
+
expose: (exposed: {}) => void;
|
|
46
|
+
attrs: any;
|
|
47
|
+
slots: Slots<T>;
|
|
48
|
+
emit: (evt: "update:modelValue", payload: GetModelValue<T, VK, M>) => void;
|
|
49
|
+
}>) => import("vue").VNode & {
|
|
50
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
51
|
+
};
|
|
52
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
53
|
+
[K in keyof T]: T[K];
|
|
54
|
+
} : {
|
|
55
|
+
[K in keyof T as K]: T[K];
|
|
56
|
+
}) & {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ComponentConfig } from '@hywax/cms-runtime';
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
3
|
+
import type { ButtonProps } from '@nuxt/ui';
|
|
4
|
+
import type { RouteLocationRaw } from 'vue-router';
|
|
5
|
+
import theme from '#build/cms-console/button-copy-text';
|
|
6
|
+
type ButtonCopyText = ComponentConfig<typeof theme, AppConfig, 'buttonCopyText'>;
|
|
7
|
+
export interface ButtonCopyTextProps extends Pick<ButtonProps, 'target' | 'external' | 'label'> {
|
|
8
|
+
text?: string | number | null;
|
|
9
|
+
showAction?: boolean;
|
|
10
|
+
alwaysShowTooltip?: boolean;
|
|
11
|
+
to?: RouteLocationRaw;
|
|
12
|
+
class?: any;
|
|
13
|
+
ui?: ButtonCopyText['slots'];
|
|
14
|
+
}
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ButtonCopyTextProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ButtonCopyTextProps> & Readonly<{}>, {
|
|
18
|
+
showAction: boolean;
|
|
19
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
20
|
+
default?: (props: {}) => any;
|
|
21
|
+
} & {
|
|
22
|
+
default?: (props: {}) => any;
|
|
23
|
+
}>;
|
|
24
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
25
|
+
new (): {
|
|
26
|
+
$slots: S;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="textValue" ref="button-copy-text" :class="ui.root({ class: [props.class, props.ui?.root] })">
|
|
3
|
+
<UButton
|
|
4
|
+
v-if="to"
|
|
5
|
+
:to="to"
|
|
6
|
+
:class="ui.text({ class: props.ui?.text })"
|
|
7
|
+
:external="external"
|
|
8
|
+
:target="target"
|
|
9
|
+
variant="link"
|
|
10
|
+
color="info"
|
|
11
|
+
>
|
|
12
|
+
<slot>{{ textValue }}</slot>
|
|
13
|
+
</UButton>
|
|
14
|
+
<span v-else :class="ui.text({ class: props.ui?.text })">
|
|
15
|
+
<slot>{{ textValue }}</slot>
|
|
16
|
+
</span>
|
|
17
|
+
|
|
18
|
+
<UTooltip
|
|
19
|
+
v-if="showAction"
|
|
20
|
+
:text="tooltipText"
|
|
21
|
+
:content="{ side: 'top' }"
|
|
22
|
+
disable-hoverable-content
|
|
23
|
+
disable-closing-trigger
|
|
24
|
+
>
|
|
25
|
+
<UButton
|
|
26
|
+
:class="ui.button({ class: props.ui?.button })"
|
|
27
|
+
:icon="copied ? appConfig.ui.icons.check : appConfig.ui.icons.copy"
|
|
28
|
+
variant="link"
|
|
29
|
+
size="sm"
|
|
30
|
+
:color="copied ? 'success' : 'neutral'"
|
|
31
|
+
@click="copy(textValue)"
|
|
32
|
+
/>
|
|
33
|
+
</UTooltip>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script>
|
|
38
|
+
import theme from "#build/cms-console/button-copy-text";
|
|
39
|
+
import { useAppConfig } from "#imports";
|
|
40
|
+
import { useClipboard, useElementHover } from "@vueuse/core";
|
|
41
|
+
import { computed, useTemplateRef } from "vue";
|
|
42
|
+
import { tv } from "../tv";
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<script setup>
|
|
46
|
+
const props = defineProps({
|
|
47
|
+
text: { type: [String, Number, null], required: false },
|
|
48
|
+
showAction: { type: Boolean, required: false, default: true },
|
|
49
|
+
alwaysShowTooltip: { type: Boolean, required: false },
|
|
50
|
+
to: { type: null, required: false },
|
|
51
|
+
class: { type: null, required: false },
|
|
52
|
+
ui: { type: null, required: false },
|
|
53
|
+
target: { type: [String, Object, null], required: false },
|
|
54
|
+
external: { type: Boolean, required: false },
|
|
55
|
+
label: { type: String, required: false }
|
|
56
|
+
});
|
|
57
|
+
const appConfig = useAppConfig();
|
|
58
|
+
const { copy, copied } = useClipboard();
|
|
59
|
+
const tooltipText = computed(() => copied.value ? "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u043E" : "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C");
|
|
60
|
+
const copyTextRef = useTemplateRef("button-copy-text");
|
|
61
|
+
const isHovered = useElementHover(copyTextRef);
|
|
62
|
+
const textValue = computed(() => {
|
|
63
|
+
const text = props.label ?? props.text;
|
|
64
|
+
return typeof text === "number" ? text.toString() : text;
|
|
65
|
+
});
|
|
66
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.buttonCopyText || {} })({
|
|
67
|
+
buttonInvisible: !isHovered.value && !props.alwaysShowTooltip,
|
|
68
|
+
to: !!props.to
|
|
69
|
+
}));
|
|
70
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ComponentConfig } from '@hywax/cms-runtime';
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
3
|
+
import type { ButtonProps } from '@nuxt/ui';
|
|
4
|
+
import type { RouteLocationRaw } from 'vue-router';
|
|
5
|
+
import theme from '#build/cms-console/button-copy-text';
|
|
6
|
+
type ButtonCopyText = ComponentConfig<typeof theme, AppConfig, 'buttonCopyText'>;
|
|
7
|
+
export interface ButtonCopyTextProps extends Pick<ButtonProps, 'target' | 'external' | 'label'> {
|
|
8
|
+
text?: string | number | null;
|
|
9
|
+
showAction?: boolean;
|
|
10
|
+
alwaysShowTooltip?: boolean;
|
|
11
|
+
to?: RouteLocationRaw;
|
|
12
|
+
class?: any;
|
|
13
|
+
ui?: ButtonCopyText['slots'];
|
|
14
|
+
}
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ButtonCopyTextProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ButtonCopyTextProps> & Readonly<{}>, {
|
|
18
|
+
showAction: boolean;
|
|
19
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
20
|
+
default?: (props: {}) => any;
|
|
21
|
+
} & {
|
|
22
|
+
default?: (props: {}) => any;
|
|
23
|
+
}>;
|
|
24
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
25
|
+
new (): {
|
|
26
|
+
$slots: S;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ComponentConfig } from '@hywax/cms-runtime';
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
3
|
+
import type { ButtonProps, ModalProps } from '@nuxt/ui';
|
|
4
|
+
import type { ComponentProps } from 'vue-component-type-helpers';
|
|
5
|
+
import type { ModalConfirmEmits, ModalConfirmProps } from './ModalConfirm.vue';
|
|
6
|
+
import theme from '#build/cms-console/button-delete-confirm';
|
|
7
|
+
import ModalConfirm from './ModalConfirm.vue';
|
|
8
|
+
type ButtonDelete = ComponentConfig<typeof theme, AppConfig, 'buttonDelete'>;
|
|
9
|
+
export interface ButtonDeleteProps extends Pick<ModalConfirmProps, 'onConfirm'> {
|
|
10
|
+
modalProps?: Omit<ModalProps & ComponentProps<typeof ModalConfirm>, 'title' | 'message' | 'onConfirm' | 'confirmButton'>;
|
|
11
|
+
confirmText?: string;
|
|
12
|
+
confirmLabel?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
message?: string;
|
|
15
|
+
tooltipText?: string;
|
|
16
|
+
color?: ButtonProps['color'];
|
|
17
|
+
variant?: ButtonProps['variant'];
|
|
18
|
+
icon?: ButtonProps['icon'];
|
|
19
|
+
size?: ButtonProps['size'];
|
|
20
|
+
label?: ButtonProps['label'];
|
|
21
|
+
class?: any;
|
|
22
|
+
ui?: ButtonDelete['slots'];
|
|
23
|
+
}
|
|
24
|
+
export interface ButtonDeleteEmits extends ModalConfirmEmits {
|
|
25
|
+
}
|
|
26
|
+
declare const _default: typeof __VLS_export;
|
|
27
|
+
export default _default;
|
|
28
|
+
declare const __VLS_export: import("vue").DefineComponent<ButtonDeleteProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
29
|
+
close: () => any;
|
|
30
|
+
confirm: () => any;
|
|
31
|
+
}, string, import("vue").PublicProps, Readonly<ButtonDeleteProps> & Readonly<{
|
|
32
|
+
onClose?: (() => any) | undefined;
|
|
33
|
+
onConfirm?: (() => any) | undefined;
|
|
34
|
+
}>, {
|
|
35
|
+
color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
|
|
36
|
+
label: string;
|
|
37
|
+
confirmLabel: string;
|
|
38
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UTooltip
|
|
3
|
+
:text="tooltipText"
|
|
4
|
+
:content="{ side: 'top' }"
|
|
5
|
+
:disabled="!tooltipText"
|
|
6
|
+
disable-hoverable-content
|
|
7
|
+
disable-closing-trigger
|
|
8
|
+
>
|
|
9
|
+
<UButton
|
|
10
|
+
:color="color"
|
|
11
|
+
:variant="variant"
|
|
12
|
+
:size="size"
|
|
13
|
+
:icon="icon"
|
|
14
|
+
:label="label === '' ? void 0 : label"
|
|
15
|
+
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
16
|
+
auto-loading
|
|
17
|
+
@click="handleDeleteClick()"
|
|
18
|
+
/>
|
|
19
|
+
</UTooltip>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script>
|
|
23
|
+
import theme from "#build/cms-console/button-delete-confirm";
|
|
24
|
+
import { computed, useAppConfig, useOverlay } from "#imports";
|
|
25
|
+
import { tv } from "../tv";
|
|
26
|
+
import ModalConfirm from "./ModalConfirm.vue";
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<script setup>
|
|
30
|
+
const props = defineProps({
|
|
31
|
+
modalProps: { type: Object, required: false },
|
|
32
|
+
confirmText: { type: String, required: false },
|
|
33
|
+
confirmLabel: { type: String, required: false, default: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" },
|
|
34
|
+
title: { type: String, required: false },
|
|
35
|
+
message: { type: String, required: false },
|
|
36
|
+
tooltipText: { type: String, required: false },
|
|
37
|
+
color: { type: null, required: false, default: "error" },
|
|
38
|
+
variant: { type: null, required: false },
|
|
39
|
+
icon: { type: null, required: false },
|
|
40
|
+
size: { type: null, required: false },
|
|
41
|
+
label: { type: String, required: false, default: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" },
|
|
42
|
+
class: { type: null, required: false },
|
|
43
|
+
ui: { type: null, required: false },
|
|
44
|
+
onConfirm: { type: Function, required: false }
|
|
45
|
+
});
|
|
46
|
+
defineEmits(["confirm", "close"]);
|
|
47
|
+
const appConfig = useAppConfig();
|
|
48
|
+
const modal = useOverlay().create(ModalConfirm);
|
|
49
|
+
function handleDeleteClick() {
|
|
50
|
+
return modal.open({
|
|
51
|
+
...props.modalProps,
|
|
52
|
+
title: props.title ?? "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435",
|
|
53
|
+
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?",
|
|
54
|
+
color: "error",
|
|
55
|
+
variant: props.variant,
|
|
56
|
+
confirmLabel: props.confirmLabel,
|
|
57
|
+
confirmText: props.confirmText,
|
|
58
|
+
onConfirm: props.onConfirm
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.buttonDelete || {} })());
|
|
62
|
+
</script>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ComponentConfig } from '@hywax/cms-runtime';
|
|
2
|
+
import type { AppConfig } from '@nuxt/schema';
|
|
3
|
+
import type { ButtonProps, ModalProps } from '@nuxt/ui';
|
|
4
|
+
import type { ComponentProps } from 'vue-component-type-helpers';
|
|
5
|
+
import type { ModalConfirmEmits, ModalConfirmProps } from './ModalConfirm.vue';
|
|
6
|
+
import theme from '#build/cms-console/button-delete-confirm';
|
|
7
|
+
import ModalConfirm from './ModalConfirm.vue';
|
|
8
|
+
type ButtonDelete = ComponentConfig<typeof theme, AppConfig, 'buttonDelete'>;
|
|
9
|
+
export interface ButtonDeleteProps extends Pick<ModalConfirmProps, 'onConfirm'> {
|
|
10
|
+
modalProps?: Omit<ModalProps & ComponentProps<typeof ModalConfirm>, 'title' | 'message' | 'onConfirm' | 'confirmButton'>;
|
|
11
|
+
confirmText?: string;
|
|
12
|
+
confirmLabel?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
message?: string;
|
|
15
|
+
tooltipText?: string;
|
|
16
|
+
color?: ButtonProps['color'];
|
|
17
|
+
variant?: ButtonProps['variant'];
|
|
18
|
+
icon?: ButtonProps['icon'];
|
|
19
|
+
size?: ButtonProps['size'];
|
|
20
|
+
label?: ButtonProps['label'];
|
|
21
|
+
class?: any;
|
|
22
|
+
ui?: ButtonDelete['slots'];
|
|
23
|
+
}
|
|
24
|
+
export interface ButtonDeleteEmits extends ModalConfirmEmits {
|
|
25
|
+
}
|
|
26
|
+
declare const _default: typeof __VLS_export;
|
|
27
|
+
export default _default;
|
|
28
|
+
declare const __VLS_export: import("vue").DefineComponent<ButtonDeleteProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
29
|
+
close: () => any;
|
|
30
|
+
confirm: () => any;
|
|
31
|
+
}, string, import("vue").PublicProps, Readonly<ButtonDeleteProps> & Readonly<{
|
|
32
|
+
onClose?: (() => any) | undefined;
|
|
33
|
+
onConfirm?: (() => any) | undefined;
|
|
34
|
+
}>, {
|
|
35
|
+
color: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
|
|
36
|
+
label: string;
|
|
37
|
+
confirmLabel: string;
|
|
38
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date';
|
|
2
|
+
import type { CalendarProps } from '@nuxt/ui';
|
|
3
|
+
import type { DateRange as CalendarDateRange } from 'reka-ui';
|
|
4
|
+
import type { DateRange, DateType } from '../types';
|
|
5
|
+
export type CalendarValue = DateValue | CalendarDateRange;
|
|
6
|
+
export type ModelValue<R extends boolean> = (R extends true ? DateRange : DateType) | undefined;
|
|
7
|
+
export interface DatePickerProps<R extends boolean> extends Omit<CalendarProps<R, false>, 'modelValue' | 'multiple' | 'minValue' | 'maxValue'> {
|
|
8
|
+
modelValue: ModelValue<R>;
|
|
9
|
+
id?: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
withTime?: boolean;
|
|
12
|
+
minValue?: DateType;
|
|
13
|
+
maxValue?: DateType;
|
|
14
|
+
}
|
|
15
|
+
export interface DatePickerEmits<R extends boolean> {
|
|
16
|
+
'update:modelValue': [value: ModelValue<R>];
|
|
17
|
+
'change': [event: Event];
|
|
18
|
+
'blur': [event: FocusEvent];
|
|
19
|
+
'focus': [event: FocusEvent];
|
|
20
|
+
}
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|
|
23
|
+
declare const __VLS_export: <R extends boolean = false>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
24
|
+
props: import("vue").PublicProps & __VLS_PrettifyLocal<DatePickerProps<R> & {
|
|
25
|
+
onBlur?: ((event: FocusEvent) => any) | undefined;
|
|
26
|
+
onChange?: ((event: Event) => any) | undefined;
|
|
27
|
+
onFocus?: ((event: FocusEvent) => any) | undefined;
|
|
28
|
+
"onUpdate:modelValue"?: ((value: ModelValue<R>) => any) | undefined;
|
|
29
|
+
}> & (typeof globalThis extends {
|
|
30
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
31
|
+
} ? P : {});
|
|
32
|
+
expose: (exposed: {}) => void;
|
|
33
|
+
attrs: any;
|
|
34
|
+
slots: {};
|
|
35
|
+
emit: ((evt: "blur", event: FocusEvent) => void) & ((evt: "change", event: Event) => void) & ((evt: "focus", event: FocusEvent) => void) & ((evt: "update:modelValue", value: ModelValue<R>) => void);
|
|
36
|
+
}>) => import("vue").VNode & {
|
|
37
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
38
|
+
};
|
|
39
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
40
|
+
[K in keyof T]: T[K];
|
|
41
|
+
} : {
|
|
42
|
+
[K in keyof T as K]: T[K];
|
|
43
|
+
}) & {};
|