@fungi.computer/caps 0.0.0-stage → 0.0.1

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 (387) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1125 -2
  3. package/dist/blocks/app-bar.d.ts +43 -0
  4. package/dist/blocks/app-bar.js +244 -0
  5. package/dist/blocks/app-status-bar.d.ts +93 -0
  6. package/dist/blocks/app-status-bar.js +42 -0
  7. package/dist/blocks/async-state.d.ts +21 -0
  8. package/dist/blocks/async-state.js +8 -0
  9. package/dist/blocks/card-grid.d.ts +11 -0
  10. package/dist/blocks/card-grid.js +21 -0
  11. package/dist/blocks/command-menu.d.ts +26 -0
  12. package/dist/blocks/command-menu.js +70 -0
  13. package/dist/blocks/composer.d.ts +23 -0
  14. package/dist/blocks/composer.js +13 -0
  15. package/dist/blocks/empty-state.d.ts +59 -0
  16. package/dist/blocks/empty-state.js +35 -0
  17. package/dist/blocks/faq-chat.d.ts +62 -0
  18. package/dist/blocks/faq-chat.js +77 -0
  19. package/dist/blocks/game-share-card.d.ts +17 -0
  20. package/dist/blocks/game-share-card.js +9 -0
  21. package/dist/blocks/launcher-grid.d.ts +50 -0
  22. package/dist/blocks/launcher-grid.js +11 -0
  23. package/dist/blocks/listing-detail.d.ts +23 -0
  24. package/dist/blocks/listing-detail.js +12 -0
  25. package/dist/blocks/loading-state.d.ts +5 -0
  26. package/dist/blocks/loading-state.js +8 -0
  27. package/dist/blocks/mosaic.d.ts +29 -0
  28. package/dist/blocks/mosaic.js +19 -0
  29. package/dist/blocks/permission-grid.d.ts +45 -0
  30. package/dist/blocks/permission-grid.js +14 -0
  31. package/dist/blocks/pricing-card.d.ts +53 -0
  32. package/dist/blocks/pricing-card.js +12 -0
  33. package/dist/blocks/release-tag.d.ts +20 -0
  34. package/dist/blocks/release-tag.js +10 -0
  35. package/dist/blocks/resource-select.d.ts +22 -0
  36. package/dist/blocks/resource-select.js +16 -0
  37. package/dist/blocks/result-state.d.ts +15 -0
  38. package/dist/blocks/result-state.js +8 -0
  39. package/dist/blocks/section-card.d.ts +31 -0
  40. package/dist/blocks/section-card.js +7 -0
  41. package/dist/blocks/section-heading.d.ts +13 -0
  42. package/dist/blocks/section-heading.js +11 -0
  43. package/dist/blocks/spec-sheet.d.ts +125 -0
  44. package/dist/blocks/spec-sheet.js +47 -0
  45. package/dist/blocks/status-tray.d.ts +83 -0
  46. package/dist/blocks/status-tray.js +79 -0
  47. package/dist/blocks/upload-queue.d.ts +48 -0
  48. package/dist/blocks/upload-queue.js +24 -0
  49. package/dist/components/action-row.d.ts +16 -0
  50. package/dist/components/action-row.js +11 -0
  51. package/dist/components/activity-line.d.ts +33 -0
  52. package/dist/components/activity-line.js +69 -0
  53. package/dist/components/alert.d.ts +17 -0
  54. package/dist/components/alert.js +17 -0
  55. package/dist/components/badge.d.ts +19 -0
  56. package/dist/components/badge.js +24 -0
  57. package/dist/components/button.d.ts +55 -0
  58. package/dist/components/button.js +230 -0
  59. package/dist/components/card.d.ts +61 -0
  60. package/dist/components/card.js +48 -0
  61. package/dist/components/chat-bubble.d.ts +34 -0
  62. package/dist/components/chat-bubble.js +10 -0
  63. package/dist/components/checkbox-bead.d.ts +6 -0
  64. package/dist/components/checkbox-bead.js +67 -0
  65. package/dist/components/checkbox.d.ts +21 -0
  66. package/dist/components/checkbox.js +46 -0
  67. package/dist/components/code-input.d.ts +35 -0
  68. package/dist/components/code-input.js +126 -0
  69. package/dist/components/combobox.d.ts +86 -0
  70. package/dist/components/combobox.js +218 -0
  71. package/dist/components/confirm-action.d.ts +23 -0
  72. package/dist/components/confirm-action.js +64 -0
  73. package/dist/components/copy-field.d.ts +53 -0
  74. package/dist/components/copy-field.js +49 -0
  75. package/dist/components/count-badge.d.ts +15 -0
  76. package/dist/components/count-badge.js +9 -0
  77. package/dist/components/cover-pattern.d.ts +19 -0
  78. package/dist/components/cover-pattern.js +74 -0
  79. package/dist/components/data-list.d.ts +25 -0
  80. package/dist/components/data-list.js +16 -0
  81. package/dist/components/dialog.d.ts +39 -0
  82. package/dist/components/dialog.js +73 -0
  83. package/dist/components/diff-view.d.ts +14 -0
  84. package/dist/components/diff-view.js +13 -0
  85. package/dist/components/disclosure.d.ts +29 -0
  86. package/dist/components/disclosure.js +19 -0
  87. package/dist/components/dropdown-menu.d.ts +49 -0
  88. package/dist/components/dropdown-menu.js +98 -0
  89. package/dist/components/field-guide.d.ts +41 -0
  90. package/dist/components/field-guide.js +18 -0
  91. package/dist/components/field.d.ts +164 -0
  92. package/dist/components/field.js +228 -0
  93. package/dist/components/game-feedback.d.ts +84 -0
  94. package/dist/components/game-feedback.js +48 -0
  95. package/dist/components/game-hud.d.ts +126 -0
  96. package/dist/components/game-hud.js +136 -0
  97. package/dist/components/generation-frame.d.ts +36 -0
  98. package/dist/components/generation-frame.js +97 -0
  99. package/dist/components/gooey.d.ts +32 -0
  100. package/dist/components/gooey.js +25 -0
  101. package/dist/components/hold-button.d.ts +26 -0
  102. package/dist/components/hold-button.js +115 -0
  103. package/dist/components/icon-button.d.ts +24 -0
  104. package/dist/components/icon-button.js +18 -0
  105. package/dist/components/icon-checkbox.d.ts +20 -0
  106. package/dist/components/icon-checkbox.js +9 -0
  107. package/dist/components/icon-choice-mark.d.ts +6 -0
  108. package/dist/components/icon-choice-mark.js +5 -0
  109. package/dist/components/icon-lamp.d.ts +42 -0
  110. package/dist/components/icon-lamp.js +15 -0
  111. package/dist/components/icon-radio.d.ts +16 -0
  112. package/dist/components/icon-radio.js +9 -0
  113. package/dist/components/inline-code.d.ts +3 -0
  114. package/dist/components/inline-code.js +7 -0
  115. package/dist/components/input-group.d.ts +9 -0
  116. package/dist/components/input-group.js +15 -0
  117. package/dist/components/input.d.ts +15 -0
  118. package/dist/components/input.js +15 -0
  119. package/dist/components/item-grid.d.ts +110 -0
  120. package/dist/components/item-grid.js +136 -0
  121. package/dist/components/keycap.d.ts +80 -0
  122. package/dist/components/keycap.js +18 -0
  123. package/dist/components/label.d.ts +13 -0
  124. package/dist/components/label.js +7 -0
  125. package/dist/components/listbox.d.ts +50 -0
  126. package/dist/components/listbox.js +134 -0
  127. package/dist/components/loader-blobs.d.ts +5 -0
  128. package/dist/components/loader-blobs.js +128 -0
  129. package/dist/components/loader.d.ts +21 -0
  130. package/dist/components/loader.js +25 -0
  131. package/dist/components/markdown.d.ts +23 -0
  132. package/dist/components/markdown.js +70 -0
  133. package/dist/components/minimap-labels.d.ts +39 -0
  134. package/dist/components/minimap-labels.js +113 -0
  135. package/dist/components/monogram.d.ts +32 -0
  136. package/dist/components/monogram.js +24 -0
  137. package/dist/components/motion-visibility.d.ts +2 -0
  138. package/dist/components/motion-visibility.js +25 -0
  139. package/dist/components/navigation-rail.d.ts +11 -0
  140. package/dist/components/navigation-rail.js +55 -0
  141. package/dist/components/overlay-root.d.ts +16 -0
  142. package/dist/components/overlay-root.js +24 -0
  143. package/dist/components/pixel-number.d.ts +50 -0
  144. package/dist/components/pixel-number.js +113 -0
  145. package/dist/components/popover.d.ts +31 -0
  146. package/dist/components/popover.js +24 -0
  147. package/dist/components/presence.d.ts +59 -0
  148. package/dist/components/presence.js +232 -0
  149. package/dist/components/price-tag.d.ts +11 -0
  150. package/dist/components/price-tag.js +6 -0
  151. package/dist/components/progress.d.ts +25 -0
  152. package/dist/components/progress.js +24 -0
  153. package/dist/components/prose.d.ts +14 -0
  154. package/dist/components/prose.js +10 -0
  155. package/dist/components/quota-meter.d.ts +24 -0
  156. package/dist/components/quota-meter.js +11 -0
  157. package/dist/components/radio-bead.d.ts +4 -0
  158. package/dist/components/radio-bead.js +53 -0
  159. package/dist/components/radio-group.d.ts +54 -0
  160. package/dist/components/radio-group.js +64 -0
  161. package/dist/components/resize-handle.d.ts +23 -0
  162. package/dist/components/resize-handle.js +31 -0
  163. package/dist/components/rough-drawing.d.ts +42 -0
  164. package/dist/components/rough-drawing.js +231 -0
  165. package/dist/components/rough.d.ts +68 -0
  166. package/dist/components/rough.js +33 -0
  167. package/dist/components/scroll-area.d.ts +12 -0
  168. package/dist/components/scroll-area.js +96 -0
  169. package/dist/components/scroll-motion.d.ts +12 -0
  170. package/dist/components/scroll-motion.js +31 -0
  171. package/dist/components/scroll-to-bottom-blob-state.d.ts +40 -0
  172. package/dist/components/scroll-to-bottom-blob-state.js +109 -0
  173. package/dist/components/scroll-to-bottom-blob.d.ts +16 -0
  174. package/dist/components/scroll-to-bottom-blob.js +174 -0
  175. package/dist/components/select.d.ts +9 -0
  176. package/dist/components/select.js +12 -0
  177. package/dist/components/selectable.d.ts +13 -0
  178. package/dist/components/selectable.js +45 -0
  179. package/dist/components/send-action.d.ts +33 -0
  180. package/dist/components/send-action.js +96 -0
  181. package/dist/components/separator.d.ts +11 -0
  182. package/dist/components/separator.js +7 -0
  183. package/dist/components/skeleton.d.ts +5 -0
  184. package/dist/components/skeleton.js +7 -0
  185. package/dist/components/slider.d.ts +18 -0
  186. package/dist/components/slider.js +31 -0
  187. package/dist/components/stat.d.ts +17 -0
  188. package/dist/components/stat.js +7 -0
  189. package/dist/components/status-bead.d.ts +9 -0
  190. package/dist/components/status-bead.js +107 -0
  191. package/dist/components/status-mark.d.ts +12 -0
  192. package/dist/components/status-mark.js +177 -0
  193. package/dist/components/status.d.ts +38 -0
  194. package/dist/components/status.js +28 -0
  195. package/dist/components/store-card.d.ts +21 -0
  196. package/dist/components/store-card.js +10 -0
  197. package/dist/components/surface.d.ts +89 -0
  198. package/dist/components/surface.js +31 -0
  199. package/dist/components/switch-bead.d.ts +4 -0
  200. package/dist/components/switch-bead.js +62 -0
  201. package/dist/components/switch.d.ts +11 -0
  202. package/dist/components/switch.js +36 -0
  203. package/dist/components/tabs.d.ts +55 -0
  204. package/dist/components/tabs.js +81 -0
  205. package/dist/components/technonomicon.d.ts +192 -0
  206. package/dist/components/technonomicon.js +121 -0
  207. package/dist/components/textarea.d.ts +9 -0
  208. package/dist/components/textarea.js +11 -0
  209. package/dist/components/toaster.d.ts +4 -0
  210. package/dist/components/toaster.js +13 -0
  211. package/dist/components/tool-call-chip.d.ts +22 -0
  212. package/dist/components/tool-call-chip.js +100 -0
  213. package/dist/components/tooltip.d.ts +41 -0
  214. package/dist/components/tooltip.js +169 -0
  215. package/dist/components/trading-card.d.ts +60 -0
  216. package/dist/components/trading-card.js +13 -0
  217. package/dist/components/undo-action.d.ts +52 -0
  218. package/dist/components/undo-action.js +100 -0
  219. package/dist/components/undo-toast.d.ts +21 -0
  220. package/dist/components/undo-toast.js +58 -0
  221. package/dist/components/visually-hidden.d.ts +9 -0
  222. package/dist/components/visually-hidden.js +11 -0
  223. package/dist/components/window.d.ts +65 -0
  224. package/dist/components/window.js +31 -0
  225. package/dist/components/wizard.d.ts +17 -0
  226. package/dist/components/wizard.js +19 -0
  227. package/dist/enhance/cigarette-card.d.ts +8 -0
  228. package/dist/enhance/cigarette-card.js +33 -0
  229. package/dist/enhance/sketch.d.ts +16 -0
  230. package/dist/enhance/sketch.js +130 -0
  231. package/dist/form-error.d.ts +7 -0
  232. package/dist/form-error.js +14 -0
  233. package/dist/form-fields.d.ts +15 -0
  234. package/dist/form-fields.js +250 -0
  235. package/dist/form-schema.d.ts +166 -0
  236. package/dist/form-schema.js +398 -0
  237. package/dist/form.d.ts +30 -0
  238. package/dist/form.js +20 -0
  239. package/dist/lib/cn.d.ts +8 -0
  240. package/dist/lib/cn.js +12 -0
  241. package/dist/lib/format-money.d.ts +2 -0
  242. package/dist/lib/format-money.js +22 -0
  243. package/dist/lib/glide.d.ts +12 -0
  244. package/dist/lib/glide.js +143 -0
  245. package/dist/lib/ime.d.ts +3 -0
  246. package/dist/lib/ime.js +8 -0
  247. package/dist/lib/motion-spring.d.ts +27 -0
  248. package/dist/lib/motion-spring.js +36 -0
  249. package/dist/lib/motion.d.ts +51 -0
  250. package/dist/lib/motion.js +161 -0
  251. package/dist/lib/reorder-motion.d.ts +13 -0
  252. package/dist/lib/reorder-motion.js +201 -0
  253. package/dist/lib/seed-hash.d.ts +6 -0
  254. package/dist/lib/seed-hash.js +13 -0
  255. package/dist/lib/tanstack-highlight.d.ts +4 -0
  256. package/dist/lib/tanstack-highlight.js +41 -0
  257. package/dist/schema-form.d.ts +120 -0
  258. package/dist/schema-form.js +129 -0
  259. package/dist/styles.css +18814 -0
  260. package/docs/api/README.md +134 -0
  261. package/docs/api/blocks/app-bar.md +227 -0
  262. package/docs/api/blocks/app-status-bar.md +257 -0
  263. package/docs/api/blocks/async-state.md +53 -0
  264. package/docs/api/blocks/card-grid.md +31 -0
  265. package/docs/api/blocks/command-menu.md +89 -0
  266. package/docs/api/blocks/composer.md +40 -0
  267. package/docs/api/blocks/empty-state.md +97 -0
  268. package/docs/api/blocks/faq-chat.md +147 -0
  269. package/docs/api/blocks/game-share-card.md +40 -0
  270. package/docs/api/blocks/launcher-grid.md +86 -0
  271. package/docs/api/blocks/listing-detail.md +51 -0
  272. package/docs/api/blocks/loading-state.md +21 -0
  273. package/docs/api/blocks/mosaic.md +94 -0
  274. package/docs/api/blocks/permission-grid.md +79 -0
  275. package/docs/api/blocks/pricing-card.md +90 -0
  276. package/docs/api/blocks/release-tag.md +62 -0
  277. package/docs/api/blocks/resource-select.md +126 -0
  278. package/docs/api/blocks/result-state.md +42 -0
  279. package/docs/api/blocks/section-card.md +42 -0
  280. package/docs/api/blocks/section-heading.md +61 -0
  281. package/docs/api/blocks/spec-sheet.md +400 -0
  282. package/docs/api/blocks/status-tray.md +141 -0
  283. package/docs/api/blocks/upload-queue.md +110 -0
  284. package/docs/api/components/action-row.md +51 -0
  285. package/docs/api/components/activity-line.md +103 -0
  286. package/docs/api/components/alert.md +60 -0
  287. package/docs/api/components/badge.md +77 -0
  288. package/docs/api/components/button.md +94 -0
  289. package/docs/api/components/card.md +165 -0
  290. package/docs/api/components/chat-bubble.md +66 -0
  291. package/docs/api/components/checkbox-bead.md +20 -0
  292. package/docs/api/components/checkbox.md +42 -0
  293. package/docs/api/components/code-input.md +61 -0
  294. package/docs/api/components/combobox.md +303 -0
  295. package/docs/api/components/confirm-action.md +58 -0
  296. package/docs/api/components/copy-field.md +106 -0
  297. package/docs/api/components/count-badge.md +39 -0
  298. package/docs/api/components/cover-pattern.md +43 -0
  299. package/docs/api/components/data-list.md +80 -0
  300. package/docs/api/components/dialog.md +235 -0
  301. package/docs/api/components/diff-view.md +59 -0
  302. package/docs/api/components/disclosure.md +71 -0
  303. package/docs/api/components/dropdown-menu.md +269 -0
  304. package/docs/api/components/field-guide.md +174 -0
  305. package/docs/api/components/field.md +252 -0
  306. package/docs/api/components/game-feedback.md +157 -0
  307. package/docs/api/components/game-hud.md +359 -0
  308. package/docs/api/components/generation-frame.md +59 -0
  309. package/docs/api/components/hold-button.md +44 -0
  310. package/docs/api/components/icon-button.md +56 -0
  311. package/docs/api/components/icon-checkbox.md +42 -0
  312. package/docs/api/components/icon-choice-mark.md +31 -0
  313. package/docs/api/components/icon-lamp.md +92 -0
  314. package/docs/api/components/icon-radio.md +42 -0
  315. package/docs/api/components/inline-code.md +21 -0
  316. package/docs/api/components/input-group.md +53 -0
  317. package/docs/api/components/input.md +54 -0
  318. package/docs/api/components/item-grid.md +262 -0
  319. package/docs/api/components/keycap.md +102 -0
  320. package/docs/api/components/label.md +40 -0
  321. package/docs/api/components/listbox.md +131 -0
  322. package/docs/api/components/loader-blobs.md +9 -0
  323. package/docs/api/components/loader.md +51 -0
  324. package/docs/api/components/markdown.md +91 -0
  325. package/docs/api/components/minimap-labels.md +84 -0
  326. package/docs/api/components/monogram.md +96 -0
  327. package/docs/api/components/motion-visibility.md +9 -0
  328. package/docs/api/components/navigation-rail.md +37 -0
  329. package/docs/api/components/overlay-root.md +92 -0
  330. package/docs/api/components/pixel-number.md +120 -0
  331. package/docs/api/components/popover.md +80 -0
  332. package/docs/api/components/presence.md +106 -0
  333. package/docs/api/components/price-tag.md +48 -0
  334. package/docs/api/components/progress.md +90 -0
  335. package/docs/api/components/prose.md +48 -0
  336. package/docs/api/components/quota-meter.md +47 -0
  337. package/docs/api/components/radio-bead.md +9 -0
  338. package/docs/api/components/radio-group.md +126 -0
  339. package/docs/api/components/resize-handle.md +46 -0
  340. package/docs/api/components/rough-drawing.md +122 -0
  341. package/docs/api/components/rough.md +66 -0
  342. package/docs/api/components/scroll-area.md +22 -0
  343. package/docs/api/components/scroll-motion.md +9 -0
  344. package/docs/api/components/scroll-to-bottom-blob-state.md +162 -0
  345. package/docs/api/components/scroll-to-bottom-blob.md +73 -0
  346. package/docs/api/components/select.md +39 -0
  347. package/docs/api/components/send-action.md +58 -0
  348. package/docs/api/components/separator.md +38 -0
  349. package/docs/api/components/skeleton.md +31 -0
  350. package/docs/api/components/slider.md +70 -0
  351. package/docs/api/components/stat.md +42 -0
  352. package/docs/api/components/status-bead.md +19 -0
  353. package/docs/api/components/status-mark.md +19 -0
  354. package/docs/api/components/status.md +105 -0
  355. package/docs/api/components/store-card.md +53 -0
  356. package/docs/api/components/surface.md +161 -0
  357. package/docs/api/components/switch-bead.md +9 -0
  358. package/docs/api/components/switch.md +40 -0
  359. package/docs/api/components/tabs.md +138 -0
  360. package/docs/api/components/technonomicon.md +773 -0
  361. package/docs/api/components/textarea.md +40 -0
  362. package/docs/api/components/toaster.md +29 -0
  363. package/docs/api/components/tool-call-chip.md +68 -0
  364. package/docs/api/components/tooltip.md +113 -0
  365. package/docs/api/components/trading-card.md +95 -0
  366. package/docs/api/components/undo-action.md +117 -0
  367. package/docs/api/components/undo-toast.md +49 -0
  368. package/docs/api/components/visually-hidden.md +37 -0
  369. package/docs/api/components/window.md +291 -0
  370. package/docs/api/components/wizard.md +65 -0
  371. package/docs/api/enhance/cigarette-card.md +52 -0
  372. package/docs/api/enhance/sketch.md +42 -0
  373. package/docs/api/form.md +1623 -0
  374. package/docs/api/lib/cn.md +46 -0
  375. package/docs/api/lib/format-money.md +30 -0
  376. package/docs/api/lib/glide.md +36 -0
  377. package/docs/api/lib/ime.md +29 -0
  378. package/docs/api/lib/motion-spring.md +91 -0
  379. package/docs/api/lib/motion.md +212 -0
  380. package/docs/api/lib/reorder-motion.md +46 -0
  381. package/docs/api/lib/seed-hash.md +31 -0
  382. package/docs/api/lib/tanstack-highlight.md +40 -0
  383. package/package.json +597 -3
  384. package/src/app-status-bar.css +158 -0
  385. package/src/fonts.css +1 -0
  386. package/src/status-tray.css +282 -0
  387. package/src/styles.css +10177 -0
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ChevronRight } from "lucide-react";
3
+ import { useEffect, useId, useLayoutEffect, useState, } from "react";
4
+ import { cn } from "../lib/cn.js";
5
+ import { Loader } from "./loader.js";
6
+ import { Collapse, Swap } from "./presence.js";
7
+ import { Status } from "./status.js";
8
+ /** Short elapsed time: `0.4s`, `4.2s`, `42s`, `3m 05s`. */
9
+ export function formatElapsed(milliseconds) {
10
+ const ms = Math.max(0, milliseconds);
11
+ if (ms < 10_000)
12
+ return `${(ms / 1_000).toFixed(1)}s`;
13
+ if (ms < 60_000)
14
+ return `${String(Math.floor(ms / 1_000))}s`;
15
+ const minutes = Math.floor(ms / 60_000);
16
+ const seconds = Math.floor((ms % 60_000) / 1_000);
17
+ return `${String(minutes)}m ${String(seconds).padStart(2, "0")}s`;
18
+ }
19
+ /**
20
+ * A clock that ticks while `running` and holds still otherwise. Times are
21
+ * epoch milliseconds (`Date.now()`), owned by the caller.
22
+ */
23
+ export function useElapsed(startedAt, finishedAt, running) {
24
+ const [now, setNow] = useState(() => Date.now());
25
+ useEffect(() => {
26
+ if (!running)
27
+ return;
28
+ setNow(Date.now());
29
+ const tick = setInterval(() => {
30
+ setNow(Date.now());
31
+ }, 100);
32
+ return () => {
33
+ clearInterval(tick);
34
+ };
35
+ }, [running]);
36
+ return (finishedAt ?? now) - startedAt;
37
+ }
38
+ /** A finished mark that closes its arc and draws itself once it appears. */
39
+ function SettledMark({ outcome }) {
40
+ const [drawn, setDrawn] = useState(false);
41
+ useLayoutEffect(() => {
42
+ setDrawn(true);
43
+ }, []);
44
+ return (_jsx(Status, { glyph: drawn ? outcome : "arc", progress: 1, size: "compact", tone: outcome === "check" ? "neutral" : "error" }));
45
+ }
46
+ /**
47
+ * One line of agent activity. While running it says what is happening with
48
+ * a live clock and shows its trace; when done it settles into "Thought for
49
+ * 4.2s" and folds the trace away, one click from reopening.
50
+ */
51
+ export function ActivityLine({ state, startedAt, finishedAt, label, doneLabel, failedLabel = "Stopped after", children, className, }) {
52
+ const running = state === "running";
53
+ const elapsed = useElapsed(startedAt, finishedAt, running);
54
+ // Open while running; fold when it settles, unless the reader chose.
55
+ const [chosen, setChosen] = useState(null);
56
+ const [settledState, setSettledState] = useState(state);
57
+ if (settledState !== state) {
58
+ setSettledState(state);
59
+ setChosen(null);
60
+ }
61
+ const open = chosen ?? running;
62
+ const panel = useId();
63
+ const summary = running
64
+ ? `${label}…`
65
+ : `${state === "done" ? doneLabel : failedLabel} ${formatElapsed(elapsed)}`;
66
+ return (_jsxs("div", { className: cn("caps-disclosure caps-disclosure-row caps-activity-line", state === "failed" && "caps-disclosure-error", className), "data-open": open ? "" : undefined, "data-state": state, children: [_jsxs("button", { type: "button", className: "caps-disclosure-trigger", "aria-expanded": open, "aria-controls": children === undefined ? undefined : panel, onClick: () => {
67
+ setChosen(!open);
68
+ }, children: [_jsx("span", { className: "caps-disclosure-leading caps-activity-line-leading", children: _jsx(Swap, { swapKey: state, children: running ? (_jsx(Loader, { decorative: true, size: "sm", variant: "line" })) : (_jsx(SettledMark, { outcome: state === "done" ? "check" : "cross" })) }) }), _jsx("span", { className: "caps-disclosure-summary", children: _jsx(Swap, { swapKey: running ? "running" : "settled", children: summary }) }), running ? (_jsx("span", { className: "caps-disclosure-trailing", "aria-hidden": "true", children: formatElapsed(elapsed) })) : null, children === undefined ? null : (_jsx(ChevronRight, { "aria-hidden": "true", className: "caps-disclosure-chevron", size: 12 }))] }), children === undefined ? null : (_jsx(Collapse, { open: open, id: panel, children: _jsx("div", { className: "caps-disclosure-panel", children: children }) }))] }));
69
+ }
@@ -0,0 +1,17 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /** Supported AlertTone values. */
3
+ export type AlertTone = "neutral" | "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error";
4
+ /** Props accepted by Alert. */
5
+ export type AlertProps = {
6
+ action?: ReactNode;
7
+ description?: ReactNode;
8
+ title?: ReactNode;
9
+ tone?: AlertTone;
10
+ } & Omit<HTMLAttributes<HTMLDivElement>, "title">;
11
+ /** A caller-labelled alert presentation. */
12
+ export declare const Alert: import("react").ForwardRefExoticComponent<{
13
+ action?: ReactNode;
14
+ description?: ReactNode;
15
+ title?: ReactNode;
16
+ tone?: AlertTone;
17
+ } & Omit<HTMLAttributes<HTMLDivElement>, "title"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn } from "../lib/cn.js";
4
+ const alertToneClasses = {
5
+ neutral: "alert-neutral",
6
+ primary: "alert-primary",
7
+ secondary: "alert-secondary",
8
+ accent: "alert-accent",
9
+ success: "alert-success",
10
+ info: "alert-info",
11
+ warning: "alert-warning",
12
+ error: "alert-error",
13
+ };
14
+ /** A caller-labelled alert presentation. */
15
+ export const Alert = forwardRef(function Alert({ action, children, className, description, title, tone = "neutral", ...props }, ref) {
16
+ return (_jsxs("div", { ...props, className: cn("alert caps-alert", alertToneClasses[tone], className), "data-tone": tone, role: props.role ?? "alert", ref: ref, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [title ? _jsx("h3", { className: "font-semibold", children: title }) : null, description ? _jsx("p", { className: "text-sm", children: description }) : null, children] }), action ? _jsx("div", { className: "shrink-0", children: action }) : null] }));
17
+ });
@@ -0,0 +1,19 @@
1
+ import { type HTMLAttributes } from "react";
2
+ /** Supported BadgeTone values. */
3
+ export type BadgeTone = "neutral" | "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error";
4
+ /** Supported BadgeSize values. */
5
+ export type BadgeSize = "sm" | "default" | "lg";
6
+ /** `quiet` is a soft tint with no outline, for labels that sit beside keys. */
7
+ export type BadgeVariant = "solid" | "quiet";
8
+ /** Props accepted by Badge. */
9
+ export type BadgeProps = {
10
+ size?: BadgeSize;
11
+ variant?: BadgeVariant;
12
+ tone?: BadgeTone;
13
+ } & HTMLAttributes<HTMLSpanElement>;
14
+ /** A compact status or category label. */
15
+ export declare const Badge: import("react").ForwardRefExoticComponent<{
16
+ size?: BadgeSize;
17
+ variant?: BadgeVariant;
18
+ tone?: BadgeTone;
19
+ } & HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn, cva } from "../lib/cn.js";
4
+ const badgeVariants = cva("badge caps-badge", {
5
+ variants: {
6
+ tone: {
7
+ neutral: "badge-neutral",
8
+ primary: "badge-primary",
9
+ secondary: "badge-secondary",
10
+ accent: "badge-accent",
11
+ success: "badge-success",
12
+ info: "badge-info",
13
+ warning: "badge-warning",
14
+ error: "badge-error",
15
+ },
16
+ size: { sm: "badge-sm", default: "badge-md", lg: "badge-lg" },
17
+ variant: { solid: "", quiet: "caps-badge-quiet" },
18
+ },
19
+ defaultVariants: { tone: "neutral", size: "default" },
20
+ });
21
+ /** A compact status or category label. */
22
+ export const Badge = forwardRef(function Badge({ className, size, tone, variant, ...props }, ref) {
23
+ return (_jsx("span", { ...props, className: cn(badgeVariants({ size, tone, variant }), className), ref: ref }));
24
+ });
@@ -0,0 +1,55 @@
1
+ import { type ButtonHTMLAttributes, type ElementRef, type ReactNode } from "react";
2
+ /** Supported Button visual variants. */
3
+ export type ButtonVariant = "primary" | "secondary" | "accent" | "destructive" | "outline" | "ghost"
4
+ /** Quiet text that turns to the error colour on hover or focus, e.g. Stop. */
5
+ | "ghost-destructive" | "link";
6
+ /** Supported ButtonSize values. */
7
+ export type ButtonSize = "xs" | "sm" | "default" | "lg" | "icon" | "menubar";
8
+ /** The outcome of a Button's last action. */
9
+ export type ButtonResult = "done" | "failed";
10
+ /** Props accepted by Button. */
11
+ export type ButtonProps = {
12
+ asChild?: boolean;
13
+ loading?: boolean;
14
+ /**
15
+ * The outcome of the last action. Becoming `done` plays a short beat: a
16
+ * check (and `resultLabel`) springs in, holds, then settles back to the
17
+ * label. Becoming `failed` shakes the label by the theme's
18
+ * `--stipe-motion-shake`. Say what failed elsewhere, next to the action.
19
+ */
20
+ result?: ButtonResult | undefined;
21
+ /** What the done beat says, such as "Installed". The button keeps the wider of its two labels, so nothing shifts. */
22
+ resultLabel?: ReactNode;
23
+ /**
24
+ * Called when the done beat has held long enough to read, just before it
25
+ * would settle back to the label. Replace the button here to hand off to
26
+ * what comes next (an "Installed" mark, an "Open" action).
27
+ */
28
+ onResultEnd?: (() => void) | undefined;
29
+ size?: ButtonSize;
30
+ variant?: ButtonVariant;
31
+ } & ButtonHTMLAttributes<HTMLButtonElement>;
32
+ /** A reusable button with caller-controlled native behavior and intrinsic loading presentation. */
33
+ export declare const Button: import("react").ForwardRefExoticComponent<{
34
+ asChild?: boolean;
35
+ loading?: boolean;
36
+ /**
37
+ * The outcome of the last action. Becoming `done` plays a short beat: a
38
+ * check (and `resultLabel`) springs in, holds, then settles back to the
39
+ * label. Becoming `failed` shakes the label by the theme's
40
+ * `--stipe-motion-shake`. Say what failed elsewhere, next to the action.
41
+ */
42
+ result?: ButtonResult | undefined;
43
+ /** What the done beat says, such as "Installed". The button keeps the wider of its two labels, so nothing shifts. */
44
+ resultLabel?: ReactNode;
45
+ /**
46
+ * Called when the done beat has held long enough to read, just before it
47
+ * would settle back to the label. Replace the button here to hand off to
48
+ * what comes next (an "Installed" mark, an "Open" action).
49
+ */
50
+ onResultEnd?: (() => void) | undefined;
51
+ size?: ButtonSize;
52
+ variant?: ButtonVariant;
53
+ } & ButtonHTMLAttributes<HTMLButtonElement> & import("react").RefAttributes<HTMLButtonElement>>;
54
+ /** The native element type used by Button. */
55
+ export type ButtonElement = ElementRef<"button">;
@@ -0,0 +1,230 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState, } from "react";
4
+ import { cn, cva } from "../lib/cn.js";
5
+ import { canAnimate, motionEasing, readMotion, useReducedMotion, } from "../lib/motion.js";
6
+ import { Loader } from "./loader.js";
7
+ /** Outline and link controls keep a neutral disabled plate behind a hairline. */
8
+ const disabledPlate = "disabled:bg-base-200 disabled:text-base-content disabled:outline-1 disabled:outline-solid disabled:outline-base-content/25 aria-disabled:bg-base-200 aria-disabled:text-base-content aria-disabled:outline-1 aria-disabled:outline-solid aria-disabled:outline-base-content/25";
9
+ const buttonVariants = cva("btn caps-button disabled:pointer-events-none", {
10
+ variants: {
11
+ variant: {
12
+ primary: "btn-primary caps-button-filled",
13
+ secondary: "btn-secondary caps-button-filled",
14
+ accent: "btn-accent caps-button-filled",
15
+ destructive: "btn-error caps-button-filled",
16
+ outline: `btn-outline ${disabledPlate}`,
17
+ // A faceless ghost stays faceless when disabled: Caps dims its ink.
18
+ ghost: "btn-ghost",
19
+ "ghost-destructive": "btn-ghost caps-button-ghost-destructive",
20
+ link: `btn-link ${disabledPlate}`,
21
+ },
22
+ size: {
23
+ xs: "btn-xs",
24
+ sm: "btn-sm",
25
+ default: "btn-md",
26
+ lg: "btn-lg",
27
+ icon: "btn-square btn-md",
28
+ menubar: "caps-button-menubar",
29
+ },
30
+ },
31
+ defaultVariants: { variant: "primary", size: "default" },
32
+ });
33
+ /** A reusable button with caller-controlled native behavior and intrinsic loading presentation. */
34
+ export const Button = forwardRef(function Button({ asChild = false, children, className, disabled, loading = false, result, resultLabel, onResultEnd, size = "default", variant = "primary", ...props }, ref) {
35
+ const classes = cn(buttonVariants({ size, variant }), className);
36
+ // A result present when the button first mounts is history, not news.
37
+ const mountedResult = useRef(result).current;
38
+ const node = useRef(null);
39
+ useImperativeHandle(ref, () => node.current);
40
+ // Text labels compare by value; element labels re-measure each render.
41
+ useWidthTween(node, [loading, result, children]);
42
+ if (asChild) {
43
+ return (_jsx(Slot, { ...props, "aria-busy": loading ? true : props["aria-busy"], "aria-disabled": disabled === true || loading ? true : undefined, className: classes, ref: node, children: children }));
44
+ }
45
+ return (_jsx("button", { ...props, "aria-busy": loading ? true : props["aria-busy"], className: classes, disabled: disabled === true || loading, ref: node, type: props.type ?? "button", children: result === undefined && resultLabel === undefined ? (_jsxs(_Fragment, { children: [loading ? (_jsx(Loader, { className: "size-3", decorative: true, size: "sm" })) : null, children] })) : (_jsx(ResultFaces, { label: resultLabel, loading: loading, onResultEnd: onResultEnd, result: result, settled: mountedResult, children: children })) }));
46
+ });
47
+ /**
48
+ * When a button's label changes (loading, a result, new text) its width eases
49
+ * to the new size instead of jumping, so neighbours never lurch.
50
+ */
51
+ function useWidthTween(node, label) {
52
+ const width = useRef(null);
53
+ const tween = useRef(null);
54
+ useLayoutEffect(() => {
55
+ const element = node.current;
56
+ if (!element)
57
+ return;
58
+ const running = tween.current;
59
+ const from = running
60
+ ? element.getBoundingClientRect().width
61
+ : width.current;
62
+ running?.cancel();
63
+ tween.current = null;
64
+ const to = element.getBoundingClientRect().width;
65
+ width.current = to;
66
+ if (from === null || Math.abs(from - to) < 1 || !canAnimate(element))
67
+ return;
68
+ const motion = readMotion(element);
69
+ if (motion.reduced)
70
+ return;
71
+ const animation = element.animate([{ width: `${String(from)}px` }, { width: `${String(to)}px` }], { duration: motion.normal, easing: motionEasing(motion, motion.ease) });
72
+ tween.current = animation;
73
+ // Content wider than the moving edge is clipped, never spilled or wrapped.
74
+ element.style.overflow = "clip";
75
+ element.style.whiteSpace = "nowrap";
76
+ const done = () => {
77
+ if (tween.current !== animation)
78
+ return;
79
+ tween.current = null;
80
+ element.style.removeProperty("overflow");
81
+ element.style.removeProperty("white-space");
82
+ };
83
+ animation.onfinish = done;
84
+ animation.oncancel = done;
85
+ }, [node, ...label]);
86
+ }
87
+ /** How long the done beat holds before settling: long enough to read. */
88
+ const resultHoldMs = 1100;
89
+ function pop(faces, motion) {
90
+ // One overshoot sized by the theme's bounce; a calm theme just nods.
91
+ const liveliness = motion.bounce / 0.3;
92
+ const lift = 1 + 0.05 * Math.min(1.4, 0.4 + liveliness);
93
+ const dip = 1 - 0.02 * Math.min(1.4, liveliness);
94
+ return faces.animate([
95
+ { transform: "scale(1)" },
96
+ { transform: `scale(${String(lift)})`, offset: 0.35 },
97
+ { transform: `scale(${String(dip)})`, offset: 0.7 },
98
+ { transform: "scale(1)" },
99
+ ], {
100
+ duration: motion.springDuration,
101
+ easing: motionEasing(motion, "ease-out"),
102
+ });
103
+ }
104
+ function shake(faces, motion) {
105
+ const x = motion.shake;
106
+ return faces.animate([
107
+ { transform: "none" },
108
+ { transform: `translateX(${String(-x)}px)` },
109
+ { transform: `translateX(${String(x)}px)` },
110
+ { transform: `translateX(${String(-x * 0.6)}px)` },
111
+ { transform: `translateX(${String(x * 0.3)}px)` },
112
+ { transform: "none" },
113
+ ], { duration: motion.slow * 1.3, easing: motionEasing(motion, "linear") });
114
+ }
115
+ function swapFaces(leaving, arriving, motion) {
116
+ const travel = motion.distance + 2;
117
+ const blur = `blur(${String(motion.blur)}px)`;
118
+ return [
119
+ leaving.animate([
120
+ { opacity: 1, transform: "none", filter: "blur(0px)" },
121
+ {
122
+ opacity: 0,
123
+ transform: `translateY(${String(-travel)}px)`,
124
+ filter: blur,
125
+ },
126
+ ], {
127
+ duration: motion.fast,
128
+ // A label rolls away at once; an ease-in would linger on stale text.
129
+ easing: motionEasing(motion, motion.ease),
130
+ }),
131
+ arriving.animate([
132
+ {
133
+ opacity: 0,
134
+ transform: `translateY(${String(travel)}px)`,
135
+ filter: blur,
136
+ },
137
+ { opacity: 1, transform: "none", filter: "blur(0px)" },
138
+ ], {
139
+ duration: motion.normal,
140
+ easing: motionEasing(motion, motion.ease),
141
+ fill: "backwards",
142
+ }),
143
+ ];
144
+ }
145
+ /** @internal The label and result faces of a Button with a result beat. */
146
+ function ResultFaces({ children, label, loading, onResultEnd, result, settled, }) {
147
+ const faces = useRef(null);
148
+ const reduced = useReducedMotion();
149
+ const [showing, setShowing] = useState(false);
150
+ // The result face exists only for its beat, so it never lingers as hidden
151
+ // text in the button.
152
+ const [resultMounted, setResultMounted] = useState(false);
153
+ if (showing && !resultMounted)
154
+ setResultMounted(true);
155
+ const previous = useRef(settled);
156
+ const ended = useRef(onResultEnd);
157
+ useEffect(() => {
158
+ ended.current = onResultEnd;
159
+ }, [onResultEnd]);
160
+ // Before paint, so the label never flashes ahead of the beat.
161
+ useLayoutEffect(() => {
162
+ const before = previous.current;
163
+ previous.current = result;
164
+ if (result === before)
165
+ return;
166
+ if (result === "done") {
167
+ setShowing(true);
168
+ const settle = setTimeout(() => {
169
+ // A caller that hands off keeps the result face until it replaces
170
+ // the button; otherwise the beat settles back to the label.
171
+ if (ended.current)
172
+ ended.current();
173
+ else
174
+ setShowing(false);
175
+ }, resultHoldMs);
176
+ return () => {
177
+ clearTimeout(settle);
178
+ };
179
+ }
180
+ setShowing(false);
181
+ const element = faces.current;
182
+ if (result !== "failed" || !element || !canAnimate(element))
183
+ return;
184
+ const motion = readMotion(element);
185
+ if (motion.shake <= 0)
186
+ return;
187
+ const refusal = shake(element, motion);
188
+ return () => {
189
+ refusal.cancel();
190
+ };
191
+ }, [result, reduced]);
192
+ const shown = useRef(showing);
193
+ useLayoutEffect(() => {
194
+ const element = faces.current;
195
+ if (!element || shown.current === showing)
196
+ return;
197
+ shown.current = showing;
198
+ const labelFace = element.querySelector('[data-face="label"]');
199
+ const resultFace = element.querySelector('[data-face="result"]');
200
+ if (!labelFace || !resultFace || !canAnimate(element)) {
201
+ if (!showing)
202
+ setResultMounted(false);
203
+ return;
204
+ }
205
+ const motion = readMotion(element);
206
+ const animations = showing
207
+ ? swapFaces(labelFace, resultFace, motion)
208
+ : swapFaces(resultFace, labelFace, motion);
209
+ if (!showing)
210
+ animations[0]?.addEventListener("finish", () => {
211
+ setResultMounted(false);
212
+ });
213
+ if (showing && !motion.reduced) {
214
+ animations.push(pop(element.closest("button") ?? element, motion));
215
+ const tick = resultFace.querySelector("path");
216
+ if (tick)
217
+ animations.push(tick.animate([{ strokeDashoffset: 1 }, { strokeDashoffset: 0 }], {
218
+ duration: motion.normal * 1.4,
219
+ delay: motion.fast / 2,
220
+ easing: motionEasing(motion, motion.ease),
221
+ fill: "backwards",
222
+ }));
223
+ }
224
+ return () => {
225
+ for (const animation of animations)
226
+ animation.cancel();
227
+ };
228
+ }, [showing, reduced]);
229
+ return (_jsxs("span", { ref: faces, className: "caps-button-faces", "data-showing": showing ? "result" : "label", children: [_jsxs("span", { className: "caps-button-face", "data-face": "label", "aria-hidden": showing ? true : undefined, children: [loading || showing ? (_jsx(Loader, { className: "size-3", decorative: true, size: "sm" })) : null, children] }), resultMounted ? (_jsxs("span", { className: "caps-button-face", "data-face": "result", "aria-hidden": showing ? undefined : true, children: [_jsx("svg", { className: "caps-button-check", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "M4.5 12.5 9.5 17.5 19.5 6.5", pathLength: 1 }) }), label === undefined ? children : label] })) : null] }));
230
+ }
@@ -0,0 +1,61 @@
1
+ import { type HTMLAttributes } from "react";
2
+ /** Props accepted by Card. */
3
+ export type CardProps = {
4
+ variant?: "surface" | "outline" | "interactive" | "game" | "fit";
5
+ /** Emphasize a featured item without changing its interaction. */
6
+ featured?: boolean;
7
+ /** Present the absence of content within the same card shell. */
8
+ state?: "empty";
9
+ /** Reduce card section padding when several related details share a page. */
10
+ density?: "regular" | "compact";
11
+ } & HTMLAttributes<HTMLDivElement>;
12
+ /** Props accepted by CenteredCard. */
13
+ export type CenteredCardProps = CardProps & {
14
+ width?: "default" | "wide";
15
+ };
16
+ /** A presentational card shell. */
17
+ export declare const Card: import("react").ForwardRefExoticComponent<{
18
+ variant?: "surface" | "outline" | "interactive" | "game" | "fit";
19
+ /** Emphasize a featured item without changing its interaction. */
20
+ featured?: boolean;
21
+ /** Present the absence of content within the same card shell. */
22
+ state?: "empty";
23
+ /** Reduce card section padding when several related details share a page. */
24
+ density?: "regular" | "compact";
25
+ } & HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
26
+ /** Center one primary card in a welcoming, viewport-filling page stage. */
27
+ export declare const CenteredCard: import("react").ForwardRefExoticComponent<{
28
+ variant?: "surface" | "outline" | "interactive" | "game" | "fit";
29
+ /** Emphasize a featured item without changing its interaction. */
30
+ featured?: boolean;
31
+ /** Present the absence of content within the same card shell. */
32
+ state?: "empty";
33
+ /** Reduce card section padding when several related details share a page. */
34
+ density?: "regular" | "compact";
35
+ } & HTMLAttributes<HTMLDivElement> & {
36
+ width?: "default" | "wide";
37
+ } & import("react").RefAttributes<HTMLDivElement>>;
38
+ /** A card header layout with optional centered alignment. */
39
+ export type CardHeaderProps = {
40
+ alignment?: "start" | "center";
41
+ } & HTMLAttributes<HTMLDivElement>;
42
+ /** Render a Caps card header with the requested alignment. */
43
+ export declare const CardHeader: import("react").ForwardRefExoticComponent<{
44
+ alignment?: "start" | "center";
45
+ } & HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
46
+ /** Props accepted by CardTitle. */
47
+ export type CardTitleProps = HTMLAttributes<HTMLHeadingElement> & {
48
+ /** Heading level; the host keeps its document outline. Defaults to 3. */
49
+ level?: 2 | 3;
50
+ };
51
+ /** A card title element. */
52
+ export declare const CardTitle: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLHeadingElement> & {
53
+ /** Heading level; the host keeps its document outline. Defaults to 3. */
54
+ level?: 2 | 3;
55
+ } & import("react").RefAttributes<HTMLHeadingElement>>;
56
+ /** A card supporting-description element. */
57
+ export declare const CardDescription: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & import("react").RefAttributes<HTMLParagraphElement>>;
58
+ /** A card body layout. */
59
+ export declare const CardContent: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
60
+ /** A card footer layout. */
61
+ export declare const CardFooter: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn, cva } from "../lib/cn.js";
4
+ const cardVariants = cva("card caps-card", {
5
+ variants: {
6
+ variant: {
7
+ surface: "caps-card-surface",
8
+ outline: "caps-card-outline",
9
+ interactive: "caps-card-interactive",
10
+ game: "caps-card-game caps-card-interactive",
11
+ fit: "caps-card-fit",
12
+ },
13
+ density: {
14
+ regular: "",
15
+ compact: "caps-card-compact",
16
+ },
17
+ },
18
+ defaultVariants: { variant: "surface", density: "regular" },
19
+ });
20
+ /** A presentational card shell. */
21
+ export const Card = forwardRef(function Card({ className, density, featured = false, state, variant, ...props }, ref) {
22
+ return (_jsx("div", { ...props, className: cn(cardVariants({ density, variant }), featured && "caps-card-featured", className), "data-state": state, ref: ref }));
23
+ });
24
+ /** Center one primary card in a welcoming, viewport-filling page stage. */
25
+ export const CenteredCard = forwardRef(function CenteredCard({ className, density, variant, width = "default", ...props }, ref) {
26
+ return (_jsx("main", { className: "caps-centered-card-stage", children: _jsx(Card, { ...props, className: cn("caps-centered-card", width === "wide" && "caps-centered-card-wide", className), ref: ref, variant: variant ?? "surface", ...(density ? { density } : {}) }) }));
27
+ });
28
+ /** Render a Caps card header with the requested alignment. */
29
+ export const CardHeader = forwardRef(function CardHeader({ alignment = "start", className, ...props }, ref) {
30
+ return (_jsx("div", { ...props, className: cn("caps-card-header", alignment === "center" && "caps-card-header-centered", className), ref: ref }));
31
+ });
32
+ /** A card title element. */
33
+ export const CardTitle = forwardRef(function CardTitle({ className, level = 3, ...props }, ref) {
34
+ const Heading = level === 2 ? "h2" : "h3";
35
+ return (_jsx(Heading, { ...props, className: cn("caps-card-title", className), ref: ref }));
36
+ });
37
+ /** A card supporting-description element. */
38
+ export const CardDescription = forwardRef(function CardDescription({ className, ...props }, ref) {
39
+ return (_jsx("p", { ...props, className: cn("caps-card-description", className), ref: ref }));
40
+ });
41
+ /** A card body layout. */
42
+ export const CardContent = forwardRef(function CardContent({ className, ...props }, ref) {
43
+ return (_jsx("div", { ...props, className: cn("caps-card-content", className), ref: ref }));
44
+ });
45
+ /** A card footer layout. */
46
+ export const CardFooter = forwardRef(function CardFooter({ className, ...props }, ref) {
47
+ return (_jsx("div", { ...props, className: cn("caps-card-footer", className), ref: ref }));
48
+ });
@@ -0,0 +1,34 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /** Which side of the conversation a bubble sits on. */
3
+ export type ChatBubbleSide = "agent" | "user";
4
+ /** `pending` is still being written; `error` is a turn that did not finish. */
5
+ export type ChatBubbleState = "settled" | "pending" | "error";
6
+ /** Props accepted by ChatBubble. */
7
+ export type ChatBubbleProps = {
8
+ /** An agent speaks from the left with its mark; the person from the right. */
9
+ side: ChatBubbleSide;
10
+ /** A mark for an agent, drawn beside its bubble. */
11
+ avatar?: ReactNode;
12
+ /** Who is speaking, on the line above the bubble. */
13
+ name?: ReactNode;
14
+ /** When it was said, or what the speaker is doing instead. */
15
+ time?: ReactNode;
16
+ state?: ChatBubbleState;
17
+ children?: ReactNode;
18
+ } & Omit<HTMLAttributes<HTMLDivElement>, "children">;
19
+ /**
20
+ * One turn of a conversation: who said it, when, and what. It owns the
21
+ * sides, the bubble and the still-writing dots; the caller owns the content.
22
+ */
23
+ export declare const ChatBubble: import("react").ForwardRefExoticComponent<{
24
+ /** An agent speaks from the left with its mark; the person from the right. */
25
+ side: ChatBubbleSide;
26
+ /** A mark for an agent, drawn beside its bubble. */
27
+ avatar?: ReactNode;
28
+ /** Who is speaking, on the line above the bubble. */
29
+ name?: ReactNode;
30
+ /** When it was said, or what the speaker is doing instead. */
31
+ time?: ReactNode;
32
+ state?: ChatBubbleState;
33
+ children?: ReactNode;
34
+ } & Omit<HTMLAttributes<HTMLDivElement>, "children"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn } from "../lib/cn.js";
4
+ /**
5
+ * One turn of a conversation: who said it, when, and what. It owns the
6
+ * sides, the bubble and the still-writing dots; the caller owns the content.
7
+ */
8
+ export const ChatBubble = forwardRef(function ChatBubble({ side, avatar, name, time, state = "settled", children, className, ...props }, ref) {
9
+ return (_jsxs("div", { ...props, className: cn("caps-chat-bubble", className), "data-side": side, "data-state": state, ref: ref, children: [avatar ? (_jsx("span", { "aria-hidden": "true", className: "caps-chat-avatar", children: avatar })) : null, _jsxs("div", { className: "caps-chat-main", children: [name || time ? (_jsxs("div", { className: "caps-chat-meta", children: [name ? _jsx("span", { className: "caps-chat-name", children: name }) : null, time ? _jsx("span", { className: "caps-chat-time", children: time }) : null] })) : null, _jsxs("div", { className: "caps-chat-body", children: [children, state === "pending" ? (_jsxs("span", { "aria-hidden": "true", className: "caps-chat-typing", children: [_jsx("i", {}), _jsx("i", {}), _jsx("i", {})] })) : null] })] })] }));
10
+ });
@@ -0,0 +1,6 @@
1
+ /** Visual state of a checkbox's mark: unchecked, checked, or indeterminate ("mixed"). */
2
+ export type CheckboxState = "unchecked" | "checked" | "mixed";
3
+ /** @internal Draw one sculpted stroke from its first tip through to its last. */
4
+ export declare function CheckboxBead({ state }: {
5
+ state: CheckboxState;
6
+ }): import("react/jsx-runtime").JSX.Element;