@kitn.ai/ui 0.29.0 → 0.30.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 (243) hide show
  1. package/README.md +11 -7
  2. package/dist/{Icon-DObhsRtm.js → Icon-BzBET3E-.js} +1 -1
  3. package/dist/{action-icons-CcgNN2oT.js → action-icons-DaW2pU6m.js} +1 -1
  4. package/dist/arrow-down-D783iMJj.js +1 -0
  5. package/dist/arrow-left-0VLM5kyg.js +1 -0
  6. package/dist/artifact-DGjzHYUT.js +1 -0
  7. package/dist/{attachments-Qr4kg-2b.js → attachments-YvXHlg88.js} +1 -1
  8. package/dist/{audio-visualizer-DToYdfSc.js → audio-visualizer-9lz5IHsL.js} +1 -1
  9. package/dist/{badge-CdEu_jn2.js → badge-Dh_vp8A5.js} +1 -1
  10. package/dist/{bell-DQAAOpDz.js → bell-CT7_WUwS.js} +1 -1
  11. package/dist/{button-DkuOnGLy.js → button-C_3te6fm.js} +1 -1
  12. package/dist/{card-renderer-Jx70m6_l.js → card-renderer-DZVaGH2e.js} +1 -1
  13. package/dist/check-CiEOVnEN.js +1 -0
  14. package/dist/{checkbox-D7iRB3nL.js → checkbox-Bu2T2e0U.js} +1 -1
  15. package/dist/{checkbox-group-B2_rpoPM.js → checkbox-group-BiryEXPQ.js} +1 -1
  16. package/dist/chevron-down-CSobuZRG.js +1 -0
  17. package/dist/chevron-right-DR9ZAP-2.js +1 -0
  18. package/dist/{choice-card-m0BYqqOK.js → choice-card-CM6IjkmL.js} +1 -1
  19. package/dist/circle-BC66EYF7.js +1 -0
  20. package/dist/circle-check-BqmahW0O.js +1 -0
  21. package/dist/{circle-x-BPG0iPst.js → circle-x-Bk-dA5Wf.js} +1 -1
  22. package/dist/{code-block-ClMLKb7C.js → code-block-B26t-Q7q.js} +1 -1
  23. package/dist/{collapsible-B4DlWicL.js → collapsible-Bhc636Cf.js} +1 -1
  24. package/dist/components/builder-composer-triggers.d.ts +62 -0
  25. package/dist/components/builder-layout.d.ts +54 -0
  26. package/dist/components/builder-message-actions.d.ts +72 -0
  27. package/dist/components/builder-panel.d.ts +189 -0
  28. package/dist/components/builder-preview.d.ts +11 -0
  29. package/dist/components/builder-shell-controls.d.ts +69 -0
  30. package/dist/components/builder-skeleton.d.ts +58 -0
  31. package/dist/components/builder-start.d.ts +75 -0
  32. package/dist/components/builder-workspace-variants.d.ts +23 -0
  33. package/dist/components/captions.d.ts +66 -0
  34. package/dist/{composer-sQ0HcvyG.js → composer-DMI85B6j.js} +1 -1
  35. package/dist/{confirm-card-rQWDQsnC.js → confirm-card-B0YIAwXp.js} +1 -1
  36. package/dist/{context-0kg4ZX1J.js → context-DWgfhqWp.js} +1 -1
  37. package/dist/controllable-BagRpyHv.js +1 -0
  38. package/dist/{conversation-item-BxwQLaFJ.js → conversation-item-BsOsVGmT.js} +1 -1
  39. package/dist/{conversation-list-BCfGN1JU.js → conversation-list-aX3Vtc7L.js} +1 -1
  40. package/dist/{copy-n9u9rqpi.js → copy-BmEwsNhJ.js} +1 -1
  41. package/dist/{create-tween-uPkArjIG.js → create-tween-CNOAU3Fx.js} +1 -1
  42. package/dist/{create-tween-C-q-JCM-.js → create-tween-WfqiENls.js} +1 -1
  43. package/dist/{create-tween-CRrJXxBd.js → create-tween-wlFtW9Kh.js} +1 -1
  44. package/dist/{create-tween-DZ3RRDHD.js → create-tween-zt79ba32.js} +1 -1
  45. package/dist/{default-input-CaMrJkgH.js → default-input-DMV5Eaze.js} +1 -1
  46. package/dist/define-CI0y3eE4.js +1 -0
  47. package/dist/define.js +40 -40
  48. package/dist/define.server.js +45 -45
  49. package/dist/{disclosure-WUImBbDv.js → disclosure-NnACBxsC.js} +1 -1
  50. package/dist/{dropdown-wZVeJOMd.js → dropdown-DT7G0RGR.js} +1 -1
  51. package/dist/elements/agent-card.js +1 -1
  52. package/dist/elements/artifact.js +1 -1
  53. package/dist/elements/attachments.js +1 -1
  54. package/dist/elements/audio-visualizer.js +1 -1
  55. package/dist/elements/avatar.js +1 -1
  56. package/dist/elements/badge.js +1 -1
  57. package/dist/elements/button.js +1 -1
  58. package/dist/elements/card.js +1 -1
  59. package/dist/elements/cards.js +1 -1
  60. package/dist/elements/chain-of-thought.js +1 -1
  61. package/dist/elements/chat-scope-picker.js +1 -1
  62. package/dist/elements/chat-workspace.js +1 -1
  63. package/dist/elements/chat.js +1 -1
  64. package/dist/elements/checkbox-group.js +1 -1
  65. package/dist/elements/checkbox.js +1 -1
  66. package/dist/elements/checkpoint.js +1 -1
  67. package/dist/elements/choice.js +1 -1
  68. package/dist/elements/coachmark.js +1 -1
  69. package/dist/elements/code-block.js +1 -1
  70. package/dist/elements/command.js +1 -1
  71. package/dist/elements/compare.js +1 -1
  72. package/dist/elements/composer.js +1 -1
  73. package/dist/elements/confirm-card.js +1 -1
  74. package/dist/elements/context-meter.js +1 -1
  75. package/dist/elements/conversation-item.js +1 -1
  76. package/dist/elements/conversation-list.js +1 -1
  77. package/dist/elements/dialog.js +1 -1
  78. package/dist/elements/dock.js +1 -1
  79. package/dist/elements/dropdown.js +1 -1
  80. package/dist/elements/editable-label.js +1 -1
  81. package/dist/elements/embed.js +1 -1
  82. package/dist/elements/empty.js +1 -1
  83. package/dist/elements/feedback-bar.js +1 -1
  84. package/dist/elements/file-tree.js +1 -1
  85. package/dist/elements/file-upload.js +1 -1
  86. package/dist/elements/form.js +1 -1
  87. package/dist/elements/hover-card.js +1 -1
  88. package/dist/elements/icon.js +1 -1
  89. package/dist/elements/image.js +1 -1
  90. package/dist/elements/input.js +1 -1
  91. package/dist/elements/kbd.js +1 -1
  92. package/dist/elements/link-preview.js +1 -1
  93. package/dist/elements/loader.js +1 -1
  94. package/dist/elements/markdown.js +1 -1
  95. package/dist/elements/menu.js +1 -1
  96. package/dist/elements/message-skills.js +1 -1
  97. package/dist/elements/message.js +1 -1
  98. package/dist/elements/model-switcher.js +1 -1
  99. package/dist/elements/nav.js +1 -1
  100. package/dist/elements/notice.js +1 -1
  101. package/dist/elements/pane-grid.js +1 -1
  102. package/dist/elements/pane-group.js +1 -1
  103. package/dist/elements/pane.js +1 -1
  104. package/dist/elements/popover.js +1 -1
  105. package/dist/elements/progress-bar.js +1 -1
  106. package/dist/elements/prompt-dock.js +1 -1
  107. package/dist/elements/prompt-input.js +1 -1
  108. package/dist/elements/prompt-suggestions.js +1 -1
  109. package/dist/elements/radio-group.js +1 -1
  110. package/dist/elements/reasoning.js +1 -1
  111. package/dist/elements/remote.js +1 -1
  112. package/dist/elements/resizable.js +1 -1
  113. package/dist/elements/response-stream.js +1 -1
  114. package/dist/elements/screen.js +1 -1
  115. package/dist/elements/scroll-area.js +1 -1
  116. package/dist/elements/scroll-button.js +1 -1
  117. package/dist/elements/search.js +1 -1
  118. package/dist/elements/segmented.js +1 -1
  119. package/dist/elements/select.js +1 -1
  120. package/dist/elements/separator.js +1 -1
  121. package/dist/elements/setting-item.js +1 -1
  122. package/dist/elements/settings-group.js +1 -1
  123. package/dist/elements/skeleton.js +1 -1
  124. package/dist/elements/slider.js +1 -1
  125. package/dist/elements/source.js +1 -1
  126. package/dist/elements/status.js +1 -1
  127. package/dist/elements/switch.js +1 -1
  128. package/dist/elements/tabs.js +1 -1
  129. package/dist/elements/tasks.js +1 -1
  130. package/dist/elements/text-shimmer.js +1 -1
  131. package/dist/elements/thinking-bar.js +1 -1
  132. package/dist/elements/thread.js +1 -1
  133. package/dist/elements/toast.js +1 -1
  134. package/dist/elements/tool.js +1 -1
  135. package/dist/elements/tooltip.js +1 -1
  136. package/dist/elements/voice-input.js +1 -1
  137. package/dist/elements/voice-output.js +1 -1
  138. package/dist/{ellipsis-CbOpJnU3.js → ellipsis-6pJ7SxYT.js} +1 -1
  139. package/dist/{embed-CrfjkbUG.js → embed-BMje-nxj.js} +1 -1
  140. package/dist/{external-link-ByXAwBBQ.js → external-link-Beh9DKeR.js} +1 -1
  141. package/dist/{file-text-DMib2qwt.js → file-text-D1GPfZ8Q.js} +1 -1
  142. package/dist/{file-tree-CJqM2aP7.js → file-tree-Dwj2lqg-.js} +1 -1
  143. package/dist/{folder-_BAb929C.js → folder-b6D8x1DY.js} +1 -1
  144. package/dist/{form-DSZgZQZk.js → form-DWgdxDXu.js} +1 -1
  145. package/dist/{hover-card-BQbul9eq.js → hover-card-CWRkqm40.js} +1 -1
  146. package/dist/{icon-CdcfRhYI.js → icon-CL0jdhsf.js} +1 -1
  147. package/dist/index.js +1741 -1725
  148. package/dist/index.server.js +1582 -1566
  149. package/dist/{info-DsFjGuI_.js → info-0cOUherQ.js} +1 -1
  150. package/dist/{input-DKbmkMos.js → input-BH6Ru91Q.js} +1 -1
  151. package/dist/kai.es.js +1 -1
  152. package/dist/{kbd-PvdGhX4s.js → kbd-DRAnVtNX.js} +1 -1
  153. package/dist/{link-zF8PzWfF.js → link-Dlr0vssB.js} +1 -1
  154. package/dist/{link-preview-DbM1866N.js → link-preview-DODgRyV9.js} +1 -1
  155. package/dist/loader-KvJB6NrT.js +1 -0
  156. package/dist/{markdown-LMvmAyBk.js → markdown-DX9tuJVj.js} +1 -1
  157. package/dist/mcp.es.js +8 -4
  158. package/dist/{message-BYZECyek.js → message-BqQ7Ot5q.js} +1 -1
  159. package/dist/{message-BSsgvHvf.js → message-DkaGfBd8.js} +1 -1
  160. package/dist/message-circle-BPpp5QKv.js +1 -0
  161. package/dist/message-square-BLbsd9BJ.js +1 -0
  162. package/dist/{minimize-2-BQRoBV1V.js → minimize-2-CyOHJwcN.js} +1 -1
  163. package/dist/{model-switcher-CMpCOYcB.js → model-switcher-0hrKDiK2.js} +1 -1
  164. package/dist/{overlay-Cb-MkyDa.js → overlay-DBMFXie6.js} +1 -1
  165. package/dist/{panel-right-i8warFxT.js → panel-right-t8SWJL6e.js} +1 -1
  166. package/dist/{paperclip-ByY3UVO6.js → paperclip-CdzuOjbU.js} +1 -1
  167. package/dist/play-BXy1u7rW.js +1 -0
  168. package/dist/primitives/use-auto-resize.d.ts +11 -0
  169. package/dist/{progress-bar-jVAHvMUf.js → progress-bar-CiBtxMWT.js} +1 -1
  170. package/dist/{prompt-suggestion-CD-qtNgC.js → prompt-suggestion-I_DHP21i.js} +1 -1
  171. package/dist/{radio-BsoBMhkF.js → radio-C_p3n39l.js} +1 -1
  172. package/dist/{reasoning-4kBPtlTx.js → reasoning-BDwy_tIe.js} +1 -1
  173. package/dist/register-impl-DvEnhIxx.js +424 -0
  174. package/dist/{resizable-uPmY9VY-.js → resizable-SYC-fStM.js} +1 -1
  175. package/dist/{rotate-ccw-B2xn93py.js → rotate-ccw-B1nwmwuY.js} +1 -1
  176. package/dist/{rotate-cw-CMVLoCyH.js → rotate-cw-CLAnBcm1.js} +1 -1
  177. package/dist/{scroll-area-BqLUo8ZZ.js → scroll-area-zRyXoLhI.js} +1 -1
  178. package/dist/{scroll-button-DslXiJyL.js → scroll-button-jzrbYCG9.js} +1 -1
  179. package/dist/{select-2cLRtPGT.js → select-DM-0nEe0.js} +1 -1
  180. package/dist/{separator-BWQtNJcM.js → separator-BToOOoOt.js} +1 -1
  181. package/dist/{settings-BBR63jLg.js → settings-PaGo_S4U.js} +1 -1
  182. package/dist/{settings-group-B2ciy-Iw.js → settings-group-BFXGIfXq.js} +1 -1
  183. package/dist/{skeleton-CkHI-HgC.js → skeleton-DYpmFnnm.js} +1 -1
  184. package/dist/{slider-DDR9U-i0.js → slider-ebutAmkQ.js} +1 -1
  185. package/dist/{solid-DruVOXnf.js → solid-15v_3WVL.js} +3563 -3412
  186. package/dist/{solid-BzCFdL25.js → solid-5P-otgdi.js} +4502 -4296
  187. package/dist/solid.d.ts +6 -0
  188. package/dist/solid.js +259 -254
  189. package/dist/solid.server.js +259 -254
  190. package/dist/{source-GEnFF528.js → source-c1gpRl9h.js} +1 -1
  191. package/dist/{star-CilHq8GP.js → star-pcV_3LqF.js} +1 -1
  192. package/dist/{store-Ciyk6eZG.js → store-CSgbFFCg.js} +1 -1
  193. package/dist/{switch-KkeQIbuH.js → switch-Bh2OdLV2.js} +1 -1
  194. package/dist/{tasks-card-BrN4bggJ.js → tasks-card-CbqQAn2S.js} +1 -1
  195. package/dist/text-shimmer-BSzgEnDH.js +1 -0
  196. package/dist/textarea-DrYNt_0z.js +1 -0
  197. package/dist/theme.tokens.css +22 -21
  198. package/dist/{thumbs-up-CsT9Wzb9.js → thumbs-up-BL3-NenK.js} +1 -1
  199. package/dist/{toast-store-tgK6MuMv.js → toast-store-DkOlYczt.js} +1 -1
  200. package/dist/{tool-DzUjIBT8.js → tool-CeIWUVUe.js} +1 -1
  201. package/dist/{tooltip-Bkkg_4t0.js → tooltip-GA-nmg06.js} +1 -1
  202. package/dist/{trash-2-jBKxjGGQ.js → trash-2-CT66QWlm.js} +1 -1
  203. package/dist/{triangle-alert-DlQ68ppf.js → triangle-alert-CeHLWxhD.js} +1 -1
  204. package/dist/ui/color-field.d.ts +48 -0
  205. package/dist/ui/textarea.d.ts +4 -0
  206. package/dist/ui/toggle-chip.d.ts +40 -0
  207. package/dist/{upload-TcAHXv9W.js → upload-9Csb0F0J.js} +1 -1
  208. package/dist/{use-card-resolution-DaZqAdWf.js → use-card-resolution-Zg0a08Z-.js} +1 -1
  209. package/dist/{variant-aurora-DbW_OWL2.js → variant-aurora-4VBQHIKV.js} +1 -1
  210. package/dist/{variant-aurora-CNmfHhcx.js → variant-aurora-DBeCAQNk.js} +2 -2
  211. package/dist/{variant-aurora-D6GsdTPA.js → variant-aurora-FzHVXHby.js} +2 -2
  212. package/dist/{variant-aurora-BhLuYxJR.js → variant-aurora-LE3fqxgw.js} +1 -1
  213. package/dist/{variant-custom-BvYHR62b.js → variant-custom-AFRGcOBS.js} +1 -1
  214. package/dist/{variant-custom-DV2x254s.js → variant-custom-BQkNuPpE.js} +2 -2
  215. package/dist/{variant-custom-BRvaNHSi.js → variant-custom-DI5R0rln.js} +1 -1
  216. package/dist/{variant-custom-DMTrEO5w.js → variant-custom-WWnrrRHS.js} +2 -2
  217. package/dist/{variant-wave-CyBueXj9.js → variant-wave-DUCbH5oI.js} +2 -2
  218. package/dist/{variant-wave-BNMGrDfj.js → variant-wave-DuQV7DhQ.js} +2 -2
  219. package/dist/{variant-wave-BpDd8t3Z.js → variant-wave-nSI2sfII.js} +1 -1
  220. package/dist/{variant-wave-sp-qwsdI.js → variant-wave-wTP5v_jU.js} +1 -1
  221. package/dist/x-eiO9V6J6.js +1 -0
  222. package/kit-base.css +311 -0
  223. package/package.json +17 -2
  224. package/solid.css +33 -0
  225. package/theme.css +39 -23
  226. package/dist/arrow-down-CjRU3JgV.js +0 -1
  227. package/dist/arrow-left-Bnpb1UEW.js +0 -1
  228. package/dist/artifact-Bwt7OgcR.js +0 -1
  229. package/dist/check-njkVdZu2.js +0 -1
  230. package/dist/chevron-down-B72s6PXR.js +0 -1
  231. package/dist/chevron-right-BatuHzUm.js +0 -1
  232. package/dist/circle-check-B62pODB3.js +0 -1
  233. package/dist/circle-zx0ByzY9.js +0 -1
  234. package/dist/controllable-CnGpMF6r.js +0 -1
  235. package/dist/define-By-uL588.js +0 -1
  236. package/dist/loader-BM4CEz4G.js +0 -1
  237. package/dist/message-circle-DruwObfX.js +0 -1
  238. package/dist/message-square-BG6q6mlm.js +0 -1
  239. package/dist/play-BvKKq3fX.js +0 -1
  240. package/dist/register-impl-B1hLkrI8.js +0 -424
  241. package/dist/text-shimmer-Dcj1MHuq.js +0 -1
  242. package/dist/textarea-Dpvbngbg.js +0 -1
  243. package/dist/x-Z5UntkIJ.js +0 -1
@@ -0,0 +1,54 @@
1
+ import { JSX } from 'solid-js';
2
+ export type BuilderViewport = 'desktop' | 'tablet' | 'mobile';
3
+ export interface BuilderLayoutProps {
4
+ /** The construct's display name, shown in the toolbar. */
5
+ name: string;
6
+ /** The inspector panel content — typically `<BuilderPanel>`. */
7
+ panel: JSX.Element;
8
+ /** The preview content — typically a device frame wrapping `<ChatThread>`.
9
+ * Callers that need to reflow their OWN preview at narrower widths (e.g.
10
+ * a docked-rail template collapsing to full-bleed on `mobile`, matching
11
+ * `ui/dock.tsx`'s own <=480px takeover) should read `viewport`/
12
+ * `defaultViewport`/`onViewportChange` below and drive their preview's
13
+ * shape from the same signal they hand this component — see
14
+ * `builder-in-app-assistant.stories.tsx` and `builder.stories.tsx` for
15
+ * the pattern. */
16
+ preview: JSX.Element;
17
+ /** Controlled viewport selection. Omit for uncontrolled (internal) state,
18
+ * same controlled/uncontrolled convention as `Switch`'s
19
+ * `checked`/`defaultChecked` and `ToggleChip`'s `pressed`/
20
+ * `defaultPressed`. A caller that needs to reflow its own `preview` JSX
21
+ * per viewport (see the doc comment on `preview`) should lift this to a
22
+ * signal of its own and pass both this and `onViewportChange`. */
23
+ viewport?: BuilderViewport;
24
+ /** Initial viewport when uncontrolled. Defaults to `'desktop'`. */
25
+ defaultViewport?: BuilderViewport;
26
+ /** Fires with the next viewport on chip selection (controlled or not). */
27
+ onViewportChange?: (viewport: BuilderViewport) => void;
28
+ /** Stub export/save action; the real seam (a file write, per the spike) isn't
29
+ * built here. */
30
+ onSave?: () => void;
31
+ class?: string;
32
+ }
33
+ /**
34
+ * `BuilderLayout` — the two-pane builder shell: a fixed-width scrollable
35
+ * inspector on the left, a live preview on the right over a dotted canvas
36
+ * background (a deliberate "this is a design tool" cue, not a real device
37
+ * emulator). A thin toolbar strip carries the construct name, a viewport
38
+ * toggle, and a stub Export action.
39
+ *
40
+ * The viewport toggle (Round A4 — was a round-1 visual stub) constrains the
41
+ * PREVIEW FRAME's width: `desktop` fills the pane exactly as before (no
42
+ * wrapper, no width style — the historical "stub" behavior for that one
43
+ * case); `tablet`/`mobile` wrap `preview` in a centered frame sized to
44
+ * `FRAME_WIDTH` above (768px / 390px), letting whatever `preview` renders
45
+ * reflow inside it. This is still not a real device emulator — no bezel,
46
+ * no user-agent spoofing, no touch simulation — just a width constraint,
47
+ * consistent with the doc comment this replaced.
48
+ *
49
+ * Pure shell: `panel` and `preview` are handed in as JSX so this component
50
+ * carries no opinion about what fills them; reflowing the CONTENT of
51
+ * `preview` at a given width (rather than just its outer box) is the
52
+ * caller's job — see the `preview` prop's own doc comment.
53
+ */
54
+ export declare function BuilderLayout(props: BuilderLayoutProps): JSX.Element;
@@ -0,0 +1,72 @@
1
+ import { JSX, Component } from 'solid-js';
2
+ import { ChatMessageAction, CustomAction } from '../elements/chat-types.js';
3
+ /**
4
+ * The role-scoped, ordered message-action picker — extracted from
5
+ * `builder-in-app-assistant.stories.tsx` (Round A3) into this standalone
6
+ * module during the T-1 build-out so the Assistant and Research templates
7
+ * (both asked for a "message actions, role-scoped picker, reuse" section)
8
+ * share one definition instead of forking it. `builder-in-app-assistant.
9
+ * stories.tsx` was retrofitted to import from here in the same round; its
10
+ * rendered output and behavior are unchanged — this is a pure extraction.
11
+ *
12
+ * Model: `ChatMessage.actions` (`elements/chat-types.ts`) is `(ChatMessage
13
+ * Action | CustomAction)[]` — an ORDERED array, not a set — and role-scoped
14
+ * only by caller curation (checked against `message.tsx`/`chat-thread.tsx`:
15
+ * neither hard-couples any built-in id to a role). This picker enforces
16
+ * role-appropriateness via two independent catalogs, one per role, each
17
+ * independently ordered and toggled.
18
+ *
19
+ * `'speak'` (read-aloud) is a kit-tier PROPOSAL, not a real
20
+ * `ChatMessageAction` value — voice OUTPUT exists as a separate element
21
+ * (`kai-voice-output`), not as a message-action id. When the row is
22
+ * enabled, callers should append `SPEAK_CUSTOM_ACTION` (a real, clickable,
23
+ * no-op `CustomAction`) rather than inventing a fake `ChatMessageAction`.
24
+ */
25
+ export type UserActionId = Extract<ChatMessageAction, 'edit' | 'copy'>;
26
+ export type AssistantActionId = ChatMessageAction | 'speak';
27
+ export interface ActionRowDef<TId extends string> {
28
+ id: TId;
29
+ label: string;
30
+ /** A curated icon — same components `ui/action-icons.ts`'s registry maps
31
+ * each built-in id to, so the picker's icons match what the real action
32
+ * bar renders. */
33
+ icon: Component<{
34
+ class?: string;
35
+ }>;
36
+ /** Not a real `ChatMessageAction` today — see the module doc comment. */
37
+ proposed?: boolean;
38
+ }
39
+ export interface ActionRowState<TId extends string> {
40
+ id: TId;
41
+ enabled: boolean;
42
+ }
43
+ export declare const USER_ACTION_CATALOG: readonly ActionRowDef<UserActionId>[];
44
+ export declare const ASSISTANT_ACTION_CATALOG: readonly ActionRowDef<AssistantActionId>[];
45
+ /** Owner defaults (Round A3): "Your messages" starts with only Edit on;
46
+ * "Assistant messages" starts with Copy/Like/Dislike on, Regenerate and
47
+ * the proposed Speak row off. Row ORDER here is also the default
48
+ * enabled-action order. */
49
+ export declare const DEFAULT_USER_ACTION_ROWS: ActionRowState<UserActionId>[];
50
+ export declare const DEFAULT_ASSISTANT_ACTION_ROWS: ActionRowState<AssistantActionId>[];
51
+ /** The real `CustomAction` a preview should append when the proposed Speak
52
+ * row is enabled — a genuine, clickable (no-op) button, never faked
53
+ * audio. `volume-2` is already a curated icon in `ui/action-icons.ts`'s
54
+ * registry. */
55
+ export declare const SPEAK_CUSTOM_ACTION: CustomAction;
56
+ /**
57
+ * One role's ordered, toggleable action list — a vertical list of rows
58
+ * (icon + label + a "Proposed" tag when the row is one + up/down reorder
59
+ * buttons + an enable switch). Row ORDER is the array order, and doubles
60
+ * as the enabled-action order once filtered — no separate "priority"
61
+ * field, because the component tier has no separate concept either.
62
+ *
63
+ * Up/down buttons over drag-and-drop: keyboard- and screen-reader-operable
64
+ * for free, which a bare drag handle is not, without extra work a design
65
+ * round doesn't need to do to prove the model (T-6).
66
+ */
67
+ export declare function ActionRowPicker<TId extends string>(props: {
68
+ legend: string;
69
+ catalog: readonly ActionRowDef<TId>[];
70
+ rows: ActionRowState<TId>[];
71
+ onChange: (next: ActionRowState<TId>[]) => void;
72
+ }): JSX.Element;
@@ -0,0 +1,189 @@
1
+ import { JSX } from 'solid-js';
2
+ export type BuilderLayoutKind = 'widget' | 'fullscreen' | 'aside' | 'split' | 'custom';
3
+ export type BuilderThemeMode = 'light' | 'dark' | 'system';
4
+ export type BuilderHistoryPersistence = 'none' | 'local' | 'endpoint';
5
+ export interface BuilderHomeLink {
6
+ label: string;
7
+ href?: string;
8
+ description?: string;
9
+ icon?: string;
10
+ }
11
+ export interface BuilderHome {
12
+ greeting?: {
13
+ title?: string;
14
+ subtitle?: string;
15
+ };
16
+ links?: BuilderHomeLink[];
17
+ }
18
+ export interface BuilderCapabilities {
19
+ starters?: string[];
20
+ attachments?: {
21
+ accept?: string[];
22
+ };
23
+ history?: {
24
+ persistence: BuilderHistoryPersistence;
25
+ };
26
+ conversations?: boolean;
27
+ }
28
+ export type BuilderWidgetPosition = 'bottom-end' | 'bottom-start' | 'top-end' | 'top-start';
29
+ /** `layout: 'widget'`-scoped FAB chrome — mirrors `construct.v1`'s own
30
+ * `widget` block. Meaningless on any other layout, which is exactly why
31
+ * the panel section it drives is HIDDEN, not just disabled, on any other
32
+ * layout (see the Layout section's own doc comment for that distinction). */
33
+ export interface BuilderWidget {
34
+ position?: BuilderWidgetPosition;
35
+ launcherIcon?: string;
36
+ defaultOpen?: boolean;
37
+ }
38
+ export type BuilderProviderMode = 'mock' | 'endpoint';
39
+ export type BuilderProviderWire = 'openai' | 'anthropic';
40
+ /** Mirrors `construct.v1`'s own `provider` discriminated union
41
+ * (`agent-tooling/construct/schema.ts`'s `ProviderSchema`) — `mock` needs
42
+ * nothing else; `endpoint` needs the consumer's own chat route + wire
43
+ * format. A DISPLAY/edit stub, not a real one: no dev-server exists for
44
+ * this design round to actually call, so there's nothing to validate the
45
+ * URL against — the field exists so a template's panel shows the whole
46
+ * construct shape, not because this round wires it to anything. */
47
+ export interface BuilderProvider {
48
+ mode: BuilderProviderMode;
49
+ url?: string;
50
+ wire?: BuilderProviderWire;
51
+ }
52
+ /** Mirrors `construct.v1`'s own `cards` entry shape (`schema.ts`'s
53
+ * `cards` array): a tool-facing `name` plus the kit's card-schema JSON.
54
+ * `schema` is `Record<string, unknown>` here too — deep card validation
55
+ * (incl. `x-kai-format` mask hints) is the kit's own card contract at
56
+ * render time, not this stub panel's job; this stub only ever READS
57
+ * `schema.title` for a display label (Round A's read-only Cards section —
58
+ * see `BuilderPanelSections.cards`). */
59
+ export interface BuilderCard {
60
+ name: string;
61
+ schema?: Record<string, unknown>;
62
+ }
63
+ export interface BuilderConstruct {
64
+ name: string;
65
+ layout: BuilderLayoutKind;
66
+ provider?: BuilderProvider;
67
+ header?: {
68
+ title?: string;
69
+ };
70
+ theme?: {
71
+ accent?: string;
72
+ unreadColor?: string;
73
+ mode?: BuilderThemeMode;
74
+ };
75
+ home?: BuilderHome;
76
+ capabilities?: BuilderCapabilities;
77
+ widget?: BuilderWidget;
78
+ cards?: BuilderCard[];
79
+ }
80
+ /**
81
+ * A template-scoped section configuration (Round W, T-2/T-6): a template
82
+ * FIXES its layout internally (no layout radio) and owns which of the
83
+ * layout-scoped sections apply — a widget template shows Widget chrome
84
+ * unconditionally (it IS the widget template, not merely "currently set to
85
+ * widget"), where the old layout-driven panel showed it only when the
86
+ * layout radio happened to be on "Widget". Omit this prop entirely to get
87
+ * the original, generic, layout-driven panel (every existing test above
88
+ * exercises that default) — a template panel opts INTO the narrower set
89
+ * rather than the generic panel opting out.
90
+ */
91
+ export interface BuilderPanelSections {
92
+ /** Show the Layout radio section. Default `true` (the generic panel).
93
+ * A template panel sets this `false` — T-2: the template fixes the
94
+ * layout, so there is nothing left to choose here. */
95
+ layout?: boolean;
96
+ /** The Widget-chrome section's visibility. `'auto'` (default) follows
97
+ * `value.layout === 'widget'`, the original cross-field-visibility
98
+ * behavior. `'always'` shows it unconditionally — what a Support widget
99
+ * template panel wants, since for THAT template the section is never
100
+ * conditional, it's simply always this template's own controls.
101
+ * `'never'` hides it — what every non-widget template wants once each
102
+ * gets its own `Labs/Builder/<Template>` story. */
103
+ widget?: 'auto' | 'always' | 'never';
104
+ /** Show the Provider section (mode + endpoint URL/wire when applicable).
105
+ * Default `false` — the generic panel predates `provider` existing on
106
+ * `BuilderConstruct` at all; a template panel opts in. */
107
+ provider?: boolean;
108
+ /** Show the Home section (greeting/links tab). Default `true` (the
109
+ * generic panel). A template with no Home concept at all — In-app
110
+ * assistant (Round A): widget-only chrome, no Home/Messages tab bar in
111
+ * its own construct basis (`fixtures/ops-console.construct.json` has no
112
+ * `home` key) — sets this `false` to remove the section outright,
113
+ * rather than leaving a switch that would only ever read "off". */
114
+ home?: boolean;
115
+ /** Show a READ-ONLY Cards section: the construct's declared card names
116
+ * (Round A's `cards` addition to `BuilderConstruct`), with a muted note
117
+ * that editing them is a later round. Default `false`. Deliberately not
118
+ * an editor — a template whose construct basis carries `cards` (like
119
+ * `ops-console.construct.json`'s `deployment_parameters` form) still
120
+ * needs the panel to acknowledge them exist rather than silently
121
+ * dropping them from view, without this design round faking a card-
122
+ * schema editor it doesn't have (decide loudly, per CLAUDE.md). */
123
+ cards?: boolean;
124
+ }
125
+ export interface BuilderPanelProps {
126
+ /** The construct being edited. Controlled — the panel never holds its own copy. */
127
+ value: BuilderConstruct;
128
+ /** Fires with the next construct on every edit. */
129
+ onChange: (next: BuilderConstruct) => void;
130
+ /** Which sections render — see `BuilderPanelSections`. Omit for the
131
+ * original generic, layout-driven panel. */
132
+ sections?: BuilderPanelSections;
133
+ class?: string;
134
+ }
135
+ /** One "common case" chip for `capabilities.attachments.accept`: a human label
136
+ * over one or more raw MIME patterns. Owner feedback (design round 2):
137
+ * raw MIME types are hostile to the audience this panel is for, so the
138
+ * common cases get a toggle chip and the raw list is a secondary, visible
139
+ * ("Advanced") affordance rather than the primary input. */
140
+ export interface AcceptChip {
141
+ id: string;
142
+ label: string;
143
+ patterns: readonly string[];
144
+ }
145
+ /**
146
+ * The chip → MIME-pattern map for the attachments accept editor below.
147
+ *
148
+ * Exported (not module-local) because it's exactly the vocabulary a future
149
+ * schema-driven wizard or capability menu (RECOMMENDATION.md's "real build")
150
+ * will also want — one place to widen the common-case list rather than a
151
+ * second one growing beside it.
152
+ */
153
+ export declare const ACCEPT_CHIPS: readonly AcceptChip[];
154
+ /**
155
+ * `BuilderPanel` — the visual construct builder's inspector: identity, layout,
156
+ * theme, an optional Home tab, and capabilities. Pure props/callbacks, stub-
157
+ * friendly (no dev-server seam, no schema derivation) — a STORY-FIRST design
158
+ * surface for the panel's look, per RECOMMENDATION.md. Composed entirely from
159
+ * the kit's own controls (`Input`/`Textarea`/`Switch`/`RadioGroup`/`Select`/
160
+ * `Button`/`ColorField`/`ToggleChip`); no `part=` attributes — this component is not
161
+ * yet wired to a `kai-*` facade.
162
+ *
163
+ * Round W (T-2/T-6) added `sections` (`BuilderPanelSections`): omit it for
164
+ * the original generic, layout-driven panel this doc comment otherwise
165
+ * describes unchanged; pass it to scope the panel to ONE template's control
166
+ * set — no Layout radio, Widget chrome shown unconditionally rather than
167
+ * `layout`-conditionally, a Provider section — the shape `Labs/Builder/
168
+ * Support widget` (`src/elements/builder.stories.tsx`) actually uses.
169
+ *
170
+ * Three patterns from the spike (plus the owner's own round-8 ruling) get
171
+ * real design treatment here rather than being hand-waved:
172
+ * - **presence-as-boolean**: `home` and `capabilities.attachments` are each
173
+ * driven by ONE switch that adds/removes the whole sub-object, with its
174
+ * revealed fields directly below (no second "enabled" flag living beside
175
+ * the object it toggles).
176
+ * - **cross-field visibility, field-level**: `capabilities.conversations`
177
+ * requires `capabilities.history.persistence` to be `local`/`endpoint`
178
+ * (the schema's own `superRefine` rule) — shown as a disabled switch with
179
+ * the reason spelled out in muted text right below it, not a validation
180
+ * error surfaced after the fact.
181
+ * - **cross-field visibility, section-level**: the whole "Widget" section
182
+ * (position/launcher icon/open-by-default) is meaningless outside
183
+ * `layout: 'widget'`, and unlike the single Conversations toggle above, a
184
+ * disabled-and-explained SECTION would just be three greyed-out rows for
185
+ * one sentence's worth of reason — so it's hidden entirely, not disabled,
186
+ * whenever `layout` isn't `'widget'` (owner ruling, design round 8; see
187
+ * that section's own comment for the full distinction).
188
+ */
189
+ export declare function BuilderPanel(props: BuilderPanelProps): JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { BuilderConstruct } from './builder-panel.js';
2
+ /**
3
+ * The inline style object a stub preview's wrapper needs so a construct's
4
+ * `theme.accent` actually retints its descendants: both the public
5
+ * (`--kai-color-primary`) and internal (`--color-primary`) tokens, plus
6
+ * their paired foreground when the accent resolves to concrete RGB — see
7
+ * the module doc comment above for why both are required. Returns `{}` for
8
+ * no accent (the kit's own neutral default applies, same as omitting the
9
+ * property entirely).
10
+ */
11
+ export declare function resolveAccentWrapperStyle(theme: BuilderConstruct['theme']): Record<string, string>;
@@ -0,0 +1,69 @@
1
+ import { JSX } from 'solid-js';
2
+ /**
3
+ * "App chrome" — the Command palette and User menu shell knobs (owner
4
+ * discovery round), factored as a shared module so every shell-bearing
5
+ * template (`Labs/Builder/Assistant`, `.../Workspace`, `.../Multi-mode`)
6
+ * reuses the same real pieces instead of forking a fourth copy —
7
+ * consistent with `builder-composer-triggers.tsx`'s own rule-of-three
8
+ * extraction earlier this round.
9
+ *
10
+ * COMMAND PALETTE: composes the kit's real `CommandList` (`ui/command.tsx`)
11
+ * — a presentational grouped listbox — inside a hand-built overlay
12
+ * (backdrop + centered panel + Escape/backdrop-click to close), the SAME
13
+ * shape `elements/claude-code.stories.tsx`'s own command-center overlay
14
+ * uses around `kai-command` (read before building this — `CommandList` is
15
+ * that facade's underlying Solid piece; the facade adds the search input's
16
+ * filtering behavior itself, which `CommandList` does not own). A plain
17
+ * `Input` above the list does the filtering here, client-side over a stub
18
+ * catalog, matching claude-code's own placeholder copy style ("Search
19
+ * commands...").
20
+ *
21
+ * USER MENU: `elements/user-menu.stories.tsx`'s own doc comment states it
22
+ * plainly — "the user menu is a RECIPE, not an element... kai-menu with a
23
+ * slotted trigger (kai-avatar + name + plan + a chevron + a kai-status
24
+ * dot)". Reused here as the Solid-tier equivalent: `Dropdown`/
25
+ * `DropdownTrigger`/`DropdownContent`/`DropdownItem` (the same primitives
26
+ * `components/model-switcher.tsx` and the Workspace composer menu already
27
+ * compose) with an `Avatar` + name/plan trigger.
28
+ */
29
+ export interface ShellControlsState {
30
+ commandPalette: boolean;
31
+ userMenu: boolean;
32
+ }
33
+ /** The command palette overlay — mounted only while `open`. Filters the
34
+ * stub catalog client-side; selecting a row or pressing Escape closes it. */
35
+ export declare function CommandPaletteOverlay(props: {
36
+ open: boolean;
37
+ onClose: () => void;
38
+ }): JSX.Element;
39
+ /** The command palette's TRIGGER — a plain search-icon button, matching
40
+ * claude-code's own rail-header search affordance. Rendering the overlay
41
+ * itself is the caller's job (`CommandPaletteOverlay`), so a template can
42
+ * place the trigger inside its own rail/header chrome while the overlay
43
+ * mounts at the frame root. */
44
+ export declare function CommandPaletteTrigger(props: {
45
+ onOpen: () => void;
46
+ }): JSX.Element;
47
+ /** The user-menu recipe itself — avatar + name/plan trigger, real Dropdown
48
+ * primitives, a stub items list (Settings/Help/Log out). `compact` (owner
49
+ * feedback round, Workspace's app-header rework) drops the name/plan text
50
+ * entirely, rendering avatar + chevron only — for a header utility cluster
51
+ * where the full name/plan reads as too much next to icon-only siblings.
52
+ * `name`/`plan` still feed the avatar initials and the accessible name
53
+ * (`aria-label`) even when compact, so the control never loses its name to
54
+ * assistive tech just because the text is hidden visually. */
55
+ export declare function UserMenu(props: {
56
+ name: string;
57
+ plan?: string;
58
+ class?: string;
59
+ compact?: boolean;
60
+ }): JSX.Element;
61
+ /** The panel section every shell-bearing template reuses: two toggles,
62
+ * "Command palette" and "User menu." Preview-only — see each template's
63
+ * own module doc comment for how the toggles wire into ITS OWN chrome
64
+ * (the trigger/overlay/menu placement differs per template's real
65
+ * anatomy, so this section only owns the on/off state, not the layout). */
66
+ export declare function ShellSection(props: {
67
+ state: ShellControlsState;
68
+ onChange: (v: ShellControlsState) => void;
69
+ }): JSX.Element;
@@ -0,0 +1,58 @@
1
+ import { JSX } from 'solid-js';
2
+ /**
3
+ * Shared wordless-skeleton language for `Labs/Builder/<Template>` preview
4
+ * hosts (docs/superpowers/specs/2026-08-28-template-builder-design.md).
5
+ *
6
+ * Extracted from `builder-in-app-assistant.stories.tsx` (Round A2) into this
7
+ * standalone module during the T-1 build-out (Assistant/Research/Workspace/
8
+ * Voice) so every template's "the rest of your app" skeleton chrome shares
9
+ * one definition instead of four copies drifting apart — the cross-cutting
10
+ * mandate the design spec's Process step names ("as shared needs emerge,
11
+ * refactor the shared components ONCE"). `builder-in-app-assistant.stories.tsx`
12
+ * was retrofitted to import from here in the same round; nothing about its
13
+ * rendered output changed.
14
+ *
15
+ * PLAIN inline CSS (`color-mix`), not a Tailwind opacity-modifier class
16
+ * on a color utility or an arbitrary-bracket width value — see the
17
+ * original Round A2 note in git blame: this Storybook dev server's
18
+ * Tailwind JIT pass proved non-deterministic for FRESH combinations
19
+ * introduced by a single file (a class would show correctly in the rendered
20
+ * `className` while `getComputedStyle` reported the rule simply wasn't
21
+ * compiled). `color-mix()` is real CSS with no compile step to race, and
22
+ * matches what Tailwind's own `/NN` opacity modifier generates.
23
+ */
24
+ export declare function mix(colorVar: string, pct: number): string;
25
+ /** One skeleton bar/pill. `widthClass` for a standard-scale Tailwind width
26
+ * utility (proven reliable); `width` for an inline CSS width (a
27
+ * percentage, or anything arbitrary); `flex` to grow and fill instead of
28
+ * taking either. Height is always a standard-scale utility unless
29
+ * overridden. */
30
+ export declare function SkeletonBar(props: {
31
+ widthClass?: string;
32
+ width?: string;
33
+ heightClass?: string;
34
+ pct: number;
35
+ flex?: boolean;
36
+ }): JSX.Element;
37
+ /** A grayscale/muted skeleton stat tile: a label bar over a bigger number
38
+ * bar. Deliberately toneless (muted-foreground tints only, never
39
+ * `bg-primary`/accent) so the host reads as chrome around the product
40
+ * rather than product itself. */
41
+ export declare function StubStatTile(props: {
42
+ class?: string;
43
+ }): JSX.Element;
44
+ /** A single stub nav-rail row: an icon-ish dot plus a label bar. `active`
45
+ * lights the row the way a real nav's current-page item would. */
46
+ export declare function StubNavRow(props: {
47
+ active?: boolean;
48
+ }): JSX.Element;
49
+ /** A single stub table row: a handful of column bars at staggered widths,
50
+ * so the row reads as data rather than one flat block. */
51
+ export declare function StubTableRow(): JSX.Element;
52
+ /** A wordless skeleton code/text block: a stack of bars at staggered
53
+ * widths, monospace rhythm (shorter, denser bars) rather than prose
54
+ * rhythm — for the Workspace template's artifact/code pane. */
55
+ export declare function StubCodeBlock(props: {
56
+ lines?: number;
57
+ class?: string;
58
+ }): JSX.Element;
@@ -0,0 +1,75 @@
1
+ import { JSX } from 'solid-js';
2
+ export type BuilderTemplateId = 'widget' | 'inAppAssistant' | 'assistant' | 'research' | 'workspace' | 'voice' | 'scratch';
3
+ /** The template ids that DO have a card — every `BuilderTemplateId` except
4
+ * `'scratch'`, which has no illustration and never appears in
5
+ * `BUILDER_TEMPLATES`. */
6
+ export type BuilderCardTemplateId = Exclude<BuilderTemplateId, 'scratch'>;
7
+ export interface BuilderTemplate {
8
+ id: BuilderCardTemplateId;
9
+ name: string;
10
+ description: string;
11
+ }
12
+ /** V1 templates, in build order (T-1: easiest to hardest, so controls
13
+ * accumulate template to template). Names and one-liners are the T-4/T-7
14
+ * copy this round exists to force into existence. Round P2 grows the set
15
+ * from four to six (In-app assistant, Voice) and sharpens the four
16
+ * existing one-liners for instant recognition. */
17
+ export declare const BUILDER_TEMPLATES: readonly BuilderTemplate[];
18
+ export interface BuilderStartProps {
19
+ /** The currently selected template id, or unset for none yet. Controlled —
20
+ * this component holds no selection state of its own. */
21
+ value?: BuilderTemplateId;
22
+ /**
23
+ * Fires with a template's id when its card is chosen. Click-to-advance
24
+ * (design choice, this round): T-7 says "selection advances to that
25
+ * template's builder", and there is nothing a second "Continue" step
26
+ * would add here that the click itself doesn't already mean — a
27
+ * disambiguating confirm step belongs to T-2's SWITCHING-template case
28
+ * (control set changes, so a re-pick needs a confirm), not to picking a
29
+ * template for the first time. So `onSelect` fires on the same click that
30
+ * shows the selected ring; the story's Continue readout below just proves
31
+ * the callback fired, since there's no template builder screen yet to
32
+ * navigate to.
33
+ */
34
+ onSelect: (id: BuilderTemplateId) => void;
35
+ class?: string;
36
+ }
37
+ export declare const BLUEPRINT_BG: {
38
+ readonly 'background-image': "radial-gradient(circle, var(--color-border) 1px, transparent 1px)";
39
+ readonly 'background-size': "14px 14px";
40
+ };
41
+ /**
42
+ * `BuilderStart` — the builder's opening screen: six selectable template
43
+ * cards (T-7, grown from four in Round P2). Each card is a real
44
+ * `ui/card.tsx` `Card` (`clickable`,
45
+ * `media` for the illustration, `header` for the name), not a hand-rolled
46
+ * button — the kit's own primitive already gives a `role="button"` with
47
+ * Enter/Space activation, which settles this screen's keyboard-semantics
48
+ * question: a `radiogroup` was the other defensible reading (this IS a
49
+ * single choice among six), but `Card` already implements exactly the
50
+ * button-per-card pattern with no extra wiring, and reusing it beats
51
+ * building a second selection primitive for one screen.
52
+ *
53
+ * Brand alignment (T-7): the kit's own tokens throughout — no new color, no
54
+ * new radius, no new type stack. The illustrations are the one genuinely new
55
+ * visual element this round adds; see `TEMPLATE_ILLUSTRATIONS` below for
56
+ * their shared style rules.
57
+ */
58
+ export declare function BuilderStart(props: BuilderStartProps): JSX.Element;
59
+ export declare const STROKE = 1.5;
60
+ export declare const LINE: {
61
+ stroke: string;
62
+ fill: string;
63
+ };
64
+ export declare const BORDER: {
65
+ stroke: string;
66
+ fill: string;
67
+ };
68
+ export declare const ACCENT: {
69
+ stroke: string;
70
+ fill: string;
71
+ };
72
+ export declare const ACCENT_FILL: {
73
+ stroke: string;
74
+ fill: string;
75
+ };
@@ -0,0 +1,23 @@
1
+ import { JSX } from 'solid-js';
2
+ export type WorkspaceVariantId = 'artifactPreview' | 'appPreview';
3
+ export interface WorkspaceVariant {
4
+ id: WorkspaceVariantId;
5
+ name: string;
6
+ description: string;
7
+ }
8
+ export declare const WORKSPACE_VARIANTS: readonly WorkspaceVariant[];
9
+ export interface WorkspaceVariantPickerProps {
10
+ value?: WorkspaceVariantId;
11
+ onSelect: (id: WorkspaceVariantId) => void;
12
+ onBack: () => void;
13
+ class?: string;
14
+ }
15
+ /**
16
+ * `WorkspaceVariantPicker` — the Workspace family's second screen: two
17
+ * function-named variant cards (smaller-scale `Card`s, reusing `Builder
18
+ * Start`'s own pattern) plus a back affordance to the template picker.
19
+ * Selection fires `onSelect` with the variant id the same click-to-advance
20
+ * shape `BuilderStart` itself uses (T-7's own reasoning: nothing a second
21
+ * "Continue" step would add here that the click doesn't already mean).
22
+ */
23
+ export declare function WorkspaceVariantPicker(props: WorkspaceVariantPickerProps): JSX.Element;
@@ -0,0 +1,66 @@
1
+ import { JSX } from 'solid-js';
2
+ /**
3
+ * `Captions` — live closed-captioning: the text shown WHILE someone (the
4
+ * user or the agent) is speaking, distinct from a scrollback transcript.
5
+ * Built for the Voice template (`elements/builder-voice.stories.tsx`) but
6
+ * kept generic — any voice surface that wants a caption line can use this
7
+ * directly.
8
+ *
9
+ * - Driven by `segments`, oldest first — the LAST entry is the current
10
+ * line. Everything else is history, only rendered by `stacked`.
11
+ * - `variant` picks the chrome: `'lower-third'` (a semi-opaque bar, the
12
+ * broadcast-caption look), `'floating'` (a card that floats above a
13
+ * visualizer, `kai-elevation`), `'minimal'` (bare text, no chrome — the
14
+ * original shape this component shipped with), `'stacked'` (the last two
15
+ * lines of history fade in behind the current line, which stays full
16
+ * strength). Default `'minimal'`.
17
+ * - Speaker-aware via `data-speaker` + a small uppercase label ("You" /
18
+ * "Assistant") — NOT a color swap. Accent stays reserved for the
19
+ * visualizer per the owner's Voice-round instruction, so the distinction
20
+ * lives in the label and a subtle weight difference, both drawn from the
21
+ * muted/foreground tiers, never `text-primary`.
22
+ * - Interim (`final: false`) text renders `text-muted-foreground` / a hair
23
+ * lighter than a finalized line's `text-foreground`, so a caption visibly
24
+ * "settles" the moment the model (or the ASR) commits it.
25
+ * - Undefined/empty `segments`, or a current segment whose `text` is empty
26
+ * or whitespace-only, renders NOTHING — a real `<Show>` around a presence
27
+ * gate, not a hidden/zero-opacity node left in the DOM.
28
+ * - One `role="status"`/`aria-live="polite"` region, wrapping ONLY the
29
+ * current line — `stacked`'s history lines sit outside it
30
+ * (`aria-hidden="true"`) so they don't get re-announced every time the
31
+ * region's content changes. This mirrors `toast.tsx`'s
32
+ * `role="region"`/`aria-live="polite"` pattern (the kit's other
33
+ * speech-adjacent live region) rather than inventing a second policy, and
34
+ * is the ONLY live region this component renders — it says nothing about
35
+ * history, so it can't double-announce anything a transcript component
36
+ * elsewhere on the page is already announcing.
37
+ * - Appear/update reuses the kit's real exit-animation primitive,
38
+ * `createPresence` (`ui/overlay.tsx`), for the whole component's
39
+ * mount/unmount, and a keyed `<For>` around the current line so a NEW
40
+ * segment object (the same "new object per changed item" contract the
41
+ * rest of the kit's reactive props follow) retriggers its own
42
+ * `animate-in` rather than being silently patched in place. Both use the
43
+ * same already-compiled `animate-in ... data-[closed]:animate-out ...`
44
+ * Tailwind-animate classes `DropdownContent`/`DialogContent`/
45
+ * `HoverCardContent` use, and both carry `motion-reduce:animate-none` (the
46
+ * same pattern `screen.tsx`/`dialog.tsx` use) so `prefers-reduced-motion:
47
+ * reduce` turns the animation off entirely — the text still appears,
48
+ * updates and disappears, just without motion.
49
+ */
50
+ export interface CaptionSegment {
51
+ /** Whose speech this line represents. */
52
+ speaker: 'user' | 'assistant';
53
+ /** The line's text. Empty/whitespace on the CURRENT segment renders nothing. */
54
+ text: string;
55
+ /** Whether ASR/the model has committed this line. Default `true`. */
56
+ final?: boolean;
57
+ }
58
+ export type CaptionsVariant = 'lower-third' | 'floating' | 'minimal' | 'stacked';
59
+ export interface CaptionsProps {
60
+ /** Caption lines, oldest first. The last entry is the current line. */
61
+ segments?: CaptionSegment[];
62
+ /** Which visual treatment to render. Default `'minimal'`. */
63
+ variant?: CaptionsVariant;
64
+ class?: string;
65
+ }
66
+ export declare function Captions(props: CaptionsProps): JSX.Element;
@@ -1,4 +1,4 @@
1
- import{A as Ye,g as z,w as Je,k as Q,j as de,o as ue,x as De,h as Qe,i as N,u as Ne,a as H,d as O,b as Z,l as ee,c as $,F as Oe,S as G,t as S,Q as Ze,e as et}from"./define-By-uL588.js";import{c as P}from"./cn-DN5AWfiS.js";import{u as tt,c as nt,a as rt}from"./overlay-Cb-MkyDa.js";function M(n){if(n==null)return[];if(typeof n=="string")return n.length?[{type:"text",text:n}]:[];const l=[];for(const t of n)if(t.type==="text"){if(!t.text)continue;const i=l[l.length-1];i&&i.type==="text"?l[l.length-1]={type:"text",text:i.text+t.text}:l.push({type:"text",text:t.text})}else l.push({type:"entity",entity:t.entity});return l}function te(n,l){let t="";for(const i of n)i.type==="text"?t+=i.text:t+=i.entity.promptText??i.entity.label;return t}function he(n){return n.filter(l=>l.type==="entity").map(l=>l.entity)}function ne(n){return n.every(l=>l.type==="text"&&l.text.length===0)}const C="\u200B",pe="data-kai-entity",fe=new WeakMap;function U(n){return!!n&&n.nodeType===1&&n.hasAttribute(pe)}function re(n){return n.ownerDocument.createTreeWalker(n,NodeFilter.SHOW_TEXT,{acceptNode(l){let t=l.parentElement;for(;t&&t!==n;){if(t.hasAttribute(pe))return NodeFilter.FILTER_REJECT;t=t.parentElement}return NodeFilter.FILTER_ACCEPT}})}function ot(n){switch(n){case"skill":return"/";case"agent":return"@";default:return""}}function Le(n){const l=t=>`<svg viewBox="0 0 24 24" width="1em" height="1em" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${t}</svg>`;switch(n){case"agent":return l('<rect x="4" y="8" width="16" height="12" rx="3"/><path d="M12 4.5V8M9.5 13.5v1.5M14.5 13.5v1.5"/><circle cx="12" cy="3" r="1.2"/>');case"plugin":return l('<path d="M9 2v4M15 2v4M6 6h12v5a6 6 0 0 1-12 0zM12 17v5"/>');default:return""}}function Ie(n,l,t){const i=n.createElement("span");i.setAttribute(pe,""),i.setAttribute("contenteditable","false"),i.dataset.kind=l.kind,i.dataset.id=l.id,i.className="kai-composer-pill";const u=ot(l.kind);if(u){const s=n.createElement("span");s.className="kai-composer-pill-sigil",s.setAttribute("aria-hidden","true"),s.textContent=u,i.appendChild(s)}else{const s=l.icon??t?.[l.kind];if(s){const h=n.createElement("img");h.src=s,h.alt="",h.className="kai-composer-pill-icon",i.appendChild(h)}else{const h=Le(l.kind);if(h){const f=n.createElement("span");f.className="kai-composer-pill-icon kai-composer-pill-glyph",f.setAttribute("aria-hidden","true"),f.innerHTML=h,i.appendChild(f)}}}return i.appendChild(n.createTextNode(l.label)),fe.set(i,l),i}function L(n){const l=[],t=n.childNodes;return t.forEach((i,u)=>{if(U(i)){const s=fe.get(i),h=i;l.push({type:"entity",entity:s??{kind:h.dataset.kind??"",id:h.dataset.id??"",label:h.textContent??""}})}else if(i.nodeType===1&&i.tagName==="BR"){if(u===t.length-1)return;l.push({type:"text",text:`
1
+ import{A as Ye,g as z,w as Je,k as Q,j as de,o as ue,x as De,h as Qe,i as N,u as Ne,a as H,d as O,b as Z,l as ee,c as $,F as Oe,S as G,t as S,Q as Ze,e as et}from"./define-CI0y3eE4.js";import{c as P}from"./cn-DN5AWfiS.js";import{u as tt,c as nt,a as rt}from"./overlay-DBMFXie6.js";function M(n){if(n==null)return[];if(typeof n=="string")return n.length?[{type:"text",text:n}]:[];const l=[];for(const t of n)if(t.type==="text"){if(!t.text)continue;const i=l[l.length-1];i&&i.type==="text"?l[l.length-1]={type:"text",text:i.text+t.text}:l.push({type:"text",text:t.text})}else l.push({type:"entity",entity:t.entity});return l}function te(n,l){let t="";for(const i of n)i.type==="text"?t+=i.text:t+=i.entity.promptText??i.entity.label;return t}function he(n){return n.filter(l=>l.type==="entity").map(l=>l.entity)}function ne(n){return n.every(l=>l.type==="text"&&l.text.length===0)}const C="\u200B",pe="data-kai-entity",fe=new WeakMap;function U(n){return!!n&&n.nodeType===1&&n.hasAttribute(pe)}function re(n){return n.ownerDocument.createTreeWalker(n,NodeFilter.SHOW_TEXT,{acceptNode(l){let t=l.parentElement;for(;t&&t!==n;){if(t.hasAttribute(pe))return NodeFilter.FILTER_REJECT;t=t.parentElement}return NodeFilter.FILTER_ACCEPT}})}function ot(n){switch(n){case"skill":return"/";case"agent":return"@";default:return""}}function Le(n){const l=t=>`<svg viewBox="0 0 24 24" width="1em" height="1em" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${t}</svg>`;switch(n){case"agent":return l('<rect x="4" y="8" width="16" height="12" rx="3"/><path d="M12 4.5V8M9.5 13.5v1.5M14.5 13.5v1.5"/><circle cx="12" cy="3" r="1.2"/>');case"plugin":return l('<path d="M9 2v4M15 2v4M6 6h12v5a6 6 0 0 1-12 0zM12 17v5"/>');default:return""}}function Ie(n,l,t){const i=n.createElement("span");i.setAttribute(pe,""),i.setAttribute("contenteditable","false"),i.dataset.kind=l.kind,i.dataset.id=l.id,i.className="kai-composer-pill";const u=ot(l.kind);if(u){const s=n.createElement("span");s.className="kai-composer-pill-sigil",s.setAttribute("aria-hidden","true"),s.textContent=u,i.appendChild(s)}else{const s=l.icon??t?.[l.kind];if(s){const h=n.createElement("img");h.src=s,h.alt="",h.className="kai-composer-pill-icon",i.appendChild(h)}else{const h=Le(l.kind);if(h){const f=n.createElement("span");f.className="kai-composer-pill-icon kai-composer-pill-glyph",f.setAttribute("aria-hidden","true"),f.innerHTML=h,i.appendChild(f)}}}return i.appendChild(n.createTextNode(l.label)),fe.set(i,l),i}function L(n){const l=[],t=n.childNodes;return t.forEach((i,u)=>{if(U(i)){const s=fe.get(i),h=i;l.push({type:"entity",entity:s??{kind:h.dataset.kind??"",id:h.dataset.id??"",label:h.textContent??""}})}else if(i.nodeType===1&&i.tagName==="BR"){if(u===t.length-1)return;l.push({type:"text",text:`
2
2
  `})}else i.nodeType===3&&l.push({type:"text",text:(i.textContent??"").split(C).join("")})}),M(l)}function oe(n,l,t=document,i){n.textContent="";for(const u of l)u.type==="text"?n.appendChild(t.createTextNode(u.text)):(n.appendChild(Ie(t,u.entity,i)),n.appendChild(t.createTextNode(C)))}function it(n,l,t){if(l<0||l>n.length)return null;for(let i=l-1;i>=0;i--){const u=n[i];if(/\s/.test(u))return null;if(t.includes(u))return i===0||/\s/.test(n[i-1])?{char:u,query:n.slice(i+1,l),start:i}:null}return null}function at(n,l,t){if(!t.length)return null;const i=t.map(h=>h.char),u=it(n,l,i);if(!u)return null;const s=t.find(h=>h.char===u.char);return s?{def:s,query:u.query,start:u.start}:null}function lt(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function st(n,l){const t=[];for(const s of l){let h,f;typeof s=="string"?(h=new RegExp(lt(s),"gi"),f=void 0):(h=new RegExp(s.pattern,s.flags??"gi"),f=s.class),h.lastIndex=0;let k;for(;(k=h.exec(n))!==null;){const x=k.index,w=x+k[0].length;if(w===x){h.lastIndex=x+1;continue}t.push({start:x,end:w,class:f})}}t.sort((s,h)=>s.start-h.start);const i=[];let u=-1;for(const s of t)s.start>=u&&(i.push(s),u=s.end);return i}function ct(){try{return typeof CSS<"u"&&typeof CSS.highlights<"u"&&typeof Highlight<"u"}catch{return!1}}const dt="kai-composer-highlight";function ut(n,l,t,i=dt){if(!ct())return;const u=CSS.highlights;if(l.length===0){u.delete(i);return}const s=[];let h=0;const f=n.ownerDocument,k=re(n);let x=k.nextNode();for(;x;){const v=x.textContent??"",b=[];for(let p=0;p<v.length;p++)v[p]!==t&&b.push(p);if(b.length>0){const p=new Int32Array(b.length);for(let m=0;m<b.length;m++)p[m]=b[m];s.push({node:x,strippedStart:h,strippedToRaw:p}),h+=b.length}x=k.nextNode()}function w(v){let b=0,p=s.length-1;for(;b<=p;){const m=b+p>>1,T=s[m],q=T.strippedStart+T.strippedToRaw.length;if(v<T.strippedStart)p=m-1;else if(v>=q)b=m+1;else{const R=v-T.strippedStart;return{node:T.node,rawOffset:T.strippedToRaw[R]}}}if(s.length>0){const m=s[s.length-1];if(v-m.strippedStart===m.strippedToRaw.length)return{node:m.node,rawOffset:m.strippedToRaw[m.strippedToRaw.length-1]+1}}return null}const y=[];for(const v of l){const b=w(v.start),p=w(v.end);if(!b||!p)continue;const m=f.createRange();m.setStart(b.node,b.rawOffset),m.setEnd(p.node,p.rawOffset),y.push(m)}if(y.length===0){u.delete(i);return}const A=new Highlight(...y);u.set(i,A)}function ht(n,l=200){let t=[n],i=0;return{record(u,s){if(s&&i===t.length-1){t[i]=u;return}t=t.slice(0,i+1),t.push(u),t.length>l?t.shift():i++},undo(){return i===0?null:(i--,t[i])},redo(){return i>=t.length-1?null:(i++,t[i])},reset(u){t=[u],i=0},canUndo(){return i>0},canRedo(){return i<t.length-1},size(){return t.length}}}var pt=S("<style>"),ft=S(`<style>
3
3
  .kai-composer-pill {
4
4
  display: inline-flex; align-items: center; gap: 0.2rem;