@urbicon-ui/table 6.1.4
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/README.md +153 -0
- package/dist/cells/ActionButtons.svelte +224 -0
- package/dist/cells/ActionButtons.svelte.d.ts +74 -0
- package/dist/cells/CopyButton.svelte +89 -0
- package/dist/cells/CopyButton.svelte.d.ts +33 -0
- package/dist/cells/CustomCell.svelte +136 -0
- package/dist/cells/CustomCell.svelte.d.ts +44 -0
- package/dist/cells/DateCell.svelte +194 -0
- package/dist/cells/DateCell.svelte.d.ts +39 -0
- package/dist/cells/LinkCell.svelte +240 -0
- package/dist/cells/LinkCell.svelte.d.ts +42 -0
- package/dist/cells/NumberCell.svelte +225 -0
- package/dist/cells/NumberCell.svelte.d.ts +47 -0
- package/dist/cells/StatusBadge.svelte +121 -0
- package/dist/cells/StatusBadge.svelte.d.ts +44 -0
- package/dist/cells/UserAvatar.svelte +71 -0
- package/dist/cells/UserAvatar.svelte.d.ts +37 -0
- package/dist/cells/index.d.ts +8 -0
- package/dist/cells/index.js +9 -0
- package/dist/core/EmptyState.svelte +161 -0
- package/dist/core/EmptyState.svelte.d.ts +16 -0
- package/dist/core/ErrorState.svelte +158 -0
- package/dist/core/ErrorState.svelte.d.ts +15 -0
- package/dist/core/GroupedRow.svelte +239 -0
- package/dist/core/GroupedRow.svelte.d.ts +18 -0
- package/dist/core/LoadingState.svelte +75 -0
- package/dist/core/LoadingState.svelte.d.ts +14 -0
- package/dist/core/MobileCard.svelte +151 -0
- package/dist/core/MobileCard.svelte.d.ts +15 -0
- package/dist/core/TableCell.svelte +105 -0
- package/dist/core/TableCell.svelte.d.ts +14 -0
- package/dist/core/TableDesktop.svelte +480 -0
- package/dist/core/TableDesktop.svelte.d.ts +26 -0
- package/dist/core/TableHead.svelte +314 -0
- package/dist/core/TableHead.svelte.d.ts +7 -0
- package/dist/core/TableMobile.svelte +112 -0
- package/dist/core/TableMobile.svelte.d.ts +13 -0
- package/dist/core/TableProvider.svelte +271 -0
- package/dist/core/TableProvider.svelte.d.ts +40 -0
- package/dist/core/TableRow.svelte +171 -0
- package/dist/core/TableRow.svelte.d.ts +16 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.js +14 -0
- package/dist/core/sticky-context.svelte.d.ts +48 -0
- package/dist/core/sticky-context.svelte.js +88 -0
- package/dist/core/table/Table.svelte +304 -0
- package/dist/core/table/Table.svelte.d.ts +26 -0
- package/dist/core/table/index.d.ts +448 -0
- package/dist/core/table/index.js +1 -0
- package/dist/core/table-style-context.d.ts +66 -0
- package/dist/core/table-style-context.js +26 -0
- package/dist/factories/ColumnValidation.d.ts +49 -0
- package/dist/factories/ColumnValidation.js +188 -0
- package/dist/factories/TableColumns.d.ts +97 -0
- package/dist/factories/TableColumns.js +262 -0
- package/dist/factories/TypedColumnBuilder.d.ts +41 -0
- package/dist/factories/TypedColumnBuilder.js +72 -0
- package/dist/factories/index.d.ts +12 -0
- package/dist/factories/index.js +13 -0
- package/dist/features/HeaderMenu.svelte +236 -0
- package/dist/features/HeaderMenu.svelte.d.ts +8 -0
- package/dist/features/LiveUpdateBanner.svelte +66 -0
- package/dist/features/LiveUpdateBanner.svelte.d.ts +6 -0
- package/dist/features/SearchHighlight.svelte +21 -0
- package/dist/features/SearchHighlight.svelte.d.ts +8 -0
- package/dist/features/SmartFilterBar/ChipsField.svelte +104 -0
- package/dist/features/SmartFilterBar/ChipsField.svelte.d.ts +5 -0
- package/dist/features/SmartFilterBar/ColumnVisibilityMenu.svelte +84 -0
- package/dist/features/SmartFilterBar/ColumnVisibilityMenu.svelte.d.ts +3 -0
- package/dist/features/SmartFilterBar/FilterMenu.svelte +367 -0
- package/dist/features/SmartFilterBar/FilterMenu.svelte.d.ts +3 -0
- package/dist/features/SmartFilterBar/GroupingMenu.svelte +82 -0
- package/dist/features/SmartFilterBar/GroupingMenu.svelte.d.ts +3 -0
- package/dist/features/SmartFilterBar/SmartFilterBar.svelte +109 -0
- package/dist/features/SmartFilterBar/SmartFilterBar.svelte.d.ts +11 -0
- package/dist/features/SmartFilterBar/SummaryMenu.svelte +118 -0
- package/dist/features/SmartFilterBar/SummaryMenu.svelte.d.ts +3 -0
- package/dist/features/SummaryRow.svelte +97 -0
- package/dist/features/SummaryRow.svelte.d.ts +8 -0
- package/dist/features/index.d.ts +4 -0
- package/dist/features/index.js +4 -0
- package/dist/i18n/index.d.ts +366 -0
- package/dist/i18n/index.js +21 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +41 -0
- package/dist/stores/TableStore.svelte.d.ts +192 -0
- package/dist/stores/TableStore.svelte.js +362 -0
- package/dist/stores/concerns/index.d.ts +15 -0
- package/dist/stores/concerns/index.js +14 -0
- package/dist/stores/concerns/types.d.ts +31 -0
- package/dist/stores/concerns/types.js +1 -0
- package/dist/stores/concerns/useColumnOrder.svelte.d.ts +16 -0
- package/dist/stores/concerns/useColumnOrder.svelte.js +81 -0
- package/dist/stores/concerns/useColumnVisibility.svelte.d.ts +16 -0
- package/dist/stores/concerns/useColumnVisibility.svelte.js +58 -0
- package/dist/stores/concerns/useExpansion.svelte.d.ts +9 -0
- package/dist/stores/concerns/useExpansion.svelte.js +32 -0
- package/dist/stores/concerns/useFiltering.svelte.d.ts +20 -0
- package/dist/stores/concerns/useFiltering.svelte.js +109 -0
- package/dist/stores/concerns/useFocusManagement.svelte.d.ts +15 -0
- package/dist/stores/concerns/useFocusManagement.svelte.js +52 -0
- package/dist/stores/concerns/useGrouping.svelte.d.ts +15 -0
- package/dist/stores/concerns/useGrouping.svelte.js +86 -0
- package/dist/stores/concerns/useLiveUpdates.svelte.d.ts +45 -0
- package/dist/stores/concerns/useLiveUpdates.svelte.js +175 -0
- package/dist/stores/concerns/usePagination.svelte.d.ts +18 -0
- package/dist/stores/concerns/usePagination.svelte.js +54 -0
- package/dist/stores/concerns/usePersistence.svelte.d.ts +36 -0
- package/dist/stores/concerns/usePersistence.svelte.js +167 -0
- package/dist/stores/concerns/useRemoteData.svelte.d.ts +21 -0
- package/dist/stores/concerns/useRemoteData.svelte.js +64 -0
- package/dist/stores/concerns/useSearch.svelte.d.ts +8 -0
- package/dist/stores/concerns/useSearch.svelte.js +16 -0
- package/dist/stores/concerns/useSelection.svelte.d.ts +21 -0
- package/dist/stores/concerns/useSelection.svelte.js +110 -0
- package/dist/stores/concerns/useSorting.svelte.d.ts +11 -0
- package/dist/stores/concerns/useSorting.svelte.js +70 -0
- package/dist/stores/concerns/useSummary.svelte.d.ts +18 -0
- package/dist/stores/concerns/useSummary.svelte.js +96 -0
- package/dist/stores/index.d.ts +1 -0
- package/dist/stores/index.js +1 -0
- package/dist/style/index.css +137 -0
- package/dist/style/index.d.ts +2 -0
- package/dist/style/index.js +2 -0
- package/dist/style/table-theme.css +131 -0
- package/dist/style/themes/comfortable.css +20 -0
- package/dist/style/themes/compact.css +20 -0
- package/dist/translations/de.d.ts +177 -0
- package/dist/translations/de.js +176 -0
- package/dist/translations/en.d.ts +177 -0
- package/dist/translations/en.js +176 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/tableTypes.d.ts +262 -0
- package/dist/types/tableTypes.js +1 -0
- package/dist/utils/index.d.ts +165 -0
- package/dist/utils/index.js +330 -0
- package/dist/utils/sticky-measure.d.ts +54 -0
- package/dist/utils/sticky-measure.js +107 -0
- package/dist/utils/virtualizer.d.ts +43 -0
- package/dist/utils/virtualizer.js +43 -0
- package/dist/variants/index.d.ts +11 -0
- package/dist/variants/index.js +15 -0
- package/dist/variants/table-cells.variants.d.ts +827 -0
- package/dist/variants/table-cells.variants.js +627 -0
- package/dist/variants/table-features.variants.d.ts +547 -0
- package/dist/variants/table-features.variants.js +412 -0
- package/dist/variants/table-states.variants.d.ts +594 -0
- package/dist/variants/table-states.variants.js +394 -0
- package/dist/variants/table.system.d.ts +301 -0
- package/dist/variants/table.system.js +314 -0
- package/dist/variants/table.variants.d.ts +428 -0
- package/dist/variants/table.variants.js +360 -0
- package/package.json +93 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
function resolveRowId(item) {
|
|
2
|
+
const id = item.id ?? item.__index;
|
|
3
|
+
return typeof id === 'string' || typeof id === 'number' ? id : undefined;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Selection concern: manages row selection state.
|
|
7
|
+
* Supports single-select and multi-select modes.
|
|
8
|
+
* @param state - Shared table state.
|
|
9
|
+
* @param getFilteredItems - Getter for filtered items (used for selectAll scope).
|
|
10
|
+
*/
|
|
11
|
+
export function useSelection(state, getFilteredItems) {
|
|
12
|
+
/** Derived list of currently selected items (resolved from selectedIds). */
|
|
13
|
+
const selectedItems = $derived.by(() => {
|
|
14
|
+
if (state.selectionMode === 'none' || state.selectedIds.size === 0)
|
|
15
|
+
return [];
|
|
16
|
+
return state.items.filter((item) => {
|
|
17
|
+
const id = resolveRowId(item);
|
|
18
|
+
return id !== undefined && state.selectedIds.has(id);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
/** Whether all visible (filtered) items are selected. */
|
|
22
|
+
const allSelected = $derived.by(() => {
|
|
23
|
+
const items = getFilteredItems();
|
|
24
|
+
if (items.length === 0 || state.selectedIds.size === 0)
|
|
25
|
+
return false;
|
|
26
|
+
return items.every((item) => {
|
|
27
|
+
const id = resolveRowId(item);
|
|
28
|
+
return id !== undefined && state.selectedIds.has(id);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
/** Whether some but not all visible items are selected (indeterminate state). */
|
|
32
|
+
const someSelected = $derived.by(() => {
|
|
33
|
+
if (allSelected)
|
|
34
|
+
return false;
|
|
35
|
+
const items = getFilteredItems();
|
|
36
|
+
return items.some((item) => {
|
|
37
|
+
const id = resolveRowId(item);
|
|
38
|
+
return id !== undefined && state.selectedIds.has(id);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
function selectItem(id) {
|
|
42
|
+
if (state.selectionMode === 'none')
|
|
43
|
+
return;
|
|
44
|
+
if (state.selectionMode === 'single') {
|
|
45
|
+
state.selectedIds.clear();
|
|
46
|
+
state.selectedIds.add(id);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
state.selectedIds.add(id);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function deselectItem(id) {
|
|
53
|
+
state.selectedIds.delete(id);
|
|
54
|
+
}
|
|
55
|
+
function toggleItem(id) {
|
|
56
|
+
if (state.selectedIds.has(id)) {
|
|
57
|
+
deselectItem(id);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
selectItem(id);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function selectAll() {
|
|
64
|
+
if (state.selectionMode !== 'multi')
|
|
65
|
+
return;
|
|
66
|
+
for (const item of getFilteredItems()) {
|
|
67
|
+
const id = resolveRowId(item);
|
|
68
|
+
if (id !== undefined)
|
|
69
|
+
state.selectedIds.add(id);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function deselectAll() {
|
|
73
|
+
state.selectedIds.clear();
|
|
74
|
+
}
|
|
75
|
+
function toggleAll() {
|
|
76
|
+
if (allSelected) {
|
|
77
|
+
deselectAll();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
selectAll();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function isSelected(id) {
|
|
84
|
+
return state.selectedIds.has(id);
|
|
85
|
+
}
|
|
86
|
+
function setSelectedIds(ids) {
|
|
87
|
+
state.selectedIds.clear();
|
|
88
|
+
for (const id of ids)
|
|
89
|
+
state.selectedIds.add(id);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
get selectedItems() {
|
|
93
|
+
return selectedItems;
|
|
94
|
+
},
|
|
95
|
+
get allSelected() {
|
|
96
|
+
return allSelected;
|
|
97
|
+
},
|
|
98
|
+
get someSelected() {
|
|
99
|
+
return someSelected;
|
|
100
|
+
},
|
|
101
|
+
selectItem,
|
|
102
|
+
deselectItem,
|
|
103
|
+
toggleItem,
|
|
104
|
+
selectAll,
|
|
105
|
+
deselectAll,
|
|
106
|
+
toggleAll,
|
|
107
|
+
isSelected,
|
|
108
|
+
setSelectedIds
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TableItem } from '../../types/tableTypes';
|
|
2
|
+
import type { TableState } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Sorting concern: manages sort column/direction and computes sorted items.
|
|
5
|
+
* @param state - Shared table state.
|
|
6
|
+
* @param getFilteredItems - Getter for upstream filtered items.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useSorting(state: TableState, getFilteredItems: () => TableItem[]): {
|
|
9
|
+
readonly sortedItems: TableItem[];
|
|
10
|
+
handleSort: (column: string) => void;
|
|
11
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { findColumnById, resolveValueById } from '../../utils';
|
|
2
|
+
function compareSortable(a, b) {
|
|
3
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
4
|
+
return a - b;
|
|
5
|
+
}
|
|
6
|
+
if (a instanceof Date && b instanceof Date) {
|
|
7
|
+
return a.getTime() - b.getTime();
|
|
8
|
+
}
|
|
9
|
+
const aStr = String(a);
|
|
10
|
+
const bStr = String(b);
|
|
11
|
+
if (aStr < bStr)
|
|
12
|
+
return -1;
|
|
13
|
+
if (aStr > bStr)
|
|
14
|
+
return 1;
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Sorting concern: manages sort column/direction and computes sorted items.
|
|
19
|
+
* @param state - Shared table state.
|
|
20
|
+
* @param getFilteredItems - Getter for upstream filtered items.
|
|
21
|
+
*/
|
|
22
|
+
export function useSorting(state, getFilteredItems) {
|
|
23
|
+
const sortedItems = $derived.by(() => {
|
|
24
|
+
const items = getFilteredItems();
|
|
25
|
+
// In server mode, items are already sorted by the server
|
|
26
|
+
if (state.mode === 'server')
|
|
27
|
+
return items;
|
|
28
|
+
if (!items.length || !state.sortColumn)
|
|
29
|
+
return [...items];
|
|
30
|
+
// Synthetic columns have no accessor — sorting by them is structurally
|
|
31
|
+
// undefined and the resolver would return undefined for every row. Skip
|
|
32
|
+
// the sort entirely in that case rather than scramble row order.
|
|
33
|
+
const sortColumn = findColumnById(state.columns, state.sortColumn);
|
|
34
|
+
if (sortColumn && sortColumn.accessor === undefined)
|
|
35
|
+
return [...items];
|
|
36
|
+
return [...items].sort((a, b) => {
|
|
37
|
+
const aValue = resolveValueById(state.columns, a, state.sortColumn);
|
|
38
|
+
const bValue = resolveValueById(state.columns, b, state.sortColumn);
|
|
39
|
+
if (aValue === undefined && bValue === undefined)
|
|
40
|
+
return 0;
|
|
41
|
+
if (aValue === undefined)
|
|
42
|
+
return 1;
|
|
43
|
+
if (bValue === undefined)
|
|
44
|
+
return -1;
|
|
45
|
+
const cmp = compareSortable(aValue, bValue);
|
|
46
|
+
return state.sortDirection === 'asc' ? cmp : -cmp;
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
function handleSort(column) {
|
|
50
|
+
if (state.sortColumn === column) {
|
|
51
|
+
if (state.sortDirection === 'asc') {
|
|
52
|
+
state.sortDirection = 'desc';
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
state.sortColumn = '';
|
|
56
|
+
state.sortDirection = 'asc';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
state.sortColumn = column;
|
|
61
|
+
state.sortDirection = 'asc';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
get sortedItems() {
|
|
66
|
+
return sortedItems;
|
|
67
|
+
},
|
|
68
|
+
handleSort
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TableItem } from '../../types/tableTypes';
|
|
2
|
+
import type { SummaryConfig } from '../TableStore.svelte';
|
|
3
|
+
import type { TableState } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Summary concern: manages summary configurations and computes aggregate values.
|
|
6
|
+
* @param state - Shared table state.
|
|
7
|
+
* @param getSortedItems - Getter for sorted items (used for global summary).
|
|
8
|
+
* @param getGrouped - Getter for grouped items (used for per-group summary).
|
|
9
|
+
*/
|
|
10
|
+
export declare function useSummary(state: TableState, getSortedItems: () => TableItem[], getGrouped: () => Record<string, TableItem[]>): {
|
|
11
|
+
readonly summaryData: Record<string, number>;
|
|
12
|
+
readonly groupedSummaryData: Record<string, Record<string, number>>;
|
|
13
|
+
addSummaryConfig: (config: SummaryConfig) => void;
|
|
14
|
+
removeSummaryConfig: (column: string) => void;
|
|
15
|
+
toggleSummary: () => void;
|
|
16
|
+
setSummaryConfigs: (configs: SummaryConfig[]) => void;
|
|
17
|
+
getFormattedSummaryValue: (column: string, value: number) => string;
|
|
18
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { calculateSummary, findColumnById, resolveValueById } from '../../utils';
|
|
2
|
+
/**
|
|
3
|
+
* Summary concern: manages summary configurations and computes aggregate values.
|
|
4
|
+
* @param state - Shared table state.
|
|
5
|
+
* @param getSortedItems - Getter for sorted items (used for global summary).
|
|
6
|
+
* @param getGrouped - Getter for grouped items (used for per-group summary).
|
|
7
|
+
*/
|
|
8
|
+
export function useSummary(state, getSortedItems, getGrouped) {
|
|
9
|
+
// Column-aware value resolver: looks up the accessor by column id so that
|
|
10
|
+
// summaries on function-accessor columns aggregate the computed value
|
|
11
|
+
// rather than the raw property name (which usually does not exist on the row).
|
|
12
|
+
const getValue = (item, columnId) => resolveValueById(state.columns, item, columnId);
|
|
13
|
+
const summaryData = $derived.by(() => {
|
|
14
|
+
if (!state.showSummary || state.summaryConfigs.length === 0)
|
|
15
|
+
return {};
|
|
16
|
+
return calculateSummary(getSortedItems(), state.summaryConfigs, getValue);
|
|
17
|
+
});
|
|
18
|
+
const groupedSummaryData = $derived.by(() => {
|
|
19
|
+
if (!state.showSummary || state.summaryConfigs.length === 0 || !state.groupByKey)
|
|
20
|
+
return {};
|
|
21
|
+
const result = {};
|
|
22
|
+
Object.entries(getGrouped()).forEach(([groupKey, groupItems]) => {
|
|
23
|
+
result[groupKey] = calculateSummary(groupItems, state.summaryConfigs, getValue);
|
|
24
|
+
});
|
|
25
|
+
return result;
|
|
26
|
+
});
|
|
27
|
+
function addSummaryConfig(config) {
|
|
28
|
+
const existing = state.summaryConfigs.findIndex((c) => c.column === config.column);
|
|
29
|
+
if (existing >= 0) {
|
|
30
|
+
state.summaryConfigs[existing] = config;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
state.summaryConfigs = [...state.summaryConfigs, config];
|
|
34
|
+
}
|
|
35
|
+
if (state.summaryConfigs.length > 0) {
|
|
36
|
+
state.showSummary = true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function removeSummaryConfig(column) {
|
|
40
|
+
state.summaryConfigs = state.summaryConfigs.filter((c) => c.column !== column);
|
|
41
|
+
if (state.summaryConfigs.length === 0) {
|
|
42
|
+
state.showSummary = false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function toggleSummary() {
|
|
46
|
+
state.showSummary = !state.showSummary;
|
|
47
|
+
}
|
|
48
|
+
function setSummaryConfigs(configs) {
|
|
49
|
+
state.summaryConfigs = configs;
|
|
50
|
+
state.showSummary = configs.length > 0;
|
|
51
|
+
}
|
|
52
|
+
function getFormattedSummaryValue(column, value) {
|
|
53
|
+
if (Number.isNaN(value))
|
|
54
|
+
return '–';
|
|
55
|
+
const config = state.summaryConfigs.find((c) => c.column === column);
|
|
56
|
+
if (config?.formatter) {
|
|
57
|
+
return config.formatter(value);
|
|
58
|
+
}
|
|
59
|
+
const col = findColumnById(state.columns, column);
|
|
60
|
+
if (col?.formatter) {
|
|
61
|
+
try {
|
|
62
|
+
const formatted = col.formatter(value, {});
|
|
63
|
+
if (formatted !== null)
|
|
64
|
+
return formatted;
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
if (import.meta.env?.DEV)
|
|
68
|
+
console.warn(`[Table] Column "${column}" formatter threw on summary value:`, err);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
switch (config?.type) {
|
|
72
|
+
case 'avg':
|
|
73
|
+
return Number(value).toFixed(2);
|
|
74
|
+
case 'sum':
|
|
75
|
+
case 'count':
|
|
76
|
+
case 'min':
|
|
77
|
+
case 'max':
|
|
78
|
+
return String(Math.round(Number(value)));
|
|
79
|
+
default:
|
|
80
|
+
return String(value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
get summaryData() {
|
|
85
|
+
return summaryData;
|
|
86
|
+
},
|
|
87
|
+
get groupedSummaryData() {
|
|
88
|
+
return groupedSummaryData;
|
|
89
|
+
},
|
|
90
|
+
addSummaryConfig,
|
|
91
|
+
removeSummaryConfig,
|
|
92
|
+
toggleSummary,
|
|
93
|
+
setSummaryConfigs,
|
|
94
|
+
getFormattedSummaryValue
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TableStore.svelte.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TableStore.svelte.js';
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/* === FLOWTABLE DESIGN SYSTEM === */
|
|
2
|
+
/* Master CSS file that imports all design tokens */
|
|
3
|
+
/*
|
|
4
|
+
* NOTE: this file does NOT `@import 'tailwindcss'` — that is the consumer
|
|
5
|
+
* app's responsibility. See `@urbicon-ui/blocks/src/lib/style/index.css`
|
|
6
|
+
* and `docs/TailwindCaveats.md` → "Library CSS must not import Tailwind"
|
|
7
|
+
* for the rationale. Re-importing Tailwind here previously caused every
|
|
8
|
+
* consumer that mounted a Table to silently lose its `@theme` overrides
|
|
9
|
+
* to the library defaults.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/* Foundation Layer - Base design tokens */
|
|
13
|
+
@import '@urbicon-ui/blocks/style/index.css';
|
|
14
|
+
|
|
15
|
+
/* === TABLE PACKAGE DESIGN SYSTEM === */
|
|
16
|
+
|
|
17
|
+
/* === TABLE-SPECIFIC THEME === */
|
|
18
|
+
/* Import table-specific theme tokens */
|
|
19
|
+
@import './table-theme.css';
|
|
20
|
+
|
|
21
|
+
/* === COMPONENT VARIANTS === */
|
|
22
|
+
/* Import tailwind-variants source files for JIT compilation */
|
|
23
|
+
@source '../variants';
|
|
24
|
+
|
|
25
|
+
/* === MINIMAL COMPONENT STYLES === */
|
|
26
|
+
/* Only complex, non-utility styles that can't be expressed in Tailwind classes */
|
|
27
|
+
|
|
28
|
+
/* Table Expand Button - Complex interactive component */
|
|
29
|
+
.table-expand-button {
|
|
30
|
+
color: var(--color-text-secondary);
|
|
31
|
+
background: transparent;
|
|
32
|
+
border: none;
|
|
33
|
+
border-radius: var(--blocks-radius-base);
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
transition: var(--blocks-transition-colors);
|
|
36
|
+
padding: var(--blocks-space-1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.table-expand-button:hover {
|
|
40
|
+
color: var(--color-text-primary);
|
|
41
|
+
background-color: var(--color-surface-hover);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.table-expand-button:focus-visible {
|
|
45
|
+
outline: none;
|
|
46
|
+
box-shadow: var(--blocks-focus-ring);
|
|
47
|
+
outline-offset: var(--blocks-focus-ring-offset);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Table Container - Complex layout component */
|
|
51
|
+
.table-container {
|
|
52
|
+
/* Use blocks foundation tokens */
|
|
53
|
+
font-family: var(--blocks-font-family);
|
|
54
|
+
font-size: var(--text-sm);
|
|
55
|
+
line-height: var(--blocks-leading-normal);
|
|
56
|
+
color: var(--color-text-primary);
|
|
57
|
+
|
|
58
|
+
/* Container styling */
|
|
59
|
+
background: var(--color-surface-base);
|
|
60
|
+
border: 1px solid var(--color-border-default);
|
|
61
|
+
border-radius: var(--blocks-radius-lg);
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
|
|
64
|
+
/* Modern scrolling */
|
|
65
|
+
container-type: inline-size;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* === SEARCH HIGHLIGHT === */
|
|
69
|
+
/* Applied via @html injection — must be global */
|
|
70
|
+
.table-search-highlight {
|
|
71
|
+
background-color: var(--color-warning-subtle, oklch(0.95 0.07 85));
|
|
72
|
+
color: var(--color-text-primary);
|
|
73
|
+
padding: 0.1em 0.2em;
|
|
74
|
+
border-radius: var(--radius-sm, 0.25rem);
|
|
75
|
+
font-weight: 500;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* === ACCESSIBILITY HELPERS === */
|
|
79
|
+
|
|
80
|
+
/* Focus management for interactive elements */
|
|
81
|
+
.table-focusable:focus-visible {
|
|
82
|
+
outline: none;
|
|
83
|
+
box-shadow: var(--blocks-focus-ring);
|
|
84
|
+
outline-offset: var(--blocks-focus-ring-offset);
|
|
85
|
+
border-radius: var(--blocks-radius-md);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Skip to content link */
|
|
89
|
+
.table-skip-link {
|
|
90
|
+
position: absolute;
|
|
91
|
+
top: -40px;
|
|
92
|
+
left: 6px;
|
|
93
|
+
background: var(--color-surface-elevated);
|
|
94
|
+
color: var(--color-text-primary);
|
|
95
|
+
padding: 8px;
|
|
96
|
+
text-decoration: none;
|
|
97
|
+
border-radius: var(--blocks-radius-md);
|
|
98
|
+
z-index: var(--z-modal);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.table-skip-link:focus {
|
|
102
|
+
top: 6px;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* === RESPONSIVE HELPERS === */
|
|
106
|
+
/* Complex responsive patterns */
|
|
107
|
+
|
|
108
|
+
@container (max-width: 768px) {
|
|
109
|
+
.table-hide-mobile {
|
|
110
|
+
display: none;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.table-mobile-stack {
|
|
114
|
+
flex-direction: column;
|
|
115
|
+
gap: var(--spacing-2);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@container (min-width: 769px) {
|
|
120
|
+
.table-hide-desktop {
|
|
121
|
+
display: none;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* === PRINT OPTIMIZATIONS === */
|
|
126
|
+
@media print {
|
|
127
|
+
.table-container {
|
|
128
|
+
background: white !important;
|
|
129
|
+
border: 1px solid #000 !important;
|
|
130
|
+
box-shadow: none !important;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.table-expand-button,
|
|
134
|
+
.table-skip-link {
|
|
135
|
+
display: none !important;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
@theme {
|
|
2
|
+
/* === TABLE-SPECIFIC INTENTS === */
|
|
3
|
+
/* Extend the blocks foundation with table-specific colors */
|
|
4
|
+
/* Filter Intent (Cyan-based) */
|
|
5
|
+
--color-filter-50: var(--color-cyan-50);
|
|
6
|
+
--color-filter-100: var(--color-cyan-100);
|
|
7
|
+
--color-filter-200: var(--color-cyan-200);
|
|
8
|
+
--color-filter-300: var(--color-cyan-300);
|
|
9
|
+
--color-filter-400: var(--color-cyan-400);
|
|
10
|
+
--color-filter-500: var(--color-cyan-500);
|
|
11
|
+
--color-filter-600: var(--color-cyan-600);
|
|
12
|
+
--color-filter-700: var(--color-cyan-700);
|
|
13
|
+
--color-filter-800: var(--color-cyan-800);
|
|
14
|
+
--color-filter-900: var(--color-cyan-900);
|
|
15
|
+
|
|
16
|
+
--color-filter: var(--color-filter-600);
|
|
17
|
+
--color-filter-hover: var(--color-filter-700);
|
|
18
|
+
--color-filter-active: var(--color-filter-800);
|
|
19
|
+
--color-filter-subtle: var(--color-filter-50);
|
|
20
|
+
--color-filter-emphasis: var(--color-filter-900);
|
|
21
|
+
|
|
22
|
+
/* Group Intent (Teal-based) */
|
|
23
|
+
--color-group-50: var(--color-teal-50);
|
|
24
|
+
--color-group-100: var(--color-teal-100);
|
|
25
|
+
--color-group-200: var(--color-teal-200);
|
|
26
|
+
--color-group-300: var(--color-teal-300);
|
|
27
|
+
--color-group-400: var(--color-teal-400);
|
|
28
|
+
--color-group-500: var(--color-teal-500);
|
|
29
|
+
--color-group-600: var(--color-teal-600);
|
|
30
|
+
--color-group-700: var(--color-teal-700);
|
|
31
|
+
--color-group-800: var(--color-teal-800);
|
|
32
|
+
--color-group-900: var(--color-teal-900);
|
|
33
|
+
|
|
34
|
+
--color-group: var(--color-group-600);
|
|
35
|
+
--color-group-hover: var(--color-group-700);
|
|
36
|
+
--color-group-active: var(--color-group-800);
|
|
37
|
+
--color-group-subtle: var(--color-group-50);
|
|
38
|
+
--color-group-emphasis: var(--color-group-900);
|
|
39
|
+
|
|
40
|
+
/* Summary Intent (Emerald-based) */
|
|
41
|
+
--color-summary-50: var(--color-emerald-50);
|
|
42
|
+
--color-summary-100: var(--color-emerald-100);
|
|
43
|
+
--color-summary-200: var(--color-emerald-200);
|
|
44
|
+
--color-summary-300: var(--color-emerald-300);
|
|
45
|
+
--color-summary-400: var(--color-emerald-400);
|
|
46
|
+
--color-summary-500: var(--color-emerald-500);
|
|
47
|
+
--color-summary-600: var(--color-emerald-600);
|
|
48
|
+
--color-summary-700: var(--color-emerald-700);
|
|
49
|
+
--color-summary-800: var(--color-emerald-800);
|
|
50
|
+
--color-summary-900: var(--color-emerald-900);
|
|
51
|
+
|
|
52
|
+
--color-summary: var(--color-summary-600);
|
|
53
|
+
--color-summary-hover: var(--color-summary-700);
|
|
54
|
+
--color-summary-active: var(--color-summary-800);
|
|
55
|
+
--color-summary-subtle: var(--color-summary-50);
|
|
56
|
+
--color-summary-emphasis: var(--color-summary-900);
|
|
57
|
+
|
|
58
|
+
/* === TABLE-SPECIFIC DESIGN TOKENS === */
|
|
59
|
+
--table-header-height: 3rem;
|
|
60
|
+
--table-row-height: 3.5rem;
|
|
61
|
+
--table-cell-padding-x: 1rem;
|
|
62
|
+
--table-cell-padding-y: 0.75rem;
|
|
63
|
+
|
|
64
|
+
--filter-bar-height: 3.5rem;
|
|
65
|
+
--filter-bar-padding: 0.75rem;
|
|
66
|
+
--filter-bar-gap: 0.75rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:root {
|
|
70
|
+
@media (prefers-color-scheme: dark) {
|
|
71
|
+
--color-filter: var(--color-filter-400);
|
|
72
|
+
--color-filter-hover: var(--color-filter-300);
|
|
73
|
+
--color-filter-active: var(--color-filter-200);
|
|
74
|
+
--color-filter-subtle: var(--color-filter-900);
|
|
75
|
+
--color-filter-emphasis: var(--color-filter-100);
|
|
76
|
+
|
|
77
|
+
--color-group: var(--color-group-400);
|
|
78
|
+
--color-group-hover: var(--color-group-300);
|
|
79
|
+
--color-group-active: var(--color-group-200);
|
|
80
|
+
--color-group-subtle: var(--color-group-900);
|
|
81
|
+
--color-group-emphasis: var(--color-group-100);
|
|
82
|
+
|
|
83
|
+
--color-summary: var(--color-summary-400);
|
|
84
|
+
--color-summary-hover: var(--color-summary-300);
|
|
85
|
+
--color-summary-active: var(--color-summary-200);
|
|
86
|
+
--color-summary-subtle: var(--color-summary-900);
|
|
87
|
+
--color-summary-emphasis: var(--color-summary-100);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* Class-based dark mode (for manual theme toggle via .dark on <html>) */
|
|
92
|
+
:root.dark {
|
|
93
|
+
--color-filter: var(--color-filter-400);
|
|
94
|
+
--color-filter-hover: var(--color-filter-300);
|
|
95
|
+
--color-filter-active: var(--color-filter-200);
|
|
96
|
+
--color-filter-subtle: var(--color-filter-900);
|
|
97
|
+
--color-filter-emphasis: var(--color-filter-100);
|
|
98
|
+
|
|
99
|
+
--color-group: var(--color-group-400);
|
|
100
|
+
--color-group-hover: var(--color-group-300);
|
|
101
|
+
--color-group-active: var(--color-group-200);
|
|
102
|
+
--color-group-subtle: var(--color-group-900);
|
|
103
|
+
--color-group-emphasis: var(--color-group-100);
|
|
104
|
+
|
|
105
|
+
--color-summary: var(--color-summary-400);
|
|
106
|
+
--color-summary-hover: var(--color-summary-300);
|
|
107
|
+
--color-summary-active: var(--color-summary-200);
|
|
108
|
+
--color-summary-subtle: var(--color-summary-900);
|
|
109
|
+
--color-summary-emphasis: var(--color-summary-100);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Class-based light mode override (forces light tokens when OS prefers dark) */
|
|
113
|
+
:root.light {
|
|
114
|
+
--color-filter: var(--color-filter-600);
|
|
115
|
+
--color-filter-hover: var(--color-filter-700);
|
|
116
|
+
--color-filter-active: var(--color-filter-800);
|
|
117
|
+
--color-filter-subtle: var(--color-filter-50);
|
|
118
|
+
--color-filter-emphasis: var(--color-filter-900);
|
|
119
|
+
|
|
120
|
+
--color-group: var(--color-group-600);
|
|
121
|
+
--color-group-hover: var(--color-group-700);
|
|
122
|
+
--color-group-active: var(--color-group-800);
|
|
123
|
+
--color-group-subtle: var(--color-group-50);
|
|
124
|
+
--color-group-emphasis: var(--color-group-900);
|
|
125
|
+
|
|
126
|
+
--color-summary: var(--color-summary-600);
|
|
127
|
+
--color-summary-hover: var(--color-summary-700);
|
|
128
|
+
--color-summary-active: var(--color-summary-800);
|
|
129
|
+
--color-summary-subtle: var(--color-summary-50);
|
|
130
|
+
--color-summary-emphasis: var(--color-summary-900);
|
|
131
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @urbicon-ui/table – Comfortable Theme
|
|
3
|
+
*
|
|
4
|
+
* Overrides the default table tokens for spacious layouts.
|
|
5
|
+
* Import AFTER the base table styles:
|
|
6
|
+
*
|
|
7
|
+
* @import '@urbicon-ui/table/style/index.css';
|
|
8
|
+
* @import '@urbicon-ui/table/style/themes/comfortable.css';
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
@theme {
|
|
12
|
+
--table-header-height: 3.5rem;
|
|
13
|
+
--table-row-height: 4rem;
|
|
14
|
+
--table-cell-padding-x: 1.5rem;
|
|
15
|
+
--table-cell-padding-y: 1rem;
|
|
16
|
+
|
|
17
|
+
--filter-bar-height: 4rem;
|
|
18
|
+
--filter-bar-padding: 1rem;
|
|
19
|
+
--filter-bar-gap: 1rem;
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @urbicon-ui/table – Compact Theme
|
|
3
|
+
*
|
|
4
|
+
* Overrides the default table tokens for denser layouts.
|
|
5
|
+
* Import AFTER the base table styles:
|
|
6
|
+
*
|
|
7
|
+
* @import '@urbicon-ui/table/style/index.css';
|
|
8
|
+
* @import '@urbicon-ui/table/style/themes/compact.css';
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
@theme {
|
|
12
|
+
--table-header-height: 2.25rem;
|
|
13
|
+
--table-row-height: 2.5rem;
|
|
14
|
+
--table-cell-padding-x: 0.5rem;
|
|
15
|
+
--table-cell-padding-y: 0.375rem;
|
|
16
|
+
|
|
17
|
+
--filter-bar-height: 2.5rem;
|
|
18
|
+
--filter-bar-padding: 0.5rem;
|
|
19
|
+
--filter-bar-gap: 0.5rem;
|
|
20
|
+
}
|