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