@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,192 @@
|
|
|
1
|
+
import { SvelteSet } from 'svelte/reactivity';
|
|
2
|
+
import type { Column, Filter, FilterOperator, TableItem } from '..';
|
|
3
|
+
import { findColumnById, getNestedValue, resolveColumnId, resolveColumnValue, resolveValueById } from '../utils';
|
|
4
|
+
import type { TableState } from './concerns/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Table context key (deprecated — kept for backwards compatibility).
|
|
7
|
+
* Prefer `setTableContext()`/`getTableContext()` directly; the value is
|
|
8
|
+
* no longer used internally now that the context goes through
|
|
9
|
+
* `createContext<T>()`.
|
|
10
|
+
* @deprecated Use `setTableContext`/`getTableContext` instead.
|
|
11
|
+
*/
|
|
12
|
+
export declare const TABLE_CONTEXT_KEY = "table";
|
|
13
|
+
/**
|
|
14
|
+
* Column summary configuration.
|
|
15
|
+
* Defines which column to aggregate and how.
|
|
16
|
+
*/
|
|
17
|
+
export interface SummaryConfig {
|
|
18
|
+
/** Column key to aggregate */
|
|
19
|
+
column: string;
|
|
20
|
+
/** Aggregation type */
|
|
21
|
+
type: 'sum' | 'avg' | 'count' | 'min' | 'max';
|
|
22
|
+
/** Optional custom formatter for the aggregated value */
|
|
23
|
+
formatter?: (value: number) => string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Configuration for table state persistence across reloads.
|
|
27
|
+
*
|
|
28
|
+
* Each `persist*` axis defaults to `true` — providing a `tableId` is
|
|
29
|
+
* enough to opt every view-state axis (filters, search, group, summary,
|
|
30
|
+
* sort, column visibility, column order) into persistence. Set
|
|
31
|
+
* individual flags to `false` to keep them volatile.
|
|
32
|
+
*
|
|
33
|
+
* Storage defaults to `localStorage` for every axis so reloads,
|
|
34
|
+
* tab-close-and-reopen, and full browser restarts all restore the view.
|
|
35
|
+
* Pass `storage: 'sessionStorage'` to limit persistence to the current
|
|
36
|
+
* tab. Pagination (current page) is never persisted — page 1 on
|
|
37
|
+
* navigation is intentional UX.
|
|
38
|
+
*/
|
|
39
|
+
export interface TablePersistenceConfig {
|
|
40
|
+
/** Unique identifier for this table — used as the storage-key suffix. */
|
|
41
|
+
tableId: string;
|
|
42
|
+
/** Storage type for every axis. Defaults to `localStorage`. */
|
|
43
|
+
storage?: 'localStorage' | 'sessionStorage';
|
|
44
|
+
/** Write debounce in ms. Defaults to 500. */
|
|
45
|
+
debounceMs?: number;
|
|
46
|
+
/** Persist `activeFilters`. Default `true`. */
|
|
47
|
+
persistFilters?: boolean;
|
|
48
|
+
/** Persist `searchTerm`. Default `true`. */
|
|
49
|
+
persistSearch?: boolean;
|
|
50
|
+
/** Persist `groupByKey`. Default `true`. */
|
|
51
|
+
persistGroupByKey?: boolean;
|
|
52
|
+
/** Persist `summaryConfigs`. Default `true`. */
|
|
53
|
+
persistSummaryConfigs?: boolean;
|
|
54
|
+
/** Persist `sortColumn` + `sortDirection`. Default `true`. */
|
|
55
|
+
persistSort?: boolean;
|
|
56
|
+
/** Persist hidden column ids. Default `true`. */
|
|
57
|
+
persistColumnVisibility?: boolean;
|
|
58
|
+
/** Persist column order. Default `true`. */
|
|
59
|
+
persistColumnOrder?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Creates the table state by composing independent concerns.
|
|
63
|
+
*
|
|
64
|
+
* Derived chain: items → filteredItems → sortedItems → grouped → paginatedItems
|
|
65
|
+
*
|
|
66
|
+
* Each concern owns a slice of functionality (search, filtering, sorting, etc.)
|
|
67
|
+
* but all read from and write to a shared reactive state object.
|
|
68
|
+
*
|
|
69
|
+
* **Generic T erasure**: The consumer-facing `TableProps<T>` is generic, but the
|
|
70
|
+
* store operates on `TableItem` (`Record<string, unknown>`). This is intentional —
|
|
71
|
+
* Svelte's context system cannot carry generics, and the store concerns only need
|
|
72
|
+
* property access by string key. Type safety for row data is the consumer's
|
|
73
|
+
* responsibility at the `TableProps<T>` boundary.
|
|
74
|
+
*/
|
|
75
|
+
export declare function createTableState(persistenceConfig?: TablePersistenceConfig): {
|
|
76
|
+
state: TableState;
|
|
77
|
+
readonly filteredItems: TableItem[];
|
|
78
|
+
readonly sortedItems: TableItem[];
|
|
79
|
+
readonly paginatedItems: TableItem[];
|
|
80
|
+
readonly totalItems: number;
|
|
81
|
+
readonly totalPages: number;
|
|
82
|
+
readonly grouped: Record<string, TableItem[]>;
|
|
83
|
+
readonly summaryData: Record<string, number>;
|
|
84
|
+
readonly groupedSummaryData: Record<string, Record<string, number>>;
|
|
85
|
+
setItems: (newItems: TableItem[]) => void;
|
|
86
|
+
setColumns: (newColumns: Column[]) => void;
|
|
87
|
+
setLoading: (isLoading: boolean) => void;
|
|
88
|
+
setError: (errorMsg: string | null) => void;
|
|
89
|
+
setSearchTerm: (term: string) => void;
|
|
90
|
+
toggleAdvancedSearch: () => void;
|
|
91
|
+
addFilter: (filter: Filter) => void;
|
|
92
|
+
removeFilter: (index: number) => void;
|
|
93
|
+
removeFiltersByColumn: (column: string, operator?: FilterOperator, value?: string) => void;
|
|
94
|
+
clearAllFilters: () => void;
|
|
95
|
+
hasFilterForColumn: (column: string, operator?: FilterOperator, value?: string) => boolean;
|
|
96
|
+
handleSort: (column: string) => void;
|
|
97
|
+
setPage: (page: number) => void;
|
|
98
|
+
goToPage: (page: number) => void;
|
|
99
|
+
setItemsPerPage: (count: number) => void;
|
|
100
|
+
toggleExpand: (itemId: string | number) => void;
|
|
101
|
+
isItemExpanded: (itemId: string | number) => boolean;
|
|
102
|
+
toggleGroup: (groupName: string) => void;
|
|
103
|
+
toggleGroupExpand: (groupName: string) => void;
|
|
104
|
+
toggleAllGroups: () => void;
|
|
105
|
+
setGroupByKey: (key: string | null) => void;
|
|
106
|
+
setGroupOrder: (order: string[]) => void;
|
|
107
|
+
addSummaryConfig: (config: SummaryConfig) => void;
|
|
108
|
+
removeSummaryConfig: (column: string) => void;
|
|
109
|
+
toggleSummary: () => void;
|
|
110
|
+
setSummaryConfigs: (configs: SummaryConfig[]) => void;
|
|
111
|
+
getFormattedSummaryValue: (column: string, value: number) => string;
|
|
112
|
+
getNestedValue: typeof getNestedValue;
|
|
113
|
+
resolveColumnId: typeof resolveColumnId;
|
|
114
|
+
resolveColumnValue: typeof resolveColumnValue;
|
|
115
|
+
resolveValueById: typeof resolveValueById;
|
|
116
|
+
findColumnById: typeof findColumnById;
|
|
117
|
+
readonly allColumns: Column[];
|
|
118
|
+
readonly hiddenColumnKeys: SvelteSet<string>;
|
|
119
|
+
hideColumn: (id: string) => void;
|
|
120
|
+
showColumn: (id: string) => void;
|
|
121
|
+
toggleColumnVisibility: (id: string) => void;
|
|
122
|
+
showAllColumns: () => void;
|
|
123
|
+
readonly selectedItems: TableItem[];
|
|
124
|
+
readonly allSelected: boolean;
|
|
125
|
+
readonly someSelected: boolean;
|
|
126
|
+
selectItem: (id: string | number) => void;
|
|
127
|
+
deselectItem: (id: string | number) => void;
|
|
128
|
+
toggleItem: (id: string | number) => void;
|
|
129
|
+
selectAll: () => void;
|
|
130
|
+
deselectAll: () => void;
|
|
131
|
+
toggleAll: () => void;
|
|
132
|
+
isSelected: (id: string | number) => boolean;
|
|
133
|
+
setSelectedIds: (ids: Array<string | number>) => void;
|
|
134
|
+
readonly orderedColumns: Column[];
|
|
135
|
+
readonly columnOrder: string[];
|
|
136
|
+
initColumnOrder: (columns: Column[]) => void;
|
|
137
|
+
reorderColumn: (fromIndex: number, toIndex: number) => void;
|
|
138
|
+
resetColumnOrder: () => void;
|
|
139
|
+
getColumnIndex: (id: string) => number;
|
|
140
|
+
readonly focusedRowIndex: number;
|
|
141
|
+
resetFocus: () => void;
|
|
142
|
+
setFocusedRow: (index: number) => void;
|
|
143
|
+
moveFocus: (direction: import("./concerns/useFocusManagement.svelte.js").FocusDirection) => void;
|
|
144
|
+
isFocusedRow: (index: number) => boolean;
|
|
145
|
+
readonly query: import("..").TableQuery;
|
|
146
|
+
readonly queryKey: string;
|
|
147
|
+
setServerResult: (result: {
|
|
148
|
+
items: TableItem[];
|
|
149
|
+
totalItems: number;
|
|
150
|
+
}) => void;
|
|
151
|
+
setServerError: (error: string) => void;
|
|
152
|
+
setServerLoading: () => void;
|
|
153
|
+
readonly liveUpdateCounts: import("./concerns/useLiveUpdates.svelte.js").LiveUpdateCounts;
|
|
154
|
+
readonly hasPendingUpdates: boolean;
|
|
155
|
+
pushInsert: (item: TableItem) => void;
|
|
156
|
+
pushUpdate: (id: string | number, changes: Partial<TableItem>) => void;
|
|
157
|
+
pushDelete: (id: string | number) => void;
|
|
158
|
+
applyAllUpdates: () => void;
|
|
159
|
+
applyInserts: () => void;
|
|
160
|
+
applyUpdates: () => void;
|
|
161
|
+
applyDeletes: () => void;
|
|
162
|
+
dismissAllUpdates: () => void;
|
|
163
|
+
isRecentlyUpdated: (id: string | number) => boolean;
|
|
164
|
+
isPendingDelete: (id: string | number) => boolean;
|
|
165
|
+
clearPersistedFilters: () => void | undefined;
|
|
166
|
+
clearPersistedSearchTerm: () => void | undefined;
|
|
167
|
+
clearPersistedGroupByKey: () => void | undefined;
|
|
168
|
+
clearPersistedSummaryConfigs: () => void | undefined;
|
|
169
|
+
clearPersistedSortState: () => void | undefined;
|
|
170
|
+
clearPersistedHiddenColumns: () => void | undefined;
|
|
171
|
+
clearPersistedColumnOrder: () => void | undefined;
|
|
172
|
+
clearAllPersistentData: () => void;
|
|
173
|
+
forceSavePersistentData: () => void;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Creates and sets the table context.
|
|
177
|
+
* @param persistenceConfig - Optional persistence configuration for filters, search, grouping, and summaries.
|
|
178
|
+
*/
|
|
179
|
+
export declare function setTableContext(persistenceConfig?: TablePersistenceConfig): any;
|
|
180
|
+
/**
|
|
181
|
+
* Retrieves the table context. Throws when called outside of a `<TableProvider>`
|
|
182
|
+
* — consumers within the table tree can rely on a defined return value. For the
|
|
183
|
+
* rare case where the absence of a provider must be detected, use
|
|
184
|
+
* `getTableContextRaw()` (internal) or `setTableContext()` (idempotent setter).
|
|
185
|
+
*/
|
|
186
|
+
export declare function getTableContext(): any;
|
|
187
|
+
/**
|
|
188
|
+
* Set the table context to an externally-created `tableState`. Used by
|
|
189
|
+
* `<TableProvider>` so it can construct the state once and share it
|
|
190
|
+
* with the rest of the table tree.
|
|
191
|
+
*/
|
|
192
|
+
export declare function attachTableContext(tableState: ReturnType<typeof createTableState>): void;
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import { createOptionalContext } from '@urbicon-ui/blocks';
|
|
2
|
+
import { SvelteSet } from 'svelte/reactivity';
|
|
3
|
+
import { findColumnById, getNestedValue, normalizeItems, resolveColumnId, resolveColumnValue, resolveValueById } from '../utils';
|
|
4
|
+
import { useColumnOrder } from './concerns/useColumnOrder.svelte.js';
|
|
5
|
+
import { useColumnVisibility } from './concerns/useColumnVisibility.svelte.js';
|
|
6
|
+
import { useExpansion } from './concerns/useExpansion.svelte.js';
|
|
7
|
+
import { useFiltering } from './concerns/useFiltering.svelte.js';
|
|
8
|
+
import { useFocusManagement } from './concerns/useFocusManagement.svelte.js';
|
|
9
|
+
import { useGrouping } from './concerns/useGrouping.svelte.js';
|
|
10
|
+
import { useLiveUpdates } from './concerns/useLiveUpdates.svelte.js';
|
|
11
|
+
import { usePagination } from './concerns/usePagination.svelte.js';
|
|
12
|
+
import { usePersistence } from './concerns/usePersistence.svelte.js';
|
|
13
|
+
import { useRemoteData } from './concerns/useRemoteData.svelte.js';
|
|
14
|
+
import { useSearch } from './concerns/useSearch.svelte.js';
|
|
15
|
+
import { useSelection } from './concerns/useSelection.svelte.js';
|
|
16
|
+
import { useSorting } from './concerns/useSorting.svelte.js';
|
|
17
|
+
import { useSummary } from './concerns/useSummary.svelte.js';
|
|
18
|
+
/**
|
|
19
|
+
* Table context key (deprecated — kept for backwards compatibility).
|
|
20
|
+
* Prefer `setTableContext()`/`getTableContext()` directly; the value is
|
|
21
|
+
* no longer used internally now that the context goes through
|
|
22
|
+
* `createContext<T>()`.
|
|
23
|
+
* @deprecated Use `setTableContext`/`getTableContext` instead.
|
|
24
|
+
*/
|
|
25
|
+
export const TABLE_CONTEXT_KEY = 'table';
|
|
26
|
+
/**
|
|
27
|
+
* Creates the table state by composing independent concerns.
|
|
28
|
+
*
|
|
29
|
+
* Derived chain: items → filteredItems → sortedItems → grouped → paginatedItems
|
|
30
|
+
*
|
|
31
|
+
* Each concern owns a slice of functionality (search, filtering, sorting, etc.)
|
|
32
|
+
* but all read from and write to a shared reactive state object.
|
|
33
|
+
*
|
|
34
|
+
* **Generic T erasure**: The consumer-facing `TableProps<T>` is generic, but the
|
|
35
|
+
* store operates on `TableItem` (`Record<string, unknown>`). This is intentional —
|
|
36
|
+
* Svelte's context system cannot carry generics, and the store concerns only need
|
|
37
|
+
* property access by string key. Type safety for row data is the consumer's
|
|
38
|
+
* responsibility at the `TableProps<T>` boundary.
|
|
39
|
+
*/
|
|
40
|
+
export function createTableState(persistenceConfig) {
|
|
41
|
+
// ── Shared reactive state ──
|
|
42
|
+
const state = $state({
|
|
43
|
+
items: [],
|
|
44
|
+
columns: [],
|
|
45
|
+
loading: false,
|
|
46
|
+
error: null,
|
|
47
|
+
searchTerm: '',
|
|
48
|
+
activeFilters: [],
|
|
49
|
+
showAdvancedSearch: false,
|
|
50
|
+
currentPage: 1,
|
|
51
|
+
itemsPerPage: 10,
|
|
52
|
+
sortColumn: '',
|
|
53
|
+
sortDirection: 'asc',
|
|
54
|
+
expandedItemId: null,
|
|
55
|
+
expandedItemIds: new SvelteSet(),
|
|
56
|
+
multiExpand: false,
|
|
57
|
+
groupByKey: null,
|
|
58
|
+
collapsedGroups: new SvelteSet(),
|
|
59
|
+
allGroupsExpanded: true,
|
|
60
|
+
groupOrder: [],
|
|
61
|
+
summaryConfigs: [],
|
|
62
|
+
showSummary: false,
|
|
63
|
+
selectionMode: 'none',
|
|
64
|
+
selectedIds: new SvelteSet(),
|
|
65
|
+
mode: 'client',
|
|
66
|
+
serverTotalItems: 0
|
|
67
|
+
});
|
|
68
|
+
// ── Persistence (initializes state from storage) ──
|
|
69
|
+
const persistence = usePersistence(state, persistenceConfig);
|
|
70
|
+
// ── Concerns (composed in derived-chain order) ──
|
|
71
|
+
const search = useSearch(state);
|
|
72
|
+
const filtering = useFiltering(state);
|
|
73
|
+
const sorting = useSorting(state, () => filtering.filteredItems);
|
|
74
|
+
const grouping = useGrouping(state, () => sorting.sortedItems);
|
|
75
|
+
const pagination = usePagination(state, () => filtering.filteredItems, () => sorting.sortedItems);
|
|
76
|
+
const expansion = useExpansion(state);
|
|
77
|
+
const columnVisibility = useColumnVisibility(state);
|
|
78
|
+
const summary = useSummary(state, () => sorting.sortedItems, () => grouping.grouped);
|
|
79
|
+
const selection = useSelection(state, () => filtering.filteredItems);
|
|
80
|
+
const columnOrder = useColumnOrder(state);
|
|
81
|
+
const focus = useFocusManagement(state, () => pagination.paginatedItems.length);
|
|
82
|
+
const remoteData = useRemoteData(state);
|
|
83
|
+
const liveUpdates = useLiveUpdates(state);
|
|
84
|
+
// ── Apply persisted snapshots that live inside concerns ──
|
|
85
|
+
// `state.columns` is still empty at this point; the consumer's
|
|
86
|
+
// `columns` prop reaches `setColumns` after construction. Filtering by
|
|
87
|
+
// the persisted hidden ids happens there.
|
|
88
|
+
if (persistence.initialHiddenColumnIds.length > 0) {
|
|
89
|
+
columnVisibility.setHiddenIds(persistence.initialHiddenColumnIds);
|
|
90
|
+
}
|
|
91
|
+
if (persistence.initialColumnOrder.length > 0) {
|
|
92
|
+
columnOrder.applyOrder(persistence.initialColumnOrder);
|
|
93
|
+
}
|
|
94
|
+
// ── Thin wrappers that add persistence syncing ──
|
|
95
|
+
function setItems(newItems) {
|
|
96
|
+
state.items = normalizeItems(newItems);
|
|
97
|
+
}
|
|
98
|
+
function setLoading(isLoading) {
|
|
99
|
+
state.loading = isLoading;
|
|
100
|
+
}
|
|
101
|
+
function setError(errorMsg) {
|
|
102
|
+
state.error = errorMsg;
|
|
103
|
+
}
|
|
104
|
+
function setSearchTerm(term) {
|
|
105
|
+
search.setSearchTerm(term);
|
|
106
|
+
persistence.syncSearch();
|
|
107
|
+
}
|
|
108
|
+
function addFilter(filter) {
|
|
109
|
+
filtering.addFilter(filter);
|
|
110
|
+
persistence.syncFilters();
|
|
111
|
+
}
|
|
112
|
+
function removeFilter(index) {
|
|
113
|
+
filtering.removeFilter(index);
|
|
114
|
+
persistence.syncFilters();
|
|
115
|
+
}
|
|
116
|
+
function removeFiltersByColumn(column, operator, value) {
|
|
117
|
+
filtering.removeFiltersByColumn(column, operator, value);
|
|
118
|
+
persistence.syncFilters();
|
|
119
|
+
}
|
|
120
|
+
function clearAllFilters() {
|
|
121
|
+
filtering.clearAllFilters();
|
|
122
|
+
persistence.syncFilters();
|
|
123
|
+
}
|
|
124
|
+
function setGroupByKey(key) {
|
|
125
|
+
grouping.setGroupByKey(key);
|
|
126
|
+
persistence.syncGroupByKey();
|
|
127
|
+
}
|
|
128
|
+
function addSummaryConfig(config) {
|
|
129
|
+
summary.addSummaryConfig(config);
|
|
130
|
+
persistence.syncSummaryConfigs();
|
|
131
|
+
}
|
|
132
|
+
function removeSummaryConfig(column) {
|
|
133
|
+
summary.removeSummaryConfig(column);
|
|
134
|
+
persistence.syncSummaryConfigs();
|
|
135
|
+
}
|
|
136
|
+
function setSummaryConfigs(configs) {
|
|
137
|
+
summary.setSummaryConfigs(configs);
|
|
138
|
+
persistence.syncSummaryConfigs();
|
|
139
|
+
}
|
|
140
|
+
function handleSort(column) {
|
|
141
|
+
sorting.handleSort(column);
|
|
142
|
+
persistence.syncSortState();
|
|
143
|
+
}
|
|
144
|
+
function hideColumn(id) {
|
|
145
|
+
columnVisibility.hideColumn(id);
|
|
146
|
+
persistence.syncHiddenColumns([...columnVisibility.hiddenColumnKeys]);
|
|
147
|
+
}
|
|
148
|
+
function showColumn(id) {
|
|
149
|
+
columnVisibility.showColumn(id);
|
|
150
|
+
persistence.syncHiddenColumns([...columnVisibility.hiddenColumnKeys]);
|
|
151
|
+
}
|
|
152
|
+
function toggleColumnVisibility(id) {
|
|
153
|
+
columnVisibility.toggleColumnVisibility(id);
|
|
154
|
+
persistence.syncHiddenColumns([...columnVisibility.hiddenColumnKeys]);
|
|
155
|
+
}
|
|
156
|
+
function showAllColumns() {
|
|
157
|
+
columnVisibility.showAllColumns();
|
|
158
|
+
persistence.syncHiddenColumns([]);
|
|
159
|
+
}
|
|
160
|
+
function reorderColumn(fromIndex, toIndex) {
|
|
161
|
+
columnOrder.reorderColumn(fromIndex, toIndex);
|
|
162
|
+
persistence.syncColumnOrder(columnOrder.columnOrder);
|
|
163
|
+
}
|
|
164
|
+
function resetColumnOrder() {
|
|
165
|
+
columnOrder.resetColumnOrder();
|
|
166
|
+
persistence.syncColumnOrder([]);
|
|
167
|
+
}
|
|
168
|
+
// ── Public API ──
|
|
169
|
+
// `state` is exposed for internal sub-components that need direct reads.
|
|
170
|
+
// External consumers should prefer the wrapper methods (setSearchTerm,
|
|
171
|
+
// addFilter, handleSort, etc.) which enforce persistence sync and side effects.
|
|
172
|
+
return {
|
|
173
|
+
state,
|
|
174
|
+
// Derived getters
|
|
175
|
+
get filteredItems() {
|
|
176
|
+
return filtering.filteredItems;
|
|
177
|
+
},
|
|
178
|
+
get sortedItems() {
|
|
179
|
+
return sorting.sortedItems;
|
|
180
|
+
},
|
|
181
|
+
get paginatedItems() {
|
|
182
|
+
return pagination.paginatedItems;
|
|
183
|
+
},
|
|
184
|
+
get totalItems() {
|
|
185
|
+
return pagination.totalItems;
|
|
186
|
+
},
|
|
187
|
+
get totalPages() {
|
|
188
|
+
return pagination.totalPages;
|
|
189
|
+
},
|
|
190
|
+
get grouped() {
|
|
191
|
+
return grouping.grouped;
|
|
192
|
+
},
|
|
193
|
+
get summaryData() {
|
|
194
|
+
return summary.summaryData;
|
|
195
|
+
},
|
|
196
|
+
get groupedSummaryData() {
|
|
197
|
+
return summary.groupedSummaryData;
|
|
198
|
+
},
|
|
199
|
+
// Data management
|
|
200
|
+
setItems,
|
|
201
|
+
setColumns: columnVisibility.setColumns,
|
|
202
|
+
setLoading,
|
|
203
|
+
setError,
|
|
204
|
+
// Search
|
|
205
|
+
setSearchTerm,
|
|
206
|
+
toggleAdvancedSearch: search.toggleAdvancedSearch,
|
|
207
|
+
// Filtering
|
|
208
|
+
addFilter,
|
|
209
|
+
removeFilter,
|
|
210
|
+
removeFiltersByColumn,
|
|
211
|
+
clearAllFilters,
|
|
212
|
+
hasFilterForColumn: filtering.hasFilterForColumn,
|
|
213
|
+
// Sorting
|
|
214
|
+
handleSort,
|
|
215
|
+
// Pagination
|
|
216
|
+
setPage: pagination.setPage,
|
|
217
|
+
goToPage: pagination.goToPage,
|
|
218
|
+
setItemsPerPage: pagination.setItemsPerPage,
|
|
219
|
+
// Expansion
|
|
220
|
+
toggleExpand: expansion.toggleExpand,
|
|
221
|
+
isItemExpanded: expansion.isItemExpanded,
|
|
222
|
+
// Grouping
|
|
223
|
+
toggleGroup: grouping.toggleGroup,
|
|
224
|
+
toggleGroupExpand: grouping.toggleGroup,
|
|
225
|
+
toggleAllGroups: grouping.toggleAllGroups,
|
|
226
|
+
setGroupByKey,
|
|
227
|
+
setGroupOrder: grouping.setGroupOrder,
|
|
228
|
+
// Summary
|
|
229
|
+
addSummaryConfig,
|
|
230
|
+
removeSummaryConfig,
|
|
231
|
+
toggleSummary: summary.toggleSummary,
|
|
232
|
+
setSummaryConfigs,
|
|
233
|
+
getFormattedSummaryValue: summary.getFormattedSummaryValue,
|
|
234
|
+
// Utilities
|
|
235
|
+
getNestedValue,
|
|
236
|
+
resolveColumnId,
|
|
237
|
+
resolveColumnValue,
|
|
238
|
+
resolveValueById,
|
|
239
|
+
findColumnById,
|
|
240
|
+
// Column visibility
|
|
241
|
+
get allColumns() {
|
|
242
|
+
return columnVisibility.allColumns;
|
|
243
|
+
},
|
|
244
|
+
get hiddenColumnKeys() {
|
|
245
|
+
return columnVisibility.hiddenColumnKeys;
|
|
246
|
+
},
|
|
247
|
+
hideColumn,
|
|
248
|
+
showColumn,
|
|
249
|
+
toggleColumnVisibility,
|
|
250
|
+
showAllColumns,
|
|
251
|
+
// Selection
|
|
252
|
+
get selectedItems() {
|
|
253
|
+
return selection.selectedItems;
|
|
254
|
+
},
|
|
255
|
+
get allSelected() {
|
|
256
|
+
return selection.allSelected;
|
|
257
|
+
},
|
|
258
|
+
get someSelected() {
|
|
259
|
+
return selection.someSelected;
|
|
260
|
+
},
|
|
261
|
+
selectItem: selection.selectItem,
|
|
262
|
+
deselectItem: selection.deselectItem,
|
|
263
|
+
toggleItem: selection.toggleItem,
|
|
264
|
+
selectAll: selection.selectAll,
|
|
265
|
+
deselectAll: selection.deselectAll,
|
|
266
|
+
toggleAll: selection.toggleAll,
|
|
267
|
+
isSelected: selection.isSelected,
|
|
268
|
+
setSelectedIds: selection.setSelectedIds,
|
|
269
|
+
// Column order
|
|
270
|
+
get orderedColumns() {
|
|
271
|
+
return columnOrder.orderedColumns;
|
|
272
|
+
},
|
|
273
|
+
get columnOrder() {
|
|
274
|
+
return columnOrder.columnOrder;
|
|
275
|
+
},
|
|
276
|
+
initColumnOrder: columnOrder.initOrder,
|
|
277
|
+
reorderColumn,
|
|
278
|
+
resetColumnOrder,
|
|
279
|
+
getColumnIndex: columnOrder.getColumnIndex,
|
|
280
|
+
// Focus management
|
|
281
|
+
get focusedRowIndex() {
|
|
282
|
+
return focus.focusedRowIndex;
|
|
283
|
+
},
|
|
284
|
+
resetFocus: focus.resetFocus,
|
|
285
|
+
setFocusedRow: focus.setFocusedRow,
|
|
286
|
+
moveFocus: focus.moveFocus,
|
|
287
|
+
isFocusedRow: focus.isFocusedRow,
|
|
288
|
+
// Remote data
|
|
289
|
+
get query() {
|
|
290
|
+
return remoteData.query;
|
|
291
|
+
},
|
|
292
|
+
get queryKey() {
|
|
293
|
+
return remoteData.queryKey;
|
|
294
|
+
},
|
|
295
|
+
setServerResult: remoteData.setServerResult,
|
|
296
|
+
setServerError: remoteData.setServerError,
|
|
297
|
+
setServerLoading: remoteData.setServerLoading,
|
|
298
|
+
// Live updates
|
|
299
|
+
get liveUpdateCounts() {
|
|
300
|
+
return liveUpdates.counts;
|
|
301
|
+
},
|
|
302
|
+
get hasPendingUpdates() {
|
|
303
|
+
return liveUpdates.hasPending;
|
|
304
|
+
},
|
|
305
|
+
pushInsert: liveUpdates.pushInsert,
|
|
306
|
+
pushUpdate: liveUpdates.pushUpdate,
|
|
307
|
+
pushDelete: liveUpdates.pushDelete,
|
|
308
|
+
applyAllUpdates: liveUpdates.applyAll,
|
|
309
|
+
applyInserts: liveUpdates.applyInserts,
|
|
310
|
+
applyUpdates: liveUpdates.applyUpdates,
|
|
311
|
+
applyDeletes: liveUpdates.applyDeletes,
|
|
312
|
+
dismissAllUpdates: liveUpdates.dismissAll,
|
|
313
|
+
isRecentlyUpdated: liveUpdates.isRecentlyUpdated,
|
|
314
|
+
isPendingDelete: liveUpdates.isPendingDelete,
|
|
315
|
+
// Persistence
|
|
316
|
+
clearPersistedFilters: persistence.clearPersistedFilters,
|
|
317
|
+
clearPersistedSearchTerm: persistence.clearPersistedSearchTerm,
|
|
318
|
+
clearPersistedGroupByKey: persistence.clearPersistedGroupByKey,
|
|
319
|
+
clearPersistedSummaryConfigs: persistence.clearPersistedSummaryConfigs,
|
|
320
|
+
clearPersistedSortState: persistence.clearPersistedSortState,
|
|
321
|
+
clearPersistedHiddenColumns: persistence.clearPersistedHiddenColumns,
|
|
322
|
+
clearPersistedColumnOrder: persistence.clearPersistedColumnOrder,
|
|
323
|
+
clearAllPersistentData: persistence.clearAllPersistentData,
|
|
324
|
+
forceSavePersistentData: persistence.forceSavePersistentData
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
// Optional — setTableContext returns the existing context if any, so the
|
|
328
|
+
// raw getter must be permissive (returns undefined when unset).
|
|
329
|
+
const [getTableContextRaw, setTableContextRaw] = createOptionalContext();
|
|
330
|
+
/**
|
|
331
|
+
* Creates and sets the table context.
|
|
332
|
+
* @param persistenceConfig - Optional persistence configuration for filters, search, grouping, and summaries.
|
|
333
|
+
*/
|
|
334
|
+
export function setTableContext(persistenceConfig) {
|
|
335
|
+
const existing = getTableContextRaw();
|
|
336
|
+
if (existing)
|
|
337
|
+
return existing;
|
|
338
|
+
const tableState = createTableState(persistenceConfig);
|
|
339
|
+
setTableContextRaw(tableState);
|
|
340
|
+
return tableState;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Retrieves the table context. Throws when called outside of a `<TableProvider>`
|
|
344
|
+
* — consumers within the table tree can rely on a defined return value. For the
|
|
345
|
+
* rare case where the absence of a provider must be detected, use
|
|
346
|
+
* `getTableContextRaw()` (internal) or `setTableContext()` (idempotent setter).
|
|
347
|
+
*/
|
|
348
|
+
export function getTableContext() {
|
|
349
|
+
const ctx = getTableContextRaw();
|
|
350
|
+
if (!ctx) {
|
|
351
|
+
throw new Error('`getTableContext()` was called outside of a `<TableProvider>`. Wrap the consuming component in `<TableProvider>` or use `setTableContext()` first.');
|
|
352
|
+
}
|
|
353
|
+
return ctx;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Set the table context to an externally-created `tableState`. Used by
|
|
357
|
+
* `<TableProvider>` so it can construct the state once and share it
|
|
358
|
+
* with the rest of the table tree.
|
|
359
|
+
*/
|
|
360
|
+
export function attachTableContext(tableState) {
|
|
361
|
+
setTableContextRaw(tableState);
|
|
362
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type { TableState } from './types.js';
|
|
2
|
+
export { useColumnOrder } from './useColumnOrder.svelte.js';
|
|
3
|
+
export { useColumnVisibility } from './useColumnVisibility.svelte.js';
|
|
4
|
+
export { useExpansion } from './useExpansion.svelte.js';
|
|
5
|
+
export { useFiltering } from './useFiltering.svelte.js';
|
|
6
|
+
export { useFocusManagement } from './useFocusManagement.svelte.js';
|
|
7
|
+
export { useGrouping } from './useGrouping.svelte.js';
|
|
8
|
+
export { useLiveUpdates } from './useLiveUpdates.svelte.js';
|
|
9
|
+
export { usePagination } from './usePagination.svelte.js';
|
|
10
|
+
export { usePersistence } from './usePersistence.svelte.js';
|
|
11
|
+
export { useRemoteData } from './useRemoteData.svelte.js';
|
|
12
|
+
export { useSearch } from './useSearch.svelte.js';
|
|
13
|
+
export { useSelection } from './useSelection.svelte.js';
|
|
14
|
+
export { useSorting } from './useSorting.svelte.js';
|
|
15
|
+
export { useSummary } from './useSummary.svelte.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { useColumnOrder } from './useColumnOrder.svelte.js';
|
|
2
|
+
export { useColumnVisibility } from './useColumnVisibility.svelte.js';
|
|
3
|
+
export { useExpansion } from './useExpansion.svelte.js';
|
|
4
|
+
export { useFiltering } from './useFiltering.svelte.js';
|
|
5
|
+
export { useFocusManagement } from './useFocusManagement.svelte.js';
|
|
6
|
+
export { useGrouping } from './useGrouping.svelte.js';
|
|
7
|
+
export { useLiveUpdates } from './useLiveUpdates.svelte.js';
|
|
8
|
+
export { usePagination } from './usePagination.svelte.js';
|
|
9
|
+
export { usePersistence } from './usePersistence.svelte.js';
|
|
10
|
+
export { useRemoteData } from './useRemoteData.svelte.js';
|
|
11
|
+
export { useSearch } from './useSearch.svelte.js';
|
|
12
|
+
export { useSelection } from './useSelection.svelte.js';
|
|
13
|
+
export { useSorting } from './useSorting.svelte.js';
|
|
14
|
+
export { useSummary } from './useSummary.svelte.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Column, Filter, TableItem } from '../../types/tableTypes';
|
|
2
|
+
import type { SummaryConfig } from '../TableStore.svelte';
|
|
3
|
+
/**
|
|
4
|
+
* Shared reactive table state. All concerns read from and write to this object.
|
|
5
|
+
*/
|
|
6
|
+
export interface TableState {
|
|
7
|
+
items: TableItem[];
|
|
8
|
+
columns: Column[];
|
|
9
|
+
loading: boolean;
|
|
10
|
+
error: string | null;
|
|
11
|
+
searchTerm: string;
|
|
12
|
+
activeFilters: Filter[];
|
|
13
|
+
showAdvancedSearch: boolean;
|
|
14
|
+
currentPage: number;
|
|
15
|
+
itemsPerPage: number;
|
|
16
|
+
sortColumn: string;
|
|
17
|
+
sortDirection: 'asc' | 'desc';
|
|
18
|
+
expandedItemId: string | number | null;
|
|
19
|
+
expandedItemIds: Set<string | number>;
|
|
20
|
+
multiExpand: boolean;
|
|
21
|
+
groupByKey: string | null;
|
|
22
|
+
collapsedGroups: Set<string>;
|
|
23
|
+
allGroupsExpanded: boolean;
|
|
24
|
+
groupOrder: string[];
|
|
25
|
+
summaryConfigs: SummaryConfig[];
|
|
26
|
+
showSummary: boolean;
|
|
27
|
+
selectionMode: 'none' | 'single' | 'multi';
|
|
28
|
+
selectedIds: Set<string | number>;
|
|
29
|
+
mode: 'client' | 'server';
|
|
30
|
+
serverTotalItems: number;
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Column } from '../../types/tableTypes';
|
|
2
|
+
import type { TableState } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Column order concern: manages column reordering.
|
|
5
|
+
* Maintains an ordered list of column ids and provides reorder operations.
|
|
6
|
+
* @param state - Shared table state (reads `columns` for initial order).
|
|
7
|
+
*/
|
|
8
|
+
export declare function useColumnOrder(state: TableState): {
|
|
9
|
+
readonly orderedColumns: Column[];
|
|
10
|
+
readonly columnOrder: string[];
|
|
11
|
+
initOrder: (columns: Column[]) => void;
|
|
12
|
+
reorderColumn: (fromIndex: number, toIndex: number) => void;
|
|
13
|
+
resetColumnOrder: () => void;
|
|
14
|
+
applyOrder: (order: string[]) => void;
|
|
15
|
+
getColumnIndex: (id: string) => number;
|
|
16
|
+
};
|