@smartnet360/svelte-components 0.0.134 → 0.0.136
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/CellHistory/CellHistoryPanel.svelte +178 -0
- package/dist/core/CellHistory/CellHistoryPanel.svelte.d.ts +4 -0
- package/dist/core/CellHistory/column-config.d.ts +26 -0
- package/dist/core/CellHistory/column-config.js +120 -0
- package/dist/core/CellHistory/index.d.ts +9 -0
- package/dist/core/CellHistory/index.js +10 -0
- package/dist/core/CellHistory/transformers.d.ts +16 -0
- package/dist/core/CellHistory/transformers.js +76 -0
- package/dist/core/CellHistory/types.d.ts +54 -0
- package/dist/core/CellHistory/types.js +6 -0
- package/dist/core/{CellTable → CellTableV2}/CellTable.svelte +7 -3
- package/dist/core/{CellTable → CellTableV2}/CellTable.svelte.d.ts +3 -0
- package/dist/core/{CellTable → CellTableV2}/CellTablePanel.svelte +87 -235
- package/dist/core/{CellTable → CellTableV2}/CellTablePanel.svelte.d.ts +16 -2
- package/dist/core/{CellTable → CellTableV2}/CellTableToolbar.svelte +0 -1
- package/dist/core/{CellTable → CellTableV2}/column-config.d.ts +11 -30
- package/dist/core/{CellTable → CellTableV2}/column-config.js +21 -220
- package/dist/core/CellTableV2/composables/index.d.ts +12 -0
- package/dist/core/CellTableV2/composables/index.js +9 -0
- package/dist/core/CellTableV2/composables/useColumnVisibility.svelte.d.ts +45 -0
- package/dist/core/CellTableV2/composables/useColumnVisibility.svelte.js +98 -0
- package/dist/core/CellTableV2/composables/usePersistence.svelte.d.ts +28 -0
- package/dist/core/CellTableV2/composables/usePersistence.svelte.js +101 -0
- package/dist/core/CellTableV2/composables/useScrollSpy.svelte.d.ts +44 -0
- package/dist/core/CellTableV2/composables/useScrollSpy.svelte.js +91 -0
- package/dist/core/CellTableV2/index.d.ts +12 -0
- package/dist/core/CellTableV2/index.js +14 -0
- package/dist/core/{CellTable → CellTableV2}/types.d.ts +3 -3
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +3 -1
- package/package.json +1 -1
- package/dist/core/CellTable/CellHistoryDemo.svelte +0 -240
- package/dist/core/CellTable/CellHistoryDemo.svelte.d.ts +0 -3
- package/dist/core/CellTable/CellTableDemo.svelte +0 -336
- package/dist/core/CellTable/CellTableDemo.svelte.d.ts +0 -3
- package/dist/core/CellTable/history-api-helper.d.ts +0 -79
- package/dist/core/CellTable/history-api-helper.js +0 -83
- package/dist/core/CellTable/index.d.ts +0 -15
- package/dist/core/CellTable/index.js +0 -20
- /package/dist/core/{CellTable → CellTableV2}/CellTableToolbar.svelte.d.ts +0 -0
- /package/dist/core/{CellTable → CellTableV2}/ColumnPicker.svelte +0 -0
- /package/dist/core/{CellTable → CellTableV2}/ColumnPicker.svelte.d.ts +0 -0
- /package/dist/core/{CellTable → CellTableV2}/types.js +0 -0
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* CellTablePanel V2 - Composable-based Cell Table Panel
|
|
4
|
+
*
|
|
5
|
+
* Uses composables for reusable logic:
|
|
6
|
+
* - usePersistence: localStorage read/write
|
|
7
|
+
* - useColumnVisibility: column preset and visibility management
|
|
8
|
+
* - useScrollSpy: group navigation
|
|
9
|
+
*/
|
|
2
10
|
import type { Snippet } from 'svelte';
|
|
11
|
+
import type { ColumnDefinition } from 'tabulator-tables';
|
|
3
12
|
import CellTable from './CellTable.svelte';
|
|
4
13
|
import CellTableToolbar from './CellTableToolbar.svelte';
|
|
5
14
|
import { getColumnMetadata, getPresetVisibleFields, DEFAULT_TECH_COLORS, DEFAULT_STATUS_COLORS, FBAND_COLORS } from './column-config';
|
|
15
|
+
import type { ColumnMetadataOptions } from './column-config';
|
|
6
16
|
import type {
|
|
7
17
|
CellData,
|
|
8
18
|
CellTableGroupField,
|
|
@@ -16,6 +26,9 @@
|
|
|
16
26
|
StatusColorMap,
|
|
17
27
|
GroupOption
|
|
18
28
|
} from './types';
|
|
29
|
+
import { usePersistence } from './composables/usePersistence.svelte';
|
|
30
|
+
import { useColumnVisibility } from './composables/useColumnVisibility.svelte';
|
|
31
|
+
import { useScrollSpy } from './composables/useScrollSpy.svelte';
|
|
19
32
|
|
|
20
33
|
interface Props {
|
|
21
34
|
/** Cell data array to display */
|
|
@@ -26,6 +39,10 @@
|
|
|
26
39
|
groupOptions?: GroupOption[];
|
|
27
40
|
/** Initial column preset */
|
|
28
41
|
columnPreset?: ColumnPreset;
|
|
42
|
+
/** Custom column definitions (overrides columnPreset when provided) */
|
|
43
|
+
customColumns?: ColumnDefinition[];
|
|
44
|
+
/** Column metadata filter options */
|
|
45
|
+
columnMetadataOptions?: ColumnMetadataOptions;
|
|
29
46
|
/** Enable row selection */
|
|
30
47
|
selectable?: boolean;
|
|
31
48
|
/** Enable multi-row selection */
|
|
@@ -52,7 +69,7 @@
|
|
|
52
69
|
showDetailsSidebar?: boolean;
|
|
53
70
|
/** Sidebar width in pixels */
|
|
54
71
|
sidebarWidth?: number;
|
|
55
|
-
/** Persist settings
|
|
72
|
+
/** Persist settings to localStorage */
|
|
56
73
|
persistSettings?: boolean;
|
|
57
74
|
/** Storage key prefix for persisted settings */
|
|
58
75
|
storageKey?: string;
|
|
@@ -84,7 +101,9 @@
|
|
|
84
101
|
cells = [],
|
|
85
102
|
groupBy = $bindable('none'),
|
|
86
103
|
groupOptions,
|
|
87
|
-
columnPreset =
|
|
104
|
+
columnPreset: initialPreset = 'default',
|
|
105
|
+
customColumns,
|
|
106
|
+
columnMetadataOptions,
|
|
88
107
|
selectable = true,
|
|
89
108
|
multiSelect = true,
|
|
90
109
|
height = '100%',
|
|
@@ -99,7 +118,7 @@
|
|
|
99
118
|
showDetailsSidebar = false,
|
|
100
119
|
sidebarWidth = 320,
|
|
101
120
|
persistSettings = true,
|
|
102
|
-
storageKey = 'cell-table',
|
|
121
|
+
storageKey = 'cell-table-v2',
|
|
103
122
|
persistLayout = true,
|
|
104
123
|
showScrollSpy = false,
|
|
105
124
|
tableRef = $bindable(null),
|
|
@@ -113,122 +132,28 @@
|
|
|
113
132
|
contextMenu
|
|
114
133
|
}: Props = $props();
|
|
115
134
|
|
|
116
|
-
//
|
|
117
|
-
let contextMenuVisible = $state(false);
|
|
118
|
-
let contextMenuRow: CellData | null = $state(null);
|
|
119
|
-
let contextMenuPosition = $state({ x: 0, y: 0 });
|
|
120
|
-
|
|
121
|
-
// Storage keys
|
|
122
|
-
const STORAGE_KEY_GROUP = `${storageKey}-groupBy`;
|
|
123
|
-
const STORAGE_KEY_FILTERS = `${storageKey}-filtersVisible`;
|
|
124
|
-
const STORAGE_KEY_SCROLLSPY = `${storageKey}-scrollSpyEnabled`;
|
|
125
|
-
const STORAGE_KEY_PRESET = `${storageKey}-columnPreset`;
|
|
135
|
+
// ========== Composables ==========
|
|
126
136
|
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
return `${storageKey}-visibleColumns-${preset}`;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Load persisted settings
|
|
133
|
-
function loadPersistedSettings() {
|
|
134
|
-
if (!persistSettings || typeof localStorage === 'undefined') return { filtersVisible: true, scrollSpyEnabled: showScrollSpy, preset: null };
|
|
135
|
-
|
|
136
|
-
let filters = true;
|
|
137
|
-
let scrollSpy = showScrollSpy;
|
|
138
|
-
let preset: ColumnPreset | null = null;
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
const savedGroup = localStorage.getItem(STORAGE_KEY_GROUP);
|
|
142
|
-
if (savedGroup) {
|
|
143
|
-
groupBy = savedGroup as CellTableGroupField;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const savedPreset = localStorage.getItem(STORAGE_KEY_PRESET);
|
|
147
|
-
if (savedPreset) {
|
|
148
|
-
preset = savedPreset as ColumnPreset;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const savedFilters = localStorage.getItem(STORAGE_KEY_FILTERS);
|
|
152
|
-
if (savedFilters !== null) {
|
|
153
|
-
filters = savedFilters === 'true';
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const savedScrollSpy = localStorage.getItem(STORAGE_KEY_SCROLLSPY);
|
|
157
|
-
if (savedScrollSpy !== null) {
|
|
158
|
-
scrollSpy = savedScrollSpy === 'true';
|
|
159
|
-
}
|
|
160
|
-
} catch (e) {
|
|
161
|
-
console.warn('Failed to load CellTable settings:', e);
|
|
162
|
-
}
|
|
163
|
-
return { filtersVisible: filters, scrollSpyEnabled: scrollSpy, preset };
|
|
164
|
-
}
|
|
137
|
+
// Persistence utilities
|
|
138
|
+
const persistence = usePersistence({ storageKey, enabled: persistSettings });
|
|
165
139
|
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Save group setting
|
|
183
|
-
function saveGroupSetting(group: CellTableGroupField) {
|
|
184
|
-
if (!persistSettings || typeof localStorage === 'undefined') return;
|
|
185
|
-
try {
|
|
186
|
-
localStorage.setItem(STORAGE_KEY_GROUP, group);
|
|
187
|
-
} catch (e) {
|
|
188
|
-
console.warn('Failed to save group setting:', e);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Save column visibility for current preset
|
|
193
|
-
function saveColumnVisibility(columns: string[]) {
|
|
194
|
-
if (!persistSettings || typeof localStorage === 'undefined') return;
|
|
195
|
-
try {
|
|
196
|
-
localStorage.setItem(getColumnsStorageKey(columnPreset), JSON.stringify(columns));
|
|
197
|
-
} catch (e) {
|
|
198
|
-
console.warn('Failed to save column visibility:', e);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Save filter visibility
|
|
203
|
-
function saveFilterVisibility(visible: boolean) {
|
|
204
|
-
if (!persistSettings || typeof localStorage === 'undefined') return;
|
|
205
|
-
try {
|
|
206
|
-
localStorage.setItem(STORAGE_KEY_FILTERS, String(visible));
|
|
207
|
-
} catch (e) {
|
|
208
|
-
console.warn('Failed to save filter visibility:', e);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Save scrollspy state
|
|
213
|
-
function saveScrollSpyState(enabled: boolean) {
|
|
214
|
-
if (!persistSettings || typeof localStorage === 'undefined') return;
|
|
215
|
-
try {
|
|
216
|
-
localStorage.setItem(STORAGE_KEY_SCROLLSPY, String(enabled));
|
|
217
|
-
} catch (e) {
|
|
218
|
-
console.warn('Failed to save scrollspy state:', e);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Save column preset
|
|
223
|
-
function savePreset(preset: ColumnPreset) {
|
|
224
|
-
if (!persistSettings || typeof localStorage === 'undefined') return;
|
|
225
|
-
try {
|
|
226
|
-
localStorage.setItem(STORAGE_KEY_PRESET, preset);
|
|
227
|
-
} catch (e) {
|
|
228
|
-
console.warn('Failed to save preset:', e);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
140
|
+
// Column visibility management
|
|
141
|
+
const columnVis = useColumnVisibility({
|
|
142
|
+
storageKey,
|
|
143
|
+
columnMeta: getColumnMetadata(columnMetadataOptions),
|
|
144
|
+
initialPreset,
|
|
145
|
+
persistSettings
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// ScrollSpy navigation
|
|
149
|
+
const scrollSpy = useScrollSpy({
|
|
150
|
+
storageKey,
|
|
151
|
+
initialEnabled: showScrollSpy,
|
|
152
|
+
persistSettings
|
|
153
|
+
});
|
|
231
154
|
|
|
155
|
+
// ========== Local State ==========
|
|
156
|
+
|
|
232
157
|
let cellTable: CellTable;
|
|
233
158
|
let selectedCount = $state(0);
|
|
234
159
|
let selectedRows = $state<CellData[]>([]);
|
|
@@ -236,50 +161,28 @@
|
|
|
236
161
|
let sidebarOpen = $state(false);
|
|
237
162
|
let clickedCell: CellData | null = $state(null);
|
|
238
163
|
let tableRefSet = false;
|
|
239
|
-
|
|
240
|
-
// Column visibility management
|
|
241
|
-
const columnMeta = getColumnMetadata();
|
|
164
|
+
let filtersVisible = $state(persistence.load('filtersVisible', true));
|
|
242
165
|
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
let
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
166
|
+
// Context menu state
|
|
167
|
+
let contextMenuVisible = $state(false);
|
|
168
|
+
let contextMenuRow: CellData | null = $state(null);
|
|
169
|
+
let contextMenuPosition = $state({ x: 0, y: 0 });
|
|
170
|
+
|
|
171
|
+
// Load initial groupBy from persistence
|
|
172
|
+
const savedGroupBy = persistence.loadString('groupBy', groupBy);
|
|
173
|
+
if (savedGroupBy && savedGroupBy !== groupBy) {
|
|
174
|
+
groupBy = savedGroupBy as CellTableGroupField;
|
|
250
175
|
}
|
|
251
|
-
|
|
252
|
-
// Load columns for the current preset (with any saved customizations)
|
|
253
|
-
let visibleColumns = $state<string[]>(loadColumnsForPreset(columnPreset));
|
|
254
|
-
|
|
255
|
-
// ScrollSpy state - initialize from persisted settings
|
|
256
|
-
let scrollSpyGroups = $state<{ key: string; count: number }[]>([]);
|
|
257
|
-
let scrollSpyEnabled = $state(persistedSettings.scrollSpyEnabled);
|
|
258
176
|
|
|
259
|
-
//
|
|
260
|
-
let prevPreset: ColumnPreset | null = columnPreset;
|
|
177
|
+
// ========== Effects ==========
|
|
261
178
|
|
|
262
|
-
//
|
|
263
|
-
|
|
264
|
-
if (!cellTable) return;
|
|
265
|
-
columnMeta.forEach(col => {
|
|
266
|
-
if (columns.includes(col.field)) {
|
|
267
|
-
cellTable.showColumn(col.field);
|
|
268
|
-
} else {
|
|
269
|
-
cellTable.hideColumn(col.field);
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
}
|
|
179
|
+
// Track preset changes to apply column visibility
|
|
180
|
+
let prevPreset: ColumnPreset | null = columnVis.columnPreset;
|
|
273
181
|
|
|
274
|
-
// Update visible columns when preset changes - load saved customizations for that preset
|
|
275
182
|
$effect(() => {
|
|
276
|
-
if (columnPreset !== prevPreset) {
|
|
277
|
-
prevPreset = columnPreset;
|
|
278
|
-
|
|
279
|
-
const newColumns = loadColumnsForPreset(columnPreset);
|
|
280
|
-
visibleColumns = newColumns;
|
|
281
|
-
// Apply to Tabulator
|
|
282
|
-
applyColumnVisibility(newColumns);
|
|
183
|
+
if (columnVis.columnPreset !== prevPreset) {
|
|
184
|
+
prevPreset = columnVis.columnPreset;
|
|
185
|
+
columnVis.applyToTable(cellTable);
|
|
283
186
|
}
|
|
284
187
|
});
|
|
285
188
|
|
|
@@ -291,7 +194,7 @@
|
|
|
291
194
|
redraw: () => cellTable?.redraw()
|
|
292
195
|
};
|
|
293
196
|
// Apply persisted column visibility after table is ready
|
|
294
|
-
setTimeout(() =>
|
|
197
|
+
setTimeout(() => columnVis.applyToTable(cellTable), 100);
|
|
295
198
|
// Apply persisted filter visibility after table is ready
|
|
296
199
|
if (!filtersVisible) {
|
|
297
200
|
setTimeout(() => cellTable?.toggleHeaderFilters(false), 100);
|
|
@@ -299,6 +202,8 @@
|
|
|
299
202
|
}
|
|
300
203
|
});
|
|
301
204
|
|
|
205
|
+
// ========== Event Handlers ==========
|
|
206
|
+
|
|
302
207
|
function handleSelectionChange(event: RowSelectionEvent) {
|
|
303
208
|
selectedCount = event.rows.length;
|
|
304
209
|
selectedRows = event.rows;
|
|
@@ -317,7 +222,9 @@
|
|
|
317
222
|
function handleDataChange(event: DataChangeEvent) {
|
|
318
223
|
filteredCount = event.filteredCount;
|
|
319
224
|
// Update scrollspy groups when data changes
|
|
320
|
-
|
|
225
|
+
if (scrollSpy.enabled && groupBy !== 'none') {
|
|
226
|
+
setTimeout(() => scrollSpy.updateGroups(cellTable), 50);
|
|
227
|
+
}
|
|
321
228
|
}
|
|
322
229
|
|
|
323
230
|
function handleRowContextMenu(event: RowContextMenuEvent) {
|
|
@@ -340,43 +247,28 @@
|
|
|
340
247
|
}
|
|
341
248
|
}
|
|
342
249
|
|
|
343
|
-
function updateScrollSpyGroups() {
|
|
344
|
-
if (scrollSpyEnabled && groupBy !== 'none') {
|
|
345
|
-
// Small delay to ensure table has updated
|
|
346
|
-
setTimeout(() => {
|
|
347
|
-
scrollSpyGroups = cellTable?.getGroups() ?? [];
|
|
348
|
-
}, 50);
|
|
349
|
-
} else {
|
|
350
|
-
scrollSpyGroups = [];
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
250
|
function handleScrollToGroup(key: string) {
|
|
355
|
-
|
|
251
|
+
scrollSpy.scrollToGroup(cellTable, key);
|
|
356
252
|
}
|
|
357
253
|
|
|
358
254
|
function handleToggleScrollSpy() {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
updateScrollSpyGroups();
|
|
363
|
-
} else {
|
|
364
|
-
scrollSpyGroups = [];
|
|
255
|
+
scrollSpy.toggle();
|
|
256
|
+
if (scrollSpy.enabled && groupBy !== 'none') {
|
|
257
|
+
setTimeout(() => scrollSpy.updateGroups(cellTable), 100);
|
|
365
258
|
}
|
|
366
259
|
}
|
|
367
260
|
|
|
368
261
|
function handleGroupChange(group: CellTableGroupField) {
|
|
369
262
|
groupBy = group;
|
|
370
|
-
|
|
263
|
+
persistence.saveString('groupBy', group);
|
|
371
264
|
// Update scrollspy groups after grouping changes
|
|
372
|
-
if (
|
|
373
|
-
setTimeout(() =>
|
|
265
|
+
if (scrollSpy.enabled) {
|
|
266
|
+
setTimeout(() => scrollSpy.updateGroups(cellTable), 100);
|
|
374
267
|
}
|
|
375
268
|
}
|
|
376
269
|
|
|
377
270
|
function handlePresetChange(preset: ColumnPreset) {
|
|
378
|
-
|
|
379
|
-
savePreset(preset);
|
|
271
|
+
columnVis.setPreset(preset);
|
|
380
272
|
}
|
|
381
273
|
|
|
382
274
|
function handleExportCSV() {
|
|
@@ -402,41 +294,21 @@
|
|
|
402
294
|
function handleToggleFilters() {
|
|
403
295
|
filtersVisible = !filtersVisible;
|
|
404
296
|
cellTable?.toggleHeaderFilters(filtersVisible);
|
|
405
|
-
|
|
297
|
+
persistence.save('filtersVisible', filtersVisible);
|
|
406
298
|
}
|
|
407
299
|
|
|
408
300
|
function handleColumnVisibilityChange(field: string, visible: boolean) {
|
|
301
|
+
columnVis.toggleColumn(field, visible);
|
|
409
302
|
if (visible) {
|
|
410
|
-
if (!visibleColumns.includes(field)) {
|
|
411
|
-
visibleColumns = [...visibleColumns, field];
|
|
412
|
-
}
|
|
413
303
|
cellTable?.showColumn(field);
|
|
414
304
|
} else {
|
|
415
|
-
visibleColumns = visibleColumns.filter(f => f !== field);
|
|
416
305
|
cellTable?.hideColumn(field);
|
|
417
306
|
}
|
|
418
|
-
saveColumnVisibility(visibleColumns);
|
|
419
307
|
}
|
|
420
308
|
|
|
421
309
|
function handleResetColumns() {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
// Show/hide columns to match preset
|
|
425
|
-
columnMeta.forEach(col => {
|
|
426
|
-
if (defaultFields.includes(col.field)) {
|
|
427
|
-
cellTable?.showColumn(col.field);
|
|
428
|
-
} else {
|
|
429
|
-
cellTable?.hideColumn(col.field);
|
|
430
|
-
}
|
|
431
|
-
});
|
|
432
|
-
// Clear persisted column visibility for this preset (use preset defaults)
|
|
433
|
-
if (persistSettings && typeof localStorage !== 'undefined') {
|
|
434
|
-
try {
|
|
435
|
-
localStorage.removeItem(getColumnsStorageKey(columnPreset));
|
|
436
|
-
} catch (e) {
|
|
437
|
-
console.warn('Failed to clear column visibility:', e);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
310
|
+
columnVis.resetToDefaults();
|
|
311
|
+
columnVis.applyToTable(cellTable);
|
|
440
312
|
}
|
|
441
313
|
|
|
442
314
|
function toggleSidebar() {
|
|
@@ -449,7 +321,8 @@
|
|
|
449
321
|
setTimeout(() => cellTable?.redraw(), 320);
|
|
450
322
|
}
|
|
451
323
|
|
|
452
|
-
//
|
|
324
|
+
// ========== Public API ==========
|
|
325
|
+
|
|
453
326
|
export function getSelectedRows(): CellData[] {
|
|
454
327
|
return cellTable?.getSelectedRows() ?? [];
|
|
455
328
|
}
|
|
@@ -497,6 +370,7 @@
|
|
|
497
370
|
class:btn-secondary={sidebarOpen}
|
|
498
371
|
onclick={toggleSidebar}
|
|
499
372
|
title={sidebarOpen ? 'Hide details' : 'Show details'}
|
|
373
|
+
aria-label={sidebarOpen ? 'Hide details' : 'Show details'}
|
|
500
374
|
>
|
|
501
375
|
<i class="bi" class:bi-layout-sidebar-reverse={!sidebarOpen} class:bi-x-lg={sidebarOpen}></i>
|
|
502
376
|
</button>
|
|
@@ -509,7 +383,7 @@
|
|
|
509
383
|
<CellTableToolbar
|
|
510
384
|
{groupBy}
|
|
511
385
|
{groupOptions}
|
|
512
|
-
{columnPreset}
|
|
386
|
+
columnPreset={columnVis.columnPreset}
|
|
513
387
|
totalCount={cells.length}
|
|
514
388
|
{filteredCount}
|
|
515
389
|
{selectedCount}
|
|
@@ -525,23 +399,23 @@
|
|
|
525
399
|
onexpandall={handleExpandAll}
|
|
526
400
|
{filtersVisible}
|
|
527
401
|
ontogglefilters={handleToggleFilters}
|
|
528
|
-
{columnMeta}
|
|
529
|
-
{visibleColumns}
|
|
402
|
+
columnMeta={columnVis.columnMeta}
|
|
403
|
+
visibleColumns={columnVis.visibleColumns}
|
|
530
404
|
oncolumnvisibilitychange={handleColumnVisibilityChange}
|
|
531
405
|
onresetcolumns={handleResetColumns}
|
|
532
|
-
{
|
|
406
|
+
scrollSpyEnabled={scrollSpy.enabled}
|
|
533
407
|
showScrollSpyToggle={showScrollSpy}
|
|
534
408
|
ontogglescrollspy={handleToggleScrollSpy}
|
|
535
409
|
/>
|
|
536
410
|
{/if}
|
|
537
411
|
|
|
538
412
|
<!-- ScrollSpy Navigation Bar -->
|
|
539
|
-
{#if
|
|
413
|
+
{#if scrollSpy.enabled && groupBy !== 'none' && scrollSpy.groups.length > 0}
|
|
540
414
|
<div class="scrollspy-bar d-flex align-items-center gap-2 px-3 py-2 bg-body-tertiary border-bottom overflow-auto">
|
|
541
415
|
<span class="text-muted small me-1">
|
|
542
416
|
<i class="bi bi-signpost-split"></i> Jump to:
|
|
543
417
|
</span>
|
|
544
|
-
{#each
|
|
418
|
+
{#each scrollSpy.groups as group (group.key)}
|
|
545
419
|
{@const bgColor = groupBy === 'tech'
|
|
546
420
|
? (techColors?.[group.key] ?? DEFAULT_TECH_COLORS[group.key] ?? '#6c757d')
|
|
547
421
|
: groupBy === 'fband'
|
|
@@ -571,7 +445,8 @@
|
|
|
571
445
|
bind:this={cellTable}
|
|
572
446
|
{cells}
|
|
573
447
|
{groupBy}
|
|
574
|
-
{columnPreset}
|
|
448
|
+
columnPreset={columnVis.columnPreset}
|
|
449
|
+
{customColumns}
|
|
575
450
|
{selectable}
|
|
576
451
|
{multiSelect}
|
|
577
452
|
height="100%"
|
|
@@ -604,6 +479,7 @@
|
|
|
604
479
|
class="btn btn-sm btn-outline-secondary"
|
|
605
480
|
onclick={closeSidebar}
|
|
606
481
|
title="Close"
|
|
482
|
+
aria-label="Close sidebar"
|
|
607
483
|
>
|
|
608
484
|
<i class="bi bi-x-lg"></i>
|
|
609
485
|
</button>
|
|
@@ -681,30 +557,6 @@
|
|
|
681
557
|
<dt class="col-5 text-muted">Comment</dt>
|
|
682
558
|
<dd class="col-7 fst-italic">{clickedCell.comment}</dd>
|
|
683
559
|
{/if}
|
|
684
|
-
|
|
685
|
-
<!-- Dynamic Other Properties -->
|
|
686
|
-
{#if clickedCell.other && Object.keys(clickedCell.other).length > 0}
|
|
687
|
-
<dt class="col-12 text-muted mt-2 mb-1 border-top pt-2">Other</dt>
|
|
688
|
-
|
|
689
|
-
{#each Object.entries(clickedCell.other) as [key, value]}
|
|
690
|
-
<dt class="col-5 text-muted text-capitalize">{key.replace(/_/g, ' ')}</dt>
|
|
691
|
-
<dd class="col-7">
|
|
692
|
-
{#if value === null || value === undefined}
|
|
693
|
-
<span class="text-muted fst-italic">—</span>
|
|
694
|
-
{:else if typeof value === 'boolean'}
|
|
695
|
-
<span class="badge" class:bg-success={value} class:bg-secondary={!value}>
|
|
696
|
-
{value ? 'Yes' : 'No'}
|
|
697
|
-
</span>
|
|
698
|
-
{:else if typeof value === 'number'}
|
|
699
|
-
<code>{value}</code>
|
|
700
|
-
{:else if typeof value === 'object'}
|
|
701
|
-
<code class="small text-break">{JSON.stringify(value)}</code>
|
|
702
|
-
{:else}
|
|
703
|
-
{String(value)}
|
|
704
|
-
{/if}
|
|
705
|
-
</dd>
|
|
706
|
-
{/each}
|
|
707
|
-
{/if}
|
|
708
560
|
</dl>
|
|
709
561
|
{:else}
|
|
710
562
|
<div class="text-center text-muted py-5">
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CellTablePanel V2 - Composable-based Cell Table Panel
|
|
3
|
+
*
|
|
4
|
+
* Uses composables for reusable logic:
|
|
5
|
+
* - usePersistence: localStorage read/write
|
|
6
|
+
* - useColumnVisibility: column preset and visibility management
|
|
7
|
+
* - useScrollSpy: group navigation
|
|
8
|
+
*/
|
|
1
9
|
import type { Snippet } from 'svelte';
|
|
10
|
+
import type { ColumnDefinition } from 'tabulator-tables';
|
|
11
|
+
import type { ColumnMetadataOptions } from './column-config';
|
|
2
12
|
import type { CellData, CellTableGroupField, ColumnPreset, RowSelectionEvent, RowClickEvent, RowDblClickEvent, TechColorMap, StatusColorMap, GroupOption } from './types';
|
|
3
13
|
interface Props {
|
|
4
14
|
/** Cell data array to display */
|
|
@@ -9,6 +19,10 @@ interface Props {
|
|
|
9
19
|
groupOptions?: GroupOption[];
|
|
10
20
|
/** Initial column preset */
|
|
11
21
|
columnPreset?: ColumnPreset;
|
|
22
|
+
/** Custom column definitions (overrides columnPreset when provided) */
|
|
23
|
+
customColumns?: ColumnDefinition[];
|
|
24
|
+
/** Column metadata filter options */
|
|
25
|
+
columnMetadataOptions?: ColumnMetadataOptions;
|
|
12
26
|
/** Enable row selection */
|
|
13
27
|
selectable?: boolean;
|
|
14
28
|
/** Enable multi-row selection */
|
|
@@ -35,7 +49,7 @@ interface Props {
|
|
|
35
49
|
showDetailsSidebar?: boolean;
|
|
36
50
|
/** Sidebar width in pixels */
|
|
37
51
|
sidebarWidth?: number;
|
|
38
|
-
/** Persist settings
|
|
52
|
+
/** Persist settings to localStorage */
|
|
39
53
|
persistSettings?: boolean;
|
|
40
54
|
/** Storage key prefix for persisted settings */
|
|
41
55
|
storageKey?: string;
|
|
@@ -79,6 +93,6 @@ declare const CellTablePanel: import("svelte").Component<Props, {
|
|
|
79
93
|
scrollToRow: (id: string) => void;
|
|
80
94
|
redraw: () => void;
|
|
81
95
|
openSidebar: () => void;
|
|
82
|
-
}, "groupBy" | "
|
|
96
|
+
}, "groupBy" | "tableRef">;
|
|
83
97
|
type CellTablePanel = ReturnType<typeof CellTablePanel>;
|
|
84
98
|
export default CellTablePanel;
|
|
@@ -61,35 +61,6 @@ export declare function heightFormatter(cell: CellComponent): string;
|
|
|
61
61
|
* - Gray: one or both values missing
|
|
62
62
|
*/
|
|
63
63
|
export declare function createCompareFormatter(atollField: string, nwtField: string): (cell: CellComponent) => string;
|
|
64
|
-
/**
|
|
65
|
-
* Create a history change formatter for showing current vs previous values
|
|
66
|
-
* Highlights changes in yellow/amber, unchanged values in muted style
|
|
67
|
-
*
|
|
68
|
-
* @param currentField - Field name for current value
|
|
69
|
-
* @param prevField - Field name for previous value
|
|
70
|
-
*/
|
|
71
|
-
export declare function createHistoryChangeFormatter(currentField: string, prevField: string): (cell: CellComponent) => string;
|
|
72
|
-
/**
|
|
73
|
-
* Format ISO date string to YYYY.MM.DD format for history display
|
|
74
|
-
*/
|
|
75
|
-
export declare function historyDateFormatter(cell: CellComponent): string;
|
|
76
|
-
/**
|
|
77
|
-
* Creates a sparkline SVG formatter for KPI time-series data
|
|
78
|
-
* Renders a mini line chart showing trend over time
|
|
79
|
-
*
|
|
80
|
-
* @param options Configuration for the sparkline
|
|
81
|
-
*/
|
|
82
|
-
export interface SparklineOptions {
|
|
83
|
-
width?: number;
|
|
84
|
-
height?: number;
|
|
85
|
-
lineColor?: string;
|
|
86
|
-
fillColor?: string;
|
|
87
|
-
showDots?: boolean;
|
|
88
|
-
showLastValue?: boolean;
|
|
89
|
-
unit?: string;
|
|
90
|
-
decimals?: number;
|
|
91
|
-
}
|
|
92
|
-
export declare function createSparklineFormatter(options?: SparklineOptions): (cell: CellComponent) => string;
|
|
93
64
|
/**
|
|
94
65
|
* Custom sorter for fband - extracts numeric portion and sorts numerically
|
|
95
66
|
* Examples: LTE700 → 700, GSM900 → 900, LTE1800 → 1800, 5G-3500 → 3500
|
|
@@ -129,10 +100,20 @@ export interface ColumnMeta {
|
|
|
129
100
|
title: string;
|
|
130
101
|
group: string;
|
|
131
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Options for filtering column metadata
|
|
105
|
+
*/
|
|
106
|
+
export interface ColumnMetadataOptions {
|
|
107
|
+
/** Include only these groups (if specified, only these groups are included) */
|
|
108
|
+
include?: string[];
|
|
109
|
+
/** Exclude these groups (applied after include filter) */
|
|
110
|
+
exclude?: string[];
|
|
111
|
+
}
|
|
132
112
|
/**
|
|
133
113
|
* Get column metadata for the column picker UI
|
|
114
|
+
* @param options Filter options for including/excluding column groups
|
|
134
115
|
*/
|
|
135
|
-
export declare function getColumnMetadata(): ColumnMeta[];
|
|
116
|
+
export declare function getColumnMetadata(options?: ColumnMetadataOptions): ColumnMeta[];
|
|
136
117
|
/**
|
|
137
118
|
* Get default visible columns for a preset
|
|
138
119
|
*/
|