@happyvertical/smrt-svelte 0.55.6 → 0.55.8
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/AGENTS.md +9 -31
- package/README.md +195 -5
- package/agents/browser-ai.md +47 -0
- package/agents/command-palette.md +85 -0
- package/agents/import-export.md +62 -0
- package/agents/overview-surfaces.md +255 -0
- package/agents/screens.md +57 -0
- package/agents/workspace.md +202 -5
- package/dist/browser-ai/adapters/stt/dictation-source.d.ts.map +1 -1
- package/dist/browser-ai/adapters/stt/dictation-source.js +8 -2
- package/dist/browser-ai/adapters/stt/factory.d.ts +6 -3
- package/dist/browser-ai/adapters/stt/factory.d.ts.map +1 -1
- package/dist/browser-ai/adapters/stt/factory.js +19 -9
- package/dist/browser-ai/adapters/stt/index.d.ts +3 -1
- package/dist/browser-ai/adapters/stt/index.d.ts.map +1 -1
- package/dist/browser-ai/adapters/stt/index.js +3 -1
- package/dist/browser-ai/adapters/stt/local-speech-model.d.ts +111 -0
- package/dist/browser-ai/adapters/stt/local-speech-model.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/local-speech-model.js +377 -0
- package/dist/browser-ai/adapters/stt/local-speech.d.ts +82 -0
- package/dist/browser-ai/adapters/stt/local-speech.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/local-speech.js +317 -0
- package/dist/browser-ai/adapters/stt/local-speech.worker.d.ts +2 -0
- package/dist/browser-ai/adapters/stt/local-speech.worker.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/local-speech.worker.js +32 -0
- package/dist/browser-ai/adapters/stt/transformers-env.d.ts +8 -0
- package/dist/browser-ai/adapters/stt/transformers-env.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/transformers-env.js +17 -0
- package/dist/browser-ai/adapters/stt/types.d.ts +54 -9
- package/dist/browser-ai/adapters/stt/types.d.ts.map +1 -1
- package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts +5 -0
- package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts.map +1 -1
- package/dist/browser-ai/adapters/tts/browser-synthesis.js +83 -55
- package/dist/browser-ai/capabilities/speech-probe.d.ts +29 -0
- package/dist/browser-ai/capabilities/speech-probe.d.ts.map +1 -0
- package/dist/browser-ai/capabilities/speech-probe.js +19 -0
- package/dist/browser-ai/core/errors.d.ts +9 -0
- package/dist/browser-ai/core/errors.d.ts.map +1 -1
- package/dist/browser-ai/core/errors.js +12 -0
- package/dist/browser-ai/index.d.ts +1 -0
- package/dist/browser-ai/index.d.ts.map +1 -1
- package/dist/browser-ai/index.js +1 -0
- package/dist/components/app/AppShell.svelte +587 -33
- package/dist/components/app/AppShell.svelte.d.ts +75 -4
- package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
- package/dist/components/app/DockToggles.svelte +0 -1
- package/dist/components/app/dock-toggle.d.ts +7 -1
- 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/slot-item.d.ts +21 -0
- package/dist/components/app/slot-item.d.ts.map +1 -0
- package/dist/components/app/slot-item.js +1 -0
- package/dist/components/command-palette/CommandPalette.svelte +75 -0
- package/dist/components/command-palette/CommandPalette.svelte.d.ts +22 -0
- package/dist/components/command-palette/CommandPalette.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/CommandPaletteDialog.svelte +406 -0
- package/dist/components/command-palette/CommandPaletteDialog.svelte.d.ts +18 -0
- package/dist/components/command-palette/CommandPaletteDialog.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/CommandPaletteTrigger.svelte +91 -0
- package/dist/components/command-palette/CommandPaletteTrigger.svelte.d.ts +17 -0
- package/dist/components/command-palette/CommandPaletteTrigger.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/context.d.ts +18 -0
- package/dist/components/command-palette/context.d.ts.map +1 -0
- package/dist/components/command-palette/context.js +38 -0
- package/dist/components/command-palette/controller.svelte.d.ts +70 -0
- package/dist/components/command-palette/controller.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/controller.svelte.js +379 -0
- package/dist/components/command-palette/hotkeys.d.ts +30 -0
- package/dist/components/command-palette/hotkeys.d.ts.map +1 -0
- package/dist/components/command-palette/hotkeys.js +161 -0
- package/dist/components/command-palette/index.d.ts +19 -0
- package/dist/components/command-palette/index.d.ts.map +1 -0
- package/dist/components/command-palette/index.js +17 -0
- package/dist/components/command-palette/match.d.ts +38 -0
- package/dist/components/command-palette/match.d.ts.map +1 -0
- package/dist/components/command-palette/match.js +172 -0
- package/dist/components/command-palette/providers.d.ts +159 -0
- package/dist/components/command-palette/providers.d.ts.map +1 -0
- package/dist/components/command-palette/providers.js +345 -0
- package/dist/components/command-palette/rank.d.ts +20 -0
- package/dist/components/command-palette/rank.d.ts.map +1 -0
- package/dist/components/command-palette/rank.js +74 -0
- package/dist/components/command-palette/types.d.ts +119 -0
- package/dist/components/command-palette/types.d.ts.map +1 -0
- package/dist/components/command-palette/types.js +10 -0
- package/dist/components/command-palette/use-provider.svelte.d.ts +14 -0
- package/dist/components/command-palette/use-provider.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/use-provider.svelte.js +23 -0
- package/dist/components/forms/AddressInput.svelte +2 -15
- package/dist/components/forms/AddressInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/DateRangeInput.svelte +2 -15
- package/dist/components/forms/DateRangeInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/DateTimeInput.svelte +8 -15
- package/dist/components/forms/DateTimeInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/MeasurementInput.svelte +2 -15
- package/dist/components/forms/MeasurementInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/MoneyInput.svelte +8 -25
- package/dist/components/forms/MoneyInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/NumberInput.svelte +7 -15
- package/dist/components/forms/NumberInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/PhoneInput.svelte +7 -15
- package/dist/components/forms/PhoneInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/SelectInput.svelte +34 -40
- package/dist/components/forms/SelectInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/TextInput.svelte +20 -37
- package/dist/components/forms/TextInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/TextareaInput.svelte +19 -35
- package/dist/components/forms/TextareaInput.svelte.d.ts.map +1 -1
- package/dist/components/import-export/ImportExport.svelte +678 -0
- package/dist/components/import-export/ImportExport.svelte.d.ts +5 -0
- package/dist/components/import-export/ImportExport.svelte.d.ts.map +1 -0
- package/dist/components/import-export/collection-adapter.d.ts +35 -0
- package/dist/components/import-export/collection-adapter.d.ts.map +1 -0
- package/dist/components/import-export/collection-adapter.js +42 -0
- package/dist/components/import-export/csv.d.ts +60 -0
- package/dist/components/import-export/csv.d.ts.map +1 -0
- package/dist/components/import-export/csv.js +192 -0
- package/dist/components/import-export/download.d.ts +4 -0
- package/dist/components/import-export/download.d.ts.map +1 -0
- package/dist/components/import-export/download.js +17 -0
- package/dist/components/import-export/export.d.ts +25 -0
- package/dist/components/import-export/export.d.ts.map +1 -0
- package/dist/components/import-export/export.js +68 -0
- package/dist/components/import-export/fields.d.ts +48 -0
- package/dist/components/import-export/fields.d.ts.map +1 -0
- package/dist/components/import-export/fields.js +103 -0
- package/dist/components/import-export/index.d.ts +12 -0
- package/dist/components/import-export/index.d.ts.map +1 -0
- package/dist/components/import-export/index.js +9 -0
- package/dist/components/import-export/mapping.d.ts +12 -0
- package/dist/components/import-export/mapping.d.ts.map +1 -0
- package/dist/components/import-export/mapping.js +38 -0
- package/dist/components/import-export/props.d.ts +34 -0
- package/dist/components/import-export/props.d.ts.map +1 -0
- package/dist/components/import-export/props.js +1 -0
- package/dist/components/import-export/report.d.ts +13 -0
- package/dist/components/import-export/report.d.ts.map +1 -0
- package/dist/components/import-export/report.js +50 -0
- package/dist/components/import-export/runner.d.ts +17 -0
- package/dist/components/import-export/runner.d.ts.map +1 -0
- package/dist/components/import-export/runner.js +39 -0
- package/dist/components/import-export/types.d.ts +100 -0
- package/dist/components/import-export/types.d.ts.map +1 -0
- package/dist/components/import-export/types.js +6 -0
- package/dist/components/import-export/validate.d.ts +39 -0
- package/dist/components/import-export/validate.d.ts.map +1 -0
- package/dist/components/import-export/validate.js +268 -0
- package/dist/components/overview/OverviewGrid.svelte +579 -0
- package/dist/components/overview/OverviewGrid.svelte.d.ts +5 -0
- package/dist/components/overview/OverviewGrid.svelte.d.ts.map +1 -0
- package/dist/components/overview/WidgetOptionsForm.svelte +193 -0
- package/dist/components/overview/WidgetOptionsForm.svelte.d.ts +5 -0
- package/dist/components/overview/WidgetOptionsForm.svelte.d.ts.map +1 -0
- package/dist/components/overview/controller.svelte.d.ts +92 -0
- package/dist/components/overview/controller.svelte.d.ts.map +1 -0
- package/dist/components/overview/controller.svelte.js +336 -0
- package/dist/components/overview/format.d.ts +13 -0
- package/dist/components/overview/format.d.ts.map +1 -0
- package/dist/components/overview/format.js +45 -0
- package/dist/components/overview/grid-types.d.ts +52 -0
- package/dist/components/overview/grid-types.d.ts.map +1 -0
- package/dist/components/overview/grid-types.js +1 -0
- package/dist/components/overview/index.d.ts +24 -0
- package/dist/components/overview/index.d.ts.map +1 -0
- package/dist/components/overview/index.js +22 -0
- package/dist/components/overview/load.d.ts +30 -0
- package/dist/components/overview/load.d.ts.map +1 -0
- package/dist/components/overview/load.js +92 -0
- package/dist/components/overview/markdown.d.ts +53 -0
- package/dist/components/overview/markdown.d.ts.map +1 -0
- package/dist/components/overview/markdown.js +203 -0
- package/dist/components/overview/model.d.ts +100 -0
- package/dist/components/overview/model.d.ts.map +1 -0
- package/dist/components/overview/model.js +460 -0
- package/dist/components/overview/recipe-widgets.d.ts +77 -0
- package/dist/components/overview/recipe-widgets.d.ts.map +1 -0
- package/dist/components/overview/recipe-widgets.js +151 -0
- package/dist/components/overview/registry.d.ts +45 -0
- package/dist/components/overview/registry.d.ts.map +1 -0
- package/dist/components/overview/registry.js +112 -0
- package/dist/components/overview/resize.d.ts +25 -0
- package/dist/components/overview/resize.d.ts.map +1 -0
- package/dist/components/overview/resize.js +41 -0
- package/dist/components/overview/schema.d.ts +34 -0
- package/dist/components/overview/schema.d.ts.map +1 -0
- package/dist/components/overview/schema.js +180 -0
- package/dist/components/overview/server.d.ts +14 -0
- package/dist/components/overview/server.d.ts.map +1 -0
- package/dist/components/overview/server.js +13 -0
- package/dist/components/overview/types.d.ts +235 -0
- package/dist/components/overview/types.d.ts.map +1 -0
- package/dist/components/overview/types.js +17 -0
- package/dist/components/overview/widgets/ChartWidget.svelte +111 -0
- package/dist/components/overview/widgets/ChartWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/ChartWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/MetricWidget.svelte +86 -0
- package/dist/components/overview/widgets/MetricWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/MetricWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/NoteWidget.svelte +61 -0
- package/dist/components/overview/widgets/NoteWidget.svelte.d.ts +5 -0
- package/dist/components/overview/widgets/NoteWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/RecordListWidget.svelte +91 -0
- package/dist/components/overview/widgets/RecordListWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/RecordListWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/ShortcutsWidget.svelte +80 -0
- package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/core.d.ts +44 -0
- package/dist/components/overview/widgets/core.d.ts.map +1 -0
- package/dist/components/overview/widgets/core.js +222 -0
- package/dist/components/overview/widgets/data.d.ts +76 -0
- package/dist/components/overview/widgets/data.d.ts.map +1 -0
- package/dist/components/overview/widgets/data.js +40 -0
- package/dist/components/screens/DetailScreen.svelte +220 -0
- package/dist/components/screens/DetailScreen.svelte.d.ts +5 -0
- package/dist/components/screens/DetailScreen.svelte.d.ts.map +1 -0
- package/dist/components/screens/EditForm.svelte +313 -0
- package/dist/components/screens/EditForm.svelte.d.ts +5 -0
- package/dist/components/screens/EditForm.svelte.d.ts.map +1 -0
- package/dist/components/screens/ListScreen.svelte +191 -0
- package/dist/components/screens/ListScreen.svelte.d.ts +5 -0
- package/dist/components/screens/ListScreen.svelte.d.ts.map +1 -0
- package/dist/components/screens/RecipeScreens.svelte +237 -0
- package/dist/components/screens/RecipeScreens.svelte.d.ts +5 -0
- package/dist/components/screens/RecipeScreens.svelte.d.ts.map +1 -0
- package/dist/components/screens/fields.d.ts +54 -0
- package/dist/components/screens/fields.d.ts.map +1 -0
- package/dist/components/screens/fields.js +229 -0
- package/dist/components/screens/index.d.ts +8 -0
- package/dist/components/screens/index.d.ts.map +1 -0
- package/dist/components/screens/index.js +6 -0
- package/dist/components/screens/types.d.ts +215 -0
- package/dist/components/screens/types.d.ts.map +1 -0
- package/dist/components/screens/types.js +1 -0
- package/dist/components/screens/values.d.ts +62 -0
- package/dist/components/screens/values.d.ts.map +1 -0
- package/dist/components/screens/values.js +289 -0
- package/dist/components/sortable/Sortable.svelte +6 -33
- package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -1
- package/dist/components/sortable/announce.d.ts +5 -0
- package/dist/components/sortable/announce.d.ts.map +1 -0
- package/dist/components/sortable/announce.js +33 -0
- package/dist/components/sortable/controller.svelte.d.ts +10 -0
- package/dist/components/sortable/controller.svelte.d.ts.map +1 -1
- package/dist/components/sortable/controller.svelte.js +29 -7
- package/dist/components/workspace/admin-shell/AdminShell.svelte +424 -58
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +27 -2
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellBrand.svelte +86 -0
- package/dist/components/workspace/admin-shell/ShellBrand.svelte.d.ts +18 -0
- package/dist/components/workspace/admin-shell/ShellBrand.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte +77 -0
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte.d.ts +26 -0
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +88 -16
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte +531 -0
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts +26 -0
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte +57 -0
- package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte.d.ts +22 -0
- package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte +290 -0
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts +32 -0
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte +67 -2
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +8 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts +67 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/layout-controller.svelte.js +129 -1
- package/dist/components/workspace/admin-shell/layout.d.ts +122 -0
- package/dist/components/workspace/admin-shell/layout.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/layout.js +410 -10
- package/dist/components/workspace/admin-shell/settings.js +4 -4
- package/dist/components/workspace/admin-shell/shell-icons.d.ts +45 -0
- package/dist/components/workspace/admin-shell/shell-icons.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/shell-icons.js +66 -0
- package/dist/components/workspace/admin-shell/slot-labels.d.ts +33 -0
- package/dist/components/workspace/admin-shell/slot-labels.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/slot-labels.js +33 -0
- package/dist/components/workspace/admin-shell/slots.d.ts +50 -0
- package/dist/components/workspace/admin-shell/slots.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/slots.js +77 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts +35 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/state.svelte.js +111 -0
- package/dist/components/workspace/admin-shell/types.d.ts +101 -1
- package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
- package/dist/components/workspace/index.d.ts +9 -2
- package/dist/components/workspace/index.d.ts.map +1 -1
- package/dist/components/workspace/index.js +6 -0
- package/dist/components/workspace/manifest-nav.d.ts +20 -0
- package/dist/components/workspace/manifest-nav.d.ts.map +1 -1
- package/dist/components/workspace/manifest-nav.js +42 -13
- package/dist/i18n/server.d.ts +6 -0
- package/dist/i18n/server.d.ts.map +1 -1
- package/dist/i18n/server.js +6 -0
- package/dist/i18n/strings.import-export.d.ts +88 -0
- package/dist/i18n/strings.import-export.d.ts.map +1 -0
- package/dist/i18n/strings.import-export.js +88 -0
- package/dist/i18n/strings.overview.d.ts +100 -0
- package/dist/i18n/strings.overview.d.ts.map +1 -0
- package/dist/i18n/strings.overview.js +107 -0
- package/dist/i18n/strings.palette.d.ts +18 -0
- package/dist/i18n/strings.palette.d.ts.map +1 -0
- package/dist/i18n/strings.palette.js +18 -0
- package/dist/i18n/strings.screens.d.ts +31 -0
- package/dist/i18n/strings.screens.d.ts.map +1 -0
- package/dist/i18n/strings.screens.js +31 -0
- package/dist/i18n/strings.workspace.d.ts +49 -0
- package/dist/i18n/strings.workspace.d.ts.map +1 -1
- package/dist/i18n/strings.workspace.js +49 -0
- package/package.json +59 -19
- package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts +0 -51
- package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts.map +0 -1
- package/dist/browser-ai/adapters/stt/whisper-wasm.js +0 -380
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# smrt-svelte/overview
|
|
2
|
+
|
|
3
|
+
Module semantics for `src/components/overview/` (`./overview` and
|
|
4
|
+
`./overview/server`, #3727). Package orientation and cross-module invariants are
|
|
5
|
+
in [../AGENTS.md](../AGENTS.md); the shell edit mode it joins is in
|
|
6
|
+
[workspace.md](workspace.md#editing-the-layout-in-place).
|
|
7
|
+
|
|
8
|
+
An overview is a **customizable surface**: a flow grid of registered widgets,
|
|
9
|
+
each with an options object. A page declares which widget types it allows and
|
|
10
|
+
its default arrangement; admins (or users, per role) add, reorder, resize,
|
|
11
|
+
configure and remove widgets inside that confined set, and reset returns to the
|
|
12
|
+
default. Phase 1 (this module) is the surface, the registry, the data model, the
|
|
13
|
+
server load contract and five core widgets; phase 2 adds package widgets from
|
|
14
|
+
recipes ("Recipe widgets"). Persistence and assistant operations are later
|
|
15
|
+
phases (see "Extension points").
|
|
16
|
+
|
|
17
|
+
## Two entries
|
|
18
|
+
|
|
19
|
+
| Entry | Contents |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `./overview/server` (`server.ts`) | Svelte-free: types, `validateWidgetOptions`, the model (`resolveOverview`, `checkOverviewOverride`, `applyOverviewOverride`, `diffOverview`, `sanitizeOverview`, ...), `WidgetRegistry` / `registerWidget`, `loadOverview`. Safe in a `+page.server.ts` or a save endpoint. |
|
|
22
|
+
| `./overview` (`index.ts`) | Everything above plus `OverviewGrid`, `createOverview` (controller), `WidgetOptionsForm`, the core widgets and `registerCoreWidgets`, `shortcutsFromNav`, `formatWidgetValue`, `parseMarkdown` / `safeHref`. |
|
|
23
|
+
|
|
24
|
+
## Data model (`types.ts`, `model.ts`)
|
|
25
|
+
|
|
26
|
+
A saved overview is data, never code:
|
|
27
|
+
`{ widgets: [{ id, type, span, options, version? }] }`. `span` is 1 to 4 (a widget
|
|
28
|
+
type may narrow its own range); `options` is a flat object of JSON primitives;
|
|
29
|
+
`version` is the widget's option-schema version the options were written
|
|
30
|
+
against (absent means 1).
|
|
31
|
+
|
|
32
|
+
- **`OverviewDefinition`** (what a page declares): `id` (dotted ids allowed,
|
|
33
|
+
`events.home`), `defaults`, `allowed` (widget types; omit for every registered
|
|
34
|
+
type), `models` (confines `model` options, including a substituted default: a
|
|
35
|
+
default outside the list fails validation, so its loader never runs),
|
|
36
|
+
`maxWidgets` (default 24).
|
|
37
|
+
`defineOverview` validates ids.
|
|
38
|
+
- **`OverviewOverride`** is the sparse, versioned (`version: 1`) delta a host
|
|
39
|
+
stores: `order`, `removed`, `added`, `changed[id] = { span?, options?, version? }`.
|
|
40
|
+
`applyOverviewOverride(base, override)` is total: ids the base no longer has
|
|
41
|
+
are ignored, an added widget colliding with a base id is skipped, and widgets
|
|
42
|
+
the order does not list keep their slots (a default shipped later still
|
|
43
|
+
appears). `diffOverview(base, next)` is its inverse (round-trip tested), so
|
|
44
|
+
every client edit is "mutate the document, store the diff"; an edit that
|
|
45
|
+
returns to the defaults stores `null`.
|
|
46
|
+
- **Ids are stable.** `nextWidgetId` yields `w<n>` and reserves the ids of
|
|
47
|
+
removed defaults, so a new widget never takes a removed default's id (the
|
|
48
|
+
override would delete it). It is total for any stored ids: numeric suffixes
|
|
49
|
+
beyond `Number.MAX_SAFE_INTEGER` are ignored when picking the next number
|
|
50
|
+
(they would stop incrementing), and an exhausted high end restarts at `w1`.
|
|
51
|
+
- **Tiers.** `resolveOverview` merges one override. A host with tenant defaults
|
|
52
|
+
and user overrides merges the tenant tier into the definition's `defaults`
|
|
53
|
+
first (phase 3); the user override then applies to that.
|
|
54
|
+
- **Reset** is `controller.reset()` (store `null`) or `resetWidget(id)`.
|
|
55
|
+
|
|
56
|
+
## Validation: what keeps a stored overview from running anything
|
|
57
|
+
|
|
58
|
+
Options are validated against the widget's versioned schema on **save**
|
|
59
|
+
(`checkOverviewOverride`, strict: any issue rejects, and the returned override is
|
|
60
|
+
re-derived from the sanitized result, so persist that) and on **load**
|
|
61
|
+
(`sanitizeOverview`, lenient: the bad widget is dropped and reported as an
|
|
62
|
+
`OverviewIssue`, the rest render). Nothing here calls a widget's `load` for a
|
|
63
|
+
widget that failed validation.
|
|
64
|
+
|
|
65
|
+
- `schema.ts` field types: `text`, `markdown`, `identifier`, `model`, `integer`,
|
|
66
|
+
`number`, `boolean`, `enum`. There is **no free-form query, filter expression,
|
|
67
|
+
URL or SQL field**. "Which data" is a `model` (a bare `Class`, `pkg:Class` or
|
|
68
|
+
`@scope/pkg:Class`, optionally confined to the page's `models`), an
|
|
69
|
+
`identifier` (a field or named-filter id, `[A-Za-z_][A-Za-z0-9_.-]{0,63}`) or a
|
|
70
|
+
closed `enum`. The loader maps those to queries it owns and authorizes.
|
|
71
|
+
- Strict: unknown keys, wrong types, out-of-range numbers, values outside a closed
|
|
72
|
+
set and missing required fields fail the whole options object. Missing optional
|
|
73
|
+
fields take their default; `null` counts as missing.
|
|
74
|
+
- `sanitizeOverview` also drops: unknown types, types outside the page's
|
|
75
|
+
`allowed` set or a widget's `allowedIn`, duplicate ids, widgets over the cap,
|
|
76
|
+
newer-than-known versions, and older versions without a working `migrate`.
|
|
77
|
+
Spans are clamped to the widget's range. It is idempotent.
|
|
78
|
+
- `migrate(options, fromVersion)` upgrades stored options to the current version
|
|
79
|
+
(return `null` to drop). It runs on untrusted input inside a try/catch, and its
|
|
80
|
+
result is validated like any other options.
|
|
81
|
+
- A widget id removed by the user and a type removed by a release both degrade to
|
|
82
|
+
"dropped and reported", never an error page.
|
|
83
|
+
|
|
84
|
+
## Registry (`registry.ts`)
|
|
85
|
+
|
|
86
|
+
`registerWidget({ type, title, options, component | loadComponent, load, allowedIn,
|
|
87
|
+
version, migrate, defaultSpan, minSpan, maxSpan })` on the shared
|
|
88
|
+
`defaultWidgetRegistry`, or `createWidgetRegistry()` for an isolated one (tests,
|
|
89
|
+
several surfaces). Registration is code, at module scope; registering a type
|
|
90
|
+
twice throws unless `{ replace: true }`. `title`, `description` and option
|
|
91
|
+
`label` / `help` / `choices[].label` are text **or i18n keys** (the UI runs them
|
|
92
|
+
through `t`, which returns an unregistered string unchanged); the core widgets
|
|
93
|
+
use `ui.overview.*` keys from `i18n/strings.overview.ts` (registered in
|
|
94
|
+
`i18n/server.ts`).
|
|
95
|
+
|
|
96
|
+
`component` renders synchronously. `loadComponent` is the lazy form (dynamic import
|
|
97
|
+
by export ref): resolve it **before** render with `resolveWidgetComponents(types)`
|
|
98
|
+
in a universal load and pass the map to `OverviewGrid components`, so server and
|
|
99
|
+
client render the same tree. A type that cannot resolve renders as unavailable.
|
|
100
|
+
|
|
101
|
+
## Server load contract (`load.ts`)
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
// +page.server.ts
|
|
105
|
+
const resolved = resolveOverview(definition, await storedOverride(event), registry);
|
|
106
|
+
const overview = await loadOverview(resolved.document, definition, registry, {
|
|
107
|
+
locale, tenantId, db /* the request's permission-checked capabilities */,
|
|
108
|
+
});
|
|
109
|
+
return { overview }; // LoadedOverview: JSON, serializable
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- A widget's `load(options, ctx)` receives **validated options only** and a
|
|
113
|
+
`WidgetLoadContext` the host built from the request principal: `overviewId`, an
|
|
114
|
+
abort `signal`, `locale`, and any host capabilities (index keys). It must
|
|
115
|
+
authorize through `ctx` (the user's permissions and tenant filters), never
|
|
116
|
+
through option values. Reports-backed chart loaders call the runtime-report
|
|
117
|
+
compiler with this context; this package does not depend on it.
|
|
118
|
+
- Loads run in parallel with a per-widget timeout (default 8 s; the signal
|
|
119
|
+
aborts). A thrown error, a timeout or non-serializable / oversized data
|
|
120
|
+
(default 256 KB of JSON) becomes a per-widget error tile
|
|
121
|
+
(`error.code`: `load_failed | timeout | invalid_data`); the real error goes only
|
|
122
|
+
to `onError` for server logs, never to the client. One bad widget never fails
|
|
123
|
+
the page.
|
|
124
|
+
- `LoadedOverview` is what the page returns and `createOverview({ loaded })` seeds
|
|
125
|
+
the controller from, so the grid renders every widget at first paint with no
|
|
126
|
+
client-only fetching and **no hydration mismatch** (the grid has no
|
|
127
|
+
effect-dependent content; the only `$effect` requests data for widgets the
|
|
128
|
+
seeded entries do not cover, which never happens on first render).
|
|
129
|
+
`scripts/overview-ssr.test.mjs` renders the grid through Vite SSR.
|
|
130
|
+
- Formatting is deterministic per locale (`Intl` with the i18n store's locale), and
|
|
131
|
+
no widget formats dates or reads the clock; loaders send preformatted meta.
|
|
132
|
+
|
|
133
|
+
## Controller (`controller.svelte.ts`)
|
|
134
|
+
|
|
135
|
+
`createOverview({ definition, registry?, override?, onchange?, canCustomize?,
|
|
136
|
+
loaded?, loadWidget? })`, the `ShellLayout` pattern: **persistence is host-owned**.
|
|
137
|
+
With an `override` getter the host is the source of truth and feeds each edit back
|
|
138
|
+
(`onchange(override | null)`); without it the value is kept in memory. Reactive
|
|
139
|
+
reads: `document`, `base`, `override`, `issues`, `customized`, `canCustomize`,
|
|
140
|
+
`addable`, `full`, `entry(widget)`. Operations, each returning
|
|
141
|
+
`{ ok: true, id } | { ok: false, reason, issues? }` and refused with
|
|
142
|
+
`not_allowed` when `canCustomize()` is false (the role gate; the server must check
|
|
143
|
+
the same on save): `add(type, options?)`, `remove`, `move(id, toIndex)` (index
|
|
144
|
+
after removal), `resize(id, span)`, `setOptions`, `resetWidget`, `reset`,
|
|
145
|
+
`restore(override)` (the Undo hook), `reload(id)`.
|
|
146
|
+
|
|
147
|
+
`loadWidget(widget, signal)` is how a client edit gets data for an added or
|
|
148
|
+
reconfigured widget: the host runs the widget's `load` where its data lives (a
|
|
149
|
+
remote function in production, the in-browser source in smrt-planner). The
|
|
150
|
+
controller drops results for stale option keys and aborts superseded loads.
|
|
151
|
+
Call `destroy()` when the owner unmounts.
|
|
152
|
+
|
|
153
|
+
## Grid and edit mode (`OverviewGrid.svelte`)
|
|
154
|
+
|
|
155
|
+
Props in `grid-types.ts`. `editing` defaults to the shell's layout editor
|
|
156
|
+
(`tryUseShellLayout()?.editing`), so the same pencil edits the grid under an
|
|
157
|
+
`AppShell` with `layoutEditing`; pass `editing` to drive it without a shell. It is
|
|
158
|
+
off whenever `controller.canCustomize` is false.
|
|
159
|
+
|
|
160
|
+
- **Flow grid.** CSS grid of 4 columns, 2 below 40rem and 1 below 22rem of the
|
|
161
|
+
grid's own width (container queries); `data-span` / `--span` carry the span. Gaps
|
|
162
|
+
are tile padding, not grid gap, so a drag never crosses a dead zone.
|
|
163
|
+
- **Reorder** uses the headless `createSortable` engine in its `flow` mode (a
|
|
164
|
+
single wrapping list): the handle is the existing grip (Space picks up, any
|
|
165
|
+
arrow steps along reading order, mirrored in RTL, Enter drops, Escape cancels;
|
|
166
|
+
pointer and native drag use the horizontal midpoint for tiles sharing a row).
|
|
167
|
+
- **Resize** is an end-edge `role="slider"` (arrows, Home, End; pointer drag snaps
|
|
168
|
+
to a column boundary via the pure `spanFromPointer`, committed on release).
|
|
169
|
+
- **Chrome** is icon-only `ShellIconButton`s (configure, remove) plus the toolbar
|
|
170
|
+
(add, reset). Widgets render as on the site inside an `inert` wrapper. Add and
|
|
171
|
+
configure open `Modal`s; `WidgetOptionsForm` is generated from the option field
|
|
172
|
+
descriptors with smrt-ui `Form` / `FormGroup` / `Input` / `Select` / `Textarea` /
|
|
173
|
+
`Checkbox` (the descriptors mirror the generated screens' field shape) and shows
|
|
174
|
+
each schema issue beside its field. A widget with a required option and no
|
|
175
|
+
default opens the form before it is added.
|
|
176
|
+
- A polite live region announces moves, resizes, adds, removals and resets.
|
|
177
|
+
`OverviewGrid.test.ts` runs axe in view and edit mode.
|
|
178
|
+
|
|
179
|
+
## Core widgets (`widgets/`)
|
|
180
|
+
|
|
181
|
+
`registerCoreWidgets(registry, loaders)` registers `note` always and each
|
|
182
|
+
data-backed widget only when its loader is given (structural injection: this
|
|
183
|
+
package depends on no data package). Widgets render only when the grid has
|
|
184
|
+
`ready` data (it draws loading and error tiles) and treat `data` as untrusted
|
|
185
|
+
shape. Data shapes are in `widgets/data.ts`.
|
|
186
|
+
|
|
187
|
+
| Type | Options | Data |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `metric` | `title`, `model`*, `measure`, `field`, `filter` | `{ value, format?, currency?, label?, change?, href? }` (money = integer minor units) |
|
|
190
|
+
| `chart` | `title`, `model`*, `groupBy`, `measure`, `field`, `period`, `style` (bar/line), `filter` | `{ points: [{ label, value }], format?, currency?, href? }`, one measure of a runtime report |
|
|
191
|
+
| `records` | `title`, `model`*, `sort`, `direction`, `limit`, `filter` | `{ rows: [{ id, title, subtitle?, meta?, href? }], total?, href? }`; the loader chooses the title field and the visible records |
|
|
192
|
+
| `shortcuts` | `title`, `section` | `{ items: [{ id, label, href, icon?, description? }] }`; `shortcutsFromNav(sections, sectionId)` maps `resolveShellNavModel` / `useShellLayout().sections` (visible entries, user renames) |
|
|
193
|
+
| `note` | `title`, `body` (Markdown) | none |
|
|
194
|
+
|
|
195
|
+
`note` renders `parseMarkdown` output as elements (headings, paragraphs, lists,
|
|
196
|
+
quotes, fenced code, bold/italic/code/links). There is no `{@html}`; raw HTML is
|
|
197
|
+
literal text and `safeHref` limits links to http(s), mailto, same-site paths and
|
|
198
|
+
fragments. Record and shortcut hrefs pass `safeHref` too. Charts carry their
|
|
199
|
+
numbers as text (inline for bars, a visually hidden table for the line).
|
|
200
|
+
|
|
201
|
+
## Recipe widgets (`recipe-widgets.ts`)
|
|
202
|
+
|
|
203
|
+
A package contributes a widget with a `widget` surface on a recipe
|
|
204
|
+
([core recipes.md](../../core/agents/recipes.md#widget-surfaces-3727) has the
|
|
205
|
+
declaration and its scan-time rules). `registerRecipeWidgets(registry, recipes,
|
|
206
|
+
resolveExport, { replace?, enabled? })` (async, Svelte-free, on both entries)
|
|
207
|
+
turns the manifest's widget surfaces into `registry.register(...)` calls:
|
|
208
|
+
|
|
209
|
+
| Surface field | Registration |
|
|
210
|
+
|---|---|
|
|
211
|
+
| `type`, `label`, `description`, `icon`, `version` | `type`, `title`, `description`, `icon`, `version` |
|
|
212
|
+
| `options` | `options` (plain JSON; `registry.register` re-validates the schema) |
|
|
213
|
+
| `export` | `loadComponent` (lazy; the export may be a component or a `{ default }` module) |
|
|
214
|
+
| `data.load` | `load` (resolved on first use; a missing or non-function loader is that widget's error tile) |
|
|
215
|
+
| `migrate` | `migrate`, **resolved eagerly** because the registry's `migrate` is synchronous |
|
|
216
|
+
| `allowedIn`, `defaultSpan`, `minSpan`, `maxSpan` | same names |
|
|
217
|
+
| `data.models` | not registered: documentation of what the loader reads; confine with the page's `models` |
|
|
218
|
+
|
|
219
|
+
- **The module resolver is injected.** `resolveExport(specifier, exportName)` is
|
|
220
|
+
the host's: a static map of dynamic imports in a bundled app, a stub in tests.
|
|
221
|
+
Nothing is imported when the manifest is read, and the registration itself
|
|
222
|
+
imports nothing except `migrate` exports. Relative or absolute specifiers
|
|
223
|
+
are refused.
|
|
224
|
+
- **Never throws for a bad surface.** The result is `{ registered, skipped,
|
|
225
|
+
dispose }`; a skip carries `reason` `duplicate_type` (a core widget or another
|
|
226
|
+
recipe owns the type; `replace` overrides), `invalid` (the registry refused the
|
|
227
|
+
definition) or `unresolved` (a `migrate` export is missing). One broken package
|
|
228
|
+
cannot take down the overview.
|
|
229
|
+
- **`enabled(recipeId)`** keeps widgets of recipes that are off out of the add
|
|
230
|
+
list. Call the helper again (after `dispose()`) when the set changes.
|
|
231
|
+
- Widget types share one registry namespace with the core widgets
|
|
232
|
+
(`metric`, `chart`, `records`, `shortcuts`, `note`). Pages still confine what
|
|
233
|
+
can appear with `defineOverview({ allowed })`, and a widget with `allowedIn`
|
|
234
|
+
only validates inside those overview ids.
|
|
235
|
+
- `src/components/overview/__tests__/recipe-widgets.test.ts` covers lazy
|
|
236
|
+
resolution, the loader and migrate paths, allowed placements and the skip
|
|
237
|
+
reasons. The scanner's copy of the option vocabulary and patterns is checked
|
|
238
|
+
against `types.ts` / `schema.ts` by `packages/scanner/src/__tests__/recipe-widgets.test.ts`,
|
|
239
|
+
and a type-level assertion here keeps `RecipeWidgetOptionType` equal to
|
|
240
|
+
`WidgetOptionType`.
|
|
241
|
+
|
|
242
|
+
## Extension points left for later phases
|
|
243
|
+
|
|
244
|
+
- **Phase 2, package widgets (#3727, done).** See "Recipe widgets" below.
|
|
245
|
+
- **Phase 3, production persistence.** Implement the `override` getter /
|
|
246
|
+
`onchange` pair against the `_smrt_` table (tenant tier merged into
|
|
247
|
+
`definition.defaults`, user tier as the override), validate saves with
|
|
248
|
+
`checkOverviewOverride` and persist its canonical `override`, run
|
|
249
|
+
`loadOverview` in the page load, and supply `loadWidget` as a remote function
|
|
250
|
+
that calls the same `load`. Role gating = `canCustomize` plus the same check in
|
|
251
|
+
the save endpoint. No migration or table lives in this package.
|
|
252
|
+
- **Phase 4, assistant.** The controller methods are the structured operations;
|
|
253
|
+
`restore(override)` plus the `override` getter give Undo (snapshot before,
|
|
254
|
+
restore after). `OverviewOpResult.issues` is the validation feedback to return.
|
|
255
|
+
- **Not built:** the activity widget (Track B, #3710) and agenda.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# smrt-svelte/screens
|
|
2
|
+
|
|
3
|
+
Module semantics for `src/components/screens/` (`./screens`). Package orientation, the cross-module
|
|
4
|
+
invariants, and the traps that apply before editing anything live in
|
|
5
|
+
[../AGENTS.md](../AGENTS.md) — read that first.
|
|
6
|
+
|
|
7
|
+
## Manifest-derived record screens (`./screens`, #3718)
|
|
8
|
+
|
|
9
|
+
`RecipeScreens` is the default screen set for a package that ships models but no
|
|
10
|
+
consumer UI (tags, facts, secrets, profiles, reports, prompts). It composes
|
|
11
|
+
`ListScreen`, `DetailScreen` and `EditForm`, each of which can also be used on
|
|
12
|
+
its own. Every screen takes a generated web `definition`
|
|
13
|
+
(`ScreenCollectionDefinition`, structurally a `SmrtWebCollectionDefinition`) and
|
|
14
|
+
an optional resolved `policy` (`ScreenPolicy`, structurally smrt-fields'
|
|
15
|
+
`ResolvedObjectFieldPolicy`). The module imports neither package: smrt-svelte
|
|
16
|
+
stays below the domain layer, and the app passes both in as props.
|
|
17
|
+
|
|
18
|
+
- **Field selection is `fields.ts`, pure and node-testable.** `deriveScreenFields`
|
|
19
|
+
is the single rule for list / view / edit. A field renders only when it is in
|
|
20
|
+
BOTH the definition and the policy, so sensitive, transient and
|
|
21
|
+
read-permission-gated fields (which the policy resolver omits) can never appear
|
|
22
|
+
on a generated screen. Hidden fields are dropped; system fields (`id`,
|
|
23
|
+
`tenantId`, `createdBy`, `updatedBy`, `createdAt`, `updatedAt`) are never
|
|
24
|
+
editable, and the two timestamps appear on a view as read-only advanced meta.
|
|
25
|
+
Do not add a second selection rule in a component.
|
|
26
|
+
- **Without a policy the code seed applies**: `ui.basic` / `ui.group` / `ui.order`
|
|
27
|
+
hints and the cold-start rule (no `basic` markers => everything basic; any
|
|
28
|
+
marker => unmarked fields advanced). Order is `order`, then declaration order.
|
|
29
|
+
- **Tiers**: list shows basic scalar columns only (no long text, JSON or raw
|
|
30
|
+
reference columns; capped at `DEFAULT_MAX_LIST_COLUMNS`, an explicit `columns`
|
|
31
|
+
list is never capped); view and edit show advanced fields behind a disclosure
|
|
32
|
+
(the edit one opens itself when an advanced field has a problem). Policy
|
|
33
|
+
`label`, `help` and `required` win over the manifest; on create, a resolved
|
|
34
|
+
policy default (an explicit `null` included) beats the manifest default.
|
|
35
|
+
`locked` governs who may change the POLICY, never the record value, so it is
|
|
36
|
+
not applied here.
|
|
37
|
+
- **Values are `values.ts`**: money (`ui.widget: 'currency'` on an INTEGER field
|
|
38
|
+
only) is integer minor units end to end. Editing shows major units but converts
|
|
39
|
+
with exact string math (`majorStringToMinorUnits`), never `* 100`; integers are
|
|
40
|
+
rejected unless JavaScript-safe; datetimes go out as ISO strings (an unchanged datetime keeps the
|
|
41
|
+
loaded record's full precision via `parseDraft`'s `record` context; the control
|
|
42
|
+
only shows minutes); JSON as parsed values. Empty optional text becomes `null` when the field is nullable and `''`
|
|
43
|
+
otherwise (unset text persists as `''`); every other empty optional field is
|
|
44
|
+
`null`. Errors are codes, mapped to messages by the component via `useI18n`.
|
|
45
|
+
- **Transport-neutral.** `RecipeScreens` drives a `RecipeScreensSource`
|
|
46
|
+
(`list` / `get` / `create` / `update` / `delete`); an operation the source lacks
|
|
47
|
+
(or `can` turns off) is simply not offered, so a read-only source is a
|
|
48
|
+
read-only screen set. `view` and `recordId` are bindable and `onnavigate`
|
|
49
|
+
fires on every user navigation, so an app can mirror them into its router.
|
|
50
|
+
`EditForm.onsubmit` throws to report a failed save or returns `{ fieldErrors }`.
|
|
51
|
+
Remount `EditForm` with `{#key}` when switching records (`RecipeScreens` does).
|
|
52
|
+
- **Not the policy-editing surface.** The policy gear, field-usage telemetry and
|
|
53
|
+
the per-field renderer registry live in `ObjectForm`
|
|
54
|
+
(`@happyvertical/smrt-fields/svelte`); `EditForm` is the dependency-light
|
|
55
|
+
default and does not replace it. Not wired into recipe surfaces yet (#3708).
|
|
56
|
+
- Component props live in `types.ts`, not in the `.svelte` files, so the barrel
|
|
57
|
+
never re-exports types from a component.
|
package/agents/workspace.md
CHANGED
|
@@ -83,6 +83,140 @@ and touch input across mobile widths and desktop panel-state combinations.
|
|
|
83
83
|
|
|
84
84
|
See `src/components/workspace/MIGRATION.md` for the old-to-new concept map.
|
|
85
85
|
|
|
86
|
+
### Regions and slots
|
|
87
|
+
|
|
88
|
+
Four regions map to the existing edges (ids and `ShellLayout.panels` keys are
|
|
89
|
+
unchanged): Header (`top`), Left sidebar (`left`), Right sidebar (`right`),
|
|
90
|
+
Footer (`bottom`). Default labels are those names; override via `config`.
|
|
91
|
+
`AdminShell`/`AppShell` take `slots?: Partial<Record<ShellSlot, Snippet>>`
|
|
92
|
+
(`ShellSlot` from `./workspace`): `header.start|center|end`,
|
|
93
|
+
`footer.start|center|end`, `leftSidebar.header|footer`,
|
|
94
|
+
`rightSidebar.header|footer`. Header/footer slots sit in the bar (start after
|
|
95
|
+
the brand/menu opener, end after the account), sidebar header sits above and
|
|
96
|
+
footer below the sidebar's main area. Defaults: brand/title/menu opener/account
|
|
97
|
+
stay where they were (`header.start`/`header.end` areas), `tenantFooter` stays
|
|
98
|
+
the left sidebar footer, `dockToggles` default to `header.end`. There is no
|
|
99
|
+
separate header row.
|
|
100
|
+
|
|
101
|
+
Fallback when a slot's region is hidden (or a sidebar is collapsed), first
|
|
102
|
+
visible wins (`slotFallbackChain`): header.X -> leftSidebar.header ->
|
|
103
|
+
rightSidebar.header -> footer.X; footer.X -> leftSidebar.footer ->
|
|
104
|
+
rightSidebar.footer -> header.X; leftSidebar.header -> header.start ->
|
|
105
|
+
rightSidebar.header -> footer.start; leftSidebar.footer -> footer.start ->
|
|
106
|
+
header.start -> rightSidebar.footer; rightSidebar.header -> header.end ->
|
|
107
|
+
leftSidebar.header -> footer.end; rightSidebar.footer -> footer.end ->
|
|
108
|
+
header.end -> leftSidebar.footer. The legacy `tenantFooter` prop keeps its own
|
|
109
|
+
`footerInHeader` fallback.
|
|
110
|
+
|
|
111
|
+
### Edge toggles and hotkeys are opt-in (#3661)
|
|
112
|
+
|
|
113
|
+
`AdminShell`/`AppShell` `edgeToggles?: boolean | Partial<Record<PanelEdge,
|
|
114
|
+
boolean>>` defaults to `false`: no edge toggle buttons, no hotkey hints, and
|
|
115
|
+
WASD/`?` are inert. Regions are laid out inline: the left sidebar is docked
|
|
116
|
+
open off phones (`ShellState.setInlineEdges`/`isInline`; viewport defaults and
|
|
117
|
+
`overlayMedia` do not apply), and the header/footer are plain bands without a
|
|
118
|
+
drop-down drawer (so `appPanel`/`systemPanel` are not reachable). Visibility
|
|
119
|
+
comes from `ShellLayout.panels.visible` and edit mode. The right edge is the
|
|
120
|
+
dock: dock toggles and focus tools still open it, it just loses its button.
|
|
121
|
+
`hotkeys` (default: follows the toggles) forces shortcuts on (`true`, panels
|
|
122
|
+
behave as drop-downs without buttons) or off. Phones keep the Menu opener and
|
|
123
|
+
the left drawer's close toggle. `showTenantToggle` is a deprecated alias for
|
|
124
|
+
`edgeToggles.left`. Migration: pass `edgeToggles` (true) to keep the previous
|
|
125
|
+
behaviour.
|
|
126
|
+
|
|
127
|
+
### Moving items between slots
|
|
128
|
+
|
|
129
|
+
Movable items have stable ids: dock toggles `dock:<tool>`, each host `slots`
|
|
130
|
+
snippet `slot:<slot>`, and host `slotItems` (`AppShell`, `{ id, label, slot,
|
|
131
|
+
render }[]`, exported type `ShellSlotItem`; keep ids stable, they are stored in
|
|
132
|
+
layouts). `AppShell` also supplies the built-in item `item:brand` (the shell
|
|
133
|
+
`logoSrc`/`logoAlt`, title and subtitle, linked to `homeHref` when set, default slot `header.start`, movable, same fallback chain
|
|
134
|
+
when the header is hidden); it sets `AdminShell` `brandInSlot` so the top band
|
|
135
|
+
draws no brand of its own (standalone `AdminShell` still does). The menu
|
|
136
|
+
opener and account content are not items yet (#3656 step 3).
|
|
137
|
+
|
|
138
|
+
`ShellLayout.placements?: Record<itemId, ShellSlot>` (additive, still version
|
|
139
|
+
1) overrides default slots. Pure helpers in `layout.ts` (also `./workspace/layout`):
|
|
140
|
+
`placeShellItem(layout, id, slot, defaultSlot?)` (passing the default drops a
|
|
141
|
+
no-op override; re-placing puts the item last), `resetShellItemPlacement`,
|
|
142
|
+
`resolveShellPlacements(items, layout)` (default order first, then placement
|
|
143
|
+
order; unknown ids and slots ignored) and `resolveShellVisiblePlacements(items,
|
|
144
|
+
layout, visible)` (placement first, then the hidden-region fallback above).
|
|
145
|
+
`useShellLayout()` adds `placeItem(id, slot)`, `resetItem(id)`, and readers
|
|
146
|
+
`placementItems`, `placements` (per slot) and `isRegionVisible(region)`.
|
|
147
|
+
|
|
148
|
+
### Editing the layout in place
|
|
149
|
+
|
|
150
|
+
`AppShell` `layoutEditing?: boolean | { slot?; floating? }` opts in (off: no toggle,
|
|
151
|
+
`setEditing(true)` refused, existing apps unchanged). It adds the built-in item
|
|
152
|
+
`item:layout-edit` (default slot `header.end`, normal hidden-region fallback):
|
|
153
|
+
a pencil `ShellIconButton` named "Edit layout" with `aria-pressed`; the same
|
|
154
|
+
button turns edit mode off (it stays a pencil, highlighted while on). Escape
|
|
155
|
+
also exits when no section toolbar is open (an open toolbar, or a keyboard move,
|
|
156
|
+
consumes Escape first).
|
|
157
|
+
`{ floating: true }` instead renders the same button fixed in the top-right
|
|
158
|
+
corner (round, elevated, safe-area aware, z-index 45): not a slot item, not
|
|
159
|
+
movable, never displaced by hidden regions. The header reserves end padding for
|
|
160
|
+
it, or, when the header is hidden, the right sidebar reserves top padding, or main
|
|
161
|
+
does when no right sidebar is shown
|
|
162
|
+
(`--smrt-shell-floating-reserve-inline|block|main`, set by `AppShell`).
|
|
163
|
+
A polite live region announces the mode. `useShellLayout()` has
|
|
164
|
+
`editable`, `editing` and `setEditing(boolean)` for hosts and assistants.
|
|
165
|
+
|
|
166
|
+
While `editing`:
|
|
167
|
+
|
|
168
|
+
- `AdminShell` `layoutEdit` (`ShellLayoutEditSurface`, set by `AppShell`) renders
|
|
169
|
+
every slot of a visible region as a dashed drop zone (entering edit mode
|
|
170
|
+
expands a collapsed left/right sidebar so its header/footer zones exist, and
|
|
171
|
+
leaving restores it; a railless `rail: false` edge is never revealed: it
|
|
172
|
+
stays as the user left it, and while editing a closed railless right edge
|
|
173
|
+
with focus/dock tools shows a slim "Open <tool>" indicator tab
|
|
174
|
+
(`data-edit-indicator`, z 21, no layout shift) that opens it and closes it
|
|
175
|
+
again on exit) (`data-smrt-edit-zone`)
|
|
176
|
+
labelled "Header · Left", empty ones included, highlighted
|
|
177
|
+
(`data-drop-target`) while a drag targets it. Movable items render exactly as
|
|
178
|
+
on the site (inside an `inert` wrapper) with a grip; the toggle itself is
|
|
179
|
+
fixed. One headless `createSortable` engine (confined to the shell root,
|
|
180
|
+
`allowSameContainerReorder: false`) drives pointer, native-drag and keyboard
|
|
181
|
+
moves (Space, Up/Down across zones in visual order, Enter drops, Escape
|
|
182
|
+
cancels) with the same announcements as `Sortable`
|
|
183
|
+
(`sortable/announce.ts`), committing `placeItem(id, slot)`. Items whose region
|
|
184
|
+
is hidden show in the zone they fall back to.
|
|
185
|
+
- Nothing in the header band renders outside the drop zones except each
|
|
186
|
+
region's edit control: the brand is an item in `header.start`, and the Menu
|
|
187
|
+
opener is hidden off phones. Every region, a collapsed sidebar rail included, gets an icon-only eye-off
|
|
188
|
+
"Hide <region>" button (`ShellLayoutEditSurface.regionControl`, end of the
|
|
189
|
+
header/footer band, top of a sidebar) that writes
|
|
190
|
+
`setPanel(edge, { visible: false })`; the strip's "Show" restores it. The
|
|
191
|
+
last visible region's button is disabled with an explanatory tooltip. Items
|
|
192
|
+
of a hidden region (the edit toggle included) follow the fallback chain.
|
|
193
|
+
Hiding the right sidebar (the dock) makes `useShellDock().available` false:
|
|
194
|
+
dock toggles render unregistered and `open` is refused until it is shown.
|
|
195
|
+
- Hidden, available regions render as thin dashed strips ("Right sidebar ·
|
|
196
|
+
hidden") with an eye "Show <region>" button (`setPanel(edge, { visible })`).
|
|
197
|
+
- `ShellNavEditor` replaces `TenantNav`: the real rows plus grips on every
|
|
198
|
+
heading and item (existing reorder/move-across-sections), icon-only
|
|
199
|
+
`ShellIconButton`s (eye `aria-pressed` = shown in navigation, heading
|
|
200
|
+
`aria-pressed` = title shown, host actions) on each section and an eye per
|
|
201
|
+
item, and a "New section" button at the end.
|
|
202
|
+
- Clicking a section heading opens its floating toolbar (rename input focused,
|
|
203
|
+
title, hide, delete for custom sections with a confirm when non-empty, host
|
|
204
|
+
actions). With `(hover: hover) and (pointer: fine)` hovering also opens it
|
|
205
|
+
(closes on leave unless a click pinned it); touch or no hover is click/tap
|
|
206
|
+
only. One toolbar at a time; Escape closes and returns focus to the heading;
|
|
207
|
+
a pinned toolbar closes on outside pointer or focus leaving.
|
|
208
|
+
|
|
209
|
+
Host extension point: `AppShell` `sectionActions?: Snippet<[ShellSectionActionsContext]>`
|
|
210
|
+
(`{ sectionId, label, custom, editing }`) renders icon buttons in both the
|
|
211
|
+
section overlay and its toolbar (e.g. the planner's Options gear and Help);
|
|
212
|
+
use `ShellIconButton` (from `./workspace`) for matching looks. It renders only
|
|
213
|
+
while editing.
|
|
214
|
+
|
|
215
|
+
`ShellLayoutEditor` no longer has a Placement section (superseded by dragging in
|
|
216
|
+
place); it keeps panels, the navigation sort (icon toggles `aria-pressed` for
|
|
217
|
+
"Show <name> in navigation" / "Show title of <name>"), the preview and Reset.
|
|
218
|
+
The layout helpers and `placeItem`/`resetItem` stay.
|
|
219
|
+
|
|
86
220
|
### Activity ticker
|
|
87
221
|
|
|
88
222
|
`ActivityTicker` accepts app-owned `activities: ReadonlyArray<ShellActivity>` plus
|
|
@@ -219,11 +353,75 @@ control panel), wired by `app/AppShell.svelte`.
|
|
|
219
353
|
`moveItem(id, sectionId, toIndex?)`, `hide(id)`, `show(id)`, `setPanel(edge,
|
|
220
354
|
{ visible?, initial? })`, `reset()`, each returning whether anything changed,
|
|
221
355
|
plus readers (`layout`, `sections`, `panels`, `applied`, `customized`,
|
|
222
|
-
`isHidden
|
|
356
|
+
`isHidden`; item placement is in "Moving items between slots", edit mode in
|
|
357
|
+
"Editing the layout in place"). An assistant calls the same methods the editor does. The
|
|
223
358
|
context is separate from `useAdminShell()` because `AppShell`, not
|
|
224
359
|
`AdminShell`, owns the navigation.
|
|
360
|
+
- **Sections belong to the app.** Hosts (and recipes, via the host) suggest
|
|
361
|
+
sections as `ShellNavGroup`s; the user overrides them in the same additive
|
|
362
|
+
version-1 layout: `sections[id] = { label?, showTitle? }` (rename; hide the
|
|
363
|
+
title) and `customSections: { id: 'custom:...', label }[]` (user-created).
|
|
364
|
+
Custom sections join `sectionOrder`, receive items through `moved`, show in
|
|
365
|
+
the editor when empty but not in the nav, and get a unique `custom:` id.
|
|
366
|
+
`showTitle: false` (also settable by a host on `ShellNavGroup.showTitle`)
|
|
367
|
+
renders the items flat in a `role="group"` named by the heading, no
|
|
368
|
+
`<details>`/`<summary>`. `applyShellLayout` keeps the section's original id
|
|
369
|
+
on renamed output groups. Helpers: `renameShellSection`,
|
|
370
|
+
`setShellSectionTitleVisible`, `createShellSection`, `deleteShellSection`
|
|
371
|
+
(custom only; items return to their default sections). Old stored layouts
|
|
372
|
+
need no migration; new host sections and items land in their suggested slot.
|
|
373
|
+
Controller: `renameSection`, `setSectionTitleVisible`, `createSection(label)`
|
|
374
|
+
(returns the id), `deleteSection`.
|
|
375
|
+
- **Item labels.** The same layout renames single navigation entries:
|
|
376
|
+
`items[itemId] = { label? }` (additive; trimmed, blank removed; ids as above,
|
|
377
|
+
top-level items of `nav` and groups). `resolveShellNavModel` items carry
|
|
378
|
+
`label` / `defaultLabel`; `applyShellLayout` emits the renamed item with
|
|
379
|
+
`label` = the user's and `defaultLabel` = the host's (so nav, breadcrumbs and
|
|
380
|
+
titles that read `nav` follow the rename). Helper `renameShellItem(nav, groups,
|
|
381
|
+
layout, itemId, label | null)`; controller `renameItem(itemId, label | null)`
|
|
382
|
+
(null or blank resets). Edit mode: each `ShellNavEditor` row has an icon-only
|
|
383
|
+
"Rename <label>" button opening an inline field (Enter saves, Escape cancels,
|
|
384
|
+
blur saves) and, once renamed, "Reset <label> to <original>"; the original shows
|
|
385
|
+
as the row tooltip. Presets ("cookbooks") ship it in the stored layout.
|
|
386
|
+
- **Sections-only navigation (`navMode: 'sections'`).** `AppShell` (and
|
|
387
|
+
`TenantNav` / `ShellNavEditor` directly) take `navMode?: 'items' | 'sections'`
|
|
388
|
+
(default `'items'`, unchanged). In `'sections'` the left sidebar shows one
|
|
389
|
+
link per section (icon + label), no entries; a collapsed rail (`tenantRail`)
|
|
390
|
+
shows the icons with tooltips. The link goes to `ShellNavGroup.href`, else
|
|
391
|
+
`AppShell` `sectionHref(sectionId)` (user-created sections), else the first
|
|
392
|
+
entry; it is `aria-current="page"` on that page and `"true"` on any of the
|
|
393
|
+
section's entry pages. `AppShell` also takes `iconComponent` for host icon
|
|
394
|
+
names. `ShellNavGroup.icon` / `.href` are additive; the user override is
|
|
395
|
+
`sections[id].icon` (trimmed; blank or the host's icon removes it), helper
|
|
396
|
+
`setShellSectionIcon(nav, groups, layout, id, icon | null)`, controller
|
|
397
|
+
`setSectionIcon(id, icon | null)`; `resolveShellNavModel` sections carry
|
|
398
|
+
`icon` / `defaultIcon` and `applyShellLayout` emits the effective `icon`.
|
|
399
|
+
Icons are shell icon names (`SHELL_SECTION_ICONS` is the picker set, drawn
|
|
400
|
+
from Material icons like the rest of `SHELL_ICON_PATHS`; `SHELL_DEFAULT_SECTION_ICON`
|
|
401
|
+
is `folder`) or host names rendered by `iconComponent` (`ShellSectionIcon`
|
|
402
|
+
tries the built-in set first). Edit mode in this mode: sections keep grip,
|
|
403
|
+
rename, hide, delete; the title toggle is replaced by an "Icon of <label>"
|
|
404
|
+
popover grid ("Use <icon> icon", `aria-pressed` on the current one; Escape
|
|
405
|
+
closes the grid before the toolbar). Entries are not in the sidebar.
|
|
406
|
+
- **`ShellSectionMenu`** (`sectionId`, `controller?`, `meta(entry)`,
|
|
407
|
+
`actions(entry)`, `iconComponent`, `aria-label`, `layout`): the section's page body.
|
|
408
|
+
`layout="cards"` renders an auto-fill grid (min 16rem) of cards: 32px icon in a
|
|
409
|
+
tinted circle, title, `ShellNavItem.description` (2 lines), then `meta` and
|
|
410
|
+
`actions` at the bottom; one stretched link, actions stay separate controls;
|
|
411
|
+
edit mode keeps grip/rename/hide in the grid. Unknown icon names draw the
|
|
412
|
+
default glyph (dev warning), never the name. `layout.items[id].description` (host/preset-set, not editable in the UI)
|
|
413
|
+
overrides an item's `description`. Default `list`: A
|
|
414
|
+
`<ul>` of rows (icon, label link, host `meta`, host `actions`, chevron; the
|
|
415
|
+
row is one stretched link, actions sit above it) in applied order with
|
|
416
|
+
renames; hidden entries are omitted. While editing, the same rows become the
|
|
417
|
+
nav editor's chrome (single-container `Sortable` grip with keyboard moves,
|
|
418
|
+
inline rename/reset, show/hide toggle) driving `moveItem`/`renameItem`/
|
|
419
|
+
`hide`/`show`; rows are not links then. `ShellSectionMenuEntry` is the snippet
|
|
420
|
+
argument (`id, href, label, defaultLabel, icon, hidden, item`).
|
|
225
421
|
- **`ShellLayoutEditor`**: `controller` (default: context), `preview` (default
|
|
226
|
-
true), `iconComponent`.
|
|
422
|
+
true), `iconComponent`. Each section has an inline name input, icon toggles
|
|
423
|
+
for visibility and title, and (custom only) a trash button, which confirms
|
|
424
|
+
when non-empty; a New section button creates one. Mount it on a settings page or in a dock tool.
|
|
227
425
|
|
|
228
426
|
### Sortable and the Board engine
|
|
229
427
|
|
|
@@ -255,9 +453,8 @@ lives beside, not inside, `./workspace` so the AdminShell barrel stays free of
|
|
|
255
453
|
(`{#snippet dock(registry)}`), the instance mounted routes register on
|
|
256
454
|
when `webmcp` UI is on; pass it to `<AssistantDock {registry} />`. `runtimeDiagnostics` (default false) mounts the
|
|
257
455
|
read-only `smrt.runtime.diagnostics.read` WebMCP tool. `dockToggles`
|
|
258
|
-
(`{ tool, label, icon? }[]`) renders icon buttons
|
|
259
|
-
|
|
260
|
-
each toggling the `ShellDockTool` with that id: `aria-pressed` and
|
|
456
|
+
(`{ tool, label, icon?, slot? }[]`) renders icon buttons in the shell slot
|
|
457
|
+
named by `slot` (default `header.end`; see "Regions and slots"), each toggling the `ShellDockTool` with that id: `aria-pressed` and
|
|
261
458
|
`aria-expanded` follow the dock, `aria-controls` is
|
|
262
459
|
`smrt-admin-shell-right-panel`, the label is the tooltip, and `assistant`
|
|
263
460
|
defaults to a chat-bubble icon (`icon: 'chat'`; other text is a glyph). A
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dictation-source.d.ts","sourceRoot":"","sources":["../../../../src/browser-ai/adapters/stt/dictation-source.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dictation-source.d.ts","sourceRoot":"","sources":["../../../../src/browser-ai/adapters/stt/dictation-source.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE5D,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,aAA0C,GAClD,MAAM,OAAO,CAAC,UAAU,CAAC,CAmB3B"}
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* adapter lazily, once, the first time someone starts dictating: nothing
|
|
8
8
|
* loads and no microphone prompt appears until then. Defaults to the
|
|
9
9
|
* browser's own speech recognition (`browser-speech`), which needs no
|
|
10
|
-
* download; an
|
|
10
|
+
* download; an on-device model is never downloaded by dictation (see
|
|
11
|
+
* `LocalSpeechSTTAdapter.prepare`). An unsupported browser rejects with
|
|
11
12
|
* `CapabilityNotAvailableError`, which `Dictation` reports in plain words.
|
|
12
13
|
*
|
|
13
14
|
* @example
|
|
@@ -26,7 +27,12 @@ export function createSttDictationSource(options = { type: 'browser-speech' }) {
|
|
|
26
27
|
return () => {
|
|
27
28
|
adapter ??= (async () => {
|
|
28
29
|
const created = await getSTT(options);
|
|
29
|
-
|
|
30
|
+
// An adapter that needs a download is never loaded here: dictation must
|
|
31
|
+
// not start one. It checks its own model when started, and the host
|
|
32
|
+
// loads it explicitly (after asking).
|
|
33
|
+
if (!created.getCapabilities().requiresDownload) {
|
|
34
|
+
await created.ensureInitialized();
|
|
35
|
+
}
|
|
30
36
|
return created;
|
|
31
37
|
})().catch((error) => {
|
|
32
38
|
// Let a later tap try again (for example after a permission change).
|
|
@@ -20,8 +20,11 @@ import type { GetSTTOptions, STTAdapter } from './types.js';
|
|
|
20
20
|
* // Whisper.cpp (recommended for accuracy)
|
|
21
21
|
* const stt = await getSTT({ type: 'whisper-cpp', model: 'tiny.en' });
|
|
22
22
|
*
|
|
23
|
-
* // Whisper
|
|
24
|
-
* const stt = await getSTT({ type: 'whisper-
|
|
23
|
+
* // Local Whisper (transformers.js; WebGPU or WASM, one-time ~45 MB download)
|
|
24
|
+
* const stt = await getSTT({ type: 'whisper-local' });
|
|
25
|
+
*
|
|
26
|
+
* // Moonshine (fastest for live dictation, one-time ~32 MB download)
|
|
27
|
+
* const stt = await getSTT({ type: 'moonshine' });
|
|
25
28
|
* ```
|
|
26
29
|
*/
|
|
27
30
|
export declare function getSTT(options?: GetSTTOptions): Promise<STTAdapter>;
|
|
@@ -45,5 +48,5 @@ export declare function getSTTAuto(options?: Partial<Omit<GetSTTOptions, 'type'>
|
|
|
45
48
|
/**
|
|
46
49
|
* Check if a specific STT backend is available
|
|
47
50
|
*/
|
|
48
|
-
export declare function isSTTAvailable(type: 'browser-speech' | 'whisper-wasm'): boolean;
|
|
51
|
+
export declare function isSTTAvailable(type: 'browser-speech' | 'whisper-wasm' | 'whisper-local' | 'moonshine'): boolean;
|
|
49
52
|
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../../src/browser-ai/adapters/stt/factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAEV,aAAa,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../../src/browser-ai/adapters/stt/factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAEV,aAAa,EAEb,UAAU,EAEX,MAAM,YAAY,CAAC;AAkCpB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAuB7E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,UAAU,CAC9B,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAM,GACjD,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,gBAAgB,GAAG,cAAc,GAAG,eAAe,GAAG,WAAW,GACtE,OAAO,CAgBT"}
|