@caido-utils/components 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MultiSelect/Container.d.vue.ts +1 -1
- package/dist/MultiSelect/Container.vue +1 -1
- package/dist/MultiSelect/Container.vue.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/package.json +1 -1
- package/dist/Table/Container.d.vue.ts +0 -36
- package/dist/Table/Container.vue +0 -512
- package/dist/Table/Container.vue.d.ts +0 -36
package/dist/index.d.ts
CHANGED
|
@@ -9,4 +9,3 @@ export { default as MenuButton } from "./MenuButton/Container.vue";
|
|
|
9
9
|
export { default as MultiSelect } from "./MultiSelect/Container.vue";
|
|
10
10
|
export { default as RequestEditor } from "./RequestEditor/Container.vue";
|
|
11
11
|
export { default as ResponseEditor } from "./ResponseEditor/Container.vue";
|
|
12
|
-
export { default as Table } from "./Table/Container.vue";
|
package/dist/index.js
CHANGED
|
@@ -9,4 +9,3 @@ export { default as MenuButton } from "./MenuButton/Container.vue";
|
|
|
9
9
|
export { default as MultiSelect } from "./MultiSelect/Container.vue";
|
|
10
10
|
export { default as RequestEditor } from "./RequestEditor/Container.vue";
|
|
11
11
|
export { default as ResponseEditor } from "./ResponseEditor/Container.vue";
|
|
12
|
-
export { default as Table } from "./Table/Container.vue";
|
package/package.json
CHANGED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { MenuItem } from "primevue/menuitem";
|
|
2
|
-
declare const _default: <T extends Record<string, unknown>>(__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<{
|
|
3
|
-
props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<import("vue").ExtractPropTypes<{}>>, never>, never> & {
|
|
4
|
-
items: T[];
|
|
5
|
-
selected: T[];
|
|
6
|
-
columns: {
|
|
7
|
-
key: string;
|
|
8
|
-
header: string;
|
|
9
|
-
width: string;
|
|
10
|
-
sortable?: boolean;
|
|
11
|
-
sortType?: "string" | "number" | "date";
|
|
12
|
-
}[];
|
|
13
|
-
rowKey: (item: T) => string;
|
|
14
|
-
activeKey?: string;
|
|
15
|
-
emptyMessage?: string;
|
|
16
|
-
selectable?: boolean;
|
|
17
|
-
scrollKey?: string;
|
|
18
|
-
contextMenu?: MenuItem[];
|
|
19
|
-
resizable?: boolean;
|
|
20
|
-
} & Partial<{}>> & import("vue").PublicProps;
|
|
21
|
-
expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
|
|
22
|
-
attrs: any;
|
|
23
|
-
slots: {
|
|
24
|
-
[x: string]: ((props: {
|
|
25
|
-
item: any;
|
|
26
|
-
value: any;
|
|
27
|
-
}) => any) | undefined;
|
|
28
|
-
};
|
|
29
|
-
emit: ((evt: "row-click", item: T) => void) & ((evt: "row-contextmenu", item: T, event: MouseEvent) => void) & ((evt: "update:selected", value: T[]) => void);
|
|
30
|
-
}>) => import("vue").VNode & {
|
|
31
|
-
__ctx?: Awaited<typeof __VLS_setup>;
|
|
32
|
-
};
|
|
33
|
-
export default _default;
|
|
34
|
-
type __VLS_PrettifyLocal<T> = {
|
|
35
|
-
[K in keyof T]: T[K];
|
|
36
|
-
} & {};
|
package/dist/Table/Container.vue
DELETED
|
@@ -1,512 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
const scrollMemory = new Map<string, number>();
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts" generic="T extends Record<string, unknown>">
|
|
6
|
-
import ContextMenu from "primevue/contextmenu";
|
|
7
|
-
import type { MenuItem } from "primevue/menuitem";
|
|
8
|
-
import VirtualScroller from "primevue/virtualscroller";
|
|
9
|
-
import {
|
|
10
|
-
computed,
|
|
11
|
-
nextTick,
|
|
12
|
-
onBeforeUnmount,
|
|
13
|
-
onMounted,
|
|
14
|
-
ref,
|
|
15
|
-
shallowRef,
|
|
16
|
-
triggerRef,
|
|
17
|
-
watch,
|
|
18
|
-
} from "vue";
|
|
19
|
-
|
|
20
|
-
type SortType = "string" | "number" | "date";
|
|
21
|
-
|
|
22
|
-
type Column = {
|
|
23
|
-
key: string;
|
|
24
|
-
header: string;
|
|
25
|
-
width: string;
|
|
26
|
-
sortable?: boolean;
|
|
27
|
-
sortType?: SortType;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
type SortOrder = "asc" | "desc" | undefined;
|
|
31
|
-
|
|
32
|
-
const props = withDefaults(
|
|
33
|
-
defineProps<{
|
|
34
|
-
items: T[];
|
|
35
|
-
selected: T[];
|
|
36
|
-
columns: Column[];
|
|
37
|
-
rowKey: (item: T) => string;
|
|
38
|
-
activeKey?: string;
|
|
39
|
-
emptyMessage?: string;
|
|
40
|
-
selectable?: boolean;
|
|
41
|
-
scrollKey?: string;
|
|
42
|
-
contextMenu?: MenuItem[];
|
|
43
|
-
resizable?: boolean;
|
|
44
|
-
}>(),
|
|
45
|
-
{ selectable: false, resizable: false },
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const emit = defineEmits<{
|
|
49
|
-
"update:selected": [value: T[]];
|
|
50
|
-
"row-click": [item: T];
|
|
51
|
-
"row-contextmenu": [item: T, event: MouseEvent];
|
|
52
|
-
}>();
|
|
53
|
-
|
|
54
|
-
const contextMenuRef = ref();
|
|
55
|
-
|
|
56
|
-
function onRowContextMenu(item: T, event: MouseEvent) {
|
|
57
|
-
event.preventDefault();
|
|
58
|
-
emit("row-contextmenu", item, event);
|
|
59
|
-
if (props.contextMenu && contextMenuRef.value) {
|
|
60
|
-
contextMenuRef.value.show(event);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const selectedKeys = ref(new Set<string>());
|
|
65
|
-
|
|
66
|
-
watch(
|
|
67
|
-
() => props.selected,
|
|
68
|
-
(val) => {
|
|
69
|
-
const keys = new Set<string>();
|
|
70
|
-
for (const item of val) {
|
|
71
|
-
keys.add(props.rowKey(item));
|
|
72
|
-
}
|
|
73
|
-
selectedKeys.value = keys;
|
|
74
|
-
},
|
|
75
|
-
{ immediate: true },
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
function syncSelection() {
|
|
79
|
-
const result: T[] = [];
|
|
80
|
-
for (const item of props.items) {
|
|
81
|
-
if (selectedKeys.value.has(props.rowKey(item))) {
|
|
82
|
-
result.push(item);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
emit("update:selected", result);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function toggleSelection(item: T) {
|
|
89
|
-
const key = props.rowKey(item);
|
|
90
|
-
if (selectedKeys.value.has(key)) {
|
|
91
|
-
selectedKeys.value.delete(key);
|
|
92
|
-
} else {
|
|
93
|
-
selectedKeys.value.add(key);
|
|
94
|
-
}
|
|
95
|
-
syncSelection();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function toggleAll() {
|
|
99
|
-
if (selectedKeys.value.size === props.items.length) {
|
|
100
|
-
selectedKeys.value.clear();
|
|
101
|
-
} else {
|
|
102
|
-
for (const item of props.items) {
|
|
103
|
-
selectedKeys.value.add(props.rowKey(item));
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
syncSelection();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const allSelected = computed(
|
|
110
|
-
() =>
|
|
111
|
-
props.items.length > 0 && selectedKeys.value.size === props.items.length,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
function onRowClick(item: T) {
|
|
115
|
-
emit("row-click", item);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function isSelected(item: T): boolean {
|
|
119
|
-
return selectedKeys.value.has(props.rowKey(item));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function isActive(item: T): boolean {
|
|
123
|
-
if (props.activeKey === undefined) return false;
|
|
124
|
-
return props.rowKey(item) === props.activeKey;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const sortKey = ref<string | undefined>(undefined);
|
|
128
|
-
const sortOrder = ref<SortOrder>(undefined);
|
|
129
|
-
|
|
130
|
-
function toggleSort(col: Column) {
|
|
131
|
-
if (!col.sortable) return;
|
|
132
|
-
|
|
133
|
-
if (sortKey.value !== col.key) {
|
|
134
|
-
sortKey.value = col.key;
|
|
135
|
-
sortOrder.value = "asc";
|
|
136
|
-
} else if (sortOrder.value === "asc") {
|
|
137
|
-
sortOrder.value = "desc";
|
|
138
|
-
} else {
|
|
139
|
-
sortKey.value = undefined;
|
|
140
|
-
sortOrder.value = undefined;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const sortedItems = computed(() => {
|
|
145
|
-
if (sortKey.value === undefined || sortOrder.value === undefined) {
|
|
146
|
-
return props.items;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const key = sortKey.value;
|
|
150
|
-
const col = props.columns.find((c) => c.key === key);
|
|
151
|
-
const type = col?.sortType ?? "string";
|
|
152
|
-
const dir = sortOrder.value === "asc" ? 1 : -1;
|
|
153
|
-
const sorted = [...props.items];
|
|
154
|
-
|
|
155
|
-
sorted.sort((a, b) => {
|
|
156
|
-
const aVal = a[key];
|
|
157
|
-
const bVal = b[key];
|
|
158
|
-
|
|
159
|
-
if (aVal === undefined || aVal === "") return 1;
|
|
160
|
-
if (bVal === undefined || bVal === "") return -1;
|
|
161
|
-
|
|
162
|
-
if (type === "number") {
|
|
163
|
-
return (Number(aVal) - Number(bVal)) * dir;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (type === "date") {
|
|
167
|
-
return (
|
|
168
|
-
(new Date(String(aVal)).getTime() - new Date(String(bVal)).getTime()) *
|
|
169
|
-
dir
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return String(aVal).localeCompare(String(bVal)) * dir;
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
return sorted;
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const VIRTUAL_THRESHOLD = 100;
|
|
180
|
-
const useVirtual = computed(
|
|
181
|
-
() => sortedItems.value.length >= VIRTUAL_THRESHOLD,
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
const scrollerKey = ref(0);
|
|
185
|
-
const containerRef = ref<HTMLElement>();
|
|
186
|
-
let resizeObserver: ResizeObserver | undefined;
|
|
187
|
-
|
|
188
|
-
function getScrollElement(): HTMLElement | undefined {
|
|
189
|
-
if (!containerRef.value) return undefined;
|
|
190
|
-
if (useVirtual.value) {
|
|
191
|
-
return (
|
|
192
|
-
containerRef.value.querySelector<HTMLElement>(".p-virtualscroller") ??
|
|
193
|
-
undefined
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
return containerRef.value;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function onScroll(e: Event) {
|
|
200
|
-
if (!props.scrollKey) return;
|
|
201
|
-
const target = e.target as HTMLElement;
|
|
202
|
-
scrollMemory.set(props.scrollKey, target.scrollTop);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function attachScrollListener() {
|
|
206
|
-
const el = getScrollElement();
|
|
207
|
-
el?.addEventListener("scroll", onScroll, { passive: true });
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function detachScrollListener() {
|
|
211
|
-
const el = getScrollElement();
|
|
212
|
-
el?.removeEventListener("scroll", onScroll);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function restoreScrollPosition() {
|
|
216
|
-
if (!props.scrollKey) return;
|
|
217
|
-
const saved = scrollMemory.get(props.scrollKey);
|
|
218
|
-
if (saved === undefined || saved <= 0) return;
|
|
219
|
-
const el = getScrollElement();
|
|
220
|
-
if (el) {
|
|
221
|
-
el.scrollTop = saved;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Resizable columns
|
|
226
|
-
const headerTableRef = ref<HTMLTableElement>();
|
|
227
|
-
const columnWidths = shallowRef<number[]>([]);
|
|
228
|
-
const widthsInitialized = ref(false);
|
|
229
|
-
const resizing = ref(false);
|
|
230
|
-
const resizeColIndex = ref(-1);
|
|
231
|
-
const resizeStartX = ref(0);
|
|
232
|
-
const resizeStartWidth = ref(0);
|
|
233
|
-
|
|
234
|
-
const colStyles = computed(() =>
|
|
235
|
-
props.columns.map((col, i) => {
|
|
236
|
-
if (
|
|
237
|
-
props.resizable &&
|
|
238
|
-
widthsInitialized.value &&
|
|
239
|
-
columnWidths.value[i] !== undefined
|
|
240
|
-
) {
|
|
241
|
-
return { width: `${columnWidths.value[i]}px` };
|
|
242
|
-
}
|
|
243
|
-
return { width: col.width };
|
|
244
|
-
}),
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
function initColumnWidths() {
|
|
248
|
-
if (!props.resizable || !headerTableRef.value) return;
|
|
249
|
-
const tableWidth = headerTableRef.value.offsetWidth;
|
|
250
|
-
if (tableWidth === 0) return;
|
|
251
|
-
const ths = headerTableRef.value.querySelectorAll("thead th");
|
|
252
|
-
const startIdx = props.selectable ? 1 : 0;
|
|
253
|
-
const rawWidths: number[] = [];
|
|
254
|
-
let fixedTotal = 0;
|
|
255
|
-
let zeroCount = 0;
|
|
256
|
-
for (let i = startIdx; i < ths.length; i++) {
|
|
257
|
-
const w = (ths[i] as HTMLElement).offsetWidth;
|
|
258
|
-
rawWidths.push(w);
|
|
259
|
-
if (w === 0) {
|
|
260
|
-
zeroCount++;
|
|
261
|
-
} else {
|
|
262
|
-
fixedTotal += w;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
const checkboxWidth =
|
|
266
|
-
props.selectable && startIdx === 1
|
|
267
|
-
? (ths[0] as HTMLElement).offsetWidth
|
|
268
|
-
: 0;
|
|
269
|
-
const remaining = tableWidth - checkboxWidth - fixedTotal;
|
|
270
|
-
const flexWidth =
|
|
271
|
-
zeroCount > 0 ? Math.max(30, Math.floor(remaining / zeroCount)) : 0;
|
|
272
|
-
const widths = rawWidths.map((w) => (w === 0 ? flexWidth : w));
|
|
273
|
-
columnWidths.value = widths;
|
|
274
|
-
widthsInitialized.value = true;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function onResizeStart(colIndex: number, event: MouseEvent) {
|
|
278
|
-
resizing.value = true;
|
|
279
|
-
resizeColIndex.value = colIndex;
|
|
280
|
-
resizeStartX.value = event.clientX;
|
|
281
|
-
resizeStartWidth.value = columnWidths.value[colIndex] ?? 0;
|
|
282
|
-
document.addEventListener("mousemove", onResizeMove);
|
|
283
|
-
document.addEventListener("mouseup", onResizeEnd);
|
|
284
|
-
document.body.style.cursor = "col-resize";
|
|
285
|
-
document.body.style.userSelect = "none";
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function onResizeMove(event: MouseEvent) {
|
|
289
|
-
if (!resizing.value) return;
|
|
290
|
-
const delta = event.clientX - resizeStartX.value;
|
|
291
|
-
const newWidth = Math.max(30, resizeStartWidth.value + delta);
|
|
292
|
-
columnWidths.value[resizeColIndex.value] = newWidth;
|
|
293
|
-
triggerRef(columnWidths);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
function onResizeEnd() {
|
|
297
|
-
resizing.value = false;
|
|
298
|
-
resizeColIndex.value = -1;
|
|
299
|
-
document.removeEventListener("mousemove", onResizeMove);
|
|
300
|
-
document.removeEventListener("mouseup", onResizeEnd);
|
|
301
|
-
document.body.style.cursor = "";
|
|
302
|
-
document.body.style.userSelect = "";
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
watch(
|
|
306
|
-
() => props.columns.map((c) => c.key).join(","),
|
|
307
|
-
async () => {
|
|
308
|
-
if (!props.resizable) return;
|
|
309
|
-
widthsInitialized.value = false;
|
|
310
|
-
await nextTick();
|
|
311
|
-
initColumnWidths();
|
|
312
|
-
},
|
|
313
|
-
);
|
|
314
|
-
|
|
315
|
-
watch(scrollerKey, async () => {
|
|
316
|
-
await nextTick();
|
|
317
|
-
attachScrollListener();
|
|
318
|
-
restoreScrollPosition();
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
onMounted(() => {
|
|
322
|
-
if (containerRef.value === undefined) return;
|
|
323
|
-
resizeObserver = new ResizeObserver((entries) => {
|
|
324
|
-
const entry = entries[0];
|
|
325
|
-
if (entry !== undefined && entry.contentRect.height > 0) {
|
|
326
|
-
scrollerKey.value++;
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
resizeObserver.observe(containerRef.value);
|
|
330
|
-
|
|
331
|
-
if (!useVirtual.value) {
|
|
332
|
-
nextTick(() => {
|
|
333
|
-
attachScrollListener();
|
|
334
|
-
restoreScrollPosition();
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
nextTick(() => initColumnWidths());
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
onBeforeUnmount(() => {
|
|
342
|
-
detachScrollListener();
|
|
343
|
-
resizeObserver?.disconnect();
|
|
344
|
-
if (resizing.value) {
|
|
345
|
-
onResizeEnd();
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
</script>
|
|
349
|
-
|
|
350
|
-
<template>
|
|
351
|
-
<ContextMenu v-if="contextMenu" ref="contextMenuRef" :model="contextMenu" />
|
|
352
|
-
<div class="h-full flex flex-col min-h-0">
|
|
353
|
-
<table
|
|
354
|
-
ref="headerTableRef"
|
|
355
|
-
class="w-full border-collapse"
|
|
356
|
-
:style="{ tableLayout: 'fixed' }"
|
|
357
|
-
>
|
|
358
|
-
<colgroup>
|
|
359
|
-
<col v-if="selectable" style="width: 32px" />
|
|
360
|
-
<col v-for="(col, i) in columns" :key="col.key" :style="colStyles[i]" />
|
|
361
|
-
</colgroup>
|
|
362
|
-
<thead>
|
|
363
|
-
<tr>
|
|
364
|
-
<th
|
|
365
|
-
v-if="selectable"
|
|
366
|
-
class="px-2 py-1.5 bg-surface-900 sticky top-0 z-10"
|
|
367
|
-
>
|
|
368
|
-
<div
|
|
369
|
-
class="w-3.5 h-3.5 rounded-sm border cursor-pointer flex items-center justify-center transition-colors"
|
|
370
|
-
:class="
|
|
371
|
-
allSelected
|
|
372
|
-
? 'bg-amber-500 border-amber-500'
|
|
373
|
-
: 'border-surface-500 hover:border-surface-300'
|
|
374
|
-
"
|
|
375
|
-
@click="toggleAll()"
|
|
376
|
-
>
|
|
377
|
-
<i
|
|
378
|
-
v-if="allSelected"
|
|
379
|
-
class="fas fa-check text-[8px] text-white"
|
|
380
|
-
/>
|
|
381
|
-
</div>
|
|
382
|
-
</th>
|
|
383
|
-
<th
|
|
384
|
-
v-for="(col, i) in columns"
|
|
385
|
-
:key="col.key"
|
|
386
|
-
class="px-2.5 py-1.5 font-mono text-sm font-semibold text-surface-300 text-left bg-surface-900 border-b border-surface-700/50 sticky top-0 z-10 select-none"
|
|
387
|
-
:class="resizable ? 'relative' : ''"
|
|
388
|
-
>
|
|
389
|
-
<span
|
|
390
|
-
class="flex items-center gap-1.5"
|
|
391
|
-
:class="
|
|
392
|
-
col.sortable
|
|
393
|
-
? 'cursor-pointer hover:text-surface-100 transition-colors'
|
|
394
|
-
: ''
|
|
395
|
-
"
|
|
396
|
-
@click="toggleSort(col)"
|
|
397
|
-
>
|
|
398
|
-
{{ col.header }}
|
|
399
|
-
<i
|
|
400
|
-
v-if="col.sortable && sortKey === col.key"
|
|
401
|
-
:class="[
|
|
402
|
-
'fas text-[9px]',
|
|
403
|
-
sortOrder === 'asc' ? 'fa-chevron-up' : 'fa-chevron-down',
|
|
404
|
-
]"
|
|
405
|
-
/>
|
|
406
|
-
</span>
|
|
407
|
-
<div
|
|
408
|
-
v-if="resizable"
|
|
409
|
-
class="absolute top-0 -right-px w-1.5 h-full cursor-col-resize bg-surface-700 hover:bg-amber-500 z-20"
|
|
410
|
-
@mousedown.prevent.stop="onResizeStart(i, $event)"
|
|
411
|
-
/>
|
|
412
|
-
</th>
|
|
413
|
-
</tr>
|
|
414
|
-
</thead>
|
|
415
|
-
</table>
|
|
416
|
-
<div
|
|
417
|
-
ref="containerRef"
|
|
418
|
-
class="flex-1 min-h-0"
|
|
419
|
-
:class="useVirtual ? 'overflow-hidden' : 'overflow-y-auto'"
|
|
420
|
-
>
|
|
421
|
-
<div
|
|
422
|
-
v-if="sortedItems.length === 0"
|
|
423
|
-
class="flex flex-col items-center justify-center h-full gap-3 text-surface-500"
|
|
424
|
-
>
|
|
425
|
-
<i class="fas fa-inbox text-3xl text-surface-600" />
|
|
426
|
-
<span class="text-sm">{{ emptyMessage ?? "No data" }}</span>
|
|
427
|
-
</div>
|
|
428
|
-
<VirtualScroller
|
|
429
|
-
v-else
|
|
430
|
-
:key="scrollerKey"
|
|
431
|
-
:items="sortedItems"
|
|
432
|
-
:item-size="33"
|
|
433
|
-
:disabled="!useVirtual"
|
|
434
|
-
class="h-full"
|
|
435
|
-
>
|
|
436
|
-
<template
|
|
437
|
-
#content="{
|
|
438
|
-
items: visibleItems,
|
|
439
|
-
styleClass,
|
|
440
|
-
contentRef,
|
|
441
|
-
contentStyle,
|
|
442
|
-
}"
|
|
443
|
-
>
|
|
444
|
-
<table
|
|
445
|
-
:ref="contentRef"
|
|
446
|
-
:class="styleClass"
|
|
447
|
-
class="w-full border-collapse"
|
|
448
|
-
:style="{ tableLayout: 'fixed', ...contentStyle }"
|
|
449
|
-
>
|
|
450
|
-
<colgroup>
|
|
451
|
-
<col v-if="selectable" style="width: 32px" />
|
|
452
|
-
<col
|
|
453
|
-
v-for="(col, i) in columns"
|
|
454
|
-
:key="col.key"
|
|
455
|
-
:style="colStyles[i]"
|
|
456
|
-
/>
|
|
457
|
-
</colgroup>
|
|
458
|
-
<tbody>
|
|
459
|
-
<tr
|
|
460
|
-
v-for="item in visibleItems as T[]"
|
|
461
|
-
:key="rowKey(item)"
|
|
462
|
-
class="cursor-pointer"
|
|
463
|
-
:class="[
|
|
464
|
-
isActive(item)
|
|
465
|
-
? 'bg-amber-400/15 hover:bg-amber-400/25'
|
|
466
|
-
: isSelected(item)
|
|
467
|
-
? 'bg-amber-400/10 hover:bg-amber-400/15'
|
|
468
|
-
: 'even:bg-white/5 hover:bg-white/10',
|
|
469
|
-
]"
|
|
470
|
-
@click="onRowClick(item)"
|
|
471
|
-
@contextmenu="onRowContextMenu(item, $event)"
|
|
472
|
-
>
|
|
473
|
-
<td
|
|
474
|
-
v-if="selectable"
|
|
475
|
-
class="px-2 py-1.5 border-b border-surface-700/50"
|
|
476
|
-
@click.stop="toggleSelection(item)"
|
|
477
|
-
>
|
|
478
|
-
<div
|
|
479
|
-
class="w-3.5 h-3.5 rounded-sm border cursor-pointer flex items-center justify-center transition-colors"
|
|
480
|
-
:class="
|
|
481
|
-
isSelected(item)
|
|
482
|
-
? 'bg-amber-500 border-amber-500'
|
|
483
|
-
: 'border-surface-600 hover:border-surface-400'
|
|
484
|
-
"
|
|
485
|
-
>
|
|
486
|
-
<i
|
|
487
|
-
v-if="isSelected(item)"
|
|
488
|
-
class="fas fa-check text-[8px] text-white"
|
|
489
|
-
/>
|
|
490
|
-
</div>
|
|
491
|
-
</td>
|
|
492
|
-
<td
|
|
493
|
-
v-for="col in columns"
|
|
494
|
-
:key="col.key"
|
|
495
|
-
class="px-2.5 py-1.5 font-mono text-[13px] font-medium text-surface-200 overflow-hidden text-ellipsis whitespace-nowrap border-b border-surface-700/50"
|
|
496
|
-
>
|
|
497
|
-
<slot
|
|
498
|
-
:name="`cell-${col.key}`"
|
|
499
|
-
:item="item"
|
|
500
|
-
:value="item[col.key]"
|
|
501
|
-
>
|
|
502
|
-
<span class="truncate block">{{ item[col.key] }}</span>
|
|
503
|
-
</slot>
|
|
504
|
-
</td>
|
|
505
|
-
</tr>
|
|
506
|
-
</tbody>
|
|
507
|
-
</table>
|
|
508
|
-
</template>
|
|
509
|
-
</VirtualScroller>
|
|
510
|
-
</div>
|
|
511
|
-
</div>
|
|
512
|
-
</template>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { MenuItem } from "primevue/menuitem";
|
|
2
|
-
declare const _default: <T extends Record<string, unknown>>(__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<{
|
|
3
|
-
props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<import("vue").ExtractPropTypes<{}>>, never>, never> & {
|
|
4
|
-
items: T[];
|
|
5
|
-
selected: T[];
|
|
6
|
-
columns: {
|
|
7
|
-
key: string;
|
|
8
|
-
header: string;
|
|
9
|
-
width: string;
|
|
10
|
-
sortable?: boolean;
|
|
11
|
-
sortType?: "string" | "number" | "date";
|
|
12
|
-
}[];
|
|
13
|
-
rowKey: (item: T) => string;
|
|
14
|
-
activeKey?: string;
|
|
15
|
-
emptyMessage?: string;
|
|
16
|
-
selectable?: boolean;
|
|
17
|
-
scrollKey?: string;
|
|
18
|
-
contextMenu?: MenuItem[];
|
|
19
|
-
resizable?: boolean;
|
|
20
|
-
} & Partial<{}>> & import("vue").PublicProps;
|
|
21
|
-
expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
|
|
22
|
-
attrs: any;
|
|
23
|
-
slots: {
|
|
24
|
-
[x: string]: ((props: {
|
|
25
|
-
item: any;
|
|
26
|
-
value: any;
|
|
27
|
-
}) => any) | undefined;
|
|
28
|
-
};
|
|
29
|
-
emit: ((evt: "row-click", item: T) => void) & ((evt: "row-contextmenu", item: T, event: MouseEvent) => void) & ((evt: "update:selected", value: T[]) => void);
|
|
30
|
-
}>) => import("vue").VNode & {
|
|
31
|
-
__ctx?: Awaited<typeof __VLS_setup>;
|
|
32
|
-
};
|
|
33
|
-
export default _default;
|
|
34
|
-
type __VLS_PrettifyLocal<T> = {
|
|
35
|
-
[K in keyof T]: T[K];
|
|
36
|
-
} & {};
|