@smartnet360/svelte-components 0.0.133 → 0.0.135

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.
Files changed (40) hide show
  1. package/dist/core/CellHistory/CellHistoryPanel.svelte +178 -0
  2. package/dist/core/CellHistory/CellHistoryPanel.svelte.d.ts +4 -0
  3. package/dist/core/CellHistory/column-config.d.ts +26 -0
  4. package/dist/core/CellHistory/column-config.js +120 -0
  5. package/dist/core/CellHistory/index.d.ts +9 -0
  6. package/dist/core/CellHistory/index.js +10 -0
  7. package/dist/core/CellHistory/transformers.d.ts +16 -0
  8. package/dist/core/CellHistory/transformers.js +76 -0
  9. package/dist/core/CellHistory/types.d.ts +54 -0
  10. package/dist/core/CellHistory/types.js +6 -0
  11. package/dist/core/CellTable/CellHistoryDemo.svelte +1 -0
  12. package/dist/core/CellTable/CellTable.svelte +7 -5
  13. package/dist/core/CellTable/CellTablePanel.svelte +82 -14
  14. package/dist/core/CellTable/CellTablePanel.svelte.d.ts +2 -0
  15. package/dist/core/CellTable/column-config.js +46 -58
  16. package/dist/core/CellTableV2/CellTable.svelte +601 -0
  17. package/dist/core/CellTableV2/CellTable.svelte.d.ts +43 -0
  18. package/dist/core/CellTableV2/CellTablePanel.svelte +685 -0
  19. package/dist/core/CellTableV2/CellTablePanel.svelte.d.ts +98 -0
  20. package/dist/core/CellTableV2/CellTableToolbar.svelte +322 -0
  21. package/dist/core/CellTableV2/CellTableToolbar.svelte.d.ts +59 -0
  22. package/dist/core/CellTableV2/ColumnPicker.svelte +214 -0
  23. package/dist/core/CellTableV2/ColumnPicker.svelte.d.ts +26 -0
  24. package/dist/core/CellTableV2/column-config.d.ts +120 -0
  25. package/dist/core/CellTableV2/column-config.js +671 -0
  26. package/dist/core/CellTableV2/composables/index.d.ts +12 -0
  27. package/dist/core/CellTableV2/composables/index.js +9 -0
  28. package/dist/core/CellTableV2/composables/useColumnVisibility.svelte.d.ts +45 -0
  29. package/dist/core/CellTableV2/composables/useColumnVisibility.svelte.js +98 -0
  30. package/dist/core/CellTableV2/composables/usePersistence.svelte.d.ts +28 -0
  31. package/dist/core/CellTableV2/composables/usePersistence.svelte.js +101 -0
  32. package/dist/core/CellTableV2/composables/useScrollSpy.svelte.d.ts +44 -0
  33. package/dist/core/CellTableV2/composables/useScrollSpy.svelte.js +91 -0
  34. package/dist/core/CellTableV2/index.d.ts +12 -0
  35. package/dist/core/CellTableV2/index.js +14 -0
  36. package/dist/core/CellTableV2/types.d.ts +172 -0
  37. package/dist/core/CellTableV2/types.js +6 -0
  38. package/dist/core/index.d.ts +2 -0
  39. package/dist/core/index.js +5 -0
  40. package/package.json +1 -1
@@ -0,0 +1,178 @@
1
+ <script lang="ts">
2
+ import CellTablePanel from '../CellTableV2/CellTablePanel.svelte';
3
+ import type { RowSelectionEvent, CellData } from '../CellTableV2/types';
4
+ import type { HistoryTableRow, CellHistoryPanelProps } from './types';
5
+ import type { CellHistoryData } from '../CellTableV2/types';
6
+ import { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
7
+ import { getHistoryColumns } from './column-config';
8
+
9
+ let {
10
+ cellName = $bindable('1001141'),
11
+ historyData: externalData,
12
+ storageKey = 'cell-history-table',
13
+ showToolbar = true,
14
+ showExport = true,
15
+ headerFilters = true,
16
+ title = 'Cell Configuration History',
17
+ onselectionchange,
18
+ oncompare,
19
+ }: CellHistoryPanelProps = $props();
20
+
21
+ // Get history-specific columns
22
+ const historyColumns = getHistoryColumns(headerFilters);
23
+
24
+ // Internal state for API data
25
+ let rawHistoryData = $state<CellHistoryData[]>(EXAMPLE_HISTORY_DATA);
26
+
27
+ // Use external data if provided, otherwise transform internal data
28
+ let historyData = $derived(externalData ?? transformHistoryData(rawHistoryData));
29
+
30
+ function loadHistory() {
31
+ // TODO: Replace with actual API call
32
+ console.log(`Loading history for cell: ${cellName}`);
33
+ rawHistoryData = EXAMPLE_HISTORY_DATA.filter(r => r.CELLNAME === cellName);
34
+ }
35
+
36
+ function handleSelectionChange(event: RowSelectionEvent) {
37
+ console.log('Selection changed:', event.ids);
38
+ onselectionchange?.({
39
+ ids: event.ids,
40
+ rows: event.rows as unknown as HistoryTableRow[]
41
+ });
42
+ }
43
+
44
+ /**
45
+ * Compare two selected history records - opens antenna compare tool
46
+ */
47
+ function handleCompareTwoRecords(record1: HistoryTableRow, record2: HistoryTableRow) {
48
+ // Allow external handler to override
49
+ if (oncompare) {
50
+ oncompare(record1, record2);
51
+ return;
52
+ }
53
+
54
+ // Default behavior: open antenna compare page
55
+ const params = new URLSearchParams();
56
+
57
+ // Use antenna from both records
58
+ if (record1.antenna) params.set('ant1', record1.antenna);
59
+ if (record2.antenna) params.set('ant2', record2.antenna);
60
+
61
+ // Use frequency (same for both records typically)
62
+ params.set('freq1', String(record1.frequency || 1800));
63
+ params.set('freq2', String(record2.frequency || 1800));
64
+
65
+ // Use electrical tilt values
66
+ params.set('etilt1', String(record1.electricalTilt || 0));
67
+ params.set('etilt2', String(record2.electricalTilt || 0));
68
+
69
+ // Use mechanical tilt values
70
+ params.set('mtilt1', String(record1.mechanicalTilt || 0));
71
+ params.set('mtilt2', String(record2.mechanicalTilt || 0));
72
+
73
+ // Add config date as labels
74
+ params.set('label1', `${record1.cellName} (${record1.configDate})`);
75
+ params.set('label2', `${record2.cellName} (${record2.configDate})`);
76
+
77
+ const url = `/apps/antenna-compare?${params.toString()}`;
78
+ window.open(url, '_blank');
79
+ }
80
+ </script>
81
+
82
+ <div class="cell-history-panel vh-100 d-flex flex-column">
83
+ <!-- Header -->
84
+ <div class="history-controls bg-light border-bottom px-3 py-2 d-flex align-items-center gap-3 flex-wrap">
85
+ <div class="input-group input-group-sm" style="width: auto;">
86
+ <span class="input-group-text">Cell Name</span>
87
+ <input
88
+ type="text"
89
+ class="form-control"
90
+ bind:value={cellName}
91
+ style="width: 120px;"
92
+ />
93
+ <button class="btn btn-outline-primary" onclick={loadHistory}>
94
+ <i class="bi bi-arrow-clockwise"></i> Load History
95
+ </button>
96
+ </div>
97
+ <span class="badge bg-info">
98
+ {historyData.length} records
99
+ </span>
100
+ <span class="text-muted small">
101
+ Select 2 rows to compare antenna configurations
102
+ </span>
103
+ </div>
104
+
105
+ <!-- CellTablePanel with custom history columns -->
106
+ <div class="flex-grow-1 overflow-hidden">
107
+ <CellTablePanel
108
+ cells={historyData as unknown as CellData[]}
109
+ groupBy="none"
110
+ {storageKey}
111
+ groupOptions={[
112
+ { value: 'none', label: 'No Grouping' },
113
+ { value: 'antenna', label: 'Antenna Type' },
114
+ { value: 'cellname', label: 'Cell Name' },
115
+ ]}
116
+ customColumns={historyColumns}
117
+ showColumnPresets={false}
118
+ selectable={true}
119
+ multiSelect={true}
120
+ {showToolbar}
121
+ {showExport}
122
+ {headerFilters}
123
+ showDetailsSidebar={false}
124
+ showScrollSpy={false}
125
+ {title}
126
+ onselectionchange={handleSelectionChange}
127
+ >
128
+ {#snippet footer({ selectedRows, selectedCount })}
129
+ <div class="d-flex align-items-center justify-content-between">
130
+ <span class="text-muted small">
131
+ {#if selectedCount > 0}
132
+ {selectedCount} record(s) selected
133
+ {:else}
134
+ Select rows to compare configurations
135
+ {/if}
136
+ </span>
137
+ <div class="btn-group">
138
+ <button
139
+ type="button"
140
+ class="btn btn-sm btn-outline-success"
141
+ disabled={selectedCount !== 2}
142
+ title={selectedCount === 2
143
+ ? 'Compare antenna patterns for selected dates'
144
+ : 'Select exactly 2 records to compare'}
145
+ onclick={() =>
146
+ handleCompareTwoRecords(
147
+ selectedRows[0] as unknown as HistoryTableRow,
148
+ selectedRows[1] as unknown as HistoryTableRow
149
+ )}
150
+ >
151
+ <i class="bi bi-broadcast-pin"></i>
152
+ <span class="d-none d-sm-inline ms-1">Compare Antennas</span>
153
+ </button>
154
+ <button
155
+ type="button"
156
+ class="btn btn-sm btn-outline-secondary"
157
+ disabled={selectedCount === 0}
158
+ onclick={() => console.log('Export:', selectedRows.map((r) => r.configDate))}
159
+ >
160
+ <i class="bi bi-download"></i>
161
+ <span class="d-none d-sm-inline ms-1">Export</span>
162
+ </button>
163
+ </div>
164
+ </div>
165
+ {/snippet}
166
+ </CellTablePanel>
167
+ </div>
168
+ </div>
169
+
170
+ <style>
171
+ .cell-history-panel {
172
+ background: var(--bs-body-bg, #f8f9fa);
173
+ }
174
+
175
+ .history-controls {
176
+ flex-shrink: 0;
177
+ }
178
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { CellHistoryPanelProps } from './types';
2
+ declare const CellHistoryPanel: import("svelte").Component<CellHistoryPanelProps, {}, "cellName">;
3
+ type CellHistoryPanel = ReturnType<typeof CellHistoryPanel>;
4
+ export default CellHistoryPanel;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * CellHistory - Column Configuration
3
+ *
4
+ * History-specific column definitions and formatters
5
+ */
6
+ import type { ColumnDefinition, CellComponent } from 'tabulator-tables';
7
+ /**
8
+ * Create a history change formatter for showing current vs previous values
9
+ * Highlights changes in yellow/amber, unchanged values in muted style
10
+ *
11
+ * @param currentField - Field name for current value
12
+ * @param prevField - Field name for previous value
13
+ */
14
+ export declare function createHistoryChangeFormatter(currentField: string, prevField: string): (cell: CellComponent) => string;
15
+ /**
16
+ * Format ISO date string to YYYY-MM-DD format for history display
17
+ */
18
+ export declare function historyDateFormatter(cell: CellComponent): string;
19
+ /**
20
+ * Get history-specific column definitions
21
+ */
22
+ export declare function getHistoryColumns(headerFilters?: boolean): ColumnDefinition[];
23
+ /**
24
+ * History column fields for visibility tracking
25
+ */
26
+ export declare const HISTORY_COLUMN_FIELDS: string[];
@@ -0,0 +1,120 @@
1
+ /**
2
+ * CellHistory - Column Configuration
3
+ *
4
+ * History-specific column definitions and formatters
5
+ */
6
+ /**
7
+ * Create a history change formatter for showing current vs previous values
8
+ * Highlights changes in yellow/amber, unchanged values in muted style
9
+ *
10
+ * @param currentField - Field name for current value
11
+ * @param prevField - Field name for previous value
12
+ */
13
+ export function createHistoryChangeFormatter(currentField, prevField) {
14
+ return (cell) => {
15
+ const row = cell.getRow().getData();
16
+ const currentVal = row[currentField];
17
+ const prevVal = row[prevField];
18
+ const currentStr = currentVal !== null && currentVal !== undefined ? String(currentVal) : '-';
19
+ const prevStr = prevVal !== null && prevVal !== undefined ? String(prevVal) : '-';
20
+ const hasChanged = currentVal !== prevVal;
21
+ if (hasChanged) {
22
+ // Value changed - highlight with amber/warning color
23
+ return `<span class="badge bg-warning text-dark" style="font-size: 0.75rem; font-weight: 500;" title="Changed from: ${prevStr}">${currentStr}</span>`;
24
+ }
25
+ else {
26
+ // No change - muted style
27
+ return `<span class="text-muted">${currentStr}</span>`;
28
+ }
29
+ };
30
+ }
31
+ /**
32
+ * Format ISO date string to YYYY-MM-DD format for history display
33
+ */
34
+ export function historyDateFormatter(cell) {
35
+ const value = cell.getValue();
36
+ if (!value)
37
+ return '-';
38
+ try {
39
+ const date = new Date(value);
40
+ const year = date.getFullYear();
41
+ const month = String(date.getMonth() + 1).padStart(2, '0');
42
+ const day = String(date.getDate()).padStart(2, '0');
43
+ return `${year}-${month}-${day}`;
44
+ }
45
+ catch {
46
+ return value;
47
+ }
48
+ }
49
+ /**
50
+ * Get history-specific column definitions
51
+ */
52
+ export function getHistoryColumns(headerFilters = true) {
53
+ const headerFilterParams = headerFilters ? { headerFilter: 'input' } : {};
54
+ return [
55
+ // Core identifier
56
+ {
57
+ title: 'Cell Name',
58
+ field: 'cellName',
59
+ width: 120,
60
+ frozen: true,
61
+ ...headerFilterParams,
62
+ },
63
+ // History-specific columns
64
+ {
65
+ title: 'Config Date',
66
+ field: 'configDate',
67
+ width: 120,
68
+ formatter: historyDateFormatter,
69
+ ...headerFilterParams,
70
+ },
71
+ {
72
+ title: 'Freq (MHz)',
73
+ field: 'frequency',
74
+ width: 100,
75
+ hozAlign: 'right',
76
+ ...headerFilterParams,
77
+ },
78
+ // Change columns (current vs previous, highlights differences)
79
+ {
80
+ title: 'Antenna',
81
+ field: 'antennaChange',
82
+ width: 160,
83
+ formatter: createHistoryChangeFormatter('antenna', 'prevAntenna'),
84
+ ...headerFilterParams,
85
+ },
86
+ {
87
+ title: 'E-Tilt',
88
+ field: 'etiltChange',
89
+ width: 80,
90
+ hozAlign: 'center',
91
+ formatter: createHistoryChangeFormatter('electricalTilt', 'prevElectricalTilt'),
92
+ },
93
+ {
94
+ title: 'M-Tilt',
95
+ field: 'mtiltChange',
96
+ width: 80,
97
+ hozAlign: 'center',
98
+ formatter: createHistoryChangeFormatter('mechanicalTilt', 'prevMechanicalTilt'),
99
+ },
100
+ {
101
+ title: 'Power',
102
+ field: 'powerChange',
103
+ width: 80,
104
+ hozAlign: 'center',
105
+ formatter: createHistoryChangeFormatter('power', 'prevPower'),
106
+ },
107
+ ];
108
+ }
109
+ /**
110
+ * History column fields for visibility tracking
111
+ */
112
+ export const HISTORY_COLUMN_FIELDS = [
113
+ 'cellName',
114
+ 'configDate',
115
+ 'frequency',
116
+ 'antennaChange',
117
+ 'etiltChange',
118
+ 'mtiltChange',
119
+ 'powerChange'
120
+ ];
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Cell History Feature
3
+ *
4
+ * Cell configuration history tracking and comparison
5
+ * Uses CellTableV2 for the underlying table functionality
6
+ */
7
+ export { default as CellHistoryPanel } from './CellHistoryPanel.svelte';
8
+ export type { HistoryTableRow, CellHistoryPanelProps } from './types';
9
+ export { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Cell History Feature
3
+ *
4
+ * Cell configuration history tracking and comparison
5
+ * Uses CellTableV2 for the underlying table functionality
6
+ */
7
+ // Main component
8
+ export { default as CellHistoryPanel } from './CellHistoryPanel.svelte';
9
+ // Utilities
10
+ export { transformHistoryData, EXAMPLE_HISTORY_DATA } from './transformers';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Cell History Transformers
3
+ *
4
+ * Functions to transform API data to table-ready format
5
+ */
6
+ import type { CellHistoryData } from '../CellTableV2/types';
7
+ import type { HistoryTableRow } from './types';
8
+ /**
9
+ * Transform API history data to table-friendly format
10
+ * Maps UPPER_CASE API fields to camelCase and adds virtual fields for change detection
11
+ */
12
+ export declare function transformHistoryData(apiData: CellHistoryData[]): HistoryTableRow[];
13
+ /**
14
+ * Example API data for cell configuration history (for demos/testing)
15
+ */
16
+ export declare const EXAMPLE_HISTORY_DATA: CellHistoryData[];
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Cell History Transformers
3
+ *
4
+ * Functions to transform API data to table-ready format
5
+ */
6
+ /**
7
+ * Transform API history data to table-friendly format
8
+ * Maps UPPER_CASE API fields to camelCase and adds virtual fields for change detection
9
+ */
10
+ export function transformHistoryData(apiData) {
11
+ return apiData.map((record, index) => ({
12
+ id: `hist-${index}`,
13
+ cellName: record.CELLNAME,
14
+ frequency: record.FREQUENCY,
15
+ configDate: record.CONFIG_DATE,
16
+ // Current values
17
+ antenna: record.ANTENNA_TYPE,
18
+ electricalTilt: record.ELECTRONIC_TILT,
19
+ mechanicalTilt: record.MECHANIC_TILT,
20
+ power: record.ANTOUTPUTPWR,
21
+ // Previous values for change comparison
22
+ prevAntenna: record.PREV_ANTENNA_TYPE,
23
+ prevElectricalTilt: record.PREV_ELECTRONIC_TILT,
24
+ prevMechanicalTilt: record.PREV_MECHANIC_TILT,
25
+ prevPower: record.PREV_ANTOUTPUTPWR,
26
+ // Virtual fields for the change columns (needed for column filtering)
27
+ antennaChange: record.ANTENNA_TYPE,
28
+ etiltChange: record.ELECTRONIC_TILT,
29
+ mtiltChange: record.MECHANIC_TILT,
30
+ powerChange: record.ANTOUTPUTPWR,
31
+ }));
32
+ }
33
+ /**
34
+ * Example API data for cell configuration history (for demos/testing)
35
+ */
36
+ export const EXAMPLE_HISTORY_DATA = [
37
+ {
38
+ CELLNAME: '1001141',
39
+ FREQUENCY: 1800,
40
+ CONFIG_DATE: '2025-12-03T23:00:00.000Z',
41
+ ANTENNA_TYPE: 'AQU4521R01v06',
42
+ PREV_ANTENNA_TYPE: 'AQU4521R01v06',
43
+ ANTOUTPUTPWR: 20,
44
+ PREV_ANTOUTPUTPWR: 20,
45
+ MECHANIC_TILT: 1,
46
+ PREV_MECHANIC_TILT: 1,
47
+ ELECTRONIC_TILT: 10,
48
+ PREV_ELECTRONIC_TILT: 9
49
+ },
50
+ {
51
+ CELLNAME: '1001141',
52
+ FREQUENCY: 1800,
53
+ CONFIG_DATE: '2025-09-11T22:00:00.000Z',
54
+ ANTENNA_TYPE: 'AQU4521R01v06',
55
+ PREV_ANTENNA_TYPE: 'ADU451602v01',
56
+ ANTOUTPUTPWR: 20,
57
+ PREV_ANTOUTPUTPWR: 20,
58
+ MECHANIC_TILT: 1,
59
+ PREV_MECHANIC_TILT: 0,
60
+ ELECTRONIC_TILT: 9,
61
+ PREV_ELECTRONIC_TILT: 10
62
+ },
63
+ {
64
+ CELLNAME: '1001141',
65
+ FREQUENCY: 1800,
66
+ CONFIG_DATE: '2021-02-15T23:00:00.000Z',
67
+ ANTENNA_TYPE: 'ADU451602v01',
68
+ PREV_ANTENNA_TYPE: 'ADU451602v01',
69
+ ANTOUTPUTPWR: 20,
70
+ PREV_ANTOUTPUTPWR: 20,
71
+ MECHANIC_TILT: 0,
72
+ PREV_MECHANIC_TILT: 2,
73
+ ELECTRONIC_TILT: 10,
74
+ PREV_ELECTRONIC_TILT: 10
75
+ }
76
+ ];
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Cell History Types
3
+ *
4
+ * Type definitions for cell configuration history feature
5
+ */
6
+ export type { CellHistoryData } from '../CellTableV2/types';
7
+ /**
8
+ * Table-ready history record after transformation from API data
9
+ * Maps UPPER_CASE API fields to camelCase for table columns
10
+ */
11
+ export interface HistoryTableRow {
12
+ id: string;
13
+ cellName: string;
14
+ frequency: number;
15
+ configDate: string;
16
+ antenna: string;
17
+ electricalTilt: number;
18
+ mechanicalTilt: number;
19
+ power: number;
20
+ prevAntenna: string;
21
+ prevElectricalTilt: number;
22
+ prevMechanicalTilt: number;
23
+ prevPower: number;
24
+ antennaChange: string;
25
+ etiltChange: number;
26
+ mtiltChange: number;
27
+ powerChange: number;
28
+ }
29
+ /**
30
+ * Props for CellHistoryPanel component
31
+ */
32
+ export interface CellHistoryPanelProps {
33
+ /** Cell name to load history for */
34
+ cellName?: string;
35
+ /** Pre-loaded history data (optional, for external data sources) */
36
+ historyData?: HistoryTableRow[];
37
+ /** Storage key prefix for persistence */
38
+ storageKey?: string;
39
+ /** Show toolbar controls */
40
+ showToolbar?: boolean;
41
+ /** Show export button */
42
+ showExport?: boolean;
43
+ /** Enable header filters */
44
+ headerFilters?: boolean;
45
+ /** Panel title */
46
+ title?: string;
47
+ /** Callback when selection changes */
48
+ onselectionchange?: (event: {
49
+ ids: string[];
50
+ rows: HistoryTableRow[];
51
+ }) => void;
52
+ /** Callback when compare is requested */
53
+ oncompare?: (record1: HistoryTableRow, record2: HistoryTableRow) => void;
54
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Cell History Types
3
+ *
4
+ * Type definitions for cell configuration history feature
5
+ */
6
+ export {};
@@ -174,6 +174,7 @@
174
174
  <CellTablePanel
175
175
  cells={historyData as unknown as import('./types').CellData[]}
176
176
  groupBy="none"
177
+ storageKey="cell-history-table"
177
178
  groupOptions={[
178
179
  { value: 'none', label: 'No Grouping' },
179
180
  { value: 'antenna', label: 'Antenna Type' },
@@ -56,7 +56,7 @@
56
56
  headerFilters = true,
57
57
  resizableColumns = true,
58
58
  movableColumns = true,
59
- persistLayout = false,
59
+ persistLayout = true,
60
60
  storageKey = 'cell-table-layout',
61
61
  onselectionchange,
62
62
  onrowclick,
@@ -119,11 +119,12 @@
119
119
  selectable: selectable ? (multiSelect ? true : 1) : false,
120
120
  selectableRangeMode: 'click',
121
121
 
122
- // Persistence - disable sort persistence to preserve pre-sorted order
122
+ // Persistence - save column widths, order, visibility and group settings
123
123
  persistence: persistLayout ? {
124
- filter: true,
125
- columns: ['width', 'visible'],
124
+ columns: ['width', 'visible', 'order'],
125
+ group: true,
126
126
  } : false,
127
+ persistenceMode: persistLayout ? 'local' : undefined,
127
128
  persistenceID: persistLayout ? storageKey : undefined,
128
129
 
129
130
  // Grouping
@@ -230,7 +231,8 @@
230
231
  // Track previous values to avoid unnecessary updates
231
232
  let prevCellsRef: unknown[] | null = null;
232
233
  let prevGroupBy: string | null = null;
233
- let prevColumnPreset: string | null = null;
234
+ // Initialize with current preset to prevent setColumns on first load (which would override persisted layout)
235
+ let prevColumnPreset: string | null = columnPreset;
234
236
 
235
237
  // Update table data when cells change (reference comparison)
236
238
  $effect(() => {