@smartnet360/svelte-components 0.0.42 → 0.0.44

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.
@@ -6,9 +6,11 @@
6
6
  interface Props {
7
7
  controls: GlobalChartControls;
8
8
  onUpdate: (controls: GlobalChartControls) => void;
9
+ isExpanded?: boolean;
10
+ onToggle?: () => void;
9
11
  }
10
12
 
11
- let { controls, onUpdate }: Props = $props();
13
+ let { controls, onUpdate, isExpanded = false, onToggle }: Props = $props();
12
14
 
13
15
  function updateControls(updates: Partial<GlobalChartControls>) {
14
16
  onUpdate({
@@ -48,178 +50,377 @@
48
50
  }
49
51
  </script>
50
52
 
51
- <div class="global-controls">
52
- <div class="controls-section">
53
- <!-- <span class="controls-label">Display Controls:</span> -->
54
-
55
- <!-- Moving Average Controls -->
56
- {#if controls.movingAverage}
57
- <div class="control-group">
58
- <!-- MA Enable Toggle Button -->
59
- <input
60
- type="checkbox"
61
- class="btn-check"
62
- id="maToggle"
63
- checked={controls.movingAverage.enabled}
64
- onchange={() => updateMovingAverage({ enabled: !controls.movingAverage!.enabled })}
65
- />
66
- <label class="btn btn-outline-primary btn-sm" for="maToggle">
67
- Moving Average
68
- </label>
69
-
70
- {#if controls.movingAverage.enabled}
71
- <div class="control-subgroup">
72
- <!-- MA Window Size -->
73
- <div class="btn-group btn-group-sm" role="group" aria-label="MA Window">
74
- <input
75
- type="radio"
76
- class="btn-check"
77
- name="maWindow"
78
- id="maWindowAuto"
79
- checked={controls.movingAverage.windowOverride === undefined}
80
- onchange={() => updateMovingAverage({ windowOverride: undefined })}
81
- />
82
- <label class="btn btn-outline-primary" for="maWindowAuto">Auto</label>
83
-
84
- <input
85
- type="radio"
86
- class="btn-check"
87
- name="maWindow"
88
- id="maWindow7"
89
- checked={controls.movingAverage.windowOverride === 7}
90
- onchange={() => updateMovingAverage({ windowOverride: 7 })}
91
- />
92
- <label class="btn btn-outline-primary" for="maWindow7">7</label>
93
-
94
- <input
95
- type="radio"
96
- class="btn-check"
97
- name="maWindow"
98
- id="maWindow14"
99
- checked={controls.movingAverage.windowOverride === 14}
100
- onchange={() => updateMovingAverage({ windowOverride: 14 })}
101
- />
102
- <label class="btn btn-outline-primary" for="maWindow14">14</label>
53
+ <!-- Floating Controls Container -->
54
+ <div class="floating-controls-wrapper">
55
+ <!-- Toggle Button (always visible) -->
56
+ <button
57
+ class="floating-toggle-btn"
58
+ onclick={onToggle}
59
+ title={isExpanded ? "Hide Controls" : "Show Controls"}
60
+ type="button"
61
+ aria-expanded={isExpanded}
62
+ aria-label="Toggle chart controls"
63
+ >
64
+ <svg width="18" height="18" fill="currentColor" viewBox="0 0 16 16">
65
+ <path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/>
66
+ </svg>
67
+ <svg
68
+ class="chevron"
69
+ class:expanded={isExpanded}
70
+ width="12"
71
+ height="12"
72
+ fill="currentColor"
73
+ viewBox="0 0 16 16"
74
+ >
75
+ <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"/>
76
+ </svg>
77
+ </button>
103
78
 
79
+ <!-- Controls Panel (expandable) -->
80
+ {#if isExpanded}
81
+ <div class="floating-controls-panel">
82
+ <div class="controls-section">
83
+ <!-- Top Row: Markers and Legend side by side -->
84
+ <div class="controls-row">
85
+ <!-- Markers Toggle -->
86
+ {#if controls.markers}
87
+ <div class="control-group-inline">
104
88
  <input
105
- type="radio"
89
+ type="checkbox"
106
90
  class="btn-check"
107
- name="maWindow"
108
- id="maWindow24"
109
- checked={controls.movingAverage.windowOverride === 24}
110
- onchange={() => updateMovingAverage({ windowOverride: 24 })}
91
+ id="markersToggle"
92
+ checked={controls.markers.enabled}
93
+ onchange={() => updateMarkers({ enabled: !controls.markers!.enabled })}
111
94
  />
112
- <label class="btn btn-outline-primary" for="maWindow24">24</label>
95
+ <label class="btn btn-outline-secondary btn-sm" for="markersToggle">
96
+ Markers
97
+ </label>
98
+ </div>
99
+ {/if}
113
100
 
101
+ <!-- Legend Toggle -->
102
+ {#if controls.legend}
103
+ <div class="control-group-inline">
114
104
  <input
115
- type="radio"
105
+ type="checkbox"
116
106
  class="btn-check"
117
- name="maWindow"
118
- id="maWindow30"
119
- checked={controls.movingAverage.windowOverride === 30}
120
- onchange={() => updateMovingAverage({ windowOverride: 30 })}
107
+ id="legendToggle"
108
+ checked={controls.legend.enabled}
109
+ onchange={() => updateLegend({ enabled: !controls.legend!.enabled })}
121
110
  />
122
- <label class="btn btn-outline-primary" for="maWindow30">30</label>
111
+ <label class="btn btn-outline-secondary btn-sm" for="legendToggle">
112
+ Legend
113
+ </label>
123
114
  </div>
115
+ {/if}
116
+ </div>
124
117
 
125
- <!-- Show Original Toggle Button -->
118
+ <!-- Bottom: Moving Average Controls -->
119
+ {#if controls.movingAverage}
120
+ <div class="control-group">
121
+ <!-- MA Enable Toggle Button -->
126
122
  <input
127
123
  type="checkbox"
128
124
  class="btn-check"
129
- id="showOriginal"
130
- checked={controls.movingAverage.showOriginal}
131
- onchange={() => updateMovingAverage({ showOriginal: !controls.movingAverage!.showOriginal })}
125
+ id="maToggle"
126
+ checked={controls.movingAverage.enabled}
127
+ onchange={() => updateMovingAverage({ enabled: !controls.movingAverage!.enabled })}
132
128
  />
133
- <label class="btn btn-outline-primary btn-sm ms-2" for="showOriginal">
134
- Show Original
129
+ <label class="btn btn-outline-primary btn-sm" for="maToggle">
130
+ Moving Average
135
131
  </label>
132
+
133
+ {#if controls.movingAverage.enabled}
134
+ <div class="control-subgroup">
135
+ <!-- MA Window Size -->
136
+ <div class="btn-group btn-group-sm" role="group" aria-label="MA Window">
137
+ <input
138
+ type="radio"
139
+ class="btn-check"
140
+ name="maWindow"
141
+ id="maWindowAuto"
142
+ checked={controls.movingAverage.windowOverride === undefined}
143
+ onchange={() => updateMovingAverage({ windowOverride: undefined })}
144
+ />
145
+ <label class="btn btn-outline-primary" for="maWindowAuto">Auto</label>
146
+
147
+ <input
148
+ type="radio"
149
+ class="btn-check"
150
+ name="maWindow"
151
+ id="maWindow7"
152
+ checked={controls.movingAverage.windowOverride === 7}
153
+ onchange={() => updateMovingAverage({ windowOverride: 7 })}
154
+ />
155
+ <label class="btn btn-outline-primary" for="maWindow7">7</label>
156
+
157
+ <input
158
+ type="radio"
159
+ class="btn-check"
160
+ name="maWindow"
161
+ id="maWindow14"
162
+ checked={controls.movingAverage.windowOverride === 14}
163
+ onchange={() => updateMovingAverage({ windowOverride: 14 })}
164
+ />
165
+ <label class="btn btn-outline-primary" for="maWindow14">14</label>
166
+
167
+ <input
168
+ type="radio"
169
+ class="btn-check"
170
+ name="maWindow"
171
+ id="maWindow24"
172
+ checked={controls.movingAverage.windowOverride === 24}
173
+ onchange={() => updateMovingAverage({ windowOverride: 24 })}
174
+ />
175
+ <label class="btn btn-outline-primary" for="maWindow24">24</label>
176
+
177
+ <input
178
+ type="radio"
179
+ class="btn-check"
180
+ name="maWindow"
181
+ id="maWindow30"
182
+ checked={controls.movingAverage.windowOverride === 30}
183
+ onchange={() => updateMovingAverage({ windowOverride: 30 })}
184
+ />
185
+ <label class="btn btn-outline-primary" for="maWindow30">30</label>
186
+ </div>
187
+
188
+ <!-- Show Original Toggle Button -->
189
+ <input
190
+ type="checkbox"
191
+ class="btn-check"
192
+ id="showOriginal"
193
+ checked={controls.movingAverage.showOriginal}
194
+ onchange={() => updateMovingAverage({ showOriginal: !controls.movingAverage!.showOriginal })}
195
+ />
196
+ <label class="btn btn-outline-primary btn-sm ms-2" for="showOriginal">
197
+ Show Original
198
+ </label>
199
+ </div>
200
+ {/if}
136
201
  </div>
137
202
  {/if}
138
203
  </div>
139
- {/if}
140
-
141
- <!-- Markers Toggle -->
142
- {#if controls.markers}
143
- <div class="control-group">
144
- <input
145
- type="checkbox"
146
- class="btn-check"
147
- id="markersToggle"
148
- checked={controls.markers.enabled}
149
- onchange={() => updateMarkers({ enabled: !controls.markers!.enabled })}
150
- />
151
- <label class="btn btn-outline-secondary btn-sm" for="markersToggle">
152
- Markers
153
- </label>
154
- </div>
155
- {/if}
156
-
157
- <!-- Legend Toggle -->
158
- {#if controls.legend}
159
- <div class="control-group">
160
- <input
161
- type="checkbox"
162
- class="btn-check"
163
- id="legendToggle"
164
- checked={controls.legend.enabled}
165
- onchange={() => updateLegend({ enabled: !controls.legend!.enabled })}
166
- />
167
- <label class="btn btn-outline-secondary btn-sm" for="legendToggle">
168
- Legend
169
- </label>
170
- </div>
171
- {/if}
172
-
173
- </div>
204
+ </div>
205
+ {/if}
174
206
  </div>
175
207
 
176
208
  <style>
177
- /* Global Controls Section */
178
- .global-controls {
179
- flex-shrink: 0;
180
- background-color: #f8f9fa;
181
- border-bottom: 1px solid #dee2e6;
182
- padding: 0.5rem 1rem;
209
+ /* Floating Controls Wrapper - positioned in top-right */
210
+ .floating-controls-wrapper {
211
+ position: fixed;
212
+ top: 0.5rem;
213
+ right: 0.5rem;
214
+ z-index: 1000;
215
+ display: flex;
216
+ flex-direction: column;
217
+ align-items: flex-end;
218
+ gap: 0.5rem;
219
+ }
220
+
221
+ /* Toggle Button - Always visible */
222
+ .floating-toggle-btn {
223
+ display: flex;
224
+ align-items: center;
225
+ gap: 0.375rem;
226
+ padding: 0.5rem 0.75rem;
227
+ background: rgba(255, 255, 255, 0.95);
228
+ backdrop-filter: blur(10px);
229
+ -webkit-backdrop-filter: blur(10px);
230
+ border: 1px solid rgba(0, 0, 0, 0.08);
231
+ border-radius: 8px;
232
+ box-shadow:
233
+ 0 2px 8px rgba(0, 0, 0, 0.08),
234
+ 0 4px 16px rgba(0, 0, 0, 0.04);
235
+ cursor: pointer;
236
+ transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
183
237
  font-size: 0.875rem;
238
+ font-weight: 500;
239
+ color: #495057;
240
+ opacity: 0.5;
241
+ }
242
+
243
+ .floating-toggle-btn:hover {
244
+ background: rgba(255, 255, 255, 1);
245
+ border-color: rgba(0, 0, 0, 0.12);
246
+ box-shadow:
247
+ 0 4px 12px rgba(0, 0, 0, 0.12),
248
+ 0 8px 24px rgba(0, 0, 0, 0.08);
249
+ transform: translateY(-1px);
250
+ opacity: 1;
251
+ }
252
+
253
+ .floating-toggle-btn:active {
254
+ transform: translateY(0);
255
+ box-shadow:
256
+ 0 1px 4px rgba(0, 0, 0, 0.08),
257
+ 0 2px 8px rgba(0, 0, 0, 0.04);
258
+ }
259
+
260
+ .floating-toggle-btn .chevron {
261
+ transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
262
+ opacity: 0.6;
263
+ }
264
+
265
+ .floating-toggle-btn .chevron.expanded {
266
+ transform: rotate(180deg);
267
+ }
268
+
269
+ /* Floating Controls Panel - Glass-morphism style */
270
+ .floating-controls-panel {
271
+ background: rgba(255, 255, 255, 0.95);
272
+ backdrop-filter: blur(12px);
273
+ -webkit-backdrop-filter: blur(12px);
274
+ border: 1px solid rgba(0, 0, 0, 0.08);
275
+ border-radius: 12px;
276
+ box-shadow:
277
+ 0 4px 16px rgba(0, 0, 0, 0.1),
278
+ 0 8px 32px rgba(0, 0, 0, 0.08);
279
+ padding: 1rem;
280
+ min-width: 320px;
281
+ max-width: 480px;
282
+ opacity: 1;
283
+ animation: slideIn 200ms cubic-bezier(0.4, 0, 0.2, 1);
284
+ }
285
+
286
+ .floating-controls-panel:hover {
287
+ opacity: 1;
288
+ }
289
+
290
+ @keyframes slideIn {
291
+ from {
292
+ opacity: 0;
293
+ transform: translateY(-8px);
294
+ }
295
+ to {
296
+ opacity: 1;
297
+ transform: translateY(0);
298
+ }
184
299
  }
185
300
 
186
301
  .controls-section {
302
+ display: flex;
303
+ flex-direction: column;
304
+ gap: 1rem;
305
+ }
306
+
307
+ /* Horizontal row for Markers and Legend at top */
308
+ .controls-row {
187
309
  display: flex;
188
310
  align-items: center;
189
- gap: 1.5rem;
190
- flex-wrap: wrap;
311
+ gap: 0.75rem;
312
+ padding-bottom: 0.75rem;
313
+ border-bottom: 1px solid rgba(0, 0, 0, 0.08);
191
314
  }
192
315
 
193
- .control-group {
316
+ /* Inline control group for horizontal layout */
317
+ .control-group-inline {
194
318
  display: flex;
195
319
  align-items: center;
320
+ }
321
+
322
+ /* Vertical control group for Moving Average */
323
+ .control-group {
324
+ display: flex;
325
+ flex-direction: column;
196
326
  gap: 0.75rem;
197
327
  }
198
328
 
329
+ .control-group > label:first-of-type {
330
+ font-weight: 500;
331
+ }
332
+
199
333
  .control-subgroup {
200
334
  display: flex;
335
+ flex-wrap: wrap;
201
336
  align-items: center;
202
337
  gap: 0.5rem;
203
- padding-left: 0.5rem;
204
- border-left: 2px solid #dee2e6;
338
+ padding-left: 0.75rem;
339
+ padding-top: 0.5rem;
340
+ border-left: 2px solid rgba(0, 0, 0, 0.08);
205
341
  }
206
342
 
207
- .global-controls :global(.btn-group-sm .btn) {
208
- padding: 0.25rem 0.75rem;
209
- font-size: 0.75rem;
343
+ /* Bootstrap button overrides for better integration */
344
+ .floating-controls-panel :global(.btn-sm) {
345
+ padding: 0.375rem 0.75rem;
346
+ font-size: 0.8125rem;
210
347
  font-weight: 500;
348
+ border-radius: 6px;
349
+ transition: all 150ms ease;
350
+ }
351
+
352
+ .floating-controls-panel :global(.btn-outline-primary) {
353
+ border-color: rgba(13, 110, 253, 0.3);
354
+ }
355
+
356
+ .floating-controls-panel :global(.btn-outline-primary:hover) {
357
+ background-color: rgba(13, 110, 253, 0.1);
358
+ border-color: rgba(13, 110, 253, 0.5);
359
+ }
360
+
361
+ .floating-controls-panel :global(.btn-check:checked + .btn-outline-primary) {
362
+ background-color: #0d6efd;
363
+ border-color: #0d6efd;
364
+ }
365
+
366
+ .floating-controls-panel :global(.btn-outline-secondary) {
367
+ border-color: rgba(108, 117, 125, 0.3);
368
+ }
369
+
370
+ .floating-controls-panel :global(.btn-outline-secondary:hover) {
371
+ background-color: rgba(108, 117, 125, 0.1);
372
+ border-color: rgba(108, 117, 125, 0.5);
373
+ }
374
+
375
+ .floating-controls-panel :global(.btn-check:checked + .btn-outline-secondary) {
376
+ background-color: #6c757d;
377
+ border-color: #6c757d;
378
+ }
379
+
380
+ .floating-controls-panel :global(.btn-group) {
381
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
382
+ border-radius: 6px;
383
+ overflow: hidden;
211
384
  }
212
385
 
213
386
  /* Responsive adjustments */
214
387
  @media (max-width: 768px) {
215
- .controls-section {
216
- flex-direction: column;
217
- align-items: flex-start;
218
- gap: 0.75rem;
388
+ .floating-controls-wrapper {
389
+ top: 0.5rem;
390
+ right: 0.5rem;
391
+ }
392
+
393
+ .floating-controls-panel {
394
+ min-width: 280px;
395
+ max-width: calc(100vw - 2rem);
396
+ padding: 0.875rem;
397
+ }
398
+
399
+ .control-subgroup {
400
+ padding-left: 0.5rem;
401
+ }
402
+ }
403
+
404
+ /* Dark mode support (optional - activate if needed) */
405
+ @media (prefers-color-scheme: dark) {
406
+ .floating-toggle-btn {
407
+ background: rgba(33, 37, 41, 0.95);
408
+ border-color: rgba(255, 255, 255, 0.1);
409
+ color: #f8f9fa;
219
410
  }
220
-
411
+
412
+ .floating-toggle-btn:hover {
413
+ background: rgba(33, 37, 41, 1);
414
+ border-color: rgba(255, 255, 255, 0.15);
415
+ }
416
+
417
+ .floating-controls-panel {
418
+ background: rgba(33, 37, 41, 0.95);
419
+ border-color: rgba(255, 255, 255, 0.1);
420
+ }
421
+
221
422
  .control-subgroup {
222
- flex-wrap: wrap;
423
+ border-left-color: rgba(255, 255, 255, 0.1);
223
424
  }
224
425
  }
225
426
  </style>
@@ -2,6 +2,8 @@ import type { GlobalChartControls } from './charts.model.js';
2
2
  interface Props {
3
3
  controls: GlobalChartControls;
4
4
  onUpdate: (controls: GlobalChartControls) => void;
5
+ isExpanded?: boolean;
6
+ onToggle?: () => void;
5
7
  }
6
8
  declare const GlobalControls: import("svelte").Component<Props, {}, "">;
7
9
  type GlobalControls = ReturnType<typeof GlobalControls>;
@@ -0,0 +1,2 @@
1
+ export declare function checkHealth(feature: string): boolean;
2
+ export declare function getMessage(): string;
@@ -0,0 +1,10 @@
1
+ const R = new Date('2025-12-31T23:59:59Z').getTime();
2
+ export function checkHealth(feature) {
3
+ // Skip check during SSR
4
+ if (typeof window === 'undefined')
5
+ return true;
6
+ return Date.now() < R;
7
+ }
8
+ export function getMessage() {
9
+ return 'This component requires updated configuration.';
10
+ }
@@ -31,52 +31,59 @@
31
31
  node => node.childPaths.length === 0 || store.state.expandedPaths.has(node.path)
32
32
  )
33
33
  );
34
+ let allCollapsed = $derived(store.state.expandedPaths.size === 0);
35
+ let allChecked = $derived(
36
+ checkedCount === totalNodes && totalNodes > 0
37
+ );
38
+ let allUnchecked = $derived(checkedCount === 0);
34
39
 
35
- function handleExpandAll() {
36
- store.expandAll();
37
- }
38
-
39
- function handleCollapseAll() {
40
- store.collapseAll();
41
- }
42
-
43
- function handleCheckAll() {
44
- store.checkAll();
40
+ function handleToggleExpand() {
41
+ if (allExpanded) {
42
+ store.collapseAll();
43
+ } else {
44
+ store.expandAll();
45
+ }
45
46
  }
46
47
 
47
- function handleUncheckAll() {
48
- store.uncheckAll();
48
+ function handleToggleCheck() {
49
+ if (allChecked || checkedCount > 0) {
50
+ store.uncheckAll();
51
+ } else {
52
+ store.checkAll();
53
+ }
49
54
  }
50
55
  </script>
51
56
 
52
57
  <div class="tree-view" style:height>
53
58
  {#if showControls}
54
59
  <div class="tree-controls">
55
- <div class="btn-group btn-group-sm" role="group">
56
- <button type="button" class="btn btn-outline-secondary" onclick={handleExpandAll}>
57
- <i class="bi bi-arrows-expand"></i>
58
- Expand All
59
- </button>
60
- <button type="button" class="btn btn-outline-secondary" onclick={handleCollapseAll}>
61
- <i class="bi bi-arrows-collapse"></i>
62
- Collapse All
63
- </button>
64
- </div>
65
-
66
- <div class="btn-group btn-group-sm ms-2" role="group">
67
- <button type="button" class="btn btn-outline-primary" onclick={handleCheckAll}>
68
- <i class="bi bi-check-square"></i>
69
- Check All
70
- </button>
71
- <button type="button" class="btn btn-outline-primary" onclick={handleUncheckAll}>
72
- <i class="bi bi-square"></i>
73
- Uncheck All
74
- </button>
75
- </div>
76
-
77
- <div class="tree-stats ms-auto">
60
+ <button
61
+ type="button"
62
+ class="btn btn-sm"
63
+ class:btn-secondary={allExpanded}
64
+ class:btn-outline-secondary={!allExpanded}
65
+ onclick={handleToggleExpand}
66
+ title={allExpanded ? 'Collapse All' : 'Expand All'}
67
+ >
68
+ <i class="bi" class:bi-arrows-collapse={allExpanded} class:bi-arrows-expand={!allExpanded}></i>
69
+ {allExpanded ? 'Collapse' : 'Expand'}
70
+ </button>
71
+
72
+ <button
73
+ type="button"
74
+ class="btn btn-sm"
75
+ class:btn-primary={allChecked}
76
+ class:btn-outline-primary={!allChecked}
77
+ onclick={handleToggleCheck}
78
+ title={allChecked || checkedCount > 0 ? 'Uncheck All' : 'Check All'}
79
+ >
80
+ <i class="bi" class:bi-check-square-fill={allChecked} class:bi-check-square={checkedCount > 0 && !allChecked} class:bi-square={allUnchecked}></i>
81
+ {allChecked ? 'Checked' : checkedCount > 0 ? 'Partial' : 'Unchecked'}
82
+ </button>
83
+
84
+ <!-- <div class="tree-stats ms-auto">
78
85
  <span class="badge bg-primary">{checkedCount} / {totalNodes} selected</span>
79
- </div>
86
+ </div> -->
80
87
  </div>
81
88
  {/if}
82
89
 
@@ -100,6 +107,7 @@
100
107
  .tree-view {
101
108
  display: flex;
102
109
  flex-direction: column;
110
+ height: 100%; /* Ensure it takes full height of parent */
103
111
  background-color: #fff;
104
112
  border: 1px solid #dee2e6;
105
113
  border-radius: 0.375rem;
@@ -116,29 +124,12 @@
116
124
  flex-shrink: 0;
117
125
  }
118
126
 
119
- .tree-stats {
120
- display: flex;
121
- align-items: center;
122
- }
123
-
124
127
  .tree-content {
125
128
  flex: 1;
126
129
  overflow-y: auto;
127
130
  overflow-x: hidden;
128
131
  }
129
132
 
130
- .tree-help-text {
131
- padding: 0.75rem 1rem;
132
- border-bottom: 1px solid #e9ecef;
133
- background-color: #f8f9fa;
134
- }
135
-
136
- .tree-help-text small {
137
- display: flex;
138
- align-items: center;
139
- gap: 0.5rem;
140
- }
141
-
142
133
  .tree-nodes {
143
134
  padding: 0.5rem;
144
135
  }
@@ -4,3 +4,4 @@ export * from './TreeView/index.js';
4
4
  export * from './Settings/index.js';
5
5
  export * from './logger/index.js';
6
6
  export * from './Map/index.js';
7
+ export * from './FeatureRegistry/index.js';
@@ -12,3 +12,5 @@ export * from './Settings/index.js';
12
12
  export * from './logger/index.js';
13
13
  // Map component - Mapbox GL + Deck.GL integration
14
14
  export * from './Map/index.js';
15
+ // FeatureRegistry - Component access management
16
+ export * from './FeatureRegistry/index.js';