@shwfed/nuxt 0.7.9 → 0.7.10

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 (95) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/app.d.vue.ts +7 -56
  3. package/dist/runtime/components/app.vue +17 -404
  4. package/dist/runtime/components/app.vue.d.ts +7 -56
  5. package/dist/runtime/components/fields.d.vue.ts +154 -132
  6. package/dist/runtime/components/fields.vue +30 -295
  7. package/dist/runtime/components/fields.vue.d.ts +154 -132
  8. package/dist/runtime/components/table.d.vue.ts +63 -59
  9. package/dist/runtime/components/table.vue +52 -617
  10. package/dist/runtime/components/table.vue.d.ts +63 -59
  11. package/dist/runtime/components/ui/app/App.d.vue.ts +86 -0
  12. package/dist/runtime/components/ui/app/App.vue +414 -0
  13. package/dist/runtime/components/ui/app/App.vue.d.ts +86 -0
  14. package/dist/runtime/components/ui/checkbox/Checkbox.vue +6 -2
  15. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.d.vue.ts +30 -0
  16. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +87 -0
  17. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue.d.ts +30 -0
  18. package/dist/runtime/components/ui/expression-editor/index.d.ts +1 -0
  19. package/dist/runtime/components/ui/expression-editor/index.js +1 -0
  20. package/dist/runtime/components/ui/field/FieldContent.vue +1 -1
  21. package/dist/runtime/components/ui/field/FieldError.vue +2 -2
  22. package/dist/runtime/components/ui/fields/Fields.d.vue.ts +376 -0
  23. package/dist/runtime/components/ui/fields/Fields.vue +441 -0
  24. package/dist/runtime/components/ui/fields/Fields.vue.d.ts +376 -0
  25. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.d.vue.ts +163 -0
  26. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.vue +363 -0
  27. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.vue.d.ts +163 -0
  28. package/dist/runtime/components/ui/input/Input.d.vue.ts +1 -0
  29. package/dist/runtime/components/ui/input/Input.vue +2 -0
  30. package/dist/runtime/components/ui/input/Input.vue.d.ts +1 -0
  31. package/dist/runtime/components/ui/input-group/InputGroupAddon.vue +4 -1
  32. package/dist/runtime/components/ui/input-group/InputGroupCombobox.d.vue.ts +8 -3
  33. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue +8 -3
  34. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue.d.ts +8 -3
  35. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.d.vue.ts +8 -1
  36. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue +10 -1
  37. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue.d.ts +8 -1
  38. package/dist/runtime/components/ui/input-group/InputGroupNumberField.d.vue.ts +5 -2
  39. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue +9 -3
  40. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue.d.ts +5 -2
  41. package/dist/runtime/components/ui/input-group/index.js +1 -1
  42. package/dist/runtime/components/ui/locale/Locale.d.vue.ts +20 -0
  43. package/dist/runtime/components/ui/locale/Locale.vue +291 -0
  44. package/dist/runtime/components/ui/locale/Locale.vue.d.ts +20 -0
  45. package/dist/runtime/components/ui/locale/index.d.ts +1 -0
  46. package/dist/runtime/components/ui/locale/index.js +1 -0
  47. package/dist/runtime/components/ui/native-select/NativeSelectOption.d.vue.ts +1 -0
  48. package/dist/runtime/components/ui/native-select/NativeSelectOption.vue +4 -1
  49. package/dist/runtime/components/ui/native-select/NativeSelectOption.vue.d.ts +1 -0
  50. package/dist/runtime/components/ui/number-field/NumberFieldInput.vue +1 -1
  51. package/dist/runtime/components/ui/switch/Switch.vue +1 -1
  52. package/dist/runtime/components/ui/table/Table.d.vue.ts +81 -0
  53. package/dist/runtime/components/ui/table/Table.vue +792 -0
  54. package/dist/runtime/components/ui/table/Table.vue.d.ts +81 -0
  55. package/dist/runtime/components/ui/table/schema.d.ts +48 -0
  56. package/dist/runtime/components/ui/table/schema.js +126 -0
  57. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.d.vue.ts +62 -0
  58. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.vue +2233 -0
  59. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.vue.d.ts +62 -0
  60. package/dist/runtime/components/ui/table-configurator/menu.d.ts +37 -0
  61. package/dist/runtime/components/ui/table-configurator/menu.js +227 -0
  62. package/dist/runtime/components/ui/tabs/Tabs.d.vue.ts +24 -0
  63. package/dist/runtime/components/ui/tabs/Tabs.vue +30 -0
  64. package/dist/runtime/components/ui/tabs/Tabs.vue.d.ts +24 -0
  65. package/dist/runtime/components/ui/tabs/TabsContent.d.vue.ts +18 -0
  66. package/dist/runtime/components/ui/tabs/TabsContent.vue +23 -0
  67. package/dist/runtime/components/ui/tabs/TabsContent.vue.d.ts +18 -0
  68. package/dist/runtime/components/ui/tabs/TabsList.d.vue.ts +18 -0
  69. package/dist/runtime/components/ui/tabs/TabsList.vue +25 -0
  70. package/dist/runtime/components/ui/tabs/TabsList.vue.d.ts +18 -0
  71. package/dist/runtime/components/ui/tabs/TabsTrigger.d.vue.ts +18 -0
  72. package/dist/runtime/components/ui/tabs/TabsTrigger.vue +27 -0
  73. package/dist/runtime/components/ui/tabs/TabsTrigger.vue.d.ts +18 -0
  74. package/dist/runtime/components/ui/tabs/index.d.ts +4 -0
  75. package/dist/runtime/components/ui/tabs/index.js +4 -0
  76. package/dist/runtime/components/ui/textarea/Textarea.d.vue.ts +1 -0
  77. package/dist/runtime/components/ui/textarea/Textarea.vue +3 -1
  78. package/dist/runtime/components/ui/textarea/Textarea.vue.d.ts +1 -0
  79. package/dist/runtime/components/ui/toggle/Toggle.d.vue.ts +34 -0
  80. package/dist/runtime/components/ui/toggle/Toggle.vue +32 -0
  81. package/dist/runtime/components/ui/toggle/Toggle.vue.d.ts +34 -0
  82. package/dist/runtime/components/ui/toggle/index.d.ts +7 -0
  83. package/dist/runtime/components/ui/toggle/index.js +22 -0
  84. package/dist/runtime/composables/useTableRenderers.d.ts +2 -1
  85. package/dist/runtime/composables/useTableRenderers.js +2 -1
  86. package/dist/runtime/style.css +1 -1
  87. package/dist/runtime/table-renderers/builtins.js +213 -98
  88. package/dist/runtime/table-renderers/registry.d.ts +1 -0
  89. package/dist/runtime/table-renderers/registry.js +3 -0
  90. package/dist/runtime/utils/coders.d.ts +27 -2
  91. package/dist/runtime/utils/coders.js +27 -2
  92. package/package.json +3 -1
  93. /package/dist/runtime/components/{logo.d.vue.ts → ui/logo/Logo.d.vue.ts} +0 -0
  94. /package/dist/runtime/components/{logo.vue → ui/logo/Logo.vue} +0 -0
  95. /package/dist/runtime/components/{logo.vue.d.ts → ui/logo/Logo.vue.d.ts} +0 -0
@@ -0,0 +1,792 @@
1
+ <script setup>
2
+ import { useNuxtApp } from "#app";
3
+ import { useCheating } from "#imports";
4
+ import { Icon } from "@iconify/vue";
5
+ import {
6
+ FlexRender,
7
+ getCoreRowModel,
8
+ getExpandedRowModel,
9
+ getPaginationRowModel,
10
+ useVueTable
11
+ } from "@tanstack/vue-table";
12
+ import { useVirtualizer } from "@tanstack/vue-virtual";
13
+ import { computedAsync } from "@vueuse/core";
14
+ import { getProperty } from "dot-prop";
15
+ import { Effect } from "effect";
16
+ import { Pagination } from "reka-ui/namespaced";
17
+ import { computed, ref, watchEffect } from "vue";
18
+ import { useI18n } from "vue-i18n";
19
+ import { useTableRenderers } from "../../../composables/useTableRenderers";
20
+ import { getLocalizedText, TableConfigC } from "./schema";
21
+ import { Button } from "../button";
22
+ import { NumberField, NumberFieldInput } from "../number-field";
23
+ import { Skeleton } from "../skeleton";
24
+ import TableConfiguratorDialog from "../table-configurator/TableConfiguratorDialog.vue";
25
+ import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip";
26
+ const props = defineProps({
27
+ config: { type: null, required: true },
28
+ data: { type: Array, required: true },
29
+ rowCount: { type: Number, required: false }
30
+ });
31
+ const emit = defineEmits(["update:config"]);
32
+ const resolvedConfig = computedAsync(async () => TableConfigC.parse(await props.config.pipe(Effect.runPromise)));
33
+ const { t, locale } = useI18n();
34
+ const slots = defineSlots();
35
+ const { $dsl } = useNuxtApp();
36
+ const isCheating = useCheating();
37
+ const { resolveTableRenderer } = useTableRenderers();
38
+ const containerRef = ref(null);
39
+ const appliedInitialStateConfig = ref();
40
+ function genColumnId(column) {
41
+ if (typeof column.accessor === "string") {
42
+ return column.accessor;
43
+ } else if (column.accessor) {
44
+ return column.accessor.read;
45
+ } else if (column.id) {
46
+ return column.id;
47
+ }
48
+ return crypto.randomUUID();
49
+ }
50
+ function getColumnTitle(column) {
51
+ return getLocalizedText(column.title, locale.value) ?? genColumnId(column);
52
+ }
53
+ function getColumnTooltip(column) {
54
+ return getLocalizedText(column.tooltip, locale.value);
55
+ }
56
+ function translate(column) {
57
+ if (Array.isArray(column.columns) && column.columns.length > 0) {
58
+ return {
59
+ id: column.id ?? genColumnId(column),
60
+ header: getColumnTitle(column),
61
+ columns: column.columns?.map((column2) => translate(column2)) ?? [],
62
+ enableSorting: column.enableSorting ?? false,
63
+ enableMultiSort: column.enableMultiSorting,
64
+ enablePinning: column.enablePinning,
65
+ size: column.size,
66
+ meta: {
67
+ tooltip: getColumnTooltip(column),
68
+ grow: column.grow ?? false,
69
+ accessor: column.accessor
70
+ }
71
+ };
72
+ }
73
+ const renderer = resolveTableRenderer(typeof column.renderer === "string" ? column.renderer : column.renderer?.id ? column.renderer.id : "table.renderer.text");
74
+ const options = renderer.parseOptions(column.renderer && typeof column.renderer === "object" && "props" in column.renderer ? column.renderer.props : null);
75
+ return {
76
+ id: column.id ?? genColumnId(column),
77
+ header: (ctx) => renderer.header?.({ ctx, options }) ?? getColumnTitle(column),
78
+ cell: (ctx) => {
79
+ const slot = slots[ctx.column.id];
80
+ if (slot) {
81
+ return slot({ cell: ctx });
82
+ }
83
+ return renderer.cell({ ctx, options });
84
+ },
85
+ accessorFn: (row, index) => {
86
+ const key = column.accessor;
87
+ if (typeof key === "string") {
88
+ return getProperty(row, key);
89
+ } else if (key !== void 0) {
90
+ try {
91
+ return $dsl.evaluate`${key.read}`({
92
+ row,
93
+ index: BigInt(index)
94
+ });
95
+ } catch (e) {
96
+ console.error(e);
97
+ return void 0;
98
+ }
99
+ }
100
+ return void 0;
101
+ },
102
+ enableSorting: column.enableSorting ?? false,
103
+ enableMultiSort: column.enableMultiSorting,
104
+ enablePinning: column.enablePinning,
105
+ size: column.size,
106
+ columns: column.columns?.map((column2) => translate(column2)) ?? [],
107
+ meta: {
108
+ tooltip: getColumnTooltip(column),
109
+ grow: column.grow ?? false,
110
+ accessor: column.accessor
111
+ },
112
+ ...renderer.columnDefOverrides
113
+ };
114
+ }
115
+ const columns = computed(() => resolvedConfig.value?.columns.map((column) => translate(column)) ?? []);
116
+ const data = computed(() => props.data);
117
+ const isManualPagination = computed(() => props.rowCount !== void 0);
118
+ const totalItems = computed(() => props.rowCount ?? data.value.length);
119
+ const paginationLeft = computed(() => resolvedConfig.value?.paginationLeft ?? "");
120
+ const paginationRight = computed(() => resolvedConfig.value?.paginationRight ?? "");
121
+ const isConfiguratorOpen = ref(false);
122
+ function handleConfiguratorConfirm(nextConfig) {
123
+ emit("update:config", nextConfig);
124
+ }
125
+ function getRowId(originalRow, index, parent) {
126
+ const expression = resolvedConfig.value?.getRowId;
127
+ if (!expression) {
128
+ return parent ? `${parent.index}.${index}` : `${index}`;
129
+ }
130
+ try {
131
+ const key = $dsl.evaluate`${expression}`(
132
+ {
133
+ row: originalRow,
134
+ index,
135
+ parent: parent ? {
136
+ id: parent.id,
137
+ index: BigInt(parent.index),
138
+ original: parent.original
139
+ } : null
140
+ }
141
+ );
142
+ if (typeof key === "string") {
143
+ return key;
144
+ }
145
+ } catch (e) {
146
+ console.error(e);
147
+ }
148
+ return parent ? `${parent.index}.${index}` : `${index}`;
149
+ }
150
+ function getSubRows(row, index) {
151
+ const expression = resolvedConfig.value?.getSubRows;
152
+ if (!expression) {
153
+ return void 0;
154
+ }
155
+ try {
156
+ const value = $dsl.evaluate`${expression}`({
157
+ row,
158
+ index
159
+ });
160
+ return Array.isArray(value) ? value : void 0;
161
+ } catch (e) {
162
+ console.error(e);
163
+ return void 0;
164
+ }
165
+ }
166
+ function enableRowSelection(row) {
167
+ const expression = resolvedConfig.value?.enableRowSelection;
168
+ if (!expression) {
169
+ return true;
170
+ }
171
+ try {
172
+ return Boolean($dsl.evaluate`${expression}`({
173
+ row: row.original,
174
+ index: BigInt(row.index),
175
+ id: row.id
176
+ }));
177
+ } catch (e) {
178
+ console.error(e);
179
+ return true;
180
+ }
181
+ }
182
+ function enableMultiRowSelection(row) {
183
+ const expression = resolvedConfig.value?.enableMultiRowSelection;
184
+ if (!expression) {
185
+ return true;
186
+ }
187
+ try {
188
+ return Boolean($dsl.evaluate`${expression}`({
189
+ row: row.original,
190
+ index: BigInt(row.index),
191
+ id: row.id
192
+ }));
193
+ } catch (e) {
194
+ console.error(e);
195
+ return true;
196
+ }
197
+ }
198
+ const columnResizeMode = "onChange";
199
+ const baseTableOptions = {
200
+ get columns() {
201
+ return columns.value;
202
+ },
203
+ data,
204
+ getCoreRowModel: getCoreRowModel(),
205
+ getExpandedRowModel: getExpandedRowModel(),
206
+ getPaginationRowModel: getPaginationRowModel(),
207
+ get manualPagination() {
208
+ return isManualPagination.value;
209
+ },
210
+ get rowCount() {
211
+ return props.rowCount;
212
+ },
213
+ get getRowId() {
214
+ return resolvedConfig.value?.getRowId ? getRowId : void 0;
215
+ },
216
+ getSubRows,
217
+ enableRowSelection,
218
+ get enableMultiRowSelection() {
219
+ return resolvedConfig.value?.enableMultiRowSelection ? enableMultiRowSelection : void 0;
220
+ },
221
+ columnResizeMode
222
+ };
223
+ function getConfigOption(property) {
224
+ const configOptions = resolvedConfig.value?.props;
225
+ if (!configOptions) {
226
+ return void 0;
227
+ }
228
+ return Reflect.get(configOptions, property);
229
+ }
230
+ const tableOptions = new Proxy(baseTableOptions, {
231
+ get(target, property, receiver) {
232
+ const baseValue = Reflect.get(target, property, receiver);
233
+ if (baseValue !== void 0) {
234
+ return baseValue;
235
+ }
236
+ return getConfigOption(property);
237
+ },
238
+ has(target, property) {
239
+ const configOptions = resolvedConfig.value?.props;
240
+ return Reflect.has(target, property) || (configOptions ? Reflect.has(configOptions, property) : false);
241
+ },
242
+ ownKeys(target) {
243
+ const keys = [...Reflect.ownKeys(target)];
244
+ const configOptions = resolvedConfig.value?.props;
245
+ if (configOptions) {
246
+ keys.push(...Reflect.ownKeys(configOptions));
247
+ }
248
+ return Array.from(new Set(keys));
249
+ },
250
+ getOwnPropertyDescriptor(target, property) {
251
+ const configOptions = resolvedConfig.value?.props;
252
+ if (!Reflect.has(target, property) && !(configOptions && Reflect.has(configOptions, property))) {
253
+ return void 0;
254
+ }
255
+ return {
256
+ configurable: true,
257
+ enumerable: true,
258
+ get() {
259
+ const baseValue = Reflect.get(target, property);
260
+ if (baseValue !== void 0) {
261
+ return baseValue;
262
+ }
263
+ return getConfigOption(property);
264
+ }
265
+ };
266
+ }
267
+ });
268
+ const tableApi = useVueTable(tableOptions);
269
+ watchEffect(() => {
270
+ const config = resolvedConfig.value;
271
+ if (!config || appliedInitialStateConfig.value === config) {
272
+ return;
273
+ }
274
+ const initialState = config.props?.initialState;
275
+ if (initialState) {
276
+ tableApi.initialState = mergeInitialState(tableApi.initialState, initialState);
277
+ tableApi.reset();
278
+ }
279
+ appliedInitialStateConfig.value = config;
280
+ });
281
+ defineExpose(tableApi);
282
+ const rowVirtualizer = useVirtualizer(
283
+ computed(() => ({
284
+ count: tableApi.getRowModel().rows.length,
285
+ estimateSize: () => 35,
286
+ getScrollElement: () => containerRef.value,
287
+ overscan: 30
288
+ }))
289
+ );
290
+ const rowTotalSize = computed(() => rowVirtualizer.value.getTotalSize());
291
+ const rowWindow = computed(() => rowVirtualizer.value.getVirtualItems());
292
+ function measureRow(el) {
293
+ if (!el || !(el instanceof Element))
294
+ return;
295
+ rowVirtualizer.value.measureElement(el);
296
+ }
297
+ const rows = computed(() => tableApi.getRowModel().rows);
298
+ const maxPage = computed(() => Math.max(tableApi.getPageCount(), 1));
299
+ function isStyleRecord(x) {
300
+ return typeof x === "object" && x !== null && !Array.isArray(x);
301
+ }
302
+ function getCellStyles(ctx) {
303
+ const expression = resolvedConfig.value?.cellStyles;
304
+ if (!expression)
305
+ return {};
306
+ try {
307
+ const result = $dsl.evaluate`${expression}`({
308
+ row: ctx.row.original,
309
+ index: BigInt(ctx.row.index),
310
+ id: ctx.column.id,
311
+ selected: ctx.row.getIsSelected(),
312
+ pinned: ctx.column.getIsPinned()
313
+ });
314
+ return isStyleRecord(result) ? result : {};
315
+ } catch (e) {
316
+ console.error(e);
317
+ return {};
318
+ }
319
+ }
320
+ function shouldHaveRightBorder(column) {
321
+ switch (column.getIsPinned()) {
322
+ case "left":
323
+ return true;
324
+ case "right":
325
+ return false;
326
+ case false:
327
+ return !column.getIsLastColumn("center");
328
+ }
329
+ }
330
+ function shouldHaveLeftBorder(column) {
331
+ switch (column.getIsPinned()) {
332
+ case "left":
333
+ return false;
334
+ case "right":
335
+ return true;
336
+ case false:
337
+ return false;
338
+ }
339
+ }
340
+ function pinnedStyle(column) {
341
+ const pinned = column.getIsPinned();
342
+ if (!pinned)
343
+ return {};
344
+ const style = {
345
+ [pinned]: pinned === "left" ? `${column.getStart("left")}px` : `${column.getAfter("right")}px`
346
+ };
347
+ if (column.getIsLastColumn("left"))
348
+ style.boxShadow = "5px 5px 5px #00000005";
349
+ if (column.getIsFirstColumn("right"))
350
+ style.boxShadow = "-5px 5px 5px #00000005";
351
+ return style;
352
+ }
353
+ const SORT_ICONS = {
354
+ unsorted: "fluent:arrow-sort-16-regular",
355
+ asc: "fluent:arrow-sort-up-16-regular",
356
+ desc: "fluent:arrow-sort-down-16-regular"
357
+ };
358
+ function getSortIcon(column) {
359
+ const sortDir = column.getIsSorted();
360
+ const iconKey = sortDir === false ? "unsorted" : sortDir;
361
+ return SORT_ICONS[iconKey];
362
+ }
363
+ function mergeInitialState(current, initialState) {
364
+ return {
365
+ ...current,
366
+ columnVisibility: initialState.columnVisibility ?? current.columnVisibility,
367
+ columnOrder: initialState.columnOrder ?? current.columnOrder,
368
+ columnPinning: initialState.columnPinning ? { ...current.columnPinning, ...initialState.columnPinning } : current.columnPinning,
369
+ rowPinning: initialState.rowPinning ? { ...current.rowPinning, ...initialState.rowPinning } : current.rowPinning,
370
+ columnFilters: initialState.columnFilters ?? current.columnFilters,
371
+ globalFilter: initialState.globalFilter ?? current.globalFilter,
372
+ sorting: initialState.sorting ?? current.sorting,
373
+ expanded: initialState.expanded ?? current.expanded,
374
+ grouping: initialState.grouping ?? current.grouping,
375
+ columnSizing: initialState.columnSizing ?? current.columnSizing,
376
+ columnSizingInfo: initialState.columnSizingInfo ?? current.columnSizingInfo,
377
+ pagination: initialState.pagination ? { ...current.pagination, ...initialState.pagination } : current.pagination,
378
+ rowSelection: initialState.rowSelection ?? current.rowSelection
379
+ };
380
+ }
381
+ function getSortLabel(column) {
382
+ const direction = column.getIsSorted();
383
+ if (direction === "asc") {
384
+ return t("table-sort-asc");
385
+ }
386
+ if (direction === "desc") {
387
+ return t("table-sort-desc");
388
+ }
389
+ return t("table-sort-unsorted");
390
+ }
391
+ </script>
392
+
393
+ <script>
394
+ export { AccessorC, ColumnC, RenderC, TableConfigC } from "./schema";
395
+ </script>
396
+
397
+ <template>
398
+ <div
399
+ class="relative flex h-full flex-col"
400
+ >
401
+ <Button
402
+ v-if="isCheating"
403
+ data-slot="table-configurator-trigger"
404
+ variant="ghost"
405
+ size="sm"
406
+ type="button"
407
+ class="absolute right-3 top-3 z-20 bg-white/90 shadow-xs backdrop-blur-sm hover:bg-white"
408
+ @click="isConfiguratorOpen = true"
409
+ >
410
+ <Icon icon="fluent:settings-20-regular" />
411
+ </Button>
412
+
413
+ <TableConfiguratorDialog
414
+ v-if="resolvedConfig"
415
+ v-model:open="isConfiguratorOpen"
416
+ :config="resolvedConfig"
417
+ @confirm="handleConfiguratorConfirm"
418
+ />
419
+
420
+ <div
421
+ class="relative flex min-h-0 flex-1 flex-col"
422
+ >
423
+ <Skeleton
424
+ v-if="resolvedConfig === void 0"
425
+ class="absolute inset-0 z-10 w-full h-full"
426
+ />
427
+
428
+ <div
429
+ :class="[
430
+ 'flex min-h-0 flex-1 flex-col',
431
+ resolvedConfig === void 0 && 'opacity-0'
432
+ ]"
433
+ >
434
+ <div
435
+ ref="containerRef"
436
+ class="overflow-scroll overscroll-none flex-1 border border-zinc-200 rounded relative"
437
+ >
438
+ <div :style="{ height: `${rowTotalSize}px` }">
439
+ <table class="grid">
440
+ <thead class="grid sticky top-0 z-10 select-none">
441
+ <tr
442
+ v-for="group in tableApi.getHeaderGroups()"
443
+ :key="group.id"
444
+ class="flex w-full border-b border-zinc-200"
445
+ >
446
+ <th
447
+ v-for="header in group.headers"
448
+ :key="header.id"
449
+ :colspan="header.colSpan"
450
+ :class="[
451
+ header.column.columnDef.meta?.grow && 'flex-1',
452
+ 'flex items-center gap-2 border-zinc-300 py-2 text-zinc-600',
453
+ 'text-xs flex items-center justify-center relative',
454
+ 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] group',
455
+ header.column.getIsPinned() && 'sticky z-15',
456
+ shouldHaveRightBorder(header.column) && 'border-r',
457
+ shouldHaveLeftBorder(header.column) && 'border-l'
458
+ ]"
459
+ :style="{
460
+ width: `${header.getSize()}px`,
461
+ ...pinnedStyle(header.column)
462
+ }"
463
+ >
464
+ <FlexRender
465
+ v-if="!header.isPlaceholder"
466
+ :render="header.column.columnDef.header"
467
+ :props="header.getContext()"
468
+ />
469
+
470
+ <Tooltip
471
+ v-if="!header.isPlaceholder && header.column.columnDef.meta?.tooltip"
472
+ :delay-duration="180"
473
+ >
474
+ <TooltipTrigger as-child>
475
+ <Icon icon="fluent:info-20-regular" />
476
+ </TooltipTrigger>
477
+ <TooltipContent
478
+ align="center"
479
+ side="top"
480
+ >
481
+ <span v-html="$md.inline`${header.column.columnDef.meta?.tooltip}`()" />
482
+ </TooltipContent>
483
+ </Tooltip>
484
+
485
+ <Tooltip
486
+ v-if="!header.isPlaceholder && isCheating && header.column.columnDef.meta?.accessor"
487
+ :delay-duration="180"
488
+ >
489
+ <TooltipTrigger as-child>
490
+ <Icon icon="fluent:code-20-regular" />
491
+ </TooltipTrigger>
492
+ <TooltipContent
493
+ align="center"
494
+ side="top"
495
+ >
496
+ <template v-if="typeof header.column.columnDef.meta?.accessor === 'string'">
497
+ <span class="font-mono">{{ header.column.columnDef.meta?.accessor }}</span>
498
+ </template>
499
+ <template v-else>
500
+ <span class="font-mono">{{ JSON.stringify(header.column.columnDef.meta?.accessor) }}</span>
501
+ </template>
502
+ </TooltipContent>
503
+ </Tooltip>
504
+
505
+ <Tooltip
506
+ v-if="!header.isPlaceholder && header.column.getCanSort()"
507
+ :delay-duration="800"
508
+ >
509
+ <TooltipTrigger as-child>
510
+ <Button
511
+ variant="ghost"
512
+ size="xs"
513
+ :class="[
514
+ 'absolute hover:bg-transparent right-1 top-1/2 -translate-y-1/2 transform-3d transition-opacity duration-180',
515
+ !header.column.getIsSorted() ? 'opacity-30 hover:opacity-60' : 'text-(--primary)/80 hover:text-(--primary)'
516
+ ]"
517
+ as-child
518
+ >
519
+ <button
520
+ type="button"
521
+ @click="header.column.getToggleSortingHandler()?.($event)"
522
+ >
523
+ <Icon :icon="getSortIcon(header.column)" />
524
+ </button>
525
+ </Button>
526
+ </TooltipTrigger>
527
+ <TooltipContent>
528
+ {{ getSortLabel(header.column) }}
529
+ </TooltipContent>
530
+ </Tooltip>
531
+
532
+ <div
533
+ v-if="!header.isPlaceholder && header.column.getCanResize() && (!header.column.getIsLastColumn('right') || !tableApi.getIsSomeColumnsPinned('right') && !header.column.getIsLastColumn('center'))"
534
+ :class="[
535
+ 'group',
536
+ 'absolute',
537
+ 'top-0',
538
+ 'bottom-0',
539
+ 'right-0',
540
+ 'px-2',
541
+ 'translate-x-2',
542
+ 'z-5',
543
+ 'opacity-0',
544
+ 'duration-150',
545
+ 'transition-opacity',
546
+ 'ease-out',
547
+ 'hover:opacity-100',
548
+ 'cursor-col-resize'
549
+ ]"
550
+ @mousedown="header.getResizeHandler()($event)"
551
+ >
552
+ <div :class="['w-2pt', 'h-full', 'translate-x-1pt', 'transform-3d', 'bg-[color-mix(in_srgb,var(--primary)_80%,white)]']" />
553
+ </div>
554
+ </th>
555
+ </tr>
556
+ </thead>
557
+
558
+ <tbody
559
+ class="grid relative"
560
+ :style="{ height: `${rowTotalSize}px` }"
561
+ >
562
+ <tr
563
+ v-for="r in rowWindow"
564
+ :key="rows[r.index]?.id ?? r.index"
565
+ :ref="measureRow"
566
+ class="flex absolute w-full not-last:border-b border-zinc-300"
567
+ :data-index="rows[r.index]?.index"
568
+ :style="{ transform: `translate3d(0, ${r.start}px, 0)` }"
569
+ >
570
+ <td
571
+ v-for="cell in rows[r.index]?.getVisibleCells() ?? []"
572
+ :key="cell.id"
573
+ :class="[
574
+ 'border-zinc-300',
575
+ cell.column.columnDef.meta?.grow && 'flex-1',
576
+ cell.column.getIsPinned() && 'sticky z-15',
577
+ shouldHaveRightBorder(cell.column) && 'border-r',
578
+ shouldHaveLeftBorder(cell.column) && 'border-l'
579
+ ]"
580
+ :style="{
581
+ width: `${cell.column.getSize()}px`,
582
+ ...pinnedStyle(cell.column),
583
+ ...getCellStyles(cell.getContext())
584
+ }"
585
+ >
586
+ <FlexRender
587
+ :render="cell.column.columnDef.cell"
588
+ :props="cell.getContext()"
589
+ />
590
+ </td>
591
+ </tr>
592
+ </tbody>
593
+
594
+ <tfoot class="hidden has-data-footer:grid sticky bottom-0 z-10 select-none border-t border-zinc-200">
595
+ <tr
596
+ v-for="group in tableApi.getFooterGroups()"
597
+ :key="group.id"
598
+ class="flex w-full border-zinc-200"
599
+ >
600
+ <th
601
+ v-for="header in group.headers"
602
+ :key="header.id"
603
+ :colSpan="header.colSpan"
604
+ :class="[
605
+ header.column.columnDef.meta?.grow && 'flex-1',
606
+ 'flex items-center gap-2 border-zinc-300 text-zinc-600 p-0',
607
+ 'text-xs flex items-center justify-center relative',
608
+ 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] group',
609
+ header.column.getIsPinned() && 'sticky z-15',
610
+ shouldHaveRightBorder(header.column) && 'border-r',
611
+ shouldHaveLeftBorder(header.column) && 'border-l'
612
+ ]"
613
+ :style="{
614
+ width: `${header.getSize()}px`,
615
+ ...pinnedStyle(header.column)
616
+ }"
617
+ >
618
+ <FlexRender
619
+ v-if="!header.isPlaceholder"
620
+ :render="header.column.columnDef.footer"
621
+ :props="header.getContext()"
622
+ />
623
+ </th>
624
+ </tr>
625
+ </tfoot>
626
+ </table>
627
+ </div>
628
+ </div>
629
+
630
+ <div class="flex items-center justify-between w-full py-2 gap-2 text-sm text-zinc-600">
631
+ <div
632
+ :class="[
633
+ 'relative p-1 flex-1 prose prose-zinc text-xs'
634
+ ]"
635
+ >
636
+ <span
637
+ v-html="$md.inline`${paginationLeft}`({
638
+ selected: tableApi.getSelectedRowModel().rows.map((row) => row.original)
639
+ })"
640
+ />
641
+ &nbsp;
642
+ </div>
643
+ <div class="flex items-center gap-4">
644
+ <i18n-t
645
+ keypath="total"
646
+ tag="span"
647
+ class="text-xs"
648
+ >
649
+ <template #count>
650
+ <strong>{{ totalItems }}</strong>
651
+ </template>
652
+ </i18n-t>
653
+ <Pagination.Root
654
+ show-edges
655
+ :total="totalItems"
656
+ :items-per-page="tableApi.getState().pagination.pageSize"
657
+ :page="tableApi.getState().pagination.pageIndex + 1"
658
+ @update:page="(page2) => tableApi.setPageIndex(page2 - 1)"
659
+ >
660
+ <Pagination.List
661
+ v-slot="{ items }"
662
+ class="flex items-center gap-1"
663
+ >
664
+ <Pagination.First
665
+ :class="[
666
+ 'w-7 h-7 flex items-center justify-center bg-transparent hover:bg-zinc-100 transition disabled:opacity-50 rounded text-zinc-600',
667
+ 'data-disabled:opacity-50 data-disabled:cursor-not-allowed cursor-pointer'
668
+ ]"
669
+ >
670
+ <Icon
671
+ icon="radix-icons:double-arrow-left"
672
+ class="w-4 h-4"
673
+ />
674
+ </Pagination.First>
675
+ <Pagination.Prev
676
+ :class="[
677
+ 'w-7 h-7 flex items-center justify-center bg-transparent hover:bg-zinc-100 transition disabled:opacity-50 rounded text-zinc-600',
678
+ 'data-disabled:opacity-50 data-disabled:cursor-not-allowed cursor-pointer'
679
+ ]"
680
+ >
681
+ <Icon
682
+ icon="radix-icons:chevron-left"
683
+ class="w-4 h-4"
684
+ />
685
+ </Pagination.Prev>
686
+
687
+ <template
688
+ v-for="(page, index) in items"
689
+ :key="page.type === 'page' ? `${page.type}-${page.value}` : `${page.type}-${index}`"
690
+ >
691
+ <Pagination.ListItem
692
+ v-if="page.type === 'page'"
693
+ :class="[
694
+ 'w-7 h-7 flex items-center justify-center rounded text-xs bg-transparent',
695
+ 'data-selected:text-(--primary) hover:bg-zinc-100 transition cursor-pointer'
696
+ ]"
697
+ :value="page.value"
698
+ >
699
+ {{ page.value }}
700
+ </Pagination.ListItem>
701
+ <Pagination.Ellipsis
702
+ v-else
703
+ class="w-7 h-7 flex items-center justify-center text-zinc-400"
704
+ >
705
+ &#8230;
706
+ </Pagination.Ellipsis>
707
+ </template>
708
+
709
+ <Pagination.Next
710
+ :class="[
711
+ 'w-7 h-7 flex items-center justify-center bg-transparent hover:bg-zinc-100 transition disabled:opacity-50 rounded text-zinc-600',
712
+ 'data-disabled:opacity-50 data-disabled:cursor-not-allowed cursor-pointer'
713
+ ]"
714
+ >
715
+ <Icon
716
+ icon="radix-icons:chevron-right"
717
+ class="w-4 h-4"
718
+ />
719
+ </Pagination.Next>
720
+ <Pagination.Last
721
+ :class="[
722
+ 'w-7 h-7 flex items-center justify-center bg-transparent hover:bg-zinc-100 transition disabled:opacity-50 rounded text-zinc-600',
723
+ 'data-disabled:opacity-50 data-disabled:cursor-not-allowed cursor-pointer'
724
+ ]"
725
+ >
726
+ <Icon
727
+ icon="radix-icons:double-arrow-right"
728
+ class="w-4 h-4"
729
+ />
730
+ </Pagination.Last>
731
+ </Pagination.List>
732
+ </Pagination.Root>
733
+ <i18n-t
734
+ keypath="goto"
735
+ tag="div"
736
+ class="text-xs flex items-center gap-2"
737
+ >
738
+ <template #page>
739
+ <NumberField
740
+ :model-value="tableApi.getState().pagination.pageIndex + 1"
741
+ :min="1"
742
+ :max="maxPage"
743
+ @update:model-value="(value) => tableApi.setPageIndex(value - 1)"
744
+ >
745
+ <NumberFieldInput class="h-6 w-16 text-xs" />
746
+ </NumberField>
747
+ </template>
748
+ </i18n-t>
749
+ </div>
750
+ <div
751
+ :class="[
752
+ 'relative p-1 flex-1 prose prose-zinc text-xs'
753
+ ]"
754
+ >
755
+ <span
756
+ v-html="$md.inline`${paginationRight}`({
757
+ selected: tableApi.getSelectedRowModel().rows.map((row) => row.original)
758
+ })"
759
+ />
760
+ &nbsp;
761
+ </div>
762
+ </div>
763
+ </div>
764
+ </div>
765
+ </div>
766
+ </template>
767
+
768
+ <i18n lang="json">
769
+ {
770
+ "zh": {
771
+ "total": "共 {count} 条",
772
+ "goto": "前往 {page} 页",
773
+ "table-sort-asc": "升序",
774
+ "table-sort-desc": "降序",
775
+ "table-sort-unsorted": "未排序"
776
+ },
777
+ "ja": {
778
+ "total": "合計 {count} 件",
779
+ "goto": "ページ {page} に移動",
780
+ "table-sort-asc": "昇順",
781
+ "table-sort-desc": "降順",
782
+ "table-sort-unsorted": "未排序"
783
+ },
784
+ "en": {
785
+ "total": "Total {count} items",
786
+ "goto": "Go to page {page}",
787
+ "table-sort-asc": "Ascending",
788
+ "table-sort-desc": "Descending",
789
+ "table-sort-unsorted": "Unsorted"
790
+ }
791
+ }
792
+ </i18n>