@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,601 @@
1
+ <script lang="ts">
2
+ import { onMount, onDestroy } from 'svelte';
3
+ import { TabulatorFull as Tabulator } from 'tabulator-tables';
4
+ // Import Bootstrap 5 theme for proper styling
5
+ import 'tabulator-tables/dist/css/tabulator_bootstrap5.min.css';
6
+ import type { Options, RowComponent } from 'tabulator-tables';
7
+ import type { ColumnDefinition } from 'tabulator-tables';
8
+ import type {
9
+ CellTableProps,
10
+ CellData,
11
+ RowSelectionEvent,
12
+ RowClickEvent,
13
+ RowDblClickEvent,
14
+ RowContextMenuEvent,
15
+ DataChangeEvent
16
+ } from './types';
17
+ import {
18
+ getColumnsForPreset,
19
+ getGroupHeaderFormatter,
20
+ DEFAULT_TECH_COLORS,
21
+ DEFAULT_STATUS_COLORS,
22
+ cellDataSorter
23
+ } from './column-config';
24
+
25
+ // Type for Tabulator group component (not exported from tabulator-tables)
26
+ interface TabulatorGroup {
27
+ getKey(): string | number | boolean;
28
+ getRows(): RowComponent[];
29
+ scrollTo(): Promise<void>;
30
+ }
31
+
32
+ interface Props extends CellTableProps {
33
+ /** Custom column definitions (overrides columnPreset when provided) */
34
+ customColumns?: ColumnDefinition[];
35
+ /** Row selection change event */
36
+ onselectionchange?: (event: RowSelectionEvent) => void;
37
+ /** Row click event */
38
+ onrowclick?: (event: RowClickEvent) => void;
39
+ /** Row double-click event */
40
+ onrowdblclick?: (event: RowDblClickEvent) => void;
41
+ /** Row context menu (right-click) event */
42
+ onrowcontextmenu?: (event: RowContextMenuEvent) => void;
43
+ /** Data change event (filter, sort, etc.) */
44
+ ondatachange?: (event: DataChangeEvent) => void;
45
+ }
46
+
47
+ let {
48
+ cells = [],
49
+ groupBy = 'none',
50
+ columnPreset = 'default',
51
+ customColumns,
52
+ columnVisibility,
53
+ selectable = false,
54
+ multiSelect = true,
55
+ height = '100%',
56
+ virtualDom = true,
57
+ tabulatorOptions,
58
+ techColors = DEFAULT_TECH_COLORS,
59
+ statusColors = DEFAULT_STATUS_COLORS,
60
+ headerFilters = true,
61
+ resizableColumns = true,
62
+ movableColumns = true,
63
+ persistLayout = true,
64
+ storageKey = 'cell-table-layout',
65
+ onselectionchange,
66
+ onrowclick,
67
+ onrowdblclick,
68
+ onrowcontextmenu,
69
+ ondatachange
70
+ }: Props = $props();
71
+
72
+ let tableContainer: HTMLDivElement;
73
+ let table: Tabulator | null = null;
74
+ let isInitialized = $state(false);
75
+
76
+ // Reactive column configuration - uses customColumns if provided, otherwise preset
77
+ let columns = $derived.by(() => {
78
+ // Use custom columns if provided, otherwise get from preset
79
+ const baseColumns = customColumns ?? getColumnsForPreset(columnPreset, techColors, statusColors, headerFilters);
80
+
81
+ // Add row selection checkbox column if selectable
82
+ if (selectable) {
83
+ const selectColumn = {
84
+ title: '',
85
+ formatter: 'rowSelection',
86
+ titleFormatter: multiSelect ? 'rowSelection' : undefined,
87
+ hozAlign: 'center' as const,
88
+ headerSort: false,
89
+ width: 40,
90
+ frozen: true,
91
+ cssClass: 'cell-table-select-column',
92
+ };
93
+ return [selectColumn, ...baseColumns];
94
+ }
95
+
96
+ return baseColumns;
97
+ });
98
+
99
+ // Pre-sort data using our custom multi-level sorter
100
+ let sortedCells = $derived.by(() => {
101
+ return [...cells].sort(cellDataSorter);
102
+ });
103
+
104
+ // Build Tabulator options
105
+ function buildOptions(): Options {
106
+ const baseOptions: Options = {
107
+ data: sortedCells,
108
+ columns: columns,
109
+ layout: 'fitDataFill',
110
+ height: height,
111
+ placeholder: 'No cells to display',
112
+
113
+ // Virtual DOM for performance with large datasets
114
+ renderVertical: virtualDom ? 'virtual' : 'basic',
115
+
116
+ // Interactivity
117
+ resizableColumns: resizableColumns,
118
+ movableColumns: movableColumns,
119
+
120
+ // No initialSort - data is pre-sorted by cellDataSorter (tech → fband → sector)
121
+
122
+ // Row selection
123
+ selectable: selectable ? (multiSelect ? true : 1) : false,
124
+ selectableRangeMode: 'click',
125
+
126
+ // Persistence - save column widths, order, visibility and group settings
127
+ persistence: persistLayout ? {
128
+ columns: ['width', 'visible', 'order'],
129
+ group: true,
130
+ } : false,
131
+ persistenceMode: persistLayout ? 'local' : undefined,
132
+ persistenceID: persistLayout ? storageKey : undefined,
133
+
134
+ // Grouping
135
+ ...(groupBy !== 'none' ? {
136
+ groupBy: groupBy,
137
+ groupStartOpen: true,
138
+ groupHeader: getGroupHeaderFormatter(groupBy),
139
+ groupToggleElement: 'header',
140
+ } : {}),
141
+
142
+ // Pagination (optional, disabled by default for virtual scrolling)
143
+ // pagination: true,
144
+ // paginationSize: 50,
145
+
146
+ // Clipboard
147
+ clipboard: true,
148
+ clipboardCopyRowRange: 'selected',
149
+ };
150
+
151
+ // Merge with custom options
152
+ return { ...baseOptions, ...tabulatorOptions };
153
+ }
154
+
155
+ // Initialize table
156
+ function initTable() {
157
+ if (!tableContainer) return;
158
+
159
+ const options = buildOptions();
160
+ table = new Tabulator(tableContainer, options);
161
+
162
+ // Bind events
163
+ table.on('rowClick', (e, row) => {
164
+ if (onrowclick) {
165
+ onrowclick({
166
+ row: (row as RowComponent).getData() as CellData,
167
+ event: e as MouseEvent
168
+ });
169
+ }
170
+ });
171
+
172
+ table.on('rowDblClick', (e, row) => {
173
+ if (onrowdblclick) {
174
+ onrowdblclick({
175
+ row: (row as RowComponent).getData() as CellData,
176
+ event: e as MouseEvent
177
+ });
178
+ }
179
+ });
180
+
181
+ table.on('rowContext', (e, row) => {
182
+ if (onrowcontextmenu) {
183
+ (e as MouseEvent).preventDefault();
184
+ onrowcontextmenu({
185
+ row: (row as RowComponent).getData() as CellData,
186
+ event: e as MouseEvent
187
+ });
188
+ }
189
+ });
190
+
191
+ table.on('rowSelectionChanged', (data, rows) => {
192
+ if (onselectionchange) {
193
+ const cellData = data as CellData[];
194
+ onselectionchange({
195
+ rows: cellData,
196
+ ids: cellData.map(d => d.id)
197
+ });
198
+ }
199
+ });
200
+
201
+ table.on('dataFiltered', (filters, rows) => {
202
+ if (ondatachange) {
203
+ ondatachange({
204
+ type: 'filter',
205
+ rowCount: cells.length,
206
+ filteredCount: (rows as RowComponent[]).length
207
+ });
208
+ }
209
+ });
210
+
211
+ table.on('dataSorted', () => {
212
+ if (ondatachange) {
213
+ ondatachange({
214
+ type: 'sort',
215
+ rowCount: cells.length,
216
+ filteredCount: table?.getDataCount('active') ?? 0
217
+ });
218
+ }
219
+ });
220
+
221
+ // Mark as initialized after table is ready
222
+ table.on('tableBuilt', () => {
223
+ isInitialized = true;
224
+ // Fire initial data change event
225
+ if (ondatachange) {
226
+ ondatachange({
227
+ type: 'load',
228
+ rowCount: cells.length,
229
+ filteredCount: cells.length
230
+ });
231
+ }
232
+ });
233
+ }
234
+
235
+ // Track previous values to avoid unnecessary updates
236
+ let prevCellsRef: unknown[] | null = null;
237
+ let prevGroupBy: string | null = null;
238
+ // Initialize with current preset to prevent setColumns on first load (which would override persisted layout)
239
+ let prevColumnPreset: string | null = columnPreset;
240
+
241
+ // Update table data when cells change (reference comparison)
242
+ $effect(() => {
243
+ // Track the cells array reference to detect any change
244
+ const currentRef = sortedCells;
245
+
246
+ // Update if reference changed (new array assignment)
247
+ if (isInitialized && table && currentRef !== prevCellsRef) {
248
+ prevCellsRef = currentRef;
249
+ table.replaceData(sortedCells);
250
+ ondatachange?.({
251
+ type: 'load',
252
+ rowCount: sortedCells.length,
253
+ filteredCount: sortedCells.length
254
+ });
255
+ }
256
+ });
257
+
258
+ // Update grouping when groupBy changes
259
+ $effect(() => {
260
+ if (isInitialized && table && groupBy !== prevGroupBy) {
261
+ prevGroupBy = groupBy;
262
+ if (groupBy === 'none') {
263
+ table.setGroupBy(false);
264
+ } else {
265
+ table.setGroupBy(groupBy);
266
+ table.setGroupHeader(getGroupHeaderFormatter(groupBy));
267
+ }
268
+ }
269
+ });
270
+
271
+ // Update columns when preset changes
272
+ $effect(() => {
273
+ if (isInitialized && table && columnPreset !== prevColumnPreset) {
274
+ prevColumnPreset = columnPreset;
275
+ table.setColumns(columns);
276
+ }
277
+ });
278
+
279
+ onMount(() => {
280
+ initTable();
281
+ });
282
+
283
+ onDestroy(() => {
284
+ if (table) {
285
+ table.destroy();
286
+ table = null;
287
+ }
288
+ });
289
+
290
+ // Public API methods
291
+ export function getTable(): Tabulator | null {
292
+ return table;
293
+ }
294
+
295
+ export function getSelectedRows(): CellData[] {
296
+ return table?.getSelectedData() as CellData[] ?? [];
297
+ }
298
+
299
+ export function clearSelection(): void {
300
+ table?.deselectRow();
301
+ }
302
+
303
+ export function selectRow(id: string): void {
304
+ const row = table?.getRow(id);
305
+ if (row) row.select();
306
+ }
307
+
308
+ export function scrollToRow(id: string): void {
309
+ table?.scrollToRow(id, 'top', true);
310
+ }
311
+
312
+ export function downloadCSV(filename: string = 'cells.csv'): void {
313
+ table?.download('csv', filename);
314
+ }
315
+
316
+ export function downloadJSON(filename: string = 'cells.json'): void {
317
+ table?.download('json', filename);
318
+ }
319
+
320
+ export function setFilter(field: string, type: string, value: unknown): void {
321
+ table?.setFilter(field, type as any, value);
322
+ }
323
+
324
+ export function clearFilters(): void {
325
+ if (!table) return;
326
+ // Clear programmatic filters
327
+ table.clearFilter();
328
+ // Clear header filter inputs
329
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
330
+ (table as any).clearHeaderFilter();
331
+ }
332
+
333
+ export function redraw(): void {
334
+ table?.redraw(true);
335
+ }
336
+
337
+ export function collapseAll(): void {
338
+ if (!table) return;
339
+ // Use setGroupStartOpen to collapse all groups, then refresh data to apply
340
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
341
+ (table as any).setGroupStartOpen(false);
342
+ table.setData(table.getData());
343
+ }
344
+
345
+ export function expandAll(): void {
346
+ if (!table) return;
347
+ // Use setGroupStartOpen to expand all groups, then refresh data to apply
348
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
349
+ (table as any).setGroupStartOpen(true);
350
+ table.setData(table.getData());
351
+ }
352
+
353
+ export function toggleHeaderFilters(visible: boolean): void {
354
+ if (!table) return;
355
+ const headerFiltersElement = tableContainer.querySelector('.tabulator-header-filter');
356
+ if (headerFiltersElement) {
357
+ // Toggle all header filter rows
358
+ const filterRows = tableContainer.querySelectorAll('.tabulator-col .tabulator-header-filter');
359
+ filterRows.forEach(el => {
360
+ (el as HTMLElement).style.display = visible ? '' : 'none';
361
+ });
362
+ table.redraw();
363
+ }
364
+ }
365
+
366
+ export function showColumn(field: string): void {
367
+ table?.showColumn(field);
368
+ }
369
+
370
+ export function hideColumn(field: string): void {
371
+ table?.hideColumn(field);
372
+ }
373
+
374
+ export function getVisibleColumns(): string[] {
375
+ if (!table) return [];
376
+ const columns = table.getColumns();
377
+ return columns
378
+ .filter(col => col.isVisible())
379
+ .map(col => col.getField())
380
+ .filter((field): field is string => !!field);
381
+ }
382
+
383
+ /** Get all group keys (when grouping is active) */
384
+ export function getGroups(): { key: string; count: number }[] {
385
+ if (!table || groupBy === 'none') return [];
386
+ try {
387
+ const groups = table.getGroups() as TabulatorGroup[];
388
+ return groups.map(g => ({
389
+ key: String(g.getKey()),
390
+ count: g.getRows().length
391
+ }));
392
+ } catch {
393
+ return [];
394
+ }
395
+ }
396
+
397
+ /** Scroll to a specific group by key */
398
+ export function scrollToGroup(key: string): void {
399
+ if (!table || groupBy === 'none') return;
400
+ try {
401
+ const groups = table.getGroups() as TabulatorGroup[];
402
+ const group = groups.find(g => String(g.getKey()) === key);
403
+ if (group) {
404
+ group.scrollTo();
405
+ }
406
+ } catch (e) {
407
+ console.warn('Failed to scroll to group:', e);
408
+ }
409
+ }
410
+ </script>
411
+
412
+ <div class="cell-table-container">
413
+ <div bind:this={tableContainer} class="cell-table"></div>
414
+ </div>
415
+
416
+ <style>
417
+ .cell-table-container {
418
+ width: 100%;
419
+ height: 100%;
420
+ display: flex;
421
+ flex-direction: column;
422
+ }
423
+
424
+ .cell-table {
425
+ flex: 1;
426
+ min-height: 0;
427
+ }
428
+
429
+ /* Bootstrap-aligned Tabulator theme overrides */
430
+ :global(.cell-table-container .tabulator) {
431
+ font-family: var(--bs-body-font-family, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);
432
+ font-size: 0.875rem;
433
+ border: 1px solid var(--bs-border-color, #dee2e6);
434
+ border-radius: var(--bs-border-radius, 0.375rem);
435
+ background-color: var(--bs-body-bg, #fff);
436
+ }
437
+
438
+ /* Header styling */
439
+ :global(.cell-table-container .tabulator-header) {
440
+ background-color: var(--bs-tertiary-bg, #f8f9fa);
441
+ border-bottom: 2px solid var(--bs-border-color, #dee2e6);
442
+ }
443
+
444
+ :global(.cell-table-container .tabulator-col) {
445
+ background-color: var(--bs-tertiary-bg, #f8f9fa);
446
+ border-right: 1px solid var(--bs-border-color, #dee2e6);
447
+ }
448
+
449
+ :global(.cell-table-container .tabulator-col-title) {
450
+ font-weight: 600;
451
+ color: var(--bs-body-color, #212529);
452
+ padding: 0.5rem 0.75rem;
453
+ }
454
+
455
+ :global(.cell-table-container .tabulator-col-sorter) {
456
+ color: var(--bs-secondary-color, #6c757d);
457
+ }
458
+
459
+ /* Header filter inputs */
460
+ :global(.cell-table-container .tabulator-header-filter input) {
461
+ font-size: 0.75rem;
462
+ padding: 0.25rem 0.5rem;
463
+ border: 1px solid var(--bs-border-color, #dee2e6);
464
+ border-radius: var(--bs-border-radius-sm, 0.25rem);
465
+ background-color: var(--bs-body-bg, #fff);
466
+ color: var(--bs-body-color, #212529);
467
+ }
468
+
469
+ :global(.cell-table-container .tabulator-header-filter input:focus) {
470
+ border-color: var(--bs-primary, #0d6efd);
471
+ outline: 0;
472
+ box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
473
+ }
474
+
475
+ /* Row styling */
476
+ :global(.cell-table-container .tabulator-row) {
477
+ border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.1));
478
+ }
479
+
480
+ :global(.cell-table-container .tabulator-row:hover) {
481
+ background-color: var(--bs-tertiary-bg, #f8f9fa);
482
+ }
483
+
484
+ :global(.cell-table-container .tabulator-row.tabulator-row-even) {
485
+ background-color: var(--bs-body-bg, #fff);
486
+ }
487
+
488
+ :global(.cell-table-container .tabulator-row.tabulator-row-odd) {
489
+ background-color: rgba(var(--bs-tertiary-bg-rgb, 248, 249, 250), 0.5);
490
+ }
491
+
492
+ :global(.cell-table-container .tabulator-row.tabulator-selected) {
493
+ background-color: rgba(var(--bs-primary-rgb, 13, 110, 253), 0.1);
494
+ }
495
+
496
+ :global(.cell-table-container .tabulator-row.tabulator-selected:hover) {
497
+ background-color: rgba(var(--bs-primary-rgb, 13, 110, 253), 0.15);
498
+ }
499
+
500
+ /* Cell styling */
501
+ :global(.cell-table-container .tabulator-cell) {
502
+ padding: 0.5rem 0.75rem;
503
+ border-right: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.05));
504
+ color: var(--bs-body-color, #212529);
505
+ }
506
+
507
+ :global(.cell-table-container .tabulator-cell.tabulator-frozen) {
508
+ background-color: var(--bs-tertiary-bg, #f8f9fa);
509
+ border-right: 2px solid var(--bs-border-color, #dee2e6);
510
+ }
511
+
512
+ /* Group header styling */
513
+ :global(.cell-table-container .tabulator-row.tabulator-group) {
514
+ background-color: var(--bs-secondary-bg, #e9ecef);
515
+ border-bottom: 1px solid var(--bs-border-color, #dee2e6);
516
+ font-weight: 500;
517
+ min-height: 36px;
518
+ }
519
+
520
+ :global(.cell-table-container .tabulator-row.tabulator-group:hover) {
521
+ background-color: var(--bs-secondary-bg, #e9ecef);
522
+ cursor: pointer;
523
+ }
524
+
525
+ :global(.cell-table-container .tabulator-row.tabulator-group span) {
526
+ color: var(--bs-body-color, #212529);
527
+ }
528
+
529
+ /* Group toggle arrow */
530
+ :global(.cell-table-container .tabulator-group-toggle) {
531
+ margin-right: 0.5rem;
532
+ }
533
+
534
+ /* Scrollbar styling */
535
+ :global(.cell-table-container .tabulator-tableholder::-webkit-scrollbar) {
536
+ width: 8px;
537
+ height: 8px;
538
+ }
539
+
540
+ :global(.cell-table-container .tabulator-tableholder::-webkit-scrollbar-track) {
541
+ background: var(--bs-tertiary-bg, #f8f9fa);
542
+ }
543
+
544
+ :global(.cell-table-container .tabulator-tableholder::-webkit-scrollbar-thumb) {
545
+ background: var(--bs-secondary-color, #6c757d);
546
+ border-radius: 4px;
547
+ }
548
+
549
+ :global(.cell-table-container .tabulator-tableholder::-webkit-scrollbar-thumb:hover) {
550
+ background: var(--bs-body-color, #212529);
551
+ }
552
+
553
+ /* Placeholder */
554
+ :global(.cell-table-container .tabulator-placeholder) {
555
+ color: var(--bs-secondary-color, #6c757d);
556
+ font-style: italic;
557
+ }
558
+
559
+ /* Resize handle */
560
+ :global(.cell-table-container .tabulator-col-resize-handle) {
561
+ width: 6px;
562
+ right: 0;
563
+ }
564
+
565
+ :global(.cell-table-container .tabulator-col-resize-handle:hover) {
566
+ background-color: var(--bs-primary, #0d6efd);
567
+ }
568
+
569
+ /* Footer/pagination (if enabled) */
570
+ :global(.cell-table-container .tabulator-footer) {
571
+ background-color: var(--bs-tertiary-bg, #f8f9fa);
572
+ border-top: 1px solid var(--bs-border-color, #dee2e6);
573
+ padding: 0.5rem;
574
+ }
575
+
576
+ :global(.cell-table-container .tabulator-page) {
577
+ padding: 0.25rem 0.5rem;
578
+ margin: 0 0.125rem;
579
+ border: 1px solid var(--bs-border-color, #dee2e6);
580
+ border-radius: var(--bs-border-radius-sm, 0.25rem);
581
+ background-color: var(--bs-body-bg, #fff);
582
+ color: var(--bs-body-color, #212529);
583
+ }
584
+
585
+ :global(.cell-table-container .tabulator-page:hover) {
586
+ background-color: var(--bs-tertiary-bg, #f8f9fa);
587
+ }
588
+
589
+ :global(.cell-table-container .tabulator-page.active) {
590
+ background-color: var(--bs-primary, #0d6efd);
591
+ border-color: var(--bs-primary, #0d6efd);
592
+ color: white;
593
+ }
594
+
595
+ /* Badge styling in cells */
596
+ :global(.cell-table-container .badge) {
597
+ font-weight: 500;
598
+ padding: 0.25em 0.5em;
599
+ border-radius: var(--bs-border-radius-sm, 0.25rem);
600
+ }
601
+ </style>
@@ -0,0 +1,43 @@
1
+ import { TabulatorFull as Tabulator } from 'tabulator-tables';
2
+ import 'tabulator-tables/dist/css/tabulator_bootstrap5.min.css';
3
+ import type { ColumnDefinition } from 'tabulator-tables';
4
+ import type { CellTableProps, CellData, RowSelectionEvent, RowClickEvent, RowDblClickEvent, RowContextMenuEvent, DataChangeEvent } from './types';
5
+ interface Props extends CellTableProps {
6
+ /** Custom column definitions (overrides columnPreset when provided) */
7
+ customColumns?: ColumnDefinition[];
8
+ /** Row selection change event */
9
+ onselectionchange?: (event: RowSelectionEvent) => void;
10
+ /** Row click event */
11
+ onrowclick?: (event: RowClickEvent) => void;
12
+ /** Row double-click event */
13
+ onrowdblclick?: (event: RowDblClickEvent) => void;
14
+ /** Row context menu (right-click) event */
15
+ onrowcontextmenu?: (event: RowContextMenuEvent) => void;
16
+ /** Data change event (filter, sort, etc.) */
17
+ ondatachange?: (event: DataChangeEvent) => void;
18
+ }
19
+ declare const CellTable: import("svelte").Component<Props, {
20
+ getTable: () => Tabulator | null;
21
+ getSelectedRows: () => CellData[];
22
+ clearSelection: () => void;
23
+ selectRow: (id: string) => void;
24
+ scrollToRow: (id: string) => void;
25
+ downloadCSV: (filename?: string) => void;
26
+ downloadJSON: (filename?: string) => void;
27
+ setFilter: (field: string, type: string, value: unknown) => void;
28
+ clearFilters: () => void;
29
+ redraw: () => void;
30
+ collapseAll: () => void;
31
+ expandAll: () => void;
32
+ toggleHeaderFilters: (visible: boolean) => void;
33
+ showColumn: (field: string) => void;
34
+ hideColumn: (field: string) => void;
35
+ getVisibleColumns: () => string[];
36
+ getGroups: () => {
37
+ key: string;
38
+ count: number;
39
+ }[];
40
+ scrollToGroup: (key: string) => void;
41
+ }, "">;
42
+ type CellTable = ReturnType<typeof CellTable>;
43
+ export default CellTable;