@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,59 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /**
3
+ * How an absence presents itself. `plain` leaves layout to the host; `panel`
4
+ * is a recessed, centered invitation; `speech` lets the visual (a mascot) say
5
+ * the copy from a molded speech bubble; `hint` is a quiet centered footnote
6
+ * under content, such as the next thing to try; `quiet` is a left-aligned
7
+ * absence nested under a card or section heading, titled below that heading.
8
+ */
9
+ export type EmptyStateVariant = "plain" | "panel" | "speech" | "hint" | "quiet";
10
+ /** The document heading level of an EmptyState title. */
11
+ export type EmptyStateHeadingLevel = 2 | 3 | 4;
12
+ /** What a visual is told while the EmptyState is on screen. */
13
+ export type EmptyStateVisualState = Readonly<{
14
+ /** True for a moment after a `speech` state mounts, unless motion is reduced. */
15
+ speaking: boolean;
16
+ /** True while the host says it is working on an answer; it outranks speaking. */
17
+ thinking: boolean;
18
+ }>;
19
+ /** A suggested next step, shown as a chip the host acts on. */
20
+ export type EmptyStateSuggestion = Readonly<{
21
+ /** The chip's text. */
22
+ label: string;
23
+ /** Called when the chip is chosen. */
24
+ onSelect: () => void;
25
+ }>;
26
+ /** Props accepted by EmptyState. */
27
+ export type EmptyStateProps = Omit<HTMLAttributes<HTMLElement>, "title"> & {
28
+ actions?: ReactNode;
29
+ description: ReactNode;
30
+ /** Chips that offer a starting point, such as a prompt to try. */
31
+ suggestions?: readonly EmptyStateSuggestion[];
32
+ /** The host is working on something, such as creating what this state invites. */
33
+ thinking?: boolean;
34
+ title: ReactNode;
35
+ /** Heading level for the title; use one below the heading it sits under. */
36
+ headingLevel?: EmptyStateHeadingLevel;
37
+ /** Static art. */
38
+ visual?: ReactNode;
39
+ /** Render a visual from the current speaking and thinking state. */
40
+ renderVisual?: (state: EmptyStateVisualState) => ReactNode;
41
+ variant?: EmptyStateVariant;
42
+ };
43
+ /** Product-neutral absence presentation; hosts supply copy, art, and actions. */
44
+ export declare const EmptyState: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "title"> & {
45
+ actions?: ReactNode;
46
+ description: ReactNode;
47
+ /** Chips that offer a starting point, such as a prompt to try. */
48
+ suggestions?: readonly EmptyStateSuggestion[];
49
+ /** The host is working on something, such as creating what this state invites. */
50
+ thinking?: boolean;
51
+ title: ReactNode;
52
+ /** Heading level for the title; use one below the heading it sits under. */
53
+ headingLevel?: EmptyStateHeadingLevel;
54
+ /** Static art. */
55
+ visual?: ReactNode;
56
+ /** Render a visual from the current speaking and thinking state. */
57
+ renderVisual?: (state: EmptyStateVisualState) => ReactNode;
58
+ variant?: EmptyStateVariant;
59
+ } & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useId, useState, useRef, } from "react";
3
+ import { Button } from "../components/button.js";
4
+ import { useMotion, motionTime } from "../lib/motion.js";
5
+ import { cn } from "../lib/cn.js";
6
+ const headingTags = { 2: "h2", 3: "h3", 4: "h4" };
7
+ function useSpeaking(enabled, timing) {
8
+ const { reduced } = timing;
9
+ const active = enabled && !reduced;
10
+ const duration = motionTime(timing, 600);
11
+ const [speaking, setSpeaking] = useState(active);
12
+ useEffect(() => {
13
+ setSpeaking(active);
14
+ if (!active)
15
+ return undefined;
16
+ const timer = globalThis.setTimeout(() => {
17
+ setSpeaking(false);
18
+ }, duration);
19
+ return () => {
20
+ globalThis.clearTimeout(timer);
21
+ };
22
+ }, [active, duration]);
23
+ return speaking;
24
+ }
25
+ /** Product-neutral absence presentation; hosts supply copy, art, and actions. */
26
+ export const EmptyState = forwardRef(function EmptyState({ actions, className, description, headingLevel = 2, suggestions, thinking = false, title, visual, renderVisual, variant = "plain", ...props }, ref) {
27
+ const titleId = useId();
28
+ const heading = useRef(null);
29
+ const timing = useMotion(heading);
30
+ const speaking = useSpeaking(variant === "speech", timing) && !thinking;
31
+ const Heading = headingTags[headingLevel];
32
+ const art = renderVisual ? renderVisual({ speaking, thinking }) : visual;
33
+ const copy = (_jsxs(_Fragment, { children: [_jsx(Heading, { ref: heading, className: "empty-state-title", id: props["aria-labelledby"] ? undefined : titleId, children: title }), _jsx("p", { children: description }), suggestions && suggestions.length > 0 ? (_jsx("ul", { "aria-label": "Try one of these", className: "empty-state-suggestions", children: suggestions.map((suggestion) => (_jsx("li", { children: _jsx(Button, { size: "sm", variant: "outline", onClick: suggestion.onSelect, children: suggestion.label }) }, suggestion.label))) })) : null, actions ? _jsx("div", { className: "empty-state-actions", children: actions }) : null] }));
34
+ return (_jsxs("section", { ...props, "aria-labelledby": props["aria-labelledby"] ?? titleId, className: cn("empty-state", variant !== "plain" && `empty-state-${variant}`, className), ref: ref, children: [art ? (_jsx("div", { "aria-hidden": "true", className: "empty-state-visual", children: art })) : null, variant === "speech" ? (_jsx("div", { className: "empty-state-bubble", children: copy })) : (copy)] }));
35
+ });
@@ -0,0 +1,62 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /** One reviewed question and its fixed answer. */
3
+ export type FaqChatEntry = {
4
+ /** Stable identity for the entry. */
5
+ id: string;
6
+ /** The question as a visitor would ask it. Also shown as a suggestion. */
7
+ question: string;
8
+ /** The reviewed answer. The chat never generates text of its own. */
9
+ answer: ReactNode;
10
+ /** Lowercase words or phrases that route a typed question here. */
11
+ keywords?: readonly string[];
12
+ /** Caller-owned next steps shown under the answer, such as links. */
13
+ actions?: ReactNode;
14
+ };
15
+ /** The reply for a typed question that matches no entry. */
16
+ export type FaqChatFallback = {
17
+ answer: ReactNode;
18
+ actions?: ReactNode;
19
+ };
20
+ /** Props accepted by FaqChat. */
21
+ export type FaqChatProps = Omit<HTMLAttributes<HTMLElement>, "title"> & {
22
+ entries: readonly FaqChatEntry[];
23
+ /** The first agent message, shown before any question. */
24
+ greeting: ReactNode;
25
+ fallback: FaqChatFallback;
26
+ /** Visible heading and accessible name of the chat. */
27
+ title: ReactNode;
28
+ /** A short honest note about where answers come from. */
29
+ note?: ReactNode;
30
+ /** Optional mark shown beside the title, such as a logo. */
31
+ avatar?: ReactNode;
32
+ /** Accessible label of the typed-question field. */
33
+ inputLabel?: string;
34
+ placeholder?: string;
35
+ submitLabel?: string;
36
+ };
37
+ /**
38
+ * Routes a typed question to the entry whose keywords it mentions most.
39
+ * Returns undefined when nothing matches, so the caller can answer honestly.
40
+ */
41
+ export declare function matchFaqEntry(entries: readonly FaqChatEntry[], text: string): FaqChatEntry | undefined;
42
+ /**
43
+ * A chat-shaped FAQ. Visitors pick or type a question and get the caller's
44
+ * reviewed answer with its next steps. Message rows follow Parakeet: the
45
+ * visitor's turn sits on the surface with a primary rule, the answer is plain.
46
+ */
47
+ export declare const FaqChat: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "title"> & {
48
+ entries: readonly FaqChatEntry[];
49
+ /** The first agent message, shown before any question. */
50
+ greeting: ReactNode;
51
+ fallback: FaqChatFallback;
52
+ /** Visible heading and accessible name of the chat. */
53
+ title: ReactNode;
54
+ /** A short honest note about where answers come from. */
55
+ note?: ReactNode;
56
+ /** Optional mark shown beside the title, such as a logo. */
57
+ avatar?: ReactNode;
58
+ /** Accessible label of the typed-question field. */
59
+ inputLabel?: string;
60
+ placeholder?: string;
61
+ submitLabel?: string;
62
+ } & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useId, useRef, useState, } from "react";
3
+ import { Button } from "../components/button.js";
4
+ import { Input } from "../components/input.js";
5
+ import { cn } from "../lib/cn.js";
6
+ import { Composer } from "./composer.js";
7
+ function words(text) {
8
+ return text.toLowerCase().match(/[a-z0-9$]+/g) ?? [];
9
+ }
10
+ /**
11
+ * Routes a typed question to the entry whose keywords it mentions most.
12
+ * Returns undefined when nothing matches, so the caller can answer honestly.
13
+ */
14
+ export function matchFaqEntry(entries, text) {
15
+ const asked = ` ${words(text).join(" ")} `;
16
+ if (asked.trim().length === 0)
17
+ return undefined;
18
+ let best;
19
+ let bestScore = 0;
20
+ for (const entry of entries) {
21
+ const score = (entry.keywords ?? []).reduce((total, keyword) => {
22
+ const phrase = words(keyword).join(" ");
23
+ return phrase.length > 0 && asked.includes(` ${phrase} `)
24
+ ? total + 1
25
+ : total;
26
+ }, 0);
27
+ if (score > bestScore) {
28
+ best = entry;
29
+ bestScore = score;
30
+ }
31
+ }
32
+ return best;
33
+ }
34
+ /**
35
+ * A chat-shaped FAQ. Visitors pick or type a question and get the caller's
36
+ * reviewed answer with its next steps. Message rows follow Parakeet: the
37
+ * visitor's turn sits on the surface with a primary rule, the answer is plain.
38
+ */
39
+ export const FaqChat = forwardRef(function FaqChat({ avatar, className, entries, fallback, greeting, inputLabel = "Ask a question", note, placeholder = "Ask about the plans", submitLabel = "Ask", title, ...rootProps }, ref) {
40
+ const titleId = useId();
41
+ const logRef = useRef(null);
42
+ const nextKey = useRef(0);
43
+ const [turns, setTurns] = useState([]);
44
+ const [draft, setDraft] = useState("");
45
+ useEffect(() => {
46
+ const log = logRef.current;
47
+ if (log)
48
+ log.scrollTop = log.scrollHeight;
49
+ }, [turns]);
50
+ function ask(text, reply) {
51
+ const userKey = nextKey.current++;
52
+ const agentKey = nextKey.current++;
53
+ setTurns((previous) => [
54
+ ...previous,
55
+ { key: userKey, speaker: "user", text },
56
+ {
57
+ actions: reply.actions,
58
+ answer: reply.answer,
59
+ key: agentKey,
60
+ speaker: "agent",
61
+ },
62
+ ]);
63
+ }
64
+ function submit(event) {
65
+ event.preventDefault();
66
+ const text = draft.trim();
67
+ if (text.length === 0)
68
+ return;
69
+ ask(text, matchFaqEntry(entries, text) ?? fallback);
70
+ setDraft("");
71
+ }
72
+ return (_jsxs("section", { ...rootProps, "aria-labelledby": titleId, className: cn("caps-faq-chat", className), ref: ref, children: [_jsxs("header", { className: "caps-faq-chat-header", children: [avatar, _jsxs("div", { className: "caps-faq-chat-heading", children: [_jsx("p", { className: "caps-faq-chat-title", id: titleId, children: title }), note ? _jsx("p", { className: "caps-faq-chat-note", children: note }) : null] })] }), _jsxs("div", { "aria-live": "polite", className: "caps-faq-chat-log", ref: logRef, role: "log", children: [_jsx("div", { className: "caps-faq-chat-agent", children: greeting }), turns.map((turn) => turn.speaker === "user" ? (_jsx("p", { className: "caps-faq-chat-user", children: turn.text }, turn.key)) : (_jsxs("div", { className: "caps-faq-chat-agent", children: [turn.answer, turn.actions ? (_jsx("div", { className: "caps-faq-chat-actions", children: turn.actions })) : null] }, turn.key)))] }), _jsx("ul", { "aria-label": "Suggested questions", className: "caps-faq-chat-suggestions", children: entries.map((entry) => (_jsx("li", { children: _jsx(Button, { onClick: () => {
73
+ ask(entry.question, entry);
74
+ }, size: "xs", type: "button", variant: "outline", children: entry.question }) }, entry.id))) }), _jsx("form", { className: "caps-faq-chat-form", onSubmit: submit, children: _jsx(Composer, { action: _jsx(Button, { className: "join-item", type: "submit", children: submitLabel }), input: _jsx(Input, { "aria-label": inputLabel, className: "join-item", onChange: (event) => {
75
+ setDraft(event.target.value);
76
+ }, placeholder: placeholder, value: draft }) }) })] }));
77
+ });
@@ -0,0 +1,17 @@
1
+ import { type HTMLAttributes, type ReactElement, type ReactNode } from "react";
2
+ /** Presentation for a published game; fetching and navigation stay with the host. */
3
+ export type GameShareCardProps = HTMLAttributes<HTMLDivElement> & {
4
+ heading: ReactNode;
5
+ eyebrow?: ReactNode;
6
+ cover?: ReactNode;
7
+ /** A host-owned link or button, presented as the primary play action. */
8
+ action: ReactElement;
9
+ };
10
+ /** Compose a game's cover, share details and play action in the enclosing theme. */
11
+ export declare const GameShareCard: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
12
+ heading: ReactNode;
13
+ eyebrow?: ReactNode;
14
+ cover?: ReactNode;
15
+ /** A host-owned link or button, presented as the primary play action. */
16
+ action: ReactElement;
17
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, } from "react";
3
+ import { Button } from "../components/button.js";
4
+ import { Card, CardContent, CardFooter, CardHeader, } from "../components/card.js";
5
+ import { cn } from "../lib/cn.js";
6
+ /** Compose a game's cover, share details and play action in the enclosing theme. */
7
+ export const GameShareCard = forwardRef(function GameShareCard({ heading, eyebrow, cover, action, children, className, ...props }, ref) {
8
+ return (_jsxs(Card, { ...props, className: cn("caps-game-share", className), ref: ref, children: [cover ? _jsx("div", { className: "caps-game-share-cover", children: cover }) : null, _jsxs(CardHeader, { children: [eyebrow, _jsx("h3", { className: "caps-game-share-heading", children: heading })] }), _jsx(CardContent, { className: "gap-sm", children: children }), _jsx(CardFooter, { children: _jsx(Button, { asChild: true, variant: "primary", className: "caps-game-share-action", children: action }) })] }));
9
+ });
@@ -0,0 +1,50 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /** SectionGrid props. */
3
+ export type SectionGridProps = HTMLAttributes<HTMLDivElement> & {
4
+ /**
5
+ * `split` is a page's two-column section grid. `desktop` composes a home
6
+ * screen: it fills and scrolls its region, centers a bounded measure, and
7
+ * lets `span="full"` sections run across both columns.
8
+ */
9
+ layout?: "split" | "desktop";
10
+ };
11
+ /** A two-column page section grid that stacks at the compact breakpoint. */
12
+ export declare const SectionGrid: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
13
+ /**
14
+ * `split` is a page's two-column section grid. `desktop` composes a home
15
+ * screen: it fills and scrolls its region, centers a bounded measure, and
16
+ * lets `span="full"` sections run across both columns.
17
+ */
18
+ layout?: "split" | "desktop";
19
+ } & import("react").RefAttributes<HTMLDivElement>>;
20
+ /** A caller-owned App launch option. */
21
+ export type AppGridItem = Readonly<{
22
+ id: string;
23
+ label: string;
24
+ icon: ReactNode;
25
+ /** Caller-owned state line below the App name. */
26
+ status?: ReactNode;
27
+ disabled?: boolean;
28
+ /** A dimmed App identity whose action may still open settings or recovery. */
29
+ muted?: boolean;
30
+ /** Invoke the caller-owned App launch behavior. */
31
+ onSelect: () => void;
32
+ }>;
33
+ /** AppGrid props. */
34
+ export type AppGridProps = Omit<HTMLAttributes<HTMLUListElement>, "children"> & {
35
+ items: readonly AppGridItem[];
36
+ /**
37
+ * `default` is a quiet launcher. `lg` gives each mark a larger key
38
+ * and a more spacious label. The theme supplies its material.
39
+ */
40
+ size?: "default" | "lg";
41
+ };
42
+ /** A responsive launcher grid with large marks and concise labels. */
43
+ export declare const AppGrid: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLUListElement>, "children"> & {
44
+ items: readonly AppGridItem[];
45
+ /**
46
+ * `default` is a quiet launcher. `lg` gives each mark a larger key
47
+ * and a more spacious label. The theme supplies its material.
48
+ */
49
+ size?: "default" | "lg";
50
+ } & import("react").RefAttributes<HTMLUListElement>>;
@@ -0,0 +1,11 @@
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
+ /** A two-column page section grid that stacks at the compact breakpoint. */
5
+ export const SectionGrid = forwardRef(function SectionGrid({ className, layout = "split", ...props }, ref) {
6
+ return (_jsx("div", { ...props, className: cn("caps-section-grid", className), "data-layout": layout === "desktop" ? "desktop" : undefined, ref: ref }));
7
+ });
8
+ /** A responsive launcher grid with large marks and concise labels. */
9
+ export const AppGrid = forwardRef(function AppGrid({ className, items, size = "default", ...props }, ref) {
10
+ return (_jsx("ul", { ...props, className: cn("caps-app-grid", className), "data-size": size === "lg" ? "lg" : undefined, ref: ref, children: items.map((item) => (_jsxs("li", { children: [_jsxs("button", { "aria-label": item.label, className: cn("caps-app-grid-item", item.muted && "opacity-55"), disabled: item.disabled, onClick: item.onSelect, type: "button", children: [_jsx("span", { "aria-hidden": "true", className: "caps-app-grid-icon", children: item.icon }), _jsx("span", { className: "caps-app-grid-label", children: item.label })] }), item.status ? (_jsx("div", { className: "flex justify-center", children: item.status })) : null] }, item.id))) }));
11
+ });
@@ -0,0 +1,23 @@
1
+ import { type ReactNode } from "react";
2
+ /** Product-neutral listing detail: callers own availability, navigation and facts. */
3
+ export type ListingDetailProps = Readonly<{
4
+ identity: string;
5
+ title: string;
6
+ tagline: string;
7
+ icon?: ReactNode;
8
+ seller?: ReactNode;
9
+ action?: ReactNode;
10
+ back?: ReactNode;
11
+ note?: ReactNode;
12
+ screenshots?: readonly {
13
+ src: string;
14
+ alt: string;
15
+ }[];
16
+ description?: readonly string[];
17
+ facts?: readonly {
18
+ label: string;
19
+ value: ReactNode;
20
+ }[];
21
+ }>;
22
+ /** A focused detail heading, screenshot strip, readable body and fact sheet. */
23
+ export declare function ListingDetail({ identity, title, tagline, icon, seller, action, back, note, screenshots, description, facts, }: ListingDetailProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useId, useRef } from "react";
3
+ import { Display } from "../components/surface.js";
4
+ /** A focused detail heading, screenshot strip, readable body and fact sheet. */
5
+ export function ListingDetail({ identity, title, tagline, icon, seller, action, back, note, screenshots = [], description = [], facts = [], }) {
6
+ const id = useId();
7
+ const heading = useRef(null);
8
+ useEffect(() => {
9
+ heading.current?.focus();
10
+ }, [identity]);
11
+ return (_jsxs("article", { className: "caps-listing-detail", "aria-labelledby": `${id}-name`, children: [back ? _jsx("div", { children: back }) : null, _jsxs("header", { className: "caps-listing-detail-header", children: [icon, _jsxs("div", { className: "caps-listing-detail-title", children: [_jsx("h1", { id: `${id}-name`, ref: heading, tabIndex: -1, children: title }), _jsx("p", { className: "caps-listing-detail-tagline", children: tagline }), _jsx("div", { className: "caps-listing-detail-meta", children: seller })] }), _jsx("div", { className: "caps-listing-detail-action", children: action })] }), note ? (_jsx("p", { className: "caps-listing-detail-note", role: "status", children: note })) : null, screenshots.length ? (_jsx("section", { "aria-label": "Screenshots", className: "caps-listing-shots", children: screenshots.map((shot) => (_jsx(Display, { className: "caps-listing-shot", density: "compact", size: "sm", children: _jsx("img", { src: shot.src, alt: shot.alt }) }, shot.src))) })) : null, _jsxs("div", { className: "caps-listing-detail-body", children: [description.length ? (_jsxs("section", { className: "caps-listing-detail-about", "aria-labelledby": `${id}-about`, children: [_jsxs("h2", { id: `${id}-about`, children: ["About ", title] }), description.map((paragraph, index) => (_jsx("p", { children: paragraph }, index)))] })) : null, facts.length ? (_jsx("dl", { className: "caps-listing-facts", children: facts.map((fact) => (_jsxs("div", { children: [_jsx("dt", { children: fact.label }), _jsx("dd", { children: fact.value })] }, fact.label))) })) : null] })] }));
12
+ }
@@ -0,0 +1,5 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /** A bounded, labelled loading region; the caller owns the message. */
3
+ export declare const LoadingState: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
4
+ message: ReactNode;
5
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Loader } from "../components/loader.js";
4
+ import { cn } from "../lib/cn.js";
5
+ /** A bounded, labelled loading region; the caller owns the message. */
6
+ export const LoadingState = forwardRef(function LoadingState({ className, message, ...props }, ref) {
7
+ return (_jsxs("div", { ...props, className: cn("caps-loading-state", className), ref: ref, role: "status", children: [_jsx(Loader, { decorative: true, size: "sm" }), _jsx("span", { children: message })] }));
8
+ });
@@ -0,0 +1,29 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /** A caller-resolved visual tile. */
3
+ export type MosaicItem = {
4
+ alt?: string;
5
+ height?: number;
6
+ id: string;
7
+ disabled?: boolean;
8
+ state?: "loading" | "ready" | "error";
9
+ url?: string;
10
+ width?: number;
11
+ };
12
+ /** Props accepted by Mosaic. */
13
+ export type MosaicProps = HTMLAttributes<HTMLDivElement> & {
14
+ empty?: ReactNode;
15
+ items: readonly MosaicItem[];
16
+ /** Caller-owned accessible copy for the list. */
17
+ label?: ReactNode;
18
+ /** When absent, tiles are deliberately non-interactive. */
19
+ onOpen?: (item: MosaicItem) => void;
20
+ };
21
+ /** Renders supplied tiles only; callers resolve data, policy, and navigation. */
22
+ export declare const Mosaic: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
23
+ empty?: ReactNode;
24
+ items: readonly MosaicItem[];
25
+ /** Caller-owned accessible copy for the list. */
26
+ label?: ReactNode;
27
+ /** When absent, tiles are deliberately non-interactive. */
28
+ onOpen?: (item: MosaicItem) => void;
29
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,19 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useId, } from "react";
3
+ /** Renders supplied tiles only; callers resolve data, policy, and navigation. */
4
+ export const Mosaic = forwardRef(function Mosaic({ className, empty, items, label, onOpen, ...rootProps }, ref) {
5
+ const labelId = useId();
6
+ if (items.length === 0)
7
+ return _jsx(_Fragment, { children: empty ?? null });
8
+ return (_jsxs("div", { ...rootProps, ref: ref, "aria-labelledby": label ? labelId : undefined, className: [
9
+ "grid grid-cols-2 gap-xs md:grid-cols-3 xl:grid-cols-4",
10
+ className,
11
+ ]
12
+ .filter(Boolean)
13
+ .join(" "), role: "list", children: [label ? (_jsx("span", { className: "sr-only", id: labelId, children: label })) : null, items.map((item) => (_jsx("div", { role: "listitem", children: onOpen ? (_jsx("button", { "aria-busy": item.state === "loading" || undefined, "aria-label": item.alt ?? item.id, className: "relative aspect-square w-full overflow-hidden rounded-box border border-base-300 bg-base-200 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 caps-focus-color", "data-mosaic-item": item.id, disabled: item.disabled, onClick: () => {
14
+ onOpen(item);
15
+ }, type: "button", children: _jsx(Tile, { item: item }) })) : (_jsx("div", { "aria-busy": item.state === "loading" || undefined, className: "relative aspect-square overflow-hidden rounded-box border border-base-300 bg-base-200", "data-mosaic-item": item.id, children: _jsx(Tile, { item: item }) })) }, item.id)))] }));
16
+ });
17
+ function Tile({ item }) {
18
+ return (_jsxs(_Fragment, { children: [item.url ? (_jsx("img", { alt: item.alt ?? "", className: "h-full w-full object-cover", height: item.height, src: item.url, width: item.width })) : null, item.state === "loading" ? (_jsx("span", { "aria-hidden": "true", className: "loading loading-spinner loading-sm absolute inset-0 m-auto" })) : null] }));
19
+ }
@@ -0,0 +1,45 @@
1
+ import type { JSX, ReactNode } from "react";
2
+ /**
3
+ * LAW — a permission grid is a spec sheet, not a form: one row per
4
+ * capability, read left to right as index, mark, name, state and scope. The
5
+ * mark is decorative; the row's name is its accessible fact. State is always
6
+ * spelled out in words, never carried by color alone. Any control a row
7
+ * carries is caller-owned and names itself.
8
+ */
9
+ /** Whether the capability is available in this scope. */
10
+ export type PermissionState = "allowed" | "denied";
11
+ /** One capability row. */
12
+ export type PermissionGridRow = Readonly<{
13
+ id: string;
14
+ /** Decorative mark, for example a sigil; hidden from assistive technology. */
15
+ mark: ReactNode;
16
+ /** The capability's name; the row's accessible fact. */
17
+ label: string;
18
+ /** Short family label shown beside the index, for example `COMPUTERS`. */
19
+ group?: string;
20
+ state: PermissionState;
21
+ /** Visible state word, for example `On` or `Off`. */
22
+ stateLabel: string;
23
+ /** Where the state comes from, for example `Owner grant` or `Default`. */
24
+ scope: string;
25
+ /** Optional caller-owned control, for example a switch naming this row. */
26
+ control?: ReactNode;
27
+ }>;
28
+ /** Props accepted by PermissionGrid. */
29
+ export type PermissionGridProps = Readonly<{
30
+ /** Visible caption naming whose permissions these are. */
31
+ caption: ReactNode;
32
+ /** Optional plain-language note under the caption. */
33
+ summary?: ReactNode;
34
+ rows: readonly PermissionGridRow[];
35
+ /** Column headings; product copy stays with the caller. */
36
+ headings?: Readonly<{
37
+ capability: string;
38
+ state: string;
39
+ scope: string;
40
+ control?: string;
41
+ }>;
42
+ className?: string;
43
+ }>;
44
+ /** Product-neutral, dense capability sheet: one row per capability. */
45
+ export declare function PermissionGrid({ caption, summary, rows, headings, className, }: PermissionGridProps): JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const DEFAULT_HEADINGS = {
3
+ capability: "Capability",
4
+ state: "State",
5
+ scope: "Scope",
6
+ };
7
+ function index(position) {
8
+ return String(position + 1).padStart(2, "0");
9
+ }
10
+ /** Product-neutral, dense capability sheet: one row per capability. */
11
+ export function PermissionGrid({ caption, summary, rows, headings = DEFAULT_HEADINGS, className, }) {
12
+ const hasControls = rows.some((row) => row.control !== undefined);
13
+ return (_jsxs("figure", { className: `caps-permission-grid ${className ?? ""}`, children: [_jsxs("figcaption", { className: "caps-permission-grid-caption", children: [_jsx("span", { className: "caps-permission-grid-title", children: caption }), summary === undefined ? null : (_jsx("span", { className: "caps-permission-grid-summary", children: summary }))] }), _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", className: "caps-permission-grid-index", children: "#" }), _jsx("th", { scope: "col", children: headings.capability }), _jsx("th", { scope: "col", children: headings.state }), _jsx("th", { scope: "col", children: headings.scope }), hasControls ? (_jsx("th", { scope: "col", children: headings.control ?? _jsx("span", { className: "sr-only", children: "Change" }) })) : null] }) }), _jsx("tbody", { children: rows.map((row, position) => (_jsxs("tr", { "data-state": row.state, children: [_jsxs("td", { className: "caps-permission-grid-index", children: [_jsx("span", { children: index(position) }), row.group === undefined ? null : (_jsx("span", { className: "caps-permission-grid-group", children: row.group }))] }), _jsx("th", { scope: "row", children: _jsxs("span", { className: "caps-permission-grid-capability", children: [_jsx("span", { className: "caps-permission-grid-mark", "aria-hidden": "true", children: row.mark }), _jsx("span", { children: row.label })] }) }), _jsx("td", { children: _jsx("span", { className: "caps-permission-grid-state", "data-state": row.state, children: row.stateLabel }) }), _jsx("td", { className: "caps-permission-grid-scope", children: row.scope }), hasControls ? _jsx("td", { children: row.control ?? null }) : null] }, row.id))) })] })] }));
14
+ }
@@ -0,0 +1,53 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import { type CardProps } from "../components/card.js";
3
+ /** Caller-provided pricing plan data. */
4
+ export type PricingPlan = {
5
+ name: ReactNode;
6
+ description?: ReactNode;
7
+ price?: ReactNode;
8
+ interval?: ReactNode;
9
+ };
10
+ /** Supported PricingCard layouts. */
11
+ export type PricingCardLayout = "stacked" | "banded";
12
+ /** Props accepted by PricingCard. */
13
+ export type PricingCardProps = HTMLAttributes<HTMLDivElement> & {
14
+ plan: PricingPlan;
15
+ /** Caller-owned feature rows. */
16
+ features?: ReactNode;
17
+ /** Caller-owned action control; this block never invokes or configures it. */
18
+ action?: ReactNode;
19
+ /** Caller-owned status content, such as a badge. */
20
+ status?: ReactNode;
21
+ /** Caller-owned illustration, such as an `img` with its own alt text. */
22
+ art?: ReactNode;
23
+ /**
24
+ * `stacked` groups the title and price in the header. `banded` places the
25
+ * name above the illustration and keeps the price on one line.
26
+ */
27
+ layout?: PricingCardLayout;
28
+ /** Marks the one plan a page recommends with a heavier shadow. */
29
+ featured?: boolean;
30
+ /** Use tighter section spacing for dense plan comparisons. */
31
+ density?: CardProps["density"];
32
+ };
33
+ /** Displays supplied plan data and slots; checkout and policy stay with the host. */
34
+ export declare const PricingCard: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
35
+ plan: PricingPlan;
36
+ /** Caller-owned feature rows. */
37
+ features?: ReactNode;
38
+ /** Caller-owned action control; this block never invokes or configures it. */
39
+ action?: ReactNode;
40
+ /** Caller-owned status content, such as a badge. */
41
+ status?: ReactNode;
42
+ /** Caller-owned illustration, such as an `img` with its own alt text. */
43
+ art?: ReactNode;
44
+ /**
45
+ * `stacked` groups the title and price in the header. `banded` places the
46
+ * name above the illustration and keeps the price on one line.
47
+ */
48
+ layout?: PricingCardLayout;
49
+ /** Marks the one plan a page recommends with a heavier shadow. */
50
+ featured?: boolean;
51
+ /** Use tighter section spacing for dense plan comparisons. */
52
+ density?: CardProps["density"];
53
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "../components/card.js";
4
+ import { cn } from "../lib/cn.js";
5
+ /** Displays supplied plan data and slots; checkout and policy stay with the host. */
6
+ export const PricingCard = forwardRef(function PricingCard({ action, art, className, density, featured = false, features, plan, status, layout = "stacked", ...rootProps }, ref) {
7
+ const banded = layout === "banded";
8
+ const title = (_jsxs("div", { className: banded
9
+ ? "caps-pricing-card-band"
10
+ : "flex w-full items-start justify-between gap-lg", children: [_jsx(CardTitle, { className: "caps-pricing-card-name", children: plan.name }), status] }));
11
+ return (_jsxs(Card, { ...rootProps, className: cn("caps-pricing-card", banded && "caps-pricing-card-banded", className), "data-featured": featured ? "true" : undefined, ref: ref, variant: "outline", ...(density ? { density } : {}), children: [banded ? title : null, art !== undefined ? (_jsx("figure", { className: "caps-pricing-card-art", children: art })) : null, banded ? (_jsxs(CardHeader, { children: [_jsxs("div", { className: "caps-pricing-card-price", children: [plan.price !== undefined ? _jsx("strong", { children: plan.price }) : null, plan.interval !== undefined ? (_jsx("span", { children: plan.interval })) : null] }), plan.description ? (_jsx(CardDescription, { className: "caps-pricing-card-description", children: plan.description })) : null] })) : (_jsxs(CardHeader, { children: [title, plan.description ? (_jsx(CardDescription, { className: "caps-pricing-card-description", children: plan.description })) : null, plan.price !== undefined ? (_jsx("div", { className: "text-3xl font-semibold", children: plan.price })) : null, plan.interval !== undefined ? (_jsx("div", { className: "text-sm text-base-content", children: plan.interval })) : null] })), features !== undefined ? (_jsx(CardContent, { className: "caps-pricing-card-features", children: features })) : null, action !== undefined ? (_jsx(CardFooter, { className: "caps-pricing-card-action", children: action })) : null] }));
12
+ });
@@ -0,0 +1,20 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ /** One shipped thing and its version, printed under the tag. */
3
+ export type ReleaseTagEntry = Readonly<{
4
+ name: string;
5
+ version: string;
6
+ }>;
7
+ /** Props accepted by ReleaseTag. */
8
+ export type ReleaseTagProps = Omit<HTMLAttributes<HTMLElement>, "title"> & {
9
+ /** One or two short lines printed large on the tag, such as ["Fungi", "Beta"]. */
10
+ title: readonly string[];
11
+ /** A small accent strip under the title, such as "Update". */
12
+ label?: ReactNode;
13
+ entries: readonly ReleaseTagEntry[];
14
+ };
15
+ /**
16
+ * A release badge: a torn-off calendar page with binder rings, a stacked
17
+ * title, one accent strip and a ruled list of names and versions below.
18
+ * Presentation only; the caller supplies every word.
19
+ */
20
+ export declare function ReleaseTag({ className, entries, label, title, ...props }: ReleaseTagProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cn.js";
3
+ /**
4
+ * A release badge: a torn-off calendar page with binder rings, a stacked
5
+ * title, one accent strip and a ruled list of names and versions below.
6
+ * Presentation only; the caller supplies every word.
7
+ */
8
+ export function ReleaseTag({ className, entries, label, title, ...props }) {
9
+ return (_jsxs("aside", { ...props, className: cn("caps-release-tag", className), children: [_jsxs("div", { className: "caps-release-tag-page", children: [_jsxs("span", { "aria-hidden": "true", className: "caps-release-tag-rings", children: [_jsx("span", {}), _jsx("span", {})] }), _jsx("p", { className: "caps-release-tag-title", children: title.map((line) => (_jsx("span", { children: line }, line))) }), label ? _jsx("p", { className: "caps-release-tag-label", children: label }) : null] }), _jsx("dl", { className: "caps-release-tag-entries", children: entries.map((entry) => (_jsxs("div", { children: [_jsx("dt", { children: entry.name }), _jsx("dd", { children: entry.version })] }, entry.name))) })] }));
10
+ }
@@ -0,0 +1,22 @@
1
+ import { type ButtonHTMLAttributes } from "react";
2
+ /** Caller-provided resource option data. */
3
+ export type ResourceOption = {
4
+ disabled?: boolean;
5
+ id: string;
6
+ label: string;
7
+ searchText?: string;
8
+ };
9
+ /** Props accepted by ResourceSelect. */
10
+ export type ResourceSelectProps = {
11
+ /** Called after an option is selected. */
12
+ onSelect: (option: ResourceOption) => void;
13
+ options: readonly ResourceOption[];
14
+ placeholder?: string;
15
+ /** Native caller metadata, including data-* attributes. */
16
+ triggerProps?: ButtonHTMLAttributes<HTMLButtonElement> & DataAttributes;
17
+ value?: string;
18
+ };
19
+ /** Native `data-*` attribute map accepted alongside typed props. */
20
+ export type DataAttributes = Record<`data-${string}`, boolean | number | string | undefined>;
21
+ /** A resource-selection block with caller-owned options and selected value. */
22
+ export declare const ResourceSelect: import("react").ForwardRefExoticComponent<ResourceSelectProps & import("react").RefAttributes<HTMLButtonElement>>;