@keboola/design 11.2.0 → 11.4.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 (249) hide show
  1. package/AGENTS.md +42 -14
  2. package/CHANGELOG.md +424 -0
  3. package/COMPONENT-API.md +33 -32
  4. package/dist/{AIKit-DiS0CVOW.js → AIKit-DDg5DBCG.js} +156 -76
  5. package/dist/AIKit-DDg5DBCG.js.map +1 -0
  6. package/dist/{Alert-DfZq9kGe.js → Alert-DHJFrWnS.js} +3 -3
  7. package/dist/{Alert-DfZq9kGe.js.map → Alert-DHJFrWnS.js.map} +1 -1
  8. package/dist/{AlertModal-Dp_XuJBW.js → AlertModal-BGJdaRRj.js} +3 -3
  9. package/dist/{AlertModal-Dp_XuJBW.js.map → AlertModal-BGJdaRRj.js.map} +1 -1
  10. package/dist/{AppShell-B5GQN6Zs.js → AppShell-DRgJxpXW.js} +29 -10
  11. package/dist/AppShell-DRgJxpXW.js.map +1 -0
  12. package/dist/{BrandEditor-DyzgfVkl.js → BrandEditor-Go7w8Zj2.js} +7 -7
  13. package/dist/{BrandEditor-DyzgfVkl.js.map → BrandEditor-Go7w8Zj2.js.map} +1 -1
  14. package/dist/{BrandLogo-CJkRd0F8.js → BrandLogo-Dmi7jo21.js} +2 -2
  15. package/dist/{BrandLogo-CJkRd0F8.js.map → BrandLogo-Dmi7jo21.js.map} +1 -1
  16. package/dist/{Breadcrumb-Frst8MTA.js → Breadcrumb-uEkM6adI.js} +3 -3
  17. package/dist/{Breadcrumb-Frst8MTA.js.map → Breadcrumb-uEkM6adI.js.map} +1 -1
  18. package/dist/{Button-6xBX0nNl.js → Button-DsRrU5F1.js} +6 -5
  19. package/dist/Button-DsRrU5F1.js.map +1 -0
  20. package/dist/{Card-BAoZ35CV.js → Card-Dyo7055Q.js} +2 -2
  21. package/dist/{Card-BAoZ35CV.js.map → Card-Dyo7055Q.js.map} +1 -1
  22. package/dist/{Checkbox-GJ8-srt4.js → Checkbox-fC0BuO2B.js} +3 -3
  23. package/dist/{Checkbox-GJ8-srt4.js.map → Checkbox-fC0BuO2B.js.map} +1 -1
  24. package/dist/{Clipboard-CBJZiviP.js → Clipboard-ChPdiUy3.js} +2 -2
  25. package/dist/{Clipboard-CBJZiviP.js.map → Clipboard-ChPdiUy3.js.map} +1 -1
  26. package/dist/{ClipboardButton-ClcluT0C.js → ClipboardButton-D9pDjgkB.js} +3 -3
  27. package/dist/{ClipboardButton-ClcluT0C.js.map → ClipboardButton-D9pDjgkB.js.map} +1 -1
  28. package/dist/{CodeEditor-DyaN-Ij2.js → CodeEditor-Cxy3HnKH.js} +244 -113
  29. package/dist/CodeEditor-Cxy3HnKH.js.map +1 -0
  30. package/dist/{ColorInput-B8z4j4Y_.js → ColorInput-Bxj-1eLT.js} +3 -3
  31. package/dist/{ColorInput-B8z4j4Y_.js.map → ColorInput-Bxj-1eLT.js.map} +1 -1
  32. package/dist/{ColorModeSwitch-dZFZyqy1.js → ColorModeSwitch-CsWLiTBX.js} +3 -3
  33. package/dist/{ColorModeSwitch-dZFZyqy1.js.map → ColorModeSwitch-CsWLiTBX.js.map} +1 -1
  34. package/dist/{Combobox-Dgm6Z4ib.js → Combobox-Cs_1pj2q.js} +31 -24
  35. package/dist/Combobox-Cs_1pj2q.js.map +1 -0
  36. package/dist/{Command-C0aZfVTq.js → Command-B7ML9YMv.js} +6 -6
  37. package/dist/{Command-C0aZfVTq.js.map → Command-B7ML9YMv.js.map} +1 -1
  38. package/dist/{CopyField-BJ96zvXs.js → CopyField-BO_sh-HO.js} +2 -2
  39. package/dist/{CopyField-BJ96zvXs.js.map → CopyField-BO_sh-HO.js.map} +1 -1
  40. package/dist/{DateInput-B3UdzRfW.js → DateInput-ZdaMQo5i.js} +4 -4
  41. package/dist/{DateInput-B3UdzRfW.js.map → DateInput-ZdaMQo5i.js.map} +1 -1
  42. package/dist/{DatePicker-Dw3DpbUh.js → DatePicker-nA8YdE84.js} +2 -2
  43. package/dist/{DatePicker-Dw3DpbUh.js.map → DatePicker-nA8YdE84.js.map} +1 -1
  44. package/dist/{DateRangeInput-DTuySEiq.js → DateRangeInput-DkvNh_sT.js} +4 -4
  45. package/dist/{DateRangeInput-DTuySEiq.js.map → DateRangeInput-DkvNh_sT.js.map} +1 -1
  46. package/dist/{DateRangePicker-DCmMHg4s.js → DateRangePicker-DjSUFjh4.js} +6 -6
  47. package/dist/{DateRangePicker-DCmMHg4s.js.map → DateRangePicker-DjSUFjh4.js.map} +1 -1
  48. package/dist/{DropdownMenu-t90tVw6l.js → DropdownMenu-CASr-jgl.js} +2 -2
  49. package/dist/{DropdownMenu-t90tVw6l.js.map → DropdownMenu-CASr-jgl.js.map} +1 -1
  50. package/dist/{FieldItem-D-h1NeBo.js → FieldItem-CCd9-xnp.js} +3 -3
  51. package/dist/{FieldItem-D-h1NeBo.js.map → FieldItem-CCd9-xnp.js.map} +1 -1
  52. package/dist/{FieldItem-CAPj9lj3.d.ts → FieldItem-vhIJW4pj.d.ts} +2 -10
  53. package/dist/{FileUpload-BRv0TaZk.js → FileUpload-ABThVZyg.js} +2 -2
  54. package/dist/{FileUpload-BRv0TaZk.js.map → FileUpload-ABThVZyg.js.map} +1 -1
  55. package/dist/{Form-DHvcFoEi.js → Form-k6PH-em3.js} +8 -8
  56. package/dist/{Form-DHvcFoEi.js.map → Form-k6PH-em3.js.map} +1 -1
  57. package/dist/{FormGroup-C41n65cE.js → FormGroup-DbcDtrgU.js} +3 -3
  58. package/dist/{FormGroup-C41n65cE.js.map → FormGroup-DbcDtrgU.js.map} +1 -1
  59. package/dist/{FullScreenModal-Cb3PGgh4.js → FullScreenModal-BvPuYibe.js} +3 -3
  60. package/dist/{FullScreenModal-Cb3PGgh4.js.map → FullScreenModal-BvPuYibe.js.map} +1 -1
  61. package/dist/{HoverCard-WfDkLK1s.js → HoverCard-B9ZMJxjn.js} +2 -2
  62. package/dist/{HoverCard-WfDkLK1s.js.map → HoverCard-B9ZMJxjn.js.map} +1 -1
  63. package/dist/{InputGroup-CdTq8H7c.js → InputGroup-BnLHY0eq.js} +3 -3
  64. package/dist/{InputGroup-CdTq8H7c.js.map → InputGroup-BnLHY0eq.js.map} +1 -1
  65. package/dist/{Kbd-CxHAo1oo.js → Kbd-CvSM3D3-.js} +2 -2
  66. package/dist/{Kbd-CxHAo1oo.js.map → Kbd-CvSM3D3-.js.map} +1 -1
  67. package/dist/MarkedText-DNGEUVWc.js +67 -0
  68. package/dist/MarkedText-DNGEUVWc.js.map +1 -0
  69. package/dist/{MermaidDiagram-ChL3WIQT.js → MermaidDiagram-WkonYErO.js} +6 -87
  70. package/dist/MermaidDiagram-WkonYErO.js.map +1 -0
  71. package/dist/{Modal-wqG8nJiK.js → Modal-Coj-H02o.js} +16 -4
  72. package/dist/Modal-Coj-H02o.js.map +1 -0
  73. package/dist/{MultiActionButtonGroup-BiIIubiL.js → MultiActionButtonGroup-CxWH7yWK.js} +3 -3
  74. package/dist/{MultiActionButtonGroup-BiIIubiL.js.map → MultiActionButtonGroup-CxWH7yWK.js.map} +1 -1
  75. package/dist/{Navbar-BfaPeLUL.js → Navbar-B2UsolVU.js} +3 -3
  76. package/dist/{Navbar-BfaPeLUL.js.map → Navbar-B2UsolVU.js.map} +1 -1
  77. package/dist/{PageToolbar-OQg3mPF-.js → PageToolbar-DnbFt14Q.js} +3 -3
  78. package/dist/{PageToolbar-OQg3mPF-.js.map → PageToolbar-DnbFt14Q.js.map} +1 -1
  79. package/dist/{Pagination-Cjfda8KG.js → Pagination-C_b7Xhey.js} +2 -2
  80. package/dist/{Pagination-Cjfda8KG.js.map → Pagination-C_b7Xhey.js.map} +1 -1
  81. package/dist/{Popconfirm-D7_vfxFd.js → Popconfirm-CILjmzKI.js} +3 -3
  82. package/dist/{Popconfirm-D7_vfxFd.js.map → Popconfirm-CILjmzKI.js.map} +1 -1
  83. package/dist/{Popover-CzeHjvrB.js → Popover-BEbQrC_P.js} +22 -19
  84. package/dist/Popover-BEbQrC_P.js.map +1 -0
  85. package/dist/{RadioGroup-sIveSsNa.js → RadioGroup-XFzFd1ti.js} +3 -3
  86. package/dist/{RadioGroup-sIveSsNa.js.map → RadioGroup-XFzFd1ti.js.map} +1 -1
  87. package/dist/{Search-3UiqNZRj.js → Search-4Bxtt8hS.js} +2 -2
  88. package/dist/{Search-3UiqNZRj.js.map → Search-4Bxtt8hS.js.map} +1 -1
  89. package/dist/{SearchInput-C7dF_Ir-.js → SearchInput-f_oY9T4Z.js} +3 -3
  90. package/dist/{SearchInput-C7dF_Ir-.js.map → SearchInput-f_oY9T4Z.js.map} +1 -1
  91. package/dist/{SectionNav-8NoTOKO8.js → SectionNav-BpJlisbT.js} +4 -4
  92. package/dist/{SectionNav-8NoTOKO8.js.map → SectionNav-BpJlisbT.js.map} +1 -1
  93. package/dist/{Select-Is0VkePH.js → Select-DpcgKqKB.js} +32 -21
  94. package/dist/Select-DpcgKqKB.js.map +1 -0
  95. package/dist/{Sheet-Dw9BDvjI.js → Sheet-Chf0kX1E.js} +3 -3
  96. package/dist/{Sheet-Dw9BDvjI.js.map → Sheet-Chf0kX1E.js.map} +1 -1
  97. package/dist/{Sidebar-Dcb4rinA.js → Sidebar-Cm6I4dE1.js} +9 -7
  98. package/dist/{Sidebar-Dcb4rinA.js.map → Sidebar-Cm6I4dE1.js.map} +1 -1
  99. package/dist/{Slider-BOPfMOMm.js → Slider-pPC_3gz9.js} +3 -3
  100. package/dist/{Slider-BOPfMOMm.js.map → Slider-pPC_3gz9.js.map} +1 -1
  101. package/dist/{Switch-CX2A0v50.js → Switch-ChfPKcTE.js} +2 -2
  102. package/dist/{Switch-CX2A0v50.js.map → Switch-ChfPKcTE.js.map} +1 -1
  103. package/dist/{Tabs-UMQuDoW8.js → Tabs-eB974xJf.js} +2 -2
  104. package/dist/{Tabs-UMQuDoW8.js.map → Tabs-eB974xJf.js.map} +1 -1
  105. package/dist/{TextInput-CMuN1WfY.js → TextInput-DHM6dHmn.js} +3 -3
  106. package/dist/{TextInput-CMuN1WfY.js.map → TextInput-DHM6dHmn.js.map} +1 -1
  107. package/dist/{ThemeProvider-QncUrfJn.js → ThemeProvider-DrQJtzpd.js} +90 -14
  108. package/dist/ThemeProvider-DrQJtzpd.js.map +1 -0
  109. package/dist/{TimePicker-D9zktB8A.js → TimePicker-BGeqc-Ed.js} +2 -2
  110. package/dist/{TimePicker-D9zktB8A.js.map → TimePicker-BGeqc-Ed.js.map} +1 -1
  111. package/dist/{Toast-DQSbs3oA.js → Toast-Dr6Uw7ao.js} +2 -2
  112. package/dist/{Toast-DQSbs3oA.js.map → Toast-Dr6Uw7ao.js.map} +1 -1
  113. package/dist/{ZoomableSvg-CZEu6sAq.js → ZoomableSvg-BWnDkR61.js} +4 -4
  114. package/dist/{ZoomableSvg-CZEu6sAq.js.map → ZoomableSvg-BWnDkR61.js.map} +1 -1
  115. package/dist/{context-KxxeMHbR.js → context-D7X470dy.js} +5 -34
  116. package/dist/context-D7X470dy.js.map +1 -0
  117. package/dist/defaults-i_xG2F_1.js +32 -0
  118. package/dist/defaults-i_xG2F_1.js.map +1 -0
  119. package/dist/editors.d.ts +12 -2
  120. package/dist/editors.js +20 -12
  121. package/dist/editors.js.map +1 -1
  122. package/dist/findLiteralMatches-BGBw8Vbl.js +62 -0
  123. package/dist/findLiteralMatches-BGBw8Vbl.js.map +1 -0
  124. package/dist/flint.d.ts +15 -0
  125. package/dist/flint.js +212 -0
  126. package/dist/flint.js.map +1 -0
  127. package/dist/index.d.ts +725 -533
  128. package/dist/index.js +60 -57
  129. package/dist/internal/blocks/AIKit.js +2 -2
  130. package/dist/internal/blocks/AppShell.js +2 -2
  131. package/dist/internal/blocks/BrandEditor.js +1 -1
  132. package/dist/internal/blocks/ChartPanel.js +1 -1
  133. package/dist/internal/blocks/ClipboardButton.js +1 -1
  134. package/dist/internal/blocks/ColorInput.js +1 -1
  135. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  136. package/dist/internal/blocks/Command.js +1 -1
  137. package/dist/internal/blocks/CopyField.js +1 -1
  138. package/dist/internal/blocks/DateInput.js +1 -1
  139. package/dist/internal/blocks/DateRangeInput.js +1 -1
  140. package/dist/{DiagramSkeleton-lwBS2YBa.js → internal/blocks/DiagramShared/DiagramSkeleton.js} +3 -3
  141. package/dist/internal/blocks/DiagramShared/DiagramSkeleton.js.map +1 -0
  142. package/dist/internal/blocks/EmptyConfigurationActionCard.js +1 -1
  143. package/dist/internal/blocks/ErrorState.js +1 -1
  144. package/dist/internal/blocks/ExportMenu.js +5 -5
  145. package/dist/internal/blocks/ExportMenu.js.map +1 -1
  146. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
  147. package/dist/internal/blocks/Form.js +1 -1
  148. package/dist/internal/blocks/FormGroup.js +1 -1
  149. package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
  150. package/dist/internal/blocks/MultiCombobox.js +15 -11
  151. package/dist/internal/blocks/MultiCombobox.js.map +1 -1
  152. package/dist/internal/blocks/NumberInput.js +1 -1
  153. package/dist/internal/blocks/PageToolbar.js +1 -1
  154. package/dist/internal/blocks/PasswordInput.js +2 -2
  155. package/dist/internal/blocks/SearchInput.js +1 -1
  156. package/dist/internal/blocks/SearchInputWithNavigation.js +3 -3
  157. package/dist/internal/blocks/SectionNav.js +1 -1
  158. package/dist/internal/blocks/SplitButton.js +2 -2
  159. package/dist/internal/blocks/StatCard.js +1 -1
  160. package/dist/internal/blocks/TextInput.js +1 -1
  161. package/dist/internal/blocks/Textarea.js +1 -1
  162. package/dist/internal/blocks/TimeInput.js +3 -3
  163. package/dist/internal/components/Alert.js +1 -1
  164. package/dist/internal/components/AlertModal.js +1 -1
  165. package/dist/internal/components/Avatar.js +1 -1
  166. package/dist/internal/components/BrandLogo.js +1 -1
  167. package/dist/internal/components/Breadcrumb.js +1 -1
  168. package/dist/internal/components/Button.js +1 -1
  169. package/dist/internal/components/Card.js +1 -1
  170. package/dist/internal/components/Checkbox.js +1 -1
  171. package/dist/internal/components/Clipboard.js +1 -1
  172. package/dist/internal/components/CollapsiblePanel.js +1 -1
  173. package/dist/internal/components/Combobox.js +1 -1
  174. package/dist/internal/components/DatePicker.js +1 -1
  175. package/dist/internal/components/DateRangePicker.js +1 -1
  176. package/dist/internal/components/DropdownMenu.js +1 -1
  177. package/dist/internal/components/FileUpload.js +1 -1
  178. package/dist/internal/components/FullScreenModal.js +1 -1
  179. package/dist/internal/components/HoverCard.js +1 -1
  180. package/dist/internal/components/InputGroup.js +1 -1
  181. package/dist/internal/components/Kbd.js +1 -1
  182. package/dist/internal/components/MarkedText.js +1 -1
  183. package/dist/internal/components/Modal.js +1 -1
  184. package/dist/internal/components/Navbar.js +1 -1
  185. package/dist/internal/components/Pagination.js +1 -1
  186. package/dist/internal/components/Popconfirm.js +1 -1
  187. package/dist/internal/components/Popover.js +1 -1
  188. package/dist/internal/components/RadioGroup.js +1 -1
  189. package/dist/internal/components/Search.js +1 -1
  190. package/dist/internal/components/Select.js +1 -1
  191. package/dist/internal/components/Sheet.js +1 -1
  192. package/dist/internal/components/Sidebar.js +1 -1
  193. package/dist/internal/components/Slider.js +1 -1
  194. package/dist/internal/components/Switch.js +1 -1
  195. package/dist/internal/components/Tabs.js +1 -1
  196. package/dist/internal/components/ThemeProvider.js +4 -3
  197. package/dist/internal/components/TimePicker.js +1 -1
  198. package/dist/internal/components/Toast.js +2 -2
  199. package/dist/internal/components/Toggle.js +3 -3
  200. package/dist/internal/components/Toggle.js.map +1 -1
  201. package/dist/internal/components/Tooltip.js +1 -1
  202. package/dist/internal/components/Truncated.js +16 -8
  203. package/dist/internal/components/Truncated.js.map +1 -1
  204. package/dist/internal/components/ZoomableSvg.js +1 -1
  205. package/dist/internal/utils.js +3 -3
  206. package/dist/markdown-editor.js +7 -7
  207. package/dist/mermaid.js +1 -1
  208. package/dist/rjsf.js +11 -11
  209. package/dist/{styles-DSUP_-9Z.js → styles-BAFscjSV.js} +4 -3
  210. package/dist/styles-BAFscjSV.js.map +1 -0
  211. package/dist/styles.css +1 -1
  212. package/dist/svgTransforms-C9njt92h.js +89 -0
  213. package/dist/svgTransforms-C9njt92h.js.map +1 -0
  214. package/dist/testing.js +4 -3
  215. package/dist/testing.js.map +1 -1
  216. package/dist/{themeTokens-BNg98Mu9.js → themeTokens-D70HeNVF.js} +13 -6
  217. package/dist/{themeTokens-BNg98Mu9.js.map → themeTokens-D70HeNVF.js.map} +1 -1
  218. package/dist/{toast-CjkURw0M.js → toast-DIC0iNRf.js} +3 -3
  219. package/dist/toast-DIC0iNRf.js.map +1 -0
  220. package/dist/types-BPcAjMG0.d.ts +10 -0
  221. package/dist/{useColorSchemeState-CYqcUfSH.js → useColorSchemeState-klihG9-i.js} +2 -2
  222. package/dist/{useColorSchemeState-CYqcUfSH.js.map → useColorSchemeState-klihG9-i.js.map} +1 -1
  223. package/dist/{utils-D0c5VAyF.js → utils-B5Z52hYs.js} +2 -2
  224. package/dist/{utils-D0c5VAyF.js.map → utils-B5Z52hYs.js.map} +1 -1
  225. package/dist/vega.d.ts +46 -0
  226. package/dist/vega.js +26 -0
  227. package/dist/vega.js.map +1 -0
  228. package/dist/vegaTheme-DfoEQhOy.js +146 -0
  229. package/dist/vegaTheme-DfoEQhOy.js.map +1 -0
  230. package/package.json +28 -9
  231. package/src/styles.css +27 -4
  232. package/dist/AIKit-DiS0CVOW.js.map +0 -1
  233. package/dist/AppShell-B5GQN6Zs.js.map +0 -1
  234. package/dist/Button-6xBX0nNl.js.map +0 -1
  235. package/dist/CodeEditor-DyaN-Ij2.js.map +0 -1
  236. package/dist/Combobox-Dgm6Z4ib.js.map +0 -1
  237. package/dist/DiagramSkeleton-lwBS2YBa.js.map +0 -1
  238. package/dist/MarkedText-Ckbft5mw.js +0 -44
  239. package/dist/MarkedText-Ckbft5mw.js.map +0 -1
  240. package/dist/MermaidDiagram-ChL3WIQT.js.map +0 -1
  241. package/dist/Modal-wqG8nJiK.js.map +0 -1
  242. package/dist/Popover-CzeHjvrB.js.map +0 -1
  243. package/dist/Select-Is0VkePH.js.map +0 -1
  244. package/dist/ThemeProvider-QncUrfJn.js.map +0 -1
  245. package/dist/context-KxxeMHbR.js.map +0 -1
  246. package/dist/escapeStringRegexp-8MxP2knR.js +0 -6
  247. package/dist/escapeStringRegexp-8MxP2knR.js.map +0 -1
  248. package/dist/styles-DSUP_-9Z.js.map +0 -1
  249. package/dist/toast-CjkURw0M.js.map +0 -1
@@ -0,0 +1,146 @@
1
+ import { createChannelResolver } from "./themeTokens-D70HeNVF.js";
2
+ //#region src/vega/vegaTokens.ts
3
+ /**
4
+ * Serializes `"R G B"` channels comma-separated, the only form vega parses.
5
+ *
6
+ * - vega reads colours through d3-color 3.1, which answers `null` for the
7
+ * space-separated CSS Color 4 form the rest of the package emits.
8
+ * - A flat fill survives that anyway — the string reaches the SVG attribute and
9
+ * the browser parses it. An interpolated one does not: both endpoints of a
10
+ * sequential ramp collapse, and a quantitative scale paints solid black.
11
+ */
12
+ const vegaRgb = (channels, alpha) => {
13
+ const c = channels.split(/\s+/).join(", ");
14
+ return alpha === void 0 ? `rgb(${c})` : `rgba(${c}, ${alpha})`;
15
+ };
16
+ /** The `--chart-*` slots, in series order. */
17
+ const SERIES_TOKENS = [
18
+ "chart-1",
19
+ "chart-2",
20
+ "chart-3",
21
+ "chart-4",
22
+ "chart-5"
23
+ ];
24
+ /**
25
+ * Fallback channels for the tokens a vega chart reads, mirroring the `:root` /
26
+ * `[data-theme='dark']` blocks of `styles.css`. The resolver reaches these only
27
+ * when the live custom property is missing — SSR, or a unit test that loads no
28
+ * CSS.
29
+ */
30
+ const FALLBACK_CHANNELS = {
31
+ foreground: {
32
+ light: "30 41 59",
33
+ dark: "229 230 236"
34
+ },
35
+ "muted-foreground": {
36
+ light: "100 116 139",
37
+ dark: "141 144 153"
38
+ },
39
+ border: {
40
+ light: "229 231 235",
41
+ dark: "52 53 62"
42
+ },
43
+ "chart-1": {
44
+ light: "31 143 255",
45
+ dark: "92 173 255"
46
+ },
47
+ "chart-2": {
48
+ light: "0 194 135",
49
+ dark: "0 230 161"
50
+ },
51
+ "chart-3": {
52
+ light: "146 92 255",
53
+ dark: "173 133 255"
54
+ },
55
+ "chart-4": {
56
+ light: "245 147 0",
57
+ dark: "255 190 92"
58
+ },
59
+ "chart-5": {
60
+ light: "237 94 223",
61
+ dark: "242 140 232"
62
+ },
63
+ accent: {
64
+ light: "224 242 254",
65
+ dark: "30 58 95"
66
+ },
67
+ card: {
68
+ light: "255 255 255",
69
+ dark: "34 34 40"
70
+ }
71
+ };
72
+ /**
73
+ * A vega-serializing token resolver bound to one `getComputedStyle` snapshot.
74
+ *
75
+ * - Answers `rgb(R, G, B)` / `rgba(R, G, B, a)` — see {@link vegaRgb}.
76
+ * - Falls back per scheme when the custom property is not painted.
77
+ * - Build one per palette, never at module level: the values change whenever
78
+ * the scheme or the brand does.
79
+ */
80
+ const createVegaColorResolver = (scheme) => {
81
+ const resolve = createChannelResolver();
82
+ return (token, alpha) => vegaRgb(resolve(token, FALLBACK_CHANNELS[token][scheme]), alpha);
83
+ };
84
+ //#endregion
85
+ //#region src/vega/vegaTheme.ts
86
+ const CHART_FONT = "Inter, system-ui, sans-serif";
87
+ /**
88
+ * Scheme-following Vega-Lite config — the design system's chart look as a plain
89
+ * `Config`, for any consumer that compiles or renders a Vega-Lite spec.
90
+ *
91
+ * - `background: 'transparent'` drops vega's opaque white backdrop, so the page
92
+ * surface shows through in both schemes.
93
+ * - Axis/legend/header/title text and lines read the live semantic tokens, so a
94
+ * dark scheme (and a customer brand) recolour the chart chrome for free.
95
+ * - `range.category` is `--chart-1..5` in series order — the same decorative
96
+ * palette the recharts wrappers in `@keboola/design/charts` use — so a
97
+ * categorical encoding matches the rest of the platform's data-viz instead of
98
+ * falling back to vega's `tableau10`.
99
+ * - `range.ramp` puts the low end of a quantitative scale on `--accent` rather
100
+ * than vega's blue-only default, which keeps the pale end legible on a dark
101
+ * surface.
102
+ * - A range set on the spec's own scale still wins, which is how a Flint chart
103
+ * keeps the series colours it resolves during assembly.
104
+ * - Colours are resolved to concrete `rgb(R, G, B)` strings, not `var()`
105
+ * references: vega does its colour maths in JS and never consults the
106
+ * stylesheet. Rebuild the config when the scheme or brand changes —
107
+ * `useVegaTheme` does that for you.
108
+ */
109
+ const vegaTheme = (scheme) => {
110
+ const token = createVegaColorResolver(scheme);
111
+ const label = token("muted-foreground");
112
+ const heading = token("foreground");
113
+ const line = token("border");
114
+ return {
115
+ background: "transparent",
116
+ font: CHART_FONT,
117
+ axis: {
118
+ labelColor: label,
119
+ titleColor: heading,
120
+ gridColor: token("border", .6),
121
+ domainColor: line,
122
+ tickColor: line
123
+ },
124
+ legend: {
125
+ labelColor: label,
126
+ titleColor: heading
127
+ },
128
+ header: {
129
+ labelColor: label,
130
+ titleColor: heading
131
+ },
132
+ title: {
133
+ color: heading,
134
+ subtitleColor: label
135
+ },
136
+ text: { color: heading },
137
+ range: {
138
+ category: SERIES_TOKENS.map((name) => token(name)),
139
+ ramp: [token("accent"), token("chart-1")]
140
+ }
141
+ };
142
+ };
143
+ //#endregion
144
+ export { SERIES_TOKENS, createVegaColorResolver, vegaRgb, vegaTheme };
145
+
146
+ //# sourceMappingURL=vegaTheme-DfoEQhOy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vegaTheme-DfoEQhOy.js","names":[],"sources":["../src/vega/vegaTokens.ts","../src/vega/vegaTheme.ts"],"sourcesContent":["import type { ResolvedColorScheme } from '../components/ThemeProvider/types';\nimport { createChannelResolver } from '../utils/themeTokens';\n\n/**\n * Serializes `\"R G B\"` channels comma-separated, the only form vega parses.\n *\n * - vega reads colours through d3-color 3.1, which answers `null` for the\n * space-separated CSS Color 4 form the rest of the package emits.\n * - A flat fill survives that anyway — the string reaches the SVG attribute and\n * the browser parses it. An interpolated one does not: both endpoints of a\n * sequential ramp collapse, and a quantitative scale paints solid black.\n */\nexport const vegaRgb = (channels: string, alpha?: number): string => {\n const c = channels.split(/\\s+/).join(', ');\n return alpha === undefined ? `rgb(${c})` : `rgba(${c}, ${alpha})`;\n};\n\n/** The `--chart-*` slots, in series order. */\nexport const SERIES_TOKENS = ['chart-1', 'chart-2', 'chart-3', 'chart-4', 'chart-5'] as const;\n\n/**\n * Fallback channels for the tokens a vega chart reads, mirroring the `:root` /\n * `[data-theme='dark']` blocks of `styles.css`. The resolver reaches these only\n * when the live custom property is missing — SSR, or a unit test that loads no\n * CSS.\n */\nconst FALLBACK_CHANNELS = {\n foreground: { light: '30 41 59', dark: '229 230 236' },\n 'muted-foreground': { light: '100 116 139', dark: '141 144 153' },\n border: { light: '229 231 235', dark: '52 53 62' },\n 'chart-1': { light: '31 143 255', dark: '92 173 255' },\n 'chart-2': { light: '0 194 135', dark: '0 230 161' },\n 'chart-3': { light: '146 92 255', dark: '173 133 255' },\n 'chart-4': { light: '245 147 0', dark: '255 190 92' },\n 'chart-5': { light: '237 94 223', dark: '242 140 232' },\n // The sequential ramp's low end and the surface it must stay legible against.\n accent: { light: '224 242 254', dark: '30 58 95' },\n card: { light: '255 255 255', dark: '34 34 40' },\n} as const;\n\nexport type VegaTokenName = keyof typeof FALLBACK_CHANNELS;\n\n/**\n * A vega-serializing token resolver bound to one `getComputedStyle` snapshot.\n *\n * - Answers `rgb(R, G, B)` / `rgba(R, G, B, a)` — see {@link vegaRgb}.\n * - Falls back per scheme when the custom property is not painted.\n * - Build one per palette, never at module level: the values change whenever\n * the scheme or the brand does.\n */\nexport const createVegaColorResolver = (scheme: ResolvedColorScheme) => {\n const resolve = createChannelResolver();\n\n return (token: VegaTokenName, alpha?: number): string =>\n vegaRgb(resolve(token, FALLBACK_CHANNELS[token][scheme]), alpha);\n};\n","import type { Config } from 'vega-lite';\n\nimport type { ResolvedColorScheme } from '../components/ThemeProvider/types';\n\nimport { createVegaColorResolver, SERIES_TOKENS } from './vegaTokens';\n\nconst CHART_FONT = 'Inter, system-ui, sans-serif';\n\n/**\n * Scheme-following Vega-Lite config — the design system's chart look as a plain\n * `Config`, for any consumer that compiles or renders a Vega-Lite spec.\n *\n * - `background: 'transparent'` drops vega's opaque white backdrop, so the page\n * surface shows through in both schemes.\n * - Axis/legend/header/title text and lines read the live semantic tokens, so a\n * dark scheme (and a customer brand) recolour the chart chrome for free.\n * - `range.category` is `--chart-1..5` in series order — the same decorative\n * palette the recharts wrappers in `@keboola/design/charts` use — so a\n * categorical encoding matches the rest of the platform's data-viz instead of\n * falling back to vega's `tableau10`.\n * - `range.ramp` puts the low end of a quantitative scale on `--accent` rather\n * than vega's blue-only default, which keeps the pale end legible on a dark\n * surface.\n * - A range set on the spec's own scale still wins, which is how a Flint chart\n * keeps the series colours it resolves during assembly.\n * - Colours are resolved to concrete `rgb(R, G, B)` strings, not `var()`\n * references: vega does its colour maths in JS and never consults the\n * stylesheet. Rebuild the config when the scheme or brand changes —\n * `useVegaTheme` does that for you.\n */\nexport const vegaTheme = (scheme: ResolvedColorScheme): Config => {\n const token = createVegaColorResolver(scheme);\n\n const label = token('muted-foreground');\n const heading = token('foreground');\n const line = token('border');\n\n return {\n background: 'transparent',\n font: CHART_FONT,\n axis: {\n labelColor: label,\n titleColor: heading,\n gridColor: token('border', 0.6),\n domainColor: line,\n tickColor: line,\n },\n legend: { labelColor: label, titleColor: heading },\n header: { labelColor: label, titleColor: heading },\n title: { color: heading, subtitleColor: label },\n text: { color: heading },\n range: {\n category: SERIES_TOKENS.map((name) => token(name)),\n ramp: [token('accent'), token('chart-1')],\n },\n };\n};\n"],"mappings":";;;;;;;;;;;AAYA,MAAa,WAAW,UAAkB,UAA2B;CACnE,MAAM,IAAI,SAAS,MAAM,KAAK,CAAC,CAAC,KAAK,IAAI;CACzC,OAAO,UAAU,KAAA,IAAY,OAAO,EAAE,KAAK,QAAQ,EAAE,IAAI,MAAM;AACjE;;AAGA,MAAa,gBAAgB;CAAC;CAAW;CAAW;CAAW;CAAW;AAAS;;;;;;;AAQnF,MAAM,oBAAoB;CACxB,YAAY;EAAE,OAAO;EAAY,MAAM;CAAc;CACrD,oBAAoB;EAAE,OAAO;EAAe,MAAM;CAAc;CAChE,QAAQ;EAAE,OAAO;EAAe,MAAM;CAAW;CACjD,WAAW;EAAE,OAAO;EAAc,MAAM;CAAa;CACrD,WAAW;EAAE,OAAO;EAAa,MAAM;CAAY;CACnD,WAAW;EAAE,OAAO;EAAc,MAAM;CAAc;CACtD,WAAW;EAAE,OAAO;EAAa,MAAM;CAAa;CACpD,WAAW;EAAE,OAAO;EAAc,MAAM;CAAc;CAEtD,QAAQ;EAAE,OAAO;EAAe,MAAM;CAAW;CACjD,MAAM;EAAE,OAAO;EAAe,MAAM;CAAW;AACjD;;;;;;;;;AAYA,MAAa,2BAA2B,WAAgC;CACtE,MAAM,UAAU,sBAAsB;CAEtC,QAAQ,OAAsB,UAC5B,QAAQ,QAAQ,OAAO,kBAAkB,MAAM,CAAC,OAAO,GAAG,KAAK;AACnE;;;ACjDA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;AAwBnB,MAAa,aAAa,WAAwC;CAChE,MAAM,QAAQ,wBAAwB,MAAM;CAE5C,MAAM,QAAQ,MAAM,kBAAkB;CACtC,MAAM,UAAU,MAAM,YAAY;CAClC,MAAM,OAAO,MAAM,QAAQ;CAE3B,OAAO;EACL,YAAY;EACZ,MAAM;EACN,MAAM;GACJ,YAAY;GACZ,YAAY;GACZ,WAAW,MAAM,UAAU,EAAG;GAC9B,aAAa;GACb,WAAW;EACb;EACA,QAAQ;GAAE,YAAY;GAAO,YAAY;EAAQ;EACjD,QAAQ;GAAE,YAAY;GAAO,YAAY;EAAQ;EACjD,OAAO;GAAE,OAAO;GAAS,eAAe;EAAM;EAC9C,MAAM,EAAE,OAAO,QAAQ;EACvB,OAAO;GACL,UAAU,cAAc,KAAK,SAAS,MAAM,IAAI,CAAC;GACjD,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC;EAC1C;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keboola/design",
3
- "version": "11.2.0",
3
+ "version": "11.4.0",
4
4
  "description": "Keboola UI platform design system — shadcn-aligned React primitives, Keboola-branded blocks, and the form bindings built on TanStack Form.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,6 +23,12 @@
23
23
  "editors": [
24
24
  "./dist/editors.d.ts"
25
25
  ],
26
+ "flint": [
27
+ "./dist/flint.d.ts"
28
+ ],
29
+ "vega": [
30
+ "./dist/vega.d.ts"
31
+ ],
26
32
  "icons": [
27
33
  "./dist/icons.d.ts"
28
34
  ],
@@ -57,6 +63,14 @@
57
63
  "types": "./dist/editors.d.ts",
58
64
  "default": "./dist/editors.js"
59
65
  },
66
+ "./flint": {
67
+ "types": "./dist/flint.d.ts",
68
+ "default": "./dist/flint.js"
69
+ },
70
+ "./vega": {
71
+ "types": "./dist/vega.d.ts",
72
+ "default": "./dist/vega.js"
73
+ },
60
74
  "./icons": {
61
75
  "types": "./dist/icons.d.ts",
62
76
  "default": "./dist/icons.js"
@@ -122,6 +136,7 @@
122
136
  "@testing-library/dom": "^10.4.1",
123
137
  "@testing-library/react": "^16.3.2",
124
138
  "@testing-library/user-event": "^14.6.1",
139
+ "@types/d3-color": "^3.1.3",
125
140
  "@types/react": "^19.2.15",
126
141
  "@types/react-dom": "^19.2.3",
127
142
  "@typescript/native": "npm:typescript@^7.0.2",
@@ -130,6 +145,7 @@
130
145
  "@vitest/browser-playwright": "4.1.10",
131
146
  "@vitest/coverage-istanbul": "4.1.10",
132
147
  "@vitest/coverage-v8": "^4.1.10",
148
+ "d3-color": "^3.1.0",
133
149
  "eslint-plugin-storybook": "^10.3.5",
134
150
  "oxfmt": "^0.57.0",
135
151
  "oxlint": "^1.72.0",
@@ -164,7 +180,7 @@
164
180
  "dependencies": {
165
181
  "@base-ui/react": "1.5.0",
166
182
  "@codemirror/autocomplete": "^6.20.3",
167
- "@codemirror/commands": "^6.10.4",
183
+ "@codemirror/commands": "^6.11.0",
168
184
  "@codemirror/lang-javascript": "^6.2.5",
169
185
  "@codemirror/lang-json": "^6.0.2",
170
186
  "@codemirror/lang-python": "^6.2.1",
@@ -174,7 +190,7 @@
174
190
  "@codemirror/lint": "^6.9.7",
175
191
  "@codemirror/merge": "^6.12.2",
176
192
  "@codemirror/state": "^6.7.1",
177
- "@codemirror/view": "^6.43.6",
193
+ "@codemirror/view": "^6.43.9",
178
194
  "@iconify-json/lucide": "^1.2.118",
179
195
  "@lezer/highlight": "^1.2.3",
180
196
  "@lexical/code": "^0.42.0",
@@ -211,7 +227,7 @@
211
227
  "@tanstack/react-form": "^1.29.1",
212
228
  "@tanstack/react-virtual": "^3.14.5",
213
229
  "@testing-library/jest-dom": "^6.8.0",
214
- "@uiw/codemirror-theme-github": "^4.25.10",
230
+ "@uiw/codemirror-theme-github": "^4.25.11",
215
231
  "@uiw/react-codemirror": "^4.25.11",
216
232
  "beautiful-mermaid": "^1.1.3",
217
233
  "boring-avatars": "^2.0.4",
@@ -219,11 +235,12 @@
219
235
  "clsx": "^2.1.1",
220
236
  "cmdk": "^1.1.1",
221
237
  "diff": "^9.0.0",
222
- "dompurify": "^3.4.12",
238
+ "dompurify": "^3.4.14",
239
+ "flint-chart": "0.5.1",
223
240
  "input-otp": "^1.4.2",
224
241
  "lexical": "^0.42.0",
225
242
  "lucide-react": "^1.17.0",
226
- "mermaid": "^11.15.0",
243
+ "mermaid": "^11.17.2",
227
244
  "node-diff3": "^3.2.0",
228
245
  "react-day-picker": "^10.0.1",
229
246
  "react-dropzone": "^14.2.3",
@@ -234,9 +251,11 @@
234
251
  "remark-gfm": "^4.0.1",
235
252
  "sonner": "^2.0.7",
236
253
  "tailwind-merge": "^3.6.0",
237
- "@keboola/tailwind-config": "^1.1.1",
238
- "@keboola/codemirror-lang-sql": "^0.7.2",
239
- "@keboola/brand-registry": "^1.9.3"
254
+ "vega": "^6.4.0",
255
+ "vega-lite": "^6.4.3",
256
+ "@keboola/codemirror-lang-sql": "^0.7.3",
257
+ "@keboola/tailwind-config": "^1.1.2",
258
+ "@keboola/brand-registry": "^1.9.4"
240
259
  },
241
260
  "scripts": {
242
261
  "dev": "storybook dev -p \"${PORT:-6006}\"",
package/src/styles.css CHANGED
@@ -41,6 +41,13 @@
41
41
  * Primitive scales (neutral-*, primary-*, error-*, warning-*, etc.) remain hardcoded in colors.ts.
42
42
  */
43
43
  :root {
44
+ /* Native chrome (scrollbars, form controls, the canvas under the page) follows the
45
+ * theme the app pins, not the OS preference.
46
+ * - `ThemeProvider` owns `data-theme`, so the OS `prefers-color-scheme` must not leak in.
47
+ * - Undeclared, a browser paints light-scheme scrollbars over a dark surface.
48
+ * - Declared per theme rather than as `light dark`, which would re-open that OS channel. */
49
+ color-scheme: light;
50
+
44
51
  /* Card — raised container chrome (Modal/Card/Sheet). */
45
52
  --card: 255 255 255; /* #ffffff */
46
53
  --card-foreground: 30 41 59; /* #1e293b */
@@ -103,7 +110,7 @@
103
110
  --sidebar: 255 255 255; /* #ffffff */
104
111
  --sidebar-foreground: 30 41 59; /* #1e293b */
105
112
  --sidebar-primary: var(--primary); /* follows brand primary (default #2563eb) */
106
- --sidebar-primary-foreground: 255 255 255; /* #ffffff */
113
+ --sidebar-primary-foreground: var(--primary-foreground); /* follows the primary label */
107
114
  --sidebar-accent: 219 234 254; /* #dbeafe */
108
115
  --sidebar-accent-foreground: 30 41 59; /* #1e293b */
109
116
  --sidebar-border: 229 231 235; /* #e5e7eb */
@@ -193,15 +200,20 @@
193
200
 
194
201
  /* Dark mode (Graphite) — Keboola-blue accent, not reachable until the theme toggle ships. */
195
202
  [data-theme='dark'] {
203
+ color-scheme: dark;
204
+
196
205
  /* Card — raised container chrome (Modal/Card/Sheet), lifted off background. */
197
206
  --card: 34 34 40; /* #222228 */
198
207
  --card-foreground: 229 230 236; /* #e5e6ec */
199
208
  --background: 19 19 23; /* #131317 */
200
209
  --foreground: 229 230 236; /* #e5e6ec */
201
210
 
202
- /* Primary — Keboola blue (kept consistent across themes). */
211
+ /* Primary — Keboola blue, lightened for dark surfaces.
212
+ - The label is a near-black, not white: white on #1f8fff is 3.27:1, below AA.
213
+ - The label is what darkens rather than the fill, because `--primary` is the
214
+ brand's own colour and doubles as link text on the dark background. 5.38:1. */
203
215
  --primary: 31 143 255; /* #1f8fff */
204
- --primary-foreground: 255 255 255; /* #ffffff */
216
+ --primary-foreground: 10 26 43; /* #0a1a2b */
205
217
 
206
218
  /* Secondary */
207
219
  --secondary: 47 48 55; /* #2f3037 */
@@ -254,7 +266,7 @@
254
266
  --sidebar: 14 14 18; /* #0e0e12 */
255
267
  --sidebar-foreground: 229 230 236; /* #e5e6ec */
256
268
  --sidebar-primary: var(--primary); /* follows brand primary (default #1f8fff) */
257
- --sidebar-primary-foreground: 255 255 255; /* #ffffff */
269
+ --sidebar-primary-foreground: var(--primary-foreground); /* follows the primary label */
258
270
  --sidebar-accent: 38 38 45; /* #26262d */
259
271
  --sidebar-accent-foreground: 229 230 236; /* #e5e6ec */
260
272
  --sidebar-border: 48 49 57; /* #303139 */
@@ -284,6 +296,17 @@
284
296
  }
285
297
 
286
298
  @layer base {
299
+ /* `color-scheme` inherits, so an embed would pick the page's up.
300
+ * - A third-party widget (the JSD help launcher, an OAuth shim) ships a transparent body and
301
+ * declares no scheme of its own, so its own document resolves to light.
302
+ * - When an iframe element's scheme and its document's disagree, the UA stops honouring that
303
+ * transparency and paints the embedded canvas opaque — a white tile over a dark page.
304
+ * - Staying neutral on the element removes the disagreement. An embed that wants the dark
305
+ * scheme opts in, in its own document or on its own call site. */
306
+ iframe {
307
+ color-scheme: normal;
308
+ }
309
+
287
310
  @font-face {
288
311
  font-family: 'Inter';
289
312
  font-style: normal;
@@ -1 +0,0 @@
1
- {"version":3,"file":"AIKit-DiS0CVOW.js","names":["renderVariantIcon"],"sources":["../src/blocks/AIKit/CollapsibleStepHeader.tsx","../src/blocks/AIKit/InlineStepDetail.tsx","../src/blocks/AIKit/InlineStepLabel.tsx","../src/blocks/AIKit/AnswerSummary.tsx","../src/blocks/AIKit/Markdown.tsx","../src/blocks/AIKit/MessageBubble.tsx","../src/blocks/AIKit/PlanApproval.tsx","../src/blocks/AIKit/PlanRewritingIndicator.tsx","../src/blocks/AIKit/PromptInputAction.tsx","../src/blocks/AIKit/PromptInputCommands.tsx","../src/blocks/AIKit/PromptInputSubmit.tsx","../src/blocks/AIKit/PromptInput.tsx","../src/blocks/AIKit/Question.tsx","../src/blocks/AIKit/QuestionBlock.tsx","../src/blocks/AIKit/SuggestedPrompt.tsx","../src/blocks/AIKit/ThinkingIndicator.tsx","../src/blocks/AIKit/ToolCall/ToolCallApproval.tsx","../src/blocks/AIKit/ToolCall/ToolCallChip.tsx","../src/blocks/AIKit/usageStatsHelpers.ts","../src/blocks/AIKit/UsageStatsRing.tsx","../src/blocks/AIKit/UsageStats.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { ChevronDown, CircleCheck, Loader2, XCircle } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Variant = 'success' | 'error' | 'processing' | 'dismissed';\n\ntype Props = {\n isExpanded: boolean;\n onToggle: () => void;\n label: ReactNode;\n variant?: Variant;\n};\n\nconst variantClasses: Record<Variant, string> = {\n success:\n 'tw:text-secondary-500 tw:focus-visible:outline-ring tw:not-disabled:hover:text-secondary-600',\n error:\n 'tw:text-error-500 tw:focus-visible:outline-error-500 tw:not-disabled:hover:text-error-600',\n processing:\n 'tw:text-secondary-500 tw:focus-visible:outline-ring tw:not-disabled:hover:text-secondary-600',\n dismissed:\n 'tw:text-neutral-700 tw:focus-visible:outline-neutral-500 tw:not-disabled:hover:text-neutral-800',\n};\n\nconst iconClasses = 'tw:size-4 tw:shrink-0 tw:basis-4';\n\nconst renderVariantIcon = (variant: Variant) => {\n if (variant === 'processing') {\n return <Loader2 className={cn(iconClasses, 'tw:animate-spin')} />;\n }\n if (variant === 'error') {\n return <XCircle className={iconClasses} />;\n }\n if (variant === 'dismissed') {\n return <XCircle className={cn(iconClasses, 'tw:text-neutral-500')} />;\n }\n return <CircleCheck className={iconClasses} />;\n};\n\nexport const CollapsibleStepHeader = ({\n isExpanded,\n onToggle,\n label,\n variant = 'success',\n}: Props) => {\n return (\n <button\n type=\"button\"\n aria-expanded={isExpanded}\n onClick={onToggle}\n className={cn(\n 'tw:flex tw:w-fit tw:items-start tw:gap-2 tw:text-left tw:text-sm tw:font-medium tw:italic tw:transition-colors tw:focus-visible:outline tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:disabled:opacity-40',\n variantClasses[variant],\n )}\n >\n {renderVariantIcon(variant)}\n <span className=\"tw:min-w-0\">\n {label}\n {/* Zero-width joiner keeps the chevron on the label's last line —\n an inline chevron with nothing binding it to the preceding word\n orphans onto a line of its own at some container widths. */}\n <span className=\"tw:whitespace-nowrap\">\n {'⁠'}\n <ChevronDown\n className={cn(\n 'tw:ml-2 tw:inline-block tw:size-4 tw:align-middle tw:transition-transform',\n isExpanded && 'tw:rotate-180',\n )}\n />\n </span>\n </span>\n </button>\n );\n};\n","import type { ReactNode } from 'react';\n\ntype Props = {\n children: ReactNode;\n};\n\nexport const InlineStepDetail = ({ children }: Props) => (\n <div className=\"tw:ml-2.5 tw:whitespace-pre-wrap tw:border-l tw:border-neutral-200 tw:pl-3 tw:text-xs tw:text-neutral-400\">\n {children}\n </div>\n);\n\nexport type { Props as InlineStepDetailProps };\n","import type { ReactNode } from 'react';\n\nimport { CircleCheck, Loader2, XCircle } from '../../icons';\n\ntype Variant = 'processing' | 'success' | 'error' | 'dismissed';\n\ntype Props = {\n variant: Variant;\n children: ReactNode;\n};\n\nconst renderVariantIcon = (variant: Variant) => {\n if (variant === 'processing') {\n return <Loader2 className=\"tw:size-4 tw:animate-spin tw:text-neutral-200\" />;\n }\n if (variant === 'error') {\n return <XCircle className=\"tw:size-4 tw:text-error-500\" />;\n }\n if (variant === 'dismissed') {\n return <XCircle className=\"tw:size-4 tw:text-neutral-200\" />;\n }\n return <CircleCheck className=\"tw:size-4 tw:text-neutral-200\" />;\n};\n\nexport const InlineStepLabel = ({ variant, children }: Props) => (\n <div className=\"tw:flex tw:min-w-0 tw:items-center tw:gap-1\">\n <div className=\"tw:flex tw:size-5 tw:shrink-0 tw:items-center tw:justify-center\">\n {renderVariantIcon(variant)}\n </div>\n <div className=\"tw:flex tw:min-w-0 tw:flex-wrap tw:items-center tw:gap-x-1.5 tw:gap-y-1 tw:text-sm tw:font-medium tw:italic tw:text-neutral-800\">\n {children}\n </div>\n </div>\n);\n\nexport type { Variant as InlineStepLabelVariant, Props as InlineStepLabelProps };\n","import { useState } from 'react';\n\nimport { CollapsibleStepHeader } from './CollapsibleStepHeader';\nimport { InlineStepDetail } from './InlineStepDetail';\nimport { InlineStepLabel } from './InlineStepLabel';\n\ntype AnswerItem = {\n question: string;\n answer?: string;\n};\n\ntype Variant = 'success' | 'dismissed';\n\ntype Props = {\n items: readonly AnswerItem[];\n variant?: Variant;\n noAnswerLabel?: string;\n};\n\nconst SECTION_LABELS: Record<Variant, string> = {\n success: 'Answered questions',\n dismissed: 'Dismissed questions',\n};\n\nexport const AnswerSummary = ({\n items,\n variant = 'success',\n noAnswerLabel = 'No answer',\n}: Props) => {\n const [isExpanded, setIsExpanded] = useState(false);\n const toggle = () => setIsExpanded((prev) => !prev);\n const count = items.length;\n const [firstItem] = items;\n const label = count === 1 && firstItem ? firstItem.question : `${count} questions`;\n\n return (\n <section className=\"tw:mt-4 tw:flex tw:flex-col tw:gap-4\" aria-label={SECTION_LABELS[variant]}>\n <CollapsibleStepHeader\n isExpanded={isExpanded}\n onToggle={toggle}\n variant={variant}\n label={label}\n />\n\n {isExpanded && (\n <div className=\"tw:flex tw:flex-col tw:gap-4 tw:pl-5\">\n {items.map(({ question, answer }, index) => (\n <div key={`${index}-${question}`} className=\"tw:flex tw:flex-col tw:gap-1\">\n <InlineStepLabel variant={variant}>{question}</InlineStepLabel>\n <InlineStepDetail>\n {answer && answer.length > 0 ? answer : noAnswerLabel}\n </InlineStepDetail>\n </div>\n ))}\n </div>\n )}\n </section>\n );\n};\n\nexport type {\n AnswerItem as AnswerSummaryItem,\n Props as AnswerSummaryProps,\n Variant as AnswerSummaryVariant,\n};\n","import { isValidElement, lazy, Suspense } from 'react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport type { Components, ExtraProps } from 'react-markdown';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\n\nimport { Table } from '../../components/Table';\nimport { cn } from '../../utils';\nimport { ClipboardButton } from '../ClipboardButton';\nimport { DiagramSkeleton } from '../MermaidDiagram/DiagramSkeleton';\n\n// beautiful-mermaid pulls elkjs (~442 kB gzip). Loading it on demand keeps it\n// out of the entry chunk of every app that touches the root barrel.\nconst MermaidDiagram = lazy(() =>\n import('@keboola/design/mermaid').then(\n (module) => ({ default: module.MermaidDiagram }),\n (error: unknown) => {\n // Typically a stale tab after a deploy. Log it so the swap to plain source\n // is not silent.\n console.error('[AIKit] failed to load the MermaidDiagram chunk', error);\n return {\n default: ({ code }: { code: string }) => (\n <pre>\n <code>{code}</code>\n </pre>\n ),\n };\n },\n ),\n);\n\nconst proseClass =\n 'tw:prose tw:prose-sm tw:max-w-none tw:break-words tw:[&_pre]:bg-neutral-50 tw:[&_pre]:text-neutral-800 tw:[&_:not(pre)>code]:bg-neutral-50 tw:[&_:not(pre)>code]:rounded tw:[&_:not(pre)>code]:px-1 tw:[&_:not(pre)>code]:py-0.5 tw:[&_:not(pre)>code]:before:content-none tw:[&_:not(pre)>code]:after:content-none';\n\nconst getText = (node: ReactNode): string => {\n if (typeof node === 'string') return node;\n if (typeof node === 'number') return String(node);\n if (Array.isArray(node)) return node.map(getText).join('');\n if (\n isValidElement(node) &&\n typeof node.props === 'object' &&\n node.props !== null &&\n 'children' in node.props\n ) {\n return getText((node.props as { children: ReactNode }).children);\n }\n return '';\n};\n\nconst getLanguage = (element: ReactNode): string | undefined => {\n if (!isValidElement(element)) return undefined;\n const { props } = element;\n if (typeof props !== 'object' || props === null || !('className' in props)) return undefined;\n if (typeof props.className !== 'string') return undefined;\n return props.className.match(/language-(\\S+)/)?.[1];\n};\n\n// react-markdown passes a hast `node` to every component; strip it before\n// spreading the rest onto a DOM element.\nconst components: Components = {\n // Handle mermaid at the `pre` level: react-markdown renders fenced blocks as\n // `<pre><code class=\"language-…\">`, so a diagram (a block `<div>`) must replace\n // the whole `<pre>` — returning it from the `code` override would nest a block\n // element inside `<pre><code>` (invalid HTML).\n pre({ children, ...props }: ComponentPropsWithoutRef<'pre'> & ExtraProps) {\n const child = Array.isArray(children) ? children[0] : children;\n if (getLanguage(child) === 'mermaid') {\n const code = getText(child).replace(/\\n$/, '');\n if (!code.trim()) return null;\n return (\n <Suspense fallback={<DiagramSkeleton />}>\n <MermaidDiagram code={code} />\n </Suspense>\n );\n }\n const { node: _node, ...rest } = props;\n const code = getText(child).replace(/\\n$/, '');\n // Wrap so the copy button can reveal on hover/focus, anchored to the block.\n return (\n <div className=\"tw:group tw:relative\">\n <span className=\"tw:absolute tw:right-2 tw:top-2 tw:opacity-0 tw:transition-opacity tw:group-focus-within:opacity-100 tw:group-hover:opacity-100\">\n <ClipboardButton text={code} tooltip=\"Copy\" size=\"icon-xs\" variant=\"outline\" />\n </span>\n <pre {...rest}>{children}</pre>\n </div>\n );\n },\n // Open absolute http(s) links in a new tab with a safe `rel`; leave relative\n // and anchor links to default in-page navigation.\n a({ children, href, ...props }: ComponentPropsWithoutRef<'a'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n const isExternal = !!href && /^https?:\\/\\//.test(href);\n return (\n <a\n href={href}\n {...(isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : null)}\n {...rest}\n >\n {children}\n </a>\n );\n },\n // Route GFM tables through the design `Table` so they match the rest of the\n // system; `tw:not-prose` opts the table out of prose typography overrides.\n table({ className, ...props }: ComponentPropsWithoutRef<'table'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return (\n <div className=\"tw:not-prose tw:my-4\">\n <Table bordered className={cn('tw:!mb-0', className)} {...rest} />\n </div>\n );\n },\n thead(props: ComponentPropsWithoutRef<'thead'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Header {...rest} />;\n },\n tbody(props: ComponentPropsWithoutRef<'tbody'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Body {...rest} />;\n },\n tr(props: ComponentPropsWithoutRef<'tr'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Row {...rest} />;\n },\n th(props: ComponentPropsWithoutRef<'th'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Head {...rest} />;\n },\n td(props: ComponentPropsWithoutRef<'td'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Cell {...rest} />;\n },\n};\n\ntype Props = {\n /** Markdown source (GFM: tables, task lists, strikethrough, autolinks). Tables\n * render through the design `Table`; fenced ```mermaid blocks render via\n * `MermaidDiagram`; other fenced blocks get a hover copy button. */\n children: string;\n className?: string;\n};\n\n/**\n * Read-only GFM Markdown renderer with design-token typography. Pair with\n * `MessageBubble` to render an assistant message body. Code blocks expose a\n * copy button, so mount a `TooltipProvider` once at the app root.\n */\nexport const Markdown = ({ children, className }: Props) => {\n return (\n <div data-prose className={cn(proseClass, className)}>\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>\n {children}\n </ReactMarkdown>\n </div>\n );\n};\n","import type { ComponentProps, PropsWithChildren, ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\n\nimport { Avatar } from '../../components/Avatar';\n\nconst containerClasses = cva(['tw:flex', 'tw:max-w-full', 'tw:gap-4'], {\n variants: {\n variant: {\n user: ['tw:justify-self-end', 'tw:flex-row-reverse'],\n assistant: ['tw:justify-self-start', 'tw:w-full', 'tw:gap-3'],\n },\n },\n defaultVariants: {\n variant: 'assistant',\n },\n});\n\nconst contentClasses = cva(\n [\n 'tw:flex',\n 'tw:flex-col',\n 'tw:gap-4',\n 'tw:break-words',\n 'tw:leading-relaxed',\n 'tw:text-foreground',\n // Hooks on `data-prose`, not the `tw:prose` class — Tailwind scans raw file\n // bytes, so a `\\:` escape in a TS string reaches the generator doubled.\n 'tw:[&_[data-prose]]:text-foreground',\n ],\n {\n variants: {\n variant: {\n assistant: ['tw:flex-1', 'tw:w-full', 'tw:min-w-0', 'tw:[&>*]:min-w-0'],\n user: [\n 'tw:max-w-screen-sm',\n 'tw:w-fit',\n 'tw:bg-muted',\n 'tw:p-3',\n 'tw:rounded-2xl',\n 'tw:ml-6',\n 'tw:overflow-hidden',\n 'tw:break-anywhere',\n ],\n },\n },\n\n defaultVariants: {\n variant: 'assistant',\n },\n },\n);\n\ntype Props = {\n variant: 'user' | 'assistant';\n user?: ComponentProps<typeof Avatar>['user'];\n actions?: ReactNode;\n createdAt?: string;\n} & PropsWithChildren;\n\nexport const MessageBubble = ({ variant, children, user, actions, createdAt }: Props) => {\n return (\n <div className={containerClasses({ variant })} data-testid={`chat-message-${variant}`}>\n {variant === 'user' && <Avatar user={user} size={30} title={createdAt} />}\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col tw:gap-2\">\n <div className={contentClasses({ variant })}>{children}</div>\n {actions}\n </div>\n </div>\n );\n};\n","import { type FormEvent, type KeyboardEvent, type ReactNode, useState } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Button } from '../../components/Button';\nimport {\n FullScreenModal,\n FullScreenModalBody,\n FullScreenModalHeader,\n} from '../../components/FullScreenModal';\nimport { Tooltip } from '../../components/Tooltip';\nimport { ChevronDown, Maximize2, Minimize2, Send, X } from '../../icons';\nimport { cn } from '../../utils';\nimport { Textarea } from '../Textarea';\n\ntype PlanApprovalStatus = 'pending' | 'approved' | 'dismissed' | 'changes-requested';\n\ntype PlanApprovalProps = {\n status: PlanApprovalStatus;\n title: string;\n summary?: ReactNode;\n stepCount?: number;\n planBody?: ReactNode;\n\n defaultExpanded?: boolean;\n isExpanded?: boolean;\n onExpandToggle?: (next: boolean) => void;\n\n onApprove?: () => void;\n onRequestChanges?: (reason: string) => void;\n onClose?: () => void;\n isSubmitting?: boolean;\n approveTooltip?: ReactNode;\n\n pendingPillLabel?: string;\n approvedPillLabel?: string;\n dismissedPillLabel?: string;\n changesRequestedPillLabel?: string;\n approveLabel?: string;\n requestChangesLabel?: string;\n cancelLabel?: string;\n showMoreLabel?: string;\n showLessLabel?: string;\n closeLabel?: string;\n fullScreenLabel?: string;\n exitFullScreenLabel?: string;\n changeRequestPlaceholder?: string;\n changeRequestSubmitLabel?: string;\n stepCountLabel?: (count: number) => string;\n\n className?: string;\n};\n\nconst defaultStepCountLabel = (count: number) => `${count} step${count === 1 ? '' : 's'}`;\n\nconst StatusPill = ({\n status,\n pendingLabel,\n approvedLabel,\n dismissedLabel,\n changesRequestedLabel,\n}: {\n status: PlanApprovalStatus;\n pendingLabel: string;\n approvedLabel: string;\n dismissedLabel: string;\n changesRequestedLabel: string;\n}) => {\n if (status === 'approved') {\n return (\n <Badge color=\"green\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {approvedLabel}\n </Badge>\n );\n }\n if (status === 'dismissed') {\n return (\n <Badge color=\"gray\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {dismissedLabel}\n </Badge>\n );\n }\n if (status === 'changes-requested') {\n return (\n <Badge color=\"blue\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {changesRequestedLabel}\n </Badge>\n );\n }\n return (\n <Badge color=\"green\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {pendingLabel}\n </Badge>\n );\n};\n\nconst ExpandToggle = ({\n isExpanded,\n onToggle,\n showMoreLabel,\n showLessLabel,\n}: {\n isExpanded: boolean;\n onToggle: () => void;\n showMoreLabel: string;\n showLessLabel: string;\n}) => (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={isExpanded}\n className=\"tw:inline-flex tw:cursor-pointer tw:items-center tw:gap-1 tw:bg-transparent tw:p-0 tw:text-sm tw:font-medium tw:text-secondary-500 tw:hover:text-secondary-600 tw:focus-visible:outline tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring tailwindcss-preflight\"\n >\n <span>{isExpanded ? showLessLabel : showMoreLabel}</span>\n <ChevronDown\n className={cn('tw:size-5 tw:transition-transform', isExpanded && 'tw:rotate-180')}\n />\n </button>\n);\n\nconst ChangeRequestForm = ({\n value,\n onValueChange,\n onSubmit,\n onKeyDown,\n placeholder,\n submitLabel,\n formLabel,\n canSubmit,\n isSubmitting,\n}: {\n value: string;\n onValueChange: (value: string) => void;\n onSubmit: (event?: FormEvent) => void;\n onKeyDown: (event: KeyboardEvent<HTMLTextAreaElement>) => void;\n placeholder: string;\n submitLabel: string;\n formLabel: string;\n canSubmit: boolean;\n isSubmitting: boolean;\n}) => (\n <form\n onSubmit={onSubmit}\n className=\"tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100 tw:bg-white tw:px-4 tw:py-3\"\n aria-label={formLabel}\n >\n <div className=\"tw:relative\">\n <Textarea\n value={value}\n onValueChange={onValueChange}\n placeholder={placeholder}\n maxRows={4}\n autoFocus\n onKeyDown={onKeyDown}\n containerClassName=\"tw:pr-12\"\n disabled={isSubmitting}\n aria-label={placeholder}\n data-testid=\"plan-change-request-input\"\n />\n <Button\n type=\"submit\"\n variant=\"invisible\"\n size=\"icon-sm\"\n aria-label={submitLabel}\n disabled={!canSubmit}\n className=\"tw:absolute tw:right-2 tw:top-1/2 tw:-translate-y-1/2 tw:[&_svg]:text-secondary-500 tw:not-disabled:hover:[&_svg]:text-secondary-600\"\n data-testid=\"plan-change-request-submit\"\n >\n <Send className=\"tw:size-4\" />\n </Button>\n </div>\n </form>\n);\n\nconst PlanActions = ({\n isRequestingChanges,\n isSubmitting,\n onApprove,\n onRequestChanges,\n onOpenRequestChanges,\n onCancelChangeRequest,\n approveLabel,\n requestChangesLabel,\n cancelLabel,\n approveTooltip,\n}: {\n isRequestingChanges: boolean;\n isSubmitting: boolean;\n onApprove?: () => void;\n onRequestChanges?: (reason: string) => void;\n onOpenRequestChanges: () => void;\n onCancelChangeRequest: () => void;\n approveLabel: string;\n requestChangesLabel: string;\n cancelLabel: string;\n approveTooltip?: ReactNode;\n}) => (\n <div className=\"tw:flex tw:shrink-0 tw:items-center tw:gap-2\">\n {isRequestingChanges ? (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onCancelChangeRequest}\n disabled={isSubmitting}\n data-testid=\"plan-cancel-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {cancelLabel}\n </Button>\n ) : (\n onRequestChanges && (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onOpenRequestChanges}\n disabled={isSubmitting}\n data-testid=\"plan-request-changes-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {requestChangesLabel}\n </Button>\n )\n )}\n {onApprove &&\n (approveTooltip ? (\n <Tooltip tooltip={approveTooltip} placement=\"top\" triggerAsChild>\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onApprove}\n disabled={isSubmitting || isRequestingChanges}\n data-testid=\"plan-approve-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {approveLabel}\n </Button>\n </Tooltip>\n ) : (\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onApprove}\n disabled={isSubmitting || isRequestingChanges}\n data-testid=\"plan-approve-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {approveLabel}\n </Button>\n ))}\n </div>\n);\n\nexport const PlanApproval = ({\n status,\n title,\n summary,\n stepCount,\n planBody,\n\n defaultExpanded = false,\n isExpanded: isExpandedProp,\n onExpandToggle,\n\n onApprove,\n onRequestChanges,\n onClose,\n isSubmitting = false,\n approveTooltip,\n\n pendingPillLabel = 'Ready for approval',\n approvedPillLabel = 'Approved',\n dismissedPillLabel = 'Dismissed',\n changesRequestedPillLabel = 'Changes Requested',\n approveLabel = 'Approve',\n requestChangesLabel = 'Request Changes',\n cancelLabel = 'Cancel',\n showMoreLabel = 'Show more',\n showLessLabel = 'Show less',\n closeLabel = 'Dismiss plan',\n fullScreenLabel = 'View full screen',\n exitFullScreenLabel = 'Exit full screen',\n changeRequestPlaceholder = 'What would you like to change in the plan?',\n changeRequestSubmitLabel = 'Send change request',\n stepCountLabel = defaultStepCountLabel,\n\n className,\n}: PlanApprovalProps) => {\n const [uncontrolledExpanded, setUncontrolledExpanded] = useState(defaultExpanded);\n const isExpanded = isExpandedProp ?? uncontrolledExpanded;\n const [isRequestingChanges, setIsRequestingChanges] = useState(false);\n const [changeRequest, setChangeRequest] = useState('');\n const [isFullScreen, setIsFullScreen] = useState(false);\n\n const isPending = status === 'pending';\n const showActions = isPending && (onApprove || onRequestChanges);\n const showClose = isPending && Boolean(onClose);\n const canShowPlanBody = planBody != null;\n const trimmedChangeRequest = changeRequest.trim();\n const canSubmitChangeRequest = trimmedChangeRequest.length > 0 && !isSubmitting;\n\n const toggleExpanded = () => {\n const next = !isExpanded;\n if (isExpandedProp === undefined) {\n setUncontrolledExpanded(next);\n }\n onExpandToggle?.(next);\n };\n\n const handleOpenRequestChanges = () => {\n setIsRequestingChanges(true);\n if (!isExpanded) {\n toggleExpanded();\n }\n };\n\n const handleCancelChangeRequest = () => {\n setIsRequestingChanges(false);\n setChangeRequest('');\n };\n\n const handleSubmitChangeRequest = (event?: FormEvent) => {\n event?.preventDefault();\n if (!canSubmitChangeRequest) return;\n onRequestChanges?.(trimmedChangeRequest);\n };\n\n const handleTextareaKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n handleSubmitChangeRequest();\n }\n };\n\n const showChangeRequestForm = isRequestingChanges && isPending;\n\n const changeRequestForm = (\n <ChangeRequestForm\n value={changeRequest}\n onValueChange={setChangeRequest}\n onSubmit={handleSubmitChangeRequest}\n onKeyDown={handleTextareaKeyDown}\n placeholder={changeRequestPlaceholder}\n submitLabel={changeRequestSubmitLabel}\n formLabel={requestChangesLabel}\n canSubmit={canSubmitChangeRequest}\n isSubmitting={isSubmitting}\n />\n );\n\n const planActions = (\n <PlanActions\n isRequestingChanges={isRequestingChanges}\n isSubmitting={isSubmitting}\n onApprove={onApprove}\n onRequestChanges={onRequestChanges}\n onOpenRequestChanges={handleOpenRequestChanges}\n onCancelChangeRequest={handleCancelChangeRequest}\n approveLabel={approveLabel}\n requestChangesLabel={requestChangesLabel}\n cancelLabel={cancelLabel}\n approveTooltip={approveTooltip}\n />\n );\n\n return (\n <>\n <section\n aria-label={title}\n className={cn(\n 'tw:flex tw:w-full tw:max-w-[800px] tw:flex-col tw:overflow-hidden tw:rounded-xl tw:border tw:border-solid tw:border-border tw:bg-neutral-50',\n className,\n )}\n data-testid=\"plan-approval-root\"\n data-plan-status={status}\n >\n <div className=\"tw:flex tw:items-start tw:gap-2 tw:pl-4 tw:pr-2 tw:pt-4\">\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col tw:gap-2 tw:pb-4\">\n <div className=\"tw:flex tw:items-center tw:gap-3\">\n <StatusPill\n status={status}\n pendingLabel={pendingPillLabel}\n approvedLabel={approvedPillLabel}\n dismissedLabel={dismissedPillLabel}\n changesRequestedLabel={changesRequestedPillLabel}\n />\n {stepCount != null && stepCount > 0 && (\n <span className=\"tw:text-xs tw:leading-4 tw:text-neutral-500\">\n {stepCountLabel(stepCount)}\n </span>\n )}\n </div>\n <p className=\"tw:m-0 tw:text-base tw:font-semibold tw:leading-6 tw:text-neutral-800\">\n {title}\n </p>\n </div>\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n {canShowPlanBody && !isFullScreen && (\n <Tooltip tooltip={fullScreenLabel} placement=\"top\" triggerAsChild>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={fullScreenLabel}\n onClick={() => setIsFullScreen(true)}\n data-testid=\"plan-fullscreen-button\"\n >\n <Maximize2 className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n )}\n {showClose && !isFullScreen && (\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={closeLabel}\n onClick={onClose}\n disabled={isSubmitting}\n data-testid=\"plan-close-button\"\n >\n <X className=\"tw:size-4\" />\n </Button>\n )}\n </div>\n </div>\n\n {summary != null && (\n <div\n className={cn(\n 'tw:whitespace-pre-wrap tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100 tw:px-4 tw:pt-4 tw:text-sm tw:text-neutral-700',\n isExpanded && canShowPlanBody ? 'tw:pb-4' : 'tw:pb-2',\n )}\n >\n {summary}\n </div>\n )}\n\n {isExpanded && canShowPlanBody && (\n <div className=\"tw:max-h-[400px] tw:overflow-y-auto tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100 tw:bg-white tw:p-4 tw:text-sm tw:text-neutral-700\">\n {planBody}\n </div>\n )}\n\n {!isFullScreen && (\n <>\n {showChangeRequestForm && changeRequestForm}\n\n <div\n className={cn(\n 'tw:flex tw:items-center tw:gap-2 tw:overflow-x-auto tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100 tw:bg-white tw:px-4 tw:py-3',\n canShowPlanBody ? 'tw:justify-between' : 'tw:justify-end',\n )}\n >\n {canShowPlanBody && (\n <div className=\"tw:shrink-0\">\n <ExpandToggle\n isExpanded={isExpanded}\n onToggle={toggleExpanded}\n showMoreLabel={showMoreLabel}\n showLessLabel={showLessLabel}\n />\n </div>\n )}\n\n {showActions && planActions}\n </div>\n </>\n )}\n </section>\n\n {canShowPlanBody && isFullScreen && (\n <FullScreenModal onEscapeKeyDown={() => setIsFullScreen(false)}>\n <FullScreenModalHeader\n title={\n <div className=\"tw:flex tw:min-w-0 tw:items-center tw:gap-3\">\n <StatusPill\n status={status}\n pendingLabel={pendingPillLabel}\n approvedLabel={approvedPillLabel}\n dismissedLabel={dismissedPillLabel}\n changesRequestedLabel={changesRequestedPillLabel}\n />\n <span className=\"tw:truncate\">{title}</span>\n </div>\n }\n onClose={() => setIsFullScreen(false)}\n showPreviousTitle={false}\n >\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n {showClose && (\n <Tooltip tooltip={closeLabel} placement=\"bottom\" triggerAsChild>\n <Button\n variant=\"outline\"\n size=\"icon\"\n aria-label={closeLabel}\n onClick={onClose}\n disabled={isSubmitting}\n data-testid=\"plan-close-button\"\n >\n <X className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n )}\n <Tooltip tooltip={exitFullScreenLabel} placement=\"bottom\" triggerAsChild>\n <Button\n variant=\"outline\"\n size=\"icon\"\n aria-label={exitFullScreenLabel}\n onClick={() => setIsFullScreen(false)}\n data-testid=\"plan-exit-fullscreen-button\"\n >\n <Minimize2 className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n </div>\n </FullScreenModalHeader>\n <FullScreenModalBody className=\"tw:bg-white tw:px-6 tw:py-4\">\n <div className=\"tw:mx-auto tw:w-full tw:max-w-[800px] tw:text-sm tw:text-neutral-700\">\n {planBody}\n </div>\n </FullScreenModalBody>\n {(showChangeRequestForm || showActions) && (\n <div className=\"tw:shrink-0 tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100 tw:bg-white\">\n <div className=\"tw:mx-auto tw:w-full tw:max-w-[800px]\">\n {showChangeRequestForm && changeRequestForm}\n {showActions && (\n <div className=\"tw:flex tw:justify-end tw:px-4 tw:py-3\">{planActions}</div>\n )}\n </div>\n </div>\n )}\n </FullScreenModal>\n )}\n </>\n );\n};\n\nexport type { PlanApprovalStatus, PlanApprovalProps };\n","import { Loader2 } from '../../icons';\n\ntype PlanRewritingIndicatorProps = {\n label?: string;\n};\n\nexport const PlanRewritingIndicator = ({\n label = 'Rewriting the plan...',\n}: PlanRewritingIndicatorProps) => (\n <div\n className=\"tw:flex tw:items-center tw:gap-2\"\n role=\"status\"\n data-testid=\"plan-rewriting-indicator\"\n >\n <Loader2 className=\"tw:size-4 tw:animate-spin tw:text-secondary-500\" />\n <span className=\"tw:text-sm tw:italic tw:text-secondary-500\">{label}</span>\n </div>\n);\n\nexport type { PlanRewritingIndicatorProps };\n","import type { ComponentProps, MouseEventHandler } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\n\ntype Props = ComponentProps<'button'>;\n\nexport const PromptInputAction = ({ ref, onMouseDown, ...rest }: Props) => {\n const handleOnMouseDown: MouseEventHandler<HTMLButtonElement> = (event) => {\n // Prevents focus stealing by PromptInput.\n event.stopPropagation();\n onMouseDown?.(event);\n };\n\n return <Slot {...rest} ref={ref} onMouseDown={handleOnMouseDown}></Slot>;\n};\n","import type { ReactNode } from 'react';\n\nimport { Truncated } from '../../components/Truncated';\nimport { cn } from '../../utils';\nimport { Command } from '../Command';\n\nexport type PromptCommand = {\n label: string;\n value: string;\n description?: string;\n icon?: ReactNode;\n group: string;\n};\n\ntype Props = {\n items: PromptCommand[];\n open: boolean;\n onSelect: (value: string) => void;\n filterValue: string;\n children: ReactNode;\n};\n\nexport const PromptInputCommands = ({ items, open, onSelect, filterValue, children }: Props) => {\n const filtered = filterValue\n ? items.filter(\n (item) =>\n item.label.toLowerCase().includes(filterValue.toLowerCase()) ||\n item.value.toLowerCase().includes(filterValue.toLowerCase()),\n )\n : items;\n\n const groups = filtered.reduce<Record<string, PromptCommand[]>>((acc, item) => {\n const group = acc[item.group] ?? [];\n group.push(item);\n acc[item.group] = group;\n return acc;\n }, {});\n\n return (\n <Command loop className=\"tw:relative\" shouldFilter={false}>\n {open && (\n <div\n className={cn(\n 'tw:absolute tw:bottom-full tw:left-0 tw:right-0 tw:z-50 tw:mb-1',\n 'tw:rounded-md tw:border tw:border-border tw:bg-popover tw:text-popover-foreground tw:shadow-lg',\n )}\n >\n {filtered.length === 0 ? (\n <div className=\"tw:px-4 tw:py-3 tw:text-center tw:text-sm tw:text-muted-foreground\">\n No commands found\n </div>\n ) : (\n <Command.List viewPortClassName=\"tw:max-h-80\">\n {Object.entries(groups).map(([groupName, groupItems]) => (\n <Command.Group key={groupName} heading={groupName}>\n {groupItems.map((item) => (\n <Command.Item\n key={item.value}\n value={item.value}\n icon={item.icon}\n onSelect={() => onSelect(item.value)}\n >\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col\">\n <span>{item.label}</span>\n {item.description && (\n <Truncated\n text={item.description}\n twoLines\n className=\"tw:text-xs tw:text-muted-foreground\"\n />\n )}\n </div>\n </Command.Item>\n ))}\n </Command.Group>\n ))}\n </Command.List>\n )}\n </div>\n )}\n\n {children}\n </Command>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Tooltip } from '../../components/Tooltip';\nimport { CirclePause, Play, Send } from '../../icons';\n\nimport { PromptInputAction } from './PromptInputAction';\n\ntype SubmitStatus = 'submitted' | 'ready' | 'streaming' | 'interrupted';\n\ntype Props = Pick<ComponentProps<typeof Button>, 'disabled' | 'ref'> & {\n status?: SubmitStatus;\n};\n\n// Icon-only button: the tooltip is visual only, so the accessible name must be\n// set separately per status to match what the button actually does (see\n// PromptInput's handleSubmit: ready->onSend, streaming->onAbort, interrupted->onContinue).\nconst ARIA_LABEL_BY_STATUS: Record<SubmitStatus, string> = {\n ready: 'Send message',\n streaming: 'Stop',\n interrupted: 'Continue',\n submitted: 'Sending…',\n};\n\nexport const PromptInputSubmit = ({ ref, disabled, status = 'ready' }: Props) => {\n const icon: ReactNode = (() => {\n if (status === 'streaming') return <CirclePause className=\"tw:size-4\" />;\n if (status === 'interrupted') return <Play className=\"tw:size-4\" />;\n return <Send className=\"tw:size-4\" />;\n })();\n\n const getTooltipText = () => {\n if (status === 'streaming') return 'Stop';\n if (status === 'interrupted') return 'Continue';\n return undefined;\n };\n\n return (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <PromptInputAction>\n <Button\n ref={ref}\n type=\"submit\"\n disabled={disabled}\n aria-label={ARIA_LABEL_BY_STATUS[status]}\n size=\"icon-sm\"\n variant=\"invisible\"\n isLoading={status === 'submitted'}\n className=\"tw:ml-auto tw:flex tw:items-center tw:rounded-lg tw:[&_svg]:text-secondary-500 tw:not-disabled:hover:[&_svg]:text-secondary-600\"\n >\n {/* Suppress the child icon while isLoading — Button already renders\n the spinner; rendering both would double-stack glyphs. */}\n {status !== 'submitted' && icon}\n </Button>\n </PromptInputAction>\n </Tooltip.Trigger>\n\n {getTooltipText() && (\n <Tooltip.Content placement=\"top\" variant=\"action\">\n {getTooltipText()}\n </Tooltip.Content>\n )}\n </Tooltip.Root>\n );\n};\n","import {\n type ChangeEventHandler,\n type ComponentProps,\n type ComponentRef,\n type FormEventHandler,\n type KeyboardEvent,\n type KeyboardEventHandler,\n type MouseEventHandler,\n type ReactNode,\n useId,\n useRef,\n useState,\n} from 'react';\nimport TextareaAutosize from 'react-textarea-autosize';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nimport { TooltipProvider } from '../../components/Tooltip';\nimport { cn } from '../../utils';\n\nimport { PromptInputAction } from './PromptInputAction';\nimport type { PromptCommand } from './PromptInputCommands';\nimport { PromptInputCommands } from './PromptInputCommands';\nimport { PromptInputSubmit } from './PromptInputSubmit';\n\nconst CMDK_HIJACKED_KEYS = new Set(['ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter']);\n\n// Whether cmdk would actually act on this keystroke, and so whether the guard\n// below still needs to hide it from the Command root.\n//\n// cmdk acts on every key in CMDK_HIJACKED_KEYS, modified or not — the arrows\n// branch on metaKey (jump to first/last) and altKey (jump to the adjacent\n// group), and Home/End preventDefault unconditionally. `Enter` is the sole\n// exception: its branch reads no modifier at all, so a modified Enter is the\n// only keystroke the Command root would ignore.\nconst isCmdkNavigation = (event: KeyboardEvent<HTMLTextAreaElement>) =>\n event.key !== 'Enter' || !(event.metaKey || event.ctrlKey || event.altKey);\n\nconst promptInputVariants = cva(\n [\n 'tailwindcss-preflight',\n 'tw:relative',\n\n 'tw:flex',\n 'tw:gap-2',\n 'tw:justify-center',\n\n // transparent border\n 'tw:border',\n 'tw:border-2',\n 'tw:border-transparent',\n 'tw:rounded-[14px]',\n\n // Gradient background\n 'tw:bg-gradient-to-bl',\n 'tw:from-[#61E4FF]',\n 'tw:via-[#1F8FFF]',\n 'tw:to-[#7C5CFF]',\n\n // Inner surface fill, leaving the 2px gradient border showing\n 'tw:bg-origin-border',\n 'tw:shadow-[inset_0_100vw_rgb(var(--card))]',\n\n // focus\n 'tw:has-[textarea:focus]:ring-4',\n 'tw:has-[textarea:focus]:ring-ring/30',\n\n 'tw:cursor-text',\n 'tw:px-2',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: ['tw:flex-col', 'tw:pt-3', 'tw:pb-2'],\n inline: ['tw:flex-row', 'tw:py-3', 'tw:items-center'],\n },\n },\n },\n);\n\nconst wrapperVariants = cva(null, {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: 'tw:rounded-[14px]',\n inline: '',\n },\n },\n});\n\ntype Props = {\n onSend?: (value: string) => void;\n onAbort?: () => void;\n onContinue?: () => void;\n value?: string;\n onValueChange?: (value: string) => void;\n defaultValue?: string;\n prefix?: ReactNode;\n suffix?: ReactNode;\n variant?: 'default' | 'inline';\n disableSubmit?: boolean;\n commands?: PromptCommand[];\n} & VariantProps<typeof promptInputVariants> &\n Pick<\n ComponentProps<typeof TextareaAutosize>,\n 'placeholder' | 'minRows' | 'maxRows' | 'disabled' | 'defaultValue' | 'autoFocus'\n > &\n ComponentProps<typeof PromptInputSubmit>;\n\nexport const PromptInput = ({\n onSend,\n onAbort,\n onContinue,\n prefix,\n variant,\n suffix,\n disabled,\n disableSubmit,\n value = '',\n onValueChange,\n status = 'ready',\n maxRows = 6,\n minRows,\n commands,\n ...textareaProps\n}: Props) => {\n const defaultMinRows = variant === 'inline' ? 1 : 2;\n const isDisabled =\n (disabled || disableSubmit || !value.trim()) &&\n status !== 'streaming' &&\n status !== 'interrupted';\n\n const textareaId = useId();\n const textareaRef = useRef<ComponentRef<'textarea'>>(null);\n const [dismissedValue, setDismissedValue] = useState<string | null>(null);\n\n // Esc dismisses the menu for the value at that moment; once the value moves away\n // from it, clear the dismissal so the menu can reopen if it re-matches the slash\n // shape. Done during render rather than in an effect, and keyed off\n // `dismissedValue` so state only updates while a dismissal is active — no extra\n // render per keystroke.\n if (dismissedValue !== null && value !== dismissedValue) setDismissedValue(null);\n\n const hasCommands = !!commands && commands.length > 0;\n const valueLooksLikeSlashCommand = value.startsWith('/') && !/\\s/.test(value);\n const commandsOpen = hasCommands && valueLooksLikeSlashCommand && value !== dismissedValue;\n const slashFilter = commandsOpen ? value.slice(1) : '';\n\n const handleSubmit = () => {\n if (isDisabled) return;\n if (status === 'streaming') onAbort?.();\n if (status === 'interrupted') onContinue?.();\n if (status === 'ready') onSend?.(value);\n };\n\n const handleOnSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n handleSubmit();\n };\n\n const handleOnChange: ChangeEventHandler<HTMLTextAreaElement> = (event) => {\n onValueChange?.(event.target.value);\n };\n\n const handleCommandSelect = (commandValue: string) => {\n onValueChange?.(commandValue + ' ');\n textareaRef.current?.focus();\n };\n\n const handleOnKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (event) => {\n if (commandsOpen) {\n if (event.key === 'Escape') {\n event.preventDefault();\n setDismissedValue(value);\n return;\n }\n // Don't preventDefault — let cmdk handle ArrowUp/Down/Enter via bubbling\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Enter') {\n return;\n }\n } else if (hasCommands && CMDK_HIJACKED_KEYS.has(event.key) && isCmdkNavigation(event)) {\n // Keep these from bubbling to the always-mounted cmdk Command root, whose\n // keydown handler preventDefaults them and breaks multiline editing.\n // Keystrokes cmdk ignores (e.g. Cmd+Enter, Alt+Enter) must still reach\n // document-level app hotkeys, so they are deliberately not stopped here.\n event.stopPropagation();\n }\n\n if (event.key === 'Enter' && !event.shiftKey && !event.ctrlKey && !event.metaKey) {\n event.preventDefault();\n if (status !== 'streaming') handleSubmit();\n }\n };\n\n const handleOnMouseDown: MouseEventHandler<HTMLFormElement> = (event) => {\n // don't prevent default if the target is the textarea itself\n if (event.target === textareaRef.current) return;\n\n event.preventDefault();\n textareaRef.current?.focus();\n };\n\n const formEl = (\n <div className={wrapperVariants({ variant })}>\n {/*This is alright, just refocused into a textarea. */}\n {/* oxlint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}\n <form\n data-testid=\"prompt-input\"\n data-status={status}\n onMouseDown={handleOnMouseDown}\n onSubmit={handleOnSubmit}\n className={cn(\n promptInputVariants({ variant }),\n disabled &&\n 'tw:bg-none tw:border-border tw:shadow-[inset_0_100vw_rgb(var(--muted))] tw:cursor-default',\n )}\n >\n {prefix && <div className=\"tw:flex tw:items-center\">{prefix}</div>}\n\n <label htmlFor={textareaId} className=\"tw:sr-only\">\n Prompt Input\n </label>\n <TextareaAutosize\n {...textareaProps}\n disabled={disabled}\n minRows={minRows ?? defaultMinRows}\n maxRows={maxRows}\n id={textareaId}\n ref={textareaRef}\n value={value}\n onChange={handleOnChange}\n onKeyDown={handleOnKeyDown}\n className={cn(\n 'tw:resize-none',\n 'tw:outline-hidden',\n 'tw:w-full',\n 'tw:px-2',\n 'tw:bg-transparent',\n\n // font\n disabled ? 'tw:text-muted-foreground' : 'tw:text-foreground',\n 'tw:text-sm',\n 'tw:font-sans',\n\n 'tw:transition-[width]',\n 'tw:delay-75',\n 'tw:ease-linear',\n 'tw:overflow-auto',\n )}\n />\n\n <div\n className={cn(\n 'tw:flex tw:items-center tw:gap-4',\n variant === 'inline' ? 'tw:items-end' : 'tw:items-center',\n )}\n >\n {suffix}\n <PromptInputSubmit disabled={isDisabled} status={status} />\n </div>\n </form>\n </div>\n );\n\n return (\n <TooltipProvider>\n {hasCommands ? (\n <PromptInputCommands\n items={commands ?? []}\n open={commandsOpen}\n onSelect={handleCommandSelect}\n filterValue={slashFilter}\n >\n {formEl}\n </PromptInputCommands>\n ) : (\n formEl\n )}\n </TooltipProvider>\n );\n};\n\nPromptInput.Action = PromptInputAction;\n","import { type KeyboardEvent, type ReactNode, useState } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Checkbox } from '../../components/Checkbox';\nimport { Progress } from '../../components/Progress';\nimport { Tooltip } from '../../components/Tooltip';\nimport { ChevronLeft, ChevronRight, X } from '../../icons';\nimport { cn } from '../../utils';\nimport { TextInput } from '../TextInput';\n\ntype QuestionOption = {\n id: string;\n label: string;\n description?: string;\n preview?: string;\n};\n\ntype Props = {\n question: string;\n header?: string;\n options: readonly QuestionOption[];\n multiSelect?: boolean;\n selectedOptionIds?: readonly string[];\n onSelectionChange?: (selectedIds: readonly string[]) => void;\n customAnswer?: string;\n onCustomAnswerChange?: (value: string) => void;\n onCustomAnswerConfirm?: () => void;\n showCustomAnswer?: boolean;\n customAnswerPlaceholder?: string;\n showSkip?: boolean;\n onSkip?: () => void;\n onClose?: () => void;\n onNext?: () => void;\n submitTooltip?: ReactNode;\n onPrevious?: () => void;\n currentStep?: number;\n totalSteps?: number;\n renderPreview?: (content: string) => ReactNode;\n className?: string;\n};\n\nconst handleKeyDown = (callback: () => void) => (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n callback();\n }\n};\n\nexport const Question = ({\n question,\n header,\n options,\n multiSelect = true,\n selectedOptionIds = [],\n onSelectionChange,\n customAnswer = '',\n onCustomAnswerChange,\n onCustomAnswerConfirm,\n showCustomAnswer = true,\n customAnswerPlaceholder = 'Type your answer…',\n showSkip = true,\n onSkip,\n onClose,\n onNext,\n submitTooltip,\n onPrevious,\n currentStep,\n totalSteps,\n renderPreview,\n className,\n}: Props) => {\n const [isCustomExpanded, setIsCustomExpanded] = useState(false);\n const isCustomSelected = isCustomExpanded || customAnswer.length > 0;\n const hasSteps = currentStep != null && totalSteps != null;\n const progressValue = hasSteps ? (currentStep / totalSteps) * 100 : 0;\n const isFirstStep = currentStep === 1;\n const isLastStep = hasSteps && currentStep === totalSteps;\n\n const handleOptionToggle = (optionId: string) => {\n if (multiSelect) {\n const isSelected = selectedOptionIds.includes(optionId);\n const nextIds = isSelected\n ? selectedOptionIds.filter((id) => id !== optionId)\n : [...selectedOptionIds, optionId];\n onSelectionChange?.(nextIds);\n } else {\n // Single-select: picking a real option deselects \"Other\" and drops any\n // typed custom answer so it can't leak into the submitted answer.\n setIsCustomExpanded(false);\n onCustomAnswerChange?.('');\n onSelectionChange?.([optionId]);\n }\n };\n\n const handleCustomToggle = (checked: boolean) => {\n setIsCustomExpanded(checked);\n if (checked) {\n // Single-select: \"Other\" and a real option are mutually exclusive.\n if (!multiSelect) {\n onSelectionChange?.([]);\n }\n } else {\n onCustomAnswerChange?.('');\n }\n };\n\n // Typing into (or focusing) the custom input selects \"Other\" directly — no\n // need to click the row/checkbox first.\n const handleCustomFocus = () => {\n setIsCustomExpanded(true);\n if (!multiSelect) {\n onSelectionChange?.([]);\n }\n };\n\n const handleCustomRowClick = () => {\n // Multi-select: the row toggles the checkbox. Single-select: clicking only\n // selects (never deselects, so a second click can't wipe typed text) —\n // switch away by picking a real option instead.\n if (multiSelect) {\n handleCustomToggle(!isCustomSelected);\n } else {\n handleCustomFocus();\n }\n };\n\n return (\n <div\n className={cn(\n 'tw:flex tw:max-w-[800px] tw:flex-col tw:gap-4 tw:overflow-hidden tw:rounded-xl tw:border tw:border-solid tw:border-border tw:bg-neutral-50 tw:shadow-lg',\n className,\n )}\n data-testid=\"question-root\"\n data-question-step={currentStep}\n data-question-total-steps={totalSteps}\n data-question-multi-select={multiSelect}\n >\n <div className=\"tw:flex tw:items-start tw:gap-2 tw:pl-4 tw:pr-2 tw:pt-4\">\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col tw:gap-1\">\n <p className=\"tw:m-0 tw:text-base tw:font-semibold tw:leading-6 tw:text-neutral-800\">\n {question}\n </p>\n {header && <p className=\"tw:m-0 tw:text-xs tw:leading-4 tw:text-neutral-500\">{header}</p>}\n </div>\n {onClose && (\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label=\"Close\"\n onClick={onClose}\n data-testid=\"question-close-button\"\n >\n <X className=\"tw:size-4\" />\n </Button>\n )}\n </div>\n\n <div className=\"tw:px-4\">\n <div className=\"tw:flex tw:flex-col tw:gap-4 tw:border-0 tw:border-l tw:border-solid tw:border-primary tw:px-4 tw:py-2\">\n {options.map((option) => (\n <div\n key={option.id}\n className=\"tw:-mx-2 tw:-my-1.5 tw:flex tw:cursor-pointer tw:items-start tw:gap-2 tw:rounded-md tw:px-2 tw:py-1.5 tw:hover:bg-neutral-100\"\n onClick={() => handleOptionToggle(option.id)}\n onKeyDown={handleKeyDown(() => handleOptionToggle(option.id))}\n role=\"button\"\n tabIndex={0}\n data-testid={`question-option-${option.id}`}\n >\n {multiSelect && (\n <Checkbox\n checked={selectedOptionIds.includes(option.id)}\n onCheckedChange={() => handleOptionToggle(option.id)}\n onClick={(e) => e.stopPropagation()}\n className=\"tw:shrink-0\"\n />\n )}\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:items-start tw:gap-3\">\n <div className=\"tw:flex tw:flex-col tw:gap-1.5\">\n <span className=\"tw:text-sm tw:font-medium tw:leading-none tw:text-neutral-800\">\n {option.label}\n </span>\n {option.description && (\n <span className=\"tw:text-sm tw:font-normal tw:leading-5 tw:text-muted-foreground\">\n {option.description}\n </span>\n )}\n </div>\n {option.preview && (\n <div\n className={cn(\n 'tw:ml-auto tw:flex tw:max-h-40 tw:min-w-0 tw:max-w-[50%] tw:flex-col tw:overflow-hidden tw:rounded-md',\n !renderPreview &&\n 'tw:overflow-auto tw:border tw:border-solid tw:border-neutral-200 tw:bg-white tw:p-2',\n )}\n >\n {renderPreview ? (\n renderPreview(option.preview)\n ) : (\n <pre className=\"tw:m-0 tw:overflow-visible tw:border-0 tw:bg-transparent tw:p-0 tw:font-mono tw:text-xs tw:leading-5 tw:text-neutral-700\">\n {option.preview}\n </pre>\n )}\n </div>\n )}\n </div>\n </div>\n ))}\n\n {showCustomAnswer && (\n <div className=\"tw:flex tw:flex-col tw:gap-2\">\n <div\n className=\"tw:-mx-2 tw:-my-1.5 tw:flex tw:cursor-pointer tw:items-start tw:gap-2 tw:rounded-md tw:px-2 tw:py-1.5 tw:hover:bg-neutral-100\"\n onClick={handleCustomRowClick}\n onKeyDown={handleKeyDown(handleCustomRowClick)}\n role=\"button\"\n tabIndex={0}\n >\n {/* Multi-select shows a checkbox alongside the option checkboxes.\n Single-select options auto-advance and carry no indicator, so\n \"Other\" is a plain clickable row that reveals the input below. */}\n {multiSelect && (\n <Checkbox\n checked={isCustomSelected}\n onCheckedChange={handleCustomToggle}\n onClick={(e) => e.stopPropagation()}\n className=\"tw:shrink-0\"\n />\n )}\n <span\n className={cn(\n 'tw:text-sm tw:font-medium tw:leading-none',\n !multiSelect && isCustomSelected ? 'tw:text-primary' : 'tw:text-neutral-800',\n )}\n >\n Other\n </span>\n </div>\n {/* Always rendered and editable: typing or focusing selects \"Other\"\n directly, and keeping it mounted avoids layout shift. */}\n <TextInput\n value={customAnswer}\n onValueChange={(value) => onCustomAnswerChange?.(value)}\n onFocus={handleCustomFocus}\n onKeyDown={\n onCustomAnswerConfirm\n ? (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter' && !e.shiftKey && !(e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n onCustomAnswerConfirm();\n }\n }\n : undefined\n }\n placeholder={customAnswerPlaceholder}\n sizing=\"small\"\n testId=\"question-custom\"\n />\n </div>\n )}\n </div>\n </div>\n\n <div className=\"tw:flex tw:flex-col\">\n {hasSteps && <Progress size=\"sm\" value={progressValue} className=\"tw:rounded-none\" />}\n\n <div\n className={cn(\n 'tw:flex tw:items-center tw:justify-end tw:gap-4 tw:px-4 tw:py-3',\n !hasSteps && 'tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100',\n )}\n >\n {hasSteps && (\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n <button\n type=\"button\"\n disabled={isFirstStep}\n className=\"tw:flex tw:cursor-pointer tw:items-center tw:justify-center tw:bg-transparent tw:p-0 tw:disabled:cursor-default tailwindcss-preflight\"\n onClick={onPrevious}\n aria-label=\"Previous step\"\n >\n <ChevronLeft\n className={cn(\n 'tw:size-5',\n isFirstStep ? 'tw:text-primary/25' : 'tw:text-primary',\n )}\n />\n </button>\n <span className=\"tw:text-xs tw:leading-4 tw:text-neutral-500\">\n {currentStep} of {totalSteps}\n </span>\n <button\n type=\"button\"\n disabled={currentStep === totalSteps}\n className=\"tw:flex tw:cursor-pointer tw:items-center tw:justify-center tw:bg-transparent tw:p-0 tw:disabled:cursor-default tailwindcss-preflight\"\n onClick={onNext}\n aria-label=\"Next step\"\n >\n <ChevronRight\n className={cn(\n 'tw:size-5',\n currentStep === totalSteps ? 'tw:text-primary/25' : 'tw:text-primary',\n )}\n />\n </button>\n </div>\n )}\n {showSkip && onSkip && (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onSkip}\n data-testid=\"question-skip-button\"\n >\n Skip\n </Button>\n )}\n {(multiSelect || isCustomSelected) &&\n (submitTooltip ? (\n <Tooltip tooltip={submitTooltip} placement=\"top\" triggerAsChild>\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onNext}\n data-testid=\"question-next-button\"\n >\n {isLastStep ? 'Submit' : 'Next'}\n </Button>\n </Tooltip>\n ) : (\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onNext}\n data-testid=\"question-next-button\"\n >\n {isLastStep ? 'Submit' : 'Next'}\n </Button>\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nexport type { QuestionOption, Props as QuestionProps };\n","import { type ReactNode, useState } from 'react';\n\nimport type { QuestionOption } from './Question';\nimport { Question } from './Question';\n\ntype QuestionStep = {\n question: string;\n header?: string;\n options: readonly QuestionOption[];\n multiSelect?: boolean;\n showCustomAnswer?: boolean;\n customAnswerPlaceholder?: string;\n};\n\ntype QuestionAnswers = {\n selections: Record<number, readonly string[]>;\n customAnswers: Record<number, string>;\n};\n\ntype Props = {\n steps: readonly [QuestionStep, ...QuestionStep[]];\n showSkip?: boolean;\n onSubmit?: (answers: QuestionAnswers) => void;\n onClose?: () => void;\n renderPreview?: (content: string) => ReactNode;\n className?: string;\n};\n\nexport const QuestionBlock = ({\n steps,\n showSkip = true,\n onSubmit,\n onClose,\n renderPreview,\n className,\n}: Props) => {\n const [currentStep, setCurrentStep] = useState(1);\n const [selections, setSelections] = useState<Record<number, readonly string[]>>({});\n const [customAnswers, setCustomAnswers] = useState<Record<number, string>>({});\n const stepData = steps[currentStep - 1]!;\n const isLastStep = currentStep === steps.length;\n\n const advance = (updatedSelections?: Record<number, readonly string[]>) => {\n const finalSelections = updatedSelections ?? selections;\n if (isLastStep) {\n onSubmit?.({ selections: finalSelections, customAnswers });\n } else {\n setCurrentStep((s) => Math.min(s + 1, steps.length));\n }\n };\n\n const handleSelectionChange = (ids: readonly string[]) => {\n const updated = { ...selections, [currentStep]: ids };\n setSelections(updated);\n if (!stepData.multiSelect) {\n advance(updated);\n }\n };\n\n return (\n <Question\n key={currentStep}\n {...stepData}\n selectedOptionIds={selections[currentStep] ?? []}\n onSelectionChange={handleSelectionChange}\n customAnswer={customAnswers[currentStep] ?? ''}\n onCustomAnswerChange={(value) =>\n setCustomAnswers((prev) => ({ ...prev, [currentStep]: value }))\n }\n currentStep={currentStep}\n totalSteps={steps.length}\n showSkip={showSkip && !isLastStep}\n onNext={() => advance()}\n onPrevious={() => setCurrentStep((s) => Math.max(s - 1, 1))}\n onSkip={() => setCurrentStep((s) => Math.min(s + 1, steps.length))}\n onClose={onClose}\n renderPreview={renderPreview}\n className={className}\n />\n );\n};\n\nexport type { QuestionStep, QuestionAnswers, Props as QuestionBlockProps };\n","import type { ReactNode } from 'react';\n\nimport { FileText } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Props = {\n label: string;\n disabled?: boolean;\n onClick: () => void;\n icon?: ReactNode;\n className?: string;\n};\n\nexport const SuggestedPrompt = ({ label, disabled, onClick, icon, className }: Props) => {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'tailwindcss-preflight tw:flex tw:items-center tw:justify-start tw:gap-2 tw:whitespace-nowrap tw:rounded-lg tw:p-2 tw:text-left tw:text-sm tw:font-medium tw:text-foreground tw:transition-colors tw:not-disabled:hover:bg-muted tw:disabled:cursor-not-allowed tw:disabled:opacity-50',\n className,\n )}\n onClick={onClick}\n >\n {icon ?? (\n // Lucide icons are stroke-based — paint the visible line with the AI\n // gradient (no fill, so the glyph keeps its outline silhouette instead\n // of becoming a solid block). The `*` selector catches every shape\n // element (path, circle, polyline, …) so multi-part icons don't lose\n // sub-shapes the way `path`-only selectors do.\n <FileText className=\"tw:size-4 tw:shrink-0 tw:basis-4 tw:[&_*]:stroke-aigradient-600\" />\n )}\n <div className=\"tw:whitespace-normal tw:text-left\">{label}</div>\n </button>\n );\n};\n","import { Loader2 } from '../../icons';\n\ntype ThinkingIndicatorProps = {\n label?: string;\n};\n\nexport const ThinkingIndicator = ({ label = 'Thinking...' }: ThinkingIndicatorProps) => {\n return (\n <div className=\"tw:flex tw:items-center tw:gap-2\" data-testid=\"chat-thinking-indicator\">\n <Loader2 className=\"tw:size-4 tw:animate-spin tw:text-secondary-500\" />\n <span className=\"tw:text-sm tw:italic tw:text-secondary-500\">{label}</span>\n </div>\n );\n};\n","import { type ReactNode, useEffect } from 'react';\n\nimport { Badge } from '../../../components/Badge';\nimport { Button } from '../../../components/Button';\nimport { cn } from '../../../utils';\n\ntype ToolCallApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired';\n\ntype ToolCallApprovalProps = {\n /** The tool being called (e.g. `run_sql`). Rendered as a monospace tag. */\n toolName: string;\n /** Human-readable summary of what the tool will do. */\n title?: ReactNode;\n status: ToolCallApprovalStatus;\n onApprove?: () => void;\n onReject?: () => void;\n /** App-rendered detail — a diff, a `ToolCallChip`, a chart, arguments. */\n children?: ReactNode;\n /**\n * Replaces the default Approve/Reject buttons in the pending state. Use when\n * the call needs bespoke controls (e.g. an inline reason field).\n */\n actions?: ReactNode;\n isSubmitting?: boolean;\n /**\n * Opt into `Enter` = approve / `Escape` = reject while pending. Off by\n * default so the shortcuts never fire unexpectedly in a busy chat.\n */\n enableShortcuts?: boolean;\n approveLabel?: string;\n rejectLabel?: string;\n className?: string;\n};\n\nconst STATUS_BADGE: Record<\n ToolCallApprovalStatus,\n { label: string; color: 'blue' | 'green' | 'red' | 'gray' }\n> = {\n pending: { label: 'Needs approval', color: 'blue' },\n approved: { label: 'Approved', color: 'green' },\n rejected: { label: 'Rejected', color: 'red' },\n expired: { label: 'Expired', color: 'gray' },\n};\n\n/**\n * Per-tool-call approve/reject frame — the granular sibling of `PlanApproval`\n * (which approves a whole plan). Chrome + status + actions only: the app\n * renders the call detail as `children` and owns the SDK/permission wiring.\n */\nexport const ToolCallApproval = ({\n toolName,\n title,\n status,\n onApprove,\n onReject,\n children,\n actions,\n isSubmitting = false,\n enableShortcuts = false,\n approveLabel = 'Approve',\n rejectLabel = 'Reject',\n className,\n}: ToolCallApprovalProps) => {\n const isPending = status === 'pending';\n const hasCustomActions = actions != null;\n const showDefaultActions = isPending && !hasCustomActions && Boolean(onApprove || onReject);\n // Custom actions, like the defaults, only make sense while a decision is\n // still pending — never leave controls visible in a terminal state.\n const showActions = isPending && (showDefaultActions || hasCustomActions);\n const badge = STATUS_BADGE[status];\n\n useEffect(() => {\n if (!enableShortcuts || !isPending || isSubmitting) return;\n\n const isEditableTarget = (target: EventTarget | null) => {\n if (!(target instanceof HTMLElement)) return false;\n return (\n target.isContentEditable ||\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.tagName === 'SELECT'\n );\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n // Ignore key-repeat and keystrokes typed into a field.\n if (event.repeat || event.defaultPrevented || isEditableTarget(event.target)) return;\n\n if (\n event.key === 'Enter' &&\n !event.shiftKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n onApprove\n ) {\n event.preventDefault();\n onApprove();\n } else if (event.key === 'Escape' && onReject) {\n event.preventDefault();\n onReject();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [enableShortcuts, isPending, isSubmitting, onApprove, onReject]);\n\n return (\n <section\n data-testid=\"tool-call-approval\"\n data-status={status}\n aria-label={typeof title === 'string' ? title : toolName}\n className={cn(\n 'tw:flex tw:w-full tw:max-w-[800px] tw:flex-col tw:gap-3 tw:overflow-hidden tw:rounded-xl tw:border tw:border-solid tw:border-border tw:bg-muted tw:p-4',\n className,\n )}\n >\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n <Badge color={badge.color} variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {badge.label}\n </Badge>\n <code className=\"tw:rounded tw:bg-background tw:px-1.5 tw:py-0.5 tw:font-mono tw:text-xs tw:text-foreground\">\n {toolName}\n </code>\n </div>\n\n {title != null && (\n <p className=\"tw:m-0 tw:text-sm tw:font-medium tw:text-foreground\">{title}</p>\n )}\n\n {children}\n\n {showActions && (\n <div className=\"tw:flex tw:items-center tw:justify-end tw:gap-2 tw:overflow-x-auto\">\n {actions ?? (\n <>\n {onReject && (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onReject}\n disabled={isSubmitting}\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {rejectLabel}\n </Button>\n )}\n {onApprove && (\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onApprove}\n disabled={isSubmitting}\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {approveLabel}\n </Button>\n )}\n </>\n )}\n </div>\n )}\n </section>\n );\n};\n\nexport type { ToolCallApprovalStatus, ToolCallApprovalProps };\n","import type { MouseEventHandler, ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\n\nimport { CircleCheck, CircleX, Loader2 } from '../../../icons';\nimport { cn } from '../../../utils';\n\ntype ToolCallState = 'processing' | 'done' | 'error';\n\ntype ToolCallChipProps = {\n label: ReactNode;\n state: ToolCallState;\n /** Leading icon; defaults to a state glyph (spinner / check / x). */\n icon?: ReactNode;\n /** Trailing node (e.g. a chevron or count). */\n trailing?: ReactNode;\n /** When set, the chip renders as a button and fires this on click. */\n onClick?: MouseEventHandler<HTMLButtonElement>;\n className?: string;\n};\n\nconst chipClasses = cva(\n [\n 'tw:inline-flex tw:items-center tw:gap-1.5 tw:rounded-md tw:border tw:border-solid',\n 'tw:border-border tw:bg-muted tw:px-2 tw:py-1 tw:text-xs tw:text-foreground',\n ],\n {\n variants: {\n interactive: {\n true: 'tw:cursor-pointer tw:focus-visible:outline-hidden tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:not-disabled:hover:bg-accent',\n false: '',\n },\n },\n defaultVariants: { interactive: false },\n },\n);\n\nconst StateIcon = ({ state }: { state: ToolCallState }) => {\n if (state === 'processing') {\n return <Loader2 className=\"tw:size-3.5 tw:shrink-0 tw:animate-spin tw:text-muted-foreground\" />;\n }\n if (state === 'error') {\n return <CircleX className=\"tw:size-3.5 tw:shrink-0 tw:text-error-500\" />;\n }\n return <CircleCheck className=\"tw:size-3.5 tw:shrink-0 tw:text-primary\" />;\n};\n\n/**\n * Presentational chip summarising a single tool call (icon + label + optional\n * trailing action). It has **no** URL/router knowledge — wrap it in a `Link`\n * or pass `onClick` for navigation; the app owns deep-linking.\n */\nexport const ToolCallChip = ({\n label,\n state,\n icon,\n trailing,\n onClick,\n className,\n}: ToolCallChipProps) => {\n const content = (\n <>\n {icon ?? <StateIcon state={state} />}\n <span className=\"tw:min-w-0 tw:truncate\">{label}</span>\n {trailing != null && (\n <span className=\"tw:ml-auto tw:inline-flex tw:shrink-0 tw:items-center\">{trailing}</span>\n )}\n </>\n );\n\n if (onClick) {\n return (\n <button\n type=\"button\"\n data-testid=\"tool-call-chip\"\n data-state={state}\n onClick={onClick}\n className={cn('tailwindcss-preflight', chipClasses({ interactive: true }), className)}\n >\n {content}\n </button>\n );\n }\n\n return (\n <span\n data-testid=\"tool-call-chip\"\n data-state={state}\n className={cn(chipClasses({ interactive: false }), className)}\n >\n {content}\n </span>\n );\n};\n\nexport type { ToolCallChipProps, ToolCallState };\n","/** Clamp a percentage to 0–100 and normalize non-finite input to 0. */\nexport const clampPercentage = (value: number) =>\n Number.isFinite(value) ? Math.min(100, Math.max(0, value)) : 0;\n","import { cn } from '../../utils';\n\nimport { clampPercentage } from './usageStatsHelpers';\n\ntype Props = {\n value: number;\n size?: number;\n strokeWidth?: number;\n className?: string;\n};\n\nexport const UsageStatsRing = ({ value, size = 16, strokeWidth = 2.5, className }: Props) => {\n const radius = Math.max(0, (size - strokeWidth) / 2 - 1);\n const circumference = 2 * Math.PI * radius;\n const offset = circumference * (1 - clampPercentage(value) / 100);\n\n return (\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n className={cn('tw:-rotate-90', className)}\n role=\"presentation\"\n >\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={strokeWidth}\n className=\"tw:stroke-neutral-400 tw:opacity-50\"\n />\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n className=\"tw:stroke-primary tw:transition-all\"\n />\n </svg>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { HoverCard } from '../../components/HoverCard';\nimport { AlertCircle } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { clampPercentage } from './usageStatsHelpers';\nimport { UsageStatsRing } from './UsageStatsRing';\n\ntype Props = {\n value: number;\n alert?: boolean;\n children: ReactNode;\n className?: string;\n /**\n * Accessible name for the trigger. Defaults to a value-aware label so\n * screen-reader users get the same information the ring conveys visually.\n */\n ariaLabel?: string;\n align?: ComponentProps<typeof HoverCard.Content>['align'];\n side?: ComponentProps<typeof HoverCard.Content>['side'];\n sideOffset?: ComponentProps<typeof HoverCard.Content>['sideOffset'];\n};\n\nexport const UsageStats = ({\n value,\n alert = false,\n children,\n className,\n ariaLabel,\n align = 'end',\n side = 'top',\n sideOffset = 8,\n}: Props) => {\n const defaultLabel = `Usage: ${Math.round(clampPercentage(value))}%${alert ? ' (usage alert)' : ''}`;\n return (\n <HoverCard>\n <HoverCard.Trigger asChild>\n <span\n aria-label={ariaLabel ?? defaultLabel}\n className={cn(\n 'tw:relative tw:inline-flex tw:size-8 tw:items-center tw:justify-center',\n className,\n )}\n >\n <UsageStatsRing value={value} />\n {alert && (\n <AlertCircle\n data-testid=\"usage-stats-alert\"\n className=\"tw:absolute tw:-right-0.5 tw:-top-0.5 tw:size-3 tw:text-error-500\"\n />\n )}\n </span>\n </HoverCard.Trigger>\n\n <HoverCard.Content align={align} side={side} sideOffset={sideOffset}>\n {children}\n </HoverCard.Content>\n </HoverCard>\n );\n};\n"],"mappings":"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"}