@smartnet360/svelte-components 0.0.125 → 0.0.126
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/Auth/auth.svelte.js +47 -2
- package/dist/map-v3/demo/DemoMap.svelte +18 -0
- package/dist/map-v3/demo/demo-custom-cells.d.ts +21 -0
- package/dist/map-v3/demo/demo-custom-cells.js +48 -0
- package/dist/map-v3/features/cells/custom/components/CustomCellFilterControl.svelte +220 -0
- package/dist/map-v3/features/cells/custom/components/CustomCellFilterControl.svelte.d.ts +15 -0
- package/dist/map-v3/features/cells/custom/components/CustomCellSetManager.svelte +306 -0
- package/dist/map-v3/features/cells/custom/components/CustomCellSetManager.svelte.d.ts +10 -0
- package/dist/map-v3/features/cells/custom/components/index.d.ts +5 -0
- package/dist/map-v3/features/cells/custom/components/index.js +5 -0
- package/dist/map-v3/features/cells/custom/index.d.ts +32 -0
- package/dist/map-v3/features/cells/custom/index.js +35 -0
- package/dist/map-v3/features/cells/custom/layers/CustomCellsLayer.svelte +262 -0
- package/dist/map-v3/features/cells/custom/layers/CustomCellsLayer.svelte.d.ts +10 -0
- package/dist/map-v3/features/cells/custom/layers/index.d.ts +4 -0
- package/dist/map-v3/features/cells/custom/layers/index.js +4 -0
- package/dist/map-v3/features/cells/custom/logic/csv-parser.d.ts +20 -0
- package/dist/map-v3/features/cells/custom/logic/csv-parser.js +164 -0
- package/dist/map-v3/features/cells/custom/logic/index.d.ts +5 -0
- package/dist/map-v3/features/cells/custom/logic/index.js +5 -0
- package/dist/map-v3/features/cells/custom/logic/tree-adapter.d.ts +24 -0
- package/dist/map-v3/features/cells/custom/logic/tree-adapter.js +67 -0
- package/dist/map-v3/features/cells/custom/stores/custom-cell-sets.svelte.d.ts +78 -0
- package/dist/map-v3/features/cells/custom/stores/custom-cell-sets.svelte.js +242 -0
- package/dist/map-v3/features/cells/custom/stores/index.d.ts +4 -0
- package/dist/map-v3/features/cells/custom/stores/index.js +4 -0
- package/dist/map-v3/features/cells/custom/types.d.ts +83 -0
- package/dist/map-v3/features/cells/custom/types.js +23 -0
- package/dist/map-v3/shared/controls/MapControl.svelte +27 -3
- package/package.json +1 -1
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
// Auth state management using Svelte 5 runes
|
|
2
2
|
import { browser } from '$app/environment';
|
|
3
|
+
// Demo mode - enabled via PUBLIC_DEMO_MODE env var (GitHub Pages)
|
|
4
|
+
const DEMO_MODE = import.meta.env.PUBLIC_DEMO_MODE === 'true';
|
|
5
|
+
const DEMO_USERNAME = 'demo';
|
|
6
|
+
const DEMO_PASSWORD = 'demo123';
|
|
7
|
+
// Demo user session (client-side only, no server needed)
|
|
8
|
+
const DEMO_SESSION = {
|
|
9
|
+
user: {
|
|
10
|
+
id: 'demo-user',
|
|
11
|
+
username: 'demo',
|
|
12
|
+
displayName: 'Demo User',
|
|
13
|
+
email: 'demo@example.com',
|
|
14
|
+
groups: ['demo'],
|
|
15
|
+
loginTime: Date.now()
|
|
16
|
+
},
|
|
17
|
+
permissions: [
|
|
18
|
+
{ featureId: 'map-view', canView: true, canEdit: false, canAdmin: false },
|
|
19
|
+
{ featureId: 'coverage-view', canView: true, canEdit: false, canAdmin: false },
|
|
20
|
+
{ featureId: 'charts-view', canView: true, canEdit: false, canAdmin: false },
|
|
21
|
+
{ featureId: 'desktop-view', canView: true, canEdit: false, canAdmin: false },
|
|
22
|
+
{ featureId: 'table-view', canView: true, canEdit: false, canAdmin: false },
|
|
23
|
+
{ featureId: 'antenna-view', canView: true, canEdit: false, canAdmin: false },
|
|
24
|
+
{ featureId: 'site-check', canView: true, canEdit: false, canAdmin: false },
|
|
25
|
+
{ featureId: 'settings-view', canView: true, canEdit: false, canAdmin: false }
|
|
26
|
+
],
|
|
27
|
+
token: 'demo-token',
|
|
28
|
+
expiresAt: Date.now() + (24 * 60 * 60 * 1000) // 24 hours for demo
|
|
29
|
+
};
|
|
3
30
|
// Default configuration
|
|
4
31
|
const defaultConfig = {
|
|
5
32
|
apiEndpoint: '/api/auth',
|
|
@@ -80,6 +107,24 @@ export function createAuthState(config = {}) {
|
|
|
80
107
|
isLoading = true;
|
|
81
108
|
error = null;
|
|
82
109
|
try {
|
|
110
|
+
// Demo mode: handle authentication client-side (no server needed)
|
|
111
|
+
if (DEMO_MODE) {
|
|
112
|
+
if (username === DEMO_USERNAME && password === DEMO_PASSWORD) {
|
|
113
|
+
// Create fresh demo session with updated timestamp
|
|
114
|
+
const demoSession = {
|
|
115
|
+
...DEMO_SESSION,
|
|
116
|
+
user: { ...DEMO_SESSION.user, loginTime: Date.now() },
|
|
117
|
+
expiresAt: Date.now() + (24 * 60 * 60 * 1000)
|
|
118
|
+
};
|
|
119
|
+
saveSession(demoSession);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
error = 'Demo mode: Use username "demo" and password "demo123"';
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Normal mode: call server API
|
|
83
128
|
const response = await fetch(`${cfg.apiEndpoint}/login`, {
|
|
84
129
|
method: 'POST',
|
|
85
130
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -121,8 +166,8 @@ export function createAuthState(config = {}) {
|
|
|
121
166
|
async function logout() {
|
|
122
167
|
isLoading = true;
|
|
123
168
|
try {
|
|
124
|
-
//
|
|
125
|
-
if (session?.token) {
|
|
169
|
+
// Skip server call in demo mode (no server available)
|
|
170
|
+
if (!DEMO_MODE && session?.token) {
|
|
126
171
|
await fetch(`${cfg.apiEndpoint}/logout`, {
|
|
127
172
|
method: 'POST',
|
|
128
173
|
headers: {
|
|
@@ -20,6 +20,12 @@
|
|
|
20
20
|
import SiteFilterControl from '../features/sites/components/SiteFilterControl.svelte';
|
|
21
21
|
import { createSiteRegistry } from '../features/sites/stores/site.registry.svelte';
|
|
22
22
|
import FeatureSelectionControl from '../features/selection/components/FeatureSelectionControl.svelte';
|
|
23
|
+
// Custom Cells Feature
|
|
24
|
+
import {
|
|
25
|
+
CustomCellsLayer,
|
|
26
|
+
CustomCellSetManager,
|
|
27
|
+
createCustomCellSetsStore
|
|
28
|
+
} from '../features/cells/custom';
|
|
23
29
|
import { demoCells } from './demo-cells';
|
|
24
30
|
import { demoRepeaters } from './demo-repeaters';
|
|
25
31
|
|
|
@@ -42,6 +48,9 @@
|
|
|
42
48
|
const repeaterRegistry = createRepeaterRegistry('demo-map');
|
|
43
49
|
const repeaterDisplay = new RepeaterDisplayStore();
|
|
44
50
|
|
|
51
|
+
// Custom Cells Store
|
|
52
|
+
const customCellSets = createCustomCellSetsStore(cellData, 'demo-map');
|
|
53
|
+
|
|
45
54
|
onMount(() => {
|
|
46
55
|
// Load dummy data
|
|
47
56
|
// Need to cast or map if types slightly differ, but they should match
|
|
@@ -81,6 +90,12 @@
|
|
|
81
90
|
displayStore={repeaterDisplay}
|
|
82
91
|
/>
|
|
83
92
|
|
|
93
|
+
<!-- Custom Cells Manager (includes filter controls for each set) -->
|
|
94
|
+
<CustomCellSetManager
|
|
95
|
+
position="top-left"
|
|
96
|
+
setsStore={customCellSets}
|
|
97
|
+
/>
|
|
98
|
+
|
|
84
99
|
<FeatureSettingsControl
|
|
85
100
|
position="top-right"
|
|
86
101
|
cellDisplayStore={cellDisplay}
|
|
@@ -99,6 +114,9 @@
|
|
|
99
114
|
<RepeatersLayer dataStore={repeaterData} registry={repeaterRegistry} displayStore={repeaterDisplay} />
|
|
100
115
|
<RepeaterLabelsLayer dataStore={repeaterData} registry={repeaterRegistry} displayStore={repeaterDisplay} />
|
|
101
116
|
|
|
117
|
+
<!-- Custom Cells Layer (renders on top of regular cells) -->
|
|
118
|
+
<CustomCellsLayer setsStore={customCellSets} />
|
|
119
|
+
|
|
102
120
|
<FeatureSelectionControl
|
|
103
121
|
position="bottom-left"
|
|
104
122
|
cellDataStore={cellData}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo Custom Cells Data
|
|
3
|
+
*
|
|
4
|
+
* Sample CSV content for testing custom cells feature.
|
|
5
|
+
* Uses txIds from the demo cells data.
|
|
6
|
+
*
|
|
7
|
+
* txId format: SSSS S BB where:
|
|
8
|
+
* - SSSS = site number (1000+)
|
|
9
|
+
* - S = sector (1, 2, or 3)
|
|
10
|
+
* - BB = band index (41-51)
|
|
11
|
+
* 41=GSM900, 42=GSM1800, 43=LTE700, 44=LTE800, 45=LTE900
|
|
12
|
+
* 46=LTE1800, 47=LTE2100, 48=LTE2600, 49=5G700, 50=5G2100, 51=5G3500
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Sample CSV content with various groups and size factors
|
|
16
|
+
*/
|
|
17
|
+
export declare const demoCustomCellsCsv = "txId,customGroup,sizeFactor,congestion,trafficGB\n1000141,High Traffic,3,critical,250\n1000241,High Traffic,2.5,high,180\n1000341,High Traffic,2,medium,120\n1001145,High Traffic,3.5,critical,300\n1001245,High Traffic,2,medium,100\n1002147,Medium Traffic,1.5,low,60\n1002247,Medium Traffic,1.2,low,45\n1002347,Medium Traffic,1,minimal,30\n1003142,Medium Traffic,1.5,low,55\n1003242,Medium Traffic,1.3,low,40\n1004151,Low Traffic,0.8,minimal,15\n1004251,Low Traffic,0.7,minimal,10\n1004351,Low Traffic,0.6,minimal,8\n1005149,Problem Cells,2,error,0\n1005249,Problem Cells,2,error,0\n1006144,Problem Cells,1.8,warning,5\n";
|
|
18
|
+
/**
|
|
19
|
+
* Another sample CSV with different groupings
|
|
20
|
+
*/
|
|
21
|
+
export declare const demoCustomCellsCsv2 = "txId,customGroup,sizeFactor,priority\n1010141,Expansion Zone A,2,high\n1010241,Expansion Zone A,2,high\n1010341,Expansion Zone A,2,high\n1011145,Expansion Zone A,1.5,medium\n1012147,Expansion Zone B,1.8,high\n1012247,Expansion Zone B,1.8,high\n1013142,Existing Coverage,1,low\n1013242,Existing Coverage,1,low\n1013342,Existing Coverage,1,low\n";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo Custom Cells Data
|
|
3
|
+
*
|
|
4
|
+
* Sample CSV content for testing custom cells feature.
|
|
5
|
+
* Uses txIds from the demo cells data.
|
|
6
|
+
*
|
|
7
|
+
* txId format: SSSS S BB where:
|
|
8
|
+
* - SSSS = site number (1000+)
|
|
9
|
+
* - S = sector (1, 2, or 3)
|
|
10
|
+
* - BB = band index (41-51)
|
|
11
|
+
* 41=GSM900, 42=GSM1800, 43=LTE700, 44=LTE800, 45=LTE900
|
|
12
|
+
* 46=LTE1800, 47=LTE2100, 48=LTE2600, 49=5G700, 50=5G2100, 51=5G3500
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Sample CSV content with various groups and size factors
|
|
16
|
+
*/
|
|
17
|
+
export const demoCustomCellsCsv = `txId,customGroup,sizeFactor,congestion,trafficGB
|
|
18
|
+
1000141,High Traffic,3,critical,250
|
|
19
|
+
1000241,High Traffic,2.5,high,180
|
|
20
|
+
1000341,High Traffic,2,medium,120
|
|
21
|
+
1001145,High Traffic,3.5,critical,300
|
|
22
|
+
1001245,High Traffic,2,medium,100
|
|
23
|
+
1002147,Medium Traffic,1.5,low,60
|
|
24
|
+
1002247,Medium Traffic,1.2,low,45
|
|
25
|
+
1002347,Medium Traffic,1,minimal,30
|
|
26
|
+
1003142,Medium Traffic,1.5,low,55
|
|
27
|
+
1003242,Medium Traffic,1.3,low,40
|
|
28
|
+
1004151,Low Traffic,0.8,minimal,15
|
|
29
|
+
1004251,Low Traffic,0.7,minimal,10
|
|
30
|
+
1004351,Low Traffic,0.6,minimal,8
|
|
31
|
+
1005149,Problem Cells,2,error,0
|
|
32
|
+
1005249,Problem Cells,2,error,0
|
|
33
|
+
1006144,Problem Cells,1.8,warning,5
|
|
34
|
+
`;
|
|
35
|
+
/**
|
|
36
|
+
* Another sample CSV with different groupings
|
|
37
|
+
*/
|
|
38
|
+
export const demoCustomCellsCsv2 = `txId,customGroup,sizeFactor,priority
|
|
39
|
+
1010141,Expansion Zone A,2,high
|
|
40
|
+
1010241,Expansion Zone A,2,high
|
|
41
|
+
1010341,Expansion Zone A,2,high
|
|
42
|
+
1011145,Expansion Zone A,1.5,medium
|
|
43
|
+
1012147,Expansion Zone B,1.8,high
|
|
44
|
+
1012247,Expansion Zone B,1.8,high
|
|
45
|
+
1013142,Existing Coverage,1,low
|
|
46
|
+
1013242,Existing Coverage,1,low
|
|
47
|
+
1013342,Existing Coverage,1,low
|
|
48
|
+
`;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Custom Cell Filter Control
|
|
4
|
+
*
|
|
5
|
+
* TreeView with color pickers for a single custom cell set.
|
|
6
|
+
* Shows groups with their cell counts and allows color customization.
|
|
7
|
+
*/
|
|
8
|
+
import { untrack, onDestroy } from 'svelte';
|
|
9
|
+
import { MapControl } from '../../../../shared';
|
|
10
|
+
import { createTreeStore, TreeView } from '../../../../../core/TreeView';
|
|
11
|
+
import type { CustomCellSetsStore } from '../stores/custom-cell-sets.svelte';
|
|
12
|
+
import type { CustomCellSet } from '../types';
|
|
13
|
+
import { buildCustomCellTree } from '../logic/tree-adapter';
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
/** The custom cell sets store */
|
|
17
|
+
setsStore: CustomCellSetsStore;
|
|
18
|
+
/** The specific set to display */
|
|
19
|
+
set: CustomCellSet;
|
|
20
|
+
/** Control position on map */
|
|
21
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
22
|
+
/** Callback when set is removed */
|
|
23
|
+
onremove?: (setId: string) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
setsStore,
|
|
28
|
+
set,
|
|
29
|
+
position = 'top-left',
|
|
30
|
+
onremove
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
|
|
33
|
+
// Reference to MapControl for explicit cleanup
|
|
34
|
+
let mapControlRef: MapControl | undefined;
|
|
35
|
+
|
|
36
|
+
// Track if this component should be destroyed (used for delayed removal)
|
|
37
|
+
let isDestroying = $state(false);
|
|
38
|
+
|
|
39
|
+
onDestroy(() => {
|
|
40
|
+
console.log(`[CustomCellFilterControl] onDestroy called for set: ${set.id}`);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Build tree from set
|
|
44
|
+
let treeStore = $derived.by(() => {
|
|
45
|
+
const _version = setsStore.version;
|
|
46
|
+
const _set = set;
|
|
47
|
+
|
|
48
|
+
return untrack(() => {
|
|
49
|
+
const nodes = buildCustomCellTree(_set);
|
|
50
|
+
return createTreeStore({
|
|
51
|
+
nodes,
|
|
52
|
+
namespace: `custom-cells:${_set.id}`,
|
|
53
|
+
persistState: true,
|
|
54
|
+
defaultExpandAll: true
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Sync tree selection -> store visibility
|
|
60
|
+
$effect(() => {
|
|
61
|
+
const val = treeStore;
|
|
62
|
+
let changes = 0;
|
|
63
|
+
|
|
64
|
+
val.state.nodes.forEach((nodeState) => {
|
|
65
|
+
// Skip root node
|
|
66
|
+
if (nodeState.node.id === `root-${set.id}`) return;
|
|
67
|
+
// Skip folder nodes
|
|
68
|
+
if (nodeState.node.children && nodeState.node.children.length > 0) return;
|
|
69
|
+
|
|
70
|
+
const groupId = nodeState.node.metadata?.groupId;
|
|
71
|
+
if (!groupId) return;
|
|
72
|
+
|
|
73
|
+
const isVisible = val.state.checkedPaths.has(nodeState.path);
|
|
74
|
+
const currentlyVisible = set.visibleGroups.has(groupId);
|
|
75
|
+
|
|
76
|
+
if (isVisible !== currentlyVisible) {
|
|
77
|
+
setsStore.toggleGroupVisibility(set.id, groupId);
|
|
78
|
+
changes++;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (changes > 0) {
|
|
83
|
+
console.log(`[CustomCellFilterControl] Synced ${changes} visibility changes`);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
function handleColorChange(groupId: string, event: Event) {
|
|
88
|
+
const input = event.target as HTMLInputElement;
|
|
89
|
+
setsStore.setGroupColor(set.id, groupId, input.value);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function handleRemove() {
|
|
93
|
+
if (onremove) {
|
|
94
|
+
onremove(set.id);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function handleToggleVisibility() {
|
|
99
|
+
setsStore.toggleSetVisibility(set.id);
|
|
100
|
+
}
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<MapControl {position} title={set.name} icon="layers" controlWidth="280px">
|
|
104
|
+
{#snippet actions()}
|
|
105
|
+
<button
|
|
106
|
+
class="btn btn-sm btn-outline-secondary border-0 p-1 px-2"
|
|
107
|
+
title={set.visible ? 'Hide Layer' : 'Show Layer'}
|
|
108
|
+
onclick={handleToggleVisibility}
|
|
109
|
+
>
|
|
110
|
+
<i class="bi bi-eye{set.visible ? '-fill' : '-slash'}"></i>
|
|
111
|
+
</button>
|
|
112
|
+
<button
|
|
113
|
+
class="btn btn-sm btn-outline-danger border-0 p-1 px-2"
|
|
114
|
+
title="Remove Set"
|
|
115
|
+
onclick={handleRemove}
|
|
116
|
+
>
|
|
117
|
+
<i class="bi bi-trash"></i>
|
|
118
|
+
</button>
|
|
119
|
+
{/snippet}
|
|
120
|
+
|
|
121
|
+
<div class="custom-cell-filter-control">
|
|
122
|
+
<!-- Set Info -->
|
|
123
|
+
<div class="set-info mb-2 px-1">
|
|
124
|
+
<small class="text-muted">
|
|
125
|
+
{set.cells.length} cells in {set.groups.length} groups
|
|
126
|
+
{#if set.unmatchedTxIds.length > 0}
|
|
127
|
+
<span class="text-warning ms-1" title="Some cells not found">
|
|
128
|
+
({set.unmatchedTxIds.length} unmatched)
|
|
129
|
+
</span>
|
|
130
|
+
{/if}
|
|
131
|
+
</small>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<!-- Size Slider -->
|
|
135
|
+
<div class="size-control mb-2 px-1">
|
|
136
|
+
<label for="baseSize-{set.id}" class="form-label small mb-1">
|
|
137
|
+
Base Size: {set.baseSize}px
|
|
138
|
+
</label>
|
|
139
|
+
<input
|
|
140
|
+
type="range"
|
|
141
|
+
class="form-range"
|
|
142
|
+
id="baseSize-{set.id}"
|
|
143
|
+
min="10"
|
|
144
|
+
max="150"
|
|
145
|
+
step="5"
|
|
146
|
+
value={set.baseSize}
|
|
147
|
+
oninput={(e) => setsStore.updateSetSettings(set.id, {
|
|
148
|
+
baseSize: parseInt((e.target as HTMLInputElement).value)
|
|
149
|
+
})}
|
|
150
|
+
/>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<!-- Opacity Slider -->
|
|
154
|
+
<div class="opacity-control mb-2 px-1">
|
|
155
|
+
<label for="opacity-{set.id}" class="form-label small mb-1">
|
|
156
|
+
Opacity: {Math.round(set.opacity * 100)}%
|
|
157
|
+
</label>
|
|
158
|
+
<input
|
|
159
|
+
type="range"
|
|
160
|
+
class="form-range"
|
|
161
|
+
id="opacity-{set.id}"
|
|
162
|
+
min="0.1"
|
|
163
|
+
max="1"
|
|
164
|
+
step="0.1"
|
|
165
|
+
value={set.opacity}
|
|
166
|
+
oninput={(e) => setsStore.updateSetSettings(set.id, {
|
|
167
|
+
opacity: parseFloat((e.target as HTMLInputElement).value)
|
|
168
|
+
})}
|
|
169
|
+
/>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<!-- Tree View -->
|
|
173
|
+
<div class="custom-cell-tree">
|
|
174
|
+
{#if set.cells.length === 0}
|
|
175
|
+
<div class="text-muted p-3 text-center small">
|
|
176
|
+
No cells in this set.
|
|
177
|
+
</div>
|
|
178
|
+
{:else}
|
|
179
|
+
<TreeView showControls={false} store={treeStore} height="200px">
|
|
180
|
+
{#snippet children({ node, state })}
|
|
181
|
+
<!-- Color Picker (Only for group leaves) -->
|
|
182
|
+
{#if (!node.children || node.children.length === 0) && node.metadata?.groupId !== '__root__'}
|
|
183
|
+
<div
|
|
184
|
+
class="d-flex align-items-center"
|
|
185
|
+
role="group"
|
|
186
|
+
onclick={(e) => e.stopPropagation()}
|
|
187
|
+
onkeydown={(e) => e.stopPropagation()}
|
|
188
|
+
>
|
|
189
|
+
<input
|
|
190
|
+
type="color"
|
|
191
|
+
class="form-control form-control-color form-control-sm border-0 p-0"
|
|
192
|
+
style="width: 16px; height: 16px; min-height: 0;"
|
|
193
|
+
value={node.metadata?.color}
|
|
194
|
+
oninput={(e) => handleColorChange(node.metadata?.groupId || '', e)}
|
|
195
|
+
title="Change color"
|
|
196
|
+
/>
|
|
197
|
+
</div>
|
|
198
|
+
{/if}
|
|
199
|
+
{/snippet}
|
|
200
|
+
</TreeView>
|
|
201
|
+
{/if}
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
</MapControl>
|
|
205
|
+
|
|
206
|
+
<style>
|
|
207
|
+
.custom-cell-filter-control {
|
|
208
|
+
font-size: 0.875rem;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.set-info {
|
|
212
|
+
border-bottom: 1px solid var(--bs-border-color, #dee2e6);
|
|
213
|
+
padding-bottom: 0.5rem;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.custom-cell-tree {
|
|
217
|
+
max-height: 250px;
|
|
218
|
+
overflow-y: auto;
|
|
219
|
+
}
|
|
220
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CustomCellSetsStore } from '../stores/custom-cell-sets.svelte';
|
|
2
|
+
import type { CustomCellSet } from '../types';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** The custom cell sets store */
|
|
5
|
+
setsStore: CustomCellSetsStore;
|
|
6
|
+
/** The specific set to display */
|
|
7
|
+
set: CustomCellSet;
|
|
8
|
+
/** Control position on map */
|
|
9
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
10
|
+
/** Callback when set is removed */
|
|
11
|
+
onremove?: (setId: string) => void;
|
|
12
|
+
}
|
|
13
|
+
declare const CustomCellFilterControl: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type CustomCellFilterControl = ReturnType<typeof CustomCellFilterControl>;
|
|
15
|
+
export default CustomCellFilterControl;
|