@happyvertical/smrt-svelte 0.55.16 → 0.55.17
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/README.md +5 -3
- package/agents/cookbook-shell.md +7 -1
- package/agents/overview-surfaces.md +5 -0
- package/agents/workspace.md +145 -11
- package/dist/browser-ai/svelte/components/DownloadProgress.svelte +22 -19
- package/dist/browser-ai/svelte/components/ModelStatusControl.svelte +16 -13
- package/dist/browser-ai/svelte/components/STTTest.svelte +41 -38
- package/dist/browser-ai/svelte/components/VoiceInput.svelte +17 -14
- package/dist/components/activity/ActivityList.svelte +1 -1
- package/dist/components/app/AppShell.svelte +274 -9
- package/dist/components/app/AppShell.svelte.d.ts +63 -2
- package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
- package/dist/components/app/DockToggles.svelte +27 -1
- package/dist/components/app/DockToggles.svelte.d.ts.map +1 -1
- package/dist/components/app/OwnerSetupForm.svelte +98 -34
- package/dist/components/app/OwnerSetupForm.svelte.d.ts +4 -0
- package/dist/components/app/OwnerSetupForm.svelte.d.ts.map +1 -1
- package/dist/components/app/PhoneTabBar.svelte +136 -0
- package/dist/components/app/PhoneTabBar.svelte.d.ts +22 -0
- package/dist/components/app/PhoneTabBar.svelte.d.ts.map +1 -0
- package/dist/components/app/ShellSettingsPage.svelte +17 -2
- package/dist/components/app/ShellSettingsPage.svelte.d.ts +11 -16
- package/dist/components/app/ShellSettingsPage.svelte.d.ts.map +1 -1
- package/dist/components/app/dock-toggle.d.ts +3 -2
- package/dist/components/app/dock-toggle.d.ts.map +1 -1
- package/dist/components/app/index.d.ts +2 -1
- package/dist/components/app/index.d.ts.map +1 -1
- package/dist/components/app/index.js +1 -0
- package/dist/components/app/owner-setup-types.d.ts +5 -0
- package/dist/components/app/owner-setup-types.d.ts.map +1 -1
- package/dist/components/app/phone-tabs.d.ts +41 -0
- package/dist/components/app/phone-tabs.d.ts.map +1 -0
- package/dist/components/app/phone-tabs.js +66 -0
- package/dist/components/app/slot-item.d.ts +16 -0
- package/dist/components/app/slot-item.d.ts.map +1 -1
- package/dist/components/app/view-transition.d.ts +43 -0
- package/dist/components/app/view-transition.d.ts.map +1 -0
- package/dist/components/app/view-transition.js +76 -0
- package/dist/components/audit/AuditList.svelte +4 -1
- package/dist/components/audit/RecordHistory.svelte +4 -1
- package/dist/components/board/Board.svelte +4 -1
- package/dist/components/command-palette/CommandPalette.svelte +4 -1
- package/dist/components/command-palette/CommandPalette.svelte.d.ts +2 -0
- package/dist/components/command-palette/CommandPalette.svelte.d.ts.map +1 -1
- package/dist/components/command-palette/CommandPaletteDialog.svelte +3 -0
- package/dist/components/command-palette/CommandPaletteTrigger.svelte +3 -0
- package/dist/components/cookbook/CookbookApp.svelte +2 -1
- package/dist/components/cookbook/CookbookApp.svelte.d.ts.map +1 -1
- package/dist/components/cookbook/CookbookSectionPage.svelte +4 -1
- package/dist/components/cookbook/brand-theme.d.ts.map +1 -1
- package/dist/components/cookbook/brand-theme.js +21 -2
- package/dist/components/cookbook/build.js +1 -1
- package/dist/components/cookbook/theme.d.ts.map +1 -1
- package/dist/components/cookbook/theme.js +9 -5
- package/dist/components/cookbook/types.d.ts +5 -1
- package/dist/components/cookbook/types.d.ts.map +1 -1
- package/dist/components/forms/AddressInput.svelte +25 -22
- package/dist/components/forms/CheckboxInput.svelte +8 -5
- package/dist/components/forms/DateRangeInput.svelte +41 -38
- package/dist/components/forms/DateTimeInput.svelte +29 -26
- package/dist/components/forms/FileUpload.svelte +24 -21
- package/dist/components/forms/Form.svelte +34 -31
- package/dist/components/forms/FormMicButton.svelte +10 -7
- package/dist/components/forms/FormScope.svelte +4 -1
- package/dist/components/forms/MeasurementInput.svelte +26 -23
- package/dist/components/forms/MoneyInput.svelte +18 -15
- package/dist/components/forms/NumberInput.svelte +17 -14
- package/dist/components/forms/PhoneInput.svelte +37 -34
- package/dist/components/forms/SearchInput.svelte +16 -13
- package/dist/components/forms/SelectInput.svelte +17 -14
- package/dist/components/forms/TextInput.svelte +19 -16
- package/dist/components/forms/TextareaInput.svelte +21 -18
- package/dist/components/import-export/ImportExport.svelte +4 -1
- package/dist/components/module/ModulePanel.svelte +14 -11
- package/dist/components/notifications/NotificationBell.svelte +4 -1
- package/dist/components/overview/OverviewAssistantUndo.svelte +4 -1
- package/dist/components/overview/OverviewGrid.svelte +11 -6
- package/dist/components/overview/OverviewGrid.svelte.d.ts.map +1 -1
- package/dist/components/overview/WidgetOptionsForm.svelte +3 -0
- package/dist/components/overview/widgets/ChartWidget.svelte +7 -4
- package/dist/components/overview/widgets/MetricWidget.svelte +5 -2
- package/dist/components/overview/widgets/NoteWidget.svelte +5 -2
- package/dist/components/overview/widgets/RecordListWidget.svelte +6 -3
- package/dist/components/overview/widgets/ShortcutsWidget.svelte +12 -6
- package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts.map +1 -1
- package/dist/components/screens/DetailScreen.svelte +6 -3
- package/dist/components/screens/EditForm.svelte +6 -3
- package/dist/components/screens/ListScreen.svelte +4 -1
- package/dist/components/screens/RecipeScreens.svelte +1 -1
- package/dist/components/settings/SettingsCatalog.svelte +4 -1
- package/dist/components/sortable/Sortable.svelte +11 -5
- package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -1
- package/dist/components/workspace/Breadcrumbs.svelte +4 -1
- package/dist/components/workspace/NavTree.svelte +4 -1
- package/dist/components/workspace/RoleShell.svelte +4 -1
- package/dist/components/workspace/WorkspaceShell.svelte +43 -40
- package/dist/components/workspace/admin-shell/ActivityItem.svelte +4 -1
- package/dist/components/workspace/admin-shell/ActivityList.svelte +5 -2
- package/dist/components/workspace/admin-shell/ActivityTicker.svelte +6 -3
- package/dist/components/workspace/admin-shell/ActivityToasts.svelte +4 -1
- package/dist/components/workspace/admin-shell/AdminShell.svelte +502 -72
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +7 -1
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/AppScopePanel.svelte +4 -1
- package/dist/components/workspace/admin-shell/HotkeyInput.svelte +4 -1
- package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte +21 -8
- package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte.d.ts +9 -2
- package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/PhoneTopBar.svelte +4 -1
- package/dist/components/workspace/admin-shell/ShellBrand.svelte +3 -0
- package/dist/components/workspace/admin-shell/ShellCorner.svelte +4 -1
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte +4 -1
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +4 -1
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte +13 -7
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts +1 -1
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellNavToggle.svelte +4 -1
- package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte +4 -1
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte +15 -10
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte +236 -48
- package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts +11 -1
- package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellTitle.svelte +4 -1
- package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte +4 -1
- package/dist/components/workspace/admin-shell/SystemScopePanel.svelte +4 -1
- package/dist/components/workspace/admin-shell/SystemStatusChips.svelte +5 -2
- package/dist/components/workspace/admin-shell/TenantNav.svelte +81 -36
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +4 -3
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte +305 -53
- package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.d.ts +15 -2
- package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/motion.d.ts +19 -0
- package/dist/components/workspace/admin-shell/motion.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/motion.js +44 -0
- package/dist/components/workspace/admin-shell/settings.d.ts +1 -0
- package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/settings.js +1 -1
- package/dist/components/workspace/admin-shell/shell-icons.d.ts +8 -0
- package/dist/components/workspace/admin-shell/shell-icons.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/shell-icons.js +8 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts +6 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/state.svelte.js +15 -0
- package/dist/components/workspace/admin-shell/types.d.ts +13 -3
- package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
- package/dist/components/workspace/tools-dock/ToolsDock.svelte +41 -38
- package/dist/i18n/strings.workspace.d.ts +37 -0
- package/dist/i18n/strings.workspace.d.ts.map +1 -1
- package/dist/i18n/strings.workspace.js +42 -2
- package/dist/mcp-apps/McpAppsBridge.svelte +4 -1
- package/package.json +14 -14
|
@@ -51,6 +51,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
51
51
|
import { M } from '../../../i18n/strings.workspace.js';
|
|
52
52
|
import ActivityBadge from './ActivityBadge.svelte';
|
|
53
53
|
import ShellBrand from './ShellBrand.svelte';
|
|
54
|
+
import { SHELL_DEFAULT_TOOL_ICON, SHELL_ICON_PATHS } from './shell-icons.js';
|
|
54
55
|
import { setAdminShell } from './context.js';
|
|
55
56
|
import {
|
|
56
57
|
formatHotkeyBinding,
|
|
@@ -64,7 +65,12 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
64
65
|
installShellViewport,
|
|
65
66
|
watchFormActionBar,
|
|
66
67
|
} from './mobile-shell-dom.js';
|
|
67
|
-
import {
|
|
68
|
+
import { tokenDuration } from './motion.js';
|
|
69
|
+
import {
|
|
70
|
+
clampPanelSize,
|
|
71
|
+
DEFAULT_PANEL_CONFIG,
|
|
72
|
+
resolveHotkey,
|
|
73
|
+
} from './settings.js';
|
|
68
74
|
import { createShellState, type ShellState } from './state.svelte.js';
|
|
69
75
|
import {
|
|
70
76
|
resolveSlot,
|
|
@@ -168,8 +174,14 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
168
174
|
* children receive them.
|
|
169
175
|
*/
|
|
170
176
|
overlays?: Snippet<[{ viewport: ShellViewport; bottomBar: BottomBarMode }]>;
|
|
171
|
-
/** Phone behavior switches (scrim
|
|
177
|
+
/** Phone behavior switches (scrim and swipe to close default on; hide on scroll). */
|
|
172
178
|
phone?: AdminShellPhoneOptions;
|
|
179
|
+
/**
|
|
180
|
+
* Show the built-in "Tools" opener on phones while the right edge has
|
|
181
|
+
* focus tools (default true). `AppShell` turns it off when dock toggles
|
|
182
|
+
* already open the dock from the header.
|
|
183
|
+
*/
|
|
184
|
+
phoneDockOpener?: boolean;
|
|
173
185
|
/** Keep the phone top bar shown (e.g. while a banner is visible). */
|
|
174
186
|
pinChrome?: boolean;
|
|
175
187
|
/**
|
|
@@ -221,6 +233,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
221
233
|
phoneBottomBar,
|
|
222
234
|
overlays,
|
|
223
235
|
phone,
|
|
236
|
+
phoneDockOpener = true,
|
|
224
237
|
pinChrome = false,
|
|
225
238
|
path,
|
|
226
239
|
children,
|
|
@@ -257,6 +270,8 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
257
270
|
let formActions = $state(false);
|
|
258
271
|
let chromeHidden = $state(false);
|
|
259
272
|
let resizing = $state<SideEdge | null>(null);
|
|
273
|
+
/** Set after hydration and two frames, so first paint never animates. */
|
|
274
|
+
let motionReady = $state(false);
|
|
260
275
|
const sideElements = $state<Partial<Record<SideEdge, HTMLElement>>>({});
|
|
261
276
|
let scrollChrome: ReturnType<typeof installScrollChrome> | null = null;
|
|
262
277
|
|
|
@@ -280,16 +295,20 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
280
295
|
});
|
|
281
296
|
return () => { cancelled = true; queueMicrotask(() => { if (opener?.isConnected) opener.focus(); }); };
|
|
282
297
|
});
|
|
283
|
-
const
|
|
298
|
+
const phoneScrim = $derived(phone?.scrim !== false);
|
|
299
|
+
const phoneSwipeToClose = $derived(phone?.swipeToClose !== false);
|
|
300
|
+
/** The right edge has tools a phone user must be able to open. */
|
|
301
|
+
const rightOpenerShown = $derived(
|
|
302
|
+
isPhone &&
|
|
303
|
+
phoneDockOpener &&
|
|
304
|
+
shell.isEdgeShown('right') &&
|
|
305
|
+
(shell.focusTools.length > 0 || Boolean(focusRail)),
|
|
306
|
+
);
|
|
307
|
+
const leftOpenerShown = $derived(
|
|
284
308
|
isPhone &&
|
|
285
|
-
!phoneTopBar &&
|
|
286
|
-
panelState('top') === 'hidden' &&
|
|
287
309
|
shell.isEdgeShown('left') &&
|
|
288
310
|
shell.phonePresentation('left') !== 'hidden',
|
|
289
311
|
);
|
|
290
|
-
const showPhoneTop = $derived(
|
|
291
|
-
isPhone && (Boolean(phoneTopBar) || showDefaultPhoneTenantOpener),
|
|
292
|
-
);
|
|
293
312
|
const showHeader = $derived(
|
|
294
313
|
Boolean(header) && !(isPhone && Boolean(phoneTopBar)),
|
|
295
314
|
);
|
|
@@ -304,6 +323,18 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
304
323
|
(edge) => panelState(edge) === 'expanded' && shell.isEdgeShown(edge),
|
|
305
324
|
),
|
|
306
325
|
);
|
|
326
|
+
// Starting to edit the layout on a phone puts any open drawer or sheet away,
|
|
327
|
+
// so the editor and a drawer never overlap.
|
|
328
|
+
let wasEditingLayout = false;
|
|
329
|
+
$effect(() => {
|
|
330
|
+
const now = Boolean(layoutEdit?.active);
|
|
331
|
+
untrack(() => {
|
|
332
|
+
if (now && !wasEditingLayout && shell.viewport === 'phone') {
|
|
333
|
+
collapsePhoneSurfaces();
|
|
334
|
+
}
|
|
335
|
+
wasEditingLayout = now;
|
|
336
|
+
});
|
|
337
|
+
});
|
|
307
338
|
const reserveStyle = $derived(
|
|
308
339
|
[
|
|
309
340
|
`--smrt-shell-floating-reserve-inline: ${floatingReserve?.inline ?? '0px'}`,
|
|
@@ -472,7 +503,45 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
472
503
|
onMount(() => {
|
|
473
504
|
const offViewport = installShellViewport(shell);
|
|
474
505
|
const offOverlayMedia = installShellOverlayMedia(shell);
|
|
475
|
-
|
|
506
|
+
const hydrated = shell
|
|
507
|
+
.hydrate()
|
|
508
|
+
.then(() => shell.closeOverlaidEdges());
|
|
509
|
+
let disposed = false;
|
|
510
|
+
let frame = 0;
|
|
511
|
+
let themeObserver: MutationObserver | null = null;
|
|
512
|
+
let themeTimer: ReturnType<typeof setTimeout> | null = null;
|
|
513
|
+
// Colour-scheme crossfade: flag the root for one transition when the
|
|
514
|
+
// theme root's scheme changes. The flag is set from the observer
|
|
515
|
+
// microtask, i.e. before the style recalc that applies the new tokens.
|
|
516
|
+
function watchColorScheme(): void {
|
|
517
|
+
const root = rootElement;
|
|
518
|
+
if (!root || typeof MutationObserver === 'undefined') return;
|
|
519
|
+
const host =
|
|
520
|
+
root.closest<HTMLElement>('[data-color-scheme]') ??
|
|
521
|
+
document.documentElement;
|
|
522
|
+
themeObserver = new MutationObserver(() => {
|
|
523
|
+
if (prefersReducedMotion()) return;
|
|
524
|
+
root.setAttribute('data-smrt-theme-changing', '');
|
|
525
|
+
if (themeTimer) clearTimeout(themeTimer);
|
|
526
|
+
themeTimer = setTimeout(
|
|
527
|
+
() => root.removeAttribute('data-smrt-theme-changing'),
|
|
528
|
+
tokenDuration('--smrt-duration-medium1', root) + 100,
|
|
529
|
+
);
|
|
530
|
+
});
|
|
531
|
+
themeObserver.observe(host, {
|
|
532
|
+
attributes: true,
|
|
533
|
+
attributeFilter: ['data-color-scheme', 'class'],
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
void hydrated.then(() => {
|
|
537
|
+
frame = requestAnimationFrame(() => {
|
|
538
|
+
frame = requestAnimationFrame(() => {
|
|
539
|
+
if (disposed) return;
|
|
540
|
+
motionReady = true;
|
|
541
|
+
watchColorScheme();
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
});
|
|
476
545
|
const offKeyboard = phoneBottomBar
|
|
477
546
|
? installKeyboardWatcher((open) => (keyboardOpen = open))
|
|
478
547
|
: () => {};
|
|
@@ -523,6 +592,10 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
523
592
|
window.addEventListener('keydown', handleKeydown);
|
|
524
593
|
return () => {
|
|
525
594
|
window.removeEventListener('keydown', handleKeydown);
|
|
595
|
+
disposed = true;
|
|
596
|
+
cancelAnimationFrame(frame);
|
|
597
|
+
themeObserver?.disconnect();
|
|
598
|
+
if (themeTimer) clearTimeout(themeTimer);
|
|
526
599
|
offViewport();
|
|
527
600
|
offOverlayMedia();
|
|
528
601
|
if (closingTimer) clearTimeout(closingTimer);
|
|
@@ -709,9 +782,69 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
709
782
|
const stripRegions = $derived(
|
|
710
783
|
layoutEdit?.active && layoutEdit.strip ? (layoutEdit.hiddenRegions ?? []) : [],
|
|
711
784
|
);
|
|
785
|
+
function slotHas(...names: ShellSlot[]): boolean {
|
|
786
|
+
return names.some((name) => (slotContent[name]?.length ?? 0) > 0);
|
|
787
|
+
}
|
|
788
|
+
const layoutEditing = $derived(Boolean(layoutEdit?.active));
|
|
789
|
+
const menuOpenerCounts = $derived(
|
|
790
|
+
!(layoutEditing && !isPhone) &&
|
|
791
|
+
shell.config.panels.left.initial !== 'hidden' &&
|
|
792
|
+
shell.layoutPanels.left?.visible !== false &&
|
|
793
|
+
(!isPhone || shell.phonePresentation('left') !== 'hidden') &&
|
|
794
|
+
(isPhone || panelState('left') === 'hidden'),
|
|
795
|
+
);
|
|
796
|
+
// A band or edge with nothing to show is not rendered and its grid track
|
|
797
|
+
// collapses to 0 (the five-row grid itself never changes).
|
|
798
|
+
const topRendered = $derived(
|
|
799
|
+
panelState('top') !== 'hidden' &&
|
|
800
|
+
(layoutEditing ||
|
|
801
|
+
Boolean(appBar) ||
|
|
802
|
+
!brandInSlot ||
|
|
803
|
+
showToggle('top') ||
|
|
804
|
+
menuOpenerCounts ||
|
|
805
|
+
rightOpenerShown ||
|
|
806
|
+
Boolean(account) ||
|
|
807
|
+
footerInHeader ||
|
|
808
|
+
Boolean(topLeftCorner) ||
|
|
809
|
+
Boolean(topRightCorner) ||
|
|
810
|
+
slotHas('header.start', 'header.center', 'header.end') ||
|
|
811
|
+
panelMounted('top')),
|
|
812
|
+
);
|
|
813
|
+
const bottomRendered = $derived(
|
|
814
|
+
panelState('bottom') !== 'hidden' &&
|
|
815
|
+
(layoutEditing ||
|
|
816
|
+
Boolean(systemBar) ||
|
|
817
|
+
Boolean(bottomLeftCorner) ||
|
|
818
|
+
Boolean(bottomRightCorner) ||
|
|
819
|
+
(showToggle('bottom') && Boolean(systemPanel || !systemBar)) ||
|
|
820
|
+
slotHas('footer.start', 'footer.center', 'footer.end') ||
|
|
821
|
+
panelMounted('bottom')),
|
|
822
|
+
);
|
|
823
|
+
const rightRendered = $derived(
|
|
824
|
+
shell.isEdgeShown('right') &&
|
|
825
|
+
(layoutEditing ||
|
|
826
|
+
shell.focusTools.length > 0 ||
|
|
827
|
+
Boolean(focusRail) ||
|
|
828
|
+
Boolean(focusPanel) ||
|
|
829
|
+
showToggle('right') ||
|
|
830
|
+
slotHas('rightSidebar.header', 'rightSidebar.footer') ||
|
|
831
|
+
panelMounted('right')),
|
|
832
|
+
);
|
|
833
|
+
const showDefaultPhoneTenantOpener = $derived(
|
|
834
|
+
isPhone &&
|
|
835
|
+
!phoneTopBar &&
|
|
836
|
+
!topRendered &&
|
|
837
|
+
(leftOpenerShown || rightOpenerShown),
|
|
838
|
+
);
|
|
839
|
+
const showPhoneTop = $derived(
|
|
840
|
+
isPhone && (Boolean(phoneTopBar) || showDefaultPhoneTenantOpener),
|
|
841
|
+
);
|
|
712
842
|
const layoutStyle = $derived(
|
|
713
843
|
[
|
|
714
844
|
buildLayoutStyle(shell),
|
|
845
|
+
...(topRendered ? [] : ['--smrt-admin-shell-top-track: 0rem']),
|
|
846
|
+
...(bottomRendered ? [] : ['--smrt-admin-shell-bottom-track: 0rem']),
|
|
847
|
+
...(rightRendered ? [] : ['--smrt-admin-shell-right-track: 0rem']),
|
|
715
848
|
...stripRegions.map(
|
|
716
849
|
(region) => `--smrt-admin-shell-${REGION_TRACK[region]}-track: ${STRIP_TRACK}`,
|
|
717
850
|
),
|
|
@@ -788,6 +921,39 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
788
921
|
return shell.config.panels[edge].label;
|
|
789
922
|
}
|
|
790
923
|
|
|
924
|
+
/**
|
|
925
|
+
* Accessible name of the left chevron. A host-configured panel label
|
|
926
|
+
* ("Packages") names the panel; the default region name ("Left sidebar")
|
|
927
|
+
* is a developer term, so the name is then just "Collapse sidebar".
|
|
928
|
+
*/
|
|
929
|
+
function leftEdgeToggleName(): string {
|
|
930
|
+
const label = labelFor('left');
|
|
931
|
+
const expanded = edgeExpanded('left');
|
|
932
|
+
if (label && label !== DEFAULT_PANEL_CONFIG.left.label) {
|
|
933
|
+
return t(
|
|
934
|
+
M[expanded ? 'ui.admin_shell.collapse_panel' : 'ui.admin_shell.expand_panel'],
|
|
935
|
+
{ panel: label },
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
return t(
|
|
939
|
+
M[expanded ? 'ui.admin_shell.collapse_sidebar' : 'ui.admin_shell.expand_sidebar'],
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
function toggleMenu(): void {
|
|
944
|
+
shell.setPanelState('left', edgeExpanded('left') ? 'collapsed' : 'expanded');
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
function toggleTools(): void {
|
|
948
|
+
if (edgeExpanded('right')) {
|
|
949
|
+
shell.collapsePanel('right');
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
const tool = resolveActiveFocusTool();
|
|
953
|
+
if (tool) shell.openFocusTool(tool.id);
|
|
954
|
+
else shell.expandPanel('right');
|
|
955
|
+
}
|
|
956
|
+
|
|
791
957
|
function hotkeyFor(edge: PanelEdge): string {
|
|
792
958
|
return formatHotkeyBinding(
|
|
793
959
|
resolveHotkey(edge, shell.config.panels[edge], shell.settings),
|
|
@@ -840,6 +1006,12 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
840
1006
|
return toggleOn(edge) || showToggle(edge);
|
|
841
1007
|
}
|
|
842
1008
|
|
|
1009
|
+
$effect(() => {
|
|
1010
|
+
shell.hotkeysAvailable = (['top', 'left', 'right', 'bottom'] as const).some(
|
|
1011
|
+
hotkeyActive,
|
|
1012
|
+
);
|
|
1013
|
+
});
|
|
1014
|
+
|
|
843
1015
|
function showsHotkeyFor(edge: PanelEdge): boolean {
|
|
844
1016
|
return (
|
|
845
1017
|
hotkeyActive(edge) &&
|
|
@@ -894,21 +1066,80 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
894
1066
|
</script>
|
|
895
1067
|
|
|
896
1068
|
{#snippet edgeToggle(edge: PanelEdge)}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1069
|
+
{#if edge === 'left'}
|
|
1070
|
+
<!-- The left toggle is an icon-only chevron: it points the way the panel
|
|
1071
|
+
will move (left to collapse, right to expand). Its accessible name
|
|
1072
|
+
carries the action and the hotkey rides in the tooltip. -->
|
|
1073
|
+
{@const name = leftEdgeToggleName()}
|
|
1074
|
+
<Button
|
|
1075
|
+
variant="ghost"
|
|
1076
|
+
size="sm"
|
|
1077
|
+
class="smrt-admin-shell__edge-toggle smrt-admin-shell__edge-toggle--left"
|
|
1078
|
+
aria-label={name}
|
|
1079
|
+
title={showsHotkeyFor('left') ? `${name} (${hotkeyFor('left')})` : name}
|
|
1080
|
+
aria-expanded={edgeExpanded('left')}
|
|
1081
|
+
aria-controls="smrt-admin-shell-left-panel"
|
|
1082
|
+
onclick={() => shell.togglePanel('left')}
|
|
1083
|
+
>
|
|
1084
|
+
<svg
|
|
1085
|
+
class="smrt-admin-shell__edge-toggle-chevron"
|
|
1086
|
+
viewBox="0 0 24 24"
|
|
1087
|
+
width="18"
|
|
1088
|
+
height="18"
|
|
1089
|
+
fill="currentColor"
|
|
1090
|
+
aria-hidden="true"
|
|
1091
|
+
focusable="false"
|
|
1092
|
+
><path d={SHELL_ICON_PATHS.chevronRight} /></svg>
|
|
1093
|
+
<ActivityBadge edge="left" />
|
|
1094
|
+
</Button>
|
|
1095
|
+
{:else}
|
|
1096
|
+
<Button
|
|
1097
|
+
variant="ghost"
|
|
1098
|
+
size="sm"
|
|
1099
|
+
class="smrt-admin-shell__edge-toggle"
|
|
1100
|
+
aria-expanded={edgeExpanded(edge)}
|
|
1101
|
+
aria-controls={`smrt-admin-shell-${edge}-panel`}
|
|
1102
|
+
onclick={() => shell.togglePanel(edge)}
|
|
1103
|
+
>
|
|
1104
|
+
<span>{labelFor(edge)}</span>
|
|
1105
|
+
{#if showsHotkeyFor(edge)}
|
|
1106
|
+
<kbd class="smrt-admin-shell__edge-toggle-kbd">{hotkeyFor(edge)}</kbd>
|
|
1107
|
+
{/if}
|
|
1108
|
+
<ActivityBadge {edge} />
|
|
1109
|
+
</Button>
|
|
1110
|
+
{/if}
|
|
1111
|
+
{/snippet}
|
|
1112
|
+
|
|
1113
|
+
{#snippet menuOpener()}
|
|
1114
|
+
<!-- raw-primitive-allow: shell chrome control, not a content button -->
|
|
1115
|
+
<button
|
|
1116
|
+
type="button"
|
|
1117
|
+
class="smrt-admin-shell__chrome-button"
|
|
1118
|
+
data-smrt-part="trigger"
|
|
1119
|
+
aria-label={t(M['ui.admin_shell.menu'])}
|
|
1120
|
+
title={t(M['ui.admin_shell.menu'])}
|
|
1121
|
+
aria-expanded={edgeExpanded('left')}
|
|
1122
|
+
aria-controls="smrt-admin-shell-left-panel"
|
|
1123
|
+
onclick={toggleMenu}
|
|
905
1124
|
>
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1125
|
+
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true" focusable="false"><path d={SHELL_ICON_PATHS.menu} /></svg>
|
|
1126
|
+
</button>
|
|
1127
|
+
{/snippet}
|
|
1128
|
+
|
|
1129
|
+
{#snippet toolsOpener()}
|
|
1130
|
+
<!-- raw-primitive-allow: shell chrome control, not a content button -->
|
|
1131
|
+
<button
|
|
1132
|
+
type="button"
|
|
1133
|
+
class="smrt-admin-shell__chrome-button smrt-admin-shell__tools-opener"
|
|
1134
|
+
data-smrt-part="trigger"
|
|
1135
|
+
aria-label={t(M['ui.admin_shell.tools'])}
|
|
1136
|
+
title={t(M['ui.admin_shell.tools'])}
|
|
1137
|
+
aria-expanded={edgeExpanded('right')}
|
|
1138
|
+
aria-controls="smrt-admin-shell-right-panel"
|
|
1139
|
+
onclick={toggleTools}
|
|
1140
|
+
>
|
|
1141
|
+
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true" focusable="false"><path d={SHELL_ICON_PATHS[SHELL_DEFAULT_TOOL_ICON]} /></svg>
|
|
1142
|
+
</button>
|
|
912
1143
|
{/snippet}
|
|
913
1144
|
|
|
914
1145
|
{#snippet resizer(edge: SideEdge)}
|
|
@@ -1007,7 +1238,8 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1007
1238
|
data-phone-top={showPhoneTop ? '' : undefined}
|
|
1008
1239
|
data-chrome-hidden={chromeHidden ? '' : undefined}
|
|
1009
1240
|
data-resizing={resizing ?? undefined}
|
|
1010
|
-
|
|
1241
|
+
data-motion={motionReady ? '' : undefined}
|
|
1242
|
+
style={`${layoutStyle}; ${chromeStyle}; ${reserveStyle}`} data-smrt-component="AdminShell"
|
|
1011
1243
|
>
|
|
1012
1244
|
{#if showHeader}
|
|
1013
1245
|
<div
|
|
@@ -1020,13 +1252,13 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1020
1252
|
{/if}
|
|
1021
1253
|
|
|
1022
1254
|
{@render regionStrip('header')}
|
|
1023
|
-
{#if
|
|
1255
|
+
{#if topRendered}
|
|
1024
1256
|
<header
|
|
1025
1257
|
id="smrt-admin-shell-top-panel"
|
|
1026
1258
|
class="smrt-admin-shell__edge smrt-admin-shell__edge--top"
|
|
1027
1259
|
data-state={panelState('top')}
|
|
1028
1260
|
data-presentation={shell.config.panels.top.presentation}
|
|
1029
|
-
style:--edge-columns={topEdgeColumns}
|
|
1261
|
+
style:--smrt-admin-shell-edge-columns={topEdgeColumns}
|
|
1030
1262
|
>
|
|
1031
1263
|
{#if topLeftCorner}
|
|
1032
1264
|
<div class="smrt-admin-shell__corner smrt-admin-shell__corner--top-left">
|
|
@@ -1035,7 +1267,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1035
1267
|
{/if}
|
|
1036
1268
|
<div
|
|
1037
1269
|
class="smrt-admin-shell__band smrt-admin-shell__band--top"
|
|
1038
|
-
style:--band-column={2}
|
|
1270
|
+
style:--smrt-admin-shell-band-column={2}
|
|
1039
1271
|
>
|
|
1040
1272
|
{#if appBar}
|
|
1041
1273
|
{@render appBar()}
|
|
@@ -1045,7 +1277,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1045
1277
|
{/if}
|
|
1046
1278
|
{#if !(layoutEdit?.active && !isPhone) && shell.config.panels.left.initial !== 'hidden' && shell.layoutPanels.left?.visible !== false && (!isPhone || shell.phonePresentation('left') !== 'hidden')}
|
|
1047
1279
|
<div class="smrt-admin-shell__tenant-opener" class:restore-hidden={panelState('left') === 'hidden'}>
|
|
1048
|
-
|
|
1280
|
+
{@render menuOpener()}
|
|
1049
1281
|
</div>
|
|
1050
1282
|
{/if}
|
|
1051
1283
|
{@render slotGroup('header.start')}
|
|
@@ -1056,6 +1288,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1056
1288
|
</div>
|
|
1057
1289
|
{/if}
|
|
1058
1290
|
{@render slotGroup('header.end')}
|
|
1291
|
+
{#if rightOpenerShown}{@render toolsOpener()}{/if}
|
|
1059
1292
|
{@render regionEdit('header')}
|
|
1060
1293
|
</div>
|
|
1061
1294
|
{#if topRightCorner}
|
|
@@ -1101,14 +1334,29 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1101
1334
|
use:swipeDismiss={{
|
|
1102
1335
|
direction: 'left',
|
|
1103
1336
|
onDismiss: () => shell.collapsePanel('left'),
|
|
1104
|
-
enabled: isPhone &&
|
|
1337
|
+
enabled: isPhone && phoneSwipeToClose && edgeExpanded('left'),
|
|
1105
1338
|
}}
|
|
1106
1339
|
>
|
|
1107
1340
|
{@render resizer('left')}
|
|
1108
1341
|
<div class="smrt-admin-shell__rail">
|
|
1109
1342
|
{@render regionEdit('leftSidebar')}
|
|
1110
|
-
{#if
|
|
1111
|
-
|
|
1343
|
+
{#if isPhone}
|
|
1344
|
+
<!-- Phone drawer: the app title and an icon-only close control. -->
|
|
1345
|
+
<div class="smrt-admin-shell__drawer-head" data-smrt-part="header">
|
|
1346
|
+
<div class="smrt-admin-shell__drawer-title">{@render shellBrand()}</div>
|
|
1347
|
+
<!-- raw-primitive-allow: shell chrome control, not a content button -->
|
|
1348
|
+
<button
|
|
1349
|
+
type="button"
|
|
1350
|
+
class="smrt-admin-shell__chrome-button"
|
|
1351
|
+
data-smrt-part="close"
|
|
1352
|
+
aria-label={t(M['ui.admin_shell.close_menu'])}
|
|
1353
|
+
title={t(M['ui.admin_shell.close_menu'])}
|
|
1354
|
+
onclick={() => shell.collapsePanel('left')}
|
|
1355
|
+
>
|
|
1356
|
+
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true" focusable="false"><path d={SHELL_ICON_PATHS.close} /></svg>
|
|
1357
|
+
</button>
|
|
1358
|
+
</div>
|
|
1359
|
+
{:else if !topRendered && (homeHref || logoSrc || brand)}{@render shellBrand(!edgeExpanded('left'))}{/if}
|
|
1112
1360
|
{#if shownOpen('left') || (tenantPanel && keepsContent('left'))}
|
|
1113
1361
|
<div
|
|
1114
1362
|
class="smrt-admin-shell__tenant-stack"
|
|
@@ -1122,6 +1370,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1122
1370
|
{@render tenantRail()}
|
|
1123
1371
|
{/if}
|
|
1124
1372
|
</div>
|
|
1373
|
+
{#if showToggle('left') && !isPhone && shownOpen('left')}{@render edgeToggle('left')}{/if}
|
|
1125
1374
|
{#if tenantFooter && !footerInHeader}
|
|
1126
1375
|
<div class="smrt-admin-shell__tenant-footer">
|
|
1127
1376
|
{@render tenantFooter()}
|
|
@@ -1132,11 +1381,10 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1132
1381
|
{/if}
|
|
1133
1382
|
{#if !shownOpen('left') && (tenantRail || tenantRailFooter)}
|
|
1134
1383
|
<div class="smrt-admin-shell__tenant-rail-stack">
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
{/if}
|
|
1384
|
+
<div class="smrt-admin-shell__tenant-rail-content">
|
|
1385
|
+
{#if tenantRail}{@render tenantRail()}{/if}
|
|
1386
|
+
</div>
|
|
1387
|
+
{#if showToggle('left') && !isPhone}{@render edgeToggle('left')}{/if}
|
|
1140
1388
|
{#if tenantRailFooter}
|
|
1141
1389
|
<div class="smrt-admin-shell__tenant-rail-footer">
|
|
1142
1390
|
{@render tenantRailFooter()}
|
|
@@ -1144,6 +1392,10 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1144
1392
|
{/if}
|
|
1145
1393
|
</div>
|
|
1146
1394
|
{/if}
|
|
1395
|
+
<!-- The chevron closes the nav region, above the footer slot: inside
|
|
1396
|
+
the expanded stack or the collapsed rail stack. Only when neither
|
|
1397
|
+
is rendered does it stand alone at the bottom of the rail. -->
|
|
1398
|
+
{#if showToggle('left') && !isPhone && !shownOpen('left') && !(tenantRail || tenantRailFooter)}{@render edgeToggle('left')}{/if}
|
|
1147
1399
|
</div>
|
|
1148
1400
|
</aside>
|
|
1149
1401
|
{/if}
|
|
@@ -1163,32 +1415,28 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1163
1415
|
{@render phoneTopBar({ hidden: chromeHidden })}
|
|
1164
1416
|
{:else if showDefaultPhoneTenantOpener}
|
|
1165
1417
|
<div class="smrt-admin-shell__phone-default-top">
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
aria-expanded={edgeExpanded('left')}
|
|
1171
|
-
aria-controls="smrt-admin-shell-left-panel"
|
|
1172
|
-
onclick={() =>
|
|
1173
|
-
shell.setPanelState(
|
|
1174
|
-
'left',
|
|
1175
|
-
edgeExpanded('left') ? 'collapsed' : 'expanded',
|
|
1176
|
-
)}
|
|
1177
|
-
>{t(M['ui.admin_shell.menu'])}</Button>
|
|
1418
|
+
{#if leftOpenerShown}{@render menuOpener()}{/if}
|
|
1419
|
+
{#if rightOpenerShown}
|
|
1420
|
+
<span class="smrt-admin-shell__phone-default-end">{@render toolsOpener()}</span>
|
|
1421
|
+
{/if}
|
|
1178
1422
|
</div>
|
|
1179
1423
|
{/if}
|
|
1180
1424
|
</div>
|
|
1181
1425
|
{/if}
|
|
1182
1426
|
|
|
1183
|
-
{#if isPhone &&
|
|
1427
|
+
{#if isPhone && phoneScrim && phoneSurfaceOpen}
|
|
1184
1428
|
<!-- raw-primitive-allow: click-catching backdrop behind a phone drawer -->
|
|
1185
1429
|
<button
|
|
1186
1430
|
type="button"
|
|
1187
1431
|
class="smrt-admin-shell__scrim"
|
|
1188
1432
|
tabindex="-1"
|
|
1189
|
-
aria-label={t(
|
|
1190
|
-
|
|
1191
|
-
|
|
1433
|
+
aria-label={t(
|
|
1434
|
+
M[
|
|
1435
|
+
edgeExpanded('left') && shell.isEdgeShown('left')
|
|
1436
|
+
? 'ui.admin_shell.close_menu'
|
|
1437
|
+
: 'ui.admin_shell.close_tools'
|
|
1438
|
+
],
|
|
1439
|
+
)}
|
|
1192
1440
|
data-testid="admin-shell-scrim"
|
|
1193
1441
|
onclick={collapsePhoneSurfaces}
|
|
1194
1442
|
></button>
|
|
@@ -1201,7 +1449,13 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1201
1449
|
type="button"
|
|
1202
1450
|
class="smrt-admin-shell__overlay-scrim"
|
|
1203
1451
|
tabindex="-1"
|
|
1204
|
-
aria-label={t(
|
|
1452
|
+
aria-label={t(
|
|
1453
|
+
M[
|
|
1454
|
+
scrimEdge === 'left'
|
|
1455
|
+
? 'ui.admin_shell.close_sidebar'
|
|
1456
|
+
: 'ui.admin_shell.close_tools'
|
|
1457
|
+
],
|
|
1458
|
+
)}
|
|
1205
1459
|
data-testid="admin-shell-overlay-scrim"
|
|
1206
1460
|
data-closing={overlayEdge ? undefined : ''}
|
|
1207
1461
|
onclick={() => {
|
|
@@ -1211,7 +1465,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1211
1465
|
{/if}
|
|
1212
1466
|
|
|
1213
1467
|
{@render regionStrip('rightSidebar')}
|
|
1214
|
-
{#if
|
|
1468
|
+
{#if rightRendered}
|
|
1215
1469
|
{@const rightPhone = isPhone ? shell.phonePresentation('right') : undefined}
|
|
1216
1470
|
<!-- tabindex -1 only while overlaid, so the panel can take focus on open -->
|
|
1217
1471
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
@@ -1234,7 +1488,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1234
1488
|
onDismiss: () => shell.collapsePanel('right'),
|
|
1235
1489
|
enabled:
|
|
1236
1490
|
rightPhone === 'drawer' &&
|
|
1237
|
-
|
|
1491
|
+
phoneSwipeToClose &&
|
|
1238
1492
|
edgeExpanded('right'),
|
|
1239
1493
|
}}
|
|
1240
1494
|
>
|
|
@@ -1254,6 +1508,19 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1254
1508
|
{/if}
|
|
1255
1509
|
<div class="smrt-admin-shell__rail">
|
|
1256
1510
|
{@render regionEdit('rightSidebar')}
|
|
1511
|
+
{#if rightPhone === 'drawer'}
|
|
1512
|
+
<!-- raw-primitive-allow: shell chrome control, not a content button -->
|
|
1513
|
+
<button
|
|
1514
|
+
type="button"
|
|
1515
|
+
class="smrt-admin-shell__chrome-button smrt-admin-shell__rail-close"
|
|
1516
|
+
data-smrt-part="close"
|
|
1517
|
+
aria-label={t(M['ui.admin_shell.close_tools'])}
|
|
1518
|
+
title={t(M['ui.admin_shell.close_tools'])}
|
|
1519
|
+
onclick={() => shell.collapsePanel('right')}
|
|
1520
|
+
>
|
|
1521
|
+
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true" focusable="false"><path d={SHELL_ICON_PATHS.close} /></svg>
|
|
1522
|
+
</button>
|
|
1523
|
+
{/if}
|
|
1257
1524
|
{#if shell.config.panels.right.rail === false}
|
|
1258
1525
|
<!-- Railless: no tool buttons; the host's toggle opens and closes it. -->
|
|
1259
1526
|
{:else if focusRail}
|
|
@@ -1276,7 +1543,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1276
1543
|
{#if tool.icon}
|
|
1277
1544
|
<tool.icon />
|
|
1278
1545
|
{:else}
|
|
1279
|
-
<
|
|
1546
|
+
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true" focusable="false"><path d={SHELL_ICON_PATHS[SHELL_DEFAULT_TOOL_ICON]} /></svg>
|
|
1280
1547
|
{/if}
|
|
1281
1548
|
{#if tool.badge != null}
|
|
1282
1549
|
<span class="smrt-admin-shell__focus-tool-badge">
|
|
@@ -1330,13 +1597,13 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1330
1597
|
{/if}
|
|
1331
1598
|
|
|
1332
1599
|
{@render regionStrip('footer')}
|
|
1333
|
-
{#if
|
|
1600
|
+
{#if bottomRendered}
|
|
1334
1601
|
<footer
|
|
1335
1602
|
id="smrt-admin-shell-bottom-panel"
|
|
1336
1603
|
class="smrt-admin-shell__edge smrt-admin-shell__edge--bottom"
|
|
1337
1604
|
data-state={panelState('bottom')}
|
|
1338
1605
|
data-presentation={shell.config.panels.bottom.presentation}
|
|
1339
|
-
style:--edge-columns={bottomEdgeColumns}
|
|
1606
|
+
style:--smrt-admin-shell-edge-columns={bottomEdgeColumns}
|
|
1340
1607
|
>
|
|
1341
1608
|
{#if bottomLeftCorner}
|
|
1342
1609
|
<div class="smrt-admin-shell__corner smrt-admin-shell__corner--bottom-left">
|
|
@@ -1345,7 +1612,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1345
1612
|
{/if}
|
|
1346
1613
|
<div
|
|
1347
1614
|
class="smrt-admin-shell__band smrt-admin-shell__band--bottom"
|
|
1348
|
-
style:--band-column={2}
|
|
1615
|
+
style:--smrt-admin-shell-band-column={2}
|
|
1349
1616
|
>
|
|
1350
1617
|
{@render slotGroup('footer.start')}
|
|
1351
1618
|
{@render slotGroup('footer.center')}
|
|
@@ -1432,6 +1699,8 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1432
1699
|
</div>
|
|
1433
1700
|
|
|
1434
1701
|
<style>
|
|
1702
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
1703
|
+
@layer smrt.theme {
|
|
1435
1704
|
.smrt-admin-shell {
|
|
1436
1705
|
--smrt-shell-floating-reserve-inline: 0px;
|
|
1437
1706
|
--smrt-shell-floating-reserve-block: 0px;
|
|
@@ -1497,7 +1766,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1497
1766
|
background-color: var(--smrt-admin-shell-scrollbar-thumb, color-mix(in srgb, var(--smrt-color-on-surface) 26%, transparent));
|
|
1498
1767
|
background-clip: padding-box;
|
|
1499
1768
|
border: 2px solid transparent;
|
|
1500
|
-
border-radius: var(--smrt-radius-full
|
|
1769
|
+
border-radius: var(--smrt-radius-full);
|
|
1501
1770
|
}
|
|
1502
1771
|
|
|
1503
1772
|
.smrt-admin-shell :global(*)::-webkit-scrollbar-thumb:hover {
|
|
@@ -1542,7 +1811,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1542
1811
|
grid-row: 2;
|
|
1543
1812
|
display: grid;
|
|
1544
1813
|
grid-template-columns: var(
|
|
1545
|
-
--edge-columns,
|
|
1814
|
+
--smrt-admin-shell-edge-columns,
|
|
1546
1815
|
var(--smrt-admin-shell-left-collapsed) minmax(0, 1fr)
|
|
1547
1816
|
var(--smrt-admin-shell-right-collapsed)
|
|
1548
1817
|
);
|
|
@@ -1578,7 +1847,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1578
1847
|
grid-row: 4;
|
|
1579
1848
|
display: grid;
|
|
1580
1849
|
grid-template-columns: var(
|
|
1581
|
-
--edge-columns,
|
|
1850
|
+
--smrt-admin-shell-edge-columns,
|
|
1582
1851
|
var(--smrt-admin-shell-left-collapsed) minmax(0, 1fr)
|
|
1583
1852
|
var(--smrt-admin-shell-right-collapsed)
|
|
1584
1853
|
);
|
|
@@ -1608,7 +1877,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1608
1877
|
|
|
1609
1878
|
.smrt-admin-shell__band--top,
|
|
1610
1879
|
.smrt-admin-shell__band--bottom {
|
|
1611
|
-
grid-column: var(--band-column, 2);
|
|
1880
|
+
grid-column: var(--smrt-admin-shell-band-column, 2);
|
|
1612
1881
|
}
|
|
1613
1882
|
|
|
1614
1883
|
/* The header's slots can render in the top band too: keep the floating
|
|
@@ -1655,7 +1924,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1655
1924
|
width: 2.35rem;
|
|
1656
1925
|
height: 2.35rem;
|
|
1657
1926
|
border: 1px solid transparent;
|
|
1658
|
-
border-radius: var(--smrt-radius-md
|
|
1927
|
+
border-radius: var(--smrt-radius-md);
|
|
1659
1928
|
background: transparent;
|
|
1660
1929
|
color: var(--smrt-color-on-surface-variant);
|
|
1661
1930
|
cursor: pointer;
|
|
@@ -1683,8 +1952,8 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1683
1952
|
padding: var(--smrt-spacing-2, 0.5rem) var(--smrt-spacing-2, 0.5rem);
|
|
1684
1953
|
border: 1px solid var(--smrt-color-outline-variant);
|
|
1685
1954
|
border-inline-end: 0;
|
|
1686
|
-
border-start-start-radius: var(--smrt-radius-md
|
|
1687
|
-
border-end-start-radius: var(--smrt-radius-md
|
|
1955
|
+
border-start-start-radius: var(--smrt-radius-md);
|
|
1956
|
+
border-end-start-radius: var(--smrt-radius-md);
|
|
1688
1957
|
background: var(--smrt-color-surface-container-high);
|
|
1689
1958
|
color: var(--smrt-color-on-surface-variant);
|
|
1690
1959
|
font: inherit;
|
|
@@ -1707,7 +1976,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1707
1976
|
inset-block-start: -0.25rem;
|
|
1708
1977
|
inset-inline-end: -0.25rem;
|
|
1709
1978
|
min-width: 1rem;
|
|
1710
|
-
border-radius: var(--smrt-radius-full
|
|
1979
|
+
border-radius: var(--smrt-radius-full);
|
|
1711
1980
|
background: var(--smrt-color-error);
|
|
1712
1981
|
color: var(--smrt-color-on-error);
|
|
1713
1982
|
font-size: var(--smrt-typography-label-small-size, 0.625rem);
|
|
@@ -1725,12 +1994,49 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1725
1994
|
max-inline-size: min(20rem, 45vw);
|
|
1726
1995
|
flex: 1 1 12rem;
|
|
1727
1996
|
}
|
|
1728
|
-
.smrt-admin-shell__account :global(.smrt-workspace-account-
|
|
1997
|
+
.smrt-admin-shell__account :global(.smrt-workspace-account-menu__popover) {
|
|
1729
1998
|
top: 100%; bottom: auto; right: 0; left: auto;
|
|
1730
1999
|
inline-size: max-content;
|
|
1731
2000
|
max-inline-size: calc(100vw - 2 * var(--smrt-spacing-4));
|
|
1732
2001
|
}
|
|
1733
2002
|
|
|
2003
|
+
.smrt-admin-shell__chrome-button {
|
|
2004
|
+
flex: 0 0 auto;
|
|
2005
|
+
display: inline-grid;
|
|
2006
|
+
place-items: center;
|
|
2007
|
+
box-sizing: border-box;
|
|
2008
|
+
inline-size: 2.5rem;
|
|
2009
|
+
block-size: 2.5rem;
|
|
2010
|
+
padding: 0;
|
|
2011
|
+
border: 0;
|
|
2012
|
+
border-radius: var(--smrt-radius-md);
|
|
2013
|
+
background: transparent;
|
|
2014
|
+
color: var(--smrt-color-on-surface-variant);
|
|
2015
|
+
cursor: pointer;
|
|
2016
|
+
}
|
|
2017
|
+
.smrt-admin-shell__chrome-button:hover {
|
|
2018
|
+
background: var(--smrt-color-surface-container-high);
|
|
2019
|
+
color: var(--smrt-color-on-surface);
|
|
2020
|
+
}
|
|
2021
|
+
.smrt-admin-shell__chrome-button:focus-visible {
|
|
2022
|
+
outline: 0.125rem solid var(--smrt-color-primary);
|
|
2023
|
+
outline-offset: 0.125rem;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
.smrt-admin-shell__drawer-head {
|
|
2027
|
+
display: flex;
|
|
2028
|
+
align-items: center;
|
|
2029
|
+
justify-content: space-between;
|
|
2030
|
+
gap: var(--smrt-spacing-2);
|
|
2031
|
+
min-inline-size: 0;
|
|
2032
|
+
}
|
|
2033
|
+
.smrt-admin-shell__drawer-title {
|
|
2034
|
+
min-inline-size: 0;
|
|
2035
|
+
overflow: hidden;
|
|
2036
|
+
text-overflow: ellipsis;
|
|
2037
|
+
}
|
|
2038
|
+
.smrt-admin-shell__rail-close { justify-self: center; }
|
|
2039
|
+
|
|
1734
2040
|
.smrt-admin-shell__tenant-opener { display: none; flex-shrink: 0; }
|
|
1735
2041
|
.smrt-admin-shell__tenant-opener.restore-hidden { display: block; }
|
|
1736
2042
|
.smrt-admin-shell__edge--left[data-state='collapsed'] .smrt-admin-shell__rail { padding-inline: var(--smrt-spacing-2); }
|
|
@@ -1748,7 +2054,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1748
2054
|
.smrt-admin-shell__tenant-stack[hidden],
|
|
1749
2055
|
.smrt-admin-shell__panel[hidden],
|
|
1750
2056
|
.smrt-admin-shell__drawer[hidden] {
|
|
1751
|
-
display: none
|
|
2057
|
+
display: none;
|
|
1752
2058
|
}
|
|
1753
2059
|
|
|
1754
2060
|
.smrt-admin-shell__tenant-stack {
|
|
@@ -1873,7 +2179,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1873
2179
|
|
|
1874
2180
|
.smrt-admin-shell__tenant-rail-stack {
|
|
1875
2181
|
display: grid;
|
|
1876
|
-
grid-template-rows: minmax(0, 1fr) auto;
|
|
2182
|
+
grid-template-rows: minmax(0, 1fr) auto auto;
|
|
1877
2183
|
flex: 1;
|
|
1878
2184
|
min-width: 0;
|
|
1879
2185
|
min-height: 0;
|
|
@@ -1888,7 +2194,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1888
2194
|
.smrt-admin-shell__tenant-rail-footer {
|
|
1889
2195
|
position: relative;
|
|
1890
2196
|
z-index: 1;
|
|
1891
|
-
grid-row:
|
|
2197
|
+
grid-row: 3;
|
|
1892
2198
|
min-width: 0;
|
|
1893
2199
|
padding-block-start: var(--smrt-spacing-2);
|
|
1894
2200
|
border-block-start: 1px solid var(--smrt-color-outline-variant);
|
|
@@ -1916,6 +2222,30 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1916
2222
|
padding-block-start: var(--smrt-shell-floating-reserve-block);
|
|
1917
2223
|
}
|
|
1918
2224
|
|
|
2225
|
+
/* The left chevron closes the navigation region: after the navigation and
|
|
2226
|
+
above the sidebar footer slot (the account menu), never below it.
|
|
2227
|
+
`margin-block-start: auto` pins it to the end of the nav region even when
|
|
2228
|
+
nothing above it grows. Expanded it hugs the inner edge and points left;
|
|
2229
|
+
collapsed it is centred in the narrow rail and points right. */
|
|
2230
|
+
.smrt-admin-shell__edge--left :global(.smrt-admin-shell__edge-toggle--left) {
|
|
2231
|
+
flex: 0 0 auto;
|
|
2232
|
+
margin-block-start: auto;
|
|
2233
|
+
align-self: flex-end;
|
|
2234
|
+
inline-size: max(2rem, var(--smrt-control-target-min, 0px));
|
|
2235
|
+
block-size: max(2rem, var(--smrt-control-target-min, 0px));
|
|
2236
|
+
padding: 0;
|
|
2237
|
+
color: var(--smrt-color-on-surface-variant);
|
|
2238
|
+
}
|
|
2239
|
+
.smrt-admin-shell__edge--left[data-state='collapsed'] :global(.smrt-admin-shell__edge-toggle--left) {
|
|
2240
|
+
align-self: center;
|
|
2241
|
+
justify-self: center;
|
|
2242
|
+
}
|
|
2243
|
+
.smrt-admin-shell__tenant-rail-stack > :global(.smrt-admin-shell__edge-toggle--left) {
|
|
2244
|
+
grid-row: 2;
|
|
2245
|
+
}
|
|
2246
|
+
.smrt-admin-shell__edge--left[data-state='expanded'] :global(.smrt-admin-shell__edge-toggle-chevron) {
|
|
2247
|
+
transform: scaleX(-1);
|
|
2248
|
+
}
|
|
1919
2249
|
.smrt-admin-shell__edge-toggle-kbd {
|
|
1920
2250
|
padding: 0 var(--smrt-spacing-1);
|
|
1921
2251
|
border-radius: var(--smrt-radius-small);
|
|
@@ -1924,6 +2254,19 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
1924
2254
|
font-size: var(--smrt-typography-body-small-size);
|
|
1925
2255
|
}
|
|
1926
2256
|
|
|
2257
|
+
:global(.smrt-admin-shell__edge-toggle--left.button.ghost) {
|
|
2258
|
+
flex: 0 0 auto;
|
|
2259
|
+
inline-size: max(2.75rem, var(--smrt-control-target-min, 0px));
|
|
2260
|
+
block-size: max(2.75rem, var(--smrt-control-target-min, 0px));
|
|
2261
|
+
padding: 0;
|
|
2262
|
+
color: var(--smrt-color-on-surface-variant);
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
:global(.smrt-admin-shell__edge-toggle--left.button.ghost:hover) {
|
|
2266
|
+
background: var(--smrt-color-surface-container-high);
|
|
2267
|
+
color: var(--smrt-color-on-surface);
|
|
2268
|
+
}
|
|
2269
|
+
|
|
1927
2270
|
.smrt-admin-shell__drawer {
|
|
1928
2271
|
position: absolute;
|
|
1929
2272
|
z-index: 40;
|
|
@@ -2083,6 +2426,8 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
2083
2426
|
var(--smrt-easing-standard, ease);
|
|
2084
2427
|
}
|
|
2085
2428
|
|
|
2429
|
+
.smrt-admin-shell__phone-default-end { margin-inline-start: auto; }
|
|
2430
|
+
|
|
2086
2431
|
.smrt-admin-shell__phone-default-top {
|
|
2087
2432
|
display: flex;
|
|
2088
2433
|
align-items: center;
|
|
@@ -2140,7 +2485,7 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
2140
2485
|
z-index: 25;
|
|
2141
2486
|
box-shadow: var(
|
|
2142
2487
|
--smrt-elevation-3,
|
|
2143
|
-
0 0.5rem 1.5rem color-mix(in srgb, var(--smrt-color-shadow
|
|
2488
|
+
0 0.5rem 1.5rem color-mix(in srgb, var(--smrt-color-shadow) 24%, transparent)
|
|
2144
2489
|
);
|
|
2145
2490
|
outline: none;
|
|
2146
2491
|
}
|
|
@@ -2351,6 +2696,13 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
2351
2696
|
}
|
|
2352
2697
|
|
|
2353
2698
|
.smrt-admin-shell__tenant-opener { display: block; }
|
|
2699
|
+
|
|
2700
|
+
/* Touch rows: every phone chrome control meets the touch target. */
|
|
2701
|
+
.smrt-admin-shell__chrome-button,
|
|
2702
|
+
.smrt-admin-shell__focus-tool {
|
|
2703
|
+
min-inline-size: var(--smrt-touch-target-min);
|
|
2704
|
+
min-block-size: var(--smrt-touch-target-min);
|
|
2705
|
+
}
|
|
2354
2706
|
.smrt-admin-shell__edge--left:not([data-state='expanded']),
|
|
2355
2707
|
.smrt-admin-shell__edge--right:not([data-state='expanded']) { visibility: hidden; }
|
|
2356
2708
|
.smrt-admin-shell__edge--left,
|
|
@@ -2459,9 +2811,86 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
2459
2811
|
}
|
|
2460
2812
|
}
|
|
2461
2813
|
|
|
2814
|
+
/* ---- Motion --------------------------------------------------------- */
|
|
2815
|
+
/* `data-motion` is set after hydration and two frames, so first paint,
|
|
2816
|
+
SSR and a persisted layout restoring never animate. The pointer-drag
|
|
2817
|
+
resize stays immediate (`data-resizing`). Phone drawers keep their own
|
|
2818
|
+
animation handshake (onEdgeAnimationEnd / waitForPanelAnimations).
|
|
2819
|
+
Every rule below sits in `no-preference`, so reduced motion is off by
|
|
2820
|
+
construction, matching the reduced-motion block at the end. */
|
|
2821
|
+
|
|
2822
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
2823
|
+
.smrt-admin-shell[data-motion]:not([data-viewport='phone']) {
|
|
2824
|
+
transition: grid-template-columns var(--smrt-duration-short4)
|
|
2825
|
+
var(--smrt-easing-emphasized);
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
.smrt-admin-shell[data-motion][data-resizing]:not([data-viewport='phone']) {
|
|
2829
|
+
transition: none;
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
/* One colour-scheme crossfade, flagged by the scheme observer. */
|
|
2833
|
+
.smrt-admin-shell[data-smrt-theme-changing]:not([data-viewport='phone']) {
|
|
2834
|
+
transition:
|
|
2835
|
+
grid-template-columns var(--smrt-duration-short4)
|
|
2836
|
+
var(--smrt-easing-emphasized),
|
|
2837
|
+
background-color var(--smrt-duration-medium1) var(--smrt-easing-standard),
|
|
2838
|
+
color var(--smrt-duration-medium1) var(--smrt-easing-standard);
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
.smrt-admin-shell[data-smrt-theme-changing]:not([data-viewport='phone']) .smrt-admin-shell__edge,
|
|
2842
|
+
.smrt-admin-shell[data-smrt-theme-changing]:not([data-viewport='phone']) .smrt-admin-shell__header,
|
|
2843
|
+
.smrt-admin-shell[data-smrt-theme-changing]:not([data-viewport='phone']) .smrt-admin-shell__main {
|
|
2844
|
+
transition:
|
|
2845
|
+
background-color var(--smrt-duration-medium1) var(--smrt-easing-standard),
|
|
2846
|
+
border-color var(--smrt-duration-medium1) var(--smrt-easing-standard),
|
|
2847
|
+
color var(--smrt-duration-medium1) var(--smrt-easing-standard);
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2850
|
+
/* Newly revealed sidebar / dock content fades in. */
|
|
2851
|
+
.smrt-admin-shell[data-motion]:not([data-viewport='phone']) .smrt-admin-shell__edge[data-presentation='push'] .smrt-admin-shell__tenant-stack:not([hidden]),
|
|
2852
|
+
.smrt-admin-shell[data-motion]:not([data-viewport='phone']) .smrt-admin-shell__edge[data-presentation='push'] .smrt-admin-shell__panel--right:not([hidden]) {
|
|
2853
|
+
animation: smrt-admin-shell-content-in var(--smrt-duration-short2)
|
|
2854
|
+
var(--smrt-easing-standard) backwards;
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
/* Layout edit mode: zones, strips and region controls fade / scale in. */
|
|
2858
|
+
.smrt-admin-shell__slot--editing,
|
|
2859
|
+
.smrt-admin-shell__strip,
|
|
2860
|
+
.smrt-admin-shell__region-edit {
|
|
2861
|
+
animation: smrt-admin-shell-edit-in var(--smrt-duration-short2)
|
|
2862
|
+
var(--smrt-easing-standard) backwards;
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
|
|
2866
|
+
@keyframes smrt-admin-shell-content-in {
|
|
2867
|
+
from { opacity: 0; }
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2870
|
+
@keyframes smrt-admin-shell-edit-in {
|
|
2871
|
+
from { opacity: 0; transform: scale(0.96); }
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
/* View transitions: the names exist only while runViewTransition runs
|
|
2875
|
+
(html[data-smrt-view-transition]); they must be unique per document, so
|
|
2876
|
+
hosts must not reuse them. */
|
|
2877
|
+
:global([data-smrt-view-transition]) .smrt-admin-shell:not([data-viewport='phone']) :global(.smrt-admin-shell__brand) {
|
|
2878
|
+
view-transition-name: smrt-shell-brand;
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
:global([data-smrt-view-transition]) .smrt-admin-shell:not([data-viewport='phone']) .smrt-admin-shell__tenant-content,
|
|
2882
|
+
:global([data-smrt-view-transition]) .smrt-admin-shell:not([data-viewport='phone']) .smrt-admin-shell__tenant-rail-content {
|
|
2883
|
+
view-transition-name: smrt-shell-nav;
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
:global([data-smrt-view-transition]) .smrt-admin-shell:not([data-viewport='phone']) .smrt-admin-shell__edge--right {
|
|
2887
|
+
view-transition-name: smrt-shell-dock;
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2462
2890
|
@media (prefers-reduced-motion: reduce) {
|
|
2463
2891
|
.smrt-admin-shell {
|
|
2464
2892
|
--smrt-admin-shell-chrome-duration: 0ms;
|
|
2893
|
+
|
|
2465
2894
|
}
|
|
2466
2895
|
|
|
2467
2896
|
.smrt-admin-shell__edge--left,
|
|
@@ -2475,4 +2904,5 @@ function buildLayoutStyle(shell: ModuleShellState): string {
|
|
|
2475
2904
|
animation: none;
|
|
2476
2905
|
}
|
|
2477
2906
|
}
|
|
2907
|
+
}
|
|
2478
2908
|
</style>
|