@nadicodeai/ui 0.20.0 → 0.22.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 (350) hide show
  1. package/AGENTS.md +4 -3
  2. package/README.md +14 -21
  3. package/dist/agents.d.ts +10 -0
  4. package/dist/agents.d.ts.map +1 -0
  5. package/dist/agents.js +9 -0
  6. package/dist/components/badge.d.ts +1 -1
  7. package/dist/components/brand-icons/apple.d.ts +18 -0
  8. package/dist/components/brand-icons/apple.d.ts.map +1 -0
  9. package/dist/components/brand-icons/apple.js +22 -0
  10. package/dist/components/brand-icons/brand-icon.d.ts +22 -0
  11. package/dist/components/brand-icons/brand-icon.d.ts.map +1 -0
  12. package/dist/components/brand-icons/brand-icon.js +26 -0
  13. package/dist/components/brand-icons/linux.d.ts +18 -0
  14. package/dist/components/brand-icons/linux.d.ts.map +1 -0
  15. package/dist/components/brand-icons/linux.js +25 -0
  16. package/dist/components/brand-icons/windows.d.ts +18 -0
  17. package/dist/components/brand-icons/windows.d.ts.map +1 -0
  18. package/dist/components/brand-icons/windows.js +22 -0
  19. package/dist/components/brand-icons.d.ts +5 -0
  20. package/dist/components/brand-icons.d.ts.map +1 -0
  21. package/dist/components/brand-icons.js +10 -0
  22. package/dist/components/button.d.ts +1 -1
  23. package/dist/components/button.js +1 -1
  24. package/dist/components/card-marketing.js +2 -2
  25. package/dist/components/card.d.ts +4 -3
  26. package/dist/components/card.d.ts.map +1 -1
  27. package/dist/components/card.js +12 -2
  28. package/dist/components/chart-breakdown-table.js +1 -1
  29. package/dist/components/chart-bullet-bar.d.ts +18 -2
  30. package/dist/components/chart-bullet-bar.d.ts.map +1 -1
  31. package/dist/components/chart-bullet-bar.js +62 -9
  32. package/dist/components/chart-date-range-control.d.ts +11 -1
  33. package/dist/components/chart-date-range-control.d.ts.map +1 -1
  34. package/dist/components/chart-date-range-control.js +13 -3
  35. package/dist/components/chart-entity-colors.d.ts +7 -1
  36. package/dist/components/chart-entity-colors.d.ts.map +1 -1
  37. package/dist/components/chart-entity-colors.js +7 -1
  38. package/dist/components/chart-kpi-stat.d.ts.map +1 -1
  39. package/dist/components/chart-kpi-stat.js +1 -1
  40. package/dist/components/chart-time-series.d.ts.map +1 -1
  41. package/dist/components/chart-time-series.js +62 -4
  42. package/dist/components/chart.js +2 -2
  43. package/dist/components/code-editor-mockup.js +1 -1
  44. package/dist/components/nav-bar.js +1 -1
  45. package/dist/components/radio-group.d.ts +1 -1
  46. package/dist/components/radio-group.d.ts.map +1 -1
  47. package/dist/components/radio-group.js +2 -2
  48. package/dist/components/theme-mode-switcher.d.ts +10 -3
  49. package/dist/components/theme-mode-switcher.d.ts.map +1 -1
  50. package/dist/components/theme-mode-switcher.js +14 -7
  51. package/dist/components/use-case-bento.d.ts +2 -4
  52. package/dist/components/use-case-bento.d.ts.map +1 -1
  53. package/dist/components/use-case-bento.js +2 -3
  54. package/dist/eslint/index.js +91 -0
  55. package/dist/eslint/rules/jsx-class-utility.js +231 -0
  56. package/dist/eslint/rules/no-deprecated-zod-api.js +156 -0
  57. package/dist/eslint/rules/no-design-system-src-import.js +11 -0
  58. package/dist/eslint/rules/no-invalid-token-utility.js +46 -0
  59. package/dist/eslint/rules/no-native-visible-control.js +86 -0
  60. package/dist/eslint/rules/no-raw-color-utility.js +109 -0
  61. package/dist/eslint/rules/no-raw-focus-ring-width.js +30 -0
  62. package/dist/eslint/rules/no-raw-logo-import.js +41 -0
  63. package/dist/eslint/rules/no-shadcn-appearance-override.js +191 -0
  64. package/dist/eslint/rules/no-token-category-bypass.js +53 -0
  65. package/dist/eslint/rules/no-ui-src-import.js +10 -0
  66. package/dist/eslint/rules/no-unpinned-vercel-functions-import.js +100 -0
  67. package/dist/eslint/rules/src-import-boundary.js +207 -0
  68. package/dist/hooks/index.d.ts +0 -1
  69. package/dist/hooks/index.d.ts.map +1 -1
  70. package/dist/hooks/index.js +0 -1
  71. package/dist/index.d.ts +1 -16
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +1 -16
  74. package/dist/internal/assistant-ui/attachment.d.ts +5 -0
  75. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -0
  76. package/dist/internal/assistant-ui/attachment.js +93 -0
  77. package/dist/internal/assistant-ui/follow-up-suggestions.d.ts +3 -0
  78. package/dist/internal/assistant-ui/follow-up-suggestions.d.ts.map +1 -0
  79. package/dist/internal/assistant-ui/follow-up-suggestions.js +8 -0
  80. package/dist/internal/assistant-ui/markdown-text.d.ts +2 -0
  81. package/dist/internal/assistant-ui/markdown-text.d.ts.map +1 -0
  82. package/dist/internal/assistant-ui/markdown-text.js +54 -0
  83. package/dist/internal/assistant-ui/reasoning.d.ts +31 -0
  84. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -0
  85. package/dist/internal/assistant-ui/reasoning.js +118 -0
  86. package/dist/internal/assistant-ui/thread.d.ts +26 -0
  87. package/dist/internal/assistant-ui/thread.d.ts.map +1 -0
  88. package/dist/internal/assistant-ui/thread.js +118 -0
  89. package/dist/internal/assistant-ui/tool-fallback.d.ts +10 -0
  90. package/dist/internal/assistant-ui/tool-fallback.d.ts.map +1 -0
  91. package/dist/internal/assistant-ui/tool-fallback.js +163 -0
  92. package/dist/internal/assistant-ui/tool-group.d.ts +18 -0
  93. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -0
  94. package/dist/internal/assistant-ui/tool-group.js +44 -0
  95. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +8 -0
  96. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -0
  97. package/dist/internal/assistant-ui/tooltip-icon-button.js +10 -0
  98. package/dist/styles/globals.css +3 -209
  99. package/docs/agents/nadicodeai-ui.md +4 -6
  100. package/docs/component-classification.md +1 -1
  101. package/docs/consuming-cross-repo.md +32 -3
  102. package/docs/contract.md +16 -6
  103. package/docs/migration/base-ui-migration.md +0 -11
  104. package/docs/product-compositions.md +1 -1
  105. package/llms.txt +5 -6
  106. package/package.json +17 -29
  107. package/skills/nadicodeai-ui/SKILL.md +5 -7
  108. package/dist/ai-elements.d.ts +0 -49
  109. package/dist/ai-elements.d.ts.map +0 -1
  110. package/dist/ai-elements.js +0 -48
  111. package/dist/components/agent-avatar.d.ts +0 -7
  112. package/dist/components/agent-avatar.d.ts.map +0 -1
  113. package/dist/components/agent-avatar.js +0 -6
  114. package/dist/components/agent-chat.d.ts +0 -20
  115. package/dist/components/agent-chat.d.ts.map +0 -1
  116. package/dist/components/agent-chat.js +0 -10
  117. package/dist/components/agent-composer.d.ts +0 -56
  118. package/dist/components/agent-composer.d.ts.map +0 -1
  119. package/dist/components/agent-composer.js +0 -56
  120. package/dist/components/agent-message.d.ts +0 -117
  121. package/dist/components/agent-message.d.ts.map +0 -1
  122. package/dist/components/agent-message.js +0 -99
  123. package/dist/components/agent-thread.d.ts +0 -26
  124. package/dist/components/agent-thread.d.ts.map +0 -1
  125. package/dist/components/agent-thread.js +0 -63
  126. package/dist/components/agent-tool-approval.d.ts +0 -27
  127. package/dist/components/agent-tool-approval.d.ts.map +0 -1
  128. package/dist/components/agent-tool-approval.js +0 -43
  129. package/dist/components/ai-elements/agent.d.ts +0 -27
  130. package/dist/components/ai-elements/agent.d.ts.map +0 -1
  131. package/dist/components/ai-elements/agent.js +0 -25
  132. package/dist/components/ai-elements/artifact.d.ts +0 -24
  133. package/dist/components/ai-elements/artifact.d.ts.map +0 -1
  134. package/dist/components/ai-elements/artifact.js +0 -20
  135. package/dist/components/ai-elements/attachments.d.ts +0 -55
  136. package/dist/components/ai-elements/attachments.d.ts.map +0 -1
  137. package/dist/components/ai-elements/attachments.js +0 -125
  138. package/dist/components/ai-elements/audio-player.d.ts +0 -30
  139. package/dist/components/ai-elements/audio-player.d.ts.map +0 -1
  140. package/dist/components/ai-elements/audio-player.js +0 -41
  141. package/dist/components/ai-elements/canvas.d.ts +0 -8
  142. package/dist/components/ai-elements/canvas.d.ts.map +0 -1
  143. package/dist/components/ai-elements/canvas.js +0 -5
  144. package/dist/components/ai-elements/chain-of-thought.d.ts +0 -30
  145. package/dist/components/ai-elements/chain-of-thought.d.ts.map +0 -1
  146. package/dist/components/ai-elements/chain-of-thought.js +0 -49
  147. package/dist/components/ai-elements/checkpoint.d.ts +0 -12
  148. package/dist/components/ai-elements/checkpoint.d.ts.map +0 -1
  149. package/dist/components/ai-elements/checkpoint.js +0 -10
  150. package/dist/components/ai-elements/code-block.d.ts +0 -53
  151. package/dist/components/ai-elements/code-block.d.ts.map +0 -1
  152. package/dist/components/ai-elements/code-block.js +0 -239
  153. package/dist/components/ai-elements/commit.d.ts +0 -65
  154. package/dist/components/ai-elements/commit.d.ts.map +0 -1
  155. package/dist/components/ai-elements/commit.js +0 -83
  156. package/dist/components/ai-elements/confirmation.d.ts +0 -50
  157. package/dist/components/ai-elements/confirmation.d.ts.map +0 -1
  158. package/dist/components/ai-elements/confirmation.js +0 -57
  159. package/dist/components/ai-elements/connection.d.ts +0 -6
  160. package/dist/components/ai-elements/connection.d.ts.map +0 -1
  161. package/dist/components/ai-elements/connection.js +0 -10
  162. package/dist/components/ai-elements/context.d.ts +0 -33
  163. package/dist/components/ai-elements/context.d.ts.map +0 -1
  164. package/dist/components/ai-elements/context.js +0 -147
  165. package/dist/components/ai-elements/controls.d.ts +0 -5
  166. package/dist/components/ai-elements/controls.d.ts.map +0 -1
  167. package/dist/components/ai-elements/controls.js +0 -5
  168. package/dist/components/ai-elements/conversation.d.ts +0 -24
  169. package/dist/components/ai-elements/conversation.d.ts.map +0 -1
  170. package/dist/components/ai-elements/conversation.js +0 -41
  171. package/dist/components/ai-elements/edge.d.ts +0 -6
  172. package/dist/components/ai-elements/edge.d.ts.map +0 -1
  173. package/dist/components/ai-elements/edge.js +0 -88
  174. package/dist/components/ai-elements/environment-variables.d.ts +0 -39
  175. package/dist/components/ai-elements/environment-variables.d.ts.map +0 -1
  176. package/dist/components/ai-elements/environment-variables.js +0 -60
  177. package/dist/components/ai-elements/file-tree.d.ts +0 -27
  178. package/dist/components/ai-elements/file-tree.d.ts.map +0 -1
  179. package/dist/components/ai-elements/file-tree.js +0 -73
  180. package/dist/components/ai-elements/image.d.ts +0 -7
  181. package/dist/components/ai-elements/image.d.ts.map +0 -1
  182. package/dist/components/ai-elements/image.js +0 -3
  183. package/dist/components/ai-elements/inline-citation.d.ts +0 -39
  184. package/dist/components/ai-elements/inline-citation.d.ts.map +0 -1
  185. package/dist/components/ai-elements/inline-citation.js +0 -86
  186. package/dist/components/ai-elements/jsx-preview.d.ts +0 -30
  187. package/dist/components/ai-elements/jsx-preview.d.ts.map +0 -1
  188. package/dist/components/ai-elements/jsx-preview.js +0 -159
  189. package/dist/components/ai-elements/message.d.ts +0 -38
  190. package/dist/components/ai-elements/message.d.ts.map +0 -1
  191. package/dist/components/ai-elements/message.js +0 -91
  192. package/dist/components/ai-elements/mic-selector.d.ts +0 -46
  193. package/dist/components/ai-elements/mic-selector.d.ts.map +0 -1
  194. package/dist/components/ai-elements/mic-selector.js +0 -180
  195. package/dist/components/ai-elements/model-selector.d.ts +0 -36
  196. package/dist/components/ai-elements/model-selector.d.ts.map +0 -1
  197. package/dist/components/ai-elements/model-selector.js +0 -18
  198. package/dist/components/ai-elements/node.d.ts +0 -22
  199. package/dist/components/ai-elements/node.d.ts.map +0 -1
  200. package/dist/components/ai-elements/node.js +0 -12
  201. package/dist/components/ai-elements/open-in-chat.d.ts +0 -27
  202. package/dist/components/ai-elements/open-in-chat.d.ts.map +0 -1
  203. package/dist/components/ai-elements/open-in-chat.js +0 -81
  204. package/dist/components/ai-elements/package-info.d.ts +0 -30
  205. package/dist/components/ai-elements/package-info.d.ts.map +0 -1
  206. package/dist/components/ai-elements/package-info.js +0 -50
  207. package/dist/components/ai-elements/panel.d.ts +0 -6
  208. package/dist/components/ai-elements/panel.d.ts.map +0 -1
  209. package/dist/components/ai-elements/panel.js +0 -5
  210. package/dist/components/ai-elements/persona.d.ts +0 -49
  211. package/dist/components/ai-elements/persona.d.ts.map +0 -1
  212. package/dist/components/ai-elements/persona.js +0 -175
  213. package/dist/components/ai-elements/plan.d.ts +0 -27
  214. package/dist/components/ai-elements/plan.d.ts.map +0 -1
  215. package/dist/components/ai-elements/plan.js +0 -34
  216. package/dist/components/ai-elements/prompt-input.d.ts +0 -149
  217. package/dist/components/ai-elements/prompt-input.d.ts.map +0 -1
  218. package/dist/components/ai-elements/prompt-input.js +0 -704
  219. package/dist/components/ai-elements/queue.d.ts +0 -62
  220. package/dist/components/ai-elements/queue.d.ts.map +0 -1
  221. package/dist/components/ai-elements/queue.js +0 -24
  222. package/dist/components/ai-elements/reasoning.d.ts +0 -27
  223. package/dist/components/ai-elements/reasoning.d.ts.map +0 -1
  224. package/dist/components/ai-elements/reasoning.js +0 -92
  225. package/dist/components/ai-elements/sandbox.d.ts +0 -25
  226. package/dist/components/ai-elements/sandbox.d.ts.map +0 -1
  227. package/dist/components/ai-elements/sandbox.js +0 -15
  228. package/dist/components/ai-elements/schema-display.d.ts +0 -56
  229. package/dist/components/ai-elements/schema-display.d.ts.map +0 -1
  230. package/dist/components/ai-elements/schema-display.js +0 -90
  231. package/dist/components/ai-elements/shimmer.d.ts +0 -10
  232. package/dist/components/ai-elements/shimmer.d.ts.map +0 -1
  233. package/dist/components/ai-elements/shimmer.js +0 -11
  234. package/dist/components/ai-elements/snippet.d.ts +0 -19
  235. package/dist/components/ai-elements/snippet.d.ts.map +0 -1
  236. package/dist/components/ai-elements/snippet.js +0 -32
  237. package/dist/components/ai-elements/sources.d.ts +0 -13
  238. package/dist/components/ai-elements/sources.d.ts.map +0 -1
  239. package/dist/components/ai-elements/sources.js +0 -9
  240. package/dist/components/ai-elements/speech-input.d.ts +0 -55
  241. package/dist/components/ai-elements/speech-input.d.ts.map +0 -1
  242. package/dist/components/ai-elements/speech-input.js +0 -187
  243. package/dist/components/ai-elements/stack-trace.d.ts +0 -38
  244. package/dist/components/ai-elements/stack-trace.d.ts.map +0 -1
  245. package/dist/components/ai-elements/stack-trace.js +0 -181
  246. package/dist/components/ai-elements/suggestion.d.ts +0 -11
  247. package/dist/components/ai-elements/suggestion.d.ts.map +0 -1
  248. package/dist/components/ai-elements/suggestion.js +0 -13
  249. package/dist/components/ai-elements/task.d.ts +0 -15
  250. package/dist/components/ai-elements/task.d.ts.map +0 -1
  251. package/dist/components/ai-elements/task.js +0 -10
  252. package/dist/components/ai-elements/terminal.d.ts +0 -28
  253. package/dist/components/ai-elements/terminal.d.ts.map +0 -1
  254. package/dist/components/ai-elements/terminal.js +0 -55
  255. package/dist/components/ai-elements/test-results.d.ts +0 -59
  256. package/dist/components/ai-elements/test-results.d.ts.map +0 -1
  257. package/dist/components/ai-elements/test-results.js +0 -98
  258. package/dist/components/ai-elements/tool.d.ts +0 -32
  259. package/dist/components/ai-elements/tool.d.ts.map +0 -1
  260. package/dist/components/ai-elements/tool.js +0 -49
  261. package/dist/components/ai-elements/toolbar.d.ts +0 -6
  262. package/dist/components/ai-elements/toolbar.d.ts.map +0 -1
  263. package/dist/components/ai-elements/toolbar.js +0 -5
  264. package/dist/components/ai-elements/transcription.d.ts +0 -17
  265. package/dist/components/ai-elements/transcription.d.ts.map +0 -1
  266. package/dist/components/ai-elements/transcription.js +0 -36
  267. package/dist/components/ai-elements/voice-selector.d.ts +0 -65
  268. package/dist/components/ai-elements/voice-selector.d.ts.map +0 -1
  269. package/dist/components/ai-elements/voice-selector.js +0 -224
  270. package/dist/components/ai-elements/web-preview.d.ts +0 -35
  271. package/dist/components/ai-elements/web-preview.d.ts.map +0 -1
  272. package/dist/components/ai-elements/web-preview.js +0 -66
  273. package/dist/components/artifact-panel.d.ts +0 -130
  274. package/dist/components/artifact-panel.d.ts.map +0 -1
  275. package/dist/components/artifact-panel.js +0 -180
  276. package/dist/components/attachment.d.ts +0 -24
  277. package/dist/components/attachment.d.ts.map +0 -1
  278. package/dist/components/attachment.js +0 -68
  279. package/dist/components/bubble.d.ts +0 -17
  280. package/dist/components/bubble.d.ts.map +0 -1
  281. package/dist/components/bubble.js +0 -59
  282. package/dist/components/demo-surface.d.ts +0 -34
  283. package/dist/components/demo-surface.d.ts.map +0 -1
  284. package/dist/components/demo-surface.js +0 -21
  285. package/dist/components/files-preview.d.ts +0 -36
  286. package/dist/components/files-preview.d.ts.map +0 -1
  287. package/dist/components/files-preview.js +0 -85
  288. package/dist/components/marker.d.ts +0 -11
  289. package/dist/components/marker.d.ts.map +0 -1
  290. package/dist/components/marker.js +0 -34
  291. package/dist/components/message-scroller.d.ts +0 -17
  292. package/dist/components/message-scroller.d.ts.map +0 -1
  293. package/dist/components/message-scroller.js +0 -29
  294. package/dist/components/message.d.ts +0 -11
  295. package/dist/components/message.d.ts.map +0 -1
  296. package/dist/components/message.js +0 -21
  297. package/dist/components/state-notice.d.ts +0 -13
  298. package/dist/components/state-notice.d.ts.map +0 -1
  299. package/dist/components/state-notice.js +0 -8
  300. package/dist/components/watch-it-work-band.d.ts +0 -12
  301. package/dist/components/watch-it-work-band.d.ts.map +0 -1
  302. package/dist/components/watch-it-work-band.js +0 -8
  303. package/dist/hooks/use-controllable-state.d.ts +0 -9
  304. package/dist/hooks/use-controllable-state.d.ts.map +0 -1
  305. package/dist/hooks/use-controllable-state.js +0 -23
  306. package/dist/lib/agent-attachment.d.ts +0 -11
  307. package/dist/lib/agent-attachment.d.ts.map +0 -1
  308. package/dist/lib/agent-attachment.js +0 -19
  309. package/dist/lib/agent-contracts.d.ts +0 -132
  310. package/dist/lib/agent-contracts.d.ts.map +0 -1
  311. package/dist/lib/agent-contracts.js +0 -6
  312. package/dist/lib/agent-state.d.ts +0 -22
  313. package/dist/lib/agent-state.d.ts.map +0 -1
  314. package/dist/lib/agent-state.js +0 -96
  315. package/dist/lib/agent-work-state.d.ts +0 -36
  316. package/dist/lib/agent-work-state.d.ts.map +0 -1
  317. package/dist/lib/agent-work-state.js +0 -36
  318. package/dist/lib/message-scroller-primitive/components.d.ts +0 -17
  319. package/dist/lib/message-scroller-primitive/components.d.ts.map +0 -1
  320. package/dist/lib/message-scroller-primitive/components.js +0 -204
  321. package/dist/lib/message-scroller-primitive/geometry.d.ts +0 -51
  322. package/dist/lib/message-scroller-primitive/geometry.d.ts.map +0 -1
  323. package/dist/lib/message-scroller-primitive/geometry.js +0 -199
  324. package/dist/lib/message-scroller-primitive/index.d.ts +0 -12
  325. package/dist/lib/message-scroller-primitive/index.d.ts.map +0 -1
  326. package/dist/lib/message-scroller-primitive/index.js +0 -12
  327. package/dist/lib/message-scroller-primitive/stores.d.ts +0 -6
  328. package/dist/lib/message-scroller-primitive/stores.d.ts.map +0 -1
  329. package/dist/lib/message-scroller-primitive/stores.js +0 -53
  330. package/dist/lib/message-scroller-primitive/types.d.ts +0 -88
  331. package/dist/lib/message-scroller-primitive/types.d.ts.map +0 -1
  332. package/dist/lib/message-scroller-primitive/types.js +0 -40
  333. package/dist/lib/message-scroller-primitive/use-message-scroller-commands.d.ts +0 -19
  334. package/dist/lib/message-scroller-primitive/use-message-scroller-commands.d.ts.map +0 -1
  335. package/dist/lib/message-scroller-primitive/use-message-scroller-commands.js +0 -188
  336. package/dist/lib/message-scroller-primitive/use-message-scroller-controller.d.ts +0 -7
  337. package/dist/lib/message-scroller-primitive/use-message-scroller-controller.d.ts.map +0 -1
  338. package/dist/lib/message-scroller-primitive/use-message-scroller-controller.js +0 -506
  339. package/dist/lib/message-scroller-primitive/use-message-scroller-refs.d.ts +0 -49
  340. package/dist/lib/message-scroller-primitive/use-message-scroller-refs.d.ts.map +0 -1
  341. package/dist/lib/message-scroller-primitive/use-message-scroller-refs.js +0 -90
  342. package/dist/lib/message-scroller-primitive/use-render.d.ts +0 -22
  343. package/dist/lib/message-scroller-primitive/use-render.d.ts.map +0 -1
  344. package/dist/lib/message-scroller-primitive/use-render.js +0 -113
  345. package/dist/lib/message-scroller-primitive/utils.d.ts +0 -4
  346. package/dist/lib/message-scroller-primitive/utils.d.ts.map +0 -1
  347. package/dist/lib/message-scroller-primitive/utils.js +0 -9
  348. package/docs/agent-work-surfaces.md +0 -132
  349. package/docs/migration/ai-elements-vendoring.md +0 -29
  350. package/docs/terminal-tui-semantics.md +0 -172
@@ -1,9 +1,31 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
+ /**
4
+ * The tip value is TEXT, so it takes the feedback pair's deep tone, not the
5
+ * rail tone the segments wear: `--nc-state-review` / `--nc-state-blocked` are
6
+ * fill tones (0.85 amber reads at 1.6:1 on the light canvas), while
7
+ * `--nc-warning-deep` and `--nc-error-deep` are authored light AND dark so the
8
+ * percentage stays readable in both modes — and it is loudest exactly when it
9
+ * crosses a threshold.
10
+ */
3
11
  const BULLET_BAR_VALUE_TONE = {
4
12
  ok: "text-foreground",
5
- warn: "text-(--nc-state-review)",
6
- over: "text-(--nc-state-blocked)",
13
+ warn: "text-(--nc-warning-deep)",
14
+ over: "text-(--nc-error-deep)",
15
+ };
16
+ /**
17
+ * The consumed length carries the severity too, not only the tip figure: a
18
+ * meter at its cap and a meter at 40% drew the same calm ramp fill, so the one
19
+ * state where the reader is actually blocked was legible only from a 10px
20
+ * percentage. Position stays the primary signal (the threshold and cap ticks
21
+ * do not move); the tone reinforces it, per DESIGN.md's meter grammar. These
22
+ * are the rail tones of the feedback pairs, the same register the overflow
23
+ * segment already wears.
24
+ */
25
+ const BULLET_BAR_FILL_TONE = {
26
+ ok: "bg-(--nc-chart-seq-3)",
27
+ warn: "bg-(--nc-state-review)",
28
+ over: "bg-(--nc-state-blocked)",
7
29
  };
8
30
  function percent(fraction) {
9
31
  return `${Number((fraction * 100).toFixed(3))}%`;
@@ -11,7 +33,7 @@ function percent(fraction) {
11
33
  function defaultFormat(value) {
12
34
  return value.toLocaleString("en-US");
13
35
  }
14
- function BulletBar({ value, max, thresholdFraction, label, valueFormatter = defaultFormat, valueText, className, ...props }) {
36
+ function BulletBar({ value, max, thresholdFraction, label, size = "panel", valueFormatter = defaultFormat, valueText, className, ...props }) {
15
37
  const overflow = Math.max(value - max, 0);
16
38
  const total = Math.max(value, max);
17
39
  const fillFraction = total > 0 ? Math.min(value, max) / total : 0;
@@ -19,12 +41,43 @@ function BulletBar({ value, max, thresholdFraction, label, valueFormatter = defa
19
41
  const capFraction = total > 0 ? max / total : 1;
20
42
  const thresholdTickFraction = capFraction * thresholdFraction;
21
43
  const tipFraction = fillFraction + overflowFraction;
22
- const severity = overflow > 0 ? "over" : value >= thresholdFraction * max ? "warn" : "ok";
44
+ // Reaching the cap IS the blocked state, not merely the last warning step:
45
+ // an allowance consumed to exactly 100% stops the work the same way 104%
46
+ // does, so both read as `over`. A zero cap with no value stays `ok` — an
47
+ // unconfigured meter is not an exhausted one.
48
+ const severity = overflow > 0 || (max > 0 && value >= max)
49
+ ? "over"
50
+ : max > 0 && value >= thresholdFraction * max
51
+ ? "warn"
52
+ : "ok";
23
53
  const meterValueText = valueText ??
24
54
  `${valueFormatter(value)} of ${valueFormatter(max)}${overflow > 0 ? ` (${valueFormatter(overflow)} over the cap)` : ""}`;
25
- return (_jsxs("div", { "data-slot": "bullet-bar", "data-severity": severity, className: cn("flex flex-col gap-1", className), ...props, children: [_jsxs("div", { role: "meter", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": max, "aria-valuenow": Math.min(value, max), "aria-valuetext": meterValueText, className: "relative h-3 w-full", children: [_jsx("div", { "data-slot": "bullet-bar-track", className: "absolute inset-y-0 rounded-r-[4px] bg-(--nc-chart-seq-1)", style: { left: 0, width: percent(capFraction) } }), _jsx("div", { "data-slot": "bullet-bar-fill", className: cn("absolute inset-y-0 bg-(--nc-chart-seq-3)", overflow === 0 && "rounded-r-[4px]"), style: { left: 0, width: percent(fillFraction) } }), overflow > 0 ? (_jsx("div", { "data-slot": "bullet-bar-overflow", className: "absolute inset-y-0 rounded-r-[4px] bg-(--nc-state-blocked)", style: {
26
- left: percent(fillFraction),
27
- width: percent(overflowFraction),
28
- } })) : null, _jsx("div", { "data-slot": "bullet-bar-threshold-tick", "aria-hidden": "true", className: "absolute -inset-y-0.5 w-px bg-foreground", style: { left: percent(thresholdTickFraction) } }), _jsx("div", { "data-slot": "bullet-bar-cap-tick", "aria-hidden": "true", className: "absolute -inset-y-0.5 w-px bg-foreground", style: { left: percent(capFraction) } })] }), _jsx("div", { className: "relative h-4 w-full text-xs", "aria-hidden": "true", children: _jsx("span", { "data-slot": "bullet-bar-value", className: cn("absolute font-mono whitespace-nowrap tabular-nums", tipFraction > 0.6 && "-translate-x-full", BULLET_BAR_VALUE_TONE[severity]), style: { left: percent(tipFraction) }, children: valueFormatter(value) }) })] }));
55
+ // The row scale prints this instead of the tip value: at row scale the
56
+ // reader is asking "how close to the wall", not "how many".
57
+ const consumedPercent = max > 0 ? Math.round((value / max) * 100) : 0;
58
+ const segments = (_jsxs(_Fragment, { children: [_jsx("div", { "data-slot": "bullet-bar-track",
59
+ // One step darker than the surface it sits on, in both themes: at
60
+ // `bg-muted` an empty meter on the light canvas read as a hairline
61
+ // rather than as a track with nothing in it.
62
+ className: "absolute inset-y-0 rounded-r-sm bg-muted-foreground/20", style: { left: 0, width: percent(capFraction) } }), _jsx("div", { "data-slot": "bullet-bar-fill", className: cn("absolute inset-y-0", BULLET_BAR_FILL_TONE[severity], overflow === 0 && "rounded-r-sm"), style: { left: 0, width: percent(fillFraction) } }), overflow > 0 ? (_jsx("div", { "data-slot": "bullet-bar-overflow",
63
+ // A darker step of the same error family: now that the consumed
64
+ // length is itself red at the cap, the over-run has to stay a
65
+ // DISTINCT segment (DESIGN.md), which one shared tone would erase.
66
+ className: "absolute inset-y-0 rounded-r-sm bg-(--nc-error-deep)", style: {
67
+ left: percent(fillFraction),
68
+ width: percent(overflowFraction),
69
+ } })) : null] }));
70
+ const meterAria = {
71
+ role: "meter",
72
+ "aria-label": label,
73
+ "aria-valuemin": 0,
74
+ "aria-valuemax": max,
75
+ "aria-valuenow": Math.min(value, max),
76
+ "aria-valuetext": meterValueText,
77
+ };
78
+ if (size === "row") {
79
+ return (_jsxs("div", { "data-slot": "bullet-bar", "data-severity": severity, "data-size": "row", className: cn("flex items-center gap-2", className), ...props, children: [_jsxs("span", { "data-slot": "bullet-bar-percent", "aria-hidden": "true", className: cn("font-mono text-xs tabular-nums", BULLET_BAR_VALUE_TONE[severity]), children: [consumedPercent, "%"] }), _jsx("div", { ...meterAria, className: "relative h-1 min-w-0 flex-1", children: segments })] }));
80
+ }
81
+ return (_jsxs("div", { "data-slot": "bullet-bar", "data-severity": severity, "data-size": "panel", className: cn("flex flex-col gap-1", className), ...props, children: [_jsxs("div", { ...meterAria, className: "relative h-3 w-full", children: [segments, _jsx("div", { "data-slot": "bullet-bar-threshold-tick", "aria-hidden": "true", className: "absolute -inset-y-0.5 w-px bg-foreground", style: { left: percent(thresholdTickFraction) } }), _jsx("div", { "data-slot": "bullet-bar-cap-tick", "aria-hidden": "true", className: "absolute -inset-y-0.5 w-px bg-foreground", style: { left: percent(capFraction) } })] }), _jsx("div", { className: "relative h-4 w-full text-xs", "aria-hidden": "true", children: _jsx("span", { "data-slot": "bullet-bar-value", className: cn("absolute font-mono whitespace-nowrap tabular-nums", tipFraction > 0.6 && "-translate-x-full", BULLET_BAR_VALUE_TONE[severity]), style: { left: percent(tipFraction) }, children: valueFormatter(value) }) })] }));
29
82
  }
30
83
  export { BulletBar };
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { type DateRangePreset, type DateRangeValue } from "./chart-date-range";
3
- declare function DateRangeControl({ value, onChange, label, presets, presetLabels, customLabel, className, ...props }: Omit<React.ComponentProps<"div">, "children" | "onChange"> & {
3
+ declare function DateRangeControl({ value, onChange, label, presets, presetLabels, customLabel, formatCustomValue, className, ...props }: Omit<React.ComponentProps<"div">, "children" | "onChange"> & {
4
4
  value: DateRangeValue;
5
5
  onChange: (value: DateRangeValue) => void;
6
6
  /** Accessible name for the control group. */
@@ -12,6 +12,16 @@ declare function DateRangeControl({ value, onChange, label, presets, presetLabel
12
12
  presets?: readonly DateRangePreset[];
13
13
  presetLabels?: Partial<Record<DateRangePreset, string>>;
14
14
  customLabel?: string;
15
+ /**
16
+ * Renders the selected custom window as a finished, localized label. The
17
+ * package owns no locale, so without it the trigger falls back to the ISO
18
+ * pair the codec stores — a storage format, never a label a reader should
19
+ * meet. Every locale-aware consumer passes this.
20
+ */
21
+ formatCustomValue?: (value: {
22
+ from: string;
23
+ to: string;
24
+ }) => string;
15
25
  }): React.JSX.Element;
16
26
  export { DateRangeControl };
17
27
  //# sourceMappingURL=chart-date-range-control.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-date-range-control.d.ts","sourceRoot":"","sources":["../../src/components/chart-date-range-control.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,+BAA+B,CAAC;AA0BvC,iBAAS,gBAAgB,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,KAAoB,EACpB,OAA4B,EAC5B,YAAY,EACZ,WAAsB,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG;IAC9D,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC1C,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,qBA2EA;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"chart-date-range-control.d.ts","sourceRoot":"","sources":["../../src/components/chart-date-range-control.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,+BAA+B,CAAC;AAmCvC,iBAAS,gBAAgB,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,KAAoB,EACpB,OAA4B,EAC5B,YAAY,EACZ,WAAsB,EACtB,iBAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG;IAC9D,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC1C,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;CACrE,qBAoFA;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -23,13 +23,20 @@ import { DATE_RANGE_PRESETS, formatIsoDay, parseIsoDay, } from "./chart-date-ran
23
23
  * (`DATE_RANGE_PRESETS`) is unchanged, so a URL arriving with an un-offered but
24
24
  * valid preset token still decodes; the consumer decides its fallback.
25
25
  */
26
+ // Which range the chart is showing is a selection, and this row is the only
27
+ // thing that says it. A soft neutral fill sits about 1.1:1 against the page in
28
+ // both modes, which is a state no sighted reader can find, so the selected
29
+ // preset wears the navigation-selection role: the same colour the console
30
+ // marks a chosen destination with, and the only neutral-safe token that clears
31
+ // the 3:1 a state-bearing control owes.
32
+ const SELECTED_PRESET_CLASS = "bg-(--nc-navigation-selection-bg) text-(--nc-navigation-selection-fg) hover:bg-(--nc-navigation-selection-hover) hover:text-(--nc-navigation-selection-fg)";
26
33
  const DEFAULT_PRESET_LABELS = {
27
34
  "7d": "7d",
28
35
  "14d": "14d",
29
36
  "30d": "30d",
30
37
  cycle: "This cycle",
31
38
  };
32
- function DateRangeControl({ value, onChange, label = "Date range", presets = DATE_RANGE_PRESETS, presetLabels, customLabel = "Custom", className, ...props }) {
39
+ function DateRangeControl({ value, onChange, label = "Date range", presets = DATE_RANGE_PRESETS, presetLabels, customLabel = "Custom", formatCustomValue, className, ...props }) {
33
40
  const [open, setOpen] = React.useState(false);
34
41
  const [pending, setPending] = React.useState(undefined);
35
42
  const isCustom = value.kind === "custom";
@@ -56,7 +63,10 @@ function DateRangeControl({ value, onChange, label = "Date range", presets = DAT
56
63
  }
57
64
  return (_jsxs("div", { "data-slot": "date-range-control", role: "group", "aria-label": label, className: cn("flex flex-wrap items-center gap-1", className), ...props, children: [presets.map((preset) => {
58
65
  const active = value.kind === "preset" && value.preset === preset;
59
- return (_jsx(Button, { size: "sm", variant: active ? "secondary" : "ghost", "aria-pressed": active, onClick: () => onChange({ kind: "preset", preset }), children: presetLabels?.[preset] ?? DEFAULT_PRESET_LABELS[preset] }, preset));
60
- }), _jsxs(Popover, { open: open, onOpenChange: handleOpenChange, children: [_jsx(PopoverTrigger, { render: _jsxs(Button, { size: "sm", variant: isCustom ? "secondary" : "ghost", "aria-pressed": isCustom, children: [_jsx(CalendarIcon, { "data-icon": "inline-start" }), isCustom ? `${value.from} – ${value.to}` : customLabel] }) }), _jsx(PopoverContent, { align: "start", className: "w-auto p-0", children: _jsx(Calendar, { mode: "range", numberOfMonths: 2, defaultMonth: selected?.from, selected: selected, onSelect: handleSelect }) })] })] }));
66
+ return (_jsx(Button, { size: "sm", variant: "ghost", "aria-pressed": active, className: active ? SELECTED_PRESET_CLASS : undefined, onClick: () => onChange({ kind: "preset", preset }), children: presetLabels?.[preset] ?? DEFAULT_PRESET_LABELS[preset] }, preset));
67
+ }), _jsxs(Popover, { open: open, onOpenChange: handleOpenChange, children: [_jsx(PopoverTrigger, { render: _jsxs(Button, { size: "sm", variant: "ghost", "aria-pressed": isCustom, className: isCustom ? SELECTED_PRESET_CLASS : undefined, children: [_jsx(CalendarIcon, { "data-icon": "inline-start" }), isCustom
68
+ ? (formatCustomValue?.({ from: value.from, to: value.to }) ??
69
+ `${value.from} – ${value.to}`)
70
+ : customLabel] }) }), _jsx(PopoverContent, { align: "start", className: "w-auto p-0", children: _jsx(Calendar, { mode: "range", numberOfMonths: 2, defaultMonth: selected?.from, selected: selected, onSelect: handleSelect }) })] })] }));
61
71
  }
62
72
  export { DateRangeControl };
@@ -17,8 +17,14 @@ declare const CHART_ENTITY_COLOR_TOKENS: readonly ["var(--nc-chart-1)", "var(--n
17
17
  /**
18
18
  * The neutral register for folded "everything else" entities. A muted ink
19
19
  * token, never an extra categorical hue.
20
+ *
21
+ * `--nc-muted` and not the `--muted-foreground` role: the role resolves to the
22
+ * body-text tone, which in dark is near-white (L 0.83) — as a mark it becomes
23
+ * the loudest thing in the chart, so the tail outshouts every named entity.
24
+ * `--nc-muted` is authored as a mid grey in both modes (L 0.53 light / 0.65
25
+ * dark), which is what a folded tail should read as either way.
20
26
  */
21
- declare const CHART_ENTITY_OTHER_COLOR = "var(--muted-foreground)";
27
+ declare const CHART_ENTITY_OTHER_COLOR = "var(--nc-muted)";
22
28
  type EntityColorMap = Readonly<Record<string, string>>;
23
29
  /**
24
30
  * Assigns `var(--nc-chart-1..6)` in fixed order by FIRST APPEARANCE of each
@@ -1 +1 @@
1
- {"version":3,"file":"chart-entity-colors.d.ts","sourceRoot":"","sources":["../../src/components/chart-entity-colors.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,QAAA,MAAM,yBAAyB,yIAOrB,CAAC;AAEX;;;GAGG;AACH,QAAA,MAAM,wBAAwB,4BAA4B,CAAC;AAE3D,KAAK,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD;;;;GAIG;AACH,iBAAS,oBAAoB,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CA2B1E;AAED;;;;GAIG;AACH,iBAAS,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;AAClG,YAAY,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"chart-entity-colors.d.ts","sourceRoot":"","sources":["../../src/components/chart-entity-colors.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,QAAA,MAAM,yBAAyB,yIAOrB,CAAC;AAEX;;;;;;;;;GASG;AACH,QAAA,MAAM,wBAAwB,oBAAoB,CAAC;AAEnD,KAAK,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD;;;;GAIG;AACH,iBAAS,oBAAoB,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CA2B1E;AAED;;;;GAIG;AACH,iBAAS,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;AAClG,YAAY,EAAE,cAAc,EAAE,CAAC"}
@@ -24,8 +24,14 @@ const CHART_ENTITY_COLOR_TOKENS = [
24
24
  /**
25
25
  * The neutral register for folded "everything else" entities. A muted ink
26
26
  * token, never an extra categorical hue.
27
+ *
28
+ * `--nc-muted` and not the `--muted-foreground` role: the role resolves to the
29
+ * body-text tone, which in dark is near-white (L 0.83) — as a mark it becomes
30
+ * the loudest thing in the chart, so the tail outshouts every named entity.
31
+ * `--nc-muted` is authored as a mid grey in both modes (L 0.53 light / 0.65
32
+ * dark), which is what a folded tail should read as either way.
27
33
  */
28
- const CHART_ENTITY_OTHER_COLOR = "var(--muted-foreground)";
34
+ const CHART_ENTITY_OTHER_COLOR = "var(--nc-muted)";
29
35
  /**
30
36
  * Assigns `var(--nc-chart-1..6)` in fixed order by FIRST APPEARANCE of each
31
37
  * stable entity id. Duplicate ids keep their first assignment. Entities past
@@ -1 +1 @@
1
- {"version":3,"file":"chart-kpi-stat.d.ts","sourceRoot":"","sources":["../../src/components/chart-kpi-stat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;;;;;;;GAWG;AAEH,KAAK,YAAY,GAAG;IAClB,yCAAyC;IACzC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,iBAAS,OAAO,CAAC,EACf,KAAK,EACL,KAAK,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IACjD,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B,qBA6BA;AAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"chart-kpi-stat.d.ts","sourceRoot":"","sources":["../../src/components/chart-kpi-stat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;;;;;;;GAWG;AAEH,KAAK,YAAY,GAAG;IAClB,yCAAyC;IACzC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,iBAAS,OAAO,CAAC,EACf,KAAK,EACL,KAAK,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IACjD,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B,qBAkCA;AAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,CAAC"}
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
3
  import { Delta } from "./chart-delta.js";
4
4
  function KpiStat({ label, value, delta, sparkline, className, ...props }) {
5
- return (_jsxs("div", { "data-slot": "kpi-stat", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx("div", { "data-slot": "kpi-stat-label", className: "font-mono text-xs text-muted-foreground uppercase", children: label }), _jsxs("div", { className: "flex items-end justify-between gap-3", children: [_jsx("div", { "data-slot": "kpi-stat-value", className: "text-3xl leading-none font-semibold text-foreground", children: value }), sparkline ? (_jsx("div", { "data-slot": "kpi-stat-sparkline", "aria-hidden": "true", children: sparkline })) : null] }), delta ? (_jsx(Delta, { value: delta.value, direction: delta.direction, upIsGood: delta.upIsGood, vsLabel: delta.vsLabel })) : null] }));
5
+ return (_jsxs("div", { "data-slot": "kpi-stat", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx("div", { "data-slot": "kpi-stat-label", className: "text-xs font-medium text-muted-foreground", children: label }), _jsxs("div", { className: "flex items-end justify-between gap-3", children: [_jsx("div", { "data-slot": "kpi-stat-value", className: "text-3xl leading-none font-semibold text-foreground", children: value }), sparkline ? (_jsx("div", { "data-slot": "kpi-stat-sparkline", "aria-hidden": "true", children: sparkline })) : null] }), delta ? (_jsx(Delta, { value: delta.value, direction: delta.direction, upIsGood: delta.upIsGood, vsLabel: delta.vsLabel })) : null] }));
6
6
  }
7
7
  export { KpiStat };
@@ -1 +1 @@
1
- {"version":3,"file":"chart-time-series.d.ts","sourceRoot":"","sources":["../../src/components/chart-time-series.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kCAAkC,CAAC;AAsD1C,KAAK,gBAAgB,GAAG;IACtB,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD,KAAK,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IACxE,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpC,2DAA2D;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAsJF,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBA+CjB;AAED,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBAwDjB;AAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"chart-time-series.d.ts","sourceRoot":"","sources":["../../src/components/chart-time-series.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kCAAkC,CAAC;AA+G1C,KAAK,gBAAgB,GAAG;IACtB,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD,KAAK,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IACxE,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpC,2DAA2D;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAsJF,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBAyDjB;AAED,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBA6EjB;AAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC"}
@@ -43,6 +43,59 @@ import { CHART_ENTITY_OTHER_COLOR, entityColor, } from "./chart-entity-colors.js
43
43
  const CHART_SURFACE_FOCUS_CLASS = "[&_.recharts-surface:focus-visible]:outline-2 " +
44
44
  "[&_.recharts-surface:focus-visible]:outline-ring " +
45
45
  "[&_.recharts-surface:focus-visible]:outline-offset-2";
46
+ /**
47
+ * The x ticks land at ONE constant stride across the range, and the stride is
48
+ * the smallest one whose labels still clear each other at the width the chart
49
+ * actually has. Recharts' default `preserveEnd` fitting is greedy on label
50
+ * width, so a 30-day axis draws the narrow early labels daily and then switches
51
+ * to every other day once "Jul 10" is wider than "Jul 1" — the rhythm breaks
52
+ * mid-chart, differently per locale. `equidistantPreserveStart` evaluates one
53
+ * stride against every label and raises it until the whole run fits, so the
54
+ * axis is even by construction AND survives a narrow viewport: a count fixed at
55
+ * the wide case superimposed eight labels into an unreadable smear on a phone,
56
+ * and worse in locales whose date labels run longer.
57
+ */
58
+ const X_AXIS_MIN_TICK_GAP = 48;
59
+ /**
60
+ * How many ticks the y axis draws, ends included. Recharts divides the data's
61
+ * own maximum by this count when it is left to itself, which produces steps of
62
+ * whatever the data happens to reach: one console chart read $0/$5/$10 while the
63
+ * chart beside it read EUR0/9/18/27/36, and the two stopped sharing a numeric
64
+ * register. The domain is rounded up to a step a person counts in instead.
65
+ */
66
+ const Y_AXIS_TICK_COUNT = 5;
67
+ /** The steps a reader counts in, per order of magnitude. */
68
+ const NICE_STEP_MULTIPLES = [1, 2, 2.5, 5, 10];
69
+ function niceStep(rawStep) {
70
+ if (!Number.isFinite(rawStep) || rawStep <= 0)
71
+ return 1;
72
+ const magnitude = 10 ** Math.floor(Math.log10(rawStep));
73
+ const normalized = rawStep / magnitude;
74
+ const multiple = NICE_STEP_MULTIPLES.find((candidate) => normalized <= candidate) ?? 10;
75
+ return multiple * magnitude;
76
+ }
77
+ /**
78
+ * The stacked maximum across the data, rounded up to a whole number of nice
79
+ * steps. Returns `undefined` when there is nothing to bound, so the axis falls
80
+ * back to recharts' own domain rather than pinning itself to zero.
81
+ */
82
+ function niceYDomainMax(data, series) {
83
+ let max = 0;
84
+ for (const datum of data) {
85
+ let total = 0;
86
+ for (const entry of series) {
87
+ const value = datum[entry.id];
88
+ if (typeof value === "number" && Number.isFinite(value))
89
+ total += value;
90
+ }
91
+ if (total > max)
92
+ max = total;
93
+ }
94
+ if (max <= 0)
95
+ return undefined;
96
+ const step = niceStep(max / (Y_AXIS_TICK_COUNT - 1));
97
+ return step * (Y_AXIS_TICK_COUNT - 1);
98
+ }
46
99
  /**
47
100
  * Synthetic id/key for the single aggregated neutral series. Entities past the
48
101
  * sixth resolve to the neutral register, and rendering each as its own
@@ -63,7 +116,7 @@ function defaultFormat(value) {
63
116
  */
64
117
  function tooltipRowFormatter(series, valueFormatter) {
65
118
  const labelById = new Map(series.map((entry) => [entry.id, entry.label]));
66
- return (value, name, item) => (_jsxs(_Fragment, { children: [_jsx("span", { "data-slot": "time-series-tooltip-swatch", className: "size-2.5 shrink-0 rounded-[2px]", style: { backgroundColor: item.color ?? item.payload?.fill } }), _jsxs("span", { className: "flex flex-1 items-center justify-between gap-2 leading-none", children: [_jsx("span", { className: "text-muted-foreground", children: labelById.get(String(name)) ?? name }), _jsx("span", { className: "font-mono font-medium text-foreground tabular-nums", children: typeof value === "number" ? valueFormatter(value) : String(value) })] })] }));
119
+ return (value, name, item) => (_jsxs(_Fragment, { children: [_jsx("span", { "data-slot": "time-series-tooltip-swatch", className: "size-2.5 shrink-0 rounded-xs", style: { backgroundColor: item.color ?? item.payload?.fill } }), _jsxs("span", { className: "flex flex-1 items-center justify-between gap-2 leading-none", children: [_jsx("span", { className: "text-muted-foreground", children: labelById.get(String(name)) ?? name }), _jsx("span", { className: "font-mono font-medium text-foreground tabular-nums", children: typeof value === "number" ? valueFormatter(value) : String(value) })] })] }));
67
120
  }
68
121
  function seriesChartConfig(series, entityColorMap) {
69
122
  return Object.fromEntries(series.map((entry) => [
@@ -114,14 +167,19 @@ function TimeSeriesFrame({ label, className, children, ...props }) {
114
167
  function TimeSeriesBars({ data, xKey, series, entityColorMap, label, xLabel = "Period", valueFormatter = defaultFormat, yAxisWidth, otherLabel = "Other", className, ...props }) {
115
168
  const folded = foldNeutralSeries(series, entityColorMap, data, otherLabel);
116
169
  const config = seriesChartConfig(folded.series, entityColorMap);
117
- return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-bars", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(BarChart, { accessibilityLayer: true, title: label, data: folded.data, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8 }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, _jsx(BarStack, { stackId: "stacked", radius: [4, 4, 0, 0], children: folded.series.map((entry) => (_jsx(Bar, { dataKey: entry.id, isAnimationActive: false, maxBarSize: 24, fill: entityColor(entityColorMap, entry.id), stroke: "var(--background)", strokeWidth: 2 }, entry.id))) })] }) }), _jsx(TimeSeriesTableAlternative, { data: folded.data, xKey: xKey, xLabel: xLabel, series: folded.series, label: label, valueFormatter: valueFormatter })] }));
170
+ const yDomainMax = niceYDomainMax(folded.data, folded.series);
171
+ return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-bars", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(BarChart, { accessibilityLayer: true, title: label, data: folded.data, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8, interval: "equidistantPreserveStart", minTickGap: X_AXIS_MIN_TICK_GAP }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickCount: Y_AXIS_TICK_COUNT, ...(yDomainMax === undefined ? {} : { domain: [0, yDomainMax] }), tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, _jsx(BarStack, { stackId: "stacked", radius: [4, 4, 0, 0], children: folded.series.map((entry) => (_jsx(Bar, { dataKey: entry.id, isAnimationActive: false, maxBarSize: 24, fill: entityColor(entityColorMap, entry.id), stroke: "var(--background)", strokeWidth: 2 }, entry.id))) })] }) }), _jsx(TimeSeriesTableAlternative, { data: folded.data, xKey: xKey, xLabel: xLabel, series: folded.series, label: label, valueFormatter: valueFormatter })] }));
118
172
  }
119
173
  function TimeSeriesArea({ data, xKey, series, entityColorMap, label, xLabel = "Period", valueFormatter = defaultFormat, yAxisWidth, otherLabel = "Other", className, ...props }) {
120
174
  const folded = foldNeutralSeries(series, entityColorMap, data, otherLabel);
121
175
  const config = seriesChartConfig(folded.series, entityColorMap);
122
- return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-area", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(AreaChart, { accessibilityLayer: true, title: label, data: folded.data, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8 }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, folded.series.map((entry) => {
176
+ const yDomainMax = niceYDomainMax(folded.data, folded.series);
177
+ return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-area", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(AreaChart, { accessibilityLayer: true, title: label, data: folded.data, margin: { top: 5, right: 20, bottom: 5, left: 20 }, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8, interval: "equidistantPreserveStart", minTickGap: X_AXIS_MIN_TICK_GAP }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickCount: Y_AXIS_TICK_COUNT, ...(yDomainMax === undefined ? {} : { domain: [0, yDomainMax] }), tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, folded.series.map((entry) => {
123
178
  const color = entityColor(entityColorMap, entry.id);
124
- return (_jsx(Area, { type: "monotone", dataKey: entry.id, isAnimationActive: false, stackId: "stacked", stroke: color, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", fill: color, fillOpacity: 0.1,
179
+ return (_jsx(Area, { type: "monotone", dataKey: entry.id, isAnimationActive: false, stackId: "stacked", stroke: color, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", fill: color,
180
+ // DESIGN.md mark specs: an area fill reads as a light wash
181
+ // (roughly 10% opacity) under a full-strength line.
182
+ fillOpacity: 0.1,
125
183
  // Recharts' default activeDot ring is stroke #fff, which the
126
184
  // chart foundation remaps to transparent — an explicit surface
127
185
  // ring keeps the DESIGN.md 2px marker-ring spec on hover/focus.
@@ -89,7 +89,7 @@ function ChartTooltipContent({ active, payload, className, indicator = "dot", hi
89
89
  const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`;
90
90
  const itemConfig = getPayloadConfigFromPayload(config, item, key);
91
91
  const indicatorColor = color ?? item.payload?.fill ?? item.color;
92
- return (_jsx("div", { className: cn("flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center"), children: formatter && item?.value !== undefined && item.name ? (formatter(item.value, item.name, item, index, item.payload)) : (_jsxs(_Fragment, { children: [itemConfig?.icon ? (_jsx(itemConfig.icon, {})) : (!hideIndicator && (_jsx("div", { className: cn("shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)", {
92
+ return (_jsx("div", { className: cn("flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", indicator === "dot" && "items-center"), children: formatter && item?.value !== undefined && item.name ? (formatter(item.value, item.name, item, index, item.payload)) : (_jsxs(_Fragment, { children: [itemConfig?.icon ? (_jsx(itemConfig.icon, {})) : (!hideIndicator && (_jsx("div", { className: cn("shrink-0 rounded-xs border-(--color-border) bg-(--color-bg)", {
93
93
  "h-2.5 w-2.5": indicator === "dot",
94
94
  "w-1": indicator === "line",
95
95
  "w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
@@ -113,7 +113,7 @@ function ChartLegendContent({ className, hideIcon = false, payload, verticalAlig
113
113
  .map((item, index) => {
114
114
  const key = `${nameKey ?? item.dataKey ?? "value"}`;
115
115
  const itemConfig = getPayloadConfigFromPayload(config, item, key);
116
- return (_jsxs("div", { className: cn("flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"), children: [itemConfig?.icon && !hideIcon ? (_jsx(itemConfig.icon, {})) : (_jsx("div", { className: "h-2 w-2 shrink-0 rounded-[2px]", style: {
116
+ return (_jsxs("div", { className: cn("flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"), children: [itemConfig?.icon && !hideIcon ? (_jsx(itemConfig.icon, {})) : (_jsx("div", { className: "h-2 w-2 shrink-0 rounded-xs", style: {
117
117
  backgroundColor: item.color,
118
118
  } })), itemConfig?.label] }, index));
119
119
  }) }));
@@ -24,7 +24,7 @@ import { cn } from "../lib/utils.js";
24
24
  * dots -> bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]
25
25
  */
26
26
  function CodeEditorMockup({ className, ...props }) {
27
- return (_jsx("div", { "data-slot": "code-editor-mockup", className: cn("grid content-start overflow-hidden rounded-[var(--nc-rounded-md)] bg-primary text-primary-foreground", className), ...props }));
27
+ return (_jsx("div", { "data-slot": "code-editor-mockup", className: cn("grid content-start overflow-hidden rounded-md bg-primary text-primary-foreground", className), ...props }));
28
28
  }
29
29
  function CodeEditorMockupChrome({ className, children, ...props }) {
30
30
  return (_jsxs("div", { "data-slot": "code-editor-mockup-chrome", className: cn("flex items-center gap-2 border-b border-b-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)] px-6 py-3", className), ...props, children: [_jsxs("span", { "data-slot": "code-editor-mockup-dots", "aria-hidden": "true", className: "flex flex-none gap-2", children: [_jsx("span", { className: "size-[11px] rounded-full bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]" }), _jsx("span", { className: "size-[11px] rounded-full bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]" }), _jsx("span", { className: "size-[11px] rounded-full bg-[color-mix(in_srgb,var(--nc-line)_24%,var(--nc-canvas)_22%)]" })] }), children] }));
@@ -28,7 +28,7 @@ function NavBarLogo({ className, ...props }) {
28
28
  function NavBarLinks({ className, ...props }) {
29
29
  return (_jsx("div", { "data-slot": "nav-bar-links", className: cn("hidden items-center justify-center gap-1 text-sm text-muted-foreground lg:inline-flex",
30
30
  // each link reads as a flat pill with hover/focus affordance against the glass.
31
- "[&_a]:rounded-[var(--nc-rounded-sm)] [&_a]:px-3 [&_a]:py-2 [&_a]:text-inherit [&_a]:no-underline [&_a]:transition-colors", "[&_a:hover]:bg-accent [&_a:hover]:text-foreground", "[&_a[data-active]]:text-foreground", "[&_a:focus-visible]:outline [&_a:focus-visible]:outline-1 [&_a:focus-visible]:[outline-color:var(--ring)] [&_a:focus-visible]:outline-offset-2", className), ...props }));
31
+ "[&_a]:rounded-sm [&_a]:px-3 [&_a]:py-2 [&_a]:text-inherit [&_a]:no-underline [&_a]:transition-colors", "[&_a:hover]:bg-accent [&_a:hover]:text-foreground", "[&_a[data-active]]:text-foreground", "[&_a:focus-visible]:outline [&_a:focus-visible]:outline-1 [&_a:focus-visible]:[outline-color:var(--ring)] [&_a:focus-visible]:outline-offset-2", className), ...props }));
32
32
  }
33
33
  function NavBarCta({ className, ...props }) {
34
34
  return (_jsx("div", { "data-slot": "nav-bar-cta", className: cn("inline-flex items-center gap-3 justify-self-end", className), ...props }));
@@ -1,6 +1,6 @@
1
1
  import { Radio as RadioPrimitive } from "@base-ui/react/radio";
2
2
  import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
3
3
  declare function RadioGroup({ className, ...props }: RadioGroupPrimitive.Props): import("react").JSX.Element;
4
- declare function RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props): import("react").JSX.Element;
4
+ declare function RadioGroupItem({ children, className, ...props }: RadioPrimitive.Root.Props): import("react").JSX.Element;
5
5
  export { RadioGroup, RadioGroupItem };
6
6
  //# sourceMappingURL=radio-group.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../src/components/radio-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAI/E,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,CAAC,KAAK,+BAQrE;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,+BAkBzE;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../src/components/radio-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAI/E,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,CAAC,KAAK,+BAQrE;AAED,iBAAS,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,+BAoBnF;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC"}
@@ -5,7 +5,7 @@ import { cn } from "../lib/utils.js";
5
5
  function RadioGroup({ className, ...props }) {
6
6
  return (_jsx(RadioGroupPrimitive, { "data-slot": "radio-group", className: cn("grid w-full gap-2", className), ...props }));
7
7
  }
8
- function RadioGroupItem({ className, ...props }) {
9
- return (_jsx(RadioPrimitive.Root, { "data-slot": "radio-group-item", className: cn("group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:top-1/2 after:left-1/2 after:size-touch-target after:-translate-x-1/2 after:-translate-y-1/2 focus-visible:border-ring focus-visible:ring-[length:var(--ring-width-focus)] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[length:var(--ring-width-focus)] aria-invalid:ring-destructive aria-invalid:aria-checked:border-primary data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground [@media(hover:hover)_and_(pointer:fine)]:after:hidden", className), ...props, children: _jsx(RadioPrimitive.Indicator, { "data-slot": "radio-group-indicator", className: "flex size-4 items-center justify-center", children: _jsx("span", { className: "absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground" }) }) }));
8
+ function RadioGroupItem({ children, className, ...props }) {
9
+ return (_jsx(RadioPrimitive.Root, { "data-slot": "radio-group-item", className: cn("group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:top-1/2 after:left-1/2 after:size-touch-target after:-translate-x-1/2 after:-translate-y-1/2 focus-visible:border-ring focus-visible:ring-[length:var(--ring-width-focus)] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[length:var(--ring-width-focus)] aria-invalid:ring-destructive aria-invalid:aria-checked:border-primary data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground [@media(hover:hover)_and_(pointer:fine)]:after:hidden", className), ...props, children: children ?? (_jsx(RadioPrimitive.Indicator, { "data-slot": "radio-group-indicator", className: "flex size-4 items-center justify-center", children: _jsx("span", { className: "absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground" }) })) }));
10
10
  }
11
11
  export { RadioGroup, RadioGroupItem };
@@ -1,17 +1,24 @@
1
1
  import * as React from "react";
2
- import { ToggleGroup } from "./toggle-group";
2
+ import { RadioGroup } from "./radio-group";
3
3
  import { isThemeMode, themeModes, type ThemeMode } from "../lib/theme-mode";
4
4
  export { isThemeMode, themeModes };
5
5
  export type { ThemeMode };
6
6
  export type ThemeModeOptionLabels = Record<ThemeMode, string>;
7
- export type ThemeModeSwitcherProps = Omit<React.ComponentProps<typeof ToggleGroup>, "children" | "defaultValue" | "onValueChange" | "type" | "value"> & {
7
+ export type ThemeModeOption = {
8
+ Icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
9
+ label: string;
10
+ mode: ThemeMode;
11
+ selected: boolean;
12
+ };
13
+ export type ThemeModeSwitcherProps = Omit<React.ComponentProps<typeof RadioGroup>, "children" | "defaultValue" | "onValueChange" | "value"> & {
8
14
  "aria-label": string;
9
15
  compact?: boolean;
10
16
  itemClassName?: string;
11
17
  labels: ThemeModeOptionLabels;
12
18
  onValueChange: (value: ThemeMode) => void;
19
+ renderItem?: (option: ThemeModeOption) => React.ReactNode;
13
20
  value: ThemeMode;
14
21
  };
15
- declare function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact, disabled, itemClassName, labels, onValueChange, value, ...props }: ThemeModeSwitcherProps): React.JSX.Element;
22
+ declare function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact, disabled, itemClassName, labels, onValueChange, renderItem, value, ...props }: ThemeModeSwitcherProps): React.JSX.Element;
16
23
  export { ThemeModeSwitcher };
17
24
  //# sourceMappingURL=theme-mode-switcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme-mode-switcher.d.ts","sourceRoot":"","sources":["../../src/components/theme-mode-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAmB,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAE9D,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,EACxC,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,MAAM,GAAG,OAAO,CACjE,GAAG;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAQF,iBAAS,iBAAiB,CAAC,EACzB,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,OAAe,EACf,QAAQ,EACR,aAAa,EACb,MAAM,EACN,aAAa,EACb,KAAK,EACL,GAAG,KAAK,EACT,EAAE,sBAAsB,qBAmCxB;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"theme-mode-switcher.d.ts","sourceRoot":"","sources":["../../src/components/theme-mode-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAkB,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAE9D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,KAAK,CAAC,cAAc,CAAC,OAAO,UAAU,CAAC,EACvC,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,OAAO,CACxD,GAAG;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1D,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAQF,iBAAS,iBAAiB,CAAC,EACzB,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,OAAe,EACf,QAAQ,EACR,aAAa,EACb,MAAM,EACN,aAAa,EACb,UAAU,EACV,KAAK,EACL,GAAG,KAAK,EACT,EAAE,sBAAsB,qBAkDxB;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,7 +1,8 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
4
- import { ToggleGroup, ToggleGroupItem } from "./toggle-group.js";
4
+ import { RadioGroup, RadioGroupItem } from "./radio-group.js";
5
+ import { toggleVariants } from "./toggle.js";
5
6
  import { isThemeMode, themeModes } from "../lib/theme-mode.js";
6
7
  import { cn } from "../lib/utils.js";
7
8
  export { isThemeMode, themeModes };
@@ -10,16 +11,22 @@ const themeModeIcons = {
10
11
  dark: MoonIcon,
11
12
  system: MonitorIcon,
12
13
  };
13
- function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact = false, disabled, itemClassName, labels, onValueChange, value, ...props }) {
14
- return (_jsx(ToggleGroup, { "aria-label": ariaLabel, className: cn("max-w-full", className), disabled: disabled, onValueChange: (nextValue) => {
15
- const nextMode = nextValue[0];
14
+ function ThemeModeSwitcher({ "aria-label": ariaLabel, className, compact = false, disabled, itemClassName, labels, onValueChange, renderItem, value, ...props }) {
15
+ return (_jsx(RadioGroup, { "aria-label": ariaLabel, className: cn("max-w-full", className), disabled: disabled, onValueChange: (nextMode) => {
16
16
  if (isThemeMode(nextMode)) {
17
17
  onValueChange(nextMode);
18
18
  }
19
- }, value: [value], variant: "outline", ...props, children: themeModes.map((mode) => {
19
+ }, value: value, ...props, children: themeModes.map((mode) => {
20
20
  const Icon = themeModeIcons[mode];
21
21
  const label = labels[mode];
22
- return (_jsxs(ToggleGroupItem, { "aria-label": label, className: cn("min-w-0 gap-1.5 px-2.5", compact ? "h-8 text-xs" : "h-9", itemClassName), disabled: disabled, value: mode, children: [_jsx(Icon, { "aria-hidden": "true", "data-icon": true }), _jsx("span", { className: "min-w-0 truncate", children: label })] }, mode));
22
+ const selected = value === mode;
23
+ return (_jsx(RadioGroupItem, { "aria-label": label, className: cn(toggleVariants({ variant: "outline" }),
24
+ // The selected tile takes the muted interaction surface the
25
+ // toggle uses for its own on-state, so it takes that surface's
26
+ // foreground with it. Left on the radio primitive's on-primary
27
+ // foreground, the selected label reads white on near-white in
28
+ // light and black on black in dark.
29
+ "aspect-auto w-auto min-w-0 gap-1.5 px-2.5 data-checked:bg-muted data-checked:text-foreground", compact ? "h-8 text-xs" : "h-9", itemClassName), disabled: disabled, value: mode, children: renderItem ? (renderItem({ Icon, label, mode, selected })) : (_jsxs(_Fragment, { children: [_jsx(Icon, { "aria-hidden": "true", "data-icon": true }), _jsx("span", { className: "min-w-0 truncate", children: label })] })) }, mode));
23
30
  }) }));
24
31
  }
25
32
  export { ThemeModeSwitcher };
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
- import { type DemoSurfaceLabels, type DemoSurfaceScript } from "./demo-surface";
3
- declare function UseCaseBento({ kicker, title, body, proof, proofLabel, media, mediaClassName, demo, demoLabels, className, ...props }: React.ComponentProps<"article"> & {
2
+ declare function UseCaseBento({ kicker, title, body, proof, proofLabel, media, mediaClassName, demo, className, ...props }: React.ComponentProps<"article"> & {
4
3
  kicker: string;
5
4
  title: string;
6
5
  body: string;
@@ -8,8 +7,7 @@ declare function UseCaseBento({ kicker, title, body, proof, proofLabel, media, m
8
7
  proofLabel?: string;
9
8
  media: React.ReactNode;
10
9
  mediaClassName?: string;
11
- demo: DemoSurfaceScript;
12
- demoLabels?: Partial<DemoSurfaceLabels>;
10
+ demo: React.ReactNode;
13
11
  }): React.JSX.Element;
14
12
  export { UseCaseBento };
15
13
  //# sourceMappingURL=use-case-bento.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-case-bento.d.ts","sourceRoot":"","sources":["../../src/components/use-case-bento.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAe,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG7F,iBAAS,YAAY,CAAC,EACpB,MAAM,EACN,KAAK,EACL,IAAI,EACJ,KAAK,EACL,UAAmC,EACnC,KAAK,EACL,cAAc,EACd,IAAI,EACJ,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACzC,qBAqCA;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"use-case-bento.d.ts","sourceRoot":"","sources":["../../src/components/use-case-bento.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,iBAAS,YAAY,CAAC,EACpB,MAAM,EACN,KAAK,EACL,IAAI,EACJ,KAAK,EACL,UAAmC,EACnC,KAAK,EACL,cAAc,EACd,IAAI,EACJ,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;CACvB,qBAmCA;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -1,9 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
3
  import { Bento, BentoCopy, BentoDemo, BentoItem, BentoMedia } from "./bento.js";
4
- import { DemoSurface } from "./demo-surface.js";
5
4
  import { MediaMount } from "./media-mount.js";
6
- function UseCaseBento({ kicker, title, body, proof, proofLabel = "What the agent shows", media, mediaClassName, demo, demoLabels, className, ...props }) {
7
- return (_jsx("article", { "data-slot": "use-case-bento", className: className, ...props, children: _jsxs(Bento, { height: "primary", children: [_jsxs(BentoItem, { span: 3, children: [_jsx("div", { className: "nc-artifact-surface pointer-events-none absolute inset-0 border-0 p-0 opacity-60", "aria-hidden": "true" }), _jsxs(BentoCopy, { children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: kicker }), _jsx("h3", { className: "nc-type-title-md text-foreground", children: title }), _jsx("p", { className: "nc-type-body-sm text-[var(--nc-body)]", children: body }), _jsxs("div", { className: "grid gap-2 border-t border-border pt-4", children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: proofLabel }), _jsx("p", { className: "nc-type-body-sm text-foreground", children: proof })] })] })] }), _jsx(BentoItem, { span: 5, flush: true, stretch: true, className: "min-h-[var(--nc-h-bento-primary)]", children: _jsx(BentoMedia, { children: _jsx(MediaMount, { ratio: "auto", className: cn("!h-full min-h-[var(--nc-h-bento-primary)]", mediaClassName), children: media }) }) }), _jsx(BentoItem, { span: 4, surface: "soft", stretch: true, className: "min-h-0 p-[var(--nc-sm)]", children: _jsx(BentoDemo, { children: _jsx(DemoSurface, { labels: demoLabels, script: demo, title: title }) }) })] }) }));
5
+ function UseCaseBento({ kicker, title, body, proof, proofLabel = "What the agent shows", media, mediaClassName, demo, className, ...props }) {
6
+ return (_jsx("article", { "data-slot": "use-case-bento", className: className, ...props, children: _jsxs(Bento, { height: "primary", children: [_jsxs(BentoItem, { span: 3, children: [_jsx("div", { className: "nc-artifact-surface pointer-events-none absolute inset-0 border-0 p-0 opacity-60", "aria-hidden": "true" }), _jsxs(BentoCopy, { children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: kicker }), _jsx("h3", { className: "nc-type-title-md text-foreground", children: title }), _jsx("p", { className: "nc-type-body-sm text-[var(--nc-body)]", children: body }), _jsxs("div", { className: "grid gap-2 border-t border-border pt-4", children: [_jsx("p", { className: "nc-type-caption-mono text-muted-foreground uppercase", children: proofLabel }), _jsx("p", { className: "nc-type-body-sm text-foreground", children: proof })] })] })] }), _jsx(BentoItem, { span: 5, flush: true, stretch: true, className: "min-h-[var(--nc-h-bento-primary)]", children: _jsx(BentoMedia, { children: _jsx(MediaMount, { ratio: "auto", className: cn("!h-full min-h-[var(--nc-h-bento-primary)]", mediaClassName), children: media }) }) }), _jsx(BentoItem, { span: 4, surface: "soft", stretch: true, className: "min-h-0 p-[var(--nc-sm)]", children: _jsx(BentoDemo, { children: demo }) })] }) }));
8
7
  }
9
8
  export { UseCaseBento };