@happyvertical/smrt-svelte 0.55.15 → 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.
Files changed (153) hide show
  1. package/README.md +5 -3
  2. package/agents/cookbook-shell.md +7 -1
  3. package/agents/overview-surfaces.md +5 -0
  4. package/agents/workspace.md +145 -11
  5. package/dist/browser-ai/svelte/components/DownloadProgress.svelte +22 -19
  6. package/dist/browser-ai/svelte/components/ModelStatusControl.svelte +16 -13
  7. package/dist/browser-ai/svelte/components/STTTest.svelte +41 -38
  8. package/dist/browser-ai/svelte/components/VoiceInput.svelte +17 -14
  9. package/dist/components/activity/ActivityList.svelte +1 -1
  10. package/dist/components/app/AppShell.svelte +274 -9
  11. package/dist/components/app/AppShell.svelte.d.ts +63 -2
  12. package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
  13. package/dist/components/app/DockToggles.svelte +27 -1
  14. package/dist/components/app/DockToggles.svelte.d.ts.map +1 -1
  15. package/dist/components/app/OwnerSetupForm.svelte +98 -34
  16. package/dist/components/app/OwnerSetupForm.svelte.d.ts +4 -0
  17. package/dist/components/app/OwnerSetupForm.svelte.d.ts.map +1 -1
  18. package/dist/components/app/PhoneTabBar.svelte +136 -0
  19. package/dist/components/app/PhoneTabBar.svelte.d.ts +22 -0
  20. package/dist/components/app/PhoneTabBar.svelte.d.ts.map +1 -0
  21. package/dist/components/app/ShellSettingsPage.svelte +17 -2
  22. package/dist/components/app/ShellSettingsPage.svelte.d.ts +11 -16
  23. package/dist/components/app/ShellSettingsPage.svelte.d.ts.map +1 -1
  24. package/dist/components/app/dock-toggle.d.ts +3 -2
  25. package/dist/components/app/dock-toggle.d.ts.map +1 -1
  26. package/dist/components/app/index.d.ts +2 -1
  27. package/dist/components/app/index.d.ts.map +1 -1
  28. package/dist/components/app/index.js +1 -0
  29. package/dist/components/app/owner-setup-types.d.ts +5 -0
  30. package/dist/components/app/owner-setup-types.d.ts.map +1 -1
  31. package/dist/components/app/phone-tabs.d.ts +41 -0
  32. package/dist/components/app/phone-tabs.d.ts.map +1 -0
  33. package/dist/components/app/phone-tabs.js +66 -0
  34. package/dist/components/app/slot-item.d.ts +16 -0
  35. package/dist/components/app/slot-item.d.ts.map +1 -1
  36. package/dist/components/app/view-transition.d.ts +43 -0
  37. package/dist/components/app/view-transition.d.ts.map +1 -0
  38. package/dist/components/app/view-transition.js +76 -0
  39. package/dist/components/audit/AuditList.svelte +4 -1
  40. package/dist/components/audit/RecordHistory.svelte +4 -1
  41. package/dist/components/board/Board.svelte +4 -1
  42. package/dist/components/command-palette/CommandPalette.svelte +4 -1
  43. package/dist/components/command-palette/CommandPalette.svelte.d.ts +2 -0
  44. package/dist/components/command-palette/CommandPalette.svelte.d.ts.map +1 -1
  45. package/dist/components/command-palette/CommandPaletteDialog.svelte +3 -0
  46. package/dist/components/command-palette/CommandPaletteTrigger.svelte +3 -0
  47. package/dist/components/cookbook/CookbookApp.svelte +2 -1
  48. package/dist/components/cookbook/CookbookApp.svelte.d.ts.map +1 -1
  49. package/dist/components/cookbook/CookbookSectionPage.svelte +4 -1
  50. package/dist/components/cookbook/brand-theme.d.ts.map +1 -1
  51. package/dist/components/cookbook/brand-theme.js +21 -2
  52. package/dist/components/cookbook/build.js +1 -1
  53. package/dist/components/cookbook/theme.d.ts.map +1 -1
  54. package/dist/components/cookbook/theme.js +9 -5
  55. package/dist/components/cookbook/types.d.ts +5 -1
  56. package/dist/components/cookbook/types.d.ts.map +1 -1
  57. package/dist/components/forms/AddressInput.svelte +25 -22
  58. package/dist/components/forms/CheckboxInput.svelte +8 -5
  59. package/dist/components/forms/DateRangeInput.svelte +41 -38
  60. package/dist/components/forms/DateTimeInput.svelte +29 -26
  61. package/dist/components/forms/FileUpload.svelte +24 -21
  62. package/dist/components/forms/Form.svelte +34 -31
  63. package/dist/components/forms/FormMicButton.svelte +10 -7
  64. package/dist/components/forms/FormScope.svelte +4 -1
  65. package/dist/components/forms/MeasurementInput.svelte +26 -23
  66. package/dist/components/forms/MoneyInput.svelte +18 -15
  67. package/dist/components/forms/NumberInput.svelte +17 -14
  68. package/dist/components/forms/PhoneInput.svelte +37 -34
  69. package/dist/components/forms/SearchInput.svelte +16 -13
  70. package/dist/components/forms/SelectInput.svelte +17 -14
  71. package/dist/components/forms/TextInput.svelte +19 -16
  72. package/dist/components/forms/TextareaInput.svelte +21 -18
  73. package/dist/components/import-export/ImportExport.svelte +4 -1
  74. package/dist/components/module/ModulePanel.svelte +14 -11
  75. package/dist/components/notifications/NotificationBell.svelte +4 -1
  76. package/dist/components/overview/OverviewAssistantUndo.svelte +4 -1
  77. package/dist/components/overview/OverviewGrid.svelte +11 -6
  78. package/dist/components/overview/OverviewGrid.svelte.d.ts.map +1 -1
  79. package/dist/components/overview/WidgetOptionsForm.svelte +3 -0
  80. package/dist/components/overview/widgets/ChartWidget.svelte +7 -4
  81. package/dist/components/overview/widgets/MetricWidget.svelte +5 -2
  82. package/dist/components/overview/widgets/NoteWidget.svelte +5 -2
  83. package/dist/components/overview/widgets/RecordListWidget.svelte +6 -3
  84. package/dist/components/overview/widgets/ShortcutsWidget.svelte +12 -6
  85. package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts.map +1 -1
  86. package/dist/components/screens/DetailScreen.svelte +6 -3
  87. package/dist/components/screens/EditForm.svelte +6 -3
  88. package/dist/components/screens/ListScreen.svelte +4 -1
  89. package/dist/components/screens/RecipeScreens.svelte +1 -1
  90. package/dist/components/settings/SettingsCatalog.svelte +4 -1
  91. package/dist/components/sortable/Sortable.svelte +11 -5
  92. package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -1
  93. package/dist/components/workspace/Breadcrumbs.svelte +4 -1
  94. package/dist/components/workspace/NavTree.svelte +4 -1
  95. package/dist/components/workspace/RoleShell.svelte +4 -1
  96. package/dist/components/workspace/WorkspaceShell.svelte +43 -40
  97. package/dist/components/workspace/admin-shell/ActivityItem.svelte +4 -1
  98. package/dist/components/workspace/admin-shell/ActivityList.svelte +5 -2
  99. package/dist/components/workspace/admin-shell/ActivityTicker.svelte +6 -3
  100. package/dist/components/workspace/admin-shell/ActivityToasts.svelte +4 -1
  101. package/dist/components/workspace/admin-shell/AdminShell.svelte +502 -72
  102. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +7 -1
  103. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
  104. package/dist/components/workspace/admin-shell/AppScopePanel.svelte +4 -1
  105. package/dist/components/workspace/admin-shell/HotkeyInput.svelte +4 -1
  106. package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte +21 -8
  107. package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte.d.ts +9 -2
  108. package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte.d.ts.map +1 -1
  109. package/dist/components/workspace/admin-shell/PhoneTopBar.svelte +4 -1
  110. package/dist/components/workspace/admin-shell/ShellBrand.svelte +3 -0
  111. package/dist/components/workspace/admin-shell/ShellCorner.svelte +4 -1
  112. package/dist/components/workspace/admin-shell/ShellIconButton.svelte +4 -1
  113. package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +4 -1
  114. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte +13 -7
  115. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts +1 -1
  116. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts.map +1 -1
  117. package/dist/components/workspace/admin-shell/ShellNavToggle.svelte +4 -1
  118. package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte +4 -1
  119. package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte +15 -10
  120. package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts.map +1 -1
  121. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte +236 -48
  122. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts +11 -1
  123. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts.map +1 -1
  124. package/dist/components/workspace/admin-shell/ShellTitle.svelte +4 -1
  125. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte +4 -1
  126. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte +4 -1
  127. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte +5 -2
  128. package/dist/components/workspace/admin-shell/TenantNav.svelte +81 -36
  129. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +4 -3
  130. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
  131. package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte +305 -53
  132. package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.d.ts +15 -2
  133. package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.d.ts.map +1 -1
  134. package/dist/components/workspace/admin-shell/motion.d.ts +19 -0
  135. package/dist/components/workspace/admin-shell/motion.d.ts.map +1 -0
  136. package/dist/components/workspace/admin-shell/motion.js +44 -0
  137. package/dist/components/workspace/admin-shell/settings.d.ts +1 -0
  138. package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -1
  139. package/dist/components/workspace/admin-shell/settings.js +1 -1
  140. package/dist/components/workspace/admin-shell/shell-icons.d.ts +8 -0
  141. package/dist/components/workspace/admin-shell/shell-icons.d.ts.map +1 -1
  142. package/dist/components/workspace/admin-shell/shell-icons.js +8 -0
  143. package/dist/components/workspace/admin-shell/state.svelte.d.ts +6 -0
  144. package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
  145. package/dist/components/workspace/admin-shell/state.svelte.js +15 -0
  146. package/dist/components/workspace/admin-shell/types.d.ts +13 -3
  147. package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
  148. package/dist/components/workspace/tools-dock/ToolsDock.svelte +41 -38
  149. package/dist/i18n/strings.workspace.d.ts +37 -0
  150. package/dist/i18n/strings.workspace.d.ts.map +1 -1
  151. package/dist/i18n/strings.workspace.js +42 -2
  152. package/dist/mcp-apps/McpAppsBridge.svelte +4 -1
  153. package/package.json +14 -14
@@ -1,11 +1,13 @@
1
1
  <script lang="ts">
2
- import type { DropdownPlacement, MenuItem } from '@happyvertical/smrt-ui';
2
+ import type { DropdownPlacement } from '@happyvertical/smrt-ui';
3
3
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
4
- import { Avatar, Dropdown } from '@happyvertical/smrt-ui/ui';
4
+ import { Avatar } from '@happyvertical/smrt-ui/ui';
5
+ import { tick } from 'svelte';
5
6
  import { M } from '../../../i18n/strings.workspace.js';
6
7
  import type { WorkspaceAccountTenant } from './types.js';
7
8
 
8
9
  const SIGN_OUT_ID = 'workspace-account:sign-out';
10
+ const SETTINGS_ID = 'workspace-account:settings';
9
11
  const TENANT_PREFIX = 'workspace-account:tenant:';
10
12
 
11
13
  export interface Props {
@@ -17,6 +19,8 @@ export interface Props {
17
19
  compact?: boolean;
18
20
  /** Custom display name for the user, falls back to userName. */
19
21
  userLabel?: string;
22
+ /** Email shown under the name at the top of the open menu. */
23
+ email?: string;
20
24
  /** URL for the user's avatar image. */
21
25
  avatarUrl?: string;
22
26
  /** Custom display name for the current tenant. */
@@ -27,10 +31,21 @@ export interface Props {
27
31
  tenants?: WorkspaceAccountTenant[];
28
32
  /** ID of the currently selected tenant. */
29
33
  currentTenantId?: string | null;
30
- /** Where the dropdown menu appears relative to the trigger button. */
31
- placement?: DropdownPlacement;
34
+ /**
35
+ * Where the menu appears relative to the trigger. `inline-end` opens beside
36
+ * the trigger, bottom-aligned (a compact trigger in a narrow rail).
37
+ */
38
+ placement?: DropdownPlacement | 'inline-end';
32
39
  /** Disables the account menu button. */
33
40
  disabled?: boolean;
41
+ /** Adds a Settings link to the menu. */
42
+ settingsHref?: string;
43
+ /**
44
+ * Adds a Sign out link (a GET navigation) to the menu. Never point it at a
45
+ * POST-only route such as the runtime's `/sign-out`; use `onSignOut` for
46
+ * those. Use `onSignOut` for a callback.
47
+ */
48
+ signOutHref?: string;
34
49
  /** Called when the user selects a different tenant. */
35
50
  onTenantSelect?: (tenantId: string) => void;
36
51
  /** Called when the user clicks sign out. */
@@ -42,6 +57,7 @@ let {
42
57
  density,
43
58
  compact = false,
44
59
  userLabel = '',
60
+ email = '',
45
61
  avatarUrl,
46
62
  tenantLabel = '',
47
63
  roleLabel = '',
@@ -49,11 +65,22 @@ let {
49
65
  currentTenantId = null,
50
66
  placement = 'top-start',
51
67
  disabled = false,
68
+ settingsHref,
69
+ signOutHref,
52
70
  onTenantSelect,
53
71
  onSignOut,
54
72
  }: Props = $props();
55
73
 
74
+ interface Entry {
75
+ id: string;
76
+ label: string;
77
+ disabled?: boolean;
78
+ href?: string;
79
+ }
80
+
56
81
  const { t } = useI18n();
82
+ const instanceId = $props.id();
83
+ const menuId = `smrt-account-menu-${instanceId}`;
57
84
  const identityLabel = $derived(userLabel || userName);
58
85
  const activeTenantLabel = $derived(
59
86
  tenantLabel ||
@@ -66,14 +93,15 @@ const accountContext = $derived(
66
93
  const summaryTitle = $derived(
67
94
  [identityLabel, activeTenantLabel, roleLabel].filter(Boolean).join(' · '),
68
95
  );
69
- const items = $derived.by(() => {
70
- const menuItems: MenuItem[] = [];
96
+ const showEmail = $derived(Boolean(email) && email !== identityLabel);
97
+ const entries = $derived.by(() => {
98
+ const out: Entry[] = [];
71
99
 
72
100
  if (tenants.length > 1 && onTenantSelect) {
73
101
  for (const tenant of tenants) {
74
102
  const isCurrent = tenant.id === currentTenantId;
75
103
  const detail = tenant.roleLabel ? ` — ${tenant.roleLabel}` : '';
76
- menuItems.push({
104
+ out.push({
77
105
  id: `${TENANT_PREFIX}${tenant.id}`,
78
106
  label: isCurrent
79
107
  ? `${t(M['ui.workspace_account_menu.current_tenant'], {
@@ -85,105 +113,328 @@ const items = $derived.by(() => {
85
113
  }
86
114
  }
87
115
 
88
- if (onSignOut) {
89
- menuItems.push({
116
+ if (settingsHref) {
117
+ out.push({
118
+ id: SETTINGS_ID,
119
+ label: t(M['ui.app_shell.account_settings']),
120
+ href: settingsHref,
121
+ });
122
+ }
123
+
124
+ if (onSignOut || signOutHref) {
125
+ out.push({
90
126
  id: SIGN_OUT_ID,
91
127
  label: t(M['ui.workspace_account_menu.sign_out']),
128
+ href: onSignOut ? undefined : signOutHref,
92
129
  });
93
130
  }
94
131
 
95
- return menuItems;
132
+ return out;
96
133
  });
97
134
 
98
- function handleSelect(id: string): void {
99
- if (id === SIGN_OUT_ID) {
100
- onSignOut?.();
101
- return;
135
+ let open = $state(false);
136
+ let wrapEl = $state<HTMLElement | null>(null);
137
+ let triggerEl = $state<HTMLButtonElement | null>(null);
138
+ let itemEls = $state<Array<HTMLElement | null>>([]);
139
+ const enabled = $derived(
140
+ entries.map((entry, i) => (entry.disabled ? -1 : i)).filter((i) => i >= 0),
141
+ );
142
+
143
+ async function openMenu(focusLast = false) {
144
+ open = true;
145
+ await tick();
146
+ const target = focusLast ? enabled[enabled.length - 1] : enabled[0];
147
+ if (target != null) itemEls[target]?.focus();
148
+ }
149
+
150
+ function closeMenu(refocus = true) {
151
+ open = false;
152
+ if (refocus) triggerEl?.focus();
153
+ }
154
+
155
+ function select(entry: Entry) {
156
+ if (entry.disabled) return;
157
+ if (entry.id === SIGN_OUT_ID) onSignOut?.();
158
+ else if (entry.id.startsWith(TENANT_PREFIX)) {
159
+ onTenantSelect?.(entry.id.slice(TENANT_PREFIX.length));
160
+ }
161
+ // A link navigates on its own: leave focus to the destination.
162
+ closeMenu(!entry.href);
163
+ }
164
+
165
+ function focusByOffset(offset: number) {
166
+ if (enabled.length === 0) return;
167
+ const current = itemEls.indexOf(document.activeElement as HTMLElement);
168
+ const pos = enabled.indexOf(current);
169
+ itemEls[enabled[(pos + offset + enabled.length) % enabled.length]]?.focus();
170
+ }
171
+
172
+ function onTriggerKeydown(event: KeyboardEvent) {
173
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
174
+ event.preventDefault();
175
+ openMenu(event.key === 'ArrowUp');
102
176
  }
103
- if (id.startsWith(TENANT_PREFIX)) {
104
- onTenantSelect?.(id.slice(TENANT_PREFIX.length));
177
+ }
178
+
179
+ function onMenuKeydown(event: KeyboardEvent) {
180
+ switch (event.key) {
181
+ case 'ArrowDown':
182
+ event.preventDefault();
183
+ focusByOffset(1);
184
+ break;
185
+ case 'ArrowUp':
186
+ event.preventDefault();
187
+ focusByOffset(-1);
188
+ break;
189
+ case 'Home':
190
+ event.preventDefault();
191
+ itemEls[enabled[0]]?.focus();
192
+ break;
193
+ case 'End':
194
+ event.preventDefault();
195
+ itemEls[enabled[enabled.length - 1]]?.focus();
196
+ break;
197
+ case 'Escape':
198
+ event.preventDefault();
199
+ event.stopPropagation();
200
+ closeMenu();
201
+ break;
202
+ case 'Tab':
203
+ closeMenu(false);
204
+ break;
105
205
  }
106
206
  }
207
+
208
+ // Dismiss on an outside click while open.
209
+ $effect(() => {
210
+ if (!open) return;
211
+ const onDocPointer = (event: MouseEvent) => {
212
+ if (wrapEl && !wrapEl.contains(event.target as Node)) closeMenu(false);
213
+ };
214
+ document.addEventListener('click', onDocPointer, true);
215
+ return () => document.removeEventListener('click', onDocPointer, true);
216
+ });
107
217
  </script>
108
218
 
109
- <div data-density={density} data-compact={compact ? '' : undefined} class="smrt-workspace-account-menu" title={summaryTitle}>
110
- <Dropdown
111
- {items}
112
- {placement}
113
- triggerLabel={compact ? `${t(M['ui.workspace_account_menu.open'])} ${summaryTitle}` : undefined}
114
- onselect={handleSelect}
115
- disabled={disabled || items.length === 0}
219
+ <div
220
+ bind:this={wrapEl}
221
+ data-density={density}
222
+ data-compact={compact ? '' : undefined}
223
+ class="smrt-workspace-account-menu"
224
+ title={summaryTitle}
225
+ data-smrt-component="WorkspaceAccountMenu"
226
+ >
227
+ <!-- raw-primitive-allow: menu trigger owns aria-haspopup/aria-expanded/aria-controls and an avatar + identity layout the Button primitive does not model -->
228
+ <button
229
+ bind:this={triggerEl}
230
+ type="button"
231
+ class="smrt-workspace-account-menu__trigger"
232
+ data-smrt-part="trigger"
233
+ aria-label={compact ? `${t(M['ui.workspace_account_menu.open'])} ${summaryTitle}` : undefined}
234
+ aria-haspopup="menu"
235
+ aria-expanded={open}
236
+ aria-controls={open ? menuId : undefined}
237
+ disabled={disabled || entries.length === 0}
238
+ onclick={() => (open ? closeMenu(false) : openMenu())}
239
+ onkeydown={onTriggerKeydown}
116
240
  >
117
- {#snippet trigger()}
118
- <span class="smrt-workspace-account-menu__open">
119
- {t(M['ui.workspace_account_menu.open'])}
120
- </span>
121
- <Avatar src={avatarUrl} name={userName} size="sm" aria-hidden="true" />
122
- <span class="smrt-workspace-account-menu__identity">
123
- <span class="smrt-workspace-account-menu__summary">{identityLabel}</span>
124
- {#if accountContext}
125
- <span class="smrt-workspace-account-menu__context">{accountContext}</span>
126
- {/if}
127
- </span>
128
- <span class="smrt-workspace-account-menu__indicator" aria-hidden="true">•••</span>
129
- {/snippet}
130
- </Dropdown>
241
+ <span class="smrt-workspace-account-menu__open">
242
+ {t(M['ui.workspace_account_menu.open'])}
243
+ </span>
244
+ <Avatar src={avatarUrl} name={userName} size="sm" aria-hidden="true" />
245
+ <span class="smrt-workspace-account-menu__identity">
246
+ <span class="smrt-workspace-account-menu__summary">{identityLabel}</span>
247
+ {#if accountContext}
248
+ <span class="smrt-workspace-account-menu__context">{accountContext}</span>
249
+ {/if}
250
+ </span>
251
+ <span class="smrt-workspace-account-menu__indicator" aria-hidden="true">•••</span>
252
+ </button>
253
+
254
+ {#if open}
255
+ <div class="smrt-workspace-account-menu__popover smrt-workspace-account-menu__popover--{placement}" data-smrt-part="panel">
256
+ {#if identityLabel || showEmail}
257
+ <div class="smrt-workspace-account-menu__header">
258
+ <span class="smrt-workspace-account-menu__name">{identityLabel}</span>
259
+ {#if showEmail}<span class="smrt-workspace-account-menu__email">{email}</span>{/if}
260
+ </div>
261
+ {/if}
262
+ <!-- svelte-ignore a11y_interactive_supports_focus -->
263
+ <div id={menuId} role="menu" tabindex="-1" class="smrt-workspace-account-menu__menu" aria-label={t(M['ui.app_shell.account_item'])} onkeydown={onMenuKeydown}>
264
+ {#each entries as entry, i (entry.id)}
265
+ {#if entry.href}
266
+ <a
267
+ bind:this={itemEls[i]}
268
+ role="menuitem"
269
+ class="smrt-workspace-account-menu__item"
270
+ href={entry.href}
271
+ tabindex="-1"
272
+ onclick={() => select(entry)}
273
+ >{entry.label}</a>
274
+ {:else}
275
+ <!-- raw-primitive-allow: role="menuitem" with roving tabindex inside a role="menu"; not a content button -->
276
+ <button
277
+ bind:this={itemEls[i]}
278
+ type="button"
279
+ role="menuitem"
280
+ class="smrt-workspace-account-menu__item"
281
+ disabled={entry.disabled}
282
+ tabindex="-1"
283
+ onclick={() => select(entry)}
284
+ >{entry.label}</button>
285
+ {/if}
286
+ {/each}
287
+ </div>
288
+ </div>
289
+ {/if}
131
290
  </div>
132
291
 
133
292
  <style>
293
+ @layer smrt.reset, smrt.structure, smrt.theme;
294
+ @layer smrt.theme {
134
295
  .smrt-workspace-account-menu {
296
+ position: relative;
297
+ display: flex;
135
298
  min-width: 0;
136
299
  width: 100%;
137
300
  }
138
301
 
139
302
  .smrt-workspace-account-menu[data-density='touch'] {
140
- --smrt-control-target-min: var(--smrt-touch-target-min, 48px);
303
+ --smrt-control-target-min: var(--smrt-touch-target-min);
141
304
  }
142
305
  .smrt-workspace-account-menu[data-density='comfortable'] {
143
306
  --smrt-control-target-min: 0px;
144
307
  }
145
- .smrt-workspace-account-menu :global(.dropdown__item) {
146
- min-block-size: var(--smrt-control-target-min, 0px);
147
- box-sizing: border-box;
148
- }
149
308
 
150
- .smrt-workspace-account-menu :global(.dropdown) {
151
- display: flex;
152
- width: 100%;
153
- }
154
-
155
- .smrt-workspace-account-menu :global(.dropdown__trigger) {
309
+ .smrt-workspace-account-menu__trigger {
310
+ appearance: none;
156
311
  display: grid;
157
312
  grid-template-columns: auto minmax(0, 1fr) auto;
158
313
  align-items: center;
159
314
  gap: var(--smrt-spacing-2);
315
+ box-sizing: border-box;
160
316
  width: 100%;
161
317
  min-width: 0;
162
318
  min-height: max(2.75rem, var(--smrt-control-target-min, 0px));
163
319
  padding: var(--smrt-spacing-2);
320
+ border: 1px solid var(--smrt-color-outline);
164
321
  border-radius: var(--smrt-radius-large);
322
+ background: var(--smrt-color-surface);
323
+ color: var(--smrt-color-on-surface);
324
+ font: inherit;
165
325
  text-align: start;
326
+ cursor: pointer;
327
+ }
328
+ .smrt-workspace-account-menu__trigger:hover:not(:disabled),
329
+ .smrt-workspace-account-menu__trigger[aria-expanded='true'] {
330
+ background: var(--smrt-color-surface-container-high);
331
+ }
332
+ .smrt-workspace-account-menu__trigger:focus-visible {
333
+ outline: var(--smrt-spacing-0_5) solid var(--smrt-color-primary);
334
+ outline-offset: var(--smrt-spacing-0_5);
335
+ }
336
+ .smrt-workspace-account-menu__trigger:disabled {
337
+ cursor: default;
166
338
  }
167
339
 
168
- .smrt-workspace-account-menu[data-compact] :global(.dropdown__trigger) {
340
+ .smrt-workspace-account-menu[data-compact] {
341
+ width: auto;
342
+ }
343
+ .smrt-workspace-account-menu[data-compact] .smrt-workspace-account-menu__trigger {
169
344
  display: grid;
170
345
  place-items: center;
171
346
  grid-template-columns: minmax(0, 1fr);
347
+ min-width: max(2.75rem, var(--smrt-control-target-min, 0px));
172
348
  padding: var(--smrt-spacing-1);
349
+ border-color: transparent;
350
+ border-radius: var(--smrt-radius-full);
351
+ background: transparent;
352
+ }
353
+ .smrt-workspace-account-menu[data-compact] .smrt-workspace-account-menu__trigger:hover:not(:disabled),
354
+ .smrt-workspace-account-menu[data-compact] .smrt-workspace-account-menu__trigger[aria-expanded='true'] {
355
+ background: var(--smrt-color-surface-container-high);
173
356
  }
174
357
 
175
358
  .smrt-workspace-account-menu[data-compact] .smrt-workspace-account-menu__identity,
176
- .smrt-workspace-account-menu[data-compact] .smrt-workspace-account-menu__indicator,
177
- .smrt-workspace-account-menu[data-compact] .smrt-workspace-account-menu__open {
359
+ .smrt-workspace-account-menu[data-compact] .smrt-workspace-account-menu__indicator {
178
360
  display: none;
179
361
  }
180
362
 
181
- .smrt-workspace-account-menu :global(.dropdown__menu) {
363
+ .smrt-workspace-account-menu__popover {
364
+ position: absolute;
365
+ z-index: var(--smrt-z-index-dropdown);
182
366
  box-sizing: border-box;
183
- width: 100%;
184
367
  min-width: 12rem;
185
368
  max-height: min(24rem, 70vh);
186
369
  overflow-y: auto;
370
+ margin: var(--smrt-spacing-1) 0;
371
+ padding: var(--smrt-spacing-1);
372
+ border: 1px solid var(--smrt-color-outline-variant);
373
+ border-radius: var(--smrt-radius-medium);
374
+ background: var(--smrt-color-surface-container);
375
+ box-shadow: var(--smrt-elevation-2);
376
+ }
377
+ .smrt-workspace-account-menu__popover--bottom-start { inset-block-start: 100%; inset-inline-start: 0; }
378
+ .smrt-workspace-account-menu__popover--bottom-end { inset-block-start: 100%; inset-inline-end: 0; }
379
+ .smrt-workspace-account-menu__popover--top-start { inset-block-end: 100%; inset-inline-start: 0; }
380
+ .smrt-workspace-account-menu__popover--top-end { inset-block-end: 100%; inset-inline-end: 0; }
381
+ .smrt-workspace-account-menu__popover--inline-end {
382
+ inset-block-end: 0;
383
+ inset-inline-start: 100%;
384
+ margin: 0 var(--smrt-spacing-2);
385
+ }
386
+
387
+ .smrt-workspace-account-menu__header {
388
+ display: grid;
389
+ gap: var(--smrt-spacing-1);
390
+ padding: var(--smrt-spacing-2) var(--smrt-spacing-3);
391
+ border-block-end: 1px solid var(--smrt-color-outline-variant);
392
+ margin-block-end: var(--smrt-spacing-1);
393
+ }
394
+ .smrt-workspace-account-menu__name {
395
+ color: var(--smrt-color-on-surface);
396
+ font-size: var(--smrt-typography-body-small-size);
397
+ font-weight: var(--smrt-typography-weight-medium);
398
+ overflow-wrap: anywhere;
399
+ }
400
+ .smrt-workspace-account-menu__email {
401
+ color: var(--smrt-color-on-surface-variant);
402
+ font-size: var(--smrt-typography-label-small-size);
403
+ overflow-wrap: anywhere;
404
+ }
405
+
406
+ .smrt-workspace-account-menu__menu {
407
+ display: flex;
408
+ flex-direction: column;
409
+ gap: var(--smrt-spacing-1);
410
+ }
411
+ .smrt-workspace-account-menu__item {
412
+ appearance: none;
413
+ display: flex;
414
+ align-items: center;
415
+ box-sizing: border-box;
416
+ min-block-size: max(2.75rem, var(--smrt-control-target-min, 0px));
417
+ padding: var(--smrt-spacing-2) var(--smrt-spacing-3);
418
+ border: none;
419
+ border-radius: var(--smrt-radius-small);
420
+ background: none;
421
+ color: var(--smrt-color-on-surface);
422
+ font: inherit;
423
+ text-align: start;
424
+ text-decoration: none;
425
+ white-space: nowrap;
426
+ cursor: pointer;
427
+ }
428
+ .smrt-workspace-account-menu__item:hover:not(:disabled) {
429
+ background: var(--smrt-color-surface-container-high);
430
+ }
431
+ .smrt-workspace-account-menu__item:focus-visible {
432
+ outline: var(--smrt-spacing-0_5) solid var(--smrt-color-primary);
433
+ outline-offset: calc(-1 * var(--smrt-spacing-0_5));
434
+ }
435
+ .smrt-workspace-account-menu__item:disabled {
436
+ color: var(--smrt-color-on-surface-variant);
437
+ cursor: default;
187
438
  }
188
439
 
189
440
  .smrt-workspace-account-menu__identity {
@@ -227,4 +478,5 @@ function handleSelect(id: string): void {
227
478
  white-space: nowrap;
228
479
  border: 0;
229
480
  }
481
+ }
230
482
  </style>
@@ -9,6 +9,8 @@ export interface Props {
9
9
  compact?: boolean;
10
10
  /** Custom display name for the user, falls back to userName. */
11
11
  userLabel?: string;
12
+ /** Email shown under the name at the top of the open menu. */
13
+ email?: string;
12
14
  /** URL for the user's avatar image. */
13
15
  avatarUrl?: string;
14
16
  /** Custom display name for the current tenant. */
@@ -19,10 +21,21 @@ export interface Props {
19
21
  tenants?: WorkspaceAccountTenant[];
20
22
  /** ID of the currently selected tenant. */
21
23
  currentTenantId?: string | null;
22
- /** Where the dropdown menu appears relative to the trigger button. */
23
- placement?: DropdownPlacement;
24
+ /**
25
+ * Where the menu appears relative to the trigger. `inline-end` opens beside
26
+ * the trigger, bottom-aligned (a compact trigger in a narrow rail).
27
+ */
28
+ placement?: DropdownPlacement | 'inline-end';
24
29
  /** Disables the account menu button. */
25
30
  disabled?: boolean;
31
+ /** Adds a Settings link to the menu. */
32
+ settingsHref?: string;
33
+ /**
34
+ * Adds a Sign out link (a GET navigation) to the menu. Never point it at a
35
+ * POST-only route such as the runtime's `/sign-out`; use `onSignOut` for
36
+ * those. Use `onSignOut` for a callback.
37
+ */
38
+ signOutHref?: string;
26
39
  /** Called when the user selects a different tenant. */
27
40
  onTenantSelect?: (tenantId: string) => void;
28
41
  /** Called when the user clicks sign out. */
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceAccountMenu.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAY,MAAM,wBAAwB,CAAC;AAI1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGzD,MAAM,WAAW,KAAK;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC;IAClC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACnC,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,sEAAsE;IACtE,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uDAAuD;IACvD,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAuGD,QAAA,MAAM,oBAAoB,2CAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"WorkspaceAccountMenu.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGzD,MAAM,WAAW,KAAK;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC;IAClC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACnC,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,iBAAiB,GAAG,YAAY,CAAC;IAC7C,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AA8ND,QAAA,MAAM,oBAAoB,2CAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /** True when the user asked for reduced motion (false off the browser). */
2
+ export declare function prefersReducedMotion(): boolean;
3
+ /** Parses a CSS `<time>` (`200ms`, `0.2s`) to milliseconds; 0 when unparsable. */
4
+ export declare function parseCssTime(value: string): number;
5
+ /**
6
+ * Reads a duration token (`--smrt-duration-short4`) off `element` (or the
7
+ * document root) and returns it in milliseconds. Returns 0 under reduced
8
+ * motion, off the browser, or when the token is missing, so callers can pass
9
+ * the result straight to a Svelte `duration` option.
10
+ */
11
+ export declare function tokenDuration(name: string, element?: Element | null): number;
12
+ /** `animate:` function: FLIP reorder with a token-driven duration. */
13
+ export declare function flipRow(node: Element, rects: {
14
+ from: DOMRect;
15
+ to: DOMRect;
16
+ }, params?: {
17
+ token?: string;
18
+ }): import("svelte/animate").AnimationConfig;
19
+ //# sourceMappingURL=motion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/motion.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,wBAAgB,oBAAoB,IAAI,OAAO,CAM9C;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,MAAM,CAU5E;AAED,sEAAsE;AACtE,wBAAgB,OAAO,CACrB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,EACrC,MAAM,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,4CAKhC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Motion helpers shared by the shell lists. Durations come from the
3
+ * `--smrt-duration-*` theme tokens (never literals) so a theme controls the
4
+ * pace, and everything collapses to zero under `prefers-reduced-motion`.
5
+ */
6
+ import { flip } from 'svelte/animate';
7
+ const REDUCED_MOTION = '(prefers-reduced-motion: reduce)';
8
+ const DEFAULT_TOKEN = '--smrt-duration-short4';
9
+ /** True when the user asked for reduced motion (false off the browser). */
10
+ export function prefersReducedMotion() {
11
+ return (typeof window !== 'undefined' &&
12
+ typeof window.matchMedia === 'function' &&
13
+ window.matchMedia(REDUCED_MOTION).matches);
14
+ }
15
+ /** Parses a CSS `<time>` (`200ms`, `0.2s`) to milliseconds; 0 when unparsable. */
16
+ export function parseCssTime(value) {
17
+ const match = /^(-?\d*\.?\d+)(ms|s)$/.exec(value.trim());
18
+ if (!match)
19
+ return 0;
20
+ const amount = Number(match[1]) * (match[2] === 's' ? 1000 : 1);
21
+ return Number.isFinite(amount) && amount > 0 ? amount : 0;
22
+ }
23
+ /**
24
+ * Reads a duration token (`--smrt-duration-short4`) off `element` (or the
25
+ * document root) and returns it in milliseconds. Returns 0 under reduced
26
+ * motion, off the browser, or when the token is missing, so callers can pass
27
+ * the result straight to a Svelte `duration` option.
28
+ */
29
+ export function tokenDuration(name, element) {
30
+ if (prefersReducedMotion())
31
+ return 0;
32
+ if (typeof document === 'undefined' ||
33
+ typeof getComputedStyle !== 'function') {
34
+ return 0;
35
+ }
36
+ const target = element ?? document.documentElement;
37
+ return parseCssTime(getComputedStyle(target).getPropertyValue(name));
38
+ }
39
+ /** `animate:` function: FLIP reorder with a token-driven duration. */
40
+ export function flipRow(node, rects, params = {}) {
41
+ return flip(node, rects, {
42
+ duration: tokenDuration(params.token ?? DEFAULT_TOKEN, node),
43
+ });
44
+ }
@@ -1,6 +1,7 @@
1
1
  import { type ShellLayoutPanel } from './layout.js';
2
2
  import type { PanelEdge, PanelState, ResolvedShellConfig, ShellHotkeyBinding, ShellPanelConfig, ShellPanelDefaults, ShellPanelResize, ShellSettingsAdapter, ShellSettingsDelta, ShellViewport } from './types.js';
3
3
  export declare const DEFAULT_SHELL_KEYMAP: Record<PanelEdge, ShellHotkeyBinding>;
4
+ export declare const DEFAULT_PANEL_CONFIG: Record<PanelEdge, ShellPanelConfig>;
4
5
  export declare function resolveShellConfig(appDefaults?: ShellPanelDefaults): ResolvedShellConfig;
5
6
  /**
6
7
  * An edge's state: hidden edges (by the host or the user's layout) stay
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,SAAS,EAAE,kBAAkB,CAKtE,CAAC;AA6CF,wBAAgB,kBAAkB,CAChC,WAAW,GAAE,kBAAuB,GACnC,mBAAmB,CA2BrB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,EACxB,QAAQ,GAAE,kBAAuB,EACjC,QAAQ,CAAC,EAAE,aAAa,EACxB,WAAW,CAAC,EAAE,gBAAgB,GAC7B,UAAU,CASZ;AAED,yDAAyD;AACzD,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,gBAAgB,CAIjE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,GACvB,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAUnC;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GACjC,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,OAAO,CAKT;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,mBAAmB,GAC1B,kBAAkB,CAqBpB;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,EACxB,QAAQ,GAAE,kBAAuB,GAChC,kBAAkB,GAAG,IAAI,CAM3B;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,kBAAkB,GACvB,kBAAkB,CAiBpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,CA2BpB;AAED,qBAAa,gCAAiC,YAAW,oBAAoB;IAC/D,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,MAAM;IAExC,IAAI,IAAI,kBAAkB,GAAG,IAAI;IAWjC,KAAK,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;CAOvC"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,SAAS,EAAE,kBAAkB,CAKtE,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAyCpE,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,WAAW,GAAE,kBAAuB,GACnC,mBAAmB,CA2BrB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,EACxB,QAAQ,GAAE,kBAAuB,EACjC,QAAQ,CAAC,EAAE,aAAa,EACxB,WAAW,CAAC,EAAE,gBAAgB,GAC7B,UAAU,CASZ;AAED,yDAAyD;AACzD,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,gBAAgB,CAIjE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,GACvB,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAUnC;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GACjC,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,OAAO,CAKT;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,mBAAmB,GAC1B,kBAAkB,CAqBpB;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,gBAAgB,EACxB,QAAQ,GAAE,kBAAuB,GAChC,kBAAkB,GAAG,IAAI,CAM3B;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,kBAAkB,GACvB,kBAAkB,CAiBpB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,kBAAkB,GACxB,kBAAkB,CA2BpB;AAED,qBAAa,gCAAiC,YAAW,oBAAoB;IAC/D,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,MAAM;IAExC,IAAI,IAAI,kBAAkB,GAAG,IAAI;IAWjC,KAAK,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;CAOvC"}
@@ -6,7 +6,7 @@ export const DEFAULT_SHELL_KEYMAP = {
6
6
  bottom: { code: 'KeyS' },
7
7
  right: { code: 'KeyD' },
8
8
  };
9
- const DEFAULT_PANEL_CONFIG = {
9
+ export const DEFAULT_PANEL_CONFIG = {
10
10
  top: {
11
11
  edge: 'top',
12
12
  scope: 'app',
@@ -33,11 +33,19 @@ export declare const SHELL_ICON_PATHS: {
33
33
  readonly repeat: "M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z";
34
34
  readonly tag: "M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58s1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z";
35
35
  readonly archive: "M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z";
36
+ readonly placeholder: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16zm0 3a5 5 0 1 1 0 10 5 5 0 0 1 0-10z";
36
37
  readonly chevronRight: "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z";
38
+ readonly menu: "M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z";
39
+ readonly chat: "M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z";
40
+ readonly close: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z";
37
41
  };
38
42
  export type ShellIconName = keyof typeof SHELL_ICON_PATHS;
43
+ /** Icon used for a dock or focus tool that does not bring its own. */
44
+ export declare const SHELL_DEFAULT_TOOL_ICON: ShellIconName;
39
45
  /** Section icon used when neither the host nor the user chose one. */
40
46
  export declare const SHELL_DEFAULT_SECTION_ICON: ShellIconName;
47
+ /** Rail glyph for an entry that has no icon of its own. */
48
+ export declare const SHELL_PLACEHOLDER_ICON: ShellIconName;
41
49
  /** Icons the section icon picker offers (a subset of the shell icon set). */
42
50
  export declare const SHELL_SECTION_ICONS: readonly ShellIconName[];
43
51
  /** True when `name` is one of the shell's built-in icon names. */
@@ -1 +1 @@
1
- {"version":3,"file":"shell-icons.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/shell-icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAE1D,sEAAsE;AACtE,eAAO,MAAM,0BAA0B,EAAE,aAAwB,CAAC;AAElE,6EAA6E;AAC7E,eAAO,MAAM,mBAAmB,EAAE,SAAS,aAAa,EAqBvD,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,aAAa,CAEnE"}
1
+ {"version":3,"file":"shell-icons.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/shell-icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsDnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAE1D,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,EAAE,aAAwB,CAAC;AAE/D,sEAAsE;AACtE,eAAO,MAAM,0BAA0B,EAAE,aAAwB,CAAC;AAElE,2DAA2D;AAC3D,eAAO,MAAM,sBAAsB,EAAE,aAA6B,CAAC;AAEnE,6EAA6E;AAC7E,eAAO,MAAM,mBAAmB,EAAE,SAAS,aAAa,EAqBvD,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,aAAa,CAEnE"}
@@ -33,10 +33,18 @@ export const SHELL_ICON_PATHS = {
33
33
  repeat: 'M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z',
34
34
  tag: 'M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58s1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z',
35
35
  archive: 'M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z',
36
+ placeholder: 'M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16zm0 3a5 5 0 1 1 0 10 5 5 0 0 1 0-10z',
36
37
  chevronRight: 'M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z',
38
+ menu: 'M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z',
39
+ chat: 'M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z',
40
+ close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z',
37
41
  };
42
+ /** Icon used for a dock or focus tool that does not bring its own. */
43
+ export const SHELL_DEFAULT_TOOL_ICON = 'wrench';
38
44
  /** Section icon used when neither the host nor the user chose one. */
39
45
  export const SHELL_DEFAULT_SECTION_ICON = 'folder';
46
+ /** Rail glyph for an entry that has no icon of its own. */
47
+ export const SHELL_PLACEHOLDER_ICON = 'placeholder';
40
48
  /** Icons the section icon picker offers (a subset of the shell icon set). */
41
49
  export const SHELL_SECTION_ICONS = [
42
50
  'folder',