@hywax/cms 0.0.23 → 1.0.1

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