@happyvertical/smrt-svelte 0.37.9 → 0.37.10

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 (86) hide show
  1. package/AGENTS.md +21 -85
  2. package/README.md +14 -10
  3. package/dist/components/workspace/MIGRATION.md +55 -0
  4. package/dist/components/workspace/README.md +22 -25
  5. package/dist/components/workspace/__tests__/AdminShell.test.js +55 -0
  6. package/dist/components/workspace/__tests__/admin-shell-hotkeys.test.js +34 -0
  7. package/dist/components/workspace/__tests__/admin-shell-settings.test.js +25 -0
  8. package/dist/components/workspace/__tests__/admin-shell-state.test.js +110 -0
  9. package/dist/components/workspace/__tests__/index.test.js +15 -24
  10. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +2 -1
  11. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +1 -1
  12. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +1 -1
  13. package/dist/components/workspace/admin-shell/ActivityBadge.svelte +25 -0
  14. package/dist/components/workspace/admin-shell/ActivityBadge.svelte.d.ts +9 -0
  15. package/dist/components/workspace/admin-shell/ActivityBadge.svelte.d.ts.map +1 -0
  16. package/dist/components/workspace/admin-shell/ActivityItem.svelte +85 -0
  17. package/dist/components/workspace/admin-shell/ActivityItem.svelte.d.ts +8 -0
  18. package/dist/components/workspace/admin-shell/ActivityItem.svelte.d.ts.map +1 -0
  19. package/dist/components/workspace/admin-shell/ActivityList.svelte +41 -0
  20. package/dist/components/workspace/admin-shell/ActivityList.svelte.d.ts +10 -0
  21. package/dist/components/workspace/admin-shell/ActivityList.svelte.d.ts.map +1 -0
  22. package/dist/components/workspace/admin-shell/ActivityToasts.svelte +140 -0
  23. package/dist/components/workspace/admin-shell/ActivityToasts.svelte.d.ts +16 -0
  24. package/dist/components/workspace/admin-shell/ActivityToasts.svelte.d.ts.map +1 -0
  25. package/dist/components/workspace/admin-shell/AdminShell.svelte +691 -0
  26. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +24 -0
  27. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -0
  28. package/dist/components/workspace/admin-shell/AppScopePanel.svelte +94 -0
  29. package/dist/components/workspace/admin-shell/AppScopePanel.svelte.d.ts +14 -0
  30. package/dist/components/workspace/admin-shell/AppScopePanel.svelte.d.ts.map +1 -0
  31. package/dist/components/workspace/admin-shell/HotkeyInput.svelte +74 -0
  32. package/dist/components/workspace/admin-shell/HotkeyInput.svelte.d.ts +11 -0
  33. package/dist/components/workspace/admin-shell/HotkeyInput.svelte.d.ts.map +1 -0
  34. package/dist/components/workspace/admin-shell/ShellCorner.svelte +25 -0
  35. package/dist/components/workspace/admin-shell/ShellCorner.svelte.d.ts +9 -0
  36. package/dist/components/workspace/admin-shell/ShellCorner.svelte.d.ts.map +1 -0
  37. package/dist/components/workspace/admin-shell/ShellDockTool.svelte +19 -0
  38. package/dist/components/workspace/admin-shell/ShellDockTool.svelte.d.ts +7 -0
  39. package/dist/components/workspace/admin-shell/ShellDockTool.svelte.d.ts.map +1 -0
  40. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte +146 -0
  41. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts +4 -0
  42. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts.map +1 -0
  43. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte +81 -0
  44. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte.d.ts +7 -0
  45. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte.d.ts.map +1 -0
  46. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte +118 -0
  47. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte.d.ts +9 -0
  48. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte.d.ts.map +1 -0
  49. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte +71 -0
  50. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte.d.ts +8 -0
  51. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte.d.ts.map +1 -0
  52. package/dist/components/workspace/admin-shell/TenantNav.svelte +101 -0
  53. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +10 -0
  54. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -0
  55. package/dist/components/workspace/admin-shell/context.d.ts +6 -0
  56. package/dist/components/workspace/admin-shell/context.d.ts.map +1 -0
  57. package/dist/components/workspace/admin-shell/context.js +16 -0
  58. package/dist/components/workspace/admin-shell/hotkeys.d.ts +14 -0
  59. package/dist/components/workspace/admin-shell/hotkeys.d.ts.map +1 -0
  60. package/dist/components/workspace/admin-shell/hotkeys.js +62 -0
  61. package/dist/components/workspace/admin-shell/settings.d.ts +14 -0
  62. package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -0
  63. package/dist/components/workspace/admin-shell/settings.js +139 -0
  64. package/dist/components/workspace/admin-shell/state.svelte.d.ts +47 -0
  65. package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -0
  66. package/dist/components/workspace/admin-shell/state.svelte.js +252 -0
  67. package/dist/components/workspace/admin-shell/types.d.ts +137 -0
  68. package/dist/components/workspace/admin-shell/types.d.ts.map +1 -0
  69. package/dist/components/workspace/admin-shell/types.js +13 -0
  70. package/dist/components/workspace/index.d.ts +25 -11
  71. package/dist/components/workspace/index.d.ts.map +1 -1
  72. package/dist/components/workspace/index.js +24 -10
  73. package/dist/i18n/strings.workspace.d.ts +30 -0
  74. package/dist/i18n/strings.workspace.d.ts.map +1 -1
  75. package/dist/i18n/strings.workspace.js +31 -0
  76. package/dist/web/__tests__/harness.svelte +25 -0
  77. package/dist/web/__tests__/harness.svelte.d.ts +15 -0
  78. package/dist/web/__tests__/harness.svelte.d.ts.map +1 -0
  79. package/dist/web/__tests__/live-collection.svelte.test.js +184 -0
  80. package/dist/web/index.d.ts +13 -0
  81. package/dist/web/index.d.ts.map +1 -0
  82. package/dist/web/index.js +12 -0
  83. package/dist/web/live-collection.svelte.d.ts +132 -0
  84. package/dist/web/live-collection.svelte.d.ts.map +1 -0
  85. package/dist/web/live-collection.svelte.js +173 -0
  86. package/package.json +13 -4
@@ -0,0 +1,691 @@
1
+ <script lang="ts" module>
2
+ import type { ShellState as ModuleShellState } from './state.svelte.js';
3
+ import type { PanelEdge as ModulePanelEdge } from './types.js';
4
+
5
+ function trackFor(shell: ModuleShellState, edge: ModulePanelEdge): string {
6
+ const state = shell.panels[edge];
7
+ const config = shell.config.panels[edge];
8
+ if (state === 'hidden') return '0rem';
9
+ if (state === 'collapsed') return config.collapsedSize;
10
+ if (config.presentation === 'overlay') return config.collapsedSize;
11
+ return config.expandedSize;
12
+ }
13
+
14
+ function expandedSize(shell: ModuleShellState, edge: ModulePanelEdge): string {
15
+ return shell.config.panels[edge].expandedSize;
16
+ }
17
+
18
+ function buildLayoutStyle(shell: ModuleShellState): string {
19
+ return [
20
+ `--smrt-admin-shell-left-track: ${trackFor(shell, 'left')}`,
21
+ `--smrt-admin-shell-right-track: ${trackFor(shell, 'right')}`,
22
+ `--smrt-admin-shell-top-track: ${trackFor(shell, 'top')}`,
23
+ `--smrt-admin-shell-bottom-track: ${trackFor(shell, 'bottom')}`,
24
+ `--smrt-admin-shell-left-expanded: ${expandedSize(shell, 'left')}`,
25
+ `--smrt-admin-shell-right-expanded: ${expandedSize(shell, 'right')}`,
26
+ `--smrt-admin-shell-top-expanded: ${expandedSize(shell, 'top')}`,
27
+ `--smrt-admin-shell-bottom-expanded: ${expandedSize(shell, 'bottom')}`,
28
+ ].join('; ');
29
+ }
30
+ </script>
31
+
32
+ <script lang="ts">
33
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
34
+ import { Button } from '@happyvertical/smrt-ui/ui';
35
+ import { onMount, untrack } from 'svelte';
36
+ import type { Snippet } from 'svelte';
37
+ import { M } from '../../../i18n/strings.workspace.js';
38
+ import ActivityBadge from './ActivityBadge.svelte';
39
+ import { setAdminShell } from './context.js';
40
+ import {
41
+ formatHotkeyBinding,
42
+ shellActionFromKeyboardEvent,
43
+ } from './hotkeys.js';
44
+ import { resolveHotkey } from './settings.js';
45
+ import { createShellState, type ShellState } from './state.svelte.js';
46
+ import type {
47
+ AdminShellProps,
48
+ PanelEdge,
49
+ ShellFocusTool,
50
+ } from './types.js';
51
+
52
+ interface Props extends AdminShellProps {
53
+ state?: ShellState;
54
+ appBar?: Snippet;
55
+ appPanel?: Snippet;
56
+ tenantRail?: Snippet;
57
+ tenantPanel?: Snippet;
58
+ focusRail?: Snippet;
59
+ focusPanel?: Snippet;
60
+ systemBar?: Snippet;
61
+ systemPanel?: Snippet;
62
+ topLeftCorner?: Snippet;
63
+ topRightCorner?: Snippet;
64
+ bottomLeftCorner?: Snippet;
65
+ bottomRightCorner?: Snippet;
66
+ shortcutsOverlay?: Snippet;
67
+ children: Snippet;
68
+ }
69
+
70
+ let {
71
+ title = 'SMRT',
72
+ subtitle = '',
73
+ config,
74
+ settings,
75
+ settingsAdapter,
76
+ storageKey = 'smrt-admin-shell',
77
+ state: providedState,
78
+ appBar,
79
+ appPanel,
80
+ tenantRail,
81
+ tenantPanel,
82
+ focusRail,
83
+ focusPanel,
84
+ systemBar,
85
+ systemPanel,
86
+ topLeftCorner,
87
+ topRightCorner,
88
+ bottomLeftCorner,
89
+ bottomRightCorner,
90
+ shortcutsOverlay,
91
+ children,
92
+ }: Props = $props();
93
+
94
+ const { t } = useI18n();
95
+ const shell = untrack(
96
+ () =>
97
+ providedState ??
98
+ createShellState({
99
+ config,
100
+ settings,
101
+ settingsAdapter,
102
+ storageKey,
103
+ }),
104
+ );
105
+ setAdminShell(shell);
106
+
107
+ let shortcutsOpen = $state(false);
108
+ const activeFocusTool = $derived(
109
+ shell.focusTools.find((tool) => tool.id === shell.activeFocusToolId) ??
110
+ shell.focusTools[0] ??
111
+ null,
112
+ );
113
+ const shortcutEdges: PanelEdge[] = ['top', 'left', 'bottom', 'right'];
114
+
115
+ onMount(() => {
116
+ void shell.hydrate();
117
+
118
+ function handleKeydown(event: KeyboardEvent): void {
119
+ if (event.key === 'Escape') {
120
+ if (shortcutsOpen) {
121
+ shortcutsOpen = false;
122
+ event.preventDefault();
123
+ return;
124
+ }
125
+ if (shell.closeTopmostExpanded()) event.preventDefault();
126
+ return;
127
+ }
128
+
129
+ const action = shellActionFromKeyboardEvent(
130
+ event,
131
+ shell.config.panels,
132
+ shell.settings,
133
+ );
134
+ if (!action) return;
135
+ event.preventDefault();
136
+ if (action.type === 'show-shortcuts') {
137
+ shortcutsOpen = true;
138
+ } else {
139
+ shell.togglePanel(action.edge);
140
+ }
141
+ }
142
+
143
+ window.addEventListener('keydown', handleKeydown);
144
+ return () => window.removeEventListener('keydown', handleKeydown);
145
+ });
146
+
147
+ const layoutStyle = $derived(buildLayoutStyle(shell));
148
+
149
+ function panelState(edge: PanelEdge) {
150
+ return shell.panels[edge];
151
+ }
152
+
153
+ function edgeExpanded(edge: PanelEdge): boolean {
154
+ return panelState(edge) === 'expanded';
155
+ }
156
+
157
+ function labelFor(edge: PanelEdge): string {
158
+ return shell.config.panels[edge].label;
159
+ }
160
+
161
+ function hotkeyFor(edge: PanelEdge): string {
162
+ return formatHotkeyBinding(
163
+ resolveHotkey(edge, shell.config.panels[edge], shell.settings),
164
+ );
165
+ }
166
+
167
+ // Focus containment for the modal shortcuts dialog. Runs on mount of the
168
+ // dialog node and tears down when it unmounts (Escape / close), restoring
169
+ // focus to whatever opened it. Keeps `aria-modal="true"` honest.
170
+ function focusTrap(node: HTMLElement) {
171
+ const previouslyFocused =
172
+ document.activeElement instanceof HTMLElement
173
+ ? document.activeElement
174
+ : null;
175
+ const selector =
176
+ 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
177
+ const focusable = (): HTMLElement[] =>
178
+ Array.from(node.querySelectorAll<HTMLElement>(selector)).filter(
179
+ (el) => el.offsetParent !== null,
180
+ );
181
+ (focusable()[0] ?? node).focus();
182
+
183
+ function onKeydown(event: KeyboardEvent): void {
184
+ if (event.key !== 'Tab') return;
185
+ const items = focusable();
186
+ if (items.length === 0) {
187
+ event.preventDefault();
188
+ node.focus();
189
+ return;
190
+ }
191
+ const first = items[0];
192
+ const last = items[items.length - 1];
193
+ if (event.shiftKey && document.activeElement === first) {
194
+ event.preventDefault();
195
+ last.focus();
196
+ } else if (!event.shiftKey && document.activeElement === last) {
197
+ event.preventDefault();
198
+ first.focus();
199
+ }
200
+ }
201
+
202
+ node.addEventListener('keydown', onKeydown);
203
+ return {
204
+ destroy(): void {
205
+ node.removeEventListener('keydown', onKeydown);
206
+ previouslyFocused?.focus();
207
+ },
208
+ };
209
+ }
210
+ </script>
211
+
212
+ {#snippet edgeToggle(edge: PanelEdge)}
213
+ <Button
214
+ variant="ghost"
215
+ size="sm"
216
+ class="smrt-admin-shell__edge-toggle"
217
+ aria-expanded={edgeExpanded(edge)}
218
+ aria-controls={`smrt-admin-shell-${edge}-panel`}
219
+ onclick={() => shell.togglePanel(edge)}
220
+ >
221
+ <span>{labelFor(edge)}</span>
222
+ <kbd class="smrt-admin-shell__edge-toggle-kbd">{hotkeyFor(edge)}</kbd>
223
+ <ActivityBadge {edge} />
224
+ </Button>
225
+ {/snippet}
226
+
227
+ {#snippet focusContent(tool: ShellFocusTool | null)}
228
+ {#if focusPanel}
229
+ {@render focusPanel()}
230
+ {:else if tool?.render}
231
+ {@render tool.render({ tool })}
232
+ {:else if tool?.component}
233
+ {@const FocusComponent = tool.component}
234
+ <FocusComponent {tool} {shell} />
235
+ {:else}
236
+ <p class="smrt-admin-shell__empty">
237
+ {t(M['ui.admin_shell.no_focus_tools'])}
238
+ </p>
239
+ {/if}
240
+ {/snippet}
241
+
242
+ <div
243
+ class="smrt-admin-shell"
244
+ data-top-state={panelState('top')}
245
+ data-left-state={panelState('left')}
246
+ data-right-state={panelState('right')}
247
+ data-bottom-state={panelState('bottom')}
248
+ style={layoutStyle}
249
+ >
250
+ {#if panelState('top') !== 'hidden'}
251
+ <header
252
+ id="smrt-admin-shell-top-panel"
253
+ class="smrt-admin-shell__edge smrt-admin-shell__edge--top"
254
+ data-state={panelState('top')}
255
+ data-presentation={shell.config.panels.top.presentation}
256
+ >
257
+ {#if topLeftCorner}
258
+ <div class="smrt-admin-shell__corner smrt-admin-shell__corner--top-left">
259
+ {@render topLeftCorner()}
260
+ </div>
261
+ {/if}
262
+ <div class="smrt-admin-shell__band smrt-admin-shell__band--top">
263
+ {#if appBar}
264
+ {@render appBar()}
265
+ {:else}
266
+ <div class="smrt-admin-shell__brand">
267
+ <strong>{title}</strong>
268
+ {#if subtitle}
269
+ <span>{subtitle}</span>
270
+ {/if}
271
+ </div>
272
+ {@render edgeToggle('top')}
273
+ {/if}
274
+ </div>
275
+ {#if topRightCorner}
276
+ <div class="smrt-admin-shell__corner smrt-admin-shell__corner--top-right">
277
+ {@render topRightCorner()}
278
+ </div>
279
+ {/if}
280
+ {#if edgeExpanded('top')}
281
+ <section
282
+ class="smrt-admin-shell__drawer smrt-admin-shell__drawer--top"
283
+ aria-label={labelFor('top')}
284
+ >
285
+ {#if appPanel}
286
+ {@render appPanel()}
287
+ {:else}
288
+ <p class="smrt-admin-shell__empty">
289
+ {t(M['ui.admin_shell.no_app_panel'])}
290
+ </p>
291
+ {/if}
292
+ </section>
293
+ {/if}
294
+ </header>
295
+ {/if}
296
+
297
+ {#if panelState('left') !== 'hidden'}
298
+ <aside
299
+ id="smrt-admin-shell-left-panel"
300
+ class="smrt-admin-shell__edge smrt-admin-shell__edge--left"
301
+ data-state={panelState('left')}
302
+ data-presentation={shell.config.panels.left.presentation}
303
+ role="navigation"
304
+ aria-label={labelFor('left')}
305
+ >
306
+ <div class="smrt-admin-shell__rail">
307
+ {#if edgeExpanded('left')}
308
+ {#if tenantPanel}
309
+ {@render tenantPanel()}
310
+ {:else if tenantRail}
311
+ {@render tenantRail()}
312
+ {:else}
313
+ {@render edgeToggle('left')}
314
+ {/if}
315
+ {:else if tenantRail}
316
+ {@render tenantRail()}
317
+ {:else}
318
+ {@render edgeToggle('left')}
319
+ {/if}
320
+ </div>
321
+ </aside>
322
+ {/if}
323
+
324
+ <main class="smrt-admin-shell__main">
325
+ {@render children()}
326
+ </main>
327
+
328
+ {#if panelState('right') !== 'hidden'}
329
+ <aside
330
+ id="smrt-admin-shell-right-panel"
331
+ class="smrt-admin-shell__edge smrt-admin-shell__edge--right"
332
+ data-state={panelState('right')}
333
+ data-presentation={shell.config.panels.right.presentation}
334
+ aria-label={labelFor('right')}
335
+ >
336
+ <div class="smrt-admin-shell__rail">
337
+ {#if edgeExpanded('right')}
338
+ {@render focusContent(activeFocusTool)}
339
+ {:else if focusRail}
340
+ {@render focusRail()}
341
+ {:else}
342
+ {@render edgeToggle('right')}
343
+ {/if}
344
+ </div>
345
+ </aside>
346
+ {/if}
347
+
348
+ {#if panelState('bottom') !== 'hidden'}
349
+ <footer
350
+ id="smrt-admin-shell-bottom-panel"
351
+ class="smrt-admin-shell__edge smrt-admin-shell__edge--bottom"
352
+ data-state={panelState('bottom')}
353
+ data-presentation={shell.config.panels.bottom.presentation}
354
+ >
355
+ {#if bottomLeftCorner}
356
+ <div class="smrt-admin-shell__corner smrt-admin-shell__corner--bottom-left">
357
+ {@render bottomLeftCorner()}
358
+ </div>
359
+ {/if}
360
+ <div class="smrt-admin-shell__band smrt-admin-shell__band--bottom">
361
+ {#if systemBar}
362
+ {@render systemBar()}
363
+ {:else}
364
+ {@render edgeToggle('bottom')}
365
+ {/if}
366
+ </div>
367
+ {#if bottomRightCorner}
368
+ <div class="smrt-admin-shell__corner smrt-admin-shell__corner--bottom-right">
369
+ {@render bottomRightCorner()}
370
+ </div>
371
+ {/if}
372
+ {#if edgeExpanded('bottom')}
373
+ <section
374
+ class="smrt-admin-shell__drawer smrt-admin-shell__drawer--bottom"
375
+ aria-label={labelFor('bottom')}
376
+ >
377
+ {#if systemPanel}
378
+ {@render systemPanel()}
379
+ {:else}
380
+ <p class="smrt-admin-shell__empty">
381
+ {t(M['ui.admin_shell.no_system_panel'])}
382
+ </p>
383
+ {/if}
384
+ </section>
385
+ {/if}
386
+ </footer>
387
+ {/if}
388
+
389
+ {#if shortcutsOpen}
390
+ <div
391
+ class="smrt-admin-shell__shortcuts"
392
+ role="dialog"
393
+ aria-modal="true"
394
+ aria-label={t(M['ui.admin_shell.shell_shortcuts'])}
395
+ tabindex="-1"
396
+ use:focusTrap
397
+ >
398
+ <div class="smrt-admin-shell__shortcuts-panel">
399
+ {#if shortcutsOverlay}
400
+ {@render shortcutsOverlay()}
401
+ {:else}
402
+ <header>
403
+ <h2>{t(M['ui.admin_shell.shell_shortcuts'])}</h2>
404
+ <Button
405
+ variant="ghost"
406
+ size="sm"
407
+ aria-label={t(M['ui.admin_shell.close_shortcuts'])}
408
+ onclick={() => (shortcutsOpen = false)}
409
+ >
410
+ {t(M['ui.admin_shell.close'])}
411
+ </Button>
412
+ </header>
413
+ <dl>
414
+ {#each shortcutEdges as edge}
415
+ <div>
416
+ <dt>{labelFor(edge)}</dt>
417
+ <dd>{hotkeyFor(edge)}</dd>
418
+ </div>
419
+ {/each}
420
+ <div>
421
+ <dt>{t(M['ui.admin_shell.shortcuts'])}</dt>
422
+ <dd>?</dd>
423
+ </div>
424
+ </dl>
425
+ {/if}
426
+ </div>
427
+ </div>
428
+ {/if}
429
+ </div>
430
+
431
+ <style>
432
+ .smrt-admin-shell {
433
+ --smrt-admin-shell-left-track: 0rem;
434
+ --smrt-admin-shell-right-track: 0rem;
435
+ --smrt-admin-shell-top-track: 0rem;
436
+ --smrt-admin-shell-bottom-track: 0rem;
437
+ --smrt-admin-shell-left-collapsed: 4.25rem;
438
+ --smrt-admin-shell-right-collapsed: 4.25rem;
439
+ --smrt-admin-shell-left-expanded: 16rem;
440
+ --smrt-admin-shell-right-expanded: 20rem;
441
+ position: relative;
442
+ display: grid;
443
+ grid-template-columns:
444
+ var(--smrt-admin-shell-left-track) minmax(0, 1fr)
445
+ var(--smrt-admin-shell-right-track);
446
+ grid-template-rows:
447
+ var(--smrt-admin-shell-top-track) minmax(0, 1fr)
448
+ var(--smrt-admin-shell-bottom-track);
449
+ min-block-size: 100svh;
450
+ background: var(--smrt-color-surface);
451
+ color: var(--smrt-color-on-surface);
452
+ overflow: hidden;
453
+ }
454
+
455
+ .smrt-admin-shell__edge {
456
+ min-width: 0;
457
+ min-height: 0;
458
+ background: var(--smrt-color-surface-container-low);
459
+ color: var(--smrt-color-on-surface);
460
+ border-color: var(--smrt-color-outline-variant);
461
+ }
462
+
463
+ .smrt-admin-shell__edge--top {
464
+ grid-column: 1 / -1;
465
+ grid-row: 1;
466
+ display: grid;
467
+ grid-template-columns:
468
+ var(--smrt-admin-shell-left-track) minmax(0, 1fr)
469
+ var(--smrt-admin-shell-right-track);
470
+ border-block-end: 1px solid var(--smrt-color-outline-variant);
471
+ z-index: 30;
472
+ }
473
+
474
+ .smrt-admin-shell__edge--left {
475
+ grid-column: 1;
476
+ grid-row: 2;
477
+ border-inline-end: 1px solid var(--smrt-color-outline-variant);
478
+ z-index: 20;
479
+ }
480
+
481
+ .smrt-admin-shell__edge--right {
482
+ grid-column: 3;
483
+ grid-row: 2;
484
+ border-inline-start: 1px solid var(--smrt-color-outline-variant);
485
+ z-index: 20;
486
+ }
487
+
488
+ .smrt-admin-shell__edge--bottom {
489
+ grid-column: 1 / -1;
490
+ grid-row: 3;
491
+ display: grid;
492
+ grid-template-columns:
493
+ var(--smrt-admin-shell-left-track) minmax(0, 1fr)
494
+ var(--smrt-admin-shell-right-track);
495
+ border-block-start: 1px solid var(--smrt-color-outline-variant);
496
+ z-index: 30;
497
+ }
498
+
499
+ .smrt-admin-shell__main {
500
+ grid-column: 2;
501
+ grid-row: 2;
502
+ min-width: 0;
503
+ min-height: 0;
504
+ overflow: auto;
505
+ background: var(--smrt-color-surface);
506
+ }
507
+
508
+ .smrt-admin-shell__band {
509
+ display: flex;
510
+ align-items: center;
511
+ justify-content: space-between;
512
+ gap: var(--smrt-spacing-3);
513
+ min-width: 0;
514
+ padding: 0 var(--smrt-spacing-4);
515
+ }
516
+
517
+ .smrt-admin-shell__band--top,
518
+ .smrt-admin-shell__band--bottom {
519
+ grid-column: 2;
520
+ }
521
+
522
+ .smrt-admin-shell__brand {
523
+ display: grid;
524
+ min-width: 0;
525
+ }
526
+
527
+ .smrt-admin-shell__brand strong,
528
+ .smrt-admin-shell__brand span {
529
+ overflow: hidden;
530
+ text-overflow: ellipsis;
531
+ white-space: nowrap;
532
+ }
533
+
534
+ .smrt-admin-shell__brand span,
535
+ .smrt-admin-shell__empty {
536
+ color: var(--smrt-color-on-surface-variant);
537
+ }
538
+
539
+ .smrt-admin-shell__rail {
540
+ min-width: 0;
541
+ min-height: 0;
542
+ block-size: 100%;
543
+ overflow: auto;
544
+ padding: var(--smrt-spacing-3);
545
+ }
546
+
547
+ .smrt-admin-shell__edge-toggle-kbd {
548
+ padding: 0 var(--smrt-spacing-1);
549
+ border-radius: var(--smrt-radius-small);
550
+ background: var(--smrt-color-surface-container-high);
551
+ color: var(--smrt-color-on-surface-variant);
552
+ font-size: var(--smrt-typography-body-small-size);
553
+ }
554
+
555
+ .smrt-admin-shell__drawer {
556
+ position: absolute;
557
+ z-index: 40;
558
+ overflow: auto;
559
+ padding: var(--smrt-spacing-5);
560
+ background: var(--smrt-color-surface-container);
561
+ color: var(--smrt-color-on-surface);
562
+ box-shadow: var(--smrt-elevation-3);
563
+ }
564
+
565
+ .smrt-admin-shell__drawer--top {
566
+ inset-block-start: var(--smrt-admin-shell-top-track);
567
+ inset-inline: var(--smrt-admin-shell-left-track)
568
+ var(--smrt-admin-shell-right-track);
569
+ max-block-size: var(--smrt-admin-shell-top-expanded);
570
+ }
571
+
572
+ .smrt-admin-shell__drawer--bottom {
573
+ inset-block-end: var(--smrt-admin-shell-bottom-track);
574
+ inset-inline: var(--smrt-admin-shell-left-track)
575
+ var(--smrt-admin-shell-right-track);
576
+ max-block-size: var(--smrt-admin-shell-bottom-expanded);
577
+ }
578
+
579
+ .smrt-admin-shell__corner {
580
+ display: grid;
581
+ align-items: center;
582
+ min-width: 0;
583
+ padding: 0 var(--smrt-spacing-3);
584
+ background: var(--smrt-color-surface-container-low);
585
+ }
586
+
587
+ .smrt-admin-shell__corner--top-left,
588
+ .smrt-admin-shell__corner--bottom-left {
589
+ grid-column: 1;
590
+ }
591
+
592
+ .smrt-admin-shell__corner--top-right,
593
+ .smrt-admin-shell__corner--bottom-right {
594
+ grid-column: 3;
595
+ }
596
+
597
+ .smrt-admin-shell__shortcuts {
598
+ position: fixed;
599
+ inset: 0;
600
+ z-index: var(--smrt-z-index-dialog, 1300);
601
+ display: grid;
602
+ place-items: center;
603
+ padding: var(--smrt-spacing-5);
604
+ background: var(--smrt-color-scrim);
605
+ }
606
+
607
+ .smrt-admin-shell__shortcuts-panel {
608
+ inline-size: min(32rem, 100%);
609
+ max-block-size: min(36rem, 100%);
610
+ overflow: auto;
611
+ border-radius: var(--smrt-radius-large);
612
+ background: var(--smrt-color-surface-container);
613
+ padding: var(--smrt-spacing-5);
614
+ box-shadow: var(--smrt-elevation-4);
615
+ }
616
+
617
+ .smrt-admin-shell__shortcuts-panel header,
618
+ .smrt-admin-shell__shortcuts-panel div {
619
+ display: flex;
620
+ align-items: center;
621
+ justify-content: space-between;
622
+ gap: var(--smrt-spacing-4);
623
+ }
624
+
625
+ .smrt-admin-shell__shortcuts-panel h2,
626
+ .smrt-admin-shell__shortcuts-panel dl {
627
+ margin: 0;
628
+ }
629
+
630
+ .smrt-admin-shell__shortcuts-panel dl {
631
+ display: grid;
632
+ gap: var(--smrt-spacing-3);
633
+ margin-block-start: var(--smrt-spacing-4);
634
+ }
635
+
636
+ .smrt-admin-shell__shortcuts-panel dd {
637
+ margin: 0;
638
+ font-family: var(--smrt-font-family-mono);
639
+ }
640
+
641
+ @media (max-width: 48rem) {
642
+ .smrt-admin-shell {
643
+ grid-template-columns: 0 minmax(0, 1fr) 0;
644
+ grid-template-rows:
645
+ var(--smrt-admin-shell-top-track) minmax(0, 1fr)
646
+ var(--smrt-admin-shell-bottom-track);
647
+ }
648
+
649
+ .smrt-admin-shell__edge--left,
650
+ .smrt-admin-shell__edge--right {
651
+ position: absolute;
652
+ inset-block: var(--smrt-admin-shell-top-track)
653
+ var(--smrt-admin-shell-bottom-track);
654
+ inline-size: min(22rem, 86vw);
655
+ transform: translateX(-100%);
656
+ transition: transform var(--smrt-duration-short2)
657
+ var(--smrt-easing-standard);
658
+ }
659
+
660
+ .smrt-admin-shell__edge--right {
661
+ inset-inline-end: 0;
662
+ transform: translateX(100%);
663
+ }
664
+
665
+ .smrt-admin-shell__edge--left[data-state='expanded'],
666
+ .smrt-admin-shell__edge--right[data-state='expanded'] {
667
+ transform: translateX(0);
668
+ }
669
+
670
+ .smrt-admin-shell__edge--top,
671
+ .smrt-admin-shell__edge--bottom {
672
+ grid-template-columns: minmax(0, 1fr);
673
+ }
674
+
675
+ .smrt-admin-shell__band--top,
676
+ .smrt-admin-shell__band--bottom {
677
+ grid-column: 1;
678
+ }
679
+
680
+ .smrt-admin-shell__corner {
681
+ display: none;
682
+ }
683
+ }
684
+
685
+ @media (prefers-reduced-motion: reduce) {
686
+ .smrt-admin-shell__edge--left,
687
+ .smrt-admin-shell__edge--right {
688
+ transition: none;
689
+ }
690
+ }
691
+ </style>
@@ -0,0 +1,24 @@
1
+ import type { Snippet } from 'svelte';
2
+ import { type ShellState } from './state.svelte.js';
3
+ import type { AdminShellProps } from './types.js';
4
+ interface Props extends AdminShellProps {
5
+ state?: ShellState;
6
+ appBar?: Snippet;
7
+ appPanel?: Snippet;
8
+ tenantRail?: Snippet;
9
+ tenantPanel?: Snippet;
10
+ focusRail?: Snippet;
11
+ focusPanel?: Snippet;
12
+ systemBar?: Snippet;
13
+ systemPanel?: Snippet;
14
+ topLeftCorner?: Snippet;
15
+ topRightCorner?: Snippet;
16
+ bottomLeftCorner?: Snippet;
17
+ bottomRightCorner?: Snippet;
18
+ shortcutsOverlay?: Snippet;
19
+ children: Snippet;
20
+ }
21
+ declare const AdminShell: import("svelte").Component<Props, {}, "">;
22
+ type AdminShell = ReturnType<typeof AdminShell>;
23
+ export default AdminShell;
24
+ //# sourceMappingURL=AdminShell.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminShell.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/AdminShell.svelte.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAStC,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EACR,eAAe,EAGhB,MAAM,YAAY,CAAC;AAGpB,UAAU,KAAM,SAAQ,eAAe;IACrC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAuUH,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}