@ai-ecoverse/slicc-spectrum 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +86 -3
  2. package/dist/chunk-364Y2XOJ.js +28 -0
  3. package/dist/chunk-364Y2XOJ.js.map +7 -0
  4. package/dist/chunk-4GQ6THC2.js +18 -0
  5. package/dist/chunk-4GQ6THC2.js.map +7 -0
  6. package/dist/chunk-5OVGH7HO.js +28 -0
  7. package/dist/chunk-5OVGH7HO.js.map +7 -0
  8. package/dist/chunk-5XWUZJTT.js +8 -0
  9. package/dist/chunk-5XWUZJTT.js.map +7 -0
  10. package/dist/chunk-64K5VONJ.js +11 -0
  11. package/dist/chunk-64K5VONJ.js.map +7 -0
  12. package/dist/chunk-6A6NIESE.js +9 -0
  13. package/dist/chunk-6A6NIESE.js.map +7 -0
  14. package/dist/chunk-6JNYNXUQ.js +180 -0
  15. package/dist/chunk-6JNYNXUQ.js.map +7 -0
  16. package/dist/chunk-6JYCQXDO.js +8 -0
  17. package/dist/chunk-6JYCQXDO.js.map +7 -0
  18. package/dist/chunk-6N3GZNXH.js +181 -0
  19. package/dist/chunk-6N3GZNXH.js.map +7 -0
  20. package/dist/chunk-6ODADG7T.js +8 -0
  21. package/dist/chunk-6ODADG7T.js.map +7 -0
  22. package/dist/chunk-6T3O5K6R.js +8 -0
  23. package/dist/chunk-6T3O5K6R.js.map +7 -0
  24. package/dist/chunk-7PY7B3ZW.js +59 -0
  25. package/dist/chunk-7PY7B3ZW.js.map +7 -0
  26. package/dist/chunk-AXQFWXYZ.js +19 -0
  27. package/dist/chunk-AXQFWXYZ.js.map +7 -0
  28. package/dist/chunk-BDOI3WEE.js +8 -0
  29. package/dist/chunk-BDOI3WEE.js.map +7 -0
  30. package/dist/chunk-BHAGWMDD.js +8 -0
  31. package/dist/chunk-BHAGWMDD.js.map +7 -0
  32. package/dist/chunk-C7X653JJ.js +8 -0
  33. package/dist/chunk-C7X653JJ.js.map +7 -0
  34. package/dist/chunk-CGS66GRP.js +11 -0
  35. package/dist/chunk-CGS66GRP.js.map +7 -0
  36. package/dist/chunk-CONYKGKV.js +11 -0
  37. package/dist/chunk-CONYKGKV.js.map +7 -0
  38. package/dist/chunk-CU7BC2RI.js +11 -0
  39. package/dist/chunk-CU7BC2RI.js.map +7 -0
  40. package/dist/chunk-EN3XGF2M.js +26 -0
  41. package/dist/chunk-EN3XGF2M.js.map +7 -0
  42. package/dist/chunk-ER3HU7OE.js +22 -0
  43. package/dist/chunk-ER3HU7OE.js.map +7 -0
  44. package/dist/chunk-EX57SDII.js +8 -0
  45. package/dist/chunk-EX57SDII.js.map +7 -0
  46. package/dist/chunk-GKXQPI4G.js +8 -0
  47. package/dist/chunk-GKXQPI4G.js.map +7 -0
  48. package/dist/chunk-HBUX7E54.js +234 -0
  49. package/dist/chunk-HBUX7E54.js.map +7 -0
  50. package/dist/chunk-I2NMYJ25.js +17 -0
  51. package/dist/chunk-I2NMYJ25.js.map +7 -0
  52. package/dist/chunk-I4OYHPAU.js +11 -0
  53. package/dist/chunk-I4OYHPAU.js.map +7 -0
  54. package/dist/chunk-IBQ4O4NO.js +13 -0
  55. package/dist/chunk-IBQ4O4NO.js.map +7 -0
  56. package/dist/chunk-J3QOBXZJ.js +1093 -0
  57. package/dist/chunk-J3QOBXZJ.js.map +7 -0
  58. package/dist/chunk-JASEW37G.js +411 -0
  59. package/dist/chunk-JASEW37G.js.map +7 -0
  60. package/dist/chunk-JBYBW627.js +8 -0
  61. package/dist/chunk-JBYBW627.js.map +7 -0
  62. package/dist/chunk-JWTAKXQS.js +8 -0
  63. package/dist/chunk-JWTAKXQS.js.map +7 -0
  64. package/dist/chunk-KMP5HO3E.js +11 -0
  65. package/dist/chunk-KMP5HO3E.js.map +7 -0
  66. package/dist/chunk-KWPU2PY3.js +14 -0
  67. package/dist/chunk-KWPU2PY3.js.map +7 -0
  68. package/dist/chunk-KYBD6ZRT.js +8 -0
  69. package/dist/chunk-KYBD6ZRT.js.map +7 -0
  70. package/dist/chunk-LBXW6XNL.js +18 -0
  71. package/dist/chunk-LBXW6XNL.js.map +7 -0
  72. package/dist/chunk-LDR4U5KX.js +8 -0
  73. package/dist/chunk-LDR4U5KX.js.map +7 -0
  74. package/dist/chunk-LII3WY6Y.js +11 -0
  75. package/dist/chunk-LII3WY6Y.js.map +7 -0
  76. package/dist/chunk-LY7WVBCB.js +10 -0
  77. package/dist/chunk-LY7WVBCB.js.map +7 -0
  78. package/dist/chunk-MJVAL555.js +8 -0
  79. package/dist/chunk-MJVAL555.js.map +7 -0
  80. package/dist/chunk-NLDFGCIL.js +11 -0
  81. package/dist/chunk-NLDFGCIL.js.map +7 -0
  82. package/dist/chunk-OFQ56DAN.js +2638 -0
  83. package/dist/chunk-OFQ56DAN.js.map +7 -0
  84. package/dist/chunk-S5EGO4NA.js +11 -0
  85. package/dist/chunk-S5EGO4NA.js.map +7 -0
  86. package/dist/chunk-T2LAT2D6.js +168 -0
  87. package/dist/chunk-T2LAT2D6.js.map +7 -0
  88. package/dist/chunk-T5NHW4KC.js +23 -0
  89. package/dist/chunk-T5NHW4KC.js.map +7 -0
  90. package/dist/chunk-TAZBKRHT.js +10 -0
  91. package/dist/chunk-TAZBKRHT.js.map +7 -0
  92. package/dist/chunk-TK4ZJ7LA.js +5346 -0
  93. package/dist/chunk-TK4ZJ7LA.js.map +7 -0
  94. package/dist/chunk-TS7SL372.js +687 -0
  95. package/dist/chunk-TS7SL372.js.map +7 -0
  96. package/dist/chunk-UCIBH53C.js +11 -0
  97. package/dist/chunk-UCIBH53C.js.map +7 -0
  98. package/dist/chunk-XZM23TK4.js +11 -0
  99. package/dist/chunk-XZM23TK4.js.map +7 -0
  100. package/dist/chunk-Y4Z7K443.js +64 -0
  101. package/dist/chunk-Y4Z7K443.js.map +7 -0
  102. package/dist/chunk-YPQKCWWG.js +19 -0
  103. package/dist/chunk-YPQKCWWG.js.map +7 -0
  104. package/dist/chunk-YX6SI5VA.js +11 -0
  105. package/dist/chunk-YX6SI5VA.js.map +7 -0
  106. package/dist/chunk-ZMBN6APP.js +11 -0
  107. package/dist/chunk-ZMBN6APP.js.map +7 -0
  108. package/dist/fonts/source-code-pro-latin-400-normal.woff2 +0 -0
  109. package/dist/fonts/source-code-pro-latin-600-normal.woff2 +0 -0
  110. package/dist/slicc-dummy.js +2811 -0
  111. package/dist/slicc-dummy.js.map +7 -0
  112. package/dist/slicc-terminal.js +7 -5369
  113. package/dist/slicc-terminal.js.map +4 -4
  114. package/dist/slicc-ui.js +61411 -0
  115. package/dist/slicc-ui.js.map +7 -0
  116. package/dist/types/app/agents.d.ts +11 -0
  117. package/dist/types/app/app.d.ts +34 -0
  118. package/dist/types/app/base.d.ts +35 -0
  119. package/dist/types/app/browser.d.ts +25 -0
  120. package/dist/types/app/changes.d.ts +24 -0
  121. package/dist/types/app/chat.d.ts +11 -0
  122. package/dist/types/app/composer.d.ts +69 -0
  123. package/dist/types/app/files.d.ts +56 -0
  124. package/dist/types/app/fonts.d.ts +3 -0
  125. package/dist/types/app/freezer.d.ts +11 -0
  126. package/dist/types/app/markdown.d.ts +33 -0
  127. package/dist/types/app/memory.d.ts +39 -0
  128. package/dist/types/app/messages.d.ts +21 -0
  129. package/dist/types/app/monitor.d.ts +11 -0
  130. package/dist/types/app/panels.d.ts +39 -0
  131. package/dist/types/app/settings.d.ts +21 -0
  132. package/dist/types/app/spectrum.d.ts +37 -0
  133. package/dist/types/app/sprinkle.d.ts +18 -0
  134. package/dist/types/app/terminals.d.ts +25 -0
  135. package/dist/types/app/tray.d.ts +25 -0
  136. package/dist/types/components/code-view.d.ts +47 -0
  137. package/dist/types/components/dock.d.ts +24 -0
  138. package/dist/types/components/file-tree.d.ts +18 -0
  139. package/dist/types/components/sheets.d.ts +1 -0
  140. package/dist/types/dummy/agent.d.ts +32 -0
  141. package/dist/types/dummy/browser.d.ts +15 -0
  142. package/dist/types/dummy/clock.d.ts +5 -0
  143. package/dist/types/dummy/extras.d.ts +8 -0
  144. package/dist/types/dummy/files.d.ts +14 -0
  145. package/dist/types/dummy/fixtures.d.ts +12 -0
  146. package/dist/types/dummy/index.d.ts +6 -0
  147. package/dist/types/dummy/memory.d.ts +9 -0
  148. package/dist/types/dummy/monitor.d.ts +9 -0
  149. package/dist/types/dummy/script.d.ts +29 -0
  150. package/dist/types/dummy/settings.d.ts +13 -0
  151. package/dist/types/dummy/shell.d.ts +16 -0
  152. package/dist/types/dummy/showcase.d.ts +6 -0
  153. package/dist/types/dummy/sprinkles.d.ts +9 -0
  154. package/dist/types/dummy/terminals.d.ts +15 -0
  155. package/dist/types/dummy/tray.d.ts +10 -0
  156. package/dist/types/dummy.d.ts +2 -0
  157. package/dist/types/model/emitter.d.ts +9 -0
  158. package/dist/types/model/types.d.ts +455 -0
  159. package/dist/types/ui.d.ts +23 -0
  160. package/package.json +34 -11
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # slicc-spectrum
2
2
 
3
- Web components for SLICC. The first one is `<slicc-terminal>`, a terminal built on [wterm](https://github.com/vercel-labs/wterm) (`@wterm/dom` 0.5.4, Zig/WASM VT core) that talks to [`@ai-ecoverse/slicc-kernel`](https://github.com/ai-ecoverse/slicc-kernel) through a small backend interface. It is a standards custom element with no framework and no shadow root, so it can move to a shared web-components repo unchanged.
3
+ Web components for SLICC: `<slicc-terminal>`, and SLICC's app UI on [Spectrum Web Components](https://opensource.adobe.com/spectrum-web-components/) (see [UI](#ui)). `<slicc-terminal>` is a terminal built on [wterm](https://github.com/vercel-labs/wterm) (`@wterm/dom` 0.5.4, Zig/WASM VT core) that talks to [`@ai-ecoverse/slicc-kernel`](https://github.com/ai-ecoverse/slicc-kernel) through a small backend interface. It is a standards custom element with no framework and no shadow root, so it can move to a shared web-components repo unchanged.
4
4
 
5
5
  ```html
6
6
  <slicc-terminal></slicc-terminal>
@@ -98,8 +98,89 @@ Things found while building this against wterm 0.5.4, recorded here, not pushed
98
98
  - The Zig core maps 24-bit colours (`38;2;r;g;b`) to the nearest of the 256 palette colours, and the DOM renderer draws the 6×6×6 cube in steps of 51 rather than xterm's 0/95/135/175/215/255. `@wterm/ghostty` is the full-VT alternative.
99
99
  - wterm sends pasted text with its `\n` line breaks unchanged, whereas xterm.js turns them into `\r`. The element does that conversion itself.
100
100
  - `@wterm/core` always ships the WASM inlined as base64 behind a dynamic import. A build without it, or an explicit entry point that takes a URL, would save the bundler plugin.
101
+ - wterm focuses its input when it finishes mounting. `<slicc-terminals>` hands focus back to where it was unless the terminal was focused on purpose.
101
102
  - wterm reads focus and selection from `ownerDocument` (`activeElement`, `getSelection()`), so selection and copy don't work inside a shadow root that wterm itself owns. That's why the element renders in light DOM. It still works when the element is placed inside someone else's shadow root.
102
103
 
104
+ ## UI
105
+
106
+ `dist/slicc-ui.js` is SLICC's app shell on Spectrum Web Components 1.12 with the Spectrum 2 theme (`<sp-theme system="spectrum-two">`), in light and dark. It runs against a typed model, not against the kernel, the agent or the browser directly, and is not wired to any of them yet. `dist/slicc-dummy.js` provides a dummy model that streams replies and tool calls with timers.
107
+
108
+ ```html
109
+ <slicc-app></slicc-app>
110
+ <script type="module">
111
+ import { createDummyModel } from './dist/slicc-dummy.js';
112
+ import './dist/slicc-ui.js';
113
+
114
+ document.querySelector('slicc-app').model = createDummyModel({ storage: localStorage });
115
+ </script>
116
+ ```
117
+
118
+ `npm start` serves it at `/ui/`. `?fonts=<url>` loads Adobe Clean from another folder (see [Fonts](#fonts)).
119
+
120
+ ### Layouts and rails
121
+
122
+ The layout follows the width of `<slicc-app>`, which it reflects as its `screen` attribute: `phone` (under 640 px) has one column, `tablet` (under 1200 px) two, `desktop` three, like SLICC v6. Each screen class starts with few panels open and saves its own layout (`slicc-ui.layout.<screen>`). Every surface has a home side, left, center or right. Closed panels wait as icons in the left and right rails (on a phone, in one bar at the bottom); one click puts a panel back on its side, next to its neighbours.
123
+
124
+ ### Fonts
125
+
126
+ Text is Adobe Clean and code Spectrum's Source Code Pro. Source Code Pro (OFL) is in `dist/fonts/`, same origin. Adobe Clean can't ship in a public package, so `<slicc-app>` loads it from `fontBase` (`AdobeClean-{Regular,Medium,Bold,ExtraBold}.otf`), which defaults to `/fonts/` on the current origin. Every `*.sliccy.ai` host passes it through to v6, and `npm start` proxies it from `seven.sliccy.ai`. Where it 404s, text falls back to the system font stack. `?delay=` sets the dummy's tick in milliseconds (default 30) and `?color=light|dark|system` the theme.
127
+
128
+ ### Elements
129
+
130
+ | Element | |
131
+ | :--- | :--- |
132
+ | `<slicc-app>` | The shell: header with the agent picker, the View menu and the theme switch, rails, a `<slicc-dock>`, and a status bar. Saves the dock layout per screen class to `storage` (default `localStorage`) under `layoutKey`. |
133
+ | `<slicc-dock>` | Generic. [dockview-core](https://dockview.dev/) 8 with a theme mapped to Spectrum tokens, in its own shadow root. Panels come from `factories` (`name → (params) => HTMLElement`). `open`, `close`, `has`, `content`, `focusPanel`, `cycleGroup`, `cycleTab`, `toJSON`, `restore`, `clear`, and the full `api`. Tabs have a context menu (close, close others, float, maximize). Events: `layout-change`, `active-panel-change`, `panel-close`. |
134
+ | `<slicc-agents>` | Cones with their scoops, status, context fill and unread count. Selecting one makes it the active agent. |
135
+ | `<slicc-chat>` | The active agent's conversation, by day: user messages (with attachments, steered, or delegated from another cone), assistant messages (Markdown with tables, task lists, quotes, code and images; thinking; tool calls, grouped into a collapsible cluster from three in a row; media galleries with images, video and audio; action cards for tools, pull requests and status; plans and checklists; inline diffs; question prompts; delegations; link previews; errors with a fix-it action), standalone tool results, system messages (compaction markers, error cards, notices) and licks, SLICC's events into a cone, on every channel. Permission requests are allowed or denied in place. |
136
+ | `<slicc-composer>` | The message box. <kbd>Enter</kbd> sends, or queues behind a running reply; <kbd>Ctrl</kbd>/<kbd>⌘</kbd>+<kbd>Enter</kbd> steers (interrupts); <kbd>Shift</kbd>+<kbd>Enter</kbd> adds a line; <kbd>Tab</kbd> takes the suggested follow-up; <kbd>↑</kbd>/<kbd>↓</kbd> at the start or end walk this agent's history; <kbd>Esc</kbd> stops. `/` completes commands (`/clear`, `/compact`, `/model`, `/thinking`, `/scoop`, `/stop`, `/theme`) and their arguments, `@` mentions agents and files. Attach from the computer, from SLICC's files, a browser screenshot or a shared secret, or paste and drop files (25 MB each). Queued messages wait above it, to send now or drop. Model and thinking pickers, and dictation where the browser has speech recognition. Drafts are kept per agent. |
137
+ | `<slicc-files>` | The file system as a `<slicc-file-tree>`, with pending changes as git status. Opening a file opens it in a tab. |
138
+ | `<slicc-file-view>` | One file (`path`), highlighted, with its pending change and a link to the diff. |
139
+ | `<slicc-changes>` | Pending changes with their author. Opens the diff, accepts or reverts one change or all of them. |
140
+ | `<slicc-diff-panel>` | The diff of one pending change (`path`), unified or split, with accept and revert. |
141
+ | `<slicc-terminals>` | Terminal sessions in tabs, each a `<slicc-terminal>` on the session's `TerminalBackend`. Sessions stay alive while hidden; `exit` closes the tab. |
142
+ | `<slicc-browser>` | Browser tabs with the agent driving each, an address bar, reload, and the active tab's screenshot. |
143
+ | `<slicc-settings>` | Theme, the model and thinking level for new cones, composer and diff preferences, and accounts to connect, reconnect or disconnect. |
144
+ | `<slicc-memory>` | What agents remember, globally or per cone, grouped by section: search, filter by tag, expand, edit, add and forget. |
145
+ | `<slicc-monitor>` | The live monitor: vitals with sparklines (active agents, spend, budget, fullest context), alerts, and the topology (cones and scoops, terminals, tabs, pending changes, sprinkles, tray followers). |
146
+ | `<slicc-freezer>` | Frozen cones, archived with their scoops: thaw to bring one back, delete, or freeze the active cone (also `/freeze`). |
147
+ | `<slicc-sprinkle>` | An agent-made panel: its HTML runs in a sandboxed frame with the theme's colors, and `postMessage({ type: 'sprinkle-event', … })` reaches the owning cone as a `sprinkle` lick. Sprinkles sit at the top of the right rail. |
148
+ | `<slicc-tray>` | The tray indicator in the header: connection, the float's name, followers and budget; its panel adds role, runtime, spend, the follower list, the join link, and disconnect or reconnect. |
149
+ | `<slicc-file-tree>` | Generic. [`@pierre/trees`](https://www.npmjs.com/package/@pierre/trees) through its `web-components` entry: `paths` (folders end in `/`), `gitStatus`, `expanded`, `reveal(path, focus)`. Fires `file-open` on click and on <kbd>Enter</kbd>. |
150
+ | `<slicc-code-view>` | Generic. A highlighted file through [`@pierre/diffs`](https://www.npmjs.com/package/@pierre/diffs): `path`, `contents`, `color`. |
151
+ | `<slicc-diff-view>` | Generic. A diff through `@pierre/diffs`: `path`, `oldText`, `newText` (`null` for an added or deleted file), `color`, `diff-style` (`unified` or `split`). |
152
+
153
+ Files and diffs open in one editor group next to the chat. Panels ask for them with `open-file` and `open-diff` events (`{ path }`), which `<slicc-app>` handles, or call `app.open('file' | 'diff', path)`.
154
+
155
+ Keys: <kbd>Alt</kbd>+<kbd>1</kbd>… opens and focuses a panel, <kbd>F6</kbd> and <kbd>Shift</kbd>+<kbd>F6</kbd> move between groups, <kbd>Ctrl</kbd>+<kbd>]</kbd> and <kbd>Ctrl</kbd>+<kbd>[</kbd> between tabs, <kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd> switches the theme. In terminal and browser tab strips, <kbd>←</kbd> and <kbd>→</kbd> switch tabs. In the agents and changes lists, arrows, <kbd>Home</kbd>, <kbd>End</kbd> and <kbd>Enter</kbd>; in the file tree, its own arrow keys and <kbd>Enter</kbd> to open. In the composer, <kbd>Enter</kbd> sends, <kbd>Shift</kbd>+<kbd>Enter</kbd> adds a line and <kbd>Esc</kbd> stops a reply.
156
+
157
+ ### Model
158
+
159
+ `SliccModel` (`src/model/types.ts`) has one port per future backend, so adapters can replace the dummy without UI changes. Every port is subscribable with `on(type, listener)`, which returns an unsubscribe function.
160
+
161
+ | Port | Later backed by | |
162
+ | :--- | :--- | :--- |
163
+ | `agent` | `@ai-ecoverse/slicc-agent` | Cones and scoops, the active agent, conversations, `send` (with attachments, as a send, a steer or a queued follow-up) and `stop`, the queue, suggestions, answers to questions, permission decisions, compaction, clearing, the model per agent and new scoops. Assistant messages stream: the same message is re-emitted as its parts grow and its tool calls go from `running` to `done`. |
164
+ | `files` | slicc-kernel's OPFS | `list`, `read`, `write`, `remove`, and pending changes with their before and after text (`accept`, `revert`). |
165
+ | `terminals` | slicc-kernel's terminal API | Terminal sessions; `backend(id)` returns a `TerminalBackend` for `<slicc-terminal>`. |
166
+ | `browser` | `@ai-ecoverse/slicc-cdp` | Tabs, the active tab, `open`, `navigate`, `close`, `screenshot`. |
167
+ | `settings` | local storage | Theme, model, thinking level, composer and diff preferences, the models on offer, and accounts. |
168
+ | `memory` | `@ai-ecoverse/slicc-agent` | Memories with scope, section, tag and body; `save` and `remove`. |
169
+ | `monitor` | all of them | A snapshot of vitals, alerts and sections, re-emitted as the system changes, and `resync`. |
170
+ | `sprinkles` | `@ai-ecoverse/slicc-agent` | Agent-made panels and `send`, which turns a panel's event into a lick. |
171
+ | `tray` | the tray protocol | Connection, role, float kind, followers, spend and budget; `reconnect` and `disconnect`. |
172
+
173
+ The `kitchen-sink` cone holds every kind of message, content and lick in one conversation, for design work and screenshots. The dummy's fixtures are invented: a small forecast API called harbor, with cones, scoops, a conversation per agent, pending changes, browser tabs and accounts. Its replies are scripted by keyword (tests, fix or add, open or docs, files, anything else), and their tool calls act on the other ports: an edit writes a file and shows up as a change, a browse opens a tab.
174
+
175
+ ### Distribution
176
+
177
+ The UI is ESM with code splitting: `slicc-ui.js`, `slicc-dummy.js` and `chunk-*.js` next to them in `dist/`, with no bare imports, so the folder can be served as plain files from OPFS. dockview's ESM build has no CSS; the build takes it from dockview's UMD bundle. `@pierre/diffs` highlights with Shiki. `dist/` carries the grammars SLICC needs most (CSS, diff, HTML, JavaScript, JSON, JSX, Markdown, Python, shell, SQL, TOML, TSX, TypeScript, XML, YAML); every other grammar and theme stays out of `dist/` and is imported from `https://cdn.jsdelivr.net/npm/@shikijs/` (pinned to the installed version, CORS and CORP headers set) the first time a file needs it. `SLICC_GRAMMAR_BASE` points the build at another copy. `dist/` is about 55 files and 5.5 MB of JavaScript. The build fails if React is bundled; `@pierre/trees` lists React as a peer dependency, so npm installs it, but the `web-components` entry runs on Preact. Types are in `dist/types/ui.d.ts` and `dist/types/dummy.d.ts`, exported as `@ai-ecoverse/slicc-spectrum/ui` and `/dummy`.
178
+
179
+ ### dockview notes
180
+
181
+ - Keyboard navigation (`keyboardNavigation`) needs dockview-enterprise, so `<slicc-dock>` implements <kbd>F6</kbd> and <kbd>Ctrl</kbd>+<kbd>]</kbd>/<kbd>[</kbd> itself.
182
+ - A floating group with a border (`--dv-floating-border`, which dockview's own light theme sets) grows by twice the border width on every save and restore. The theme draws the edge with a box shadow instead.
183
+
103
184
  ## Development
104
185
 
105
186
  ```sh
@@ -108,9 +189,11 @@ npm run lint
108
189
  npm test
109
190
  ```
110
191
 
111
- `npm test` builds `dist/` and runs the integration tests in headless Chromium over raw CDP against a fake backend (`test/integration/page/fake-backend.js`). It writes V8 coverage to `coverage/` and CPU profiles, screenshots and console logs to `artifacts/`. The test page is served cross-origin isolated (COOP/COEP), as slicc-kernel requires. `test/integration/kernel.test.mjs` runs `bash -i` end to end on `@ai-ecoverse/slicc-kernel` (a pinned dev dependency), with `@ai-ecoverse/wasm-bash` and `@ai-ecoverse/wasm-coreutils` installed into OPFS by the page (`/kernel.html`). `npm start` serves the test page on port 8080.
192
+ `npm test` builds `dist/` and runs the integration tests in headless Chromium over raw CDP, through the [harness from slicc-shared-web](https://github.com/ai-ecoverse/slicc-shared-web#integration-test-harness), against a fake backend (`test/integration/page/fake-backend.js`). It writes V8 coverage to `coverage/` and CPU profiles, screenshots and console logs to `artifacts/`. The test page is served cross-origin isolated (COOP/COEP), as slicc-kernel requires. `test/integration/kernel.test.mjs` runs `bash -i` end to end on `@ai-ecoverse/slicc-kernel` (a pinned dev dependency), with `@ai-ecoverse/wasm-bash` and `@ai-ecoverse/wasm-coreutils` installed into OPFS by the page (`/kernel.html`). `npm start` serves the test page on port 8080, and the UI at `/ui/`. `test/integration/ui.test.mjs` covers the shell, the layout (moving, closing, floating, reopening and reloading), streaming a reply with a tool call, stopping it, switching themes and the keyboard, and saves screenshots to `artifacts/ui/`.
193
+
194
+ The Biome, TypeScript, lefthook, Renovate and CI configuration comes from [slicc-shared-web](https://github.com/ai-ecoverse/slicc-shared-web), which also provides the `slicc-lint-comments`, `slicc-no-unit-tests` and `slicc-diff-cover` commands used by `npm run lint` and the pre-commit hook.
112
195
 
113
- Unit tests live in `test/unit/`, which is gitignored. The pre-commit hook runs them in Node against happy-dom under monocart and fails the commit unless the staged lines in `src/` are fully covered (`diff-cover --fail-under 100`).
196
+ Unit tests live in `test/unit/`, which is gitignored. The pre-commit hook runs them in Node against happy-dom under monocart and fails the commit unless the staged lines in `src/` are fully covered (`slicc-diff-cover`, which runs `diff-cover --fail-under 100` and needs [uv](https://docs.astral.sh/uv/)).
114
197
 
115
198
  ## License
116
199
 
@@ -0,0 +1,28 @@
1
+ import {
2
+ e
3
+ } from "./chunk-TS7SL372.js";
4
+
5
+ // node_modules/@lit/reactive-element/decorators/query-assigned-elements.js
6
+ function o(o2) {
7
+ return (e2, n) => {
8
+ const { slot: r, selector: s } = o2 ?? {}, c = "slot" + (r ? `[name=${r}]` : ":not([name])");
9
+ return e(e2, n, { get() {
10
+ const t = this.renderRoot?.querySelector(c), e3 = t?.assignedElements(o2) ?? [];
11
+ return void 0 === s ? e3 : e3.filter((t2) => t2.matches(s));
12
+ } });
13
+ };
14
+ }
15
+
16
+ export {
17
+ o
18
+ };
19
+ /*! Bundled license information:
20
+
21
+ @lit/reactive-element/decorators/query-assigned-elements.js:
22
+ (**
23
+ * @license
24
+ * Copyright 2021 Google LLC
25
+ * SPDX-License-Identifier: BSD-3-Clause
26
+ *)
27
+ */
28
+ //# sourceMappingURL=chunk-364Y2XOJ.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../node_modules/@lit/reactive-element/src/decorators/query-assigned-elements.ts"],
4
+ "sourcesContent": ["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/*\n * IMPORTANT: For compatibility with tsickle and the Closure JS compiler, all\n * property decorators (but not class decorators) in this file that have\n * an @ExportDecoratedItems annotation must be defined as a regular function,\n * not an arrow function.\n */\n\nimport type {ReactiveElement} from '../reactive-element.js';\nimport type {QueryAssignedNodesOptions} from './query-assigned-nodes.js';\nimport {desc, type Interface} from './base.js';\n\nexport type QueryAssignedElementsDecorator = {\n // legacy\n (\n proto: Interface<ReactiveElement>,\n name: PropertyKey,\n descriptor?: PropertyDescriptor\n // Note TypeScript requires the return type to be `void|any`\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): void | any;\n\n // standard\n <C extends Interface<ReactiveElement>, V extends Array<Element>>(\n value: ClassAccessorDecoratorTarget<C, V>,\n context: ClassAccessorDecoratorContext<C, V>\n ): ClassAccessorDecoratorResult<C, V>;\n};\n\n/**\n * Options for the {@linkcode queryAssignedElements} decorator. Extends the\n * options that can be passed into\n * [HTMLSlotElement.assignedElements](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/assignedElements).\n */\nexport interface QueryAssignedElementsOptions\n extends QueryAssignedNodesOptions {\n /**\n * CSS selector used to filter the elements returned. For example, a selector\n * of `\".item\"` will only include elements with the `item` class.\n */\n selector?: string;\n}\n\n/**\n * A property decorator that converts a class property into a getter that\n * returns the `assignedElements` of the given `slot`. Provides a declarative\n * way to use\n * [`HTMLSlotElement.assignedElements`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/assignedElements).\n *\n * Can be passed an optional {@linkcode QueryAssignedElementsOptions} object.\n *\n * Example usage:\n * ```ts\n * class MyElement {\n * @queryAssignedElements({ slot: 'list' })\n * listItems!: Array<HTMLElement>;\n * @queryAssignedElements()\n * unnamedSlotEls!: Array<HTMLElement>;\n *\n * render() {\n * return html`\n * <slot name=\"list\"></slot>\n * <slot></slot>\n * `;\n * }\n * }\n * ```\n *\n * Note, the type of this property should be annotated as `Array<HTMLElement>`.\n *\n * @category Decorator\n */\nexport function queryAssignedElements(\n options?: QueryAssignedElementsOptions\n): QueryAssignedElementsDecorator {\n return (<V extends Array<Element>>(\n obj: object,\n name: PropertyKey | ClassAccessorDecoratorContext<unknown, unknown>\n ) => {\n const {slot, selector} = options ?? {};\n const slotSelector = `slot${slot ? `[name=${slot}]` : ':not([name])'}`;\n return desc(obj, name, {\n get(this: ReactiveElement): V {\n const slotEl =\n this.renderRoot?.querySelector<HTMLSlotElement>(slotSelector);\n const elements = slotEl?.assignedElements(options) ?? [];\n return (\n selector === undefined\n ? elements\n : elements.filter((node) => node.matches(selector))\n ) as V;\n },\n });\n }) as QueryAssignedElementsDecorator;\n}\n"],
5
+ "mappings": ";;;;;AA6EM,SAAUA,EACdC,IAAAA;AAEA,SAAA,CACEC,IACAC,MAAAA;AAEA,UAAA,EAAMC,MAACA,GAAIC,UAAEA,EAAAA,IAAYJ,MAAW,CAAA,GAC9BK,IAAe,UAAOF,IAAO,SAASA,CAAAA,MAAU;AACtD,WAAOG,EAAKL,IAAKC,GAAM,EACrB,MAAAK;AACE,YAAMC,IACJC,KAAKC,YAAYC,cAA+BN,CAAAA,GAC5CO,KAAWJ,GAAQK,iBAAiBb,EAAAA,KAAY,CAAA;AACtD,aAAA,WACEI,IACIQ,KACAA,GAASE,OAAQC,CAAAA,OAASA,GAAKC,QAAQZ,CAAAA,CAAAA;IAE/C,EAAA,CAAA;EAEH;AACH;",
6
+ "names": ["queryAssignedElements", "options", "obj", "name", "slot", "selector", "slotSelector", "desc", "get", "slotEl", "this", "renderRoot", "querySelector", "elements", "assignedElements", "filter", "node", "matches"]
7
+ }
@@ -0,0 +1,18 @@
1
+ import {
2
+ defineElement
3
+ } from "./chunk-6A6NIESE.js";
4
+ import {
5
+ Overlay
6
+ } from "./chunk-OFQ56DAN.js";
7
+ import "./chunk-IBQ4O4NO.js";
8
+ import "./chunk-ZMBN6APP.js";
9
+ import "./chunk-Y4Z7K443.js";
10
+ import "./chunk-364Y2XOJ.js";
11
+ import "./chunk-ER3HU7OE.js";
12
+ import "./chunk-JASEW37G.js";
13
+ import "./chunk-TS7SL372.js";
14
+ import "./chunk-AXQFWXYZ.js";
15
+
16
+ // node_modules/@spectrum-web-components/overlay/sp-overlay.js
17
+ defineElement("sp-overlay", Overlay);
18
+ //# sourceMappingURL=chunk-4GQ6THC2.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../node_modules/@spectrum-web-components/overlay/sp-overlay.ts"],
4
+ "sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { Overlay } from './src/Overlay.js';\n\ndefineElement('sp-overlay', Overlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-overlay': Overlay;\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;AAeAA,cAAc,cAAcC,OAAO;",
6
+ "names": ["defineElement", "Overlay"]
7
+ }
@@ -0,0 +1,28 @@
1
+ // node_modules/@spectrum-web-components/reactive-controllers/src/MatchMedia.js
2
+ var IS_MOBILE = "(max-width: 743px) and (hover: none) and (pointer: coarse)";
3
+ var IS_TOUCH_DEVICE = "(hover: none) and (pointer: coarse)";
4
+ var MatchMediaController = class {
5
+ constructor(e, t) {
6
+ this.key = /* @__PURE__ */ Symbol("match-media-key");
7
+ this.matches = false;
8
+ this.host = e, this.host.addController(this), this.media = window.matchMedia(t), this.matches = this.media.matches, this.onChange = this.onChange.bind(this), e.addController(this);
9
+ }
10
+ hostConnected() {
11
+ var e;
12
+ (e = this.media) == null || e.addEventListener("change", this.onChange);
13
+ }
14
+ hostDisconnected() {
15
+ var e;
16
+ (e = this.media) == null || e.removeEventListener("change", this.onChange);
17
+ }
18
+ onChange(e) {
19
+ this.matches !== e.matches && (this.matches = e.matches, this.host.requestUpdate(this.key, !this.matches));
20
+ }
21
+ };
22
+
23
+ export {
24
+ IS_MOBILE,
25
+ IS_TOUCH_DEVICE,
26
+ MatchMediaController
27
+ };
28
+ //# sourceMappingURL=chunk-5OVGH7HO.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../node_modules/@spectrum-web-components/reactive-controllers/src/MatchMedia.ts"],
4
+ "sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport type { ReactiveController, ReactiveElement } from 'lit';\n\nexport const DARK_MODE = '(prefers-color-scheme: dark)';\nexport const IS_MOBILE =\n '(max-width: 743px) and (hover: none) and (pointer: coarse)';\nexport const IS_TOUCH_DEVICE = '(hover: none) and (pointer: coarse)';\n\nexport class MatchMediaController implements ReactiveController {\n key = Symbol('match-media-key');\n\n matches = false;\n\n protected host: ReactiveElement;\n\n protected media: MediaQueryList;\n\n constructor(host: ReactiveElement, query: string) {\n this.host = host;\n this.host.addController(this);\n this.media = window.matchMedia(query);\n this.matches = this.media.matches;\n this.onChange = this.onChange.bind(this);\n host.addController(this);\n }\n\n public hostConnected(): void {\n this.media?.addEventListener('change', this.onChange);\n }\n\n public hostDisconnected(): void {\n this.media?.removeEventListener('change', this.onChange);\n }\n\n protected onChange(event: MediaQueryListEvent): void {\n if (this.matches === event.matches) {\n return;\n }\n this.matches = event.matches;\n this.host.requestUpdate(this.key, !this.matches);\n }\n}\n"],
5
+ "mappings": ";AAaO,IACM,YACX;AAFK,IAGM,kBAAkB;AAExB,IAAM,uBAAN,MAAyD;EAS9D,YAAYA,GAAuBC,GAAe;AARlD,SAAA,MAAM,uBAAO,iBAAiB;AAE9B,SAAA,UAAU;AAOR,SAAK,OAAOD,GACZ,KAAK,KAAK,cAAc,IAAI,GAC5B,KAAK,QAAQ,OAAO,WAAWC,CAAK,GACpC,KAAK,UAAU,KAAK,MAAM,SAC1B,KAAK,WAAW,KAAK,SAAS,KAAK,IAAI,GACvCD,EAAK,cAAc,IAAI;EACzB;EAEO,gBAAsB;AApC/B,QAAAE;AAAAA,KAqCIA,IAAA,KAAK,UAAL,QAAAA,EAAY,iBAAiB,UAAU,KAAK,QAAA;EAC9C;EAEO,mBAAyB;AAxClC,QAAAA;AAAAA,KAyCIA,IAAA,KAAK,UAAL,QAAAA,EAAY,oBAAoB,UAAU,KAAK,QAAA;EACjD;EAEU,SAASC,GAAkC;AAC/C,SAAK,YAAYA,EAAM,YAG3B,KAAK,UAAUA,EAAM,SACrB,KAAK,KAAK,cAAc,KAAK,KAAK,CAAC,KAAK,OAAO;EACjD;AACF;",
6
+ "names": ["host", "query", "_a", "event"]
7
+ }
@@ -0,0 +1,8 @@
1
+ import "./chunk-HBUX7E54.js";
2
+ import "./chunk-6A6NIESE.js";
3
+ import "./chunk-364Y2XOJ.js";
4
+ import "./chunk-ER3HU7OE.js";
5
+ import "./chunk-JASEW37G.js";
6
+ import "./chunk-TS7SL372.js";
7
+ import "./chunk-AXQFWXYZ.js";
8
+ //# sourceMappingURL=chunk-5XWUZJTT.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ import "./chunk-AXQFWXYZ.js";
2
+
3
+ // node_modules/@shikijs/langs/dist/diff.mjs
4
+ var lang = Object.freeze(JSON.parse('{"displayName":"Diff","name":"diff","patterns":[{"captures":{"1":{"name":"punctuation.definition.separator.diff"}},"match":"^((\\\\*{15})|(={67})|(-{3}))$\\\\n?","name":"meta.separator.diff"},{"match":"^\\\\d+(,\\\\d+)*([acd])\\\\d+(,\\\\d+)*$\\\\n?","name":"meta.diff.range.normal"},{"captures":{"1":{"name":"punctuation.definition.range.diff"},"2":{"name":"meta.toc-list.line-number.diff"},"3":{"name":"punctuation.definition.range.diff"}},"match":"^(@@)\\\\s*(.+?)\\\\s*(@@)($\\\\n?)?","name":"meta.diff.range.unified"},{"captures":{"3":{"name":"punctuation.definition.range.diff"},"4":{"name":"punctuation.definition.range.diff"},"6":{"name":"punctuation.definition.range.diff"},"7":{"name":"punctuation.definition.range.diff"}},"match":"^(((-{3}) .+ (-{4}))|((\\\\*{3}) .+ (\\\\*{4})))$\\\\n?","name":"meta.diff.range.context"},{"match":"^diff --git a/.*$\\\\n?","name":"meta.diff.header.git"},{"match":"^diff (-|\\\\S+\\\\s+\\\\S+).*$\\\\n?","name":"meta.diff.header.command"},{"captures":{"4":{"name":"punctuation.definition.from-file.diff"},"6":{"name":"punctuation.definition.from-file.diff"},"7":{"name":"punctuation.definition.from-file.diff"}},"match":"^((((-{3}) .+)|((\\\\*{3}) .+))$\\\\n?|(={4}) .+(?= - ))","name":"meta.diff.header.from-file"},{"captures":{"2":{"name":"punctuation.definition.to-file.diff"},"3":{"name":"punctuation.definition.to-file.diff"},"4":{"name":"punctuation.definition.to-file.diff"}},"match":"(^(\\\\+{3}) .+$\\\\n?| (-) .* (={4})$\\\\n?)","name":"meta.diff.header.to-file"},{"captures":{"3":{"name":"punctuation.definition.inserted.diff"},"6":{"name":"punctuation.definition.inserted.diff"}},"match":"^(((>)( .*)?)|((\\\\+).*))$\\\\n?","name":"markup.inserted.diff"},{"captures":{"1":{"name":"punctuation.definition.changed.diff"}},"match":"^(!).*$\\\\n?","name":"markup.changed.diff"},{"captures":{"3":{"name":"punctuation.definition.deleted.diff"},"6":{"name":"punctuation.definition.deleted.diff"}},"match":"^(((<)( .*)?)|((-).*))$\\\\n?","name":"markup.deleted.diff"},{"begin":"^(#)","captures":{"1":{"name":"punctuation.definition.comment.diff"}},"end":"\\\\n","name":"comment.line.number-sign.diff"},{"match":"^index [0-9a-f]{7,40}\\\\.\\\\.[0-9a-f]{7,40}.*$\\\\n?","name":"meta.diff.index.git"},{"captures":{"1":{"name":"punctuation.separator.key-value.diff"},"2":{"name":"meta.toc-list.file-name.diff"}},"match":"^Index(:) (.+)$\\\\n?","name":"meta.diff.index"},{"match":"^Only in .*: .*$\\\\n?","name":"meta.diff.only-in"}],"scopeName":"source.diff"}'));
5
+ var diff_default = [
6
+ lang
7
+ ];
8
+ export {
9
+ diff_default as default
10
+ };
11
+ //# sourceMappingURL=chunk-64K5VONJ.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../node_modules/@shikijs/langs/dist/diff.mjs"],
4
+ "sourcesContent": ["const lang = Object.freeze(JSON.parse(\"{\\\"displayName\\\":\\\"Diff\\\",\\\"name\\\":\\\"diff\\\",\\\"patterns\\\":[{\\\"captures\\\":{\\\"1\\\":{\\\"name\\\":\\\"punctuation.definition.separator.diff\\\"}},\\\"match\\\":\\\"^((\\\\\\\\*{15})|(={67})|(-{3}))$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.separator.diff\\\"},{\\\"match\\\":\\\"^\\\\\\\\d+(,\\\\\\\\d+)*([acd])\\\\\\\\d+(,\\\\\\\\d+)*$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.diff.range.normal\\\"},{\\\"captures\\\":{\\\"1\\\":{\\\"name\\\":\\\"punctuation.definition.range.diff\\\"},\\\"2\\\":{\\\"name\\\":\\\"meta.toc-list.line-number.diff\\\"},\\\"3\\\":{\\\"name\\\":\\\"punctuation.definition.range.diff\\\"}},\\\"match\\\":\\\"^(@@)\\\\\\\\s*(.+?)\\\\\\\\s*(@@)($\\\\\\\\n?)?\\\",\\\"name\\\":\\\"meta.diff.range.unified\\\"},{\\\"captures\\\":{\\\"3\\\":{\\\"name\\\":\\\"punctuation.definition.range.diff\\\"},\\\"4\\\":{\\\"name\\\":\\\"punctuation.definition.range.diff\\\"},\\\"6\\\":{\\\"name\\\":\\\"punctuation.definition.range.diff\\\"},\\\"7\\\":{\\\"name\\\":\\\"punctuation.definition.range.diff\\\"}},\\\"match\\\":\\\"^(((-{3}) .+ (-{4}))|((\\\\\\\\*{3}) .+ (\\\\\\\\*{4})))$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.diff.range.context\\\"},{\\\"match\\\":\\\"^diff --git a/.*$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.diff.header.git\\\"},{\\\"match\\\":\\\"^diff (-|\\\\\\\\S+\\\\\\\\s+\\\\\\\\S+).*$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.diff.header.command\\\"},{\\\"captures\\\":{\\\"4\\\":{\\\"name\\\":\\\"punctuation.definition.from-file.diff\\\"},\\\"6\\\":{\\\"name\\\":\\\"punctuation.definition.from-file.diff\\\"},\\\"7\\\":{\\\"name\\\":\\\"punctuation.definition.from-file.diff\\\"}},\\\"match\\\":\\\"^((((-{3}) .+)|((\\\\\\\\*{3}) .+))$\\\\\\\\n?|(={4}) .+(?= - ))\\\",\\\"name\\\":\\\"meta.diff.header.from-file\\\"},{\\\"captures\\\":{\\\"2\\\":{\\\"name\\\":\\\"punctuation.definition.to-file.diff\\\"},\\\"3\\\":{\\\"name\\\":\\\"punctuation.definition.to-file.diff\\\"},\\\"4\\\":{\\\"name\\\":\\\"punctuation.definition.to-file.diff\\\"}},\\\"match\\\":\\\"(^(\\\\\\\\+{3}) .+$\\\\\\\\n?| (-) .* (={4})$\\\\\\\\n?)\\\",\\\"name\\\":\\\"meta.diff.header.to-file\\\"},{\\\"captures\\\":{\\\"3\\\":{\\\"name\\\":\\\"punctuation.definition.inserted.diff\\\"},\\\"6\\\":{\\\"name\\\":\\\"punctuation.definition.inserted.diff\\\"}},\\\"match\\\":\\\"^(((>)( .*)?)|((\\\\\\\\+).*))$\\\\\\\\n?\\\",\\\"name\\\":\\\"markup.inserted.diff\\\"},{\\\"captures\\\":{\\\"1\\\":{\\\"name\\\":\\\"punctuation.definition.changed.diff\\\"}},\\\"match\\\":\\\"^(!).*$\\\\\\\\n?\\\",\\\"name\\\":\\\"markup.changed.diff\\\"},{\\\"captures\\\":{\\\"3\\\":{\\\"name\\\":\\\"punctuation.definition.deleted.diff\\\"},\\\"6\\\":{\\\"name\\\":\\\"punctuation.definition.deleted.diff\\\"}},\\\"match\\\":\\\"^(((<)( .*)?)|((-).*))$\\\\\\\\n?\\\",\\\"name\\\":\\\"markup.deleted.diff\\\"},{\\\"begin\\\":\\\"^(#)\\\",\\\"captures\\\":{\\\"1\\\":{\\\"name\\\":\\\"punctuation.definition.comment.diff\\\"}},\\\"end\\\":\\\"\\\\\\\\n\\\",\\\"name\\\":\\\"comment.line.number-sign.diff\\\"},{\\\"match\\\":\\\"^index [0-9a-f]{7,40}\\\\\\\\.\\\\\\\\.[0-9a-f]{7,40}.*$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.diff.index.git\\\"},{\\\"captures\\\":{\\\"1\\\":{\\\"name\\\":\\\"punctuation.separator.key-value.diff\\\"},\\\"2\\\":{\\\"name\\\":\\\"meta.toc-list.file-name.diff\\\"}},\\\"match\\\":\\\"^Index(:) (.+)$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.diff.index\\\"},{\\\"match\\\":\\\"^Only in .*: .*$\\\\\\\\n?\\\",\\\"name\\\":\\\"meta.diff.only-in\\\"}],\\\"scopeName\\\":\\\"source.diff\\\"}\"))\n\nexport default [\nlang\n]\n"],
5
+ "mappings": ";;;AAAA,IAAM,OAAO,OAAO,OAAO,KAAK,MAAM,y8EAA2uF,CAAC;AAElxF,IAAO,eAAQ;AAAA,EACf;AACA;",
6
+ "names": []
7
+ }
@@ -0,0 +1,9 @@
1
+ // node_modules/@spectrum-web-components/base/src/define-element.js
2
+ function defineElement(e, n) {
3
+ window.__swc, customElements.define(e, n);
4
+ }
5
+
6
+ export {
7
+ defineElement
8
+ };
9
+ //# sourceMappingURL=chunk-6A6NIESE.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../node_modules/@spectrum-web-components/base/src/define-element.ts"],
4
+ "sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\ninterface CustomElementConstructor {\n new (...params: unknown[]): HTMLElement;\n}\n\nexport function defineElement(\n name: string,\n constructor: CustomElementConstructor\n): void {\n if (window.__swc && window.__swc.DEBUG) {\n if (customElements.get(name)) {\n window.__swc.warn(\n undefined,\n `Attempted to redefine <${name}>. This usually indicates that multiple versions of the same web component were loaded onto a single page.`,\n 'https://opensource.adobe.com/spectrum-web-components/registry-conflicts'\n );\n }\n }\n customElements.define(name, constructor);\n}\n"],
5
+ "mappings": ";AAgBO,SAAS,cACdA,GACAC,GACM;AACF,SAAO,OASX,eAAe,OAAOD,GAAMC,CAAW;AACzC;",
6
+ "names": ["name", "constructor"]
7
+ }
@@ -0,0 +1,180 @@
1
+ import {
2
+ MatchMediaController
3
+ } from "./chunk-5OVGH7HO.js";
4
+ import {
5
+ defineElement
6
+ } from "./chunk-6A6NIESE.js";
7
+ import {
8
+ firstFocusableIn
9
+ } from "./chunk-IBQ4O4NO.js";
10
+ import "./chunk-ZMBN6APP.js";
11
+ import {
12
+ r
13
+ } from "./chunk-ER3HU7OE.js";
14
+ import {
15
+ A,
16
+ SpectrumElement,
17
+ b,
18
+ e2 as e,
19
+ i,
20
+ n
21
+ } from "./chunk-TS7SL372.js";
22
+ import "./chunk-AXQFWXYZ.js";
23
+
24
+ // node_modules/@spectrum-web-components/modal/src/modal.css.js
25
+ var i2 = i`
26
+ :host{--spectrum-modal-confirm-entry-animation-duration:var(--mod-modal-confirm-entry-animation-duration,var(--spectrum-animation-duration-500));--spectrum-modal-confirm-entry-animation-delay:var(--mod-overlay-animation-duration-opened,var(--mod-modal-confirm-entry-animation-delay,var(--spectrum-animation-duration-200)));--spectrum-modal-confirm-exit-animation-duration:var(--mod-overlay-animation-duration,var(--mod-modal-confirm-exit-animation-duration,var(--spectrum-animation-duration-100)));--spectrum-modal-confirm-exit-animation-delay:var(--mod-modal-confirm-exit-animation-delay,var(--spectrum-animation-duration-0));--spectrum-modal-fullscreen-margin:var(--mod-modal-fullscreen-margin,32px)}.modal{visibility:hidden;z-index:1;max-inline-size:90%;max-inline-size:var(--mod-modal-max-width,90%);max-block-size:90vh;max-block-size:var(--mod-modal-max-height,90vh);background:var(--mod-modal-background-color,var(--spectrum-modal-background-color));border-radius:var(--mod-modal-confirm-border-radius,var(--spectrum-corner-radius-100));pointer-events:auto;opacity:0;transform:translateY(var(--mod-modal-confirm-entry-animation-distance,var(--spectrum-dialog-confirm-entry-animation-distance)));transition:opacity var(--spectrum-modal-confirm-exit-animation-duration)var(--spectrum-animation-ease-in)var(--spectrum-modal-confirm-exit-animation-delay),visibility var(--spectrum-animation-duration-0)var(--spectrum-animation-linear)calc(var(--spectrum-modal-confirm-exit-animation-delay) + var(--spectrum-modal-confirm-exit-animation-duration)),transform var(--spectrum-animation-duration-0)var(--spectrum-animation-linear)calc(var(--spectrum-modal-confirm-exit-animation-delay) + var(--spectrum-modal-confirm-exit-animation-duration));outline:none;overflow:hidden}:host([open]) .modal{visibility:visible;pointer-events:auto;opacity:1;transition:transform var(--spectrum-modal-confirm-entry-animation-duration)var(--spectrum-animation-ease-out)var(--spectrum-modal-confirm-entry-animation-delay),opacity var(--spectrum-modal-confirm-entry-animation-duration)var(--spectrum-animation-ease-out)var(--spectrum-modal-confirm-entry-animation-delay);transform:translateY(0)}@media only screen and (device-height<=350px),only screen and (device-width<=400px){:host([responsive]) .modal{border-radius:0;block-size:100%;max-block-size:100%;inline-size:100%;max-inline-size:100%}}.fullscreen{max-block-size:none;max-inline-size:none;position:fixed;inset-block-start:var(--spectrum-modal-fullscreen-margin);inset-block-end:var(--spectrum-modal-fullscreen-margin);inset-inline-start:var(--spectrum-modal-fullscreen-margin);inset-inline-end:var(--spectrum-modal-fullscreen-margin)}.fullscreenTakeover{box-sizing:border-box;border:none;border-radius:0;max-block-size:none;max-inline-size:none;position:fixed;inset:0}.fullscreenTakeover,:host([open]) .fullscreenTakeover{transform:none}:host{--spectrum-modal-background-color:var(--system-modal-background-color)}:host{--spectrum-dialog-confirm-exit-animation-duration:var(--swc-test-duration);--spectrum-dialog-confirm-entry-animation-duration:var(--swc-test-duration);--spectrum-modal-confirm-entry-animation-distance:var(--spectrum-dialog-confirm-entry-animation-distance);height:100dvh}.modal{overflow:visible}
27
+ `;
28
+ var modal_css_default = i2;
29
+
30
+ // node_modules/@spectrum-web-components/underlay/src/underlay.css.js
31
+ var n2 = i`
32
+ :host{--spectrum-underlay-background-exit-animation-duration:var(--mod-underlay-background-exit-animation-duration,var(--spectrum-animation-duration-300));--spectrum-underlay-background-exit-animation-ease:var(--mod-underlay-background-exit-animation-ease,var(--spectrum-animation-ease-in));--spectrum-underlay-background-exit-animation-delay:var(--mod-underlay-background-exit-animation-delay,var(--spectrum-animation-duration-200));--spectrum-underlay-background-entry-animation-duration:var(--mod-underlay-background-entry-animation-duration,var(--spectrum-animation-duration-600));--spectrum-underlay-background-entry-animation-ease:var(--mod-underlay-background-entry-animation-ease,var(--spectrum-animation-ease-out));--spectrum-underlay-background-entry-animation-delay:var(--mod-underlay-background-entry-animation-delay,var(--mod-overlay-animation-duration-opened,var(--spectrum-animation-duration-0)));--spectrum-underlay-background-color:var(--mod-underlay-background-color,rgba(var(--spectrum-black-rgb),var(--spectrum-overlay-opacity)));visibility:hidden;z-index:1;background-color:var(--spectrum-underlay-background-color);pointer-events:none;opacity:0;transition:opacity var(--spectrum-underlay-background-exit-animation-duration)var(--spectrum-underlay-background-exit-animation-ease)var(--spectrum-underlay-background-exit-animation-delay),visibility 0s linear calc(var(--spectrum-underlay-background-exit-animation-delay) + var(--spectrum-underlay-background-exit-animation-duration));position:fixed;inset-block:0;inset-inline:0;overflow:hidden}:host([open]){visibility:visible;pointer-events:auto;opacity:1;transition:opacity var(--spectrum-underlay-background-entry-animation-duration)var(--spectrum-underlay-background-entry-animation-ease)var(--spectrum-underlay-background-entry-animation-delay);transition-delay:var(--spectrum-underlay-background-entry-animation-delay)}
33
+ `;
34
+ var underlay_css_default = n2;
35
+
36
+ // node_modules/@spectrum-web-components/underlay/src/Underlay.js
37
+ var d = Object.defineProperty;
38
+ var p = Object.getOwnPropertyDescriptor;
39
+ var s = (i4, t, o, r3) => {
40
+ for (var e2 = r3 > 1 ? void 0 : r3 ? p(t, o) : t, n3 = i4.length - 1, l; n3 >= 0; n3--) (l = i4[n3]) && (e2 = (r3 ? l(t, o, e2) : l(e2)) || e2);
41
+ return r3 && e2 && d(t, o, e2), e2;
42
+ };
43
+ var Underlay = class extends SpectrumElement {
44
+ constructor() {
45
+ super(...arguments);
46
+ this.canClick = false;
47
+ this.open = false;
48
+ }
49
+ static get styles() {
50
+ return [underlay_css_default];
51
+ }
52
+ click() {
53
+ this.dispatchEvent(new Event("close"));
54
+ }
55
+ handlePointerdown() {
56
+ this.canClick = true;
57
+ }
58
+ handlePointerup() {
59
+ this.canClick && this.click(), this.canClick = false;
60
+ }
61
+ render() {
62
+ return b``;
63
+ }
64
+ firstUpdated() {
65
+ this.addEventListener("pointerdown", this.handlePointerdown), this.addEventListener("pointerup", this.handlePointerup);
66
+ }
67
+ };
68
+ s([n({ type: Boolean, reflect: true })], Underlay.prototype, "open", 2);
69
+
70
+ // node_modules/@spectrum-web-components/underlay/sp-underlay.js
71
+ defineElement("sp-underlay", Underlay);
72
+
73
+ // node_modules/@spectrum-web-components/tray/src/tray.css.js
74
+ var r2 = i`
75
+ :host{justify-content:center;inline-size:100%;display:flex;position:fixed;inset-block-end:0;inset-inline-start:0}.tray{--spectrum-tray-max-inline-size:var(--mod-tray-max-inline-size,375px);--spectrum-tray-spacing-edge-to-tray-safe-zone:var(--mod-tray-spacing-edge-to-tray-safe-zone,64px);--spectrum-tray-entry-animation-delay:var(--mod-tray-entry-animation-delay,.16s);--spectrum-tray-entry-animation-duration:var(--mod-tray-entry-animation-duration,var(--spectrum-animation-duration-500));--spectrum-tray-exit-animation-delay:var(--mod-tray-exit-animation-delay,0s);--spectrum-tray-exit-animation-duration:var(--mod-tray-exit-animation-duration,var(--spectrum-animation-duration-100));--spectrum-tray-corner-radius:var(--mod-tray-corner-radius,var(--spectrum-corner-radius-100));--spectrum-tray-background-color:var(--highcontrast-tray-background-color,var(--mod-tray-background-color,var(--spectrum-background-layer-2-color)));--mod-modal-max-width:100%;box-sizing:border-box;max-block-size:calc(100vh - 64px);inline-size:100%;max-inline-size:100%;max-block-size:calc(100vh - var(--spectrum-tray-spacing-edge-to-tray-safe-zone));background-color:var(--spectrum-tray-background-color);border-radius:0;border-radius:var(--mod-tray-corner-radius-portrait,0)var(--mod-tray-corner-radius-portrait,0)0 0;transition:opacity var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)0s,visibility var(--spectrum-tray-exit-animation-duration)linear calc(var(--spectrum-tray-exit-animation-duration)),transform var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)0s;transition:opacity var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)var(--spectrum-tray-exit-animation-delay),visibility var(--spectrum-tray-exit-animation-duration)linear calc(var(--spectrum-tray-exit-animation-delay) + var(--spectrum-tray-exit-animation-duration)),transform var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)var(--spectrum-tray-exit-animation-delay);outline:none;margin-block-start:var(--spectrum-tray-spacing-edge-to-tray-safe-zone);padding-block-start:var(--mod-tray-top-to-content-area,var(--spectrum-tray-top-to-content-area));padding-block-end:var(--mod-tray-bottom-to-content-area,var(--spectrum-tray-top-to-content-area));overflow:auto;transform:translateY(100%)}:host([open]) .tray{transition:transform var(--spectrum-tray-entry-animation-duration)cubic-bezier(0,0,.4,1)var(--spectrum-tray-entry-animation-delay),opacity var(--spectrum-tray-entry-animation-duration)cubic-bezier(0,0,.4,1)var(--spectrum-tray-entry-animation-delay);transform:translateY(0)}@media screen and (orientation:landscape){.tray{max-inline-size:var(--spectrum-tray-max-inline-size);border-start-start-radius:var(--spectrum-tray-corner-radius);border-start-end-radius:var(--spectrum-tray-corner-radius)}}@media (forced-colors:active){.tray{--highcontrast-tray-background-color:Canvas;border:solid}.tray ::slotted(*){border:none}}:host{align-items:flex-end;max-height:100dvh;position:fixed!important}sp-underlay{touch-action:none}.tray{overscroll-behavior:contain;display:inline-flex}.visually-hidden,::slotted(.visually-hidden){white-space:nowrap;clip-path:inset(50%);border:0;width:1px;height:1px;margin:0 -1px -1px 0;padding:0;position:absolute;overflow:hidden}
76
+ `;
77
+ var tray_css_default = r2;
78
+
79
+ // node_modules/@spectrum-web-components/tray/src/Tray.js
80
+ var h = Object.defineProperty;
81
+ var m = Object.getOwnPropertyDescriptor;
82
+ var i3 = (n3, r3, e2, s2) => {
83
+ for (var t = s2 > 1 ? void 0 : s2 ? m(r3, e2) : r3, o = n3.length - 1, a; o >= 0; o--) (a = n3[o]) && (t = (s2 ? a(r3, e2, t) : a(t)) || t);
84
+ return s2 && t && h(r3, e2, t), t;
85
+ };
86
+ var Tray = class extends SpectrumElement {
87
+ constructor() {
88
+ super(...arguments);
89
+ this.open = false;
90
+ this.prefersMotion = new MatchMediaController(this, "(prefers-reduced-motion: no-preference)");
91
+ this.transitionPromise = Promise.resolve();
92
+ this.resolveTransitionPromise = () => {
93
+ };
94
+ this.animating = false;
95
+ this.hasKeyboardDismissButton = false;
96
+ this.needsDismissHelper = true;
97
+ }
98
+ static get styles() {
99
+ return [modal_css_default, tray_css_default];
100
+ }
101
+ focus() {
102
+ const e2 = firstFocusableIn(this);
103
+ e2 ? e2.focus() : this.children.length === 1 ? this.tray.focus() : super.focus();
104
+ }
105
+ overlayWillCloseCallback() {
106
+ return this.open ? (this.close(), true) : this.animating;
107
+ }
108
+ close() {
109
+ this.open = false, this.prefersMotion.matches || this.dispatchClosed();
110
+ }
111
+ get dismissHelper() {
112
+ return b`
113
+ <div class="visually-hidden">
114
+ <button aria-label="Dismiss" @click=${this.close}></button>
115
+ </div>
116
+ `;
117
+ }
118
+ checkForDismissButtons() {
119
+ if (!this.contentSlot) {
120
+ this.needsDismissHelper = true;
121
+ return;
122
+ }
123
+ const e2 = this.contentSlot.assignedElements({ flatten: true });
124
+ if (e2.length === 0) {
125
+ this.needsDismissHelper = true;
126
+ return;
127
+ }
128
+ const s2 = e2.some((t) => !!(t.tagName === "SP-BUTTON" || t.tagName === "SP-CLOSE-BUTTON" || t.tagName === "BUTTON" || t.tagName === "SP-DIALOG" && t.hasAttribute("dismissable") || t.tagName === "SP-DIALOG-WRAPPER" && t.hasAttribute("dismissable") || t.querySelectorAll("sp-button, sp-close-button, button").length > 0));
129
+ this.needsDismissHelper = !s2;
130
+ }
131
+ handleSlotChange() {
132
+ this.checkForDismissButtons();
133
+ }
134
+ dispatchClosed() {
135
+ this.dispatchEvent(new Event("close", { bubbles: true }));
136
+ }
137
+ handleUnderlayTransitionend() {
138
+ this.open || (this.resolveTransitionPromise(), this.dispatchClosed());
139
+ }
140
+ handleTrayTransitionend() {
141
+ this.open && this.resolveTransitionPromise();
142
+ }
143
+ firstUpdated(e2) {
144
+ super.firstUpdated(e2), this.checkForDismissButtons();
145
+ }
146
+ update(e2) {
147
+ e2.has("open") && e2.get("open") !== void 0 && this.prefersMotion.matches && (this.animating = true, this.transitionPromise = new Promise((s2) => {
148
+ this.resolveTransitionPromise = () => {
149
+ this.animating = false, s2();
150
+ };
151
+ })), super.update(e2);
152
+ }
153
+ render() {
154
+ return b`
155
+ <sp-underlay
156
+ ?open=${this.open}
157
+ @close=${this.close}
158
+ @transitionend=${this.handleUnderlayTransitionend}
159
+ ></sp-underlay>
160
+ <div
161
+ class="tray modal"
162
+ tabindex="-1"
163
+ @transitionend=${this.handleTrayTransitionend}
164
+ >
165
+ ${!this.hasKeyboardDismissButton && this.needsDismissHelper ? this.dismissHelper : A}
166
+ <slot @slotchange=${this.handleSlotChange}></slot>
167
+ ${!this.hasKeyboardDismissButton && this.needsDismissHelper ? this.dismissHelper : A}
168
+ </div>
169
+ `;
170
+ }
171
+ async getUpdateComplete() {
172
+ const e2 = await super.getUpdateComplete();
173
+ return await this.transitionPromise, e2;
174
+ }
175
+ };
176
+ i3([n({ type: Boolean, reflect: true })], Tray.prototype, "open", 2), i3([e(".tray")], Tray.prototype, "tray", 2), i3([e("slot")], Tray.prototype, "contentSlot", 2), i3([n({ type: Boolean, attribute: "has-keyboard-dismiss" })], Tray.prototype, "hasKeyboardDismissButton", 2), i3([r()], Tray.prototype, "needsDismissHelper", 2);
177
+
178
+ // node_modules/@spectrum-web-components/tray/sp-tray.js
179
+ defineElement("sp-tray", Tray);
180
+ //# sourceMappingURL=chunk-6JNYNXUQ.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../node_modules/@spectrum-web-components/modal/src/modal.css.ts", "../node_modules/@spectrum-web-components/underlay/src/underlay.css.ts", "../node_modules/@spectrum-web-components/underlay/src/Underlay.ts", "../node_modules/@spectrum-web-components/underlay/sp-underlay.ts", "../node_modules/@spectrum-web-components/tray/src/tray.css.ts", "../node_modules/@spectrum-web-components/tray/src/Tray.ts", "../node_modules/@spectrum-web-components/tray/sp-tray.ts"],
4
+ "sourcesContent": ["import { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{--spectrum-modal-confirm-entry-animation-duration:var(--mod-modal-confirm-entry-animation-duration,var(--spectrum-animation-duration-500));--spectrum-modal-confirm-entry-animation-delay:var(--mod-overlay-animation-duration-opened,var(--mod-modal-confirm-entry-animation-delay,var(--spectrum-animation-duration-200)));--spectrum-modal-confirm-exit-animation-duration:var(--mod-overlay-animation-duration,var(--mod-modal-confirm-exit-animation-duration,var(--spectrum-animation-duration-100)));--spectrum-modal-confirm-exit-animation-delay:var(--mod-modal-confirm-exit-animation-delay,var(--spectrum-animation-duration-0));--spectrum-modal-fullscreen-margin:var(--mod-modal-fullscreen-margin,32px)}.modal{visibility:hidden;z-index:1;max-inline-size:90%;max-inline-size:var(--mod-modal-max-width,90%);max-block-size:90vh;max-block-size:var(--mod-modal-max-height,90vh);background:var(--mod-modal-background-color,var(--spectrum-modal-background-color));border-radius:var(--mod-modal-confirm-border-radius,var(--spectrum-corner-radius-100));pointer-events:auto;opacity:0;transform:translateY(var(--mod-modal-confirm-entry-animation-distance,var(--spectrum-dialog-confirm-entry-animation-distance)));transition:opacity var(--spectrum-modal-confirm-exit-animation-duration)var(--spectrum-animation-ease-in)var(--spectrum-modal-confirm-exit-animation-delay),visibility var(--spectrum-animation-duration-0)var(--spectrum-animation-linear)calc(var(--spectrum-modal-confirm-exit-animation-delay) + var(--spectrum-modal-confirm-exit-animation-duration)),transform var(--spectrum-animation-duration-0)var(--spectrum-animation-linear)calc(var(--spectrum-modal-confirm-exit-animation-delay) + var(--spectrum-modal-confirm-exit-animation-duration));outline:none;overflow:hidden}:host([open]) .modal{visibility:visible;pointer-events:auto;opacity:1;transition:transform var(--spectrum-modal-confirm-entry-animation-duration)var(--spectrum-animation-ease-out)var(--spectrum-modal-confirm-entry-animation-delay),opacity var(--spectrum-modal-confirm-entry-animation-duration)var(--spectrum-animation-ease-out)var(--spectrum-modal-confirm-entry-animation-delay);transform:translateY(0)}@media only screen and (device-height<=350px),only screen and (device-width<=400px){:host([responsive]) .modal{border-radius:0;block-size:100%;max-block-size:100%;inline-size:100%;max-inline-size:100%}}.fullscreen{max-block-size:none;max-inline-size:none;position:fixed;inset-block-start:var(--spectrum-modal-fullscreen-margin);inset-block-end:var(--spectrum-modal-fullscreen-margin);inset-inline-start:var(--spectrum-modal-fullscreen-margin);inset-inline-end:var(--spectrum-modal-fullscreen-margin)}.fullscreenTakeover{box-sizing:border-box;border:none;border-radius:0;max-block-size:none;max-inline-size:none;position:fixed;inset:0}.fullscreenTakeover,:host([open]) .fullscreenTakeover{transform:none}:host{--spectrum-modal-background-color:var(--system-modal-background-color)}:host{--spectrum-dialog-confirm-exit-animation-duration:var(--swc-test-duration);--spectrum-dialog-confirm-entry-animation-duration:var(--swc-test-duration);--spectrum-modal-confirm-entry-animation-distance:var(--spectrum-dialog-confirm-entry-animation-distance);height:100dvh}.modal{overflow:visible}\n`;\nexport default styles;", "import { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{--spectrum-underlay-background-exit-animation-duration:var(--mod-underlay-background-exit-animation-duration,var(--spectrum-animation-duration-300));--spectrum-underlay-background-exit-animation-ease:var(--mod-underlay-background-exit-animation-ease,var(--spectrum-animation-ease-in));--spectrum-underlay-background-exit-animation-delay:var(--mod-underlay-background-exit-animation-delay,var(--spectrum-animation-duration-200));--spectrum-underlay-background-entry-animation-duration:var(--mod-underlay-background-entry-animation-duration,var(--spectrum-animation-duration-600));--spectrum-underlay-background-entry-animation-ease:var(--mod-underlay-background-entry-animation-ease,var(--spectrum-animation-ease-out));--spectrum-underlay-background-entry-animation-delay:var(--mod-underlay-background-entry-animation-delay,var(--mod-overlay-animation-duration-opened,var(--spectrum-animation-duration-0)));--spectrum-underlay-background-color:var(--mod-underlay-background-color,rgba(var(--spectrum-black-rgb),var(--spectrum-overlay-opacity)));visibility:hidden;z-index:1;background-color:var(--spectrum-underlay-background-color);pointer-events:none;opacity:0;transition:opacity var(--spectrum-underlay-background-exit-animation-duration)var(--spectrum-underlay-background-exit-animation-ease)var(--spectrum-underlay-background-exit-animation-delay),visibility 0s linear calc(var(--spectrum-underlay-background-exit-animation-delay) + var(--spectrum-underlay-background-exit-animation-duration));position:fixed;inset-block:0;inset-inline:0;overflow:hidden}:host([open]){visibility:visible;pointer-events:auto;opacity:1;transition:opacity var(--spectrum-underlay-background-entry-animation-duration)var(--spectrum-underlay-background-entry-animation-ease)var(--spectrum-underlay-background-entry-animation-delay);transition-delay:var(--spectrum-underlay-background-entry-animation-delay)}\n`;\nexport default styles;", "/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport { property } from '@spectrum-web-components/base/src/decorators.js';\n\nimport styles from './underlay.css.js';\n\n/**\n * @element sp-underlay\n *\n * @fires close - When the underlay is \"clicked\" and the consuming pattern should chose whether to close based on that interaction\n */\nexport class Underlay extends SpectrumElement {\n public static override get styles(): CSSResultArray {\n return [styles];\n }\n\n private canClick = false;\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n public override click(): void {\n this.dispatchEvent(new Event('close'));\n }\n\n protected handlePointerdown(): void {\n this.canClick = true;\n }\n\n protected handlePointerup(): void {\n if (this.canClick) {\n this.click();\n }\n this.canClick = false;\n }\n\n protected override render(): TemplateResult {\n return html``;\n }\n\n protected override firstUpdated(): void {\n this.addEventListener('pointerdown', this.handlePointerdown);\n this.addEventListener('pointerup', this.handlePointerup);\n }\n}\n", "/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { Underlay } from './src/Underlay.js';\n\ndefineElement('sp-underlay', Underlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-underlay': Underlay;\n }\n}\n", "import { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{justify-content:center;inline-size:100%;display:flex;position:fixed;inset-block-end:0;inset-inline-start:0}.tray{--spectrum-tray-max-inline-size:var(--mod-tray-max-inline-size,375px);--spectrum-tray-spacing-edge-to-tray-safe-zone:var(--mod-tray-spacing-edge-to-tray-safe-zone,64px);--spectrum-tray-entry-animation-delay:var(--mod-tray-entry-animation-delay,.16s);--spectrum-tray-entry-animation-duration:var(--mod-tray-entry-animation-duration,var(--spectrum-animation-duration-500));--spectrum-tray-exit-animation-delay:var(--mod-tray-exit-animation-delay,0s);--spectrum-tray-exit-animation-duration:var(--mod-tray-exit-animation-duration,var(--spectrum-animation-duration-100));--spectrum-tray-corner-radius:var(--mod-tray-corner-radius,var(--spectrum-corner-radius-100));--spectrum-tray-background-color:var(--highcontrast-tray-background-color,var(--mod-tray-background-color,var(--spectrum-background-layer-2-color)));--mod-modal-max-width:100%;box-sizing:border-box;max-block-size:calc(100vh - 64px);inline-size:100%;max-inline-size:100%;max-block-size:calc(100vh - var(--spectrum-tray-spacing-edge-to-tray-safe-zone));background-color:var(--spectrum-tray-background-color);border-radius:0;border-radius:var(--mod-tray-corner-radius-portrait,0)var(--mod-tray-corner-radius-portrait,0)0 0;transition:opacity var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)0s,visibility var(--spectrum-tray-exit-animation-duration)linear calc(var(--spectrum-tray-exit-animation-duration)),transform var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)0s;transition:opacity var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)var(--spectrum-tray-exit-animation-delay),visibility var(--spectrum-tray-exit-animation-duration)linear calc(var(--spectrum-tray-exit-animation-delay) + var(--spectrum-tray-exit-animation-duration)),transform var(--spectrum-tray-exit-animation-duration)cubic-bezier(.5,0,1,1)var(--spectrum-tray-exit-animation-delay);outline:none;margin-block-start:var(--spectrum-tray-spacing-edge-to-tray-safe-zone);padding-block-start:var(--mod-tray-top-to-content-area,var(--spectrum-tray-top-to-content-area));padding-block-end:var(--mod-tray-bottom-to-content-area,var(--spectrum-tray-top-to-content-area));overflow:auto;transform:translateY(100%)}:host([open]) .tray{transition:transform var(--spectrum-tray-entry-animation-duration)cubic-bezier(0,0,.4,1)var(--spectrum-tray-entry-animation-delay),opacity var(--spectrum-tray-entry-animation-duration)cubic-bezier(0,0,.4,1)var(--spectrum-tray-entry-animation-delay);transform:translateY(0)}@media screen and (orientation:landscape){.tray{max-inline-size:var(--spectrum-tray-max-inline-size);border-start-start-radius:var(--spectrum-tray-corner-radius);border-start-end-radius:var(--spectrum-tray-corner-radius)}}@media (forced-colors:active){.tray{--highcontrast-tray-background-color:Canvas;border:solid}.tray ::slotted(*){border:none}}:host{align-items:flex-end;max-height:100dvh;position:fixed!important}sp-underlay{touch-action:none}.tray{overscroll-behavior:contain;display:inline-flex}.visually-hidden,::slotted(.visually-hidden){white-space:nowrap;clip-path:inset(50%);border:0;width:1px;height:1px;margin:0 -1px -1px 0;padding:0;position:absolute;overflow:hidden}\n`;\nexport default styles;", "/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n nothing,\n PropertyValues,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport modalStyles from '@spectrum-web-components/modal/src/modal.css.js';\nimport { MatchMediaController } from '@spectrum-web-components/reactive-controllers/src/MatchMedia.js';\nimport { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js';\n\nimport '@spectrum-web-components/underlay/sp-underlay.js';\n\nimport styles from './tray.css.js';\n\n/**\n * @element sp-tray\n *\n * @slot - content to display within the Tray\n *\n * @fires close - Announces that the Tray has been closed.\n */\nexport class Tray extends SpectrumElement {\n public static override get styles(): CSSResultArray {\n return [modalStyles, styles];\n }\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n protected prefersMotion = new MatchMediaController(\n this,\n '(prefers-reduced-motion: no-preference)'\n );\n\n private transitionPromise = Promise.resolve();\n\n private resolveTransitionPromise = () => {};\n\n @query('.tray')\n private tray!: HTMLDivElement;\n\n @query('slot')\n private contentSlot!: HTMLSlotElement;\n\n public override focus(): void {\n const firstFocusable = firstFocusableIn(this);\n if (firstFocusable) {\n firstFocusable.focus();\n } else if (this.children.length === 1) {\n this.tray.focus();\n } else {\n super.focus();\n }\n }\n\n private animating = false;\n\n public overlayWillCloseCallback(): boolean {\n if (!this.open) {\n return this.animating;\n }\n this.close();\n return true;\n }\n\n public close(): void {\n this.open = false;\n if (!this.prefersMotion.matches) {\n this.dispatchClosed();\n }\n }\n\n /**\n * When set, prevents the tray from rendering visually-hidden dismiss helpers.\n * Use this if your slotted content has custom keyboard-accessible dismiss functionality\n * that the auto-detection doesn't recognize.\n *\n * By default, the tray automatically detects buttons in slotted content.\n */\n @property({ type: Boolean, attribute: 'has-keyboard-dismiss' })\n public hasKeyboardDismissButton = false;\n\n /**\n * Returns a visually hidden dismiss button for mobile screen reader accessibility.\n * This button is placed before and after tray content to allow mobile screen reader\n * users (particularly VoiceOver on iOS) to easily dismiss the overlay.\n */\n protected get dismissHelper(): TemplateResult {\n return html`\n <div class=\"visually-hidden\">\n <button aria-label=\"Dismiss\" @click=${this.close}></button>\n </div>\n `;\n }\n\n /**\n * Internal state tracking whether dismiss helpers are needed.\n * Automatically updated when slotted content changes.\n */\n @state()\n private needsDismissHelper = true;\n\n /**\n * Check if slotted content has keyboard-accessible dismiss buttons.\n * Looks for buttons in light DOM and checks for known components with built-in dismiss.\n */\n private checkForDismissButtons(): void {\n if (!this.contentSlot) {\n this.needsDismissHelper = true;\n return;\n }\n\n const slottedElements = this.contentSlot.assignedElements({\n flatten: true,\n });\n\n if (slottedElements.length === 0) {\n this.needsDismissHelper = true;\n return;\n }\n\n const hasDismissButton = slottedElements.some((element) => {\n // Check if element is a button itself\n if (\n element.tagName === 'SP-BUTTON' ||\n element.tagName === 'SP-CLOSE-BUTTON' ||\n element.tagName === 'BUTTON'\n ) {\n return true;\n }\n\n // Check for dismissable dialog (has built-in dismiss button in shadow DOM)\n if (\n element.tagName === 'SP-DIALOG' &&\n element.hasAttribute('dismissable')\n ) {\n return true;\n }\n\n // Check for dismissable dialog-wrapper\n if (\n element.tagName === 'SP-DIALOG-WRAPPER' &&\n element.hasAttribute('dismissable')\n ) {\n return true;\n }\n\n // Check for buttons in light DOM (won't see shadow DOM)\n const buttons = element.querySelectorAll(\n 'sp-button, sp-close-button, button'\n );\n if (buttons.length > 0) {\n return true;\n }\n\n return false;\n });\n\n this.needsDismissHelper = !hasDismissButton;\n }\n\n private handleSlotChange(): void {\n this.checkForDismissButtons();\n }\n\n private dispatchClosed(): void {\n this.dispatchEvent(\n new Event('close', {\n bubbles: true,\n })\n );\n }\n\n protected handleUnderlayTransitionend(): void {\n if (!this.open) {\n this.resolveTransitionPromise();\n this.dispatchClosed();\n }\n }\n\n protected handleTrayTransitionend(): void {\n if (this.open) {\n this.resolveTransitionPromise();\n }\n }\n\n protected override firstUpdated(changes: PropertyValues<this>): void {\n super.firstUpdated(changes);\n // Run initial button detection\n this.checkForDismissButtons();\n }\n\n protected override update(changes: PropertyValues<this>): void {\n if (\n changes.has('open') &&\n changes.get('open') !== undefined &&\n this.prefersMotion.matches\n ) {\n this.animating = true;\n this.transitionPromise = new Promise((res) => {\n this.resolveTransitionPromise = () => {\n this.animating = false;\n res();\n };\n });\n }\n super.update(changes);\n }\n\n protected override render(): TemplateResult {\n return html`\n <sp-underlay\n ?open=${this.open}\n @close=${this.close}\n @transitionend=${this.handleUnderlayTransitionend}\n ></sp-underlay>\n <div\n class=\"tray modal\"\n tabindex=\"-1\"\n @transitionend=${this.handleTrayTransitionend}\n >\n ${!this.hasKeyboardDismissButton && this.needsDismissHelper\n ? this.dismissHelper\n : nothing}\n <slot @slotchange=${this.handleSlotChange}></slot>\n ${!this.hasKeyboardDismissButton && this.needsDismissHelper\n ? this.dismissHelper\n : nothing}\n </div>\n `;\n }\n\n /**\n * Bind the open/close transition into the update complete lifecycle so\n * that the overlay system can wait for it to be \"visibly ready\" before\n * attempting to throw focus into the content contained herein. Not\n * waiting for this can cause small amounts of page scroll to happen\n * while opening the Tray when focusable content is included: e.g. Menu\n * elements whose selected Menu Item is not the first Menu Item.\n */\n protected override async getUpdateComplete(): Promise<boolean> {\n const complete = (await super.getUpdateComplete()) as boolean;\n await this.transitionPromise;\n return complete;\n }\n}\n", "/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { Tray } from './src/Tray.js';\n\ndefineElement('sp-tray', Tray);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tray': Tray;\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AACA,IAAMA,KAASC;;;AAGf,IAAA,oBAAeD;;;ACHf,IAAME,KAASC;;;AAGf,IAAA,uBAAeD;;;;;;;;;ACuBR,IAAM,WAAN,cAAuBE,gBAAgB;EAAvC,cAAA;AAAA,UAAA,GAAA,SAAA;AAKL,SAAQ,WAAW;AAGnB,SAAO,OAAO;EAAA;EAPd,WAA2B,SAAyB;AAClD,WAAO,CAACC,oBAAM;EAChB;EAOgB,QAAc;AAC5B,SAAK,cAAc,IAAI,MAAM,OAAO,CAAC;EACvC;EAEU,oBAA0B;AAClC,SAAK,WAAW;EAClB;EAEU,kBAAwB;AAC5B,SAAK,YACP,KAAK,MAAM,GAEb,KAAK,WAAW;EAClB;EAEmB,SAAyB;AAC1C,WAAOC;EACT;EAEmB,eAAqB;AACtC,SAAK,iBAAiB,eAAe,KAAK,iBAAiB,GAC3D,KAAK,iBAAiB,aAAa,KAAK,eAAe;EACzD;AACF;AAzBSC,EAAA,CADNC,EAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC,CAAA,GAP/B,SAQJ,WAAA,QAAA,CAAA;;;ACpBTC,cAAc,eAAeC,QAAQ;;;ACdrC,IAAMC,KAASC;;;AAGf,IAAA,mBAAeD;;;;;;;;;ACoCR,IAAM,OAAN,cAAmBE,gBAAgB;EAAnC,cAAA;AAAA,UAAA,GAAA,SAAA;AAML,SAAO,OAAO;AAEd,SAAU,gBAAgB,IAAIC,qBAC5B,MACA,yCACF;AAEA,SAAQ,oBAAoB,QAAQ,QAAQ;AAE5C,SAAQ,2BAA2B,MAAM;IAAC;AAmB1C,SAAQ,YAAY;AAyBpB,SAAO,2BAA2B;AAoBlC,SAAQ,qBAAqB;EAAA;EA9E7B,WAA2B,SAAyB;AAClD,WAAO,CAACC,mBAAaC,gBAAM;EAC7B;EAoBgB,QAAc;AAC5B,UAAMC,KAAiBC,iBAAiB,IAAI;AACxCD,IAAAA,KACFA,GAAe,MAAM,IACZ,KAAK,SAAS,WAAW,IAClC,KAAK,KAAK,MAAM,IAEhB,MAAM,MAAM;EAEhB;EAIO,2BAAoC;AACzC,WAAK,KAAK,QAGV,KAAK,MAAM,GACJ,QAHE,KAAK;EAIhB;EAEO,QAAc;AACnB,SAAK,OAAO,OACP,KAAK,cAAc,WACtB,KAAK,eAAe;EAExB;EAiBA,IAAc,gBAAgC;AAC5C,WAAOE;;8CAEmC,KAAK,KAAK;;;EAGtD;EAaQ,yBAA+B;AACrC,QAAI,CAAC,KAAK,aAAa;AACrB,WAAK,qBAAqB;AAC1B;IACF;AAEA,UAAMC,KAAkB,KAAK,YAAY,iBAAiB,EACxD,SAAS,KACX,CAAC;AAED,QAAIA,GAAgB,WAAW,GAAG;AAChC,WAAK,qBAAqB;AAC1B;IACF;AAEA,UAAMC,KAAmBD,GAAgB,KAAME,OAG3C,CAAA,EAAAA,EAAQ,YAAY,eACpBA,EAAQ,YAAY,qBACpBA,EAAQ,YAAY,YAOpBA,EAAQ,YAAY,eACpBA,EAAQ,aAAa,aAAa,KAOlCA,EAAQ,YAAY,uBACpBA,EAAQ,aAAa,aAAa,KAMpBA,EAAQ,iBACtB,oCACF,EACY,SAAS,EAKtB;AAED,SAAK,qBAAqB,CAACD;EAC7B;EAEQ,mBAAyB;AAC/B,SAAK,uBAAuB;EAC9B;EAEQ,iBAAuB;AAC7B,SAAK,cACH,IAAI,MAAM,SAAS,EACjB,SAAS,KACX,CAAC,CACH;EACF;EAEU,8BAAoC;AACvC,SAAK,SACR,KAAK,yBAAyB,GAC9B,KAAK,eAAe;EAExB;EAEU,0BAAgC;AACpC,SAAK,QACP,KAAK,yBAAyB;EAElC;EAEmB,aAAaE,IAAqC;AACnE,UAAM,aAAaA,EAAO,GAE1B,KAAK,uBAAuB;EAC9B;EAEmB,OAAOA,IAAqC;AAE3DA,IAAAA,GAAQ,IAAI,MAAM,KAClBA,GAAQ,IAAI,MAAM,MAAM,UACxB,KAAK,cAAc,YAEnB,KAAK,YAAY,MACjB,KAAK,oBAAoB,IAAI,QAASC,CAAAA,OAAQ;AAC5C,WAAK,2BAA2B,MAAM;AACpC,aAAK,YAAY,OACjBA,GAAI;MACN;IACF,CAAC,IAEH,MAAM,OAAOD,EAAO;EACtB;EAEmB,SAAyB;AAC1C,WAAOJ;;gBAEK,KAAK,IAAI;iBACR,KAAK,KAAK;yBACF,KAAK,2BAA2B;;;;;yBAKhC,KAAK,uBAAuB;;UAE3C,CAAC,KAAK,4BAA4B,KAAK,qBACrC,KAAK,gBACLM,CAAO;4BACS,KAAK,gBAAgB;UACvC,CAAC,KAAK,4BAA4B,KAAK,qBACrC,KAAK,gBACLA,CAAO;;;EAGjB;EAUA,MAAyB,oBAAsC;AAC7D,UAAMC,KAAY,MAAM,MAAM,kBAAkB;AAChD,WAAA,MAAM,KAAK,mBACJA;EACT;AACF;AA1NSC,GAAA,CADNC,EAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC,CAAA,GAL/B,KAMJ,WAAA,QAAA,CAAA,GAYCD,GAAA,CADPE,EAAM,OAAO,CAAA,GAjBH,KAkBH,WAAA,QAAA,CAAA,GAGAF,GAAA,CADPE,EAAM,MAAM,CAAA,GApBF,KAqBH,WAAA,eAAA,CAAA,GAsCDF,GAAA,CADNC,EAAS,EAAE,MAAM,SAAS,WAAW,uBAAuB,CAAC,CAAA,GA1DnD,KA2DJ,WAAA,4BAAA,CAAA,GAoBCD,GAAA,CADPG,EAAM,CAAA,GA9EI,KA+EH,WAAA,sBAAA,CAAA;;;ACvGVC,cAAc,WAAWC,IAAI;",
6
+ "names": ["styles", "css", "styles", "css", "SpectrumElement", "styles", "html", "__decorateClass", "property", "defineElement", "Underlay", "styles", "css", "SpectrumElement", "MatchMediaController", "modalStyles", "styles", "firstFocusable", "firstFocusableIn", "html", "slottedElements", "hasDismissButton", "element", "changes", "res", "nothing", "complete", "__decorateClass", "property", "query", "state", "defineElement", "Tray"]
7
+ }