@smartnet360/svelte-components 0.0.125 → 0.0.127

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 (48) hide show
  1. package/dist/core/Auth/auth.svelte.js +47 -2
  2. package/dist/map-v3/demo/DemoMap.svelte +36 -0
  3. package/dist/map-v3/demo/demo-custom-cells.d.ts +21 -0
  4. package/dist/map-v3/demo/demo-custom-cells.js +48 -0
  5. package/dist/map-v3/features/cells/custom/components/CustomCellFilterControl.svelte +220 -0
  6. package/dist/map-v3/features/cells/custom/components/CustomCellFilterControl.svelte.d.ts +15 -0
  7. package/dist/map-v3/features/cells/custom/components/CustomCellSetManager.svelte +306 -0
  8. package/dist/map-v3/features/cells/custom/components/CustomCellSetManager.svelte.d.ts +10 -0
  9. package/dist/map-v3/features/cells/custom/components/index.d.ts +5 -0
  10. package/dist/map-v3/features/cells/custom/components/index.js +5 -0
  11. package/dist/map-v3/features/cells/custom/index.d.ts +32 -0
  12. package/dist/map-v3/features/cells/custom/index.js +35 -0
  13. package/dist/map-v3/features/cells/custom/layers/CustomCellsLayer.svelte +262 -0
  14. package/dist/map-v3/features/cells/custom/layers/CustomCellsLayer.svelte.d.ts +10 -0
  15. package/dist/map-v3/features/cells/custom/layers/index.d.ts +4 -0
  16. package/dist/map-v3/features/cells/custom/layers/index.js +4 -0
  17. package/dist/map-v3/features/cells/custom/logic/csv-parser.d.ts +20 -0
  18. package/dist/map-v3/features/cells/custom/logic/csv-parser.js +164 -0
  19. package/dist/map-v3/features/cells/custom/logic/index.d.ts +5 -0
  20. package/dist/map-v3/features/cells/custom/logic/index.js +5 -0
  21. package/dist/map-v3/features/cells/custom/logic/tree-adapter.d.ts +24 -0
  22. package/dist/map-v3/features/cells/custom/logic/tree-adapter.js +67 -0
  23. package/dist/map-v3/features/cells/custom/stores/custom-cell-sets.svelte.d.ts +78 -0
  24. package/dist/map-v3/features/cells/custom/stores/custom-cell-sets.svelte.js +242 -0
  25. package/dist/map-v3/features/cells/custom/stores/index.d.ts +4 -0
  26. package/dist/map-v3/features/cells/custom/stores/index.js +4 -0
  27. package/dist/map-v3/features/cells/custom/types.d.ts +83 -0
  28. package/dist/map-v3/features/cells/custom/types.js +23 -0
  29. package/dist/map-v3/features/sites/custom/components/CustomSiteFilterControl.svelte +203 -0
  30. package/dist/map-v3/features/sites/custom/components/CustomSiteFilterControl.svelte.d.ts +15 -0
  31. package/dist/map-v3/features/sites/custom/components/CustomSiteSetManager.svelte +261 -0
  32. package/dist/map-v3/features/sites/custom/components/CustomSiteSetManager.svelte.d.ts +10 -0
  33. package/dist/map-v3/features/sites/custom/index.d.ts +13 -0
  34. package/dist/map-v3/features/sites/custom/index.js +16 -0
  35. package/dist/map-v3/features/sites/custom/layers/CustomSitesLayer.svelte +201 -0
  36. package/dist/map-v3/features/sites/custom/layers/CustomSitesLayer.svelte.d.ts +8 -0
  37. package/dist/map-v3/features/sites/custom/logic/csv-parser.d.ts +12 -0
  38. package/dist/map-v3/features/sites/custom/logic/csv-parser.js +182 -0
  39. package/dist/map-v3/features/sites/custom/logic/tree-adapter.d.ts +16 -0
  40. package/dist/map-v3/features/sites/custom/logic/tree-adapter.js +59 -0
  41. package/dist/map-v3/features/sites/custom/stores/custom-site-sets.svelte.d.ts +78 -0
  42. package/dist/map-v3/features/sites/custom/stores/custom-site-sets.svelte.js +248 -0
  43. package/dist/map-v3/features/sites/custom/types.d.ts +74 -0
  44. package/dist/map-v3/features/sites/custom/types.js +8 -0
  45. package/dist/map-v3/index.d.ts +2 -0
  46. package/dist/map-v3/index.js +4 -0
  47. package/dist/map-v3/shared/controls/MapControl.svelte +27 -3
  48. package/package.json +1 -1
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Custom Cells - CSV Parser
3
+ *
4
+ * Parses CSV files for custom cell sets.
5
+ * Required column: txId
6
+ * Optional columns: customGroup, sizeFactor, + any extras for tooltips
7
+ */
8
+ import type { CustomCellImportResult } from '../types';
9
+ import type { Cell } from '../../../../../shared/demo';
10
+ /**
11
+ * Parse a CSV string into custom cells
12
+ * @param csvContent Raw CSV content
13
+ * @param cellLookup Map of txId -> Cell for resolving cell data
14
+ * @returns Import result with cells, unmatched IDs, groups, and extra columns
15
+ */
16
+ export declare function parseCustomCellsCsv(csvContent: string, cellLookup: Map<string, Cell>): CustomCellImportResult;
17
+ /**
18
+ * Build a cell lookup map from an array of cells
19
+ */
20
+ export declare function buildCellLookup(cells: Cell[]): Map<string, Cell>;
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Custom Cells - CSV Parser
3
+ *
4
+ * Parses CSV files for custom cell sets.
5
+ * Required column: txId
6
+ * Optional columns: customGroup, sizeFactor, + any extras for tooltips
7
+ */
8
+ /**
9
+ * Known/reserved column names
10
+ */
11
+ const RESERVED_COLUMNS = ['txId', 'txid', 'customGroup', 'customgroup', 'sizeFactor', 'sizefactor'];
12
+ /**
13
+ * Normalize column name for matching
14
+ */
15
+ function normalizeColumnName(name) {
16
+ return name.trim().toLowerCase();
17
+ }
18
+ /**
19
+ * Parse a CSV string into custom cells
20
+ * @param csvContent Raw CSV content
21
+ * @param cellLookup Map of txId -> Cell for resolving cell data
22
+ * @returns Import result with cells, unmatched IDs, groups, and extra columns
23
+ */
24
+ export function parseCustomCellsCsv(csvContent, cellLookup) {
25
+ const lines = csvContent.trim().split('\n');
26
+ if (lines.length < 2) {
27
+ return {
28
+ cells: [],
29
+ unmatchedTxIds: [],
30
+ groups: [],
31
+ extraColumns: [],
32
+ totalRows: 0
33
+ };
34
+ }
35
+ // Parse header
36
+ const headerLine = lines[0];
37
+ const headers = parseCSVLine(headerLine);
38
+ const normalizedHeaders = headers.map(normalizeColumnName);
39
+ // Find required txId column
40
+ const txIdIndex = normalizedHeaders.findIndex(h => h === 'txid');
41
+ if (txIdIndex === -1) {
42
+ throw new Error('CSV must contain a "txId" column');
43
+ }
44
+ // Find optional columns
45
+ const groupIndex = normalizedHeaders.findIndex(h => h === 'customgroup');
46
+ const sizeFactorIndex = normalizedHeaders.findIndex(h => h === 'sizefactor');
47
+ // Find extra columns (not reserved)
48
+ const extraColumns = [];
49
+ const extraIndices = [];
50
+ headers.forEach((header, idx) => {
51
+ const normalized = normalizeColumnName(header);
52
+ if (!RESERVED_COLUMNS.includes(normalized)) {
53
+ extraColumns.push(header.trim());
54
+ extraIndices.push(idx);
55
+ }
56
+ });
57
+ // Parse data rows
58
+ const cells = [];
59
+ const unmatchedTxIds = [];
60
+ const groupsSet = new Set();
61
+ for (let i = 1; i < lines.length; i++) {
62
+ const line = lines[i].trim();
63
+ if (!line)
64
+ continue;
65
+ const values = parseCSVLine(line);
66
+ const txId = values[txIdIndex]?.trim();
67
+ if (!txId)
68
+ continue;
69
+ // Get custom group (default to 'default')
70
+ const customGroup = groupIndex !== -1
71
+ ? (values[groupIndex]?.trim() || 'default')
72
+ : 'default';
73
+ groupsSet.add(customGroup);
74
+ // Get size factor (default to 1)
75
+ let sizeFactor = 1;
76
+ if (sizeFactorIndex !== -1) {
77
+ const parsed = parseFloat(values[sizeFactorIndex]);
78
+ if (!isNaN(parsed) && parsed > 0) {
79
+ sizeFactor = parsed;
80
+ }
81
+ }
82
+ // Collect extra fields
83
+ const extraFields = {};
84
+ extraIndices.forEach((idx, i) => {
85
+ const value = values[idx]?.trim() || '';
86
+ // Try to parse as number
87
+ const numValue = parseFloat(value);
88
+ extraFields[extraColumns[i]] = isNaN(numValue) ? value : numValue;
89
+ });
90
+ // Resolve cell from lookup
91
+ const resolvedCell = cellLookup.get(txId);
92
+ if (resolvedCell) {
93
+ cells.push({
94
+ txId,
95
+ customGroup,
96
+ sizeFactor,
97
+ extraFields,
98
+ resolvedCell
99
+ });
100
+ }
101
+ else {
102
+ unmatchedTxIds.push(txId);
103
+ }
104
+ }
105
+ return {
106
+ cells,
107
+ unmatchedTxIds,
108
+ groups: Array.from(groupsSet).sort(),
109
+ extraColumns,
110
+ totalRows: lines.length - 1
111
+ };
112
+ }
113
+ /**
114
+ * Parse a single CSV line, handling quoted fields
115
+ */
116
+ function parseCSVLine(line) {
117
+ const result = [];
118
+ let current = '';
119
+ let inQuotes = false;
120
+ for (let i = 0; i < line.length; i++) {
121
+ const char = line[i];
122
+ const nextChar = line[i + 1];
123
+ if (inQuotes) {
124
+ if (char === '"' && nextChar === '"') {
125
+ // Escaped quote
126
+ current += '"';
127
+ i++;
128
+ }
129
+ else if (char === '"') {
130
+ // End of quoted field
131
+ inQuotes = false;
132
+ }
133
+ else {
134
+ current += char;
135
+ }
136
+ }
137
+ else {
138
+ if (char === '"') {
139
+ inQuotes = true;
140
+ }
141
+ else if (char === ',') {
142
+ result.push(current);
143
+ current = '';
144
+ }
145
+ else {
146
+ current += char;
147
+ }
148
+ }
149
+ }
150
+ result.push(current);
151
+ return result;
152
+ }
153
+ /**
154
+ * Build a cell lookup map from an array of cells
155
+ */
156
+ export function buildCellLookup(cells) {
157
+ const lookup = new Map();
158
+ for (const cell of cells) {
159
+ if (cell.txId) {
160
+ lookup.set(cell.txId, cell);
161
+ }
162
+ }
163
+ return lookup;
164
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Custom Cells Logic - Barrel Export
3
+ */
4
+ export { parseCustomCellsCsv, buildCellLookup } from './csv-parser';
5
+ export { buildCustomCellTree, getGroupCounts } from './tree-adapter';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Custom Cells Logic - Barrel Export
3
+ */
4
+ export { parseCustomCellsCsv, buildCellLookup } from './csv-parser';
5
+ export { buildCustomCellTree, getGroupCounts } from './tree-adapter';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Custom Cells - Tree Adapter
3
+ *
4
+ * Builds tree structure for TreeView component, grouped by customGroup
5
+ */
6
+ import type { TreeNode } from '../../../../../core/TreeView/tree.model';
7
+ import type { CustomCellSet } from '../types';
8
+ /**
9
+ * Metadata for tree nodes
10
+ */
11
+ export interface CustomCellTreeMetadata {
12
+ color: string;
13
+ count: number;
14
+ groupId: string;
15
+ setId: string;
16
+ }
17
+ /**
18
+ * Build tree nodes for a custom cell set, grouped by customGroup
19
+ */
20
+ export declare function buildCustomCellTree(set: CustomCellSet): TreeNode<CustomCellTreeMetadata>[];
21
+ /**
22
+ * Get cell counts per group
23
+ */
24
+ export declare function getGroupCounts(set: CustomCellSet): Map<string, number>;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Custom Cells - Tree Adapter
3
+ *
4
+ * Builds tree structure for TreeView component, grouped by customGroup
5
+ */
6
+ /**
7
+ * Build tree nodes for a custom cell set, grouped by customGroup
8
+ */
9
+ export function buildCustomCellTree(set) {
10
+ // Group cells by customGroup
11
+ const groupMap = new Map();
12
+ for (const cell of set.cells) {
13
+ if (!cell.resolvedCell)
14
+ continue; // Skip unresolved cells
15
+ if (!groupMap.has(cell.customGroup)) {
16
+ groupMap.set(cell.customGroup, []);
17
+ }
18
+ groupMap.get(cell.customGroup).push(cell);
19
+ }
20
+ // Build leaf nodes for each group
21
+ const groupNodes = [];
22
+ for (const [group, cells] of groupMap) {
23
+ const color = set.groupColors[group] || set.defaultColor;
24
+ const isVisible = set.visibleGroups.has(group);
25
+ groupNodes.push({
26
+ id: `${set.id}__${group}`,
27
+ label: `${group} (${cells.length})`,
28
+ metadata: {
29
+ color,
30
+ count: cells.length,
31
+ groupId: group,
32
+ setId: set.id
33
+ },
34
+ defaultChecked: isVisible
35
+ });
36
+ }
37
+ // Sort groups alphabetically
38
+ groupNodes.sort((a, b) => a.label.localeCompare(b.label));
39
+ // Wrap in root node
40
+ const rootNode = {
41
+ id: `root-${set.id}`,
42
+ label: `${set.name} (${set.cells.length})`,
43
+ children: groupNodes,
44
+ defaultExpanded: true,
45
+ defaultChecked: set.visible,
46
+ metadata: {
47
+ color: set.defaultColor,
48
+ count: set.cells.length,
49
+ groupId: '__root__',
50
+ setId: set.id
51
+ }
52
+ };
53
+ return [rootNode];
54
+ }
55
+ /**
56
+ * Get cell counts per group
57
+ */
58
+ export function getGroupCounts(set) {
59
+ const counts = new Map();
60
+ for (const cell of set.cells) {
61
+ if (!cell.resolvedCell)
62
+ continue;
63
+ const current = counts.get(cell.customGroup) || 0;
64
+ counts.set(cell.customGroup, current + 1);
65
+ }
66
+ return counts;
67
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Custom Cell Sets Store
3
+ *
4
+ * Manages multiple custom cell sets, each loaded from a CSV file.
5
+ * Resolves cell data from the parent CellDataStore.
6
+ */
7
+ import type { CellDataStore } from '../../stores/cell.data.svelte';
8
+ import type { CustomCellSet, CustomCellImportResult } from '../types';
9
+ /**
10
+ * Store for managing custom cell sets
11
+ */
12
+ export declare class CustomCellSetsStore {
13
+ /** All custom cell sets */
14
+ sets: CustomCellSet[];
15
+ /** Version counter for reactivity */
16
+ version: number;
17
+ /** Reference to parent cell data store */
18
+ private cellDataStore;
19
+ /** Storage key for persistence */
20
+ private storageKey;
21
+ constructor(cellDataStore: CellDataStore, namespace?: string);
22
+ /**
23
+ * Import a CSV file and create a new custom cell set
24
+ */
25
+ importFromCsv(csvContent: string, fileName: string): CustomCellImportResult;
26
+ /**
27
+ * Create a new set from import result
28
+ */
29
+ createSet(name: string, importResult: CustomCellImportResult): CustomCellSet;
30
+ /**
31
+ * Remove a set by ID
32
+ */
33
+ removeSet(setId: string): boolean;
34
+ /**
35
+ * Get a set by ID
36
+ */
37
+ getSet(setId: string): CustomCellSet | undefined;
38
+ /**
39
+ * Toggle set visibility
40
+ */
41
+ toggleSetVisibility(setId: string): void;
42
+ /**
43
+ * Toggle group visibility within a set
44
+ */
45
+ toggleGroupVisibility(setId: string, group: string): void;
46
+ /**
47
+ * Set group color
48
+ */
49
+ setGroupColor(setId: string, group: string, color: string): void;
50
+ /**
51
+ * Update set display settings
52
+ */
53
+ updateSetSettings(setId: string, settings: Partial<Pick<CustomCellSet, 'baseSize' | 'opacity' | 'defaultColor'>>): void;
54
+ /**
55
+ * Rename a set
56
+ */
57
+ renameSet(setId: string, newName: string): void;
58
+ /**
59
+ * Get visible cells for a set (filtered by visible groups)
60
+ */
61
+ getVisibleCells(setId: string): import("..").CustomCell[];
62
+ /**
63
+ * Re-resolve cells after main cell data changes
64
+ */
65
+ refreshResolutions(): void;
66
+ /**
67
+ * Load from localStorage
68
+ */
69
+ private load;
70
+ /**
71
+ * Save to localStorage
72
+ */
73
+ private save;
74
+ }
75
+ /**
76
+ * Factory function to create a custom cell sets store
77
+ */
78
+ export declare function createCustomCellSetsStore(cellDataStore: CellDataStore, namespace?: string): CustomCellSetsStore;
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Custom Cell Sets Store
3
+ *
4
+ * Manages multiple custom cell sets, each loaded from a CSV file.
5
+ * Resolves cell data from the parent CellDataStore.
6
+ */
7
+ import { browser } from '$app/environment';
8
+ import { CUSTOM_CELL_PALETTE } from '../types';
9
+ import { parseCustomCellsCsv, buildCellLookup } from '../logic/csv-parser';
10
+ /**
11
+ * Generate a unique ID for a new set
12
+ */
13
+ function generateSetId() {
14
+ return `set-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
15
+ }
16
+ /**
17
+ * Store for managing custom cell sets
18
+ */
19
+ export class CustomCellSetsStore {
20
+ /** All custom cell sets */
21
+ sets = $state([]);
22
+ /** Version counter for reactivity */
23
+ version = $state(0);
24
+ /** Reference to parent cell data store */
25
+ cellDataStore;
26
+ /** Storage key for persistence */
27
+ storageKey;
28
+ constructor(cellDataStore, namespace = 'default') {
29
+ this.cellDataStore = cellDataStore;
30
+ this.storageKey = `${namespace}:custom-cell-sets`;
31
+ if (browser) {
32
+ this.load();
33
+ // Auto-save on changes
34
+ $effect(() => {
35
+ // Read version to trigger on changes
36
+ const _v = this.version;
37
+ this.save();
38
+ });
39
+ // Re-resolve cells when main cell data changes
40
+ $effect(() => {
41
+ const cellCount = this.cellDataStore.rawCells.length;
42
+ if (cellCount > 0 && this.sets.length > 0) {
43
+ // Check if any cells need resolution
44
+ const needsResolution = this.sets.some(set => set.cells.some(c => !c.resolvedCell));
45
+ if (needsResolution) {
46
+ console.log('[CustomCellSetsStore] Re-resolving cells after main data loaded');
47
+ this.refreshResolutions();
48
+ }
49
+ }
50
+ });
51
+ }
52
+ }
53
+ /**
54
+ * Import a CSV file and create a new custom cell set
55
+ */
56
+ importFromCsv(csvContent, fileName) {
57
+ // Build lookup from all cells (unfiltered)
58
+ const cellLookup = buildCellLookup(this.cellDataStore.rawCells);
59
+ // Parse CSV
60
+ const result = parseCustomCellsCsv(csvContent, cellLookup);
61
+ return result;
62
+ }
63
+ /**
64
+ * Create a new set from import result
65
+ */
66
+ createSet(name, importResult) {
67
+ const id = generateSetId();
68
+ // Assign default colors to groups
69
+ const groupColors = {};
70
+ importResult.groups.forEach((group, idx) => {
71
+ groupColors[group] = CUSTOM_CELL_PALETTE[idx % CUSTOM_CELL_PALETTE.length];
72
+ });
73
+ const newSet = {
74
+ id,
75
+ name,
76
+ cells: importResult.cells,
77
+ unmatchedTxIds: importResult.unmatchedTxIds,
78
+ groups: importResult.groups,
79
+ extraColumns: importResult.extraColumns,
80
+ baseSize: 50,
81
+ opacity: 0.7,
82
+ defaultColor: CUSTOM_CELL_PALETTE[0],
83
+ groupColors,
84
+ visible: true,
85
+ visibleGroups: new Set(importResult.groups)
86
+ };
87
+ this.sets.push(newSet);
88
+ this.version++;
89
+ return newSet;
90
+ }
91
+ /**
92
+ * Remove a set by ID
93
+ */
94
+ removeSet(setId) {
95
+ const index = this.sets.findIndex(s => s.id === setId);
96
+ if (index !== -1) {
97
+ // Use filter to create a new array for proper reactivity
98
+ this.sets = this.sets.filter(s => s.id !== setId);
99
+ this.version++;
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ /**
105
+ * Get a set by ID
106
+ */
107
+ getSet(setId) {
108
+ return this.sets.find(s => s.id === setId);
109
+ }
110
+ /**
111
+ * Toggle set visibility
112
+ */
113
+ toggleSetVisibility(setId) {
114
+ const set = this.getSet(setId);
115
+ if (set) {
116
+ set.visible = !set.visible;
117
+ this.version++;
118
+ }
119
+ }
120
+ /**
121
+ * Toggle group visibility within a set
122
+ */
123
+ toggleGroupVisibility(setId, group) {
124
+ const set = this.getSet(setId);
125
+ if (set) {
126
+ if (set.visibleGroups.has(group)) {
127
+ set.visibleGroups.delete(group);
128
+ }
129
+ else {
130
+ set.visibleGroups.add(group);
131
+ }
132
+ this.version++;
133
+ }
134
+ }
135
+ /**
136
+ * Set group color
137
+ */
138
+ setGroupColor(setId, group, color) {
139
+ const set = this.getSet(setId);
140
+ if (set) {
141
+ set.groupColors[group] = color;
142
+ this.version++;
143
+ }
144
+ }
145
+ /**
146
+ * Update set display settings
147
+ */
148
+ updateSetSettings(setId, settings) {
149
+ const set = this.getSet(setId);
150
+ if (set) {
151
+ if (settings.baseSize !== undefined)
152
+ set.baseSize = settings.baseSize;
153
+ if (settings.opacity !== undefined)
154
+ set.opacity = settings.opacity;
155
+ if (settings.defaultColor !== undefined)
156
+ set.defaultColor = settings.defaultColor;
157
+ this.version++;
158
+ }
159
+ }
160
+ /**
161
+ * Rename a set
162
+ */
163
+ renameSet(setId, newName) {
164
+ const set = this.getSet(setId);
165
+ if (set) {
166
+ set.name = newName;
167
+ this.version++;
168
+ }
169
+ }
170
+ /**
171
+ * Get visible cells for a set (filtered by visible groups)
172
+ */
173
+ getVisibleCells(setId) {
174
+ const set = this.getSet(setId);
175
+ if (!set || !set.visible)
176
+ return [];
177
+ return set.cells.filter(c => c.resolvedCell && set.visibleGroups.has(c.customGroup));
178
+ }
179
+ /**
180
+ * Re-resolve cells after main cell data changes
181
+ */
182
+ refreshResolutions() {
183
+ const cellLookup = buildCellLookup(this.cellDataStore.rawCells);
184
+ for (const set of this.sets) {
185
+ for (const cell of set.cells) {
186
+ cell.resolvedCell = cellLookup.get(cell.txId);
187
+ }
188
+ }
189
+ this.version++;
190
+ }
191
+ /**
192
+ * Load from localStorage
193
+ */
194
+ load() {
195
+ try {
196
+ const stored = localStorage.getItem(this.storageKey);
197
+ if (stored) {
198
+ const data = JSON.parse(stored);
199
+ // Reconstruct sets with proper Set objects
200
+ this.sets = data.map((setData) => ({
201
+ ...setData,
202
+ visibleGroups: new Set(setData.visibleGroups || []),
203
+ cells: setData.cells || []
204
+ }));
205
+ // Re-resolve cells
206
+ this.refreshResolutions();
207
+ }
208
+ }
209
+ catch (e) {
210
+ console.warn('[CustomCellSetsStore] Failed to load from storage', e);
211
+ }
212
+ }
213
+ /**
214
+ * Save to localStorage
215
+ */
216
+ save() {
217
+ try {
218
+ // Convert Sets to arrays for JSON serialization
219
+ const data = this.sets.map(set => ({
220
+ ...set,
221
+ visibleGroups: Array.from(set.visibleGroups),
222
+ // Don't persist resolved cells - will re-resolve on load
223
+ cells: set.cells.map(c => ({
224
+ txId: c.txId,
225
+ customGroup: c.customGroup,
226
+ sizeFactor: c.sizeFactor,
227
+ extraFields: c.extraFields
228
+ }))
229
+ }));
230
+ localStorage.setItem(this.storageKey, JSON.stringify(data));
231
+ }
232
+ catch (e) {
233
+ console.warn('[CustomCellSetsStore] Failed to save to storage', e);
234
+ }
235
+ }
236
+ }
237
+ /**
238
+ * Factory function to create a custom cell sets store
239
+ */
240
+ export function createCustomCellSetsStore(cellDataStore, namespace = 'default') {
241
+ return new CustomCellSetsStore(cellDataStore, namespace);
242
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Custom Cells Stores - Barrel Export
3
+ */
4
+ export { CustomCellSetsStore, createCustomCellSetsStore } from './custom-cell-sets.svelte';
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Custom Cells Stores - Barrel Export
3
+ */
4
+ export { CustomCellSetsStore, createCustomCellSetsStore } from './custom-cell-sets.svelte';