@happyvertical/smrt-svelte 0.55.1 → 0.55.3
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 +29 -2
- package/agents/components.md +44 -1
- package/agents/workspace.md +77 -2
- package/dist/components/app/AppShell.svelte +121 -9
- package/dist/components/app/AppShell.svelte.d.ts +24 -2
- package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
- package/dist/components/app/DockToggles.svelte +103 -0
- package/dist/components/app/DockToggles.svelte.d.ts +8 -0
- package/dist/components/app/DockToggles.svelte.d.ts.map +1 -0
- package/dist/components/app/dock-toggle.d.ts +14 -0
- package/dist/components/app/dock-toggle.d.ts.map +1 -0
- package/dist/components/app/dock-toggle.js +1 -0
- package/dist/components/app/index.d.ts +2 -0
- package/dist/components/app/index.d.ts.map +1 -1
- package/dist/components/app/index.js +1 -0
- package/dist/components/board/Board.svelte +92 -394
- package/dist/components/board/Board.svelte.d.ts.map +1 -1
- package/dist/components/forms/RelationInput.svelte +379 -0
- package/dist/components/forms/RelationInput.svelte.d.ts +75 -0
- package/dist/components/forms/RelationInput.svelte.d.ts.map +1 -0
- package/dist/components/forms/index.d.ts +2 -1
- package/dist/components/forms/index.d.ts.map +1 -1
- package/dist/components/forms/index.js +1 -0
- package/dist/components/forms/types.d.ts +9 -0
- package/dist/components/forms/types.d.ts.map +1 -1
- package/dist/components/sortable/Sortable.svelte +359 -0
- package/dist/components/sortable/Sortable.svelte.d.ts +26 -0
- package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -0
- package/dist/components/sortable/controller.svelte.d.ts +152 -0
- package/dist/components/sortable/controller.svelte.d.ts.map +1 -0
- package/dist/components/sortable/controller.svelte.js +453 -0
- package/dist/components/sortable/index.d.ts +5 -0
- package/dist/components/sortable/index.d.ts.map +1 -0
- package/dist/components/sortable/index.js +2 -0
- package/dist/components/sortable/types.d.ts +80 -0
- package/dist/components/sortable/types.d.ts.map +1 -0
- package/dist/components/sortable/types.js +1 -0
- package/dist/components/workspace/admin-shell/AdminShell.svelte +49 -1
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +196 -0
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte.d.ts +17 -0
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte +69 -3
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/dock.d.ts +37 -0
- package/dist/components/workspace/admin-shell/dock.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/dock.js +25 -0
- package/dist/components/workspace/admin-shell/layout-context.d.ts +7 -0
- package/dist/components/workspace/admin-shell/layout-context.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/layout-context.js +17 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts +69 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.js +91 -0
- package/dist/components/workspace/admin-shell/layout.d.ts +120 -0
- package/dist/components/workspace/admin-shell/layout.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/layout.js +402 -0
- package/dist/components/workspace/admin-shell/settings.d.ts +6 -4
- package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/settings.js +14 -4
- package/dist/components/workspace/admin-shell/state.svelte.d.ts +59 -1
- package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/state.svelte.js +146 -2
- package/dist/components/workspace/admin-shell/types.d.ts +52 -0
- package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
- package/dist/components/workspace/index.d.ts +6 -1
- package/dist/components/workspace/index.d.ts.map +1 -1
- package/dist/components/workspace/index.js +5 -0
- package/dist/i18n/server.d.ts +1 -0
- package/dist/i18n/server.d.ts.map +1 -1
- package/dist/i18n/server.js +1 -0
- package/dist/i18n/strings.sortable.d.ts +13 -0
- package/dist/i18n/strings.sortable.d.ts.map +1 -0
- package/dist/i18n/strings.sortable.js +13 -0
- package/dist/i18n/strings.workspace.d.ts +13 -0
- package/dist/i18n/strings.workspace.d.ts.map +1 -1
- package/dist/i18n/strings.workspace.js +13 -0
- package/package.json +26 -15
package/README.md
CHANGED
|
@@ -32,6 +32,24 @@ pipeline (`opportunity.stage`) without importing `@happyvertical/smrt-projects`.
|
|
|
32
32
|
|
|
33
33
|
Svelte 5 component library for the s-m-r-t framework. Provides UI components, browser AI integration (STT/TTS/LLM with warm cache), a theme system, permission-aware rendering, and module UI registry for agent admin panels.
|
|
34
34
|
|
|
35
|
+
## Sortable and shell layout
|
|
36
|
+
|
|
37
|
+
`@happyvertical/smrt-svelte/sortable` provides `Sortable`, an accessible
|
|
38
|
+
(pointer, touch, keyboard, screen-reader announcements) list of containers and
|
|
39
|
+
items that share Board's drag engine. `AppShell` lets users customize their
|
|
40
|
+
shell: pass `layout` and `onlayoutchange` to own persistence (for example in an
|
|
41
|
+
exported app blueprint), or neither to store it in the user's settings. Mount
|
|
42
|
+
`ShellLayoutEditor` (from `/app` or `/workspace`) on a settings page, and call
|
|
43
|
+
`useShellLayout()` to make the same changes from code or an assistant. See
|
|
44
|
+
`agents/workspace.md`; the pure `ShellLayout` model is published without Svelte
|
|
45
|
+
as `@happyvertical/smrt-svelte/workspace/layout`.
|
|
46
|
+
|
|
47
|
+
```svelte
|
|
48
|
+
<AppShell {nav} {navGroups} layout={stored} onlayoutchange={(next) => (stored = next)}>
|
|
49
|
+
<ShellLayoutEditor />
|
|
50
|
+
</AppShell>
|
|
51
|
+
```
|
|
52
|
+
|
|
35
53
|
## Installation
|
|
36
54
|
|
|
37
55
|
```bash
|
|
@@ -486,6 +504,15 @@ keys the shell renders exactly as before.
|
|
|
486
504
|
- **Nav attention**: a `ShellNavItem` with `attention: true` (or a string
|
|
487
505
|
label) shows a dot in `TenantNav`, over the icon when collapsed, and
|
|
488
506
|
announces the label ("Needs attention" by default) inside the link.
|
|
507
|
+
- **Nav action**: a `ShellNavItem` with `action: { href, label, icon?,
|
|
508
|
+
visibility? }` renders a separate icon-only link after the item's link
|
|
509
|
+
(`aria-label`/tooltip = `label`, default settings-gear icon,
|
|
510
|
+
`aria-current="page"` on its own page). `visibility: 'active'` omits the link
|
|
511
|
+
from the DOM unless the item's section is current: for a `ShellNavGroup`
|
|
512
|
+
item, any item of the group, their children, or any action href is current;
|
|
513
|
+
for a top-level item, the item, its children, or its action href. A collapsed
|
|
514
|
+
nav renders no actions (the action page stays reachable by its route).
|
|
515
|
+
`AppShell` passes `nav`/`navGroups` through unchanged.
|
|
489
516
|
- **Public region ids** (`ADMIN_SHELL_REGION_IDS`): `smrt-admin-shell-header`,
|
|
490
517
|
`smrt-admin-shell-{top,left,right,bottom}-panel`, and
|
|
491
518
|
`smrt-admin-shell-main`, which is the page scroller.
|
|
@@ -510,7 +537,7 @@ importable, even if it appears in `dist/`.
|
|
|
510
537
|
| `@happyvertical/smrt-svelte/forms` | Form inputs (TextInput, Select, MoneyInput, DateTimeInput, Toggle, etc.) |
|
|
511
538
|
| `@happyvertical/smrt-svelte/settings` | Server-paged settings search, selection, and list/detail layout (`SettingsCatalog`, `paginateSettingsCatalog`) |
|
|
512
539
|
| `@happyvertical/smrt-svelte/workspace` | AdminShell, ShellState, tenant nav, focus tools, settings, activities, and system/app panels |
|
|
513
|
-
| `@happyvertical/smrt-svelte/app` | `AppShell` (Provider + themes + AdminShell + nav/dock slots), `OwnerSetupForm` (first-run owner setup), `ShellSettingsPage`, `RuntimeDiagnosticsWebMcp` |
|
|
540
|
+
| `@happyvertical/smrt-svelte/app` | `AppShell` (Provider + themes + AdminShell + nav/dock slots, `dockToggles` header buttons), `OwnerSetupForm` (first-run owner setup), `ShellSettingsPage`, `RuntimeDiagnosticsWebMcp` |
|
|
514
541
|
| `@happyvertical/smrt-svelte/app/runtime-diagnostics` | Svelte-free diagnostics WebMCP registration and its tool name/endpoint constants, importable from server routes |
|
|
515
542
|
| `@happyvertical/smrt-svelte/workspace/legacy` | Opt-in ToolsDock compatibility surface for applications migrating to AdminShell |
|
|
516
543
|
| `@happyvertical/smrt-svelte/workspace/server` | Server-side workspace helpers (Node only) |
|
|
@@ -560,7 +587,7 @@ clears it.
|
|
|
560
587
|
|
|
561
588
|
### Components by Category
|
|
562
589
|
|
|
563
|
-
**Forms**: `AddressInput`, `CheckboxInput`, `DateRangeInput`, `DateTimeInput`, `FileUpload`, `Form`, `FormGroup`, `FormMicButton`, `Input`, `MeasurementInput`, `MoneyInput`, `NumberInput`, `PhoneInput`, `SearchInput`, `Select`, `SelectInput`, `Textarea`, `TextareaInput`, `TextInput`, `Toggle`
|
|
590
|
+
**Forms**: `AddressInput`, `CheckboxInput`, `DateRangeInput`, `DateTimeInput`, `FileUpload`, `Form`, `FormGroup`, `FormMicButton`, `Input`, `MeasurementInput`, `MoneyInput`, `NumberInput`, `PhoneInput`, `RelationInput`, `SearchInput`, `Select`, `SelectInput`, `Textarea`, `TextareaInput`, `TextInput`, `Toggle`
|
|
564
591
|
|
|
565
592
|
**Layout**: `Container`, `EmptyState`, `Footer`, `Grid`, `Header`, `Masthead`, `PageHeader`, `SummaryCard`
|
|
566
593
|
|
package/agents/components.md
CHANGED
|
@@ -15,10 +15,11 @@ the top-of-stack, domain-aware pieces:
|
|
|
15
15
|
| Category | Components |
|
|
16
16
|
|----------|------------|
|
|
17
17
|
| AI | `Provider`, `AILoadingOverlay`, `CapabilityGate`, `DownloadProgress`, `STTTest`, `VoiceInput` |
|
|
18
|
-
| Forms (`/forms`) | `TextInput`, `Select`, `MoneyInput`, `DateTimeInput`, `Toggle`, `FileUpload`, `AddressInput`, + more (AI-wired inputs use the hooks/browser-ai here) |
|
|
18
|
+
| Forms (`/forms`) | `TextInput`, `Select`, `MoneyInput`, `DateTimeInput`, `Toggle`, `FileUpload`, `AddressInput`, `RelationInput`, + more (AI-wired inputs use the hooks/browser-ai here) |
|
|
19
19
|
| Module | `ModulePanel` |
|
|
20
20
|
| Settings (`/settings`) | `SettingsCatalog`, `paginateSettingsCatalog` |
|
|
21
21
|
| Audit (root export) | `RecordHistory`, `AuditList` — authorized data props; [contract](../../../docs/content/audit-trail.md) |
|
|
22
|
+
| Board (`/board`) / Sortable (`/sortable`) | `Board` (kanban) and `Sortable` (nested lists) share one headless drag engine, `SortableController` — [details](workspace.md#sortable-and-the-board-engine) |
|
|
22
23
|
| Workspace (`/workspace`) | `AdminShell`, `ShellState`, `TenantNav`, focus tools, settings, activities, and system/app panels |
|
|
23
24
|
| Legacy workspace (`/workspace/legacy`) | First-generation `ToolsDock` compatibility surface during AdminShell migration |
|
|
24
25
|
|
|
@@ -49,6 +50,48 @@ migrate domain re-rolls *onto* them rather than build new primitives:
|
|
|
49
50
|
flow.
|
|
50
51
|
- **`Card`** (`./ui`) — the standard surface/container; retire local card CSS.
|
|
51
52
|
|
|
53
|
+
### `RelationInput` (`./forms`, #3600)
|
|
54
|
+
|
|
55
|
+
Searchable single-select for relation (foreign-key) fields, a thin wrapper over
|
|
56
|
+
the smrt-ui `Combobox`. It is presentation only: the caller supplies the data,
|
|
57
|
+
so the same lookup an assistant uses to turn "Acme" into a record id backs the
|
|
58
|
+
picker. Option shape is `RelationOption` — `{ id, label, detail? }`.
|
|
59
|
+
|
|
60
|
+
- **Props.** `name`, `label`, `value` (bindable id, `''` = none), `required`,
|
|
61
|
+
`disabled`, `error`, `placeholder`, `description`, `search(query)`, optional
|
|
62
|
+
`resolve(id)` and `onCreate(query)`, plus `debounceMs` (250), `interaction`,
|
|
63
|
+
`onchange` and overridable text (`createLabel`, `clearLabel`, `loadingText`,
|
|
64
|
+
`emptyText`, `errorText`, `resultsText`).
|
|
65
|
+
- **`search`** runs with `''` when the list opens and then debounced per
|
|
66
|
+
keystroke; a response for a superseded query is dropped. A rejected search
|
|
67
|
+
shows `errorText` and the next keystroke retries.
|
|
68
|
+
- **`resolve`** supplies the label of a `value` that has not been searched yet
|
|
69
|
+
(initial value, parent rebind, form reset). Without it such a value shows an
|
|
70
|
+
empty field, never the raw id. A `null` result also leaves the field empty.
|
|
71
|
+
- **`onCreate`** adds a "New ..." button; it receives the text most recently
|
|
72
|
+
searched for and may return the created `RelationOption`, which is selected.
|
|
73
|
+
- **Form integration** is through `Combobox`'s control registration (rich `Form`
|
|
74
|
+
provides the registry), not a `FieldDefinition`: agents see a `combobox`
|
|
75
|
+
control whose value is the id. The form posts the id under `name`.
|
|
76
|
+
- **Known limit.** An agent staging a value through the registered control can
|
|
77
|
+
only choose among the options last listed (the registry matches against
|
|
78
|
+
`options`; `allowCustom` is off), so it cannot write an id it has not
|
|
79
|
+
searched. It fails closed. Writing a resolved id needs an async hook on
|
|
80
|
+
`Combobox` and is tracked separately.
|
|
81
|
+
- **Stale options.** Typing clears the listed options until the new search
|
|
82
|
+
answers, so Enter or a click can never pick a record for an older query.
|
|
83
|
+
- **Clear button** shows only when not `required`, not `disabled`, and a value
|
|
84
|
+
is set; it returns focus to the field.
|
|
85
|
+
- **Accessibility** is the combobox pattern (`role=combobox`, `aria-expanded`,
|
|
86
|
+
`aria-activedescendant`, listbox/option, Arrow/Enter/Escape) plus a polite
|
|
87
|
+
`role=status` live region announcing searching / "N results" / no matches,
|
|
88
|
+
`aria-busy` while fetching, and `aria-invalid` + `aria-describedby` for
|
|
89
|
+
`error` and `description`.
|
|
90
|
+
- Options render `detail` under the label, so the option's accessible name
|
|
91
|
+
includes it. The `Combobox` additions that make this possible (`filter`,
|
|
92
|
+
`onquery`, `status`, `busy`, `invalid`, `describedby`, `optionContent`) are
|
|
93
|
+
generic and default to the previous behaviour.
|
|
94
|
+
|
|
52
95
|
### Import convention (S10 #1415)
|
|
53
96
|
|
|
54
97
|
Domain packages **consume** these primitives; they do not re-roll them. The
|
package/agents/workspace.md
CHANGED
|
@@ -172,6 +172,64 @@ enforce permissions.
|
|
|
172
172
|
|
|
173
173
|
`ActivityTicker` accepts optional `statuses` restricted to queued/running; running-only remains the default. Opting into queued work adds an explicit localized Queued label without progress. Terminal outcomes belong in expanded `ActivityList`, with retention controlled by the app-owned data source.
|
|
174
174
|
|
|
175
|
+
## Shell layout customization
|
|
176
|
+
|
|
177
|
+
Users can show/hide the edge panels and reorder, hide, and move navigation
|
|
178
|
+
sections and items. Source: `workspace/admin-shell/layout.ts` (pure model),
|
|
179
|
+
`layout-controller.svelte.ts` (the API), `ShellLayoutEditor.svelte` (the
|
|
180
|
+
control panel), wired by `app/AppShell.svelte`.
|
|
181
|
+
|
|
182
|
+
- **`ShellLayout`** is a versioned (`version: 1`), JSON-serializable sparse
|
|
183
|
+
delta: `sectionOrder`, `itemOrder` (per section), `hidden` (section and item
|
|
184
|
+
ids), `moved` (item id to section id), `panels` (per edge `visible` /
|
|
185
|
+
`initial`). It is what a host stores or exports (smrt-planner bundles it in
|
|
186
|
+
its app blueprint). `normalizeShellLayout(unknown)` reads untrusted JSON and
|
|
187
|
+
never throws (unknown version yields an empty layout).
|
|
188
|
+
- **Ids.** Sections: `ShellNavGroup.id ?? heading`; items: `ShellNavItem.id ??
|
|
189
|
+
href`; one shared namespace (duplicates get `#2`, `#3`). Set explicit ids
|
|
190
|
+
when headings are translated or hrefs change. The flat `nav` items are the
|
|
191
|
+
implicit first section, `@root` (`SHELL_NAV_ROOT_SECTION_ID`): items can be
|
|
192
|
+
moved in and out, the section itself cannot move or hide.
|
|
193
|
+
- **`applyShellLayout(nav, groups, panels, layout)`** is pure and total. Ids the
|
|
194
|
+
host no longer has are ignored; new host items and sections keep their
|
|
195
|
+
default slots (listed ids permute among the slots they occupy). A hidden
|
|
196
|
+
section hides its items; a section the layout empties is dropped from
|
|
197
|
+
`groups`; an empty layout returns the inputs unchanged. A layout can hide a
|
|
198
|
+
panel but cannot bring back one the host removed (`false` / `initial:
|
|
199
|
+
'hidden'`). Published from the browser-safe `./workspace/layout` subpath (no
|
|
200
|
+
Svelte) as well as `./workspace`.
|
|
201
|
+
- **Persistence is host-owned.** `AppShell` takes `layout` and `onlayoutchange`:
|
|
202
|
+
with `layout` the host is the single source of truth (pass `null` for none);
|
|
203
|
+
with only `onlayoutchange` the shell keeps the value in memory and reports
|
|
204
|
+
edits; with neither, the layout lives in the settings-core user tier
|
|
205
|
+
(`ShellSettingsDelta.layout`, via `storageKey`). `AppShell` now creates the
|
|
206
|
+
`ShellState` itself and passes it to `AdminShell`, so panel overrides reach
|
|
207
|
+
it (`ShellState.setLayoutPanels`); a layout-hidden edge ignores toggles,
|
|
208
|
+
hotkeys, viewport defaults, and the restore opener.
|
|
209
|
+
- **Layout API** (`useShellLayout()` / `tryUseShellLayout()` under an
|
|
210
|
+
`AppShell`, also `ShellLayoutController`): `moveSection(id, toIndex)`,
|
|
211
|
+
`moveItem(id, sectionId, toIndex?)`, `hide(id)`, `show(id)`, `setPanel(edge,
|
|
212
|
+
{ visible?, initial? })`, `reset()`, each returning whether anything changed,
|
|
213
|
+
plus readers (`layout`, `sections`, `panels`, `applied`, `customized`,
|
|
214
|
+
`isHidden`). An assistant calls the same methods the editor does. The
|
|
215
|
+
context is separate from `useAdminShell()` because `AppShell`, not
|
|
216
|
+
`AdminShell`, owns the navigation.
|
|
217
|
+
- **`ShellLayoutEditor`**: `controller` (default: context), `preview` (default
|
|
218
|
+
true), `iconComponent`. Mount it on a settings page or in a dock tool.
|
|
219
|
+
|
|
220
|
+
### Sortable and the Board engine
|
|
221
|
+
|
|
222
|
+
`components/sortable/controller.svelte.ts` is the headless engine extracted from
|
|
223
|
+
`Board`: keyboard pick-up (Space/Enter, arrows, Escape), pointer and native-drag
|
|
224
|
+
moves with a 6px threshold, one in-flight move at a time (a rejected `commit`
|
|
225
|
+
restores and announces), focus return, and announcements as typed events the
|
|
226
|
+
host localizes. `Board` (own markup and `ui.board.*` strings) and `Sortable`
|
|
227
|
+
(`ui.sortable.*`) both use it. `Sortable` renders stacked containers of items
|
|
228
|
+
with a move handle per item, optional `reorderContainers` (a second engine; `fixed`
|
|
229
|
+
containers lead and stay put), a drop marker, and cancel-on-blur; it is
|
|
230
|
+
controlled and never mutates `items`. Item moves report `target.index` after
|
|
231
|
+
removing the item from `source`.
|
|
232
|
+
|
|
175
233
|
## App shell and owner setup (`./app`)
|
|
176
234
|
|
|
177
235
|
`@happyvertical/smrt-svelte/app` (`src/components/app/`) is browser-only. It
|
|
@@ -182,13 +240,30 @@ lives beside, not inside, `./workspace` so the AdminShell barrel stays free of
|
|
|
182
240
|
unchanged), `ThemeProvider`, the theme CSS (`themes/styles/{all,fonts}.css`
|
|
183
241
|
are imported by the component — forgetting them leaves `--smrt-*` unresolved),
|
|
184
242
|
`AdminShell`, `TenantNav` from the consumer's `nav`/`navGroups`/`currentHref`,
|
|
185
|
-
and an `AppScopePanel`. Panels start collapsed as in `AdminShell`; pass
|
|
243
|
+
and an `AppScopePanel`. `ShellNavItem.action` (trailing icon link, optional `visibility: 'active'` = only while the item's section is current; omitted when collapsed) is rendered by `TenantNav` and passed through `AppShell` unchanged. Panels start collapsed as in `AdminShell`; pass
|
|
186
244
|
`config` to change that. `dock` is a snippet rendered inside the shell: a host
|
|
187
245
|
places its assistant there in a `ShellDockTool`, so this package never
|
|
188
246
|
imports `smrt-chat`. It receives the Provider's `DataSurfaceRegistry`
|
|
189
247
|
(`{#snippet dock(registry)}`), the instance mounted routes register on
|
|
190
248
|
when `webmcp` UI is on; pass it to `<AssistantDock {registry} />`. `runtimeDiagnostics` (default false) mounts the
|
|
191
|
-
read-only `smrt.runtime.diagnostics.read` WebMCP tool.
|
|
249
|
+
read-only `smrt.runtime.diagnostics.read` WebMCP tool. `dockToggles`
|
|
250
|
+
(`{ tool, label, icon? }[]`) renders icon buttons at the right of the shell
|
|
251
|
+
header (the AdminShell `header` row, shown only when the prop is non-empty),
|
|
252
|
+
each toggling the `ShellDockTool` with that id: `aria-pressed` and
|
|
253
|
+
`aria-expanded` follow the dock, `aria-controls` is
|
|
254
|
+
`smrt-admin-shell-right-panel`, the label is the tooltip, and `assistant`
|
|
255
|
+
defaults to a chat-bubble icon (`icon: 'chat'`; other text is a glyph). A
|
|
256
|
+
toggle whose tool is not registered yet, or whose dock is not `available`
|
|
257
|
+
(the right edge removed by the host or hidden by the user's layout), is
|
|
258
|
+
`aria-disabled` and `open`/`toggle` return false. Hosts, routes and
|
|
259
|
+
assistants drive the same dock with `useShellDock()` from `./workspace`
|
|
260
|
+
(`{ active, tools, available, has, isOpen, open, close, toggle }`, throws outside a
|
|
261
|
+
shell). Opening moves focus into the dock (first focusable, else the panel);
|
|
262
|
+
closing by Escape, toggle or code returns it to the opener when focus was left
|
|
263
|
+
in the dock. `open(tool, { focus: false })` skips the focus move. The
|
|
264
|
+
dock-control state lives on `ShellState` (`openDockTool`, `toggleDockTool`,
|
|
265
|
+
`closeFocusTool`, `openFocusToolId`). Playground:
|
|
266
|
+
`playground/src/routes/app-shell-dock-toggles`. Server code that
|
|
192
267
|
lists that tool (the diagnostics route's `toolNames`) imports
|
|
193
268
|
`RUNTIME_DIAGNOSTICS_WEBMCP_TOOL_NAME` from `./app/runtime-diagnostics`,
|
|
194
269
|
which is plain TypeScript; the `./app` barrel loads Svelte components and
|
|
@@ -9,20 +9,33 @@ import '@happyvertical/smrt-ui/themes/styles/base.css';
|
|
|
9
9
|
import '@happyvertical/smrt-ui/themes/styles/fonts.css';
|
|
10
10
|
import type { DataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
|
|
11
11
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
12
|
-
import type
|
|
12
|
+
import { type Snippet, untrack } from 'svelte';
|
|
13
13
|
import { M } from '../../i18n/strings.workspace.js';
|
|
14
14
|
import Provider from '../../Provider.svelte';
|
|
15
15
|
import type { User } from '../../state/app-state.js';
|
|
16
16
|
import type { WebMcpProviderConfig } from '../../web/webmcp-provider.js';
|
|
17
17
|
import AdminShell from '../workspace/admin-shell/AdminShell.svelte';
|
|
18
18
|
import AppScopePanel from '../workspace/admin-shell/AppScopePanel.svelte';
|
|
19
|
+
import {
|
|
20
|
+
applyShellLayout,
|
|
21
|
+
normalizeShellLayout,
|
|
22
|
+
type ShellLayout,
|
|
23
|
+
} from '../workspace/admin-shell/layout.js';
|
|
24
|
+
import { setShellLayout } from '../workspace/admin-shell/layout-context.js';
|
|
25
|
+
import { ShellLayoutController } from '../workspace/admin-shell/layout-controller.svelte.js';
|
|
26
|
+
import { resolveShellConfig } from '../workspace/admin-shell/settings.js';
|
|
27
|
+
import { createShellState } from '../workspace/admin-shell/state.svelte.js';
|
|
19
28
|
import TenantNav from '../workspace/admin-shell/TenantNav.svelte';
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
import {
|
|
30
|
+
PANEL_EDGES,
|
|
31
|
+
type PanelEdge,
|
|
32
|
+
type ShellNavGroup,
|
|
33
|
+
type ShellNavItem,
|
|
34
|
+
type ShellPanelDefaults,
|
|
24
35
|
} from '../workspace/admin-shell/types.js';
|
|
25
36
|
import DockSlot from './DockSlot.svelte';
|
|
37
|
+
import DockToggles from './DockToggles.svelte';
|
|
38
|
+
import type { DockToggle } from './dock-toggle.js';
|
|
26
39
|
import RuntimeDiagnosticsWebMcp from './RuntimeDiagnosticsWebMcp.svelte';
|
|
27
40
|
|
|
28
41
|
interface Props {
|
|
@@ -54,6 +67,17 @@ interface Props {
|
|
|
54
67
|
runtimeDiagnostics?: boolean;
|
|
55
68
|
/** Initial panel states and presentation; forwarded to AdminShell. */
|
|
56
69
|
config?: ShellPanelDefaults;
|
|
70
|
+
/**
|
|
71
|
+
* The user's layout customization (panel visibility, navigation order and
|
|
72
|
+
* visibility), applied over `nav`, `navGroups` and `config`. Passing it
|
|
73
|
+
* makes the host the owner: the shell never stores it, and reports edits
|
|
74
|
+
* through `onlayoutchange` for the host to pass back. Pass `null` for "no
|
|
75
|
+
* customization yet". Omit both `layout` and `onlayoutchange` to let the
|
|
76
|
+
* shell keep the layout in the user's settings (`storageKey`).
|
|
77
|
+
*/
|
|
78
|
+
layout?: ShellLayout | null;
|
|
79
|
+
/** Called with the next layout whenever the user (or an assistant) edits it. */
|
|
80
|
+
onlayoutchange?: (layout: ShellLayout) => void;
|
|
57
81
|
/** Theme preset applied by the ThemeProvider. */
|
|
58
82
|
preset?: ThemePreset;
|
|
59
83
|
/** Light, dark or system color scheme; the user's persisted choice wins. */
|
|
@@ -69,6 +93,15 @@ interface Props {
|
|
|
69
93
|
* register on it when the `webmcp` UI is enabled (`webmcp: true`).
|
|
70
94
|
*/
|
|
71
95
|
dock?: Snippet<[DataSurfaceRegistry]>;
|
|
96
|
+
/**
|
|
97
|
+
* Icon buttons rendered at the right of the shell header, each toggling
|
|
98
|
+
* the `ShellDockTool` with the same id open and closed. `aria-pressed` and
|
|
99
|
+
* `aria-expanded` follow the dock, focus moves into the dock when it
|
|
100
|
+
* opens and back to the button when it closes (Escape included). The
|
|
101
|
+
* `assistant` tool defaults to a chat-bubble icon. Hosts and assistants can
|
|
102
|
+
* drive the same dock from code with `useShellDock()`.
|
|
103
|
+
*/
|
|
104
|
+
dockToggles?: DockToggle[];
|
|
72
105
|
children: Snippet;
|
|
73
106
|
}
|
|
74
107
|
|
|
@@ -87,20 +120,99 @@ let {
|
|
|
87
120
|
permissions = [],
|
|
88
121
|
runtimeDiagnostics = false,
|
|
89
122
|
config,
|
|
123
|
+
layout,
|
|
124
|
+
onlayoutchange,
|
|
90
125
|
preset = 'smrt',
|
|
91
126
|
colorScheme = 'system',
|
|
92
127
|
appPanelDocs,
|
|
93
128
|
dock,
|
|
129
|
+
dockToggles = [],
|
|
94
130
|
children,
|
|
95
131
|
}: Props = $props();
|
|
96
132
|
const { t } = useI18n();
|
|
97
|
-
|
|
133
|
+
|
|
134
|
+
// The shell state lives here (not inside AdminShell) so the layout can reach
|
|
135
|
+
// it: panel overrides apply to it, and the user's layout is stored in it when
|
|
136
|
+
// the host does not own persistence.
|
|
137
|
+
const shell = untrack(() =>
|
|
138
|
+
createShellState({
|
|
139
|
+
config,
|
|
140
|
+
storageKey,
|
|
141
|
+
layoutPanels: normalizeShellLayout(layout).panels,
|
|
142
|
+
}),
|
|
143
|
+
);
|
|
144
|
+
// Hosts that pass only `onlayoutchange` own persistence but not the value:
|
|
145
|
+
// keep it in memory so edits show at once.
|
|
146
|
+
let localLayout = $state<ShellLayout | undefined>();
|
|
147
|
+
const controlled = $derived(layout !== undefined);
|
|
148
|
+
const effectiveLayout = $derived(
|
|
149
|
+
normalizeShellLayout(
|
|
150
|
+
controlled ? layout : onlayoutchange ? localLayout : shell.settings.layout,
|
|
151
|
+
),
|
|
152
|
+
);
|
|
153
|
+
const applied = $derived(
|
|
154
|
+
applyShellLayout(nav, navGroups, config, effectiveLayout),
|
|
155
|
+
);
|
|
156
|
+
const hasNav = $derived(applied.nav.length > 0 || applied.groups.length > 0);
|
|
157
|
+
|
|
158
|
+
// Starting-state edits made through the layout API, applied once the layout
|
|
159
|
+
// carrying them is in force (or dropped if the host answered differently).
|
|
160
|
+
const pendingStart = new Map<PanelEdge, 'collapsed' | 'expanded'>();
|
|
161
|
+
$effect(() => {
|
|
162
|
+
const panels = effectiveLayout.panels ?? {};
|
|
163
|
+
shell.setLayoutPanels(panels);
|
|
164
|
+
for (const [edge, state] of pendingStart) {
|
|
165
|
+
const initial =
|
|
166
|
+
panels[edge]?.initial ?? resolveShellConfig(config).panels[edge].initial;
|
|
167
|
+
if (initial === state) shell.setPanelStart(edge, state);
|
|
168
|
+
}
|
|
169
|
+
pendingStart.clear();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
setShellLayout(
|
|
173
|
+
new ShellLayoutController({
|
|
174
|
+
nav: () => nav,
|
|
175
|
+
groups: () => navGroups,
|
|
176
|
+
panels: () => config,
|
|
177
|
+
layout: () => effectiveLayout,
|
|
178
|
+
commit(next) {
|
|
179
|
+
// A changed starting state is an explicit edit: show it now. It waits
|
|
180
|
+
// for the layout to actually change (the host may reject the edit) and
|
|
181
|
+
// is never done for a loaded layout (hydration, a late `layout` prop),
|
|
182
|
+
// so loading cannot erase the user's own open/closed toggle.
|
|
183
|
+
for (const edge of PANEL_EDGES) {
|
|
184
|
+
const before = effectiveLayout.panels?.[edge]?.initial;
|
|
185
|
+
const after = next.panels?.[edge]?.initial;
|
|
186
|
+
if (before === after) continue;
|
|
187
|
+
const state = after ?? resolveShellConfig(config).panels[edge].initial;
|
|
188
|
+
if (state === 'collapsed' || state === 'expanded') {
|
|
189
|
+
pendingStart.set(edge, state);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (!controlled) {
|
|
193
|
+
if (onlayoutchange) localLayout = next;
|
|
194
|
+
else shell.setLayout(next);
|
|
195
|
+
}
|
|
196
|
+
onlayoutchange?.(next);
|
|
197
|
+
},
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
98
200
|
</script>
|
|
99
201
|
|
|
202
|
+
{#snippet dockHeader()}
|
|
203
|
+
<DockToggles toggles={dockToggles} />
|
|
204
|
+
{/snippet}
|
|
205
|
+
|
|
100
206
|
<Provider {webmcp} {user} {permissions}>
|
|
101
207
|
<RuntimeDiagnosticsWebMcp enabled={runtimeDiagnostics} />
|
|
102
208
|
<ThemeProvider {preset} {colorScheme} persist={true}>
|
|
103
|
-
<AdminShell
|
|
209
|
+
<AdminShell
|
|
210
|
+
{title}
|
|
211
|
+
{subtitle}
|
|
212
|
+
state={shell}
|
|
213
|
+
path={currentHref}
|
|
214
|
+
header={dockToggles.length > 0 ? dockHeader : undefined}
|
|
215
|
+
>
|
|
104
216
|
{#snippet appPanel()}
|
|
105
217
|
<AppScopePanel
|
|
106
218
|
appName={title}
|
|
@@ -120,8 +232,8 @@ const hasNav = $derived(nav.length > 0 || navGroups.length > 0);
|
|
|
120
232
|
{#snippet tenantPanel()}
|
|
121
233
|
{#if hasNav}
|
|
122
234
|
<TenantNav
|
|
123
|
-
items={nav}
|
|
124
|
-
groups={
|
|
235
|
+
items={applied.nav}
|
|
236
|
+
groups={applied.groups}
|
|
125
237
|
{currentHref}
|
|
126
238
|
aria-label={t(M['ui.app_shell.navigation'])}
|
|
127
239
|
/>
|
|
@@ -3,10 +3,12 @@ import '@happyvertical/smrt-ui/themes/styles/all.css';
|
|
|
3
3
|
import '@happyvertical/smrt-ui/themes/styles/base.css';
|
|
4
4
|
import '@happyvertical/smrt-ui/themes/styles/fonts.css';
|
|
5
5
|
import type { DataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
|
|
6
|
-
import type
|
|
6
|
+
import { type Snippet } from 'svelte';
|
|
7
7
|
import type { User } from '../../state/app-state.js';
|
|
8
8
|
import type { WebMcpProviderConfig } from '../../web/webmcp-provider.js';
|
|
9
|
-
import
|
|
9
|
+
import { type ShellLayout } from '../workspace/admin-shell/layout.js';
|
|
10
|
+
import { type ShellNavGroup, type ShellNavItem, type ShellPanelDefaults } from '../workspace/admin-shell/types.js';
|
|
11
|
+
import type { DockToggle } from './dock-toggle.js';
|
|
10
12
|
interface Props {
|
|
11
13
|
/** Application name shown in the shell brand and app panel. */
|
|
12
14
|
title?: string;
|
|
@@ -36,6 +38,17 @@ interface Props {
|
|
|
36
38
|
runtimeDiagnostics?: boolean;
|
|
37
39
|
/** Initial panel states and presentation; forwarded to AdminShell. */
|
|
38
40
|
config?: ShellPanelDefaults;
|
|
41
|
+
/**
|
|
42
|
+
* The user's layout customization (panel visibility, navigation order and
|
|
43
|
+
* visibility), applied over `nav`, `navGroups` and `config`. Passing it
|
|
44
|
+
* makes the host the owner: the shell never stores it, and reports edits
|
|
45
|
+
* through `onlayoutchange` for the host to pass back. Pass `null` for "no
|
|
46
|
+
* customization yet". Omit both `layout` and `onlayoutchange` to let the
|
|
47
|
+
* shell keep the layout in the user's settings (`storageKey`).
|
|
48
|
+
*/
|
|
49
|
+
layout?: ShellLayout | null;
|
|
50
|
+
/** Called with the next layout whenever the user (or an assistant) edits it. */
|
|
51
|
+
onlayoutchange?: (layout: ShellLayout) => void;
|
|
39
52
|
/** Theme preset applied by the ThemeProvider. */
|
|
40
53
|
preset?: ThemePreset;
|
|
41
54
|
/** Light, dark or system color scheme; the user's persisted choice wins. */
|
|
@@ -51,6 +64,15 @@ interface Props {
|
|
|
51
64
|
* register on it when the `webmcp` UI is enabled (`webmcp: true`).
|
|
52
65
|
*/
|
|
53
66
|
dock?: Snippet<[DataSurfaceRegistry]>;
|
|
67
|
+
/**
|
|
68
|
+
* Icon buttons rendered at the right of the shell header, each toggling
|
|
69
|
+
* the `ShellDockTool` with the same id open and closed. `aria-pressed` and
|
|
70
|
+
* `aria-expanded` follow the dock, focus moves into the dock when it
|
|
71
|
+
* opens and back to the button when it closes (Escape included). The
|
|
72
|
+
* `assistant` tool defaults to a chat-bubble icon. Hosts and assistants can
|
|
73
|
+
* drive the same dock from code with `useShellDock()`.
|
|
74
|
+
*/
|
|
75
|
+
dockToggles?: DockToggle[];
|
|
54
76
|
children: Snippet;
|
|
55
77
|
}
|
|
56
78
|
declare const AppShell: import("svelte").Component<Props, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppShell.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/app/AppShell.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,8CAA8C,CAAC;AACtD,OAAO,+CAA+C,CAAC;AACvD,OAAO,gDAAgD,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAEvE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"AppShell.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/app/AppShell.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,8CAA8C,CAAC;AACtD,OAAO,+CAA+C,CAAC;AACvD,OAAO,gDAAgD,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAEvE,OAAO,EAAE,KAAK,OAAO,EAAW,MAAM,QAAQ,CAAC;AAG/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGzE,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,oCAAoC,CAAC;AAM5C,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACxB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,UAAU,KAAK;IACb,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAC;IACxC,yFAAyF;IACzF,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,+FAA+F;IAC/F,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sEAAsE;IACtE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,gFAAgF;IAChF,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;IAC/C,iDAAiD;IACjD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACtC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB;AA+JD,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useShellDock } from '../workspace/admin-shell/dock.js';
|
|
3
|
+
import type { DockToggle } from './dock-toggle.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
toggles: DockToggle[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { toggles }: Props = $props();
|
|
10
|
+
const dock = useShellDock();
|
|
11
|
+
|
|
12
|
+
function iconFor(toggle: DockToggle): string | undefined {
|
|
13
|
+
return toggle.icon ?? (toggle.tool === 'assistant' ? 'chat' : undefined);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function press(event: MouseEvent, toggle: DockToggle): void {
|
|
17
|
+
if (!dock.has(toggle.tool) || !dock.available) return;
|
|
18
|
+
dock.toggle(toggle.tool, {
|
|
19
|
+
returnFocus: event.currentTarget as HTMLElement,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<div class="smrt-dock-toggles" data-testid="dock-toggles">
|
|
25
|
+
{#each toggles as toggle (toggle.tool)}
|
|
26
|
+
{@const registered = dock.has(toggle.tool) && dock.available}
|
|
27
|
+
{@const open = dock.isOpen(toggle.tool)}
|
|
28
|
+
{@const icon = iconFor(toggle)}
|
|
29
|
+
<!-- raw-primitive-allow: shell chrome toggle, not a content button -->
|
|
30
|
+
<button
|
|
31
|
+
type="button"
|
|
32
|
+
class="smrt-dock-toggles__button"
|
|
33
|
+
class:active={open}
|
|
34
|
+
data-dock-tool={toggle.tool}
|
|
35
|
+
aria-label={toggle.label}
|
|
36
|
+
title={toggle.label}
|
|
37
|
+
aria-pressed={open}
|
|
38
|
+
aria-expanded={open}
|
|
39
|
+
aria-controls="smrt-admin-shell-right-panel"
|
|
40
|
+
aria-disabled={registered ? undefined : true}
|
|
41
|
+
onclick={(event) => press(event, toggle)}
|
|
42
|
+
>
|
|
43
|
+
{#if icon === 'chat'}
|
|
44
|
+
<svg
|
|
45
|
+
viewBox="0 0 24 24"
|
|
46
|
+
width="20"
|
|
47
|
+
height="20"
|
|
48
|
+
fill="none"
|
|
49
|
+
stroke="currentColor"
|
|
50
|
+
stroke-width="2"
|
|
51
|
+
stroke-linecap="round"
|
|
52
|
+
stroke-linejoin="round"
|
|
53
|
+
aria-hidden="true"
|
|
54
|
+
>
|
|
55
|
+
<path d="M21 11.5a8.5 8.5 0 0 1-12.4 7.5L3 20.5l1.6-5A8.5 8.5 0 1 1 21 11.5z" />
|
|
56
|
+
</svg>
|
|
57
|
+
{:else}
|
|
58
|
+
<span aria-hidden="true">{icon ?? toggle.label.charAt(0)}</span>
|
|
59
|
+
{/if}
|
|
60
|
+
</button>
|
|
61
|
+
{/each}
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<style>
|
|
65
|
+
.smrt-dock-toggles {
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
gap: var(--smrt-spacing-1);
|
|
69
|
+
margin-inline-start: auto;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.smrt-dock-toggles__button {
|
|
73
|
+
display: inline-grid;
|
|
74
|
+
place-items: center;
|
|
75
|
+
inline-size: 2.25rem;
|
|
76
|
+
block-size: 2.25rem;
|
|
77
|
+
padding: 0;
|
|
78
|
+
border: 1px solid transparent;
|
|
79
|
+
border-radius: var(--smrt-radius-md, 0.5rem);
|
|
80
|
+
background: transparent;
|
|
81
|
+
color: var(--smrt-color-on-surface);
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.smrt-dock-toggles__button:hover {
|
|
86
|
+
background: var(--smrt-color-surface-container-high);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.smrt-dock-toggles__button:focus-visible {
|
|
90
|
+
outline: 2px solid var(--smrt-color-primary);
|
|
91
|
+
outline-offset: 2px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.smrt-dock-toggles__button.active {
|
|
95
|
+
background: var(--smrt-color-primary-container, var(--smrt-color-surface-container-high));
|
|
96
|
+
color: var(--smrt-color-on-primary-container, var(--smrt-color-primary));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.smrt-dock-toggles__button[aria-disabled='true'] {
|
|
100
|
+
opacity: 0.5;
|
|
101
|
+
cursor: default;
|
|
102
|
+
}
|
|
103
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DockToggle } from './dock-toggle.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
toggles: DockToggle[];
|
|
4
|
+
}
|
|
5
|
+
declare const DockToggles: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type DockToggles = ReturnType<typeof DockToggles>;
|
|
7
|
+
export default DockToggles;
|
|
8
|
+
//# sourceMappingURL=DockToggles.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DockToggles.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/app/DockToggles.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,UAAU,KAAK;IACb,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AA2CD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A header button that toggles one dock tool. */
|
|
2
|
+
export interface DockToggle {
|
|
3
|
+
/** Id of the `ShellDockTool` to toggle. */
|
|
4
|
+
tool: string;
|
|
5
|
+
/** Accessible name and tooltip. */
|
|
6
|
+
label: string;
|
|
7
|
+
/**
|
|
8
|
+
* Icon name. `chat` (the default for the `assistant` tool) draws a
|
|
9
|
+
* chat bubble; any other text is shown as a glyph. Without an icon the
|
|
10
|
+
* label's first letter stands in.
|
|
11
|
+
*/
|
|
12
|
+
icon?: string;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=dock-toggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dock-toggle.d.ts","sourceRoot":"","sources":["../../../src/components/app/dock-toggle.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* server or `$app/*` imports. Pair with the server `load`/`actions` from
|
|
6
6
|
* `@happyvertical/smrt-app-runtime/sveltekit`.
|
|
7
7
|
*/
|
|
8
|
+
export { type ShellLayout, ShellLayoutController, ShellLayoutEditor, tryUseShellLayout, useShellLayout, } from '../workspace/index.js';
|
|
8
9
|
export { default as AppShell } from './AppShell.svelte';
|
|
10
|
+
export type { DockToggle } from './dock-toggle.js';
|
|
9
11
|
export { default as OwnerSetupForm } from './OwnerSetupForm.svelte';
|
|
10
12
|
export type { OwnerSetupData, OwnerSetupFormResult, } from './owner-setup-types.js';
|
|
11
13
|
export { default as RuntimeDiagnosticsWebMcp } from './RuntimeDiagnosticsWebMcp.svelte';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/app/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/app/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,YAAY,EACV,cAAc,EACd,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EACL,kCAAkC,EAClC,KAAK,uCAAuC,EAC5C,4BAA4B,EAC5B,oCAAoC,EACpC,KAAK,6BAA6B,EAClC,gCAAgC,GACjC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* server or `$app/*` imports. Pair with the server `load`/`actions` from
|
|
6
6
|
* `@happyvertical/smrt-app-runtime/sveltekit`.
|
|
7
7
|
*/
|
|
8
|
+
export { ShellLayoutController, ShellLayoutEditor, tryUseShellLayout, useShellLayout, } from '../workspace/index.js';
|
|
8
9
|
export { default as AppShell } from './AppShell.svelte';
|
|
9
10
|
export { default as OwnerSetupForm } from './OwnerSetupForm.svelte';
|
|
10
11
|
export { default as RuntimeDiagnosticsWebMcp } from './RuntimeDiagnosticsWebMcp.svelte';
|