@keboola/design 11.3.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 (229) hide show
  1. package/AGENTS.md +17 -0
  2. package/CHANGELOG.md +170 -0
  3. package/COMPONENT-API.md +32 -31
  4. package/dist/{AIKit-DaFT7p92.js → AIKit-DDg5DBCG.js} +142 -63
  5. package/dist/AIKit-DDg5DBCG.js.map +1 -0
  6. package/dist/{Alert-CseY3yAj.js → Alert-DHJFrWnS.js} +3 -3
  7. package/dist/{Alert-CseY3yAj.js.map → Alert-DHJFrWnS.js.map} +1 -1
  8. package/dist/{AlertModal-DQAGpsEy.js → AlertModal-BGJdaRRj.js} +3 -3
  9. package/dist/{AlertModal-DQAGpsEy.js.map → AlertModal-BGJdaRRj.js.map} +1 -1
  10. package/dist/{AppShell-BUoxM3fv.js → AppShell-DRgJxpXW.js} +2 -2
  11. package/dist/{AppShell-BUoxM3fv.js.map → AppShell-DRgJxpXW.js.map} +1 -1
  12. package/dist/{BrandEditor-BnTLMRMp.js → BrandEditor-Go7w8Zj2.js} +7 -7
  13. package/dist/{BrandEditor-BnTLMRMp.js.map → BrandEditor-Go7w8Zj2.js.map} +1 -1
  14. package/dist/{BrandLogo-V2pRUAeO.js → BrandLogo-Dmi7jo21.js} +2 -2
  15. package/dist/{BrandLogo-V2pRUAeO.js.map → BrandLogo-Dmi7jo21.js.map} +1 -1
  16. package/dist/{Breadcrumb-CQTPn_KB.js → Breadcrumb-uEkM6adI.js} +3 -3
  17. package/dist/{Breadcrumb-CQTPn_KB.js.map → Breadcrumb-uEkM6adI.js.map} +1 -1
  18. package/dist/{Button-CPsEQuTN.js → Button-DsRrU5F1.js} +6 -5
  19. package/dist/Button-DsRrU5F1.js.map +1 -0
  20. package/dist/{Card-Cd5HSBmv.js → Card-Dyo7055Q.js} +2 -2
  21. package/dist/{Card-Cd5HSBmv.js.map → Card-Dyo7055Q.js.map} +1 -1
  22. package/dist/{Checkbox-5VNCcV7E.js → Checkbox-fC0BuO2B.js} +3 -3
  23. package/dist/{Checkbox-5VNCcV7E.js.map → Checkbox-fC0BuO2B.js.map} +1 -1
  24. package/dist/{Clipboard-B7rckqV_.js → Clipboard-ChPdiUy3.js} +2 -2
  25. package/dist/{Clipboard-B7rckqV_.js.map → Clipboard-ChPdiUy3.js.map} +1 -1
  26. package/dist/{ClipboardButton-CQ6Aewpg.js → ClipboardButton-D9pDjgkB.js} +3 -3
  27. package/dist/{ClipboardButton-CQ6Aewpg.js.map → ClipboardButton-D9pDjgkB.js.map} +1 -1
  28. package/dist/{CodeEditor-CUse8znx.js → CodeEditor-Cxy3HnKH.js} +15 -26
  29. package/dist/CodeEditor-Cxy3HnKH.js.map +1 -0
  30. package/dist/{ColorInput-Q1D9Vcc_.js → ColorInput-Bxj-1eLT.js} +3 -3
  31. package/dist/{ColorInput-Q1D9Vcc_.js.map → ColorInput-Bxj-1eLT.js.map} +1 -1
  32. package/dist/{ColorModeSwitch-B5PXCVqB.js → ColorModeSwitch-CsWLiTBX.js} +3 -3
  33. package/dist/{ColorModeSwitch-B5PXCVqB.js.map → ColorModeSwitch-CsWLiTBX.js.map} +1 -1
  34. package/dist/{Combobox-CyoRA7oY.js → Combobox-Cs_1pj2q.js} +29 -22
  35. package/dist/Combobox-Cs_1pj2q.js.map +1 -0
  36. package/dist/{Command-Ds68v2rX.js → Command-B7ML9YMv.js} +6 -6
  37. package/dist/{Command-Ds68v2rX.js.map → Command-B7ML9YMv.js.map} +1 -1
  38. package/dist/{CopyField-DI66uY_g.js → CopyField-BO_sh-HO.js} +2 -2
  39. package/dist/{CopyField-DI66uY_g.js.map → CopyField-BO_sh-HO.js.map} +1 -1
  40. package/dist/{DateInput-BPj2pzsn.js → DateInput-ZdaMQo5i.js} +4 -4
  41. package/dist/{DateInput-BPj2pzsn.js.map → DateInput-ZdaMQo5i.js.map} +1 -1
  42. package/dist/{DatePicker-DyEGuW9m.js → DatePicker-nA8YdE84.js} +2 -2
  43. package/dist/{DatePicker-DyEGuW9m.js.map → DatePicker-nA8YdE84.js.map} +1 -1
  44. package/dist/{DateRangeInput-u9DxNbHW.js → DateRangeInput-DkvNh_sT.js} +4 -4
  45. package/dist/{DateRangeInput-u9DxNbHW.js.map → DateRangeInput-DkvNh_sT.js.map} +1 -1
  46. package/dist/{DateRangePicker-CYYhX6S7.js → DateRangePicker-DjSUFjh4.js} +5 -5
  47. package/dist/{DateRangePicker-CYYhX6S7.js.map → DateRangePicker-DjSUFjh4.js.map} +1 -1
  48. package/dist/{DropdownMenu-DpMEcyCq.js → DropdownMenu-CASr-jgl.js} +2 -2
  49. package/dist/{DropdownMenu-DpMEcyCq.js.map → DropdownMenu-CASr-jgl.js.map} +1 -1
  50. package/dist/{FieldItem-qQKGU9lF.js → FieldItem-CCd9-xnp.js} +3 -3
  51. package/dist/{FieldItem-qQKGU9lF.js.map → FieldItem-CCd9-xnp.js.map} +1 -1
  52. package/dist/{FileUpload-C336MVnU.js → FileUpload-ABThVZyg.js} +2 -2
  53. package/dist/{FileUpload-C336MVnU.js.map → FileUpload-ABThVZyg.js.map} +1 -1
  54. package/dist/{Form-CTygENDc.js → Form-k6PH-em3.js} +8 -8
  55. package/dist/{Form-CTygENDc.js.map → Form-k6PH-em3.js.map} +1 -1
  56. package/dist/{FormGroup-BnwP0jNu.js → FormGroup-DbcDtrgU.js} +3 -3
  57. package/dist/{FormGroup-BnwP0jNu.js.map → FormGroup-DbcDtrgU.js.map} +1 -1
  58. package/dist/{FullScreenModal-j-M4aPFd.js → FullScreenModal-BvPuYibe.js} +3 -3
  59. package/dist/{FullScreenModal-j-M4aPFd.js.map → FullScreenModal-BvPuYibe.js.map} +1 -1
  60. package/dist/{HoverCard-yQq-O49c.js → HoverCard-B9ZMJxjn.js} +2 -2
  61. package/dist/{HoverCard-yQq-O49c.js.map → HoverCard-B9ZMJxjn.js.map} +1 -1
  62. package/dist/{InputGroup-D7zlmqPB.js → InputGroup-BnLHY0eq.js} +3 -3
  63. package/dist/{InputGroup-D7zlmqPB.js.map → InputGroup-BnLHY0eq.js.map} +1 -1
  64. package/dist/{Kbd-D6LpR7G2.js → Kbd-CvSM3D3-.js} +2 -2
  65. package/dist/{Kbd-D6LpR7G2.js.map → Kbd-CvSM3D3-.js.map} +1 -1
  66. package/dist/MarkedText-DNGEUVWc.js +67 -0
  67. package/dist/MarkedText-DNGEUVWc.js.map +1 -0
  68. package/dist/{MermaidDiagram-JlvuGcY-.js → MermaidDiagram-WkonYErO.js} +3 -3
  69. package/dist/{MermaidDiagram-JlvuGcY-.js.map → MermaidDiagram-WkonYErO.js.map} +1 -1
  70. package/dist/{Modal-o4ATIexE.js → Modal-Coj-H02o.js} +16 -4
  71. package/dist/Modal-Coj-H02o.js.map +1 -0
  72. package/dist/{MultiActionButtonGroup-GTeFk-L8.js → MultiActionButtonGroup-CxWH7yWK.js} +3 -3
  73. package/dist/{MultiActionButtonGroup-GTeFk-L8.js.map → MultiActionButtonGroup-CxWH7yWK.js.map} +1 -1
  74. package/dist/{Navbar-CAQs4BZz.js → Navbar-B2UsolVU.js} +3 -3
  75. package/dist/{Navbar-CAQs4BZz.js.map → Navbar-B2UsolVU.js.map} +1 -1
  76. package/dist/{PageToolbar-bG2YtSa3.js → PageToolbar-DnbFt14Q.js} +3 -3
  77. package/dist/{PageToolbar-bG2YtSa3.js.map → PageToolbar-DnbFt14Q.js.map} +1 -1
  78. package/dist/{Pagination-BB3X7ooY.js → Pagination-C_b7Xhey.js} +2 -2
  79. package/dist/{Pagination-BB3X7ooY.js.map → Pagination-C_b7Xhey.js.map} +1 -1
  80. package/dist/{Popconfirm-C2Ky5hJO.js → Popconfirm-CILjmzKI.js} +3 -3
  81. package/dist/{Popconfirm-C2Ky5hJO.js.map → Popconfirm-CILjmzKI.js.map} +1 -1
  82. package/dist/{Popover-DsbI2HKu.js → Popover-BEbQrC_P.js} +22 -19
  83. package/dist/Popover-BEbQrC_P.js.map +1 -0
  84. package/dist/{RadioGroup-BMxuZEbT.js → RadioGroup-XFzFd1ti.js} +3 -3
  85. package/dist/{RadioGroup-BMxuZEbT.js.map → RadioGroup-XFzFd1ti.js.map} +1 -1
  86. package/dist/{Search-DFeECt5D.js → Search-4Bxtt8hS.js} +2 -2
  87. package/dist/{Search-DFeECt5D.js.map → Search-4Bxtt8hS.js.map} +1 -1
  88. package/dist/{SearchInput-CCpdUego.js → SearchInput-f_oY9T4Z.js} +3 -3
  89. package/dist/{SearchInput-CCpdUego.js.map → SearchInput-f_oY9T4Z.js.map} +1 -1
  90. package/dist/{SectionNav-Bw_MVL0_.js → SectionNav-BpJlisbT.js} +4 -4
  91. package/dist/{SectionNav-Bw_MVL0_.js.map → SectionNav-BpJlisbT.js.map} +1 -1
  92. package/dist/{Select-D6IZVvwL.js → Select-DpcgKqKB.js} +31 -20
  93. package/dist/Select-DpcgKqKB.js.map +1 -0
  94. package/dist/{Sheet-BIzs2K2H.js → Sheet-Chf0kX1E.js} +3 -3
  95. package/dist/{Sheet-BIzs2K2H.js.map → Sheet-Chf0kX1E.js.map} +1 -1
  96. package/dist/{Sidebar-r1TW4g_b.js → Sidebar-Cm6I4dE1.js} +9 -7
  97. package/dist/{Sidebar-r1TW4g_b.js.map → Sidebar-Cm6I4dE1.js.map} +1 -1
  98. package/dist/{Slider-CjxyfEty.js → Slider-pPC_3gz9.js} +3 -3
  99. package/dist/{Slider-CjxyfEty.js.map → Slider-pPC_3gz9.js.map} +1 -1
  100. package/dist/{Switch-BueTV03C.js → Switch-ChfPKcTE.js} +2 -2
  101. package/dist/{Switch-BueTV03C.js.map → Switch-ChfPKcTE.js.map} +1 -1
  102. package/dist/{Tabs-l72-WuhK.js → Tabs-eB974xJf.js} +2 -2
  103. package/dist/{Tabs-l72-WuhK.js.map → Tabs-eB974xJf.js.map} +1 -1
  104. package/dist/{TextInput-DhdRk8qm.js → TextInput-DHM6dHmn.js} +3 -3
  105. package/dist/{TextInput-DhdRk8qm.js.map → TextInput-DHM6dHmn.js.map} +1 -1
  106. package/dist/{ThemeProvider-DZfGdf1v.js → ThemeProvider-DrQJtzpd.js} +90 -15
  107. package/dist/ThemeProvider-DrQJtzpd.js.map +1 -0
  108. package/dist/{TimePicker-B6d2rAbX.js → TimePicker-BGeqc-Ed.js} +2 -2
  109. package/dist/{TimePicker-B6d2rAbX.js.map → TimePicker-BGeqc-Ed.js.map} +1 -1
  110. package/dist/{Toast-CxXUulYN.js → Toast-Dr6Uw7ao.js} +2 -2
  111. package/dist/{Toast-CxXUulYN.js.map → Toast-Dr6Uw7ao.js.map} +1 -1
  112. package/dist/{ZoomableSvg-CNIzRHKH.js → ZoomableSvg-BWnDkR61.js} +4 -4
  113. package/dist/{ZoomableSvg-CNIzRHKH.js.map → ZoomableSvg-BWnDkR61.js.map} +1 -1
  114. package/dist/{context-BrNtMc1H.js → context-D7X470dy.js} +4 -3
  115. package/dist/context-D7X470dy.js.map +1 -0
  116. package/dist/{defaults-CTfvj2KB.js → defaults-i_xG2F_1.js} +2 -4
  117. package/dist/defaults-i_xG2F_1.js.map +1 -0
  118. package/dist/editors.js +4 -4
  119. package/dist/findLiteralMatches-BGBw8Vbl.js +62 -0
  120. package/dist/findLiteralMatches-BGBw8Vbl.js.map +1 -0
  121. package/dist/flint.js +3 -3
  122. package/dist/index.d.ts +677 -527
  123. package/dist/index.js +59 -58
  124. package/dist/internal/blocks/AIKit.js +2 -2
  125. package/dist/internal/blocks/AppShell.js +1 -1
  126. package/dist/internal/blocks/BrandEditor.js +1 -1
  127. package/dist/internal/blocks/ChartPanel.js +1 -1
  128. package/dist/internal/blocks/ClipboardButton.js +1 -1
  129. package/dist/internal/blocks/ColorInput.js +1 -1
  130. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  131. package/dist/internal/blocks/Command.js +1 -1
  132. package/dist/internal/blocks/CopyField.js +1 -1
  133. package/dist/internal/blocks/DateInput.js +1 -1
  134. package/dist/internal/blocks/DateRangeInput.js +1 -1
  135. package/dist/internal/blocks/EmptyConfigurationActionCard.js +1 -1
  136. package/dist/internal/blocks/ErrorState.js +1 -1
  137. package/dist/internal/blocks/ExportMenu.js +5 -5
  138. package/dist/internal/blocks/ExportMenu.js.map +1 -1
  139. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
  140. package/dist/internal/blocks/Form.js +1 -1
  141. package/dist/internal/blocks/FormGroup.js +1 -1
  142. package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
  143. package/dist/internal/blocks/MultiCombobox.js +14 -11
  144. package/dist/internal/blocks/MultiCombobox.js.map +1 -1
  145. package/dist/internal/blocks/NumberInput.js +1 -1
  146. package/dist/internal/blocks/PageToolbar.js +1 -1
  147. package/dist/internal/blocks/PasswordInput.js +2 -2
  148. package/dist/internal/blocks/SearchInput.js +1 -1
  149. package/dist/internal/blocks/SearchInputWithNavigation.js +3 -3
  150. package/dist/internal/blocks/SectionNav.js +1 -1
  151. package/dist/internal/blocks/SplitButton.js +2 -2
  152. package/dist/internal/blocks/StatCard.js +1 -1
  153. package/dist/internal/blocks/TextInput.js +1 -1
  154. package/dist/internal/blocks/Textarea.js +1 -1
  155. package/dist/internal/blocks/TimeInput.js +3 -3
  156. package/dist/internal/components/Alert.js +1 -1
  157. package/dist/internal/components/AlertModal.js +1 -1
  158. package/dist/internal/components/Avatar.js +1 -1
  159. package/dist/internal/components/BrandLogo.js +1 -1
  160. package/dist/internal/components/Breadcrumb.js +1 -1
  161. package/dist/internal/components/Button.js +1 -1
  162. package/dist/internal/components/Card.js +1 -1
  163. package/dist/internal/components/Checkbox.js +1 -1
  164. package/dist/internal/components/Clipboard.js +1 -1
  165. package/dist/internal/components/CollapsiblePanel.js +1 -1
  166. package/dist/internal/components/Combobox.js +1 -1
  167. package/dist/internal/components/DatePicker.js +1 -1
  168. package/dist/internal/components/DateRangePicker.js +1 -1
  169. package/dist/internal/components/DropdownMenu.js +1 -1
  170. package/dist/internal/components/FileUpload.js +1 -1
  171. package/dist/internal/components/FullScreenModal.js +1 -1
  172. package/dist/internal/components/HoverCard.js +1 -1
  173. package/dist/internal/components/InputGroup.js +1 -1
  174. package/dist/internal/components/Kbd.js +1 -1
  175. package/dist/internal/components/MarkedText.js +1 -1
  176. package/dist/internal/components/Modal.js +1 -1
  177. package/dist/internal/components/Navbar.js +1 -1
  178. package/dist/internal/components/Pagination.js +1 -1
  179. package/dist/internal/components/Popconfirm.js +1 -1
  180. package/dist/internal/components/Popover.js +1 -1
  181. package/dist/internal/components/RadioGroup.js +1 -1
  182. package/dist/internal/components/Search.js +1 -1
  183. package/dist/internal/components/Select.js +1 -1
  184. package/dist/internal/components/Sheet.js +1 -1
  185. package/dist/internal/components/Sidebar.js +1 -1
  186. package/dist/internal/components/Slider.js +1 -1
  187. package/dist/internal/components/Switch.js +1 -1
  188. package/dist/internal/components/Tabs.js +1 -1
  189. package/dist/internal/components/ThemeProvider.js +4 -4
  190. package/dist/internal/components/TimePicker.js +1 -1
  191. package/dist/internal/components/Toast.js +2 -2
  192. package/dist/internal/components/Toggle.js +3 -3
  193. package/dist/internal/components/Toggle.js.map +1 -1
  194. package/dist/internal/components/Tooltip.js +1 -1
  195. package/dist/internal/components/Truncated.js +1 -1
  196. package/dist/internal/components/ZoomableSvg.js +1 -1
  197. package/dist/internal/utils.js +3 -3
  198. package/dist/markdown-editor.js +7 -7
  199. package/dist/mermaid.js +1 -1
  200. package/dist/rjsf.js +11 -11
  201. package/dist/styles.css +1 -1
  202. package/dist/testing.js +4 -4
  203. package/dist/testing.js.map +1 -1
  204. package/dist/{themeTokens-7T1AFLhq.js → themeTokens-D70HeNVF.js} +3 -3
  205. package/dist/{themeTokens-7T1AFLhq.js.map → themeTokens-D70HeNVF.js.map} +1 -1
  206. package/dist/{toast-BweSoKn3.js → toast-DIC0iNRf.js} +2 -2
  207. package/dist/{toast-BweSoKn3.js.map → toast-DIC0iNRf.js.map} +1 -1
  208. package/dist/{useColorSchemeState-BJEk6esG.js → useColorSchemeState-klihG9-i.js} +2 -2
  209. package/dist/{useColorSchemeState-BJEk6esG.js.map → useColorSchemeState-klihG9-i.js.map} +1 -1
  210. package/dist/{utils-B-g7d_Jb.js → utils-B5Z52hYs.js} +2 -2
  211. package/dist/{utils-B-g7d_Jb.js.map → utils-B5Z52hYs.js.map} +1 -1
  212. package/dist/vega.js +2 -2
  213. package/dist/{vegaTheme-FBXgAdHK.js → vegaTheme-DfoEQhOy.js} +2 -2
  214. package/dist/{vegaTheme-FBXgAdHK.js.map → vegaTheme-DfoEQhOy.js.map} +1 -1
  215. package/package.json +5 -5
  216. package/dist/AIKit-DaFT7p92.js.map +0 -1
  217. package/dist/Button-CPsEQuTN.js.map +0 -1
  218. package/dist/CodeEditor-CUse8znx.js.map +0 -1
  219. package/dist/Combobox-CyoRA7oY.js.map +0 -1
  220. package/dist/MarkedText-Ckbft5mw.js +0 -44
  221. package/dist/MarkedText-Ckbft5mw.js.map +0 -1
  222. package/dist/Modal-o4ATIexE.js.map +0 -1
  223. package/dist/Popover-DsbI2HKu.js.map +0 -1
  224. package/dist/Select-D6IZVvwL.js.map +0 -1
  225. package/dist/ThemeProvider-DZfGdf1v.js.map +0 -1
  226. package/dist/context-BrNtMc1H.js.map +0 -1
  227. package/dist/defaults-CTfvj2KB.js.map +0 -1
  228. package/dist/escapeStringRegexp-8MxP2knR.js +0 -6
  229. package/dist/escapeStringRegexp-8MxP2knR.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"AIKit-DaFT7p92.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 '../DiagramShared/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\n// Code surfaces are painted here rather than left to Tailwind Typography, whose\n// palette is pinned to light-mode values. The fill is the same `--muted` /\n// `--foreground` pair `styles.css` gives `.tw\\:prose blockquote` — the file's\n// idiom for an inset surface — so both follow the colour scheme and the brand.\n//\n// The colour has to be stated on `pre` and on inline `code` separately:\n// `[data-theme='dark'] .tw\\:prose` applies `prose-invert`, whose `code` rules are\n// `:where()`-wrapped, so these utilities win on specificity. Set only the fill\n// and dark mode pairs an inverted light text with it.\nconst proseClass =\n 'tw:prose tw:prose-sm tw:max-w-none tw:break-words tw:[&_pre]:bg-muted tw:[&_pre]:text-foreground tw:[&_:not(pre)>code]:bg-muted tw:[&_:not(pre)>code]:text-foreground 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 — including ```flint, deliberately,\n * as this is the reduced-capability renderer — 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-card tw:text-card-foreground 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\">{question}</p>\n {header && (\n <p className=\"tw:m-0 tw:text-xs tw:leading-4 tw:text-muted-foreground\">{header}</p>\n )}\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-accent\"\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\">{option.label}</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 data-testid=\"question-option-preview\"\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-border tw:bg-muted tw:p-2 tw:text-foreground',\n )}\n >\n {renderPreview ? (\n renderPreview(option.preview)\n ) : (\n // `text-foreground` restates the ink the box above already\n // sets, and is not redundant: consuming apps ship a global\n // `pre { color; background-color; border }` rule that beats\n // inheritance but loses to a utility — the same reason\n // `border-0` and `bg-transparent` are spelled out here.\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-foreground\">\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-accent\"\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',\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-border',\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-muted-foreground\">\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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Button-CPsEQuTN.js","names":[],"sources":["../src/components/Button/styles.ts","../src/components/Button/Button.tsx","../src/components/Button/ButtonInline.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\n\nexport const variants = cva(\n [\n 'tailwindcss-preflight',\n 'tw:group/button',\n 'tw:border-box',\n\n // layout\n 'tw:relative',\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:gap-2',\n\n // text — chrome weight/tracking are brand-overridable tokens\n // (`--font-weight-medium` / `--letter-spacing-chrome`). Casing: standard case is\n // the default; only legacy brands (`keboola-legacy-*`) uppercase the chrome, so\n // modern brands (incl. Keboola V2) read naturally. Mirrors the V2 standard-case\n // treatment shipped for Tooltip/Badge (PR 7629).\n 'tw:text-xs',\n 'tw:leading-5',\n 'tw:font-medium',\n 'tw:[[data-brand^=keboola-legacy]_&]:tracking-chrome',\n 'tw:[[data-brand^=keboola-legacy]_&]:uppercase',\n\n // border — legacy (non-argo) chrome uses a fixed radius, not the brand token.\n 'tw:rounded',\n 'tw:border',\n 'tw:border-transparent',\n\n // styling\n 'tw:shadow-none',\n 'tw:[a]:cursor-pointer', // explicitly set for anchor\n\n 'tw:focus-visible:outline',\n 'tw:focus-visible:outline-1',\n 'tw:focus-visible:-outline-offset-1',\n 'tw:focus-visible:outline-ring',\n 'tw:focus-visible:ring-4',\n 'tw:focus-visible:ring-ring/30',\n\n // disabled\n 'tw:disabled:opacity-40',\n 'tw:disabled:cursor-not-allowed',\n\n // anchor support\n 'tw:!no-underline',\n 'tw:aria-disabled:opacity-40',\n 'tw:aria-disabled:cursor-not-allowed',\n\n 'tw:[&_svg]:shrink-0',\n ],\n {\n defaultVariants: {\n size: 'medium',\n variant: 'primary',\n block: false,\n },\n variants: {\n block: {\n true: ['tw:w-full'],\n },\n variant: {\n primary: [\n 'tw:text-white',\n 'tw:bg-primary-500',\n\n 'tw:focus:text-white',\n 'tw:hover:text-white',\n 'tw:hover:not-disabled:bg-primary-600',\n 'tw:active:not-disabled:bg-primary-800',\n\n // anchor disabled override\n 'tw:aria-disabled:!bg-primary-500',\n ],\n secondary: [\n 'tw:text-white',\n 'tw:bg-secondary-500',\n\n 'tw:focus:text-white',\n 'tw:hover:text-white',\n 'tw:hover:not-disabled:bg-secondary-700',\n 'tw:active:not-disabled:bg-secondary-800',\n\n // anchor disabled override\n 'tw:aria-disabled:!bg-secondary-500',\n ],\n danger: [\n 'tw:text-white',\n 'tw:bg-error-500',\n\n 'tw:focus:text-white',\n 'tw:hover:text-white',\n 'tw:hover:not-disabled:bg-error-600',\n 'tw:active:not-disabled:bg-error-700',\n\n // anchor disabled override\n 'tw:aria-disabled:!bg-error-500',\n ],\n // The label and the hover/active fills read tokens rather than the fixed\n // neutral scale, so the variant follows the active brand and colour scheme\n // (argo's `invisible` already did). A transparent button inherits whatever\n // surface it is dropped on, so it is the one legacy variant that cannot\n // assume a light page — pinning it forced every dark-scheme call site to\n // re-declare the colour by hand.\n invisible: [\n 'tw:text-foreground',\n 'tw:bg-transparent',\n\n 'tw:focus:text-foreground',\n 'tw:hover:not-disabled:bg-muted',\n 'tw:hover:text-foreground',\n 'tw:active:not-disabled:bg-secondary',\n\n // contrasting icon on hover/active\n 'tw:[&_svg]:text-neutral-400',\n 'tw:hover:not-disabled:[&_svg]:text-secondary-600',\n 'tw:active:not-disabled:[&_svg]:text-secondary-600',\n\n // anchor disabled override\n 'tw:aria-disabled:!bg-transparent',\n ],\n outline: [\n 'tw:text-foreground',\n 'tw:bg-card',\n // border\n 'tw:!border-input',\n 'tw:hover:text-foreground',\n 'tw:focus:text-foreground',\n // Hover/pressed fills and the hover border are `muted-foreground` tints, not\n // tokens of their own: a tint composites over `bg-card` and so steps visibly in\n // either scheme, where `bg-muted` sits 4/255 from `bg-card` in the dark one.\n 'tw:hover:not-disabled:!border-muted-foreground/60',\n 'tw:hover:not-disabled:bg-muted-foreground/15',\n 'tw:active:not-disabled:bg-muted-foreground/35',\n\n // contrasting icon hover, same as invisible\n 'tw:[&_svg]:text-muted-foreground',\n 'tw:not-disabled:hover:[&_svg]:text-secondary-600',\n 'tw:active:not-disabled:[&_svg]:text-secondary-600',\n\n // anchor disabled override\n 'tw:aria-disabled:!bg-card',\n 'tw:aria-disabled:!border-input',\n ],\n\n inline: [\n 'tw:text-foreground',\n 'tw:bg-transparent',\n 'tw:rounded-full',\n\n 'tw:[&_svg]:text-muted-foreground',\n 'tw:not-disabled:hover:[&_svg]:text-secondary-600',\n 'tw:not-disabled:focus:[&_svg]:text-secondary-600',\n ],\n },\n size: {\n medium: [\n 'tw:max-h-10',\n 'tw:min-h-10',\n 'tw:px-4',\n 'tw:py-2.5',\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4',\n ],\n small: [\n 'tw:max-h-8',\n 'tw:min-h-8',\n 'tw:px-4',\n 'tw:py-1.5',\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4',\n ],\n large: [\n 'tw:max-h-12',\n 'tw:min-h-12',\n 'tw:px-4',\n 'tw:py-3.5',\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4',\n ],\n\n 'icon-lg': ['tw:size-12', 'tw:p-0', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-6'],\n icon: ['tw:size-10', 'tw:p-0', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4'],\n 'icon-sm': ['tw:size-8', 'tw:p-0', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4'],\n 'icon-xs': ['tw:size-6', 'tw:p-0', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4'],\n 'icon-2xs': [\n 'tw:!inline-flex',\n 'tw:size-5',\n 'tw:max-h-5',\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-3',\n ],\n 'icon-3xs': ['tw:h-fit', 'tw:w-fit', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4'],\n },\n },\n },\n);\n\nexport const argoVariants = cva(\n [\n 'tailwindcss-preflight',\n\n // layout\n 'tw:relative',\n 'tw:inline-flex',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:whitespace-nowrap',\n 'tw:gap-2',\n\n // border\n 'tw:border',\n 'tw:border-transparent',\n 'tw:rounded-[var(--radius-lg,0.25rem)]',\n\n // text\n 'tw:font-medium',\n 'tw:select-none',\n\n // focus visible\n 'tw:!outline-hidden',\n 'tw:focus-visible:ring-2',\n\n // disabled\n 'tw:disabled:cursor-not-allowed',\n 'tw:disabled:opacity-50',\n 'tw:active:opacity-60',\n\n 'tw:transition-all',\n 'tw:bg-clip-padding',\n\n // anchor support\n 'tw:!no-underline',\n 'tw:aria-disabled:cursor-not-allowed',\n 'tw:aria-disabled:opacity-50',\n\n // icon\n 'tw:shrink-0',\n 'tw:[&_svg]:pointer-events-none',\n 'tw:[&_svg]:shrink-0',\n \"tw:[&_svg:not([class*='tw:size-'])]:size-4\",\n ],\n {\n defaultVariants: {\n variant: 'primary',\n size: 'medium',\n },\n variants: {\n block: {\n true: ['tw:w-full'],\n },\n variant: {\n primary: [\n 'tw:bg-primary',\n 'tw:text-primary-foreground',\n 'tw:[a]:hover:bg-primary/80',\n 'tw:hover:not-disabled:bg-primary/90',\n 'tw:hover:text-primary-foreground',\n 'tw:focus:text-primary-foreground',\n\n 'tw:focus-visible:border-primary',\n 'tw:focus-visible:ring-ring/50',\n ],\n secondary: [\n 'tw:bg-primary/10',\n 'tw:text-primary',\n 'tw:hover:not-disabled:bg-primary/20',\n\n 'tw:focus-visible:border-primary',\n 'tw:focus-visible:ring-ring/50',\n ],\n\n // should be called \"destructive\" by Figma\n danger: [\n 'tw:bg-destructive',\n 'tw:text-destructive-foreground',\n 'tw:hover:not-disabled:bg-destructive/90',\n 'tw:hover:text-destructive-foreground',\n 'tw:focus:text-destructive-foreground',\n\n 'tw:focus-visible:border-destructive',\n 'tw:focus-visible:ring-destructive/20',\n ],\n outline: [\n 'tw:!border-input',\n 'tw:bg-background',\n // Semantic base text color so the label/icon flips in dark mode\n // (matches `invisible`); previously unset → inherited a fixed dark color.\n 'tw:text-foreground',\n // Hover follows the brand primary (translucent tint), matching the\n // `secondary` variant — not the fixed `accent` blue.\n 'tw:hover:not-disabled:bg-primary/10',\n 'tw:hover:not-disabled:text-primary',\n 'tw:hover:active:bg-background',\n 'tw:focus-visible:!border-primary',\n 'tw:focus-visible:ring-ring/50',\n ],\n\n // should be called \"ghost\" by Figma\n invisible: [\n 'tw:bg-transparent',\n 'tw:text-foreground',\n 'tw:hover:not-disabled:bg-primary/10',\n 'tw:hover:not-disabled:text-primary',\n 'tw:hover:not-disabled:border-primary/10',\n\n 'tw:focus-visible:ring-ring/50',\n ],\n // should be called \"link\" by Figma\n inline: [\n 'tw:bg-transparent',\n 'tw:text-primary',\n 'tw:hover:underline',\n 'tw:hover:active:bg-transparent',\n 'tw:focus-visible:ring-ring/50',\n ],\n },\n size: {\n // should be called \"default\" by Figma\n medium: ['tw:max-h-9', 'tw:py-2', 'tw:px-4', 'tw:text-sm'],\n // should be called \"small\" by Figma\n small: ['tw:max-h-8', 'tw:py-2', 'tw:px-3', 'tw:text-xs'],\n // should be called \"large\" by Figma\n large: ['tw:max-h-10', 'tw:py-2.5', 'tw:px-6', 'tw:text-sm'],\n\n 'icon-lg': ['tw:size-10'],\n icon: ['tw:size-9'],\n 'icon-sm': ['tw:size-8'],\n 'icon-xs': ['tw:size-6'],\n // unsupported in ARGO, remove when old design is gone\n 'icon-2xs': [],\n 'icon-3xs': [],\n },\n },\n },\n);\n","import type { ComponentProps } from 'react';\nimport { Root, Slottable } from '@radix-ui/react-slot';\nimport type { VariantProps } from 'class-variance-authority';\n\nimport { Loader2 } from '../../icons';\nimport { cn } from '../../utils';\nimport { useArgoDesign } from '../ThemeProvider/context';\n\nimport { argoVariants, variants } from './styles';\n\n/**\n * Props for the `Button` component.\n *\n * Pass `variant` for primary/secondary/danger/outline/invisible looks, `size`\n * for height (including `icon-*` sizes when rendering icon-only). Icons are\n * composed as children — `<Button><Trash2 className=\"tw:size-4\" /> Delete</Button>`.\n */\ntype Props = {\n /** Replaces the leading content with a spinner and disables the button visually. The caller still controls `disabled`. */\n isLoading?: boolean;\n /** Render as a Radix `Slot` so the parent JSX (e.g. a `react-router` `<Link>`) becomes the button element. */\n asChild?: boolean;\n} & ComponentProps<'button'> &\n VariantProps<typeof variants>;\n\n/**\n * Primary action surface for the design system — covers all clickable controls except inline text links.\n *\n * **When to use:** any user-initiated action (submit, save, open modal, run job). Use `size=\"icon-*\"` with no\n * children for an icon-only button; there is no separate `IconButton` component.\n * **When NOT to use:** for inline text-link actions inside body copy use `ButtonInline`; for navigation that\n * opens a URL use `Link`; for \"primary action + dropdown of related actions\" use `SplitButton`.\n * **Composition:** wrap in `Tooltip` when icon-only or when disabled state needs an explanation; pair with\n * `Popconfirm` for destructive confirmations; pass through `Modal.Trigger` / `DropdownMenu.Trigger` via `asChild`.\n *\n * @see RECIPES.md#disabled-button-tooltip — for the disabled-button + tooltip pattern\n * @see RECIPES.md#confirm-dialog — for destructive-action confirmation\n */\nexport const Button = ({\n ref,\n children,\n disabled = false,\n className,\n type = 'button',\n isLoading = false,\n asChild = false,\n onClick,\n variant = 'primary',\n size = 'medium',\n block = false,\n ...buttonProps\n}: Props) => {\n const renderArgo = useArgoDesign();\n const Comp = asChild ? Root : 'button';\n const isIconOnly = String(size).startsWith('icon');\n const classNames = renderArgo\n ? argoVariants({ variant, size, block, className })\n : variants({ size, variant, block, className });\n\n const handleClick: ComponentProps<'button'>['onClick'] = (event) => {\n const isAnchor = event.currentTarget.tagName === 'A';\n\n // <a/> does not support disabled by default, and we cannot use pointer-events: none because cursor-not-allowed would not work.\n if (isAnchor && disabled) {\n event.preventDefault();\n return;\n }\n\n onClick?.(event);\n };\n\n return (\n <Comp\n {...buttonProps}\n ref={ref}\n disabled={disabled}\n aria-disabled={disabled}\n data-variant={variant}\n // `size=\"icon\"` / `size=\"icon-*\"` flags the button as icon-only — needed\n // by `ButtonGroup space=\"block\"` which stretches non-icon children to\n // equal width.\n data-icon-only={isIconOnly}\n type={type}\n onClick={handleClick}\n className={cn(classNames)}\n >\n {isLoading && <Loader2 className=\"tw:size-4 tw:shrink-0 tw:animate-spin\" />}\n <Slottable>{isLoading && isIconOnly ? null : children}</Slottable>\n </Comp>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Root } from '@radix-ui/react-slot';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nconst buttonInlineVariants = cva(\n [\n 'tailwindcss-preflight',\n\n 'tw:inline-flex',\n 'tw:items-center',\n 'tw:gap-2',\n\n 'tw:underline-offset-2',\n\n 'tw:disabled:opacity-40',\n 'tw:disabled:cursor-not-allowed',\n 'tw:disabled:text-neutral-500',\n 'tw:disabled:no-underline',\n 'tw:disabled:[&_svg]:text-neutral-400',\n\n // Default size for nested Lucide icons; callers can override on the icon.\n \"tw:[&_svg.lucide:not([class*='tw:size-'])]:size-4\",\n 'tw:[&_svg]:shrink-0',\n ],\n {\n defaultVariants: {\n variant: 'link',\n color: 'link',\n },\n variants: {\n color: {\n link: ['tw:text-primary', 'tw:hover:text-primary/90', 'tw:[&_svg]:text-primary'],\n dark: ['tw:text-foreground tw:[&_svg]:text-muted-foreground'],\n danger: ['tw:text-error-500 tw:[&_svg]:text-error-500'],\n muted: ['tw:text-muted-foreground tw:[&_svg]:text-muted-foreground'],\n custom: [],\n },\n variant: {\n link: ['tw:underline', 'tw:hover:no-underline'],\n 'link-reverse': ['tw:no-underline', '', 'tw:hover:underline'],\n custom: [],\n },\n },\n },\n);\n\ntype Props = ComponentProps<'button'> &\n VariantProps<typeof buttonInlineVariants> & { asChild?: boolean };\n\nexport const ButtonInline = ({\n ref,\n children,\n className,\n variant,\n color,\n type = 'button',\n asChild = false,\n ...buttonProps\n}: Props) => {\n const Comp = asChild ? Root : 'button';\n\n return (\n <Comp\n {...buttonProps}\n ref={ref}\n type={asChild ? undefined : type}\n className={buttonInlineVariants({ variant, color, className })}\n >\n {children}\n </Comp>\n );\n};\n"],"mappings":";;;;;;;AAEA,MAAa,WAAW,IACtB;CACE;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CAOA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CAGA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CAEA;AACF,GACA;CACE,iBAAiB;EACf,MAAM;EACN,SAAS;EACT,OAAO;CACT;CACA,UAAU;EACR,OAAO,EACL,MAAM,CAAC,WAAW,EACpB;EACA,SAAS;GACP,SAAS;IACP;IACA;IAEA;IACA;IACA;IACA;IAGA;GACF;GACA,WAAW;IACT;IACA;IAEA;IACA;IACA;IACA;IAGA;GACF;GACA,QAAQ;IACN;IACA;IAEA;IACA;IACA;IACA;IAGA;GACF;GAOA,WAAW;IACT;IACA;IAEA;IACA;IACA;IACA;IAGA;IACA;IACA;IAGA;GACF;GACA,SAAS;IACP;IACA;IAEA;IACA;IACA;IAIA;IACA;IACA;IAGA;IACA;IACA;IAGA;IACA;GACF;GAEA,QAAQ;IACN;IACA;IACA;IAEA;IACA;IACA;GACF;EACF;EACA,MAAM;GACJ,QAAQ;IACN;IACA;IACA;IACA;IACA;GACF;GACA,OAAO;IACL;IACA;IACA;IACA;IACA;GACF;GACA,OAAO;IACL;IACA;IACA;IACA;IACA;GACF;GAEA,WAAW;IAAC;IAAc;IAAU;GAA4C;GAChF,MAAM;IAAC;IAAc;IAAU;GAA4C;GAC3E,WAAW;IAAC;IAAa;IAAU;GAA4C;GAC/E,WAAW;IAAC;IAAa;IAAU;GAA4C;GAC/E,YAAY;IACV;IACA;IACA;IACA;GACF;GACA,YAAY;IAAC;IAAY;IAAY;GAA4C;EACnF;CACF;AACF,CACF;AAEA,MAAa,eAAe,IAC1B;CACE;CAGA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CAGA;CACA;CAGA;CACA;CAGA;CACA;CACA;CAEA;CACA;CAGA;CACA;CACA;CAGA;CACA;CACA;CACA;AACF,GACA;CACE,iBAAiB;EACf,SAAS;EACT,MAAM;CACR;CACA,UAAU;EACR,OAAO,EACL,MAAM,CAAC,WAAW,EACpB;EACA,SAAS;GACP,SAAS;IACP;IACA;IACA;IACA;IACA;IACA;IAEA;IACA;GACF;GACA,WAAW;IACT;IACA;IACA;IAEA;IACA;GACF;GAGA,QAAQ;IACN;IACA;IACA;IACA;IACA;IAEA;IACA;GACF;GACA,SAAS;IACP;IACA;IAGA;IAGA;IACA;IACA;IACA;IACA;GACF;GAGA,WAAW;IACT;IACA;IACA;IACA;IACA;IAEA;GACF;GAEA,QAAQ;IACN;IACA;IACA;IACA;IACA;GACF;EACF;EACA,MAAM;GAEJ,QAAQ;IAAC;IAAc;IAAW;IAAW;GAAY;GAEzD,OAAO;IAAC;IAAc;IAAW;IAAW;GAAY;GAExD,OAAO;IAAC;IAAe;IAAa;IAAW;GAAY;GAE3D,WAAW,CAAC,YAAY;GACxB,MAAM,CAAC,WAAW;GAClB,WAAW,CAAC,WAAW;GACvB,WAAW,CAAC,WAAW;GAEvB,YAAY,CAAC;GACb,YAAY,CAAC;EACf;CACF;AACF,CACF;;;;;;;;;;;;;;;;ACvSA,MAAa,UAAU,EACrB,KACA,UACA,WAAW,OACX,WACA,OAAO,UACP,YAAY,OACZ,UAAU,OACV,SACA,UAAU,WACV,OAAO,UACP,QAAQ,OACR,GAAG,kBACQ;CACX,MAAM,aAAa,cAAc;CACjC,MAAM,OAAO,UAAU,OAAO;CAC9B,MAAM,aAAa,OAAO,IAAI,CAAC,CAAC,WAAW,MAAM;CACjD,MAAM,aAAa,aACf,aAAa;EAAE;EAAS;EAAM;EAAO;CAAU,CAAC,IAChD,SAAS;EAAE;EAAM;EAAS;EAAO;CAAU,CAAC;CAEhD,MAAM,eAAoD,UAAU;EAIlE,IAHiB,MAAM,cAAc,YAAY,OAGjC,UAAU;GACxB,MAAM,eAAe;GACrB;EACF;EAEA,UAAU,KAAK;CACjB;CAEA,OACE,qBAAC,MAAD;EACE,GAAI;EACC;EACK;EACV,iBAAe;EACf,gBAAc;EAId,kBAAgB;EACV;EACN,SAAS;EACT,WAAW,GAAG,UAAU;EAZ1B,UAAA,CAcG,aAAa,oBAAC,SAAD,EAAS,WAAU,wCAAyC,CAAA,GAC1E,oBAAC,WAAD,EAAA,UAAY,aAAa,aAAa,OAAO,SAAoB,CAAA,CAC7D;;AAEV;;;ACrFA,MAAM,uBAAuB,IAC3B;CACE;CAEA;CACA;CACA;CAEA;CAEA;CACA;CACA;CACA;CACA;CAGA;CACA;AACF,GACA;CACE,iBAAiB;EACf,SAAS;EACT,OAAO;CACT;CACA,UAAU;EACR,OAAO;GACL,MAAM;IAAC;IAAmB;IAA4B;GAAyB;GAC/E,MAAM,CAAC,qDAAqD;GAC5D,QAAQ,CAAC,6CAA6C;GACtD,OAAO,CAAC,2DAA2D;GACnE,QAAQ,CAAC;EACX;EACA,SAAS;GACP,MAAM,CAAC,gBAAgB,uBAAuB;GAC9C,gBAAgB;IAAC;IAAmB;IAAI;GAAoB;GAC5D,QAAQ,CAAC;EACX;CACF;AACF,CACF;AAKA,MAAa,gBAAgB,EAC3B,KACA,UACA,WACA,SACA,OACA,OAAO,UACP,UAAU,OACV,GAAG,kBACQ;CAGX,OACE,oBAHW,UAAU,OAAO,UAG5B;EACE,GAAI;EACC;EACL,MAAM,UAAU,KAAA,IAAY;EAC5B,WAAW,qBAAqB;GAAE;GAAS;GAAO;EAAU,CAAC;EAE5D;CACG,CAAA;AAEV"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"CodeEditor-CUse8znx.js","names":["cmPlaceholder","placeholder"],"sources":["../src/components/CodeEditor/ButtonToolbar.tsx","../src/components/CodeEditor/modes/dbt.ts","../src/components/CodeEditor/modes/jsonnet.ts","../src/components/CodeEditor/diffWash.ts","../src/components/CodeEditor/syntaxPalette.ts","../src/components/CodeEditor/helpers.ts","../src/components/CodeEditor/editorChrome.ts","../src/components/CodeEditor/search.ts","../src/components/CodeEditor/ToggleComponentHelp.tsx","../src/components/CodeEditor/tokenTheme.ts","../src/components/CodeEditor/tooltips.ts","../src/components/CodeEditor/variableCompletion.ts","../src/components/CodeEditor/CodeEditor.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { ClipboardButton } from '../../blocks/ClipboardButton';\n\n// Floats over the top-right corner of the editor it is rendered into — private to\n// `CodeEditor`, which is the `relative` ancestor it positions against. `right-3`\n// leaves room for the scrollbar track, whose width the browser owns and no token\n// here describes.\nexport const ButtonToolbar = ({ value, children }: { value?: string; children?: ReactNode }) => {\n if (!value && !children) return null;\n\n return (\n <div className=\"tw:absolute tw:right-3 tw:top-1 tw:z-10 tw:flex tw:gap-0.5 tw:overflow-visible tw:rounded tw:border tw:border-solid tw:border-border tw:!bg-background tw:p-px tw:shadow-sm\">\n {!!value && <ClipboardButton size=\"icon-xs\" variant=\"invisible\" text={value} />}\n {children}\n </div>\n );\n};\n","import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';\nimport { simpleMode } from '@codemirror/legacy-modes/mode/simple-mode';\n\n// A dbt step is `dbt <command> [<subcommand>] [arguments, flags and selectors]`,\n// and the vocabulary below is grouped by the slot it belongs to — both to colour\n// it and to decide what is worth offering where.\nconst COMMANDS = [\n 'run-operation',\n 'run',\n 'test',\n 'seed',\n 'snapshot',\n 'list',\n 'ls',\n 'compile',\n 'build',\n 'deps',\n 'docs',\n 'source',\n];\nconst SUBCOMMANDS: Record<string, string[]> = { docs: ['generate'], source: ['freshness'] };\nconst ARGUMENTS = ['--select', '--exclude', '--selector', '--defer', '--resource-type', '-s'];\n// The arguments whose value is a graph selector, and so the only ones a selector\n// method has anything to attach to.\nconst SELECTORS = ['--select', '--exclude', '-s'];\nconst METHODS = [\n 'path:',\n 'source:',\n 'tag:',\n 'package:',\n 'config:',\n 'test_type:',\n 'test_name:',\n 'state:',\n 'exposure:',\n 'metric:',\n 'result:',\n 'source_status:',\n 'column_name:',\n];\nconst FLAGS = [\n '--fail-fast',\n '--warn-error',\n '--favor-state',\n '--vars',\n '--models',\n '--threads',\n '--profiles-dir',\n '--profile',\n '--full-refresh',\n];\n\n// A subcommand only ever highlights together with its command, so `dbt docs` stays\n// unpainted until `generate` follows it.\nconst COMMAND_PHRASES = COMMANDS.flatMap((command) => {\n const subcommands = SUBCOMMANDS[command];\n\n return subcommands ? subcommands.map((subcommand) => `${command} ${subcommand}`) : [command];\n});\n\n// Alternation is first-match, so a word that prefixes another has to come first\n// (`run-operation` before `run`, `--profiles-dir` before `--profile`). Sorting by\n// length keeps that true however the lists above are written.\nconst alternation = (list: string[]) => [...list].sort((a, b) => b.length - a.length).join('|');\n\n// Every keyword follows whitespace, so the leading run is part of the match.\n// Commands and arguments end on a word boundary; methods and flags carry their\n// own terminator (`:`) or need none.\nconst word = (list: string[]) => new RegExp(`^\\\\s+(?:${alternation(list)})\\\\b`, 'i');\nconst prefix = (list: string[]) => new RegExp(`^\\\\s+(?:${alternation(list)})`, 'i');\n\n// The word being completed: letters, digits, `_`, `-` and the `:` a selector\n// method ends with. Whitespace stays out of it, so a two-word label like `docs\n// generate` cannot stretch the match back across the words before the cursor.\nconst WORD = /[\\w:-]*$/;\n\nconst asOptions = (list: string[], type: string): Completion[] =>\n list.map((label) => ({ label, type }));\n\n// `type` drives the popup icon, so each group carries the one that matches the\n// colour the mode paints it in.\nconst DBT: Completion[] = [{ label: 'dbt', type: 'keyword' }];\nconst COMMAND_OPTIONS = asOptions(COMMANDS, 'keyword');\nconst SUBCOMMAND_OPTIONS: Record<string, Completion[]> = Object.fromEntries(\n Object.entries(SUBCOMMANDS).map(([command, subcommands]) => [\n command,\n asOptions(subcommands, 'keyword'),\n ]),\n);\nconst ARGUMENT_OPTIONS = asOptions(ARGUMENTS, 'variable');\nconst FLAG_OPTIONS = asOptions(FLAGS, 'constant');\nconst METHOD_OPTIONS = asOptions(METHODS, 'property');\n\n// Which slice of the vocabulary the cursor's slot can hold, given the words\n// already finished ahead of it. Offering the whole vocabulary everywhere proposes\n// `dbt` mid-command and a selector method with no selector to attach to.\nconst optionsAfter = (words: string[]): Completion[] => {\n const [step, command, ...rest] = words;\n\n if (step === undefined) return DBT;\n if (step.toLowerCase() !== 'dbt') return [];\n if (command === undefined) return COMMAND_OPTIONS;\n\n const subcommands = SUBCOMMAND_OPTIONS[command.toLowerCase()];\n if (subcommands && rest.length === 0) return subcommands;\n\n // A selector argument takes any number of space-separated values, so what\n // decides the slot is the last argument, not whether a selector appeared at all:\n // `--select tag:a tag:b` keeps offering methods, `--select a --profile p` stops.\n const lastArgument = rest.filter((it) => it.startsWith('-')).at(-1);\n const selecting = lastArgument !== undefined && SELECTORS.includes(lastArgument.toLowerCase());\n\n return selecting\n ? [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS, ...METHOD_OPTIONS]\n : [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS];\n};\n\nconst complete = (context: CompletionContext): CompletionResult | null => {\n const typed = context.matchBefore(WORD);\n\n // `WORD` also matches the empty string, so without this the popup would open on\n // every space. Asking for completions explicitly still opens it there.\n if (!typed?.text && !context.explicit) return null;\n\n const from = typed?.from ?? context.pos;\n const line = context.state.doc.lineAt(from);\n const options = optionsAfter(\n line.text\n .slice(0, from - line.from)\n .split(/\\s+/)\n .filter(Boolean),\n );\n\n return options.length > 0 ? { from, options, validFor: WORD } : null;\n};\n\nexport const dbt = simpleMode({\n languageData: {\n // `toggleComment` is a no-op without these, so Mod-/ silently does nothing.\n commentTokens: { line: '--', block: { open: '/*', close: '*/' } },\n autocomplete: complete,\n },\n start: [\n { regex: /\"(?:[^\\\\]|\\\\.)*?(?:\"|$)/, token: 'string' },\n // Word-bounded, so `dbtX` is not a dbt step whose first word happens to\n // colour — the same thing the completion source asks of it.\n { regex: /dbt\\b/, token: 'keyword', sol: true },\n { regex: word(COMMAND_PHRASES), token: 'keyword' },\n { regex: word(ARGUMENTS), token: 'variableName' },\n { regex: prefix(METHODS), token: 'propertyName' },\n { regex: prefix(FLAGS), token: 'attributeName' },\n { regex: /(?:@|\\*|,|\\+\\d+|\\d+\\+|\\+)/, token: 'operator' },\n { regex: /'.*'/, token: 'string' },\n { regex: /true|false/, token: 'atom' },\n ],\n});\n","import type { StreamParser } from '@codemirror/language';\n\n/**\n * Ported from google/codemirror-mode-jsonnet (Apache-2.0), the mode written by\n * the language's own authors, which was never taken past CodeMirror 5.\n * CodeMirror 5 style names are replaced by their CodeMirror 6 highlight tags:\n * `string-2` is `escape`, `error` is `invalid`.\n *\n * Every pattern is anchored and hoisted. `StringStream.match` slices the rest of\n * the line and, without `^`, scans all of it for a match it then discards unless\n * it started at the cursor — so an unanchored probe costs the whole remaining\n * line, and this tokenizer makes up to twenty of them per token.\n */\n\nconst COMMENT_END = /^\\*\\//;\nconst COMMENT_START = /^\\/\\/|^#/;\nconst C_COMMENT_START = /^\\/\\*/;\nconst TEXT_BLOCK = /^\\|\\|\\|/;\nconst TEXT_BLOCK_END = /^\\s*\\|\\|\\|/;\nconst RAW_DOUBLE = /^\"\"/;\nconst RAW_SINGLE = /^''/;\nconst CLOSE_DOUBLE = /^\"/;\nconst CLOSE_SINGLE = /^'/;\nconst ESCAPE = /^\\\\[\\\\\"'/bfnrt0]/;\nconst UNICODE_ESCAPE = /^\\\\u[0-9a-fA-F]{4}/;\nconst BACKSLASH = /^\\\\/;\nconst IMPORT = /^import(?:str)?\\s*(@?)([\"'])/;\nconst QUOTE = /^(@?)([\"'])/;\nconst ROOT = /^\\$/;\nconst NUMBER = /^(?:\\.\\d+|\\d+\\.?\\d*)(?:e[-+]?\\d+)?/i;\nconst OPERATOR = /^[-+/*=<>!&~^|$%]+/;\nconst IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*/;\n\nconst KEYWORDS: Record<string, 'keyword' | 'atom'> = {\n local: 'keyword',\n self: 'keyword',\n super: 'keyword',\n assert: 'keyword',\n function: 'keyword',\n if: 'keyword',\n then: 'keyword',\n else: 'keyword',\n for: 'keyword',\n in: 'keyword',\n tailstrict: 'keyword',\n error: 'keyword',\n true: 'atom',\n false: 'atom',\n null: 'atom',\n};\n\ntype State = {\n cComment: boolean;\n textBlock: boolean;\n textBlockIndent: number | null;\n string: boolean;\n importString: boolean;\n stringSingle: boolean;\n stringRaw: boolean;\n};\n\nexport const jsonnet: StreamParser<State> = {\n name: 'jsonnet',\n\n // `toggleComment` is a no-op without these, so Mod-/ silently does nothing.\n languageData: { commentTokens: { line: '//', block: { open: '/*', close: '*/' } } },\n\n startState: () => ({\n cComment: false,\n textBlock: false,\n textBlockIndent: null,\n string: false,\n importString: false,\n stringSingle: false,\n stringRaw: false,\n }),\n\n token: (stream, state) => {\n if (state.cComment) {\n if (stream.match(COMMENT_END)) {\n state.cComment = false;\n return 'comment';\n }\n stream.next();\n return 'comment';\n }\n\n // A `|||` block runs from its own first content line to the first line\n // indented less than that — so the closing `|||` has to be recognised\n // before the indent is measured, or a block closed at column 0 never ends.\n if (state.textBlock) {\n if (state.textBlockIndent == null) {\n if (stream.match(TEXT_BLOCK_END)) {\n state.textBlock = false;\n return 'string';\n }\n state.textBlockIndent = stream.indentation();\n }\n if (stream.indentation() >= state.textBlockIndent) {\n stream.skipToEnd();\n return 'string';\n }\n if (stream.match(TEXT_BLOCK_END)) {\n state.textBlock = false;\n return 'string';\n }\n stream.next();\n return 'invalid';\n }\n\n // Quoted and `@`-raw strings, single or double, plain or after an import.\n if (state.string || state.importString) {\n const style = state.string ? 'string' : 'meta';\n\n if (state.stringRaw) {\n if (stream.match(state.stringSingle ? RAW_SINGLE : RAW_DOUBLE)) return 'escape';\n } else {\n if (stream.match(ESCAPE)) return 'escape';\n if (stream.match(UNICODE_ESCAPE)) return 'escape';\n if (stream.match(BACKSLASH)) return 'invalid';\n }\n\n if (stream.match(state.stringSingle ? CLOSE_SINGLE : CLOSE_DOUBLE)) {\n state.string = false;\n state.importString = false;\n return style;\n }\n\n stream.next();\n return style;\n }\n\n if (stream.match(COMMENT_START)) {\n stream.skipToEnd();\n return 'comment';\n }\n if (stream.match(C_COMMENT_START)) {\n state.cComment = true;\n return 'comment';\n }\n\n // An import opens a string that is styled as meta rather than as content.\n const imported = stream.match(IMPORT);\n if (Array.isArray(imported)) {\n state.importString = true;\n state.stringRaw = imported[1] === '@';\n state.stringSingle = imported[2] === \"'\";\n return 'meta';\n }\n\n const quoted = stream.match(QUOTE);\n if (Array.isArray(quoted)) {\n state.string = true;\n state.stringRaw = quoted[1] === '@';\n state.stringSingle = quoted[2] === \"'\";\n return 'string';\n }\n\n if (stream.match(TEXT_BLOCK)) {\n state.textBlock = true;\n state.textBlockIndent = null;\n return 'string';\n }\n\n if (stream.match(ROOT)) return 'keyword';\n if (stream.match(NUMBER)) return 'number';\n if (stream.match(OPERATOR)) return 'operator';\n\n // Consumed whole so that a keyword's prefix (`locally`) is not styled.\n const identifier = stream.match(IDENTIFIER);\n if (Array.isArray(identifier)) return KEYWORDS[identifier[0]] ?? null;\n\n stream.next();\n return null;\n },\n};\n","import type { ResolvedColorScheme } from '../ThemeProvider/types';\n\n/**\n * Alpha suffixes for the dark-scheme diff and state tints.\n *\n * - The line fill stays subtle enough for the `foreground` text to read; the gutter sits a step\n * stronger so the scan-lane is still obvious next to it.\n * - `DARK_LINE_ALPHA` also carries the run-state and search washes in `highlighting.ts` and\n * `search.ts`, which are static base themes and so append the suffix themselves.\n */\nexport const DARK_LINE_ALPHA = '29'; /* 16% */\nconst DARK_GUTTER_ALPHA = '47'; /* 28% */\n\n/**\n * The two diff fills, per scheme: light keeps the opaque pastel, dark tints the same `500` hue at\n * low alpha over whatever token surface is behind it.\n *\n * - Its own module, importing nothing, so `MergeEditor` can share it without reaching into\n * `CodeEditor/helpers.ts` and pulling the language modes and the CodeMirror runtime with it.\n * - Shared by the unified merge wash in `helpers.ts` and `buildDiffHighlightTheme` in\n * `MergeEditor/decorations.ts`, so the two views cannot drift apart on the alphas.\n * - Callers pass the hue and the pastel; which one is used is this function's business.\n */\nexport const buildDiffWash = (scheme: ResolvedColorScheme) => {\n const dark = scheme === 'dark';\n\n return {\n line: (hue: string, pastel: string) => (dark ? `${hue}${DARK_LINE_ALPHA}` : pastel),\n gutter: (hue: string, pastel: string) => (dark ? `${hue}${DARK_GUTTER_ALPHA}` : pastel),\n };\n};\n","import { tags } from '@lezer/highlight';\n\nimport colors from '@keboola/tailwind-config/colors';\n\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\n\n/**\n * The tag colours layered over the stock github palette, per colour scheme.\n *\n * - Its own module, importing nothing but the tag vocabulary and the ramps, so\n * `scripts/contrast-audit.ts` can measure the palette without pulling the language modes and the\n * CodeMirror runtime into a build script.\n * - Later entries win over the stock rule for the same tag — both `githubLightInit` and\n * `githubDarkInit` concatenate these after their own.\n * - `foreground` is the caller's, because it is a live `--*` token rather than a ramp step: the\n * theme passes `resolveToken('foreground')`, the audit passes the scheme's channel value.\n * - Every ramp step here is a light/dark pair, and each pair is chosen against **two** surfaces —\n * the theme's `background` setting is the page, but `variant=\"field\"` paints on `muted`, which\n * the theme never sees. Ratios in the comments are quoted `background` / `muted`.\n */\nexport const buildSyntaxPalette = (scheme: ResolvedColorScheme, foreground: string) => {\n const dark = scheme === 'dark';\n\n return [\n // Plain identifiers, quoted identifiers (`\"a column\"`) and brackets carry no colour of their\n // own, matching github.com's own rendering — stock github lumps brackets in with comments.\n { tag: [tags.name, tags.special(tags.string), tags.bracket], color: foreground },\n // Functions — light `600` 6.13 / 5.84, dark `300` 9.62 / 7.80.\n { tag: tags.standard(tags.name), color: dark ? colors.purple[300] : colors.purple[600] },\n // Special vars — light `800` 7.26 / 6.92, dark `300` 13.49 / 10.94.\n { tag: tags.special(tags.name), color: dark ? colors.cyan[300] : colors.cyan[800] },\n // Strings — light `800` 7.23 / 6.89, dark `300` 13.53 / 10.97.\n { tag: tags.string, color: dark ? colors.warning[300] : colors.warning[800] },\n // The four below re-target stock light colours that sit below AA, each to the nearest step of\n // our own ramp in the same hue. Dark needs none of them — `githubDarkStyle` clears AA on every\n // surface — so under dark they fall through to it.\n //\n // Ratios are `background` / `muted`; `CONTRAST-AUDIT.md` carries all four surfaces and the\n // stock values these replace.\n ...(dark\n ? []\n : [\n // Keywords — 5.96 / 5.69, from 4.38 / 4.18.\n { tag: [tags.keyword, tags.typeName, tags.typeOperator], color: colors.error[550] },\n // Comments — 6.44 / 6.15, from 4.61 / 4.40.\n { tag: tags.comment, color: colors.neutral[500] },\n // Markdown quotes — 7.15 / 6.82, from 4.43 / 4.22.\n { tag: tags.quote, color: colors.green[900] },\n // Lex errors — 7.81 / 7.45. The stock red clears both of these and fails the read-only\n // wash at 4.44, the darkest of the four surfaces an editor paints on.\n { tag: tags.invalid, color: colors.error[700] },\n ]),\n // Dark only, because `githubDarkStyle` carries no `escape` rule where the light array does.\n // The jsonnet mode emits it for `\\n` and `\\uXXXX`; unpainted, those fall back to `foreground`\n // and stop being distinguishable from the amber string body they sit in. `blue[300]` is\n // 10.97 / 8.90 and reads as \"special, inside a string\" against that amber.\n ...(dark ? [{ tag: [tags.escape, tags.url, tags.link], color: colors.blue[300] }] : []),\n ];\n};\n","import { javascript } from '@codemirror/lang-javascript';\nimport { json, jsonParseLinter } from '@codemirror/lang-json';\nimport { python } from '@codemirror/lang-python';\nimport { MSSQL, MySQL, PLSQL, PostgreSQL, StandardSQL } from '@codemirror/lang-sql';\nimport { StreamLanguage } from '@codemirror/language';\nimport { r } from '@codemirror/legacy-modes/mode/r';\nimport { shell } from '@codemirror/legacy-modes/mode/shell';\nimport { toml } from '@codemirror/legacy-modes/mode/toml';\nimport type { LintSource } from '@codemirror/lint';\nimport { linter } from '@codemirror/lint';\nimport { githubDarkInit, githubLightInit } from '@uiw/codemirror-theme-github';\nimport type { BasicSetupOptions } from '@uiw/react-codemirror';\n\nimport { getSqlLanguageSupport } from '@keboola/codemirror-lang-sql';\nimport colors from '@keboola/tailwind-config/colors';\n\nimport { resolveToken } from '../../utils/themeTokens';\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\n\nimport { dbt } from './modes/dbt';\nimport { jsonnet } from './modes/jsonnet';\nimport { buildDiffWash } from './diffWash';\nimport { buildSyntaxPalette } from './syntaxPalette';\n\n// The MIME vocabulary callers pass. Kept as a const so the runtime whitelist and\n// the type stay one list — an annotated `LANGUAGE_MODE[]` copy elsewhere silently\n// drifts, since the type checker accepts a short one.\nexport const LANGUAGE_MODES = [\n 'application/json',\n 'text/plain',\n 'text/x-python',\n 'text/x-sql',\n 'text/x-mysql',\n 'text/x-pgsql',\n 'text/x-mssql',\n // Snowflake, under a historical name — these strings are a published prop contract.\n 'text/x-sfsql',\n 'text/x-bqsql',\n 'text/x-plsql',\n 'text/x-rsrc',\n 'text/x-sh',\n 'text/x-toml',\n 'text/jsonnet',\n 'text/x-dbt',\n 'text/javascript',\n 'text/typescript',\n] as const;\n\nexport type LANGUAGE_MODE = (typeof LANGUAGE_MODES)[number];\n\nexport const isLanguageMode = (mode: string): mode is LANGUAGE_MODE =>\n (LANGUAGE_MODES as readonly string[]).includes(mode);\n\n// `readOnly` reaches CodeMirror as `contenteditable`, so the two states are only\n// addressable through it. Exported because `fieldChrome` overrides the read-only\n// wash below by re-declaring the same key — which only works while the strings\n// match exactly.\nexport const READ_ONLY_EDITOR = '&.cm-editor:has(.cm-content[contenteditable=\"false\"])';\nexport const EDITABLE_EDITOR = '&.cm-editor:has(.cm-content[contenteditable=\"true\"])';\n\n/**\n * Editor chrome and the unified merge (diff) wash.\n *\n * - Chrome surfaces (selection, read-only wash) resolve from live `--*` tokens, so they re-skin\n * with brand and colour scheme. Fallback channels mirror the light-mode token values for SSR /\n * no-provider parity.\n * - Diff colours stay categorical — fixed across brands, because added/removed is meaning, not\n * chrome — but each is a light/dark pair from `buildDiffWash`, shared with\n * `buildDiffHighlightTheme` in `MergeEditor/decorations.ts`.\n * - This wash reaches only `CodeEditor`'s *unified* merge view — the one a `previousValue` turns on.\n * `MergePane` builds its own theme from scratch.\n */\nexport const buildBaseThemeStyles = (scheme: ResolvedColorScheme) => {\n const { line, gutter } = buildDiffWash(scheme);\n const dark = scheme === 'dark';\n\n return {\n '*': { lineHeight: '20px' },\n '*::selection': {\n backgroundColor: resolveToken('primary', '31 143 255'),\n color: `${resolveToken('primary-foreground', '255 255 255')} !important`,\n },\n // The recessed wash. `secondary` sits a step darker than `muted` in light but a step *lighter*\n // in dark, where it would take the palette's tightest colour (`comment`) to 4.27:1 — so dark\n // asks for `muted` (4.89:1). The inversion is a token-system quirk, not an editor one.\n [READ_ONLY_EDITOR]: {\n backgroundColor: dark\n ? resolveToken('muted', '38 38 45')\n : resolveToken('secondary', '226 232 240'),\n },\n [`${READ_ONLY_EDITOR} .cm-gutters`]: {\n backgroundColor: resolveToken('border', '229 231 235'),\n },\n '&.cm-editor .cm-scroller': { overflowAnchor: 'none' },\n '&.cm-editor, &.cm-editor .cm-scroller': {\n minHeight: '100%',\n flexGrow: 1,\n alignItems: 'stretch !important',\n outline: 'none',\n },\n '.cm-gutter.cm-foldGutter': { display: 'none !important' },\n '.cm-gutter.cm-lineNumbers': { paddingLeft: '20px', paddingRight: '6px' },\n '.cm-gutters': { height: 'auto' },\n\n // merge (diff) view\n '&[class*=\"cm-merge-\"] .cm-deletedLine': {\n backgroundColor: line(colors.error[500], colors.error[100]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedLine': {\n backgroundColor: line(colors.green[500], colors.green[100]),\n },\n '&[class*=\"cm-merge-\"] .cm-deletedLineGutter': {\n backgroundColor: gutter(colors.error[500], colors.error[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedLineGutter': {\n backgroundColor: gutter(colors.green[500], colors.green[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-deletedText': {\n background: gutter(colors.error[500], colors.error[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedText': {\n background: gutter(colors.green[500], colors.green[200]),\n },\n // The container and its gutter follow the page, not the diff — a fixed white here would be the\n // whole editor as a light slab under dark.\n '&[class*=\"cm-merge-\"]': {\n backgroundColor: `${resolveToken('background', '249 250 251')} !important`,\n },\n '&[class*=\"cm-merge-\"] .cm-gutters': {\n backgroundColor: `${resolveToken('muted', '241 245 249')} !important`,\n },\n '.cm-changeGutter': { position: 'absolute', zIndex: -1, width: '100%', paddingLeft: 0 },\n '&[class*=\"cm-merge-\"] .cm-changedLine,&[class*=\"cm-merge-\"] .cm-line, &[class*=\"cm-merge-\"] .cm-deletedChunk':\n { paddingLeft: 0 },\n };\n};\n\n// Dead whatever the editor does with them: `buildBaseThemeStyles` hides the fold\n// gutter outright, and `buildCustomTheme` paints the active line transparent.\n//\n// `autocompletion` is off because both editors install their own and a second instance\n// is not a no-op: `CodeEditor` gates its copy on `readOnly` and on `withCompletions`,\n// and `SqlEditor` passes options through `installExtensions`, which basicSetup's\n// option-less copy would compete with.\nconst ALWAYS_OFF = {\n autocompletion: false,\n drawSelection: false,\n foldGutter: false,\n foldKeymap: false,\n highlightActiveLine: false,\n highlightActiveLineGutter: false,\n} as const;\n\n// `basicSetup` enables everything it is not told to skip, so a viewer would\n// otherwise install bracket closing and keybindings for commands a read-only\n// document rejects. Search stays — Mod-f is useful on a viewer. Same reasoning\n// as `shouldLintJson` below.\n//\n// `history` stays too, though a viewer can never add an entry: a caller that\n// flips `readOnly` mid-session reconfigures the view, and a reconfigure discards\n// state fields the new configuration doesn't have. Leaving it out saves nothing\n// and costs the editable session its undo stack.\nexport const buildBasicSetup = (readOnly: boolean): BasicSetupOptions => ({\n ...ALWAYS_OFF,\n ...(readOnly\n ? {\n closeBrackets: false,\n closeBracketsKeymap: false,\n lintKeymap: false,\n indentOnInput: false,\n rectangularSelection: false,\n dropCursor: false,\n highlightSelectionMatches: false,\n }\n : null),\n});\n\n/**\n * The syntax theme, per colour scheme.\n *\n * - The stock github palette is picked by scheme: `githubDarkInit` under dark, `githubLightInit`\n * otherwise. One palette cannot serve both — the light set scores 1.14:1 to 4.31:1 on the two\n * dark surfaces, so 10 of its 11 colours failed AA there (UT-5194).\n * - `githubDarkInit` also passes `dark: true` to `EditorView.theme`, which sets the\n * `EditorView.darkTheme` facet. That is what makes the `&dark` rules apply — CodeMirror's own\n * base theme (cursor, selection layer, panels, buttons) and ours (`search.ts`,\n * `highlighting.ts`) both key off it, so they follow the scheme without a second signal.\n * - Chrome (surface, gutter, selection, caret) resolves from live `--*` tokens, so it re-skins with\n * the brand too. Fallback channels mirror the light-mode token values, for SSR and jsdom.\n * - `caret` and `selectionMatch` are pinned because the two initialisers disagree on them, and the\n * branch would otherwise change values nothing here chose. The caret follows `foreground`; before\n * the facet was set, CodeMirror's own default painted it black on the dark page, so it was\n * invisible. `selectionMatch` is a 10% `primary` tint, which beats each initialiser's own value\n * on the token it hurts most: 3.82:1 against the light default's 3.29, 5.40:1 against the dark\n * default's 3.57. Any occurrence wash costs contrast — this is the cheapest one, and it is the\n * same in both schemes.\n * - `styles` comes from `buildSyntaxPalette`, which lives apart so the audit script can measure it.\n *\n * Those overrides exist because the github theme paints every `name`-family tag one colour, and in\n * SQL nearly every token is a name — identifiers, function calls and `$variables` all drowned\n * together, and a keyword that doubles as a function (`create or REPLACE`) read as a value\n * (UT-5024). Instead: identifiers and brackets carry no colour, functions and special vars get\n * their own hues, and amber is unique to string literals — in JSON that shifts string values from\n * navy to amber, the one visible non-SQL change.\n */\nexport const buildCustomTheme = (scheme: ResolvedColorScheme) => {\n const foreground = resolveToken('foreground', '30 41 59');\n const init = scheme === 'dark' ? githubDarkInit : githubLightInit;\n\n return init({\n settings: {\n fontFamily: `'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New'`,\n background: resolveToken('background', '249 250 251'),\n foreground,\n caret: foreground,\n gutterBackground: resolveToken('muted', '241 245 249'),\n gutterForeground: resolveToken('muted-foreground', '100 116 139'),\n gutterBorder: 'transparent',\n lineHighlight: 'transparent',\n selection: resolveToken('primary', '31 143 255'),\n selectionMatch: resolveToken('primary', '31 143 255', 0.1),\n },\n styles: buildSyntaxPalette(scheme, foreground),\n });\n};\n\nexport const getLanguageMode = (mode?: LANGUAGE_MODE) => {\n switch (mode) {\n case undefined:\n case 'application/json':\n return json();\n case 'text/x-python':\n return python();\n case 'text/x-sql':\n return getSqlLanguageSupport(StandardSQL);\n case 'text/x-mysql':\n return getSqlLanguageSupport(MySQL);\n case 'text/x-pgsql':\n return getSqlLanguageSupport(PostgreSQL);\n case 'text/x-mssql':\n return getSqlLanguageSupport(MSSQL);\n case 'text/x-sfsql':\n return getSqlLanguageSupport('snowflake');\n case 'text/x-bqsql':\n return getSqlLanguageSupport('bigquery');\n case 'text/x-plsql':\n return getSqlLanguageSupport(PLSQL);\n case 'text/x-rsrc':\n return StreamLanguage.define(r);\n case 'text/x-sh':\n return StreamLanguage.define(shell);\n case 'text/x-toml':\n return StreamLanguage.define(toml);\n case 'text/jsonnet':\n return StreamLanguage.define(jsonnet);\n case 'text/x-dbt':\n return StreamLanguage.define(dbt);\n case 'text/javascript':\n return javascript({ jsx: true });\n case 'text/typescript':\n return javascript({ jsx: true, typescript: true });\n // No language — `text/plain` lands here, and so does any mode added to\n // LANGUAGE_MODES without an arm above. Unstyled text is the safe degradation;\n // a `json()` default would colour unrelated content as if it were JSON.\n default:\n return [];\n }\n};\n\n// The JSON parse linter is only useful on an editable editor — a read-only one\n// can't act on the errors, so running it is wasted work and its underlines are\n// noise (e.g. non-strict JSON shown read-only in Kai chat).\nexport const shouldLintJson = (mode: LANGUAGE_MODE | undefined, readOnly: boolean): boolean =>\n mode === 'application/json' && !readOnly;\n\n/**\n * Wraps a lint source so a blank document produces no diagnostics.\n *\n * `jsonParseLinter` reports \"Unexpected end of input\" for empty content, which is right for a file and\n * wrong for an *optional* form field: it starts empty, and clearing it is how its value is removed.\n * Left unwrapped, every such field opens with a red gutter marker contradicting its own validation —\n * `CodeEditorField` puts six of them on one screen.\n *\n * Exported for its test: the wrapper is the behaviour worth pinning, and it needs no editor to exercise.\n */\nexport const skipBlankDocument =\n (source: LintSource): LintSource =>\n (view) =>\n view.state.doc.toString().trim() === '' ? [] : source(view);\n\n/**\n * The JSON linter, optionally blind to a blank document.\n *\n * - `allowBlankDocument` is opt-in, and only `CodeEditorField` opts in (from `!required`). Suppressing\n * the marker by default would break callers that treat empty as invalid *and* say so nowhere else:\n * `ex-generic/JsonConfiguration.tsx`, `flows/TaskParamsModalContent.tsx` and\n * `stream/PayloadTest.tsx` all gate their button on `isValidJsonConfig`, which is `false` for `''`,\n * with no `disabledReason` — so the gutter marker is the only thing explaining a dead button.\n * - Not derivable from `variant`: `ex-generic/FunctionControl.tsx` is `variant=\"field\"` and empty is\n * an error there too. Whether blank is valid is the *field's* contract, not the control's shape.\n */\nexport const buildJsonLinter = (allowBlankDocument: boolean) => {\n const source = jsonParseLinter();\n\n return linter(allowBlankDocument ? skipBlankDocument(source) : source);\n};\n","import colors from '@keboola/tailwind-config/colors';\n\nimport { resolveToken } from '../../utils/themeTokens';\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\n\nimport { EDITABLE_EDITOR, READ_ONLY_EDITOR } from './helpers';\n\n/**\n * The parts of an editor's outer chrome that differ between presets; how they\n * reach CodeMirror's selectors lives once in `buildChromeStyles`.\n */\nexport type EditorChrome = {\n surface: string;\n borderColor: string;\n readOnlySurface: string;\n readOnlyBorderColor: string;\n /** `null` for a preset with no hover affordance — form inputs have none. */\n hoverBorderColor: string | null;\n focusBorderColor: string;\n focusRing: string;\n radius: string;\n paddingY: string;\n /** `null` leaves CodeMirror's own 6px/2px line inset alone. */\n paddingX: { left: string; right: string } | null;\n};\n\n/**\n * Mirrors `InputGroup` at the sizing each design language gives a `TextInput`,\n * so an editor dropped into a form reads as one of its fields.\n *\n * The legacy preset reads the neutral ramp because the legacy `secondary`\n * variant does. No semantic token holds that grey, and the nearest one\n * (`--muted`) is a few points off — which is the \"almost, but not quite, the\n * input next to it\" mismatch this preset exists to remove.\n *\n * That ramp is fixed, so the legacy preset needs its own scheme pair — a legacy brand and the dark\n * scheme are independent choices, and `neutral[100]` under dark is a light slab: `foreground` on it\n * is 1.09:1 and the darkest syntax colour 2.69:1. Dark mirrors the same two steps from the other\n * end of the ramp (`800` / `900`, 5.00:1 and 6.14:1 for that colour).\n */\nexport const buildInputChrome = (isArgo: boolean, scheme: ResolvedColorScheme): EditorChrome => {\n const dark = scheme === 'dark';\n const legacySurface = dark ? colors.neutral[800] : colors.neutral[100];\n const legacyReadOnly = dark ? colors.neutral[900] : colors.neutral[150];\n\n return {\n surface: isArgo ? resolveToken('muted', '241 245 249') : legacySurface,\n borderColor: isArgo ? resolveToken('input', '203 213 225') : legacySurface,\n readOnlySurface: isArgo ? resolveToken('muted', '241 245 249') : legacyReadOnly,\n readOnlyBorderColor: isArgo ? resolveToken('input', '203 213 225') : legacyReadOnly,\n hoverBorderColor: null,\n focusBorderColor: isArgo\n ? resolveToken('primary', '37 99 235')\n : resolveToken('ring', '31 143 255'),\n focusRing: `0 0 0 4px ${resolveToken('ring', '31 143 255', isArgo ? 0.5 : 0.3)}`,\n radius: isArgo ? 'var(--radius-lg, 0.25rem)' : '0.25rem',\n // 2px border + 2×this + `.cm-content`'s own 4px + a 20px line, against the\n // height a one-line `TextInput` has: argo forces `sizing: 'medium'` (36px),\n // legacy leaves it at `default` (40px).\n paddingY: isArgo ? '3px' : '5px',\n // Tops `.cm-line`'s 6px/2px up to the 16px an input's text is inset by.\n paddingX: { left: '10px', right: '14px' },\n };\n};\n\n/** The SQL workspace's notebook cell: a white canvas, not a form control. */\nexport const buildCanvasChrome = (): EditorChrome => ({\n surface: resolveToken('card', '255 255 255'),\n borderColor: 'transparent',\n readOnlySurface: resolveToken('muted', '241 245 249'),\n readOnlyBorderColor: 'transparent',\n hoverBorderColor: resolveToken('ring', '31 143 255'),\n focusBorderColor: resolveToken('ring', '31 143 255'),\n focusRing: `0 0 0 4px ${resolveToken('ring', '31 143 255', 0.3)}`,\n radius: '8px',\n paddingY: '8px',\n paddingX: null,\n});\n\n/**\n * Spread over `buildBaseThemeStyles()` — never used alone. The read-only keys\n * are the base's own, so they replace its wash instead of landing beside it.\n */\nexport const buildChromeStyles = (chrome: EditorChrome) => ({\n '&.cm-editor': {\n border: `solid 1px ${chrome.borderColor}`,\n borderRadius: chrome.radius,\n backgroundColor: chrome.surface,\n paddingTop: chrome.paddingY,\n paddingBottom: chrome.paddingY,\n },\n '&.cm-editor :is(.cm-gutters,.cm-scroller)': { backgroundColor: chrome.surface },\n\n ...(chrome.paddingX\n ? {\n // Only without a gutter: there the editor reads as a one-line input and\n // its text should start where a neighbouring `TextInput`'s does. With a\n // gutter, the gutter owns the left edge.\n '&.cm-editor:not(:has(.cm-gutters)) .cm-content': {\n paddingLeft: chrome.paddingX.left,\n paddingRight: chrome.paddingX.right,\n },\n }\n : null),\n\n ...(chrome.hoverBorderColor\n ? { [`${EDITABLE_EDITOR}:hover`]: { borderColor: chrome.hoverBorderColor } }\n : null),\n [`${EDITABLE_EDITOR}:focus-within`]: {\n borderColor: chrome.focusBorderColor,\n boxShadow: chrome.focusRing,\n },\n\n [READ_ONLY_EDITOR]: {\n backgroundColor: chrome.readOnlySurface,\n borderColor: chrome.readOnlyBorderColor,\n },\n [`${READ_ONLY_EDITOR} .cm-gutters`]: { backgroundColor: chrome.readOnlySurface },\n [`${READ_ONLY_EDITOR} .cm-scroller`]: { backgroundColor: chrome.readOnlySurface },\n});\n","import { StateEffect, StateField, type Text } from '@codemirror/state';\nimport {\n Decoration,\n type DecorationSet,\n EditorView,\n ViewPlugin,\n type ViewUpdate,\n} from '@codemirror/view';\n\nimport colors from '@keboola/tailwind-config/colors';\n\nimport { escapeStringRegexp } from '../../utils/escapeStringRegexp';\n\nimport { DARK_LINE_ALPHA } from './diffWash';\n\n// Represents a single search match in the editor\ntype SearchMatch = {\n /** Start position in document */\n from: number;\n /** End position in document */\n to: number;\n /** Text content of the match */\n text: string;\n /** Local match index within this editor (0-based) */\n localIndex: number;\n};\n\n// Effect to update search state\nconst setSearchEffect = StateEffect.define<{\n query: string;\n selectedMatchIndex?: number;\n}>();\n\n// State to track current search matches\ntype SearchState = {\n query: string;\n selectedMatchIndex?: number;\n matches: SearchMatch[];\n decorations: DecorationSet;\n};\n\n// Find all matches in the document\nfunction findMatches(doc: Text, query: string): SearchMatch[] {\n if (!query) return [];\n\n const text = doc.toString();\n\n try {\n const regex = new RegExp(escapeStringRegexp(query), 'gi');\n\n return Array.from(text.matchAll(regex)).map((match, index) => {\n const from = match.index!;\n const to = from + match[0].length;\n\n return { from, to, text: match[0], localIndex: index };\n });\n } catch (e) {\n // Invalid regex - return no matches\n console.warn('Invalid search regex:', e);\n return [];\n }\n}\n\n// Create decorations for search matches\nfunction createDecorations(matches: SearchMatch[], selectedLocalIndex?: number): DecorationSet {\n const decorations = matches.map((match) => {\n const isSelected = match.localIndex === selectedLocalIndex;\n\n const decoration = Decoration.mark({\n class: isSelected ? 'cm-searchMatch-selected' : 'cm-searchMatch',\n });\n\n return decoration.range(match.from, match.to);\n });\n\n return Decoration.set(decorations, true);\n}\n\n// StateField to manage search state\nconst searchField = StateField.define<SearchState>({\n create() {\n return {\n query: '',\n selectedMatchIndex: undefined,\n matches: [],\n decorations: Decoration.none,\n };\n },\n\n update(state, tr) {\n let newState = state;\n\n // Handle search effect\n for (const effect of tr.effects) {\n if (!effect.is(setSearchEffect)) {\n continue;\n }\n\n const { query, selectedMatchIndex } = effect.value;\n\n // Find matches\n const matches = findMatches(tr.state.doc, query);\n\n // Create decorations\n const decorations = createDecorations(matches, selectedMatchIndex);\n\n newState = {\n query,\n selectedMatchIndex,\n matches,\n decorations,\n };\n }\n\n // Map decorations through document changes\n if (tr.docChanged && newState.query) {\n const matches = findMatches(tr.state.doc, newState.query);\n const decorations = createDecorations(matches, newState.selectedMatchIndex);\n\n newState = {\n ...newState,\n matches,\n decorations,\n };\n }\n\n return newState;\n },\n\n provide: (field) => EditorView.decorations.from(field, (state) => state.decorations),\n});\n\n// View plugin to handle scrolling to selected match\nconst searchViewPlugin = ViewPlugin.fromClass(\n class {\n private lastSelectedIndex?: number;\n\n update(update: ViewUpdate) {\n const state = update.state.field(searchField);\n\n // Scroll to selected match when it changes\n if (\n state.selectedMatchIndex !== undefined &&\n state.selectedMatchIndex !== this.lastSelectedIndex\n ) {\n const match = state.matches[state.selectedMatchIndex];\n\n if (match) {\n requestAnimationFrame(() => {\n update.view.dispatch({\n effects: EditorView.scrollIntoView(match.from, { y: 'center' }),\n });\n });\n }\n\n this.lastSelectedIndex = state.selectedMatchIndex;\n }\n\n // Reset if no selection\n if (state.selectedMatchIndex === undefined) {\n this.lastSelectedIndex = undefined;\n }\n }\n },\n);\n\n/**\n * Match and current-match fills, per colour scheme.\n *\n * - `&dark` is how a *static* base theme follows the scheme, without becoming a\n * `useThemedExtension` builder and a second entry in its never-evicting cache. It applies\n * whenever the `EditorView.darkTheme` facet is set — see `buildBaseThemeStyles`' callers, which\n * set it explicitly.\n * - Light text is `blue[700]`: 5.42:1 on the fill, and 6.29:1 for white on the current match.\n * - Dark tints `blue[500]` for the plain match, with `blue[200]` text: 11.10:1 on the page surface,\n * 8.86:1 on the `variant=\"field\"` one. The current match keeps a solid `blue[500]` and takes\n * `neutral[900]` as its text (5.78:1) — white on it is 2.55:1, since the token that reads as\n * \"strong\" in light is a light colour.\n */\nconst searchTheme = EditorView.baseTheme({\n '.cm-searchMatch': {\n backgroundColor: colors.blue[100],\n },\n '.cm-searchMatch > span': {\n color: `${colors.blue[700]} !important`,\n },\n '.cm-searchMatch-selected': {\n backgroundColor: colors.blue[700],\n },\n '.cm-searchMatch-selected > span': {\n color: `${colors.white} !important`,\n },\n\n '&dark .cm-searchMatch': {\n backgroundColor: `${colors.blue[500]}${DARK_LINE_ALPHA}`,\n },\n '&dark .cm-searchMatch > span': {\n color: `${colors.blue[200]} !important`,\n },\n '&dark .cm-searchMatch-selected': {\n backgroundColor: colors.blue[500],\n },\n '&dark .cm-searchMatch-selected > span': {\n color: `${colors.neutral[900]} !important`,\n },\n});\n\nexport function searchExtension() {\n return [searchField, searchViewPlugin, searchTheme];\n}\n\nexport function updateSearch(view: EditorView, query: string, selectedMatchIndex?: number) {\n view.dispatch({ effects: setSearchEffect.of({ query, selectedMatchIndex }) });\n}\n","import { isMac } from '../../utils';\nimport { Kbd } from '../Kbd';\n\nexport const ToggleComponentHelp = () => (\n <div>\n Use <Kbd>{isMac ? 'Command+/' : 'Ctrl+/'}</Kbd> to toggle comments.\n </div>\n);\n","import { type Extension } from '@codemirror/state';\n\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\nimport { useThemeAttributes } from '../ThemeProvider/useThemeAttributes';\n\n// Cached across component instances, not just across renders. A CodeMirror theme\n// extension carries its own StyleModule, and mounting an EditorView appends its\n// rules to a document-level stylesheet — which invalidates style for the whole\n// document. Sharing one module per theme keeps the stylesheet a constant size no\n// matter how many editors mount.\nconst themeCache = new Map<string, Extension>();\n\n/**\n * Memoize a CodeMirror theme/extension built from `resolveToken`, shared across\n * every instance that passes the same `cacheKey` and rebuilt whenever the active\n * brand / light-dark mode changes. `build` reads live `--*` values off `<html>`,\n * so the active theme is an invisible dependency a deps array can't see.\n *\n * `build` receives the scheme those values were read under, for the theme values\n * that are a light/dark *pair* rather than a token lookup (a categorical diff\n * wash has no semantic token, but an opaque light pastel still has to become a\n * low-alpha tint under dark). It comes from the same read that produced the key,\n * so a builder cannot resolve one scheme's colours under the other one's key.\n *\n * `cacheKey` is the extension's full identity: anything the builder closes over\n * must be part of it (e.g. `` `merge-pane:${deleted}` ``), or instances built\n * from different inputs would share one theme.\n */\nexport const useThemedExtension = (\n cacheKey: string,\n build: (scheme: ResolvedColorScheme) => Extension,\n): Extension => {\n const { scheme, cacheKey: themeKey } = useThemeAttributes();\n const key = `${themeKey} ${cacheKey}`;\n\n // The module-level cache is the memo; reading and filling it during render is\n // idempotent and keyed only on values already stable for the render.\n let cached = themeCache.get(key);\n if (!cached) {\n cached = build(scheme);\n themeCache.set(key, cached);\n }\n\n return cached;\n};\n","import { useMemo } from 'react';\nimport { Compartment, type Extension } from '@codemirror/state';\nimport { tooltips, ViewPlugin } from '@codemirror/view';\n\n// A `position: fixed` box is laid out against the viewport — and so escapes\n// every scroll container above it — only while no ancestor claims the job of\n// being its containing block. This encodes the CSS rule for who claims it\n// rather than the subset this repo happens to use today; `contain` and\n// `will-change` take value lists, so those two are matched loosely.\n//\n// `content-visibility` is absent on purpose: it implies containment without\n// saying so through `contain`, and it is handled below as a clipper — which is\n// the stronger of the two properties for our purposes.\nconst establishesFixedContainingBlock = (style: CSSStyleDeclaration) =>\n style.transform !== 'none' ||\n style.translate !== 'none' ||\n style.rotate !== 'none' ||\n style.scale !== 'none' ||\n style.perspective !== 'none' ||\n style.filter !== 'none' ||\n style.backdropFilter !== 'none' ||\n /\\b(paint|layout|strict|content)\\b/.test(style.contain) ||\n /\\b(transform|perspective|filter|contain)\\b/.test(style.willChange);\n\n// Crops its content, so hosting the tooltip inside it would not help. Paint\n// containment — which `content-visibility: auto` turns on without ever showing\n// up in computed `contain` — crops even a fixed-position descendant, and so\n// does a mask.\nconst crops = (style: CSSStyleDeclaration) =>\n style.overflowX !== 'visible' ||\n style.overflowY !== 'visible' ||\n style.maskImage !== 'none' ||\n style.contentVisibility !== 'visible' ||\n /\\b(paint|strict|content)\\b/.test(style.contain);\n\n/**\n * Where a tooltip can hang without being cropped, or `null` for \"wherever\n * CodeMirror would put it anyway\".\n *\n * Two ancestors matter, and they are not the same ancestor. The **outermost\n * cropper** is the one to get above — landing anywhere below it leaves the\n * tooltip inside the box doing the cropping. The **containing block** is where\n * the search can stop, because from there upwards `position: fixed` is measured\n * against that element and nothing higher can crop it.\n *\n * `document.body` and `<html>` are not treated as croppers: a fixed box whose\n * containing block is the viewport is not clipped by their overflow, and\n * hosting outside `<body>` would drop the tooltip out of the app's stacking and\n * pointer-events scope for no gain.\n */\nconst findTooltipHost = (from: HTMLElement) => {\n let outermostCropper: HTMLElement | null = null;\n\n for (let node = from.parentElement; node && node !== document.body; node = node.parentElement) {\n const style = getComputedStyle(node);\n\n if (crops(style)) {\n outermostCropper = node;\n } else if (establishesFixedContainingBlock(style)) {\n return outermostCropper?.parentElement ?? node;\n }\n }\n\n return outermostCropper?.parentElement ?? null;\n};\n\n/**\n * `tooltips()`, re-hosted so the completion popup is never cropped.\n *\n * CodeMirror hangs tooltips inside the editor and lets `position: fixed` carry\n * them past its edges. That holds only while the viewport is their containing\n * block — a modal centred with a translate, a sheet sliding in, or a box under\n * paint containment takes that job, and then every scroller, mask and contained\n * box in between crops the popup instead. A tall editor hides the damage; a\n * one-line one shows a sliver of an unreadable list.\n *\n * The two shapes this has to survive in production are a `Modal`, whose body\n * scrolls and carries the argo fade mask, and kbc-ui's SQL editor, which wraps\n * every code block in `content-visibility: auto` to keep long scripts cheap.\n *\n * Hosting the layer above the outermost cropper clears all of that while keeping\n * the popup inside the modal's stacking, focus and pointer-events scope — which\n * `document.body` would not: the popup would sit behind the modal, and Radix\n * leaves the body `pointer-events: none` while a dialog is open.\n *\n * Both editors install this, and it is the only place either of them configures\n * a tooltip host. Keep it that way: CodeMirror's tooltip config takes the first\n * contributor that names a parent, so a second mechanism would not compose with\n * this one — it would silently win or lose on extension order.\n */\nconst tooltipsExtension = (): Extension => {\n // The resolved host lives in a compartment, not in an appended config: React\n // hands CodeMirror a new extension array whenever the editor's props move,\n // which dispatches a full reconfigure. That replaces appended config, while\n // compartment contents are carried over.\n const layer = new Compartment();\n\n return [\n layer.of(tooltips()),\n ViewPlugin.define((view) => {\n // Deferred on two counts: a plugin cannot dispatch while the view it\n // belongs to is still being built, and reading computed styles here would\n // force a style and layout flush in the middle of the commit that inserted\n // the editor. The lookup is one-shot — an ancestor that gains a transform\n // afterwards is not picked up.\n const scheduled = setTimeout(() => {\n if (!view.dom.isConnected) return;\n\n const parent = findTooltipHost(view.dom);\n if (parent) view.dispatch({ effects: layer.reconfigure(tooltips({ parent })) });\n });\n\n return { destroy: () => clearTimeout(scheduled) };\n }),\n ];\n};\n\n/**\n * The extension above, built once per editor. Rebuilding it would hand\n * CodeMirror a fresh compartment and plugin on every reconfigure, dropping the\n * host it had already resolved — so it is only ever reached through this hook.\n */\nexport const useTooltipsExtension = () => useMemo(tooltipsExtension, []);\n","import type { Completion, CompletionContext, CompletionSource } from '@codemirror/autocomplete';\n\nimport { useStableCallback } from '../../hooks/useStableCallback';\n\nexport type EditorVariable = { name: string; value?: string };\n\n// Keywords come by the hundred from the language, so a variable would otherwise rank\n// below every one of them that shares a prefix.\nconst BOOST = 2000;\n\n// One brace or two, because `closeBrackets` turns a typed `{` into `{}` and a caret\n// that has only opened the placeholder is still asking for a variable. One charset\n// for the name throughout: a second, narrower one would start the range mid-name on\n// anything it disagreed about, and a range that starts mid-name never matches.\nconst NAME = String.raw`[\\w-]*`;\nconst AT_CARET = new RegExp(String.raw`(?:\\{{1,2} ?)?${NAME}$`);\nconst NAME_AT_END = new RegExp(`${NAME}$`);\nconst OPENING = /\\{{1,2} ?$/;\nconst CLOSING = /^ ?\\}{1,2}/;\n\n/**\n * Completes a mustache-style `{{name}}` placeholder.\n */\nexport const completeVariables = (variables: EditorVariable[] = []): CompletionSource => {\n if (variables.length === 0) return () => null;\n\n const options: Completion[] = variables.map(({ name, value }) => ({\n // The bare name: `SqlEditor` filters prefix-only while `CodeEditor` filters\n // fuzzily, and this is the only spelling both accept whether or not the caret\n // has typed the braces. The braces are `displayLabel`, which is what renders.\n label: name,\n displayLabel: `{{${name}}}`,\n detail: value,\n type: 'variable',\n boost: BOOST,\n apply: (view, completion, from, to) => {\n const { doc } = view.state;\n const line = doc.lineAt(from);\n const insert = `{{${completion.label}}}`;\n\n // The range covers the name alone, so the braces around it are found rather\n // than assumed — `closeBrackets` may have added a closing one nobody typed.\n const opening = OPENING.exec(doc.sliceString(line.from, from));\n const closing = CLOSING.exec(doc.sliceString(to, line.to));\n const start = opening ? from - opening[0].length : from;\n const end = closing ? to + closing[0].length : to;\n\n view.dispatch({\n changes: { from: start, to: end, insert },\n selection: { anchor: start + insert.length },\n });\n },\n }));\n\n return (context: CompletionContext) => {\n const match = context.matchBefore(AT_CARET);\n\n if (!match?.text) return null;\n\n const [name = ''] = NAME_AT_END.exec(match.text) ?? [];\n\n return { from: match.to - name.length, options };\n };\n};\n\n/**\n * The completion source both editors install, with an identity that never moves.\n *\n * Both hold it inside the memo that keys their whole extension tree, and callers\n * build the list inline — a config row mapped to `{ name, value }` in a store\n * selector, so a fresh array arrives on every store push. Because CodeMirror asks\n * the source for options rather than reading them up front, holding it steady costs\n * nothing: a completion request always reaches the latest render's variables.\n */\nexport const useVariableCompletion = (variables: EditorVariable[] = []): CompletionSource =>\n useStableCallback(completeVariables(variables));\n","import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';\nimport type { KeyboardEvent, ReactNode } from 'react';\nimport type { CompletionSource } from '@codemirror/autocomplete';\nimport { autocompletion, completeAnyWord } from '@codemirror/autocomplete';\nimport { unifiedMergeView } from '@codemirror/merge';\nimport { EditorView, keymap, placeholder as cmPlaceholder } from '@codemirror/view';\nimport CodeMirror, {\n EditorState,\n type Extension,\n type ReactCodeMirrorRef,\n} from '@uiw/react-codemirror';\n\nimport { keyCodes } from '../../constants/keyCodes';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { cn } from '../../utils';\nimport { HelpBlock } from '../HelpBlock';\nimport { useArgoDesign } from '../ThemeProvider/context';\n\nimport { ButtonToolbar } from './ButtonToolbar';\nimport { buildChromeStyles, buildInputChrome } from './editorChrome';\nimport type { LANGUAGE_MODE } from './helpers';\nimport {\n buildBaseThemeStyles,\n buildBasicSetup,\n buildCustomTheme,\n buildJsonLinter,\n getLanguageMode,\n shouldLintJson,\n} from './helpers';\nimport { searchExtension, updateSearch } from './search';\nimport { ToggleComponentHelp } from './ToggleComponentHelp';\nimport { useThemedExtension } from './tokenTheme';\nimport { useTooltipsExtension } from './tooltips';\nimport { type EditorVariable, useVariableCompletion } from './variableCompletion';\n\ntype Props = {\n value: string;\n previousValue?: string;\n /**\n * `'field'` draws the chrome an `InputGroup` draws — surface, border, radius,\n * focus ring, read-only wash — for an editor that is one control among others\n * in a form. It sizes to its content, so don't pin its height.\n *\n * `'plain'` (the default) is the full-bleed surface of an editor that *is* the\n * panel: a modal body, a chat block, a fixed-height viewer already framed by\n * whatever contains it.\n */\n variant?: 'plain' | 'field';\n mode?: LANGUAGE_MODE;\n placeholder?: string;\n /** Names the editable region for screen readers — the editor has no visible label of its own. */\n ariaLabel?: string;\n /**\n * Names the editable region from an existing element, for when the label is already on screen.\n * Prefer this over `ariaLabel` inside a form — `CodeEditorField` passes the field's own label id.\n */\n ariaLabelledBy?: string;\n /** Links the editable region to help / error text. Space-delimited idref list. */\n ariaDescribedBy?: string;\n /** Marks the editable region invalid. Visual error styling is the caller's (`variant=\"field\"`). */\n ariaInvalid?: boolean;\n ariaRequired?: boolean;\n /**\n * Treats a blank document as valid instead of a parse error (JSON modes only).\n *\n * - Off by default: for a standalone editor \"Unexpected end of input\" is correct, and at several\n * call sites the gutter marker is the only thing explaining a Save button that\n * `isValidJsonConfig('') === false` has already disabled.\n * - `CodeEditorField` turns it on for a field that is not `required`, where an empty document is\n * how the value is removed.\n */\n allowBlankDocument?: boolean;\n /**\n * Fires when focus leaves the editable region — what a form connector needs to mark its field\n * blurred, which is the gate errors are revealed on.\n *\n * - Bound as a CodeMirror DOM handler on the content node, not on the wrapper: the wrapper is not\n * what gets focused.\n * - Installed only when passed, so an editor without it keeps the extension set it had.\n */\n onBlur?: () => void;\n /**\n * Highlights every occurrence and scrolls the selected one into view. The find\n * UI is the caller's — pass the query it holds, and omit both props entirely to\n * leave the search extension uninstalled.\n */\n searchQuery?: string;\n searchMatchIndex?: number;\n readOnly?: boolean;\n /**\n * Refuses edits while leaving the editor looking and behaving as it did — for a\n * transient lock such as an in-flight save, where a keystroke landing mid-request\n * would be overwritten by the response. `readOnly` is the wrong prop for that:\n * it turns the editor into a viewer, greying the surface and taking the lint\n * marks and completions with it.\n */\n inputLocked?: boolean;\n /**\n * A flat list of completions, offered everywhere in the document. One word per\n * label: CodeMirror derives the pattern for the word being completed from the\n * labels' characters, so a space in one widens it across whitespace and the\n * editor offers nothing past the first word of a line. A phrase belongs in\n * `completionSource`.\n *\n * Compared by identity, like `completionSource` — hand the editor a stable array.\n */\n autocompletions?: string[];\n /**\n * Completions that depend on where the cursor is — a column list offered only\n * after its table, say. Wins over both `autocompletions` and `completeAny`,\n * which stay the right props for a list that is the same everywhere in the\n * document and for having no list at all. Like them, it opens on typing.\n *\n * Compared by identity: build it in a `useMemo` or the editor rebuilds its whole\n * extension tree on every render.\n */\n completionSource?: CompletionSource;\n /**\n * Configuration variables, completed into `{{name}}`. Independent of\n * `completionSource`: both are offered, so a caller keeps its own completions and\n * gets variables spelled the way the rest of the platform writes them.\n */\n variables?: EditorVariable[];\n /**\n * Whether the completion popup runs at all.\n *\n * - `false` silences every source, the *language's* own vocabulary included.\n * - For a field highlighted as a language nobody authors there: pasted `.env` and a\n * cURL command sit in shell mode for its colours, and shell's `ls`, `sudo`, `vim`\n * are noise over content we cannot predict.\n */\n withCompletions?: boolean;\n extraKeys?: Record<string, () => void>;\n withToggleCommentHint?: boolean;\n withAutofocus?: boolean;\n withLineNumbers?: boolean;\n withLineWrapping?: boolean;\n withCollapseUnchanged?: boolean;\n withCopyButton?: boolean;\n completeAny?: boolean;\n help?: ReactNode;\n helpPostfix?: ReactNode;\n /**\n * Extra actions for the toolbar that floats over the editor's top-right corner,\n * beside the copy button. The toolbar is a 28px chip, so pass `size=\"icon-xs\"`\n * buttons — a default-sized one grows the chip and de-aligns the copy button.\n */\n renderAdditionalButtons?: (value?: string) => ReactNode;\n className?: string;\n} & (\n | { readOnly: true; onChange?: never }\n // `boolean` rather than `false`: a field the user's permissions may lock still\n // needs its handler for the case where they can edit.\n | { readOnly?: boolean; onChange: (value: string) => void }\n);\n\nconst emptyObject = {};\n\nexport const CodeEditor = ({\n value,\n previousValue,\n onChange,\n variant = 'plain',\n mode = 'application/json',\n placeholder = '',\n ariaLabel,\n ariaLabelledBy,\n ariaDescribedBy,\n ariaInvalid,\n ariaRequired,\n allowBlankDocument = false,\n onBlur,\n searchQuery,\n searchMatchIndex,\n readOnly = false,\n inputLocked = false,\n autocompletions,\n completionSource,\n variables,\n withCompletions = true,\n extraKeys = emptyObject,\n withToggleCommentHint = false,\n withAutofocus = false,\n withLineNumbers = true,\n withLineWrapping = true,\n withCollapseUnchanged = false,\n withCopyButton = false,\n completeAny = false,\n help = null,\n helpPostfix = null,\n renderAdditionalButtons,\n className,\n}: Props) => {\n // CodeMirror rebuilds and re-resolves the whole extension tree whenever the\n // change handler's identity moves, and callers pass inline arrows.\n const handleChange = useStableCallback((next: string) => onChange?.(next));\n const handleBlur = useStableCallback(() => onBlur?.());\n\n // Themes re-resolve their `--*` tokens on brand / light-dark change. The\n // syntax palette is keyed without a component prefix so `SqlEditor` — which\n // builds it from the same `buildCustomTheme` — shares this one module.\n // Presence, not truthiness: a caller that searches always passes the prop, so\n // the extension set stays stable while the query changes.\n const withSearch = searchQuery !== undefined;\n // Same presence-not-truthiness reasoning as `withSearch`: gate the handler extension on the prop\n // being passed at all, so every existing caller keeps the extension set it had.\n const withBlur = onBlur !== undefined;\n const editorRef = useRef<ReactCodeMirrorRef>(null);\n\n // One object so the extension list has a single dependency instead of five, and `null` when nothing\n // is set so the extension is left out entirely rather than added empty.\n const contentAria = useMemo(() => {\n const attributes: Record<string, string> = {};\n if (ariaLabel !== undefined) attributes['aria-label'] = ariaLabel;\n if (ariaLabelledBy !== undefined) attributes['aria-labelledby'] = ariaLabelledBy;\n if (ariaDescribedBy !== undefined) attributes['aria-describedby'] = ariaDescribedBy;\n // Stringified because `contentAttributes` writes DOM attributes, where `aria-invalid=\"false\"` and\n // an absent attribute mean the same thing but `false` would be dropped by a truthiness check.\n if (ariaInvalid !== undefined) attributes['aria-invalid'] = String(ariaInvalid);\n if (ariaRequired !== undefined) attributes['aria-required'] = String(ariaRequired);\n return Object.keys(attributes).length > 0 ? attributes : null;\n }, [ariaLabel, ariaLabelledBy, ariaDescribedBy, ariaInvalid, ariaRequired]);\n\n useEffect(() => {\n const view = editorRef.current?.view;\n if (view && withSearch) updateSearch(view, searchQuery, searchMatchIndex);\n }, [withSearch, searchQuery, searchMatchIndex]);\n\n // A view created while a query is already set — a remount, a tab switch —\n // starts with no highlights unless the search is applied as it is built.\n const handleCreateEditor = useStableCallback((view: EditorView) => {\n if (searchQuery) updateSearch(view, searchQuery, searchMatchIndex);\n });\n\n // Same reasoning as `onChange` above, one level out: callers build this object\n // inline, so keying the extensions on it would reconfigure the editor on every\n // parent render. Only the set of bound keys can change what the keymap *is* —\n // the handlers behind them are read when the key is actually pressed.\n const extraKeysRef = useRef(extraKeys);\n useLayoutEffect(() => {\n extraKeysRef.current = extraKeys;\n });\n\n const boundKeysSignature = Object.keys(extraKeys).join('\\n');\n const boundKeys = useMemo(\n () => boundKeysSignature.split('\\n').filter(Boolean),\n [boundKeysSignature],\n );\n\n const tooltipLayer = useTooltipsExtension();\n\n // `languageData.of` takes a function CodeMirror calls per completion request, so\n // the source is built here rather than inside it — otherwise every keystroke that\n // opens the popup rebuilds an option per variable.\n const variableCompletion = useVariableCompletion(variables);\n\n const customTheme = useThemedExtension('editor:syntax', buildCustomTheme);\n\n // The brand decides which `InputGroup` the field chrome has to match, so it is\n // part of the theme's identity — `useThemedExtension` caches per key across\n // every instance, and the theme signal it keys on carries only `<html>`.\n const isArgo = useArgoDesign();\n const isField = variant === 'field';\n const baseTheme = useThemedExtension(\n isField ? `code-editor:field:${isArgo ? 'argo' : 'legacy'}` : 'code-editor:chrome',\n (scheme) =>\n // `dark` sets `EditorView.darkTheme`, which is what activates every `&dark` rule — ours in\n // `search.ts` / `highlighting.ts`, and CodeMirror's own for the cursor, selection layer and\n // panels. Declared here rather than inherited from whichever github palette\n // `buildCustomTheme` picked, so swapping that palette cannot silently turn them all off.\n EditorView.theme(\n {\n ...buildBaseThemeStyles(scheme),\n ...(isField ? buildChromeStyles(buildInputChrome(isArgo, scheme)) : null),\n },\n { dark: scheme === 'dark' },\n ),\n );\n\n const commonExtensions: Extension[] = useMemo(() => {\n const callerCompletions =\n completionSource ??\n (completeAny ? completeAnyWord : autocompletions?.length ? autocompletions : null);\n\n // An empty list is left out: CodeMirror wraps a list in `completeFromList`, which\n // answers an empty result rather than none, so the editor would run a source that\n // can never match on every keystroke.\n const completionEntries = [\n ...(callerCompletions ? [{ autocomplete: callerCompletions }] : []),\n { autocomplete: variableCompletion },\n ];\n\n return [\n getLanguageMode(mode),\n shouldLintJson(mode, readOnly) ? buildJsonLinter(allowBlankDocument) : [],\n withLineWrapping ? EditorView.lineWrapping : [],\n EditorState.languageData.of(() => completionEntries),\n keymap.of(\n boundKeys.map((key) => ({\n key,\n run: () => {\n extraKeysRef.current[key]?.();\n return true;\n },\n })),\n ),\n readOnly || !withCompletions\n ? []\n : [\n // The only `autocompletion()` an editor gets — `buildBasicSetup` turns\n // basicSetup's own off. Not gated on the completion props: that hid what the\n // *language* supplies — dbt's vocabulary, Snowflake's keywords — behind a\n // shortcut, and macOS leaves no usable one. With nothing to offer no popup\n // opens anyway, so only `withCompletions={false}` asks for silence.\n autocompletion(),\n ],\n // Every a11y attribute goes onto the *content* node, not the wrapper: CodeMirror's\n // `div[role=\"textbox\"]` is what gets focused, so it is the only element AT will read them from.\n contentAria ? EditorView.contentAttributes.of(contentAria) : [],\n withBlur ? EditorView.domEventHandlers({ blur: handleBlur }) : [],\n withSearch ? searchExtension() : [],\n tooltipLayer,\n baseTheme,\n ];\n }, [\n autocompletions,\n completionSource,\n variableCompletion,\n completeAny,\n withCompletions,\n boundKeys,\n mode,\n readOnly,\n allowBlankDocument,\n withLineWrapping,\n baseTheme,\n contentAria,\n withBlur,\n handleBlur,\n withSearch,\n tooltipLayer,\n ]);\n\n const extensions = useMemo(() => {\n return [\n ...commonExtensions,\n cmPlaceholder(placeholder),\n EditorView.editable.of(!readOnly),\n // The lock is this facet and nothing else. `contenteditable` is what the\n // read-only wash keys off, and `basicSetup` is what holds the undo history,\n // so leaving both alone is what makes the lock invisible.\n EditorState.readOnly.of(readOnly || inputLocked),\n previousValue\n ? unifiedMergeView({\n original: previousValue,\n mergeControls: false,\n highlightChanges: false,\n collapseUnchanged: withCollapseUnchanged ? {} : undefined,\n })\n : [],\n ];\n }, [commonExtensions, placeholder, readOnly, inputLocked, previousValue, withCollapseUnchanged]);\n\n const config = useMemo(() => {\n return {\n ...buildBasicSetup(readOnly),\n lineNumbers: withLineNumbers,\n // Mod-f opens CodeMirror's own panel, which would run a second query and a\n // second match count over the same document beside the caller's input.\n ...(withSearch ? { searchKeymap: false } : null),\n };\n }, [withLineNumbers, readOnly, withSearch]);\n\n return (\n // oxlint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n data-variant={variant}\n className={cn(\n // Scoped to the box CodeMirror renders into rather than to every child, so\n // the toolbar below does not have to undo all three in `!important`.\n 'tw:relative tw:flex tw:min-h-0 tw:flex-col tw:[&_.cm-mergeViewEditor]:overflow-visible tw:[&_.cm-mergeViewEditors]:h-full tw:[&_.cm-mergeView]:h-full tw:[&_>.cm-theme]:h-full',\n // A field's `.cm-editor` is rounded, so the square box behind it would show\n // at the corners, and `overflow-auto` would crop the focus ring — a shadow\n // painted outside the editor's own box.\n isField\n ? 'tw:[&_>.cm-theme]:overflow-visible tw:[&_>.cm-theme]:bg-transparent'\n : 'tw:[&_>.cm-theme]:overflow-auto tw:[&_>.cm-theme]:bg-background',\n className,\n )}\n onKeyDown={(event: KeyboardEvent) => {\n if (event.key === keyCodes.ESCAPE) {\n event.stopPropagation();\n }\n }}\n >\n <ButtonToolbar value={withCopyButton ? value : undefined}>\n {renderAdditionalButtons?.(value)}\n </ButtonToolbar>\n <CodeMirror\n ref={editorRef}\n onCreateEditor={handleCreateEditor}\n theme={customTheme}\n value={value}\n onChange={handleChange}\n extensions={extensions}\n autoFocus={withAutofocus}\n basicSetup={config}\n />\n {!readOnly && (withToggleCommentHint || help || helpPostfix) && (\n <HelpBlock className=\"tw:mt-2 tw:flex tw:flex-wrap tw:gap-1\">\n {help}\n {withToggleCommentHint ? <ToggleComponentHelp /> : null}\n {helpPostfix}\n </HelpBlock>\n )}\n </div>\n );\n};\n"],"mappings":"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"}