@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.
Files changed (122) hide show
  1. package/.nuxt/cms-console/button-copy-text.ts +19 -0
  2. package/.nuxt/cms-console/button-delete-confirm.ts +5 -0
  3. package/.nuxt/cms-console/editor/index.ts +0 -0
  4. package/.nuxt/cms-console/form-panel-aside-section.ts +9 -0
  5. package/.nuxt/cms-console/form-panel-section.ts +8 -0
  6. package/.nuxt/cms-console/form-panel.ts +15 -0
  7. package/.nuxt/cms-console/index.ts +11 -0
  8. package/.nuxt/cms-console/input-seo.ts +5 -0
  9. package/.nuxt/cms-console/input-slug.ts +5 -0
  10. package/.nuxt/cms-console/input-uplora-image.ts +27 -0
  11. package/.nuxt/cms-console/modal-confirm.ts +5 -0
  12. package/.nuxt/cms-console/table-panel.ts +8 -0
  13. package/.nuxt/cms-console/table-search-input.ts +6 -0
  14. package/.nuxt/cms-console.css +31 -0
  15. package/dist/module.d.mts +11 -0
  16. package/dist/module.json +9 -0
  17. package/dist/module.mjs +387 -0
  18. package/dist/runtime/components/AutocompleteSelect.d.vue.ts +56 -0
  19. package/dist/runtime/components/AutocompleteSelect.vue +225 -0
  20. package/dist/runtime/components/AutocompleteSelect.vue.d.ts +56 -0
  21. package/dist/runtime/components/ButtonCopyText.d.vue.ts +28 -0
  22. package/dist/runtime/components/ButtonCopyText.vue +70 -0
  23. package/dist/runtime/components/ButtonCopyText.vue.d.ts +28 -0
  24. package/dist/runtime/components/ButtonDeleteConfirm.d.vue.ts +38 -0
  25. package/dist/runtime/components/ButtonDeleteConfirm.vue +62 -0
  26. package/dist/runtime/components/ButtonDeleteConfirm.vue.d.ts +38 -0
  27. package/dist/runtime/components/DatePicker.d.vue.ts +43 -0
  28. package/dist/runtime/components/DatePicker.vue +232 -0
  29. package/dist/runtime/components/DatePicker.vue.d.ts +43 -0
  30. package/dist/runtime/components/EditorFull.d.vue.ts +13 -0
  31. package/dist/runtime/components/EditorFull.vue +139 -0
  32. package/dist/runtime/components/EditorFull.vue.d.ts +13 -0
  33. package/dist/runtime/components/EditorLinkPopover.d.vue.ts +8 -0
  34. package/dist/runtime/components/EditorLinkPopover.vue +137 -0
  35. package/dist/runtime/components/EditorLinkPopover.vue.d.ts +8 -0
  36. package/dist/runtime/components/FormPanel.d.vue.ts +47 -0
  37. package/dist/runtime/components/FormPanel.vue +73 -0
  38. package/dist/runtime/components/FormPanel.vue.d.ts +47 -0
  39. package/dist/runtime/components/FormPanelAsideSection.d.vue.ts +24 -0
  40. package/dist/runtime/components/FormPanelAsideSection.vue +41 -0
  41. package/dist/runtime/components/FormPanelAsideSection.vue.d.ts +24 -0
  42. package/dist/runtime/components/FormPanelSection.d.vue.ts +21 -0
  43. package/dist/runtime/components/FormPanelSection.vue +31 -0
  44. package/dist/runtime/components/FormPanelSection.vue.d.ts +21 -0
  45. package/dist/runtime/components/InputSeo.d.vue.ts +21 -0
  46. package/dist/runtime/components/InputSeo.vue +73 -0
  47. package/dist/runtime/components/InputSeo.vue.d.ts +21 -0
  48. package/dist/runtime/components/InputSlug.d.vue.ts +30 -0
  49. package/dist/runtime/components/InputSlug.vue +70 -0
  50. package/dist/runtime/components/InputSlug.vue.d.ts +30 -0
  51. package/dist/runtime/components/InputUploraImage.d.vue.ts +39 -0
  52. package/dist/runtime/components/InputUploraImage.vue +163 -0
  53. package/dist/runtime/components/InputUploraImage.vue.d.ts +39 -0
  54. package/dist/runtime/components/Layout.d.vue.ts +30 -0
  55. package/dist/runtime/components/Layout.vue +82 -0
  56. package/dist/runtime/components/Layout.vue.d.ts +30 -0
  57. package/dist/runtime/components/ModalConfirm.d.vue.ts +33 -0
  58. package/dist/runtime/components/ModalConfirm.vue +97 -0
  59. package/dist/runtime/components/ModalConfirm.vue.d.ts +33 -0
  60. package/dist/runtime/components/TableColumnSorting.d.vue.ts +17 -0
  61. package/dist/runtime/components/TableColumnSorting.vue +81 -0
  62. package/dist/runtime/components/TableColumnSorting.vue.d.ts +17 -0
  63. package/dist/runtime/components/TableColumnVisibility.d.vue.ts +24 -0
  64. package/dist/runtime/components/TableColumnVisibility.vue +110 -0
  65. package/dist/runtime/components/TableColumnVisibility.vue.d.ts +24 -0
  66. package/dist/runtime/components/TableFilters.d.vue.ts +90 -0
  67. package/dist/runtime/components/TableFilters.vue +199 -0
  68. package/dist/runtime/components/TableFilters.vue.d.ts +90 -0
  69. package/dist/runtime/components/TablePanel.d.vue.ts +95 -0
  70. package/dist/runtime/components/TablePanel.vue +297 -0
  71. package/dist/runtime/components/TablePanel.vue.d.ts +95 -0
  72. package/dist/runtime/components/TableSearchInput.d.vue.ts +33 -0
  73. package/dist/runtime/components/TableSearchInput.vue +97 -0
  74. package/dist/runtime/components/TableSearchInput.vue.d.ts +33 -0
  75. package/dist/runtime/composables/useAdmin.d.ts +6 -0
  76. package/dist/runtime/composables/useAdmin.js +14 -0
  77. package/dist/runtime/composables/useEditorDragHandle.d.ts +17 -0
  78. package/dist/runtime/composables/useEditorDragHandle.js +95 -0
  79. package/dist/runtime/composables/useEditorSuggestions.d.ts +74 -0
  80. package/dist/runtime/composables/useEditorSuggestions.js +25 -0
  81. package/dist/runtime/composables/useEditorToolbar.d.ts +121 -0
  82. package/dist/runtime/composables/useEditorToolbar.js +87 -0
  83. package/dist/runtime/composables/useQueryState.d.ts +28 -0
  84. package/dist/runtime/composables/useQueryState.js +105 -0
  85. package/dist/runtime/composables/useRouteQuery.d.ts +37 -0
  86. package/dist/runtime/composables/useRouteQuery.js +81 -0
  87. package/dist/runtime/composables/useSeoStats.d.ts +12 -0
  88. package/dist/runtime/composables/useSeoStats.js +44 -0
  89. package/dist/runtime/composables/useTable.d.ts +25 -0
  90. package/dist/runtime/composables/useTable.js +84 -0
  91. package/dist/runtime/composables/useTableColumns.d.ts +28 -0
  92. package/dist/runtime/composables/useTableColumns.js +54 -0
  93. package/dist/runtime/editor/uplora-image/EditorUploraImage.d.ts +18 -0
  94. package/dist/runtime/editor/uplora-image/EditorUploraImage.js +42 -0
  95. package/dist/runtime/editor/uplora-image/EditorUploraImageNode.d.vue.ts +4 -0
  96. package/dist/runtime/editor/uplora-image/EditorUploraImageNode.vue +23 -0
  97. package/dist/runtime/editor/uplora-image/EditorUploraImageNode.vue.d.ts +4 -0
  98. package/dist/runtime/index.css +1 -0
  99. package/dist/runtime/server/tsconfig.json +3 -0
  100. package/dist/runtime/tv.d.ts +1 -0
  101. package/dist/runtime/tv.js +4 -0
  102. package/dist/runtime/types/app.config.d.ts +6 -0
  103. package/dist/runtime/types/date.d.ts +5 -0
  104. package/dist/runtime/types/date.js +0 -0
  105. package/dist/runtime/types/dictionaries.d.ts +1 -0
  106. package/dist/runtime/types/dictionaries.js +0 -0
  107. package/dist/runtime/types/index.d.ts +30 -0
  108. package/dist/runtime/types/index.js +30 -0
  109. package/dist/runtime/types/seo.d.ts +4 -0
  110. package/dist/runtime/types/seo.js +0 -0
  111. package/dist/runtime/utils/auth.d.ts +2 -0
  112. package/dist/runtime/utils/auth.js +5 -0
  113. package/dist/runtime/utils/date.d.ts +5 -0
  114. package/dist/runtime/utils/date.js +15 -0
  115. package/dist/runtime/utils/formatters.d.ts +5 -0
  116. package/dist/runtime/utils/formatters.js +24 -0
  117. package/dist/runtime/utils/index.d.ts +4 -0
  118. package/dist/runtime/utils/index.js +4 -0
  119. package/dist/runtime/utils/slugify.d.ts +1 -0
  120. package/dist/runtime/utils/slugify.js +11 -0
  121. package/dist/types.d.mts +11 -0
  122. package/package.json +89 -0
@@ -0,0 +1,297 @@
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
+ <TableColumnVisibility
20
+ v-model:visibility="columnVisibility"
21
+ v-model:order="columnOrder"
22
+ :table="tableRef?.tableApi"
23
+ :storage-key="storageKey"
24
+ />
25
+ <TableColumnSorting
26
+ :model-value="sorting"
27
+ :table="tableRef?.tableApi"
28
+ @update:model-value="emit('update:sorting', $event)"
29
+ />
30
+ <TableFilters
31
+ v-if="props.filtersSource"
32
+ :model-value="props.filters"
33
+ :schema="props.filtersSchema"
34
+ :source="props.filtersSource"
35
+ :fields="props.filtersFields"
36
+ @update:model-value="emit('update:filters', $event)"
37
+ @reset="emit('filtersReset', $event)"
38
+ @submit="emit('filtersSubmit', $event)"
39
+ >
40
+ <template
41
+ v-for="(filterSlot, pageTableSlot) in getFiltersSlots(slots)"
42
+ #[filterSlot]="slotData"
43
+ >
44
+ <slot :name="pageTableSlot" v-bind="slotData" />
45
+ </template>
46
+ </TableFilters>
47
+ </template>
48
+ </UDashboardToolbar>
49
+ </template>
50
+ <template #body>
51
+ <div v-show="status === 'pending'" :class="ui.loader({ class: props.ui?.loader })">
52
+ <UIcon :name="appConfig.ui.icons.loading" :class="ui.loaderIcon({ class: props.ui?.loaderIcon })" />
53
+ </div>
54
+
55
+ <UTable
56
+ ref="table"
57
+ v-model:column-visibility="columnVisibility"
58
+ v-model:column-order="columnOrder"
59
+ :class="ui.table({ class: props.ui?.table })"
60
+ :ui="{
61
+ base: 'table-fixed border-separate border-spacing-0',
62
+ thead: '[&>tr]:bg-elevated/50 [&>tr]:after:content-none',
63
+ tbody: '[&>tr]:last:[&>td]:border-b-0',
64
+ th: 'py-2 first:rounded-l-lg last:rounded-r-lg border-y border-default first:border-l last:border-r',
65
+ td: 'border-b border-default'
66
+ }"
67
+ :loading="status === 'pending'"
68
+ :row-selection="rowSelection"
69
+ :row-selection-options="rowSelectionOptions"
70
+ :column-pinning="columnPinningWrap"
71
+ :columns="tableColumns"
72
+ :data="data"
73
+ :sorting-options="{ manualSorting: hasPagination }"
74
+ :sorting="sorting"
75
+ :sticky="sticky"
76
+ :get-row-id="getRowId"
77
+ :grouping="grouping"
78
+ :grouping-options="groupingOptions"
79
+ :column-filters="columnFilters"
80
+ :empty="empty"
81
+ @select="onSelect"
82
+ @update:row-selection="emit('update:row-selection', $event)"
83
+ @update:grouping="emit('update:grouping', $event)"
84
+ >
85
+ <template v-for="(_, name) in slots" #[name]="slotData">
86
+ <slot :name="name" v-bind="slotData" />
87
+ </template>
88
+ </UTable>
89
+ </template>
90
+
91
+ <template v-if="hasPagination" #footer>
92
+ <div class="flex justify-between items-center py-3 px-4">
93
+ <div>
94
+ <span class="text-sm text-muted">
95
+ Всего: {{ total ?? 0 }}
96
+ </span>
97
+ </div>
98
+ <div class="flex items-center gap-2">
99
+ <USelect
100
+ :model-value="itemsPerPage"
101
+ :items="itemsPerPageItems"
102
+ :ui="{ base: 'text-muted' }"
103
+ variant="subtle"
104
+ @update:model-value="emit('update:items-per-page', $event)"
105
+ >
106
+ <template #default="{ modelValue }">
107
+ {{ modelValue }} / на страницу
108
+ </template>
109
+
110
+ <template #item="{ item }">
111
+ {{ item }}
112
+ </template>
113
+ </USelect>
114
+
115
+ <UPagination
116
+ v-bind="paginationProps"
117
+ :ui="isTotalUnknown ? { first: 'hidden', last: 'hidden' } : void 0"
118
+ variant="subtle"
119
+ :sibling-count="isTotalUnknown ? 3 : 1"
120
+ :show-edges="!isTotalUnknown"
121
+ @update:page="emit('update:page', $event)"
122
+ />
123
+ </div>
124
+ </div>
125
+ </template>
126
+ </UDashboardPanel>
127
+ </template>
128
+
129
+ <script>
130
+ import theme from "#build/cms-console/table-panel";
131
+ import { UButton, UCheckbox, UDropdownMenu, UTable } from "#components";
132
+ import { useAppConfig } from "#imports";
133
+ import { useOverlay } from "@nuxt/ui/composables/useOverlay";
134
+ import { getGroupedRowModel } from "@tanstack/vue-table";
135
+ import { reactivePick } from "@vueuse/core";
136
+ import { defu } from "defu";
137
+ import { useForwardProps } from "reka-ui";
138
+ import { computed, h, ref, useTemplateRef, watch } from "vue";
139
+ import { tv } from "../tv";
140
+ import CModalConfirm from "./ModalConfirm.vue";
141
+ import TableColumnSorting from "./TableColumnSorting.vue";
142
+ import TableColumnVisibility from "./TableColumnVisibility.vue";
143
+ import TableFilters from "./TableFilters.vue";
144
+ </script>
145
+
146
+ <script setup>
147
+ const props = defineProps({
148
+ title: { type: String, required: false },
149
+ status: { type: String, required: false },
150
+ page: { type: Number, required: false },
151
+ itemsPerPage: { type: Number, required: false },
152
+ total: { type: Number, required: false },
153
+ storageKey: { type: String, required: false },
154
+ columnVisibility: { type: Boolean, required: false, default: true },
155
+ defaultHiddenColumns: { type: Array, required: false },
156
+ sorting: { type: Array, required: false },
157
+ columns: { type: Array, required: false },
158
+ data: { type: Array, required: false },
159
+ sticky: { type: [Boolean, String], required: false, default: true },
160
+ columnPinning: { type: Object, required: false },
161
+ getRowId: { type: Function, required: false },
162
+ rowSelection: { type: Object, required: false },
163
+ rowSelectionOptions: { type: Object, required: false },
164
+ resetRowSelection: { type: Boolean, required: false, default: true },
165
+ grouping: { type: Array, required: false },
166
+ groupingOptions: { type: Object, required: false, default: () => ({ getGroupedRowModel: getGroupedRowModel(), groupedColumnMode: false }) },
167
+ hideSelectedFilters: { type: Boolean, required: false },
168
+ filters: { type: null, required: false },
169
+ filtersSchema: { type: null, required: false },
170
+ filtersSource: { type: null, required: false },
171
+ filtersFields: { type: null, required: false },
172
+ empty: { type: String, required: false },
173
+ actions: { type: Function, required: false },
174
+ onSelect: { type: Function, required: false },
175
+ class: { type: null, required: false },
176
+ ui: { type: null, required: false }
177
+ });
178
+ const emit = defineEmits(["update:page", "update:items-per-page", "update:sorting", "update:row-selection", "update:filters", "update:grouping", "filtersReset", "filtersSubmit"]);
179
+ const slots = defineSlots();
180
+ const appConfig = useAppConfig();
181
+ const paginationProps = useForwardProps(
182
+ reactivePick(props, "page", "itemsPerPage", "total")
183
+ );
184
+ const tableRef = useTemplateRef("table");
185
+ watch(() => props.resetRowSelection && props.data, (value) => {
186
+ value && tableRef.value?.tableApi.resetRowSelection();
187
+ });
188
+ watch(() => props.data, () => {
189
+ tableRef.value?.tableRef?.parentElement?.scrollTo({ top: 0 });
190
+ });
191
+ const modalConfirm = useOverlay().create(CModalConfirm);
192
+ function createActionCell(action) {
193
+ if (action.visibility && !action.visibility()) {
194
+ return;
195
+ }
196
+ if (action.confirm) {
197
+ return {
198
+ ...action,
199
+ onClick: () => modalConfirm.open(action.confirm)
200
+ };
201
+ }
202
+ if (action.delete) {
203
+ return {
204
+ ...action,
205
+ color: "error",
206
+ onClick: () => modalConfirm.open(defu(action.delete, {
207
+ title: "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435",
208
+ 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 \u044D\u043B\u0435\u043C\u0435\u043D\u0442?",
209
+ confirmButton: { color: "error", label: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C" }
210
+ }))
211
+ };
212
+ }
213
+ return action;
214
+ }
215
+ const tableColumns = computed(() => {
216
+ const columns = props.columns ? [...props.columns] : Object.keys(props.data?.[0] ?? {}).map((accessorKey) => ({ accessorKey, header: accessorKey }));
217
+ if (props.actions) {
218
+ columns.push({
219
+ id: "actions",
220
+ enableHiding: false,
221
+ meta: {
222
+ class: {
223
+ th: "w-20",
224
+ td: "text-right"
225
+ }
226
+ },
227
+ cell: ({ row }) => {
228
+ const items = props.actions?.(row)?.map(createActionCell).filter((item) => item);
229
+ if (!items?.length) {
230
+ return;
231
+ }
232
+ return h(
233
+ UDropdownMenu,
234
+ {
235
+ items,
236
+ content: { align: "end" }
237
+ },
238
+ () => h(UButton, {
239
+ icon: appConfig.ui.icons.ellipsisVertical,
240
+ color: "neutral",
241
+ variant: "ghost"
242
+ })
243
+ );
244
+ }
245
+ });
246
+ }
247
+ if (props.rowSelection) {
248
+ columns.unshift({
249
+ id: "select",
250
+ header: ({ table }) => h(UCheckbox, {
251
+ "modelValue": table.getIsSomeRowsSelected() ? "indeterminate" : table.getIsAllPageRowsSelected(),
252
+ "onUpdate:modelValue": (value) => table.toggleAllPageRowsSelected(!!value)
253
+ }),
254
+ cell: ({ row }) => h(UCheckbox, {
255
+ "modelValue": row.getIsSelected(),
256
+ "disabled": !row.getCanSelect(),
257
+ "onUpdate:modelValue": (value) => row.toggleSelected(!!value)
258
+ }),
259
+ enableHiding: false
260
+ });
261
+ }
262
+ return columns;
263
+ });
264
+ const columnVisibility = ref();
265
+ watch(() => props.defaultHiddenColumns, (value) => {
266
+ columnVisibility.value = Object.fromEntries(
267
+ value?.map((column) => [column, false]) ?? []
268
+ );
269
+ }, { immediate: true });
270
+ const columnOrder = ref([]);
271
+ const hasPagination = computed(() => props.page !== void 0);
272
+ const itemsPerPageItems = [20, 50, 100, 200];
273
+ const isTotalUnknown = computed(() => (props.total ?? 0) >= 1e6);
274
+ const columnPinningWrap = computed(() => {
275
+ return defu(props.columnPinning, { right: props.actions ? ["actions"] : [] });
276
+ });
277
+ const columnFilters = computed(() => {
278
+ if (hasPagination.value || !props.filters) {
279
+ return;
280
+ }
281
+ return Object.entries(props.filters).flatMap(([id, value]) => {
282
+ if (value === void 0) {
283
+ return [];
284
+ }
285
+ return [{ id, value }];
286
+ });
287
+ });
288
+ function getFiltersSlots(slots2) {
289
+ return Object.keys(slots2).reduce((acc, key) => {
290
+ if (key.startsWith("filter-")) {
291
+ acc[key] = key.replace("filter-", "");
292
+ }
293
+ return acc;
294
+ }, {});
295
+ }
296
+ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.tablePanel || {} })());
297
+ </script>
@@ -0,0 +1,95 @@
1
+ import type { AsyncDataRequestStatus } from '#app';
2
+ import type { ComponentConfig, OptionalKeys } from '@hywax/cms-runtime';
3
+ import type { AppConfig } from '@nuxt/schema';
4
+ import type { DropdownMenuItem, FormSchema, PaginationEmits, PaginationProps, TableData, TableProps, TableRow, TableSlots } from '@nuxt/ui';
5
+ import type { ColumnPinningState, GroupingState, RowSelectionState } from '@tanstack/vue-table';
6
+ import type { ModalConfirmProps } from './ModalConfirm.vue';
7
+ import type { TableColumnSortingModel } from './TableColumnSorting.vue';
8
+ import type { TableColumnVisibilityProps } from './TableColumnVisibility.vue';
9
+ import type { TableFiltersEmits, TableFiltersModel, TableFiltersProps, TableFiltersSlots } from './TableFilters.vue';
10
+ import theme from '#build/cms-console/table-panel';
11
+ type TablePanel = ComponentConfig<typeof theme, AppConfig, 'tablePanel'>;
12
+ export interface ActionMenuItem extends DropdownMenuItem {
13
+ confirm?: ModalConfirmProps;
14
+ delete?: OptionalKeys<ModalConfirmProps, 'message'>;
15
+ visibility?: () => boolean;
16
+ }
17
+ export interface TablePanelProps<Data extends TableData, Schema extends FormSchema> {
18
+ title?: string;
19
+ status?: AsyncDataRequestStatus;
20
+ page?: PaginationProps['page'];
21
+ itemsPerPage?: PaginationProps['itemsPerPage'];
22
+ total?: PaginationProps['total'];
23
+ storageKey?: TableColumnVisibilityProps['storageKey'];
24
+ /** @default true */
25
+ columnVisibility?: boolean;
26
+ defaultHiddenColumns?: string[];
27
+ sorting?: TableColumnSortingModel;
28
+ columns?: TableProps<Data>['columns'];
29
+ data?: TableProps<Data>['data'];
30
+ /** @default true */
31
+ sticky?: TableProps<Data>['sticky'];
32
+ columnPinning?: ColumnPinningState;
33
+ getRowId?: TableProps<Data>['getRowId'];
34
+ rowSelection?: RowSelectionState;
35
+ rowSelectionOptions?: TableProps<Data>['rowSelectionOptions'];
36
+ /** @default true */
37
+ resetRowSelection?: boolean;
38
+ grouping?: GroupingState;
39
+ /** @default { getGroupedRowModel: getGroupedRowModel(), groupedColumnMode: false } */
40
+ groupingOptions?: TableProps<Data>['groupingOptions'];
41
+ hideSelectedFilters?: true;
42
+ filters?: TableFiltersModel<Schema>;
43
+ filtersSchema?: Schema;
44
+ filtersSource?: TableFiltersProps<Schema>['source'];
45
+ filtersFields?: TableFiltersProps<Schema>['fields'];
46
+ empty?: TableProps<Data>['empty'];
47
+ actions?: ((row: TableRow<Data>) => ActionMenuItem[] | undefined);
48
+ onSelect?: TableProps<Data>['onSelect'];
49
+ class?: any;
50
+ ui?: TablePanel['slots'];
51
+ }
52
+ export interface TablePanelEmits<Schema extends FormSchema> {
53
+ 'update:page': PaginationEmits['update:page'];
54
+ 'update:items-per-page': [value: number];
55
+ 'update:sorting': [value: TableColumnSortingModel];
56
+ 'update:row-selection': [value?: RowSelectionState];
57
+ 'update:filters': [value: TableFiltersModel<Schema>];
58
+ 'update:grouping': [value?: GroupingState];
59
+ 'filtersReset': TableFiltersEmits<Schema>['reset'];
60
+ 'filtersSubmit': TableFiltersEmits<Schema>['submit'];
61
+ }
62
+ export type TablePanelSlots<Data extends TableData, Schema extends FormSchema> = TableSlots<Data> & {
63
+ 'toolbar-left'?: () => any;
64
+ 'navbar-right'?: () => any;
65
+ 'toolbar-right'?: () => any;
66
+ } & {
67
+ [P in keyof TableFiltersSlots<Schema> as `filter-${P}`]: TableFiltersSlots<Schema>[P];
68
+ };
69
+ declare const _default: typeof __VLS_export;
70
+ export default _default;
71
+ declare const __VLS_export: <Data extends TableData, Schema extends FormSchema>(__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<{
72
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<TablePanelProps<Data, Schema> & {
73
+ "onUpdate:page"?: ((value: number) => any) | undefined;
74
+ "onUpdate:items-per-page"?: ((value: number) => any) | undefined;
75
+ "onUpdate:sorting"?: ((value: import("@tanstack/table-core").SortingState) => any) | undefined;
76
+ "onUpdate:row-selection"?: ((value?: RowSelectionState | undefined) => any) | undefined;
77
+ "onUpdate:filters"?: ((value: import("@nuxt/ui").InferOutput<Schema>) => any) | undefined;
78
+ "onUpdate:grouping"?: ((value?: GroupingState | undefined) => any) | undefined;
79
+ onFiltersReset?: ((args_0: import("@nuxt/ui").InferOutput<Schema>) => any) | undefined;
80
+ onFiltersSubmit?: ((args_0: import("@nuxt/ui").InferOutput<Schema>) => any) | undefined;
81
+ }> & (typeof globalThis extends {
82
+ __VLS_PROPS_FALLBACK: infer P;
83
+ } ? P : {});
84
+ expose: (exposed: {}) => void;
85
+ attrs: any;
86
+ slots: TablePanelSlots<Data, Schema>;
87
+ emit: ((evt: "update:page", value: number) => void) & ((evt: "update:items-per-page", value: number) => void) & ((evt: "update:sorting", value: import("@tanstack/table-core").SortingState) => void) & ((evt: "update:row-selection", value?: RowSelectionState | undefined) => void) & ((evt: "update:filters", value: import("@nuxt/ui").InferOutput<Schema>) => void) & ((evt: "update:grouping", value?: GroupingState | undefined) => void) & ((evt: "filtersReset", args_0: import("@nuxt/ui").InferOutput<Schema>) => void) & ((evt: "filtersSubmit", args_0: import("@nuxt/ui").InferOutput<Schema>) => void);
88
+ }>) => import("vue").VNode & {
89
+ __ctx?: Awaited<typeof __VLS_setup>;
90
+ };
91
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
92
+ [K in keyof T]: T[K];
93
+ } : {
94
+ [K in keyof T as K]: T[K];
95
+ }) & {};
@@ -0,0 +1,33 @@
1
+ import type { ComponentConfig } from '@hywax/cms-runtime';
2
+ import type { AppConfig } from '@nuxt/schema';
3
+ import type { InputEmits, InputProps, InputValue } from '@nuxt/ui';
4
+ import theme from '#build/cms-console/table-search-input';
5
+ type TableSearchInput = ComponentConfig<typeof theme, AppConfig, 'tableSearchInput'>;
6
+ export interface TableSearchInputProps<T extends InputValue> extends Omit<InputProps<T>, 'ui'> {
7
+ class?: any;
8
+ ui?: TableSearchInput['slots'];
9
+ }
10
+ export interface TableSearchInputEmits<T extends InputValue> extends InputEmits<T> {
11
+ }
12
+ declare const _default: typeof __VLS_export;
13
+ export default _default;
14
+ declare const __VLS_export: <T extends InputValue>(__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<{
15
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<TableSearchInputProps<T> & {
16
+ onBlur?: ((event: FocusEvent) => any) | undefined;
17
+ onChange?: ((event: Event) => any) | undefined;
18
+ "onUpdate:modelValue"?: ((value: T) => any) | undefined;
19
+ }> & (typeof globalThis extends {
20
+ __VLS_PROPS_FALLBACK: infer P;
21
+ } ? P : {});
22
+ expose: (exposed: {}) => void;
23
+ attrs: any;
24
+ slots: {};
25
+ emit: ((evt: "blur", event: FocusEvent) => void) & ((evt: "change", event: Event) => void) & ((evt: "update:modelValue", value: T) => void);
26
+ }>) => import("vue").VNode & {
27
+ __ctx?: Awaited<typeof __VLS_setup>;
28
+ };
29
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
30
+ [K in keyof T]: T[K];
31
+ } : {
32
+ [K in keyof T as K]: T[K];
33
+ }) & {};
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <UInput
3
+ :class="ui.input({ class: props.ui?.input })"
4
+ :leading-icon="appConfig.ui.icons.search"
5
+ variant="subtle"
6
+ v-bind="{
7
+ ...forward,
8
+ 'modelValue': inputValue,
9
+ 'modelModifiers': { trim: true, ...forward.modelModifiers },
10
+ 'onUpdate:modelValue': updateInputValue
11
+ }"
12
+ >
13
+ <template #trailing>
14
+ <UButton
15
+ v-if="inputValue"
16
+ :icon="appConfig.ui.icons.close"
17
+ variant="link"
18
+ size="sm"
19
+ color="neutral"
20
+ @click="clearInput"
21
+ />
22
+ </template>
23
+ </UInput>
24
+ </template>
25
+
26
+ <script>
27
+ import theme from "#build/cms-console/table-search-input";
28
+ import { computed, useAppConfig } from "#imports";
29
+ import { reactiveOmit, watchDebounced } from "@vueuse/core";
30
+ import { useForwardPropsEmits } from "reka-ui";
31
+ import { ref, watch } from "vue";
32
+ import { tv } from "../tv";
33
+ </script>
34
+
35
+ <script setup>
36
+ const props = defineProps({
37
+ class: { type: null, required: false },
38
+ ui: { type: null, required: false },
39
+ as: { type: null, required: false },
40
+ id: { type: String, required: false },
41
+ name: { type: String, required: false },
42
+ type: { type: null, required: false },
43
+ placeholder: { type: String, required: false },
44
+ color: { type: null, required: false },
45
+ variant: { type: null, required: false },
46
+ size: { type: null, required: false },
47
+ required: { type: Boolean, required: false },
48
+ autocomplete: { type: null, required: false },
49
+ autofocus: { type: Boolean, required: false },
50
+ autofocusDelay: { type: Number, required: false },
51
+ disabled: { type: Boolean, required: false },
52
+ highlight: { type: Boolean, required: false },
53
+ modelValue: { type: null, required: false },
54
+ defaultValue: { type: null, required: false },
55
+ modelModifiers: { type: Object, required: false },
56
+ icon: { type: null, required: false },
57
+ avatar: { type: Object, required: false },
58
+ leading: { type: Boolean, required: false },
59
+ leadingIcon: { type: null, required: false },
60
+ trailing: { type: Boolean, required: false },
61
+ trailingIcon: { type: null, required: false },
62
+ loading: { type: Boolean, required: false },
63
+ loadingIcon: { type: null, required: false }
64
+ });
65
+ const emit = defineEmits(["update:modelValue", "blur", "change"]);
66
+ const appConfig = useAppConfig();
67
+ const forward = useForwardPropsEmits(reactiveOmit(props, "modelValue"), emit);
68
+ const inputValue = ref();
69
+ function updateInputValue(value) {
70
+ inputValue.value = value;
71
+ }
72
+ watch(() => props.modelValue, (value) => {
73
+ if (value !== inputValue.value) {
74
+ updateInputValue(value);
75
+ }
76
+ }, { immediate: true });
77
+ watchDebounced(inputValue, () => search(), { debounce: 500 });
78
+ function search() {
79
+ if (props.modelValue !== inputValue.value) {
80
+ emit("update:modelValue", inputValue.value);
81
+ }
82
+ }
83
+ const defaultValue = computed(() => {
84
+ if (props.modelModifiers?.nullable) {
85
+ return null;
86
+ }
87
+ if (props.modelModifiers?.optional) {
88
+ return void 0;
89
+ }
90
+ return props.defaultValue;
91
+ });
92
+ function clearInput() {
93
+ updateInputValue(defaultValue.value);
94
+ search();
95
+ }
96
+ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.tableSearchInput || {} })());
97
+ </script>
@@ -0,0 +1,33 @@
1
+ import type { ComponentConfig } from '@hywax/cms-runtime';
2
+ import type { AppConfig } from '@nuxt/schema';
3
+ import type { InputEmits, InputProps, InputValue } from '@nuxt/ui';
4
+ import theme from '#build/cms-console/table-search-input';
5
+ type TableSearchInput = ComponentConfig<typeof theme, AppConfig, 'tableSearchInput'>;
6
+ export interface TableSearchInputProps<T extends InputValue> extends Omit<InputProps<T>, 'ui'> {
7
+ class?: any;
8
+ ui?: TableSearchInput['slots'];
9
+ }
10
+ export interface TableSearchInputEmits<T extends InputValue> extends InputEmits<T> {
11
+ }
12
+ declare const _default: typeof __VLS_export;
13
+ export default _default;
14
+ declare const __VLS_export: <T extends InputValue>(__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<{
15
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<TableSearchInputProps<T> & {
16
+ onBlur?: ((event: FocusEvent) => any) | undefined;
17
+ onChange?: ((event: Event) => any) | undefined;
18
+ "onUpdate:modelValue"?: ((value: T) => any) | undefined;
19
+ }> & (typeof globalThis extends {
20
+ __VLS_PROPS_FALLBACK: infer P;
21
+ } ? P : {});
22
+ expose: (exposed: {}) => void;
23
+ attrs: any;
24
+ slots: {};
25
+ emit: ((evt: "blur", event: FocusEvent) => void) & ((evt: "change", event: Event) => void) & ((evt: "update:modelValue", value: T) => void);
26
+ }>) => import("vue").VNode & {
27
+ __ctx?: Awaited<typeof __VLS_setup>;
28
+ };
29
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
30
+ [K in keyof T]: T[K];
31
+ } : {
32
+ [K in keyof T as K]: T[K];
33
+ }) & {};
@@ -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 { createSharedComposable, useRoute } from "#imports";
2
+ import { ref, watch } from "vue";
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
+ });
@@ -0,0 +1,17 @@
1
+ import type { DropdownMenuItem, EditorCustomHandlers } from '@nuxt/ui';
2
+ import type { Editor, JSONContent } from '@tiptap/vue-3';
3
+ import type { MaybeRefOrGetter } from 'vue';
4
+ export declare function useEditorDragHandle<T extends EditorCustomHandlers>(customHandlers?: MaybeRefOrGetter<T>): {
5
+ selectedNode: import("vue").Ref<{
6
+ node: JSONContent | null;
7
+ pos: number;
8
+ } | undefined, {
9
+ node: JSONContent | null;
10
+ pos: number;
11
+ } | undefined>;
12
+ getItems: (editor: Editor) => DropdownMenuItem[][];
13
+ onNodeChange: (event: {
14
+ node: JSONContent | null;
15
+ pos: number;
16
+ }) => void;
17
+ };