svelora 3.0.0 → 3.0.2
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/Accordion/Accordion.svelte +66 -97
- package/dist/Alert/Alert.svelte +39 -64
- package/dist/Alert/Alert.svelte.d.ts +1 -1
- package/dist/Avatar/Avatar.svelte +35 -75
- package/dist/AvatarGroup/AvatarGroup.svelte +38 -55
- package/dist/Badge/Badge.svelte +28 -50
- package/dist/Banner/Banner.svelte +46 -41
- package/dist/Banner/Banner.svelte.d.ts +1 -1
- package/dist/Breadcrumb/Breadcrumb.svelte +32 -26
- package/dist/Button/Button.svelte +70 -138
- package/dist/Calendar/Calendar.svelte +94 -157
- package/dist/Calendar/Calendar.svelte.d.ts +1 -1
- package/dist/Card/Card.svelte +18 -31
- package/dist/Carousel/Carousel.svelte +118 -173
- package/dist/Checkbox/Checkbox.svelte +52 -97
- package/dist/CheckboxGroup/CheckboxGroup.svelte +62 -107
- package/dist/CheckboxGroup/CheckboxGroup.svelte.d.ts +1 -1
- package/dist/Chip/Chip.svelte +22 -34
- package/dist/CodeBlock/CodeBlock.svelte +42 -59
- package/dist/Collapsible/Collapsible.svelte +22 -38
- package/dist/Collapsible/Collapsible.svelte.d.ts +1 -1
- package/dist/Collapsible/CollapsibleTestWrapper.svelte +2 -5
- package/dist/Collapsible/CollapsibleTestWrapper.svelte.d.ts +1 -1
- package/dist/Command/Command.svelte +40 -77
- package/dist/Command/Command.svelte.d.ts +1 -1
- package/dist/Command/CommandTestWrapper.svelte +2 -10
- package/dist/Command/CommandTestWrapper.svelte.d.ts +1 -1
- package/dist/Container/Container.svelte +11 -14
- package/dist/ContextMenu/ContextMenu.svelte +51 -114
- package/dist/ContextMenu/ContextMenu.svelte.d.ts +1 -1
- package/dist/Drawer/Drawer.svelte +72 -110
- package/dist/Drawer/DrawerTriggerTestWrapper.svelte +1 -2
- package/dist/DropdownMenu/DropdownMenu.svelte +63 -124
- package/dist/DropdownMenu/DropdownMenu.svelte.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuTriggerTestWrapper.svelte +2 -5
- package/dist/Editor/Editor.svelte +441 -576
- package/dist/Editor/Editor.svelte.d.ts +1 -1
- package/dist/Editor/EditorUrlPrompt.svelte +40 -53
- package/dist/Editor/SlashPopup.svelte +12 -24
- package/dist/Empty/Empty.svelte +32 -63
- package/dist/FieldGroup/FieldGroup.svelte +23 -38
- package/dist/FileUpload/FileUpload.svelte +242 -320
- package/dist/FileUpload/FileUpload.svelte.d.ts +1 -1
- package/dist/Fonts/Fonts.svelte +15 -37
- package/dist/Form/Form.svelte +112 -170
- package/dist/FormField/FormField.svelte +102 -135
- package/dist/Icon/Icon.svelte +7 -32
- package/dist/Input/Input.svelte +71 -141
- package/dist/Input/Input.svelte.d.ts +2 -2
- package/dist/Kbd/Kbd.svelte +18 -34
- package/dist/Link/Link.svelte +129 -196
- package/dist/LocaleButton/LocaleButton.svelte +165 -0
- package/dist/LocaleButton/LocaleButton.svelte.d.ts +5 -0
- package/dist/LocaleButton/index.d.ts +2 -0
- package/dist/LocaleButton/index.js +1 -0
- package/dist/LocaleButton/locale-button.types.d.ts +182 -0
- package/dist/LocaleButton/locale-button.types.js +1 -0
- package/dist/LocaleButton/locale-button.variants.d.ts +61 -0
- package/dist/LocaleButton/locale-button.variants.js +34 -0
- package/dist/Modal/Modal.svelte +52 -106
- package/dist/Modal/ModalTriggerTestWrapper.svelte +1 -2
- package/dist/Pagination/Pagination.svelte +48 -92
- package/dist/Pagination/pagination.variants.d.ts +1 -1
- package/dist/PinInput/PinInput.svelte +57 -111
- package/dist/PinInput/PinInput.svelte.d.ts +1 -1
- package/dist/Popover/Popover.svelte +28 -61
- package/dist/Popover/Popover.svelte.d.ts +1 -1
- package/dist/Progress/Progress.svelte +75 -94
- package/dist/RadioGroup/RadioGroup.svelte +54 -99
- package/dist/RadioGroup/RadioGroup.svelte.d.ts +1 -1
- package/dist/Select/Select.svelte +112 -269
- package/dist/Select/Select.svelte.d.ts +1 -1
- package/dist/SelectMenu/SelectMenu.svelte +211 -409
- package/dist/SelectMenu/SelectMenu.svelte.d.ts +1 -1
- package/dist/SelectMenu/SelectMenuFormFieldTestWrapper.svelte +3 -6
- package/dist/Separator/Separator.svelte +29 -44
- package/dist/Skeleton/Skeleton.svelte +11 -23
- package/dist/Slideover/Slideover.svelte +52 -106
- package/dist/Slideover/SlideoverTriggerTestWrapper.svelte +1 -2
- package/dist/Slider/Slider.svelte +48 -84
- package/dist/Slider/Slider.svelte.d.ts +1 -1
- package/dist/Stepper/Stepper.svelte +139 -132
- package/dist/Stepper/Stepper.svelte.d.ts +1 -1
- package/dist/Switch/Switch.svelte +62 -98
- package/dist/Table/Table.svelte +232 -283
- package/dist/Table/table.variants.d.ts +1 -1
- package/dist/Tabs/Tabs.svelte +96 -129
- package/dist/Tabs/Tabs.svelte.d.ts +1 -1
- package/dist/Textarea/Textarea.svelte +90 -173
- package/dist/Textarea/Textarea.svelte.d.ts +1 -1
- package/dist/ThemeModeButton/ThemeModeButton.svelte +16 -38
- package/dist/Timeline/Timeline.svelte +75 -54
- package/dist/Toast/Toaster.svelte +8 -25
- package/dist/Tooltip/Tooltip.svelte +34 -66
- package/dist/Tooltip/Tooltip.svelte.d.ts +1 -1
- package/dist/Tooltip/TooltipTestWrapper.svelte +2 -5
- package/dist/User/User.svelte +33 -49
- package/dist/docs/navigation.d.ts +1 -1
- package/dist/docs/navigation.js +8 -1
- package/dist/hooks/HookContextProbe.svelte +2 -4
- package/dist/hooks/HookContextProvider.svelte +8 -6
- package/dist/hooks/HookEmitProbe.svelte +8 -11
- package/dist/i18n.d.ts +2 -0
- package/dist/i18n.js +19 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/svelora-docs.data.json +4 -2
- package/dist/theme.css +1 -1
- package/package.json +16 -8
package/dist/Table/Table.svelte
CHANGED
|
@@ -1,57 +1,25 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
export type Props = TableProps;
|
|
1
|
+
<script lang="ts" module>export {};
|
|
3
2
|
</script>
|
|
4
3
|
|
|
5
4
|
<!-- eslint-disable-next-line @typescript-eslint/no-explicit-any -->
|
|
6
5
|
<script lang="ts" generics="T extends Record<string, any>">;
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const config = getComponentConfig('table', tableDefaults);
|
|
17
|
-
const icons = getComponentConfig('icons', iconsDefaults);
|
|
18
|
-
let { ref = $bindable(null), as = 'div', data = [] as T[], columns: columnsProp, rowKey, caption,
|
|
19
|
-
// Sorting
|
|
20
|
-
sorting = $bindable([]), multiSort = false, manualSorting = false, onSortingChange,
|
|
21
|
-
// Global Filter
|
|
22
|
-
globalFilter = $bindable(''), globalFilterKeys, manualFiltering = false, onGlobalFilterChange,
|
|
23
|
-
// Column Filters
|
|
24
|
-
columnFilters = $bindable({}), onColumnFiltersChange,
|
|
25
|
-
// Pagination
|
|
26
|
-
page = $bindable(0), pageSize = 10, manualPagination = false, onPageChange,
|
|
27
|
-
// Row Selection
|
|
28
|
-
selection, selectedRows = $bindable([]), onSelectionChange,
|
|
29
|
-
// Column Visibility
|
|
30
|
-
columnVisibility = $bindable(), onColumnVisibilityChange,
|
|
31
|
-
// Column Pinning
|
|
32
|
-
columnPinning = $bindable(),
|
|
33
|
-
// Row Pinning
|
|
34
|
-
pinnedRows = $bindable([]), onPinnedRowsChange,
|
|
35
|
-
// Row Expanding
|
|
36
|
-
expandedRows = $bindable([]), onExpandedChange,
|
|
37
|
-
// Column Resizing
|
|
38
|
-
columnSizing = $bindable({}), onColumnSizingChange,
|
|
39
|
-
// Visual
|
|
40
|
-
loading = false, loadingColor = config.defaultVariants.loadingColor ?? 'primary', loadingAnimation = config.defaultVariants.loadingAnimation ?? 'carousel', empty = 'No data.', striped = false, hoverable = config.defaultVariants.hoverable ?? true, sticky = false, action,
|
|
41
|
-
// Callbacks
|
|
42
|
-
onRowClick, onRowHover, onRowContextmenu,
|
|
43
|
-
// Styling
|
|
44
|
-
ui, class: className,
|
|
45
|
-
// Slots
|
|
46
|
-
captionSlot, emptySlot, loadingSlot, expandedSlot, bodyTopSlot, bodyBottomSlot, headerSlot, cellSlot, ...restProps }: TableProps<T> = $props();
|
|
6
|
+
import Button from "../Button/Button.svelte";
|
|
7
|
+
import Checkbox from "../Checkbox/Checkbox.svelte";
|
|
8
|
+
import { getComponentConfig, iconsDefaults } from "../config.js";
|
|
9
|
+
import Icon from "../Icon/Icon.svelte";
|
|
10
|
+
import { autoGenerateColumns, computePinOffsets, filterByColumns, filterByGlobal, formatCellValue, getRowKey, paginateData, resolveVisibleColumns, sortData } from "./table.utils.js";
|
|
11
|
+
import { tableDefaults, tableVariants } from "./table.variants.js";
|
|
12
|
+
const config = getComponentConfig("table", tableDefaults);
|
|
13
|
+
const icons = getComponentConfig("icons", iconsDefaults);
|
|
14
|
+
let { ref = $bindable(null), as = "div", data = [], columns: columnsProp, rowKey, caption, sorting = $bindable([]), multiSort = false, manualSorting = false, onSortingChange, globalFilter = $bindable(""), globalFilterKeys, manualFiltering = false, onGlobalFilterChange, columnFilters = $bindable({}), onColumnFiltersChange, page = $bindable(0), pageSize = 10, manualPagination = false, onPageChange, selection, selectedRows = $bindable([]), onSelectionChange, columnVisibility = $bindable(), onColumnVisibilityChange, columnPinning = $bindable(), pinnedRows = $bindable([]), onPinnedRowsChange, expandedRows = $bindable([]), onExpandedChange, columnSizing = $bindable({}), onColumnSizingChange, loading = false, loadingColor = config.defaultVariants.loadingColor ?? "primary", loadingAnimation = config.defaultVariants.loadingAnimation ?? "carousel", empty = "No data.", striped = false, hoverable = config.defaultVariants.hoverable ?? true, sticky = false, action, onRowClick, onRowHover, onRowContextmenu, ui, class: className, captionSlot, emptySlot, loadingSlot, expandedSlot, bodyTopSlot, bodyBottomSlot, headerSlot, cellSlot, ...restProps } = $props();
|
|
47
15
|
// =========================================================================
|
|
48
16
|
// Apply Svelte action on root element
|
|
49
17
|
// =========================================================================
|
|
50
18
|
$effect(() => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
19
|
+
if (ref && action) {
|
|
20
|
+
const result = action(ref);
|
|
21
|
+
return () => result?.destroy?.();
|
|
22
|
+
}
|
|
55
23
|
});
|
|
56
24
|
// =========================================================================
|
|
57
25
|
// Change notifications — skip initial mount, fire only on subsequent changes
|
|
@@ -63,331 +31,312 @@ let _prevColumnVisibility = columnVisibility;
|
|
|
63
31
|
let _prevPinnedRows = pinnedRows;
|
|
64
32
|
let _prevExpandedRows = expandedRows;
|
|
65
33
|
$effect(() => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
34
|
+
if (globalFilter !== _prevGlobalFilter) {
|
|
35
|
+
_prevGlobalFilter = globalFilter;
|
|
36
|
+
onGlobalFilterChange?.(globalFilter);
|
|
37
|
+
}
|
|
70
38
|
});
|
|
71
39
|
$effect(() => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
40
|
+
if (columnFilters !== _prevColumnFilters) {
|
|
41
|
+
_prevColumnFilters = columnFilters;
|
|
42
|
+
onColumnFiltersChange?.(columnFilters);
|
|
43
|
+
}
|
|
76
44
|
});
|
|
77
45
|
$effect(() => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
46
|
+
if (page !== _prevPage) {
|
|
47
|
+
_prevPage = page;
|
|
48
|
+
onPageChange?.(page);
|
|
49
|
+
}
|
|
82
50
|
});
|
|
83
51
|
$effect(() => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
52
|
+
if (columnVisibility !== _prevColumnVisibility) {
|
|
53
|
+
_prevColumnVisibility = columnVisibility;
|
|
54
|
+
if (columnVisibility !== undefined) onColumnVisibilityChange?.(columnVisibility);
|
|
55
|
+
}
|
|
89
56
|
});
|
|
90
57
|
$effect(() => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
58
|
+
if (pinnedRows !== _prevPinnedRows) {
|
|
59
|
+
_prevPinnedRows = pinnedRows;
|
|
60
|
+
onPinnedRowsChange?.(pinnedRows);
|
|
61
|
+
}
|
|
95
62
|
});
|
|
96
63
|
$effect(() => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
64
|
+
if (expandedRows !== _prevExpandedRows) {
|
|
65
|
+
_prevExpandedRows = expandedRows;
|
|
66
|
+
onExpandedChange?.(expandedRows);
|
|
67
|
+
}
|
|
101
68
|
});
|
|
102
69
|
// =========================================================================
|
|
103
70
|
// Resolved Columns
|
|
104
71
|
// =========================================================================
|
|
105
|
-
const resolvedColumns = $derived.by(()
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return autoGenerateColumns(data);
|
|
72
|
+
const resolvedColumns = $derived.by(() => {
|
|
73
|
+
if (columnsProp && columnsProp.length > 0) return columnsProp;
|
|
74
|
+
return autoGenerateColumns(data);
|
|
109
75
|
});
|
|
110
76
|
const visibleColumns = $derived(resolveVisibleColumns(resolvedColumns, columnVisibility, columnPinning));
|
|
111
77
|
const hasFooter = $derived(visibleColumns.some((col) => col.footer));
|
|
112
|
-
const totalColspan = $derived(visibleColumns.length + (selection ===
|
|
78
|
+
const totalColspan = $derived(visibleColumns.length + (selection === "multiple" ? 1 : 0));
|
|
113
79
|
// =========================================================================
|
|
114
80
|
// Data Pipeline: filter → sort → paginate
|
|
115
81
|
// =========================================================================
|
|
116
82
|
const filteredData = $derived.by(() => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return result;
|
|
83
|
+
if (manualFiltering) return data;
|
|
84
|
+
let result = data;
|
|
85
|
+
if (globalFilter) {
|
|
86
|
+
result = filterByGlobal(result, globalFilter, globalFilterKeys);
|
|
87
|
+
}
|
|
88
|
+
if (columnFilters && Object.keys(columnFilters).length > 0) {
|
|
89
|
+
result = filterByColumns(result, columnFilters, resolvedColumns);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
127
92
|
});
|
|
128
93
|
const sortedData = $derived.by(() => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return sortData(filteredData, sorting, resolvedColumns);
|
|
94
|
+
if (manualSorting || sorting.length === 0) return filteredData;
|
|
95
|
+
return sortData(filteredData, sorting, resolvedColumns);
|
|
132
96
|
});
|
|
133
97
|
const paginatedData = $derived.by(() => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return sortedData;
|
|
138
|
-
return paginateData(sortedData, page, pageSize);
|
|
98
|
+
if (manualPagination) return sortedData;
|
|
99
|
+
if (pageSize <= 0) return sortedData;
|
|
100
|
+
return paginateData(sortedData, page, pageSize);
|
|
139
101
|
});
|
|
140
102
|
// =========================================================================
|
|
141
103
|
// Row Pinning — split paginated data into pinned (top) + unpinned
|
|
142
104
|
// =========================================================================
|
|
143
105
|
const pinnedKeySet = $derived(new Set(pinnedRows));
|
|
144
106
|
const pinnedData = $derived.by(() => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return sortedData.filter((row, i) => pinnedKeySet.has(getRowKey(row, rowKey, i)));
|
|
107
|
+
if (pinnedRows.length === 0) return [];
|
|
108
|
+
return sortedData.filter((row, i) => pinnedKeySet.has(getRowKey(row, rowKey, i)));
|
|
148
109
|
});
|
|
149
110
|
const unpinnedPaginatedData = $derived.by(() => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
111
|
+
if (pinnedRows.length === 0) return paginatedData;
|
|
112
|
+
return paginatedData.filter((row, i) => {
|
|
113
|
+
const absIdx = manualPagination ? i : page * pageSize + i;
|
|
114
|
+
return !pinnedKeySet.has(getRowKey(row, rowKey, absIdx));
|
|
115
|
+
});
|
|
156
116
|
});
|
|
157
117
|
const hasVisibleRows = $derived(pinnedData.length > 0 || unpinnedPaginatedData.length > 0);
|
|
158
118
|
// =========================================================================
|
|
159
119
|
// Sorting
|
|
160
120
|
// =========================================================================
|
|
161
|
-
function getSortDirection(key
|
|
162
|
-
|
|
163
|
-
|
|
121
|
+
function getSortDirection(key) {
|
|
122
|
+
const item = sorting.find((s) => s.key === key);
|
|
123
|
+
return item ? item.direction : null;
|
|
164
124
|
}
|
|
165
|
-
function toggleSort(key
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
125
|
+
function toggleSort(key, event = undefined) {
|
|
126
|
+
const current = getSortDirection(key);
|
|
127
|
+
let next;
|
|
128
|
+
if (current === null) next = {
|
|
129
|
+
key,
|
|
130
|
+
direction: "asc"
|
|
131
|
+
};
|
|
132
|
+
else if (current === "asc") next = {
|
|
133
|
+
key,
|
|
134
|
+
direction: "desc"
|
|
135
|
+
};
|
|
136
|
+
else next = null;
|
|
137
|
+
let newSorting;
|
|
138
|
+
if (multiSort && event?.shiftKey) {
|
|
139
|
+
const without = sorting.filter((s) => s.key !== key);
|
|
140
|
+
newSorting = next ? [...without, next] : without;
|
|
141
|
+
} else {
|
|
142
|
+
newSorting = next ? [next] : [];
|
|
143
|
+
}
|
|
144
|
+
sorting = newSorting;
|
|
145
|
+
onSortingChange?.(newSorting);
|
|
184
146
|
}
|
|
185
147
|
// =========================================================================
|
|
186
148
|
// Row Selection — uses actual visible rows (pinned + unpinned on page)
|
|
187
149
|
// =========================================================================
|
|
188
150
|
const selectedKeySet = $derived.by(() => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return new Set(selectedRows.map((row, i) => getRowKey(row, rowKey, i)));
|
|
151
|
+
if (!selection) return new Set();
|
|
152
|
+
return new Set(selectedRows.map((row, i) => getRowKey(row, rowKey, i)));
|
|
192
153
|
});
|
|
193
|
-
const actualVisibleRows = $derived.by(()
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
154
|
+
const actualVisibleRows = $derived.by(() => {
|
|
155
|
+
const rows = [];
|
|
156
|
+
for (let i = 0; i < pinnedData.length; i++) {
|
|
157
|
+
rows.push({
|
|
158
|
+
row: pinnedData[i],
|
|
159
|
+
absIdx: i
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
for (let i = 0; i < unpinnedPaginatedData.length; i++) {
|
|
163
|
+
const absIdx = manualPagination ? i : page * pageSize + i;
|
|
164
|
+
rows.push({
|
|
165
|
+
row: unpinnedPaginatedData[i],
|
|
166
|
+
absIdx
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return rows;
|
|
209
170
|
});
|
|
210
|
-
function isRowSelected(row
|
|
211
|
-
|
|
171
|
+
function isRowSelected(row, index) {
|
|
172
|
+
return selectedKeySet.has(getRowKey(row, rowKey, index));
|
|
212
173
|
}
|
|
213
|
-
function toggleRowSelect(row
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
selectedRows = next;
|
|
233
|
-
onSelectionChange?.(next);
|
|
174
|
+
function toggleRowSelect(row, index) {
|
|
175
|
+
if (!selection) return;
|
|
176
|
+
const key = getRowKey(row, rowKey, index);
|
|
177
|
+
if (selection === "single") {
|
|
178
|
+
const isSelected = selectedKeySet.has(key);
|
|
179
|
+
const next = isSelected ? [] : [row];
|
|
180
|
+
selectedRows = next;
|
|
181
|
+
onSelectionChange?.(next);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const isSelected = selectedKeySet.has(key);
|
|
185
|
+
let next;
|
|
186
|
+
if (isSelected) {
|
|
187
|
+
next = selectedRows.filter((r, i) => getRowKey(r, rowKey, i) !== key);
|
|
188
|
+
} else {
|
|
189
|
+
next = [...selectedRows, row];
|
|
190
|
+
}
|
|
191
|
+
selectedRows = next;
|
|
192
|
+
onSelectionChange?.(next);
|
|
234
193
|
}
|
|
235
|
-
const allVisibleSelected = $derived(selection ===
|
|
236
|
-
|
|
237
|
-
actualVisibleRows.every(({ row, absIdx }) => isRowSelected(row, absIdx)));
|
|
238
|
-
const someVisibleSelected = $derived(selection === 'multiple' &&
|
|
239
|
-
actualVisibleRows.length > 0 &&
|
|
240
|
-
actualVisibleRows.some(({ row, absIdx }) => isRowSelected(row, absIdx)) &&
|
|
241
|
-
!allVisibleSelected);
|
|
194
|
+
const allVisibleSelected = $derived(selection === "multiple" && actualVisibleRows.length > 0 && actualVisibleRows.every(({ row, absIdx }) => isRowSelected(row, absIdx)));
|
|
195
|
+
const someVisibleSelected = $derived(selection === "multiple" && actualVisibleRows.length > 0 && actualVisibleRows.some(({ row, absIdx }) => isRowSelected(row, absIdx)) && !allVisibleSelected);
|
|
242
196
|
function toggleSelectAll() {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
next = [...selectedRows, ...toAdd];
|
|
256
|
-
}
|
|
257
|
-
selectedRows = next;
|
|
258
|
-
onSelectionChange?.(next);
|
|
197
|
+
if (!selection || selection !== "multiple") return;
|
|
198
|
+
let next;
|
|
199
|
+
if (allVisibleSelected) {
|
|
200
|
+
const visibleKeys = new Set(actualVisibleRows.map(({ row, absIdx }) => getRowKey(row, rowKey, absIdx)));
|
|
201
|
+
next = selectedRows.filter((r, i) => !visibleKeys.has(getRowKey(r, rowKey, i)));
|
|
202
|
+
} else {
|
|
203
|
+
const existing = new Set(selectedRows.map((r, i) => getRowKey(r, rowKey, i)));
|
|
204
|
+
const toAdd = actualVisibleRows.filter(({ row, absIdx }) => !existing.has(getRowKey(row, rowKey, absIdx))).map(({ row }) => row);
|
|
205
|
+
next = [...selectedRows, ...toAdd];
|
|
206
|
+
}
|
|
207
|
+
selectedRows = next;
|
|
208
|
+
onSelectionChange?.(next);
|
|
259
209
|
}
|
|
260
210
|
// =========================================================================
|
|
261
211
|
// Row Expanding
|
|
262
212
|
// =========================================================================
|
|
263
|
-
function isRowExpanded(key
|
|
264
|
-
|
|
213
|
+
function isRowExpanded(key) {
|
|
214
|
+
return expandedRows.includes(key);
|
|
265
215
|
}
|
|
266
216
|
// =========================================================================
|
|
267
217
|
// Column Resizing
|
|
268
218
|
// =========================================================================
|
|
269
|
-
let resizing = $state
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
219
|
+
let resizing = $state(null);
|
|
220
|
+
function onResizeStart(e, col) {
|
|
221
|
+
e.preventDefault();
|
|
222
|
+
const currentWidth = columnSizing[col.key] ?? col.width ?? 150;
|
|
223
|
+
resizing = {
|
|
224
|
+
key: col.key,
|
|
225
|
+
startX: e.clientX,
|
|
226
|
+
startWidth: currentWidth
|
|
227
|
+
};
|
|
228
|
+
const onMove = (ev) => {
|
|
229
|
+
if (!resizing) return;
|
|
230
|
+
const diff = ev.clientX - resizing.startX;
|
|
231
|
+
let newWidth = resizing.startWidth + diff;
|
|
232
|
+
const min = col.minWidth ?? 50;
|
|
233
|
+
const max = col.maxWidth ?? Infinity;
|
|
234
|
+
newWidth = Math.max(min, Math.min(max, newWidth));
|
|
235
|
+
columnSizing = {
|
|
236
|
+
...columnSizing,
|
|
237
|
+
[resizing.key]: newWidth
|
|
238
|
+
};
|
|
239
|
+
onColumnSizingChange?.(columnSizing);
|
|
240
|
+
};
|
|
241
|
+
const onUp = () => {
|
|
242
|
+
resizing = null;
|
|
243
|
+
document.removeEventListener("mousemove", onMove);
|
|
244
|
+
document.removeEventListener("mouseup", onUp);
|
|
245
|
+
};
|
|
246
|
+
document.addEventListener("mousemove", onMove);
|
|
247
|
+
document.addEventListener("mouseup", onUp);
|
|
296
248
|
}
|
|
297
249
|
// =========================================================================
|
|
298
250
|
// Row Interactions
|
|
299
251
|
// =========================================================================
|
|
300
252
|
const isSelectable = $derived(!!onRowClick || !!selection || !!onRowHover || !!onRowContextmenu);
|
|
301
|
-
function handleRowClick(e
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
toggleRowSelect(row, index);
|
|
307
|
-
onRowClick?.(row, index, e);
|
|
253
|
+
function handleRowClick(e, row, index) {
|
|
254
|
+
const target = e.target;
|
|
255
|
+
if (target.closest("button, a, input, select, textarea, [role=\"checkbox\"]")) return;
|
|
256
|
+
if (selection) toggleRowSelect(row, index);
|
|
257
|
+
onRowClick?.(row, index, e);
|
|
308
258
|
}
|
|
309
|
-
function handleRowKeyDown(e
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
onRowClick?.(row, index, e as unknown as MouseEvent);
|
|
317
|
-
}
|
|
259
|
+
function handleRowKeyDown(e, row, index) {
|
|
260
|
+
if (!onRowClick && !selection) return;
|
|
261
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
262
|
+
e.preventDefault();
|
|
263
|
+
if (selection) toggleRowSelect(row, index);
|
|
264
|
+
onRowClick?.(row, index, e);
|
|
265
|
+
}
|
|
318
266
|
}
|
|
319
|
-
function handleRowPointerEnter(e
|
|
320
|
-
|
|
267
|
+
function handleRowPointerEnter(e, row, index) {
|
|
268
|
+
onRowHover?.(row, index, e);
|
|
321
269
|
}
|
|
322
|
-
function handleRowPointerLeave(e
|
|
323
|
-
|
|
270
|
+
function handleRowPointerLeave(e, row, index) {
|
|
271
|
+
onRowHover?.(null, index, e);
|
|
324
272
|
}
|
|
325
|
-
function handleRowContextmenu(e
|
|
326
|
-
|
|
273
|
+
function handleRowContextmenu(e, row, index) {
|
|
274
|
+
onRowContextmenu?.(row, index, e);
|
|
327
275
|
}
|
|
328
276
|
// =========================================================================
|
|
329
277
|
// Column Pinning
|
|
330
278
|
// =========================================================================
|
|
331
279
|
const pinOffsets = $derived(computePinOffsets(visibleColumns, columnSizing, columnPinning));
|
|
332
|
-
function getPinStyle(key
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
return `${pin.side}: ${pin.offset}px`;
|
|
280
|
+
function getPinStyle(key) {
|
|
281
|
+
const pin = pinOffsets.get(key);
|
|
282
|
+
if (!pin) return "";
|
|
283
|
+
return `${pin.side}: ${pin.offset}px`;
|
|
337
284
|
}
|
|
338
|
-
function isPinned(key
|
|
339
|
-
|
|
285
|
+
function isPinned(key) {
|
|
286
|
+
return pinOffsets.has(key);
|
|
340
287
|
}
|
|
341
288
|
// =========================================================================
|
|
342
289
|
// Column Width Style
|
|
343
290
|
// =========================================================================
|
|
344
|
-
function getColWidth(col
|
|
345
|
-
|
|
346
|
-
|
|
291
|
+
function getColWidth(col) {
|
|
292
|
+
const w = columnSizing[col.key] ?? col.width;
|
|
293
|
+
return w ? `${w}px` : undefined;
|
|
347
294
|
}
|
|
348
295
|
// =========================================================================
|
|
349
296
|
// Align class
|
|
350
297
|
// =========================================================================
|
|
351
|
-
function getAlignClass(align
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
return 'text-right';
|
|
356
|
-
return '';
|
|
298
|
+
function getAlignClass(align) {
|
|
299
|
+
if (align === "center") return "text-center";
|
|
300
|
+
if (align === "right") return "text-right";
|
|
301
|
+
return "";
|
|
357
302
|
}
|
|
358
303
|
// =========================================================================
|
|
359
304
|
// Variant Classes
|
|
360
305
|
// =========================================================================
|
|
361
306
|
const variantSlots = $derived(tableVariants({
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
const pinnedVariantSlots = $derived(tableVariants({ pinned: true }
|
|
307
|
+
hoverable: hoverable || undefined,
|
|
308
|
+
striped: striped || undefined,
|
|
309
|
+
sticky: sticky || undefined,
|
|
310
|
+
loading: loading || undefined,
|
|
311
|
+
loadingColor,
|
|
312
|
+
loadingAnimation
|
|
313
|
+
}));
|
|
314
|
+
const pinnedVariantSlots = $derived(tableVariants({ pinned: true }));
|
|
370
315
|
const classes = $derived({
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
316
|
+
root: variantSlots.root({ class: [
|
|
317
|
+
config.slots.root,
|
|
318
|
+
className,
|
|
319
|
+
ui?.root
|
|
320
|
+
] }),
|
|
321
|
+
base: variantSlots.base({ class: [config.slots.base, ui?.base] }),
|
|
322
|
+
caption: variantSlots.caption({ class: [config.slots.caption, ui?.caption] }),
|
|
323
|
+
thead: variantSlots.thead({ class: [config.slots.thead, ui?.thead] }),
|
|
324
|
+
tbody: variantSlots.tbody({ class: [config.slots.tbody, ui?.tbody] }),
|
|
325
|
+
tfoot: variantSlots.tfoot({ class: [config.slots.tfoot, ui?.tfoot] }),
|
|
326
|
+
tr: variantSlots.tr({ class: [config.slots.tr, ui?.tr] }),
|
|
327
|
+
th: variantSlots.th({ class: [config.slots.th, ui?.th] }),
|
|
328
|
+
thPinned: pinnedVariantSlots.th({ class: [config.slots.th, ui?.th] }),
|
|
329
|
+
td: variantSlots.td({ class: [config.slots.td, ui?.td] }),
|
|
330
|
+
tdPinned: pinnedVariantSlots.td({ class: [config.slots.td, ui?.td] }),
|
|
331
|
+
separator: variantSlots.separator({ class: [config.slots.separator, ui?.separator] }),
|
|
332
|
+
empty: variantSlots.empty({ class: [config.slots.empty, ui?.empty] }),
|
|
333
|
+
loading: variantSlots.loading({ class: [config.slots.loading, ui?.loading] })
|
|
385
334
|
});
|
|
386
|
-
function thClass(key
|
|
387
|
-
|
|
335
|
+
function thClass(key) {
|
|
336
|
+
return isPinned(key) ? classes.thPinned : classes.th;
|
|
388
337
|
}
|
|
389
|
-
function tdClass(key
|
|
390
|
-
|
|
338
|
+
function tdClass(key) {
|
|
339
|
+
return isPinned(key) ? classes.tdPinned : classes.td;
|
|
391
340
|
}
|
|
392
341
|
</script>
|
|
393
342
|
|
|
@@ -197,7 +197,7 @@ export declare const tableDefaults: {
|
|
|
197
197
|
loadingColor: "primary";
|
|
198
198
|
loadingAnimation: "carousel";
|
|
199
199
|
loading?: boolean | undefined;
|
|
200
|
-
sticky?: boolean | "
|
|
200
|
+
sticky?: boolean | "footer" | "header" | undefined;
|
|
201
201
|
pinned?: boolean | undefined;
|
|
202
202
|
striped?: boolean | undefined;
|
|
203
203
|
};
|