@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,169 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
3
+ import { Slot } from "@radix-ui/react-slot";
4
+ import { createContext, useCallback, forwardRef, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useRef, useState, } from "react";
5
+ import { useOverlayRoot, useOverlayDismiss } from "./overlay-root.js";
6
+ import { cn } from "../lib/cn.js";
7
+ import { canAnimate, motionEasing, readMotion } from "../lib/motion.js";
8
+ const warmth = { open: 0, warm: false, cooling: undefined };
9
+ /** How long the group stays warm after the last tooltip closes. */
10
+ const coolingMs = 600;
11
+ const TooltipContext = createContext(null);
12
+ function useTooltipContext() {
13
+ const context = useContext(TooltipContext);
14
+ if (!context)
15
+ throw new Error("Tooltip parts must be used inside <Tooltip>");
16
+ return context;
17
+ }
18
+ /** A tooltip controller with explicit controlled or uncontrolled open state. */
19
+ export const Tooltip = forwardRef(function Tooltip({ children, className, defaultOpen = false, delayDuration = 300, onOpenChange, open: controlledOpen, side = "top", ...props }, forwardedRef) {
20
+ const trigger = useRef(null);
21
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
22
+ const [arrivedWarm, setArrivedWarm] = useState(false);
23
+ const open = controlledOpen ?? uncontrolledOpen;
24
+ // Count this tooltip toward its group's warmth while it is open.
25
+ useEffect(() => {
26
+ if (!open)
27
+ return;
28
+ warmth.open += 1;
29
+ warmth.warm = true;
30
+ clearTimeout(warmth.cooling);
31
+ return () => {
32
+ warmth.open -= 1;
33
+ if (warmth.open > 0)
34
+ return;
35
+ warmth.cooling = setTimeout(() => {
36
+ warmth.warm = false;
37
+ }, coolingMs);
38
+ };
39
+ }, [open]);
40
+ const contentId = `${useId()}-content`;
41
+ const timer = useRef(null);
42
+ const clearTimer = () => {
43
+ if (timer.current !== null) {
44
+ clearTimeout(timer.current);
45
+ timer.current = null;
46
+ }
47
+ };
48
+ const setOpen = (next) => {
49
+ clearTimer();
50
+ if (controlledOpen === undefined)
51
+ setUncontrolledOpen(next);
52
+ onOpenChange?.(next);
53
+ };
54
+ useOverlayDismiss(() => {
55
+ setOpen(false);
56
+ });
57
+ const scheduleOpen = () => {
58
+ clearTimer();
59
+ if (open)
60
+ return;
61
+ const warm = warmth.warm;
62
+ timer.current = setTimeout(() => {
63
+ setArrivedWarm(warm);
64
+ setOpen(true);
65
+ }, warm ? 0 : Math.max(0, delayDuration));
66
+ };
67
+ const scheduleClose = () => {
68
+ clearTimer();
69
+ if (!open)
70
+ return;
71
+ timer.current = setTimeout(() => {
72
+ setOpen(false);
73
+ }, 0);
74
+ };
75
+ useEffect(() => clearTimer, []);
76
+ return (_jsx(TooltipContext.Provider, { value: {
77
+ arrivedWarm,
78
+ cancelClose: clearTimer,
79
+ contentId,
80
+ open,
81
+ scheduleClose,
82
+ scheduleOpen,
83
+ side,
84
+ trigger,
85
+ }, children: _jsx(BaseTooltip.Root, { open: open, onOpenChange: setOpen, children: _jsx("span", { ...props, className: cn("relative inline-flex", className), ref: forwardedRef, children: children }) }) }));
86
+ });
87
+ /** The trigger control for a Tooltip. */
88
+ export const TooltipTrigger = forwardRef(function TooltipTrigger({ asChild = false, children, className, onBlur, onFocus, onPointerEnter, onPointerLeave, ...props }, forwardedRef) {
89
+ const tooltip = useTooltipContext();
90
+ const attach = useCallback((node) => {
91
+ tooltip.trigger.current = node;
92
+ }, [tooltip.trigger]);
93
+ useImperativeHandle(forwardedRef, () => tooltip.trigger.current);
94
+ const { "aria-describedby": callerDescribedBy, ...nativeProps } = props;
95
+ const triggerProps = {
96
+ ...nativeProps,
97
+ "aria-describedby": [callerDescribedBy, tooltip.open ? tooltip.contentId : undefined]
98
+ .filter(Boolean)
99
+ .join(" ") || undefined,
100
+ "data-state": tooltip.open ? "open" : "closed",
101
+ onBlur: (event) => {
102
+ onBlur?.(event);
103
+ if (!event.defaultPrevented)
104
+ tooltip.scheduleClose();
105
+ },
106
+ onFocus: (event) => {
107
+ onFocus?.(event);
108
+ if (!event.defaultPrevented)
109
+ tooltip.scheduleOpen();
110
+ },
111
+ onPointerEnter: (event) => {
112
+ onPointerEnter?.(event);
113
+ if (!event.defaultPrevented)
114
+ tooltip.scheduleOpen();
115
+ },
116
+ onPointerLeave: (event) => {
117
+ onPointerLeave?.(event);
118
+ if (!event.defaultPrevented)
119
+ tooltip.scheduleClose();
120
+ },
121
+ };
122
+ if (asChild) {
123
+ return (_jsx(Slot, { ...triggerProps, className: cn(className), ref: attach, children: children }));
124
+ }
125
+ return (_jsx("button", { ...triggerProps, className: cn("btn", className), ref: attach, type: props.type ?? "button", children: children }));
126
+ });
127
+ /** The positioned content region for a Tooltip. */
128
+ export const TooltipContent = forwardRef(function TooltipContent({ children, className, onPointerEnter, onPointerLeave, ...props }, ref) {
129
+ const tooltip = useTooltipContext();
130
+ const root = useOverlayRoot("tooltip");
131
+ const [node, setNode] = useState(null);
132
+ useImperativeHandle(ref, () => node, [node]);
133
+ // A cold tooltip arrives from its trigger; a warm one simply swaps in.
134
+ useLayoutEffect(() => {
135
+ const element = node;
136
+ if (!tooltip.open || !element || !canAnimate(element))
137
+ return;
138
+ const motion = readMotion(element);
139
+ const travel = tooltip.arrivedWarm ? 0 : motion.distance;
140
+ const offset = {
141
+ bottom: `0 ${String(-travel)}px`,
142
+ left: `${String(travel)}px 0`,
143
+ right: `${String(-travel)}px 0`,
144
+ top: `0 ${String(travel)}px`,
145
+ }[tooltip.side];
146
+ const arrival = element.animate([
147
+ { opacity: 0, translate: offset },
148
+ { opacity: 1, translate: "0 0" },
149
+ ], {
150
+ duration: tooltip.arrivedWarm ? motion.fast : motion.normal,
151
+ easing: motionEasing(motion, motion.ease),
152
+ composite: "add",
153
+ });
154
+ return () => {
155
+ arrival.cancel();
156
+ };
157
+ }, [node, tooltip.open, tooltip.arrivedWarm, tooltip.side]);
158
+ if (!tooltip.open || !root)
159
+ return null;
160
+ return (_jsx(BaseTooltip.Portal, { container: root, children: _jsx(BaseTooltip.Positioner, { anchor: tooltip.trigger, side: tooltip.side, sideOffset: 8, collisionPadding: 8, collisionBoundary: root === document.body ? undefined : root, className: "pointer-events-auto z-(--stipe-layer-tooltip)", children: _jsx(BaseTooltip.Popup, { ...props, "aria-live": "polite", className: cn("pointer-events-auto max-w-(--container-xs) rounded-box bg-base-content px-md py-sm text-xs text-base-100 shadow-lg", className), id: tooltip.contentId, onPointerEnter: (event) => {
161
+ onPointerEnter?.(event);
162
+ if (!event.defaultPrevented)
163
+ tooltip.cancelClose();
164
+ }, onPointerLeave: (event) => {
165
+ onPointerLeave?.(event);
166
+ if (!event.defaultPrevented)
167
+ tooltip.scheduleClose();
168
+ }, ref: setNode, role: "tooltip", children: children }) }) }));
169
+ });
@@ -0,0 +1,60 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ /** Print finish: `holo` adds a foil sheen on hover that stills for reduced motion. */
3
+ export type TradingCardFinish = "standard" | "holo";
4
+ /** One footer fact, printed like a trading card's weakness or retreat line. */
5
+ export type TradingCardFact = Readonly<{
6
+ label: string;
7
+ value: ReactNode;
8
+ }>;
9
+ /** The card's one move: a cost of symbols, a name, and caller-owned text or controls. */
10
+ export type TradingCardMove = Readonly<{
11
+ /** Decorative cost symbols, such as Sigils. Hidden from assistive technology. */
12
+ cost?: ReactNode;
13
+ name: string;
14
+ /** An optional figure printed at the end of the move line. */
15
+ value?: ReactNode;
16
+ children?: ReactNode;
17
+ }>;
18
+ /** Props accepted by TradingCard. */
19
+ export type TradingCardProps = Omit<HTMLAttributes<HTMLElement>, "title" | "children"> & {
20
+ name: string;
21
+ /** A small stage label printed before the name, such as "Spore". */
22
+ stage?: string;
23
+ /** The stat printed at the right of the name bar, such as "60 SP". */
24
+ stat?: ReactNode;
25
+ /** The type line under the art window. */
26
+ typeLine?: string;
27
+ art: ReactNode;
28
+ move: TradingCardMove;
29
+ flavor?: ReactNode;
30
+ facts?: readonly TradingCardFact[];
31
+ /** Collector number, such as "001/001". */
32
+ setNumber?: string;
33
+ /** A small rarity mark printed by the set number. */
34
+ rarity?: ReactNode;
35
+ finish?: TradingCardFinish;
36
+ };
37
+ /**
38
+ * A 63:88 trading card: a bright rim, a name bar with a stage and stat, an art
39
+ * window, one move row that can hold a real form, a flavor line and a footer of
40
+ * facts with a set number and rarity mark. The move body is caller-owned, so a
41
+ * form inside it keeps its own labels, focus and errors.
42
+ */
43
+ export declare const TradingCard: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "title" | "children"> & {
44
+ name: string;
45
+ /** A small stage label printed before the name, such as "Spore". */
46
+ stage?: string;
47
+ /** The stat printed at the right of the name bar, such as "60 SP". */
48
+ stat?: ReactNode;
49
+ /** The type line under the art window. */
50
+ typeLine?: string;
51
+ art: ReactNode;
52
+ move: TradingCardMove;
53
+ flavor?: ReactNode;
54
+ facts?: readonly TradingCardFact[];
55
+ /** Collector number, such as "001/001". */
56
+ setNumber?: string;
57
+ /** A small rarity mark printed by the set number. */
58
+ rarity?: ReactNode;
59
+ finish?: TradingCardFinish;
60
+ } & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useId } from "react";
3
+ import { cn } from "../lib/cn.js";
4
+ /**
5
+ * A 63:88 trading card: a bright rim, a name bar with a stage and stat, an art
6
+ * window, one move row that can hold a real form, a flavor line and a footer of
7
+ * facts with a set number and rarity mark. The move body is caller-owned, so a
8
+ * form inside it keeps its own labels, focus and errors.
9
+ */
10
+ export const TradingCard = forwardRef(function TradingCard({ art, className, facts = [], finish = "standard", flavor, move, name, rarity, setNumber, stage, stat, typeLine, ...props }, ref) {
11
+ const nameId = useId();
12
+ return (_jsx("article", { ...props, "aria-labelledby": props["aria-labelledby"] ?? nameId, className: cn("caps-trading-card", className), "data-finish": finish, ref: ref, children: _jsxs("div", { className: "caps-trading-card-face", children: [_jsxs("header", { className: "caps-trading-card-name-bar", children: [stage ? (_jsx("span", { className: "caps-trading-card-stage", children: stage })) : null, _jsx("h2", { className: "caps-trading-card-name", id: nameId, children: name }), stat ? (_jsx("span", { className: "caps-trading-card-stat", children: stat })) : null] }), _jsx("div", { className: "caps-trading-card-window", children: art }), typeLine ? (_jsx("p", { className: "caps-trading-card-type", children: typeLine })) : null, _jsxs("section", { className: "caps-trading-card-move", children: [_jsxs("div", { className: "caps-trading-card-move-line", children: [move.cost ? (_jsx("span", { "aria-hidden": "true", className: "caps-trading-card-cost", children: move.cost })) : null, _jsx("h3", { className: "caps-trading-card-move-name", children: move.name }), move.value ? (_jsx("span", { className: "caps-trading-card-move-value", children: move.value })) : null] }), move.children ? (_jsx("div", { className: "caps-trading-card-move-body", children: move.children })) : null] }), flavor ? _jsx("p", { className: "caps-trading-card-flavor", children: flavor }) : null, facts.length > 0 || setNumber || rarity ? (_jsxs("footer", { className: "caps-trading-card-footer", children: [facts.length > 0 ? (_jsx("dl", { className: "caps-trading-card-facts", children: facts.map((fact) => (_jsxs("div", { children: [_jsx("dt", { children: fact.label }), _jsx("dd", { children: fact.value })] }, fact.label))) })) : null, setNumber || rarity ? (_jsxs("p", { className: "caps-trading-card-collector", children: [setNumber ? _jsx("span", { children: setNumber }) : null, rarity ? (_jsx("span", { className: "caps-trading-card-rarity", children: rarity })) : null] })) : null] })) : null] }) }));
13
+ });
@@ -0,0 +1,52 @@
1
+ import { type ReactNode } from "react";
2
+ import { type ButtonProps } from "./button.js";
3
+ /** Props accepted by Fuse. */
4
+ export type FuseProps = {
5
+ /** How long the fuse burns, in milliseconds: a decision window, not motion. */
6
+ duration: number;
7
+ /** Hold the burn, for example while the pointer rests on the action. */
8
+ paused?: boolean;
9
+ /** Called once when the fuse has burnt down. */
10
+ onBurnt: () => void;
11
+ className?: string;
12
+ };
13
+ /**
14
+ * A hairline that burns down over its duration, then calls `onBurnt`. Its
15
+ * thickness is the theme's `--stipe-motion-fuse` (0 hides it but the window
16
+ * still runs). Under reduced motion it ticks down once a second instead of
17
+ * burning smoothly.
18
+ */
19
+ export declare function Fuse({ duration, paused, onBurnt, className, }: FuseProps): import("react/jsx-runtime").JSX.Element;
20
+ /** Props accepted by UndoAction. */
21
+ export type UndoActionProps = {
22
+ /** The action's label, such as "Stop". */
23
+ children: ReactNode;
24
+ /** Runs when the undo window closes without an undo: the action happens then. */
25
+ onCommit: () => void;
26
+ /** Spoken when the action is armed, such as "Port 5173 stops in 5 seconds". */
27
+ armedAnnouncement: string;
28
+ /** Spoken after an undo, such as "Port 5173 kept open". */
29
+ undoneAnnouncement: string;
30
+ undoLabel?: ReactNode;
31
+ /** The undo window in milliseconds. */
32
+ undoMs?: number;
33
+ } & Omit<ButtonProps, "children" | "onClick" | "result" | "resultLabel">;
34
+ /**
35
+ * A destructive action that waits for its undo window instead of asking
36
+ * first. Pressing it turns the same button into Undo with a fuse burning along
37
+ * its edge; Undo or Escape cancels, and the action commits when the fuse runs
38
+ * out. Resting the pointer on it holds the fuse.
39
+ */
40
+ export declare const UndoAction: import("react").ForwardRefExoticComponent<{
41
+ /** The action's label, such as "Stop". */
42
+ children: ReactNode;
43
+ /** Runs when the undo window closes without an undo: the action happens then. */
44
+ onCommit: () => void;
45
+ /** Spoken when the action is armed, such as "Port 5173 stops in 5 seconds". */
46
+ armedAnnouncement: string;
47
+ /** Spoken after an undo, such as "Port 5173 kept open". */
48
+ undoneAnnouncement: string;
49
+ undoLabel?: ReactNode;
50
+ /** The undo window in milliseconds. */
51
+ undoMs?: number;
52
+ } & Omit<ButtonProps, "children" | "onClick" | "result" | "resultLabel"> & import("react").RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,100 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useId, useLayoutEffect, useRef, useState, } from "react";
3
+ import { cn } from "../lib/cn.js";
4
+ import { canAnimate, motionEasing, readMotion } from "../lib/motion.js";
5
+ import { Button } from "./button.js";
6
+ import { VisuallyHidden } from "./visually-hidden.js";
7
+ /**
8
+ * A hairline that burns down over its duration, then calls `onBurnt`. Its
9
+ * thickness is the theme's `--stipe-motion-fuse` (0 hides it but the window
10
+ * still runs). Under reduced motion it ticks down once a second instead of
11
+ * burning smoothly.
12
+ */
13
+ export function Fuse({ duration, paused = false, onBurnt, className, }) {
14
+ const node = useRef(null);
15
+ const burn = useRef(null);
16
+ const burnt = useRef(onBurnt);
17
+ useEffect(() => {
18
+ burnt.current = onBurnt;
19
+ }, [onBurnt]);
20
+ useLayoutEffect(() => {
21
+ const element = node.current;
22
+ if (!element)
23
+ return;
24
+ if (!canAnimate(element)) {
25
+ const timer = setTimeout(() => {
26
+ burnt.current();
27
+ }, duration);
28
+ return () => {
29
+ clearTimeout(timer);
30
+ };
31
+ }
32
+ const motion = readMotion(element);
33
+ const seconds = Math.max(1, Math.round(duration / 1000));
34
+ const animation = element.animate([{ transform: "scaleX(1)" }, { transform: "scaleX(0)" }], {
35
+ duration,
36
+ easing: motion.reduced
37
+ ? `steps(${String(seconds)}, end)`
38
+ : motionEasing(motion, "linear"),
39
+ fill: "forwards",
40
+ });
41
+ animation.addEventListener("finish", () => {
42
+ burnt.current();
43
+ });
44
+ burn.current = animation;
45
+ return () => {
46
+ animation.cancel();
47
+ burn.current = null;
48
+ };
49
+ }, [duration]);
50
+ useEffect(() => {
51
+ const animation = burn.current;
52
+ if (!animation)
53
+ return;
54
+ if (paused)
55
+ animation.pause();
56
+ else if (animation.playState === "paused")
57
+ animation.play();
58
+ }, [paused]);
59
+ return (_jsx("span", { ref: node, "aria-hidden": "true", className: cn("caps-fuse", className) }));
60
+ }
61
+ /**
62
+ * A destructive action that waits for its undo window instead of asking
63
+ * first. Pressing it turns the same button into Undo with a fuse burning along
64
+ * its edge; Undo or Escape cancels, and the action commits when the fuse runs
65
+ * out. Resting the pointer on it holds the fuse.
66
+ */
67
+ export const UndoAction = forwardRef(function UndoAction({ children, onCommit, armedAnnouncement, undoneAnnouncement, undoLabel = "Undo", undoMs = 5000, className, onKeyDown, onPointerEnter, onPointerLeave, ...props }, ref) {
68
+ const [armed, setArmed] = useState(false);
69
+ const [held, setHeld] = useState(false);
70
+ const [spoken, setSpoken] = useState("");
71
+ const hint = useId();
72
+ const undo = () => {
73
+ setArmed(false);
74
+ setSpoken(undoneAnnouncement);
75
+ };
76
+ return (_jsxs(_Fragment, { children: [_jsxs(Button, { ...props, ref: ref, "aria-label": armed ? undefined : props["aria-label"], "aria-labelledby": armed ? undefined : props["aria-labelledby"], "aria-describedby": armed ? hint : props["aria-describedby"], className: cn("caps-undo-action", className), "data-armed": armed ? "" : undefined, onClick: () => {
77
+ if (armed) {
78
+ undo();
79
+ return;
80
+ }
81
+ setArmed(true);
82
+ setSpoken(armedAnnouncement);
83
+ }, onKeyDown: (event) => {
84
+ onKeyDown?.(event);
85
+ if (armed && event.key === "Escape") {
86
+ event.preventDefault();
87
+ undo();
88
+ }
89
+ }, onPointerEnter: (event) => {
90
+ onPointerEnter?.(event);
91
+ setHeld(true);
92
+ }, onPointerLeave: (event) => {
93
+ onPointerLeave?.(event);
94
+ setHeld(false);
95
+ }, children: [armed ? undoLabel : children, armed ? (_jsx(Fuse, { duration: undoMs, paused: held, onBurnt: () => {
96
+ setArmed(false);
97
+ setSpoken("");
98
+ onCommit();
99
+ } })) : null] }), _jsx(VisuallyHidden, { id: hint, children: "Press Escape to undo." }), _jsx(VisuallyHidden, { role: "status", children: spoken })] }));
100
+ });
@@ -0,0 +1,21 @@
1
+ import { type ReactNode } from "react";
2
+ /** What an undo toast says and does. */
3
+ export type UndoToastOptions = Readonly<{
4
+ title: ReactNode;
5
+ description?: ReactNode;
6
+ /** Runs when the toast's fuse burns out: the action happens then. */
7
+ onCommit: () => void;
8
+ /** Runs when the person undoes, by the button or Escape. */
9
+ onUndo?: () => void;
10
+ undoLabel?: string;
11
+ /** The undo window in milliseconds. */
12
+ undoMs?: number;
13
+ /** The Toaster to show it on, when a page has more than one. */
14
+ toasterId?: string;
15
+ }>;
16
+ /**
17
+ * Show a done-and-undoable toast: the action is deferred while a fuse burns
18
+ * along the toast's edge, Undo or Escape cancels it, and resting on the toast
19
+ * holds the fuse. Returns the toast id.
20
+ */
21
+ export declare function toastUndo(options: UndoToastOptions): string | number;
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { toast } from "sonner";
4
+ import { Alert } from "./alert.js";
5
+ import { Button } from "./button.js";
6
+ import { Fuse } from "./undo-action.js";
7
+ function UndoToast({ dismiss, options, }) {
8
+ const [held, setHeld] = useState(false);
9
+ const [settled, setSettled] = useState(false);
10
+ const undo = () => {
11
+ if (settled)
12
+ return;
13
+ setSettled(true);
14
+ options.onUndo?.();
15
+ dismiss();
16
+ };
17
+ useEffect(() => {
18
+ const onKey = (event) => {
19
+ if (event.key !== "Escape" || settled)
20
+ return;
21
+ setSettled(true);
22
+ options.onUndo?.();
23
+ dismiss();
24
+ };
25
+ globalThis.addEventListener("keydown", onKey);
26
+ return () => {
27
+ globalThis.removeEventListener("keydown", onKey);
28
+ };
29
+ }, [settled, options, dismiss]);
30
+ return (_jsxs("div", { className: "caps-undo-toast", onPointerEnter: () => {
31
+ setHeld(true);
32
+ }, onPointerLeave: () => {
33
+ setHeld(false);
34
+ }, onFocus: () => {
35
+ setHeld(true);
36
+ }, onBlur: () => {
37
+ setHeld(false);
38
+ }, children: [_jsx(Alert, { title: options.title, description: options.description, tone: "info", action: _jsx(Button, { size: "sm", variant: "outline", onClick: undo, children: options.undoLabel ?? "Undo" }) }), _jsx(Fuse, { duration: options.undoMs ?? 5000, paused: held, onBurnt: () => {
39
+ if (settled)
40
+ return;
41
+ setSettled(true);
42
+ options.onCommit();
43
+ dismiss();
44
+ } })] }));
45
+ }
46
+ /**
47
+ * Show a done-and-undoable toast: the action is deferred while a fuse burns
48
+ * along the toast's edge, Undo or Escape cancels it, and resting on the toast
49
+ * holds the fuse. Returns the toast id.
50
+ */
51
+ export function toastUndo(options) {
52
+ const settings = { duration: Infinity };
53
+ if (options.toasterId !== undefined)
54
+ settings.toasterId = options.toasterId;
55
+ return toast.custom((id) => (_jsx(UndoToast, { options: options, dismiss: () => {
56
+ toast.dismiss(id);
57
+ } })), settings);
58
+ }
@@ -0,0 +1,9 @@
1
+ import { type HTMLAttributes } from "react";
2
+ /** Props accepted by VisuallyHidden. */
3
+ export type VisuallyHiddenProps = {
4
+ asChild?: boolean;
5
+ } & HTMLAttributes<HTMLElement>;
6
+ /** Content visually hidden while remaining available to assistive technology. */
7
+ export declare const VisuallyHidden: import("react").ForwardRefExoticComponent<{
8
+ asChild?: boolean;
9
+ } & HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { forwardRef } from "react";
4
+ import { cn } from "../lib/cn.js";
5
+ /** Content visually hidden while remaining available to assistive technology. */
6
+ export const VisuallyHidden = forwardRef(function VisuallyHidden({ asChild = false, className, ...props }, ref) {
7
+ const classes = cn("absolute h-px w-px overflow-hidden whitespace-nowrap border-0 p-0 [clip:rect(0,0,0,0)]", className);
8
+ if (asChild)
9
+ return _jsx(Slot, { ...props, className: classes, ref: ref });
10
+ return _jsx("span", { ...props, className: classes, ref: ref });
11
+ });
@@ -0,0 +1,65 @@
1
+ import { type ButtonHTMLAttributes, type HTMLAttributes, type ReactNode } from "react";
2
+ /** Window presentation only. The host owns geometry, focus order and lifecycle. */
3
+ export type WindowFrameProps = HTMLAttributes<HTMLElement> & {
4
+ active?: boolean;
5
+ floating?: boolean;
6
+ /** Shrink a floating panel to its contents, up to the host's max-height. */
7
+ fitContent?: boolean;
8
+ };
9
+ /** A clipped, rounded shell for either a tiled or floating application. */
10
+ export declare const WindowFrame: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
11
+ active?: boolean;
12
+ floating?: boolean;
13
+ /** Shrink a floating panel to its contents, up to the host's max-height. */
14
+ fitContent?: boolean;
15
+ } & import("react").RefAttributes<HTMLElement>>;
16
+ /** Decorative snap destination. Geometry and visibility belong to the layout owner. */
17
+ export declare function WindowSnapPreview({ className, ...props }: HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
18
+ /** A host-owned request to go back inside the window's content. */
19
+ export type WindowBackAction = {
20
+ /** Accessible name, e.g. "Back in Games". */
21
+ label: string;
22
+ /** Request going back; the host owns the history and the outcome. */
23
+ onBack: () => void;
24
+ /** Tooltip text, e.g. the keyboard route to the same action. */
25
+ hint?: string;
26
+ };
27
+ /** Supply handleProps only when the title is an interactive layout handle. */
28
+ export type WindowHeaderProps = Omit<HTMLAttributes<HTMLElement>, "title" | "children"> & {
29
+ title: string;
30
+ /** Where the content is now, shown after the title and truncated first. */
31
+ subtitle?: string;
32
+ icon?: ReactNode;
33
+ actions?: ReactNode;
34
+ /** Present only while there is somewhere to go back to. */
35
+ back?: WindowBackAction;
36
+ /** `compact` is a slim bar for tiled layouts; touch targets keep 44px. */
37
+ density?: "regular" | "compact";
38
+ handleProps?: Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "type">;
39
+ };
40
+ /** The handle, Back and actions are siblings, so presses never start a drag. */
41
+ export declare function WindowHeader({ title, subtitle, icon, actions, back, density, handleProps, className, ...props }: WindowHeaderProps): import("react/jsx-runtime").JSX.Element;
42
+ /** Available callbacks determine available controls; no inert placeholder actions. */
43
+ export type WindowActionsProps = {
44
+ title: string;
45
+ floating?: boolean;
46
+ maximized?: boolean;
47
+ /** Request making this window the main tiled window. */
48
+ onPromote?: () => void;
49
+ /** Request switching between floating and tiled placement. */
50
+ onToggleFloating?: () => void;
51
+ /** Request toggling maximized presentation. */
52
+ onToggleMaximize?: () => void;
53
+ /** Request minimizing; the caller owns window visibility. */
54
+ onMinimize?: () => void;
55
+ /** Request closing; the caller owns disposal and removal. */
56
+ onClose?: () => void;
57
+ /** Select a compact game panel for reading on a narrow screen. */
58
+ onSelect?: () => void;
59
+ };
60
+ /** Consistent icons, ordering and accessible names for host-owned commands. */
61
+ export declare function WindowActions({ title, floating, maximized, onPromote, onToggleFloating, onToggleMaximize, onMinimize, onClose, onSelect, }: WindowActionsProps): import("react/jsx-runtime").JSX.Element;
62
+ /** The scrolling region stays inside the shell, beneath a stationary title bar. */
63
+ export declare const WindowBody: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
64
+ /** Reading rhythm for compact game-window blocks and action keys. */
65
+ export declare const GameWindowContent: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { ArrowLeft, ArrowUpRight, Columns2, Maximize2, Minimize2, Minus, PanelsTopLeft, X, } from "lucide-react";
3
+ import { forwardRef, } from "react";
4
+ import { cn } from "../lib/cn.js";
5
+ import { IconButton } from "./icon-button.js";
6
+ /** A clipped, rounded shell for either a tiled or floating application. */
7
+ export const WindowFrame = forwardRef(function WindowFrame({ active = false, floating = false, fitContent = false, className, ...props }, ref) {
8
+ return (_jsx("section", { ...props, ref: ref, className: cn("caps-window", className), "data-active": active, "data-floating": floating, "data-fit-content": fitContent }));
9
+ });
10
+ /** Decorative snap destination. Geometry and visibility belong to the layout owner. */
11
+ export function WindowSnapPreview({ className, ...props }) {
12
+ return (_jsx("div", { ...props, "aria-hidden": "true", className: cn("caps-window-snap-preview", className) }));
13
+ }
14
+ /** The handle, Back and actions are siblings, so presses never start a drag. */
15
+ export function WindowHeader({ title, subtitle, icon, actions, back, density = "regular", handleProps, className, ...props }) {
16
+ const label = subtitle ? `${title} · ${subtitle}` : title;
17
+ const content = (_jsxs(_Fragment, { children: [icon && (_jsx("span", { className: "caps-window-icon", "aria-hidden": "true", children: icon })), _jsx("span", { className: "caps-window-name", children: title }), subtitle && (_jsxs("span", { className: "caps-window-subtitle", children: [_jsx("span", { "aria-hidden": "true", children: "\u00B7" }), " ", subtitle] }))] }));
18
+ return (_jsxs("header", { ...props, className: cn("caps-window-header", className), "data-density": density, children: [back && (_jsx(IconButton, { className: "caps-window-back", "aria-label": back.label, title: back.hint ?? back.label, icon: _jsx(ArrowLeft, {}), onClick: back.onBack })), handleProps ? (_jsx("button", { ...handleProps, type: "button", "data-caps-window-handle": true, className: cn("caps-window-title", handleProps.className), title: label, children: content })) : (_jsx("div", { className: "caps-window-title", title: label, children: content })), actions] }));
19
+ }
20
+ /** Consistent icons, ordering and accessible names for host-owned commands. */
21
+ export function WindowActions({ title, floating = false, maximized = false, onPromote, onToggleFloating, onToggleMaximize, onMinimize, onClose, onSelect, }) {
22
+ return (_jsxs("div", { className: "caps-window-actions", role: "group", "aria-label": `${title} window actions`, children: [onSelect && (_jsx(IconButton, { "aria-label": `Show ${title}`, title: `Show ${title}`, icon: _jsx(Maximize2, {}), onClick: onSelect })), onPromote && (_jsx(IconButton, { "aria-label": `Make ${title} main`, title: "Make main", icon: _jsx(ArrowUpRight, {}), onClick: onPromote })), onToggleFloating && (_jsx(IconButton, { "aria-label": `${floating ? "Tile" : "Float"} ${title}`, title: floating ? "Tile" : "Float", icon: floating ? _jsx(Columns2, {}) : _jsx(PanelsTopLeft, {}), onClick: onToggleFloating })), onToggleMaximize && (_jsx(IconButton, { "aria-label": `${maximized ? "Restore" : "Zoom"} ${title}`, title: maximized ? "Restore" : "Zoom", icon: maximized ? _jsx(Minimize2, {}) : _jsx(Maximize2, {}), onClick: onToggleMaximize })), onMinimize && (_jsx(IconButton, { "aria-label": `Minimize ${title}`, title: "Minimize", icon: _jsx(Minus, {}), onClick: onMinimize })), onClose && (_jsx(IconButton, { "aria-label": `Close ${title}`, title: "Close", tone: "destructive", icon: _jsx(X, {}), onClick: onClose }))] }));
23
+ }
24
+ /** The scrolling region stays inside the shell, beneath a stationary title bar. */
25
+ export const WindowBody = forwardRef(function WindowBody({ className, ...props }, ref) {
26
+ return (_jsx("div", { ...props, ref: ref, className: cn("caps-window-body", className) }));
27
+ });
28
+ /** Reading rhythm for compact game-window blocks and action keys. */
29
+ export const GameWindowContent = forwardRef(function GameWindowContent({ className, ...props }, ref) {
30
+ return (_jsx("div", { ...props, ref: ref, className: cn("caps-game-window-content", className) }));
31
+ });
@@ -0,0 +1,17 @@
1
+ import { type ReactNode } from "react";
2
+ /** A named step. Values and validation remain in the caller's form. */
3
+ export type WizardStep = {
4
+ id: string;
5
+ title: string;
6
+ content: ReactNode;
7
+ };
8
+ /** Controlled step presentation, composable with one TanStack Form across steps. */
9
+ export declare function Wizard({ steps, current, onStepChange, disabled, nextDisabled, actions, }: {
10
+ steps: readonly WizardStep[];
11
+ current: string;
12
+ onStepChange: (id: string) => void;
13
+ disabled?: boolean;
14
+ /** Validation may block advancing without preventing edits to previous steps. */
15
+ nextDisabled?: boolean;
16
+ actions?: ReactNode;
17
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useId } from "react";
3
+ import { Button } from "./button.js";
4
+ /** Controlled step presentation, composable with one TanStack Form across steps. */
5
+ export function Wizard({ steps, current, onStepChange, disabled = false, nextDisabled = false, actions, }) {
6
+ const id = useId();
7
+ const index = steps.findIndex((step) => step.id === current);
8
+ return (_jsxs("div", { className: "caps-wizard", children: [_jsx("nav", { "aria-label": "Configuration steps", children: _jsx("ol", { className: "caps-wizard-steps", children: steps.map((step, stepIndex) => (_jsx("li", { children: _jsxs(Button, { id: `${id}-${step.id}-label`, type: "button", size: "sm", variant: current === step.id ? "outline" : "ghost", "aria-current": current === step.id ? "step" : undefined, "aria-controls": `${id}-${step.id}`, disabled: disabled, onClick: () => {
9
+ onStepChange(step.id);
10
+ }, children: [_jsxs("span", { "aria-hidden": "true", children: [stepIndex + 1, "."] }), " ", step.title] }) }, step.id))) }) }), steps.map((step) => (_jsx("section", { id: `${id}-${step.id}`, "aria-labelledby": `${id}-${step.id}-label`, hidden: current !== step.id, children: step.content }, step.id))), _jsxs("div", { className: "caps-wizard-actions", children: [_jsx(Button, { type: "button", size: "sm", variant: "ghost", disabled: disabled || index <= 0, onClick: () => {
11
+ const previous = steps[index - 1];
12
+ if (previous)
13
+ onStepChange(previous.id);
14
+ }, children: "Back" }), index < steps.length - 1 ? (_jsx(Button, { type: "button", size: "sm", disabled: disabled || nextDisabled, onClick: () => {
15
+ const next = steps[index + 1];
16
+ if (next)
17
+ onStepChange(next.id);
18
+ }, children: "Next" })) : (actions)] })] }));
19
+ }
@@ -0,0 +1,8 @@
1
+ /** Show one face of a server-rendered CigaretteCard. */
2
+ export declare function setCigaretteCardFlipped(card: HTMLElement, flipped: boolean): void;
3
+ /**
4
+ * Flip server-rendered CigaretteCards on click, tap, Enter or Space. The card
5
+ * is a native button, so the keyboard reaches it as a click; this only
6
+ * toggles the pressed state. Returns a cleanup that removes the listener.
7
+ */
8
+ export declare function enhanceCigaretteCards(root?: Document | HTMLElement): () => void;