makersclaw 0.8.0 → 0.8.2

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 (401) hide show
  1. package/README.md +9 -3
  2. package/package.json +1 -1
  3. package/r/activity-log.json +52 -0
  4. package/r/agent-changes.json +51 -0
  5. package/r/agent-chat.json +53 -0
  6. package/r/agent-column.json +85 -0
  7. package/r/agent-dock.json +57 -0
  8. package/r/agent-kit.json +49 -0
  9. package/r/agent-marks.json +49 -0
  10. package/r/agent-pane.json +93 -0
  11. package/r/ai-action.json +56 -0
  12. package/r/annotate.json +3 -3
  13. package/r/approval-request.json +2 -2
  14. package/r/approval.json +54 -0
  15. package/r/ask-bar.json +50 -0
  16. package/r/audio-player.json +2 -2
  17. package/r/auth-form.json +2 -2
  18. package/r/automation-editor.json +66 -0
  19. package/r/automation-list.json +57 -0
  20. package/r/automation-model.json +118 -0
  21. package/r/automations-screen.json +71 -0
  22. package/r/board.json +2 -2
  23. package/r/calendar-view.json +3 -3
  24. package/r/cart.json +2 -2
  25. package/r/chart.json +2 -2
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +2 -2
  28. package/r/code-editor.json +2 -2
  29. package/r/comment-box.json +3 -3
  30. package/r/connect-card.json +51 -0
  31. package/r/contact-section.json +2 -2
  32. package/r/core.json +13 -7
  33. package/r/cost.json +51 -0
  34. package/r/csv-import.json +3 -3
  35. package/r/data-picker.json +60 -0
  36. package/r/data-table.json +2 -2
  37. package/r/diagram.json +2 -2
  38. package/r/doc-editor.json +2 -2
  39. package/r/doc-page.json +3 -3
  40. package/r/email-render.json +2 -2
  41. package/r/faq.json +2 -2
  42. package/r/file-upload.json +2 -2
  43. package/r/first-run.json +63 -0
  44. package/r/fix-note.json +57 -0
  45. package/r/flow-canvas.json +2 -2
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +2 -2
  48. package/r/gantt.json +3 -3
  49. package/r/job-panel.json +2 -2
  50. package/r/json-editor.json +3 -3
  51. package/r/library-shelf.json +56 -0
  52. package/r/map.json +2 -2
  53. package/r/margin-notes.json +67 -0
  54. package/r/menubar.json +2 -2
  55. package/r/mind-map.json +3 -3
  56. package/r/navigation-menu.json +2 -2
  57. package/r/needs-you.json +55 -0
  58. package/r/order-detail.json +2 -2
  59. package/r/org-chart.json +3 -3
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +2 -2
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +2 -2
  65. package/r/product-detail.json +2 -2
  66. package/r/product-grid.json +3 -3
  67. package/r/record-form.json +2 -2
  68. package/r/record-grid.json +52 -0
  69. package/r/record-notes.json +4 -4
  70. package/r/registry.json +4086 -1512
  71. package/r/run-history.json +52 -0
  72. package/r/run-view.json +80 -0
  73. package/r/schedule-card.json +54 -0
  74. package/r/schedule-engine.json +79 -0
  75. package/r/schedule-gantt.json +83 -0
  76. package/r/schedule-ruler.json +64 -0
  77. package/r/search-dialog.json +2 -2
  78. package/r/settings-list.json +2 -2
  79. package/r/setup-checklist.json +2 -2
  80. package/r/share-dialog.json +2 -2
  81. package/r/sidebar.json +2 -2
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +2 -2
  84. package/r/source-receipt.json +52 -0
  85. package/r/spreadsheet.json +3 -3
  86. package/r/stat-cards.json +3 -3
  87. package/r/step-picker.json +53 -0
  88. package/r/step-settings.json +72 -0
  89. package/r/suggestion.json +58 -0
  90. package/r/sum-bar.json +64 -0
  91. package/r/task-list.json +3 -3
  92. package/r/task-model.json +2 -2
  93. package/r/testimonials.json +2 -2
  94. package/r/tier-map.json +67 -0
  95. package/r/time-grid.json +73 -0
  96. package/r/time-strip.json +64 -0
  97. package/r/top-bar.json +66 -0
  98. package/r/transaction-list.json +2 -2
  99. package/r/trigger-picker.json +61 -0
  100. package/r/whiteboard.json +3 -3
  101. package/r/workflow-view.json +55 -0
  102. package/registry/blocks/activity-log/README.md +112 -0
  103. package/registry/blocks/activity-log/activity-log.jsx +351 -0
  104. package/registry/blocks/activity-log/block.json +33 -0
  105. package/registry/blocks/activity-log/demo.jsx +48 -0
  106. package/registry/blocks/activity-log/index.js +4 -0
  107. package/registry/blocks/agent-changes/README.md +94 -0
  108. package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
  109. package/registry/blocks/agent-changes/block.json +28 -0
  110. package/registry/blocks/agent-changes/demo.jsx +39 -0
  111. package/registry/blocks/agent-changes/index.js +3 -0
  112. package/registry/blocks/agent-chat/README.md +145 -0
  113. package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
  114. package/registry/blocks/agent-chat/block.json +30 -0
  115. package/registry/blocks/agent-chat/demo.jsx +165 -0
  116. package/registry/blocks/agent-chat/index.js +3 -0
  117. package/registry/blocks/agent-column/README.md +197 -0
  118. package/registry/blocks/agent-column/agent-column.jsx +492 -0
  119. package/registry/blocks/agent-column/block.json +67 -0
  120. package/registry/blocks/agent-column/column-picker.jsx +163 -0
  121. package/registry/blocks/agent-column/demo.jsx +50 -0
  122. package/registry/blocks/agent-column/index.js +7 -0
  123. package/registry/blocks/agent-column/model.js +164 -0
  124. package/registry/blocks/agent-column/receipt.jsx +483 -0
  125. package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
  126. package/registry/blocks/agent-dock/README.md +210 -0
  127. package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
  128. package/registry/blocks/agent-dock/block.json +47 -0
  129. package/registry/blocks/agent-dock/demo.jsx +153 -0
  130. package/registry/blocks/agent-dock/dock-model.js +118 -0
  131. package/registry/blocks/agent-dock/index.js +5 -0
  132. package/registry/blocks/agent-kit/README.md +73 -0
  133. package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
  134. package/registry/blocks/agent-kit/block.json +10 -0
  135. package/registry/blocks/agent-kit/demo.jsx +35 -0
  136. package/registry/blocks/agent-kit/index.js +3 -0
  137. package/registry/blocks/agent-marks/README.md +80 -0
  138. package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
  139. package/registry/blocks/agent-marks/block.json +27 -0
  140. package/registry/blocks/agent-marks/demo.jsx +49 -0
  141. package/registry/blocks/agent-marks/index.js +3 -0
  142. package/registry/blocks/agent-pane/README.md +234 -0
  143. package/registry/blocks/agent-pane/agent-pane.jsx +246 -0
  144. package/registry/blocks/agent-pane/block.json +41 -0
  145. package/registry/blocks/agent-pane/composer.jsx +6 -0
  146. package/registry/blocks/agent-pane/demo.jsx +233 -0
  147. package/registry/blocks/agent-pane/dock-context.js +10 -0
  148. package/registry/blocks/agent-pane/index.js +4 -0
  149. package/registry/blocks/agent-pane/prose.jsx +84 -0
  150. package/registry/blocks/agent-pane/questions.jsx +134 -0
  151. package/registry/blocks/agent-pane/transcript.jsx +268 -0
  152. package/registry/blocks/agent-pane/work.jsx +368 -0
  153. package/registry/blocks/ai-action/README.md +94 -0
  154. package/registry/blocks/ai-action/ai-action.jsx +188 -0
  155. package/registry/blocks/ai-action/block.json +34 -0
  156. package/registry/blocks/ai-action/demo.jsx +93 -0
  157. package/registry/blocks/ai-action/index.js +3 -0
  158. package/registry/blocks/approval/README.md +145 -0
  159. package/registry/blocks/approval/approval.jsx +163 -0
  160. package/registry/blocks/approval/block.json +31 -0
  161. package/registry/blocks/approval/demo.jsx +121 -0
  162. package/registry/blocks/approval/index.js +3 -0
  163. package/registry/blocks/ask-bar/README.md +105 -0
  164. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  165. package/registry/blocks/ask-bar/block.json +26 -0
  166. package/registry/blocks/ask-bar/demo.jsx +78 -0
  167. package/registry/blocks/ask-bar/index.js +3 -0
  168. package/registry/blocks/automation-editor/README.md +291 -0
  169. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  170. package/registry/blocks/automation-editor/block.json +39 -0
  171. package/registry/blocks/automation-editor/demo.jsx +284 -0
  172. package/registry/blocks/automation-editor/index.js +4 -0
  173. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  174. package/registry/blocks/automation-list/README.md +129 -0
  175. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  176. package/registry/blocks/automation-list/block.json +35 -0
  177. package/registry/blocks/automation-list/demo.jsx +67 -0
  178. package/registry/blocks/automation-list/index.js +3 -0
  179. package/registry/blocks/automation-model/README.md +109 -0
  180. package/registry/blocks/automation-model/block.json +135 -0
  181. package/registry/blocks/automation-model/catalog.js +256 -0
  182. package/registry/blocks/automation-model/check.js +161 -0
  183. package/registry/blocks/automation-model/demo.jsx +42 -0
  184. package/registry/blocks/automation-model/edit.js +262 -0
  185. package/registry/blocks/automation-model/fixes.js +287 -0
  186. package/registry/blocks/automation-model/glyph.jsx +13 -0
  187. package/registry/blocks/automation-model/graph.js +410 -0
  188. package/registry/blocks/automation-model/index.js +33 -0
  189. package/registry/blocks/automation-model/overlay.js +175 -0
  190. package/registry/blocks/automation-model/parts.jsx +94 -0
  191. package/registry/blocks/automation-model/schedule.js +53 -0
  192. package/registry/blocks/automation-model/templates.js +128 -0
  193. package/registry/blocks/automation-model/values.js +29 -0
  194. package/registry/blocks/automation-model/words.js +439 -0
  195. package/registry/blocks/automations-screen/README.md +207 -0
  196. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  197. package/registry/blocks/automations-screen/block.json +47 -0
  198. package/registry/blocks/automations-screen/demo.jsx +364 -0
  199. package/registry/blocks/automations-screen/index.js +4 -0
  200. package/registry/blocks/automations-screen/screen-model.js +129 -0
  201. package/registry/blocks/chat-pane/README.md +143 -0
  202. package/registry/blocks/chat-pane/block.json +48 -0
  203. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  204. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  205. package/registry/blocks/chat-pane/chat-context.js +17 -0
  206. package/registry/blocks/chat-pane/chat-model.js +43 -0
  207. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  208. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  209. package/registry/blocks/chat-pane/demo.jsx +103 -0
  210. package/registry/blocks/chat-pane/index.js +9 -0
  211. package/registry/blocks/connect-card/README.md +99 -0
  212. package/registry/blocks/connect-card/block.json +10 -0
  213. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  214. package/registry/blocks/connect-card/demo.jsx +49 -0
  215. package/registry/blocks/connect-card/index.js +3 -0
  216. package/registry/blocks/cost/README.md +115 -0
  217. package/registry/blocks/cost/block.json +10 -0
  218. package/registry/blocks/cost/cost.jsx +176 -0
  219. package/registry/blocks/cost/demo.jsx +66 -0
  220. package/registry/blocks/cost/index.js +3 -0
  221. package/registry/blocks/data-picker/README.md +81 -0
  222. package/registry/blocks/data-picker/block.json +38 -0
  223. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  224. package/registry/blocks/data-picker/demo.jsx +34 -0
  225. package/registry/blocks/data-picker/fields.js +89 -0
  226. package/registry/blocks/data-picker/index.js +4 -0
  227. package/registry/blocks/data-table/demo.jsx +1 -1
  228. package/registry/blocks/first-run/README.md +118 -0
  229. package/registry/blocks/first-run/block.json +11 -0
  230. package/registry/blocks/first-run/demo.jsx +88 -0
  231. package/registry/blocks/first-run/first-run-model.js +51 -0
  232. package/registry/blocks/first-run/first-run.jsx +156 -0
  233. package/registry/blocks/first-run/index.js +5 -0
  234. package/registry/blocks/first-run/probe-rules.js +26 -0
  235. package/registry/blocks/fix-note/README.md +79 -0
  236. package/registry/blocks/fix-note/block.json +35 -0
  237. package/registry/blocks/fix-note/demo.jsx +30 -0
  238. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  239. package/registry/blocks/fix-note/index.js +3 -0
  240. package/registry/blocks/flow-editor/README.md +108 -0
  241. package/registry/blocks/flow-editor/block.json +44 -0
  242. package/registry/blocks/flow-editor/demo.jsx +115 -0
  243. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  244. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  245. package/registry/blocks/flow-editor/index.js +6 -0
  246. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  247. package/registry/blocks/flow-editor/outline.jsx +134 -0
  248. package/registry/blocks/library-shelf/README.md +117 -0
  249. package/registry/blocks/library-shelf/block.json +28 -0
  250. package/registry/blocks/library-shelf/demo.jsx +68 -0
  251. package/registry/blocks/library-shelf/index.js +3 -0
  252. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  253. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  254. package/registry/blocks/margin-notes/README.md +222 -0
  255. package/registry/blocks/margin-notes/block.json +10 -0
  256. package/registry/blocks/margin-notes/demo.jsx +144 -0
  257. package/registry/blocks/margin-notes/index.js +20 -0
  258. package/registry/blocks/margin-notes/margin-model.js +224 -0
  259. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  260. package/registry/blocks/needs-you/README.md +177 -0
  261. package/registry/blocks/needs-you/block.json +34 -0
  262. package/registry/blocks/needs-you/demo.jsx +143 -0
  263. package/registry/blocks/needs-you/index.js +3 -0
  264. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  265. package/registry/blocks/pace-bar/README.md +230 -0
  266. package/registry/blocks/pace-bar/block.json +10 -0
  267. package/registry/blocks/pace-bar/demo.jsx +255 -0
  268. package/registry/blocks/pace-bar/index.js +22 -0
  269. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  270. package/registry/blocks/pace-bar/pace-model.js +288 -0
  271. package/registry/blocks/record-grid/README.md +100 -0
  272. package/registry/blocks/record-grid/block.json +28 -0
  273. package/registry/blocks/record-grid/demo.jsx +43 -0
  274. package/registry/blocks/record-grid/index.js +3 -0
  275. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  276. package/registry/blocks/run-history/README.md +138 -0
  277. package/registry/blocks/run-history/block.json +10 -0
  278. package/registry/blocks/run-history/demo.jsx +74 -0
  279. package/registry/blocks/run-history/index.js +3 -0
  280. package/registry/blocks/run-history/run-history.jsx +218 -0
  281. package/registry/blocks/run-view/README.md +174 -0
  282. package/registry/blocks/run-view/block.json +50 -0
  283. package/registry/blocks/run-view/demo.jsx +286 -0
  284. package/registry/blocks/run-view/index.js +5 -0
  285. package/registry/blocks/run-view/run-controls.jsx +266 -0
  286. package/registry/blocks/run-view/run-view.jsx +236 -0
  287. package/registry/blocks/run-view/runs-list.jsx +99 -0
  288. package/registry/blocks/schedule-card/README.md +121 -0
  289. package/registry/blocks/schedule-card/block.json +10 -0
  290. package/registry/blocks/schedule-card/demo.jsx +82 -0
  291. package/registry/blocks/schedule-card/index.js +3 -0
  292. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  293. package/registry/blocks/schedule-engine/README.md +137 -0
  294. package/registry/blocks/schedule-engine/block.json +10 -0
  295. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  296. package/registry/blocks/schedule-engine/engine.js +769 -0
  297. package/registry/blocks/schedule-engine/index.js +9 -0
  298. package/registry/blocks/schedule-engine/ops.js +71 -0
  299. package/registry/blocks/schedule-engine/place.js +294 -0
  300. package/registry/blocks/schedule-engine/tree.js +79 -0
  301. package/registry/blocks/schedule-engine/waits.js +80 -0
  302. package/registry/blocks/schedule-gantt/README.md +159 -0
  303. package/registry/blocks/schedule-gantt/block.json +10 -0
  304. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  305. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  306. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  307. package/registry/blocks/schedule-gantt/index.js +26 -0
  308. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  309. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  310. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  311. package/registry/blocks/schedule-ruler/README.md +148 -0
  312. package/registry/blocks/schedule-ruler/block.json +10 -0
  313. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  314. package/registry/blocks/schedule-ruler/index.js +21 -0
  315. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  316. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  317. package/registry/blocks/source-receipt/README.md +97 -0
  318. package/registry/blocks/source-receipt/block.json +30 -0
  319. package/registry/blocks/source-receipt/demo.jsx +71 -0
  320. package/registry/blocks/source-receipt/index.js +3 -0
  321. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  322. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  323. package/registry/blocks/step-picker/README.md +78 -0
  324. package/registry/blocks/step-picker/block.json +31 -0
  325. package/registry/blocks/step-picker/demo.jsx +23 -0
  326. package/registry/blocks/step-picker/index.js +3 -0
  327. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  328. package/registry/blocks/step-settings/README.md +100 -0
  329. package/registry/blocks/step-settings/block.json +44 -0
  330. package/registry/blocks/step-settings/demo.jsx +93 -0
  331. package/registry/blocks/step-settings/fields.jsx +58 -0
  332. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  333. package/registry/blocks/step-settings/index.js +5 -0
  334. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  335. package/registry/blocks/suggestion/README.md +171 -0
  336. package/registry/blocks/suggestion/block.json +40 -0
  337. package/registry/blocks/suggestion/demo.jsx +91 -0
  338. package/registry/blocks/suggestion/index.js +3 -0
  339. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  340. package/registry/blocks/sum-bar/README.md +122 -0
  341. package/registry/blocks/sum-bar/block.json +10 -0
  342. package/registry/blocks/sum-bar/demo.jsx +110 -0
  343. package/registry/blocks/sum-bar/index.js +5 -0
  344. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  345. package/registry/blocks/sum-bar/sum-model.js +126 -0
  346. package/registry/blocks/tier-map/README.md +217 -0
  347. package/registry/blocks/tier-map/block.json +10 -0
  348. package/registry/blocks/tier-map/demo.jsx +222 -0
  349. package/registry/blocks/tier-map/index.js +24 -0
  350. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  351. package/registry/blocks/tier-map/tier-model.js +318 -0
  352. package/registry/blocks/time-grid/README.md +305 -0
  353. package/registry/blocks/time-grid/block.json +10 -0
  354. package/registry/blocks/time-grid/demo.jsx +279 -0
  355. package/registry/blocks/time-grid/grid-model.js +322 -0
  356. package/registry/blocks/time-grid/index.js +25 -0
  357. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  358. package/registry/blocks/time-strip/README.md +141 -0
  359. package/registry/blocks/time-strip/block.json +10 -0
  360. package/registry/blocks/time-strip/demo.jsx +129 -0
  361. package/registry/blocks/time-strip/index.js +19 -0
  362. package/registry/blocks/time-strip/strip-model.js +178 -0
  363. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  364. package/registry/blocks/top-bar/README.md +149 -0
  365. package/registry/blocks/top-bar/block.json +35 -0
  366. package/registry/blocks/top-bar/demo.jsx +78 -0
  367. package/registry/blocks/top-bar/index.js +5 -0
  368. package/registry/blocks/top-bar/probe-rules.js +74 -0
  369. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  370. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  371. package/registry/blocks/trigger-picker/README.md +98 -0
  372. package/registry/blocks/trigger-picker/block.json +38 -0
  373. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  374. package/registry/blocks/trigger-picker/index.js +3 -0
  375. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  376. package/registry/blocks/workflow-view/README.md +123 -0
  377. package/registry/blocks/workflow-view/block.json +10 -0
  378. package/registry/blocks/workflow-view/demo.jsx +90 -0
  379. package/registry/blocks/workflow-view/index.js +3 -0
  380. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  381. package/src/install.mjs +77 -16
  382. package/src/registry.mjs +3 -0
  383. package/templates/next/browser/lib/data.js +6 -1
  384. package/templates/next/files/README.md +627 -24
  385. package/templates/next/files/check/automation-format.ts +2103 -0
  386. package/templates/next/files/check/automation-package.ts +142 -0
  387. package/templates/next/files/check/run.mjs +968 -9
  388. package/templates/next/files/components/ui/field.jsx +17 -4
  389. package/templates/next/files/components/ui/icon.jsx +13 -0
  390. package/templates/next/files/components/ui/index.js +2 -1
  391. package/templates/next/files/components/ui/layout.jsx +77 -2
  392. package/templates/next/files/components/ui/notice.jsx +70 -0
  393. package/templates/next/files/components/ui/page.jsx +124 -0
  394. package/templates/next/files/components/ui/stat.jsx +22 -7
  395. package/templates/next/files/components/ui/toast.jsx +6 -3
  396. package/templates/next/files/lib/automations.js +660 -0
  397. package/templates/next/files/lib/claw.js +241 -5
  398. package/templates/next/files/lib/door.js +92 -0
  399. package/templates/next/files/lib/hooks.js +1677 -8
  400. package/templates/next/files/lib/platform.js +529 -21
  401. package/templates/next/template.json +13 -3
@@ -23,10 +23,14 @@ const CONTROL = `w-full ${BOX}`;
23
23
  const ownWidth = (className) => /(?:^|\s)!?(?:w|size)-/.test(className ?? "");
24
24
 
25
25
  /** Label, control, hint and error in one stack. Pass `id`; the label
26
- * points at it. `error` (a string) marks the control invalid. */
26
+ * points at it. `error` (a string) marks the control invalid.
27
+ * Two Fields side by side in a grid row are stretched to the taller one;
28
+ * `content-start` keeps the shorter one's label and control at the top
29
+ * where they were (without it the grid spread them apart, and Start
30
+ * date's box sat lower than Target date's when only Target had a hint). */
27
31
  export function Field({ id, label, hint, error, required, className, children }) {
28
32
  return (
29
- <div className={cx("grid gap-1.5", className)}>
33
+ <div className={cx("grid content-start gap-1.5", className)}>
30
34
  {label ? (
31
35
  <label htmlFor={id} className="text-sm font-medium text-foreground">
32
36
  {label}
@@ -177,15 +181,24 @@ export function Textarea({ className, invalid, rows = 4, autoGrow = false, minRo
177
181
  * `options` is empty it renders `empty` (a short muted line, or nothing
178
182
  * when `empty` is null) rather than a disabled dropdown. For "pick a
179
183
  * saved record or make a new one" use RecordSwitcher (components/parts).
184
+ * A width in `className` (w-40, w-fit, w-[12rem], size-10) sets the width of
185
+ * the whole control, as it does on an Input (0.8.1).
180
186
  */
181
187
  export function Select({ options, empty = "Nothing to choose yet.", className, invalid, children, ...rest }) {
182
188
  if (options && options.length === 0 && !children) {
183
189
  return empty ? <p className="text-sm text-muted-foreground">{empty}</p> : null;
184
190
  }
191
+ // As Input: a width in className (w-40, w-auto, w-[12rem], size-10) is
192
+ // honoured. The chevron sits on the wrapper, so the width goes to the
193
+ // wrapper and the select fills it; the rest of className stays on the
194
+ // select. Without one it is as wide as its column, as before.
195
+ const tokens = String(className ?? "").split(/\s+/).filter(Boolean);
196
+ const own = tokens.filter((t) => /^!?(?:w|size)-/.test(t));
197
+ const others = tokens.filter((t) => !own.includes(t));
185
198
  return (
186
- <span className="relative block">
199
+ <span className={cx("relative block", own.join(" "))}>
187
200
  <select
188
- className={cx(CONTROL, "appearance-none pr-9", className)}
201
+ className={cx(CONTROL, "appearance-none pr-9", others.join(" "))}
189
202
  aria-invalid={invalid ? true : undefined}
190
203
  {...rest}
191
204
  >
@@ -186,6 +186,19 @@ const PATHS = {
186
186
  "calendar-check": "M3 5h18v16H3zM16 3v4M8 3v4M3 10h18M9 15.5l2 2 4-4",
187
187
  "trash-2": "M3 6h18M8 6V4h8v2m-9 0 1 14h8l1-14M10 11v6M14 11v6",
188
188
  network: "M9 2h6v6H9zM2 16h6v6H2zM16 16h6v6h-6zM12 8v4M5 16v-4h14v4",
189
+ // Automations (flow-editor and the blocks around it): one glyph per kind
190
+ // of step, drawn to the same 24 box. calendar-clock is a schedule's
191
+ // trigger, split a condition's fork, braces a set of values, timer a
192
+ // wait, plug a connected tool, bot the agent, workflow another
193
+ // automation, book-open a read of the company brain.
194
+ "calendar-clock": "M12 21H5V5h14v7M3 10h18M8 3v4M16 3v4M17.5 14a4 4 0 1 0 .01 0M17.5 16v2l1.2.8",
195
+ split: "M3 12h5c3 0 3-6 6-6h6M8 12c3 0 3 6 6 6h6M17 3l3 3-3 3M17 15l3 3-3 3",
196
+ braces: "M8 3H7a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2 2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1M16 3h1a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2 2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-1",
197
+ timer: "M10 2h4M12 8v5l3 2M12 6a8 8 0 1 0 0 16 8 8 0 0 0 0-16Z",
198
+ plug: "M9 2v5M15 2v5M6 7h12v4a6 6 0 0 1-12 0V7ZM12 17v5",
199
+ bot: "M12 3v3M5 8h14v11H5ZM9 13h.01M15 13h.01M2 13v3M22 13v3M9 17h6",
200
+ workflow: "M3 4h7v7H3zM14 13h7v7h-7zM10 7.5h2.5a2 2 0 0 1 2 2V13",
201
+ "book-open": "M12 6c-2-2-5-3-9-3v15c4 0 7 1 9 3 2-2 5-3 9-3V3c-4 0-7 1-9 3ZM12 6v15",
189
202
  };
190
203
 
191
204
  const BRANDS = {
@@ -5,7 +5,7 @@ export { cx } from "./cx";
5
5
  export { Icon, ICON_NAMES } from "./icon";
6
6
  export { Button, IconButton } from "./button";
7
7
  export { Field, Input, TimeInput, Textarea, Select, Switch, Checkbox } from "./field";
8
- export { Card, Notice, Badge, Kicker, Empty } from "./notice";
8
+ export { Card, ActionCard, Notice, Badge, Kicker, Empty } from "./notice";
9
9
  export { Sheet, Confirm } from "./sheet";
10
10
  export { Tabs, TabPanel } from "./tabs";
11
11
  export { Menu, MenuPanel } from "./menu";
@@ -49,6 +49,7 @@ export { Steps } from "./steps";
49
49
  export { Separator, Kbd, KbdGroup, AspectRatio } from "./separator";
50
50
  export { ScrollArea } from "./scroll-area";
51
51
  export { AppLayout, DocumentLayout } from "./layout";
52
+ export { PageLayout } from "./page";
52
53
  export { Slider } from "./slider";
53
54
  export { InputGroup, PasswordInput } from "./input-group";
54
55
  export { Image } from "./image";
@@ -51,8 +51,22 @@ import { Sheet } from "./sheet";
51
51
  // inspectorWidth in px (360; 240 to 560). Builds have needed 300 and 440
52
52
  // inspectorAt md · lg (the default) · xl: the width from which the
53
53
  // inspector sits beside the content
54
+ // inspectorIn window (the default): inspectorAt is the window's
55
+ // width (768 · 1024 · 1280 px) · frame: it is the
56
+ // width of the body between the rail and the dock
57
+ // (42 · 48 · 64 rem), so an agent dock that takes a
58
+ // quarter of the window makes the inspector go under
59
+ // the work when there is no room, not squeeze it
54
60
  // footer under the content, always in view (the save state,
55
61
  // the composer, the commands for what is above)
62
+ // dock a column beside the whole body (rail, content and
63
+ // inspector), under the header, that the app's own
64
+ // block draws: the agent's dock (blocks/agent-dock).
65
+ // It sizes itself, remembers its width and, where the
66
+ // body is too narrow, lays itself over the app as a
67
+ // sheet; the layout only gives it a place in the row
68
+ // and takes no part in its width. Nothing when it is
69
+ // not given
56
70
  // height viewport (the default): the frame is the window's
57
71
  // height · parent: it fills a bounded parent. Nested,
58
72
  // it is parent whatever this says
@@ -108,7 +122,60 @@ const BESIDE = {
108
122
  },
109
123
  };
110
124
 
125
+ // The same classes by the width of the body's own column (a container
126
+ // query on the frame between the rail and the dock), for an app whose dock
127
+ // takes a quarter of the window: md is a body 42rem wide, lg 48rem, xl 64rem.
128
+ const BESIDE_FRAME = {
129
+ md: {
130
+ main: "@2xl:grid @2xl:grid-cols-[minmax(0,1fr)_var(--app-inspector)] @2xl:grid-rows-[minmax(0,1fr)_auto]",
131
+ flow: "@2xl:contents",
132
+ content: "@2xl:col-start-1 @2xl:row-start-1",
133
+ scrolls: "@2xl:min-h-0 @2xl:overflow-y-auto @2xl:overscroll-contain",
134
+ inspector: "@2xl:col-start-2 @2xl:row-span-2 @2xl:row-start-1 @2xl:max-h-none @2xl:min-h-0 @2xl:overflow-y-auto @2xl:border-l @2xl:border-t-0",
135
+ footer: "@2xl:col-start-1 @2xl:row-start-2",
136
+ },
137
+ lg: {
138
+ main: "@3xl:grid @3xl:grid-cols-[minmax(0,1fr)_var(--app-inspector)] @3xl:grid-rows-[minmax(0,1fr)_auto]",
139
+ flow: "@3xl:contents",
140
+ content: "@3xl:col-start-1 @3xl:row-start-1",
141
+ scrolls: "@3xl:min-h-0 @3xl:overflow-y-auto @3xl:overscroll-contain",
142
+ inspector: "@3xl:col-start-2 @3xl:row-span-2 @3xl:row-start-1 @3xl:max-h-none @3xl:min-h-0 @3xl:overflow-y-auto @3xl:border-l @3xl:border-t-0",
143
+ footer: "@3xl:col-start-1 @3xl:row-start-2",
144
+ },
145
+ xl: {
146
+ main: "@5xl:grid @5xl:grid-cols-[minmax(0,1fr)_var(--app-inspector)] @5xl:grid-rows-[minmax(0,1fr)_auto]",
147
+ flow: "@5xl:contents",
148
+ content: "@5xl:col-start-1 @5xl:row-start-1",
149
+ scrolls: "@5xl:min-h-0 @5xl:overflow-y-auto @5xl:overscroll-contain",
150
+ inspector: "@5xl:col-start-2 @5xl:row-span-2 @5xl:row-start-1 @5xl:max-h-none @5xl:min-h-0 @5xl:overflow-y-auto @5xl:border-l @5xl:border-t-0",
151
+ footer: "@5xl:col-start-1 @5xl:row-start-2",
152
+ },
153
+ };
154
+
155
+ // inspectorIn="frame": the body's column is the container the BESIDE_FRAME
156
+ // classes answer to. Off, it is nothing: the children, in the same place.
157
+ function FrameBox({ on, children }) {
158
+ if (!on) return children;
159
+ return (
160
+ <div data-layout-frame className={cx("@container flex min-h-0 min-w-0 flex-1 flex-col", LETS_GO)}>
161
+ {children}
162
+ </div>
163
+ );
164
+ }
165
+
111
166
  const REGION = "outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring";
167
+
168
+ // The inspector holds its width and its contents fit it (UI review X4: a
169
+ // shelf's row ran out of the panel and its title was cut at the edge). A
170
+ // grid with no grid-cols-* has one `auto` column, and `auto` grows to its
171
+ // widest child's minimum width, past the panel; the usual inspector is
172
+ // exactly `<div className="grid content-start gap-3 p-4">`. So the panel's
173
+ // own direct children may not grow it (min-w-0), a direct child that is a
174
+ // grid with no columns of its own gets the one column that can shrink
175
+ // (minmax(0,1fr)), and nothing paints past the panel's edge (overflow-x
176
+ // hidden: a wide child wraps or truncates, it does not sideways-scroll).
177
+ const INSPECTOR_FIT =
178
+ "min-w-0 max-w-full overflow-x-hidden [&>*]:min-w-0 [&>.grid:not([class*=grid-cols])]:grid-cols-[minmax(0,1fr)]";
112
179
  const LETS_GO = "print:block print:h-auto print:min-h-0 print:overflow-visible";
113
180
 
114
181
  export function AppLayout({
@@ -125,14 +192,18 @@ export function AppLayout({
125
192
  inspectorLabel = "Details",
126
193
  inspectorWidth,
127
194
  inspectorAt = "lg",
195
+ inspectorIn = "window",
128
196
  footer,
197
+ dock,
129
198
  height = "viewport",
130
199
  className,
131
200
  }) {
132
201
  const nested = useContext(Nested);
133
202
  const bounded = nested || height === "parent";
134
203
  const fill = contentMode === "fill";
135
- const at = BESIDE[inspectorAt] ?? BESIDE.lg;
204
+ const byFrame = inspectorIn === "frame";
205
+ const table = byFrame ? BESIDE_FRAME : BESIDE;
206
+ const at = table[inspectorAt] ?? table.lg;
136
207
  const hasInspector = inspector != null && inspector !== false;
137
208
  const hasNavigation = navigation != null && navigation !== false;
138
209
  const shared = hasInspector && !fill; // below `at`: content and inspector in one scroll region
@@ -197,6 +268,7 @@ export function AppLayout({
197
268
  </div>
198
269
  ) : null}
199
270
 
271
+ <FrameBox on={byFrame && hasInspector}>
200
272
  <div data-layout-main className={cx("flex min-h-0 min-w-0 flex-1 flex-col", hasInspector && at.main, LETS_GO)}>
201
273
  <div
202
274
  ref={flowRef}
@@ -238,7 +310,8 @@ export function AppLayout({
238
310
  aria-label={inspectorLabel}
239
311
  tabIndex={0}
240
312
  className={cx(
241
- "min-w-0 shrink-0 border-t border-border print:hidden",
313
+ "shrink-0 border-t border-border print:hidden",
314
+ INSPECTOR_FIT,
242
315
  REGION,
243
316
  fill && "max-h-[45%] overflow-y-auto overscroll-contain",
244
317
  at.inspector,
@@ -254,6 +327,8 @@ export function AppLayout({
254
327
  </div>
255
328
  ) : null}
256
329
  </div>
330
+ </FrameBox>
331
+ {dock != null && dock !== false ? dock : null}
257
332
  </div>
258
333
  </div>
259
334
  </Nested.Provider>
@@ -53,6 +53,76 @@ export function Card({
53
53
  );
54
54
  }
55
55
 
56
+ const STATUS_ICON = {
57
+ success: { name: "circle-check", box: "text-success" },
58
+ warning: { name: "warning", box: "text-warning" },
59
+ danger: { name: "warning", box: "text-destructive" },
60
+ neutral: { name: "info", box: "text-muted-foreground" },
61
+ };
62
+
63
+ /** A card that is one step the member takes: a title (with an icon), what
64
+ * it does, optionally the state it is in, and ONE action under it.
65
+ * Stacked, always: the status line above a full-width button, so neither
66
+ * squeezes the other and the button's label has the room it needs.
67
+ *
68
+ * Cards in a row are the same height, and their buttons line up (UI
69
+ * review X6). A card stretches to the height of its row, and the status
70
+ * and the action are pinned to the card's bottom: title, words, children,
71
+ * then whatever room is left, then the status, then the button. So in a
72
+ * row of four the buttons sit on one line, however long each card's words
73
+ * are, and a status line in only some of them sits just above its button.
74
+ * It was `self-start` (each card only as tall as its own words) from 0.8.1's
75
+ * first cut: that meant ragged heights and buttons at different heights.
76
+ * The big empty block it was meant to stop came from a squeezed row (check
77
+ * rule 16, squeeze), not from stretching, and it cannot come back here:
78
+ * the spare room is a gap above the footer, never a blank box below it.
79
+ * icon a kit icon name, before the title
80
+ * title the step ("Connect your mailbox")
81
+ * description what it does, in a sentence or two (muted)
82
+ * children anything between the description and the state (a price
83
+ * line, a form, a list of rows)
84
+ * status { tone: success · warning · danger · neutral, children } the
85
+ * state it is in, with its mark, above the action. Say
86
+ * "Connected" only when the thing exists (an account, a file).
87
+ * action the one button (or a link), laid full width below
88
+ * fit true: only as tall as its own words (self-start), for ONE
89
+ * card on its own beside something unrelated. Never for
90
+ * cards in a row: check rule 19 (stretch) refuses a row of
91
+ * ActionCards that sets self-start, or items-start on the row
92
+ * For a card that holds a table or a list, use Card (padding none). For
93
+ * a screen's boxes in general: Card, ActionCard, Notice, never a hand-drawn
94
+ * bordered div. */
95
+ export function ActionCard({ icon, title, description, status, action, className, children, fit = false, as: Tag = "section" }) {
96
+ const mark = status ? (STATUS_ICON[status.tone] ?? STATUS_ICON.neutral) : null;
97
+ return (
98
+ <Tag
99
+ className={cx(
100
+ "flex min-w-0 flex-col gap-2.5 rounded-lg border border-border bg-card p-4 text-sm text-card-foreground",
101
+ fit && "self-start",
102
+ className,
103
+ )}
104
+ >
105
+ <h2 className="flex min-w-0 items-center gap-2 font-semibold leading-tight">
106
+ {icon ? <Icon name={icon} size={16} className="shrink-0 text-muted-foreground" /> : null}
107
+ <span className="min-w-0">{title}</span>
108
+ </h2>
109
+ {description ? <p className="text-muted-foreground">{description}</p> : null}
110
+ {children}
111
+ {status || action ? (
112
+ <div className="mt-auto grid gap-2.5">
113
+ {status ? (
114
+ <div className="flex items-start gap-2 border-t border-border pt-2.5 text-[13px]">
115
+ <Icon name={mark.name} size={14} className={cx("mt-0.5 shrink-0", mark.box)} />
116
+ <div className="min-w-0">{status.children}</div>
117
+ </div>
118
+ ) : null}
119
+ {action ? <div className="grid">{action}</div> : null}
120
+ </div>
121
+ ) : null}
122
+ </Tag>
123
+ );
124
+ }
125
+
56
126
  /** One line the user should read, with an optional action. `tone`
57
127
  * neutral · info · success · warning · danger. Colour is the signal, so
58
128
  * status tones are for status only — never decoration. */
@@ -0,0 +1,124 @@
1
+ "use client";
2
+
3
+ import { cx } from "./cx";
4
+
5
+ // PageLayout — a screen's main area with an optional side column, taking the
6
+ // full height of the content it sits in. The MAIN is the column that scrolls.
7
+ // The SIDE is the fixed one: it holds its place, top to bottom, while the
8
+ // main scrolls, and it is short.
9
+ //
10
+ // Why (UI review X12, 2026-10-12): Project Roadmap's Today ended at 680px in
11
+ // a 1240px window. The screen drew its own two-column grid inside the
12
+ // scrolling content, so it was only as tall as its words: the side column's
13
+ // divider stopped halfway down and the bottom half of the window was empty.
14
+ // Every screen with a side drew that grid by hand. This is the one.
15
+ // `npm run check` (rule 23, page) refuses a hand-drawn main + side with a
16
+ // ruled <aside>.
17
+ //
18
+ // What goes in the side, and what never does (UI review X13, 2026-10-12:
19
+ // Newsletter Engine's first run was a short intro on the left and a long
20
+ // "Name it" form in the right column. "this can only work if one column is
21
+ // fixed, usually the 3rd column, and the middle one is scrolling"): the side
22
+ // is a summary, the next step, a small panel, a few facts, a short list. It
23
+ // never needs a scroll of its own. A form, a paste box, a long list, a
24
+ // shelf of examples belong in the MAIN, where the page scrolls: a step that
25
+ // opens reveals its own card there. The side's own scroll is a last resort
26
+ // for a window shorter than the side (the bar is thin to say so), never how
27
+ // a long thing is meant to be read. `npm run check` (rule 27, sidelong)
28
+ // refuses a side column that holds a form or a long list.
29
+ //
30
+ // It lives INSIDE an AppLayout (the shell or the screen's own): the layout
31
+ // owns the window's height, this fills the content region it is given. Use
32
+ // the AppLayout's `contentMode="fill"` and give its content no padding
33
+ // (omit `contentClassName`): the columns pad themselves, so the divider can
34
+ // run to the edges. In contentMode scroll it fills the same.
35
+ //
36
+ // children the main area
37
+ // side the side column, the FIXED one: short things (a summary, the
38
+ // next step, a record's facts, a small panel). It stays put
39
+ // while the main scrolls; never a long form or a long list.
40
+ // Without it the page is one scrolling column
41
+ // sideWidth px (304; 220 to 560)
42
+ // sideAt md · lg (the default) · xl: the width of THIS page from
43
+ // which the side sits beside the main (42 · 48 · 64 rem). It
44
+ // is the page's own width, not the window's: an open agent
45
+ // dock takes a quarter of the window, and the page must not
46
+ // be squeezed by it. Narrower, the side goes under the main in
47
+ // one scroll, nothing hidden behind a button
48
+ // mainLabel the main area's name for a screen reader ("Content")
49
+ // sideLabel the side's name ("Details")
50
+ // padded default true: p-4 sm:p-6 on the main, p-4 on the side. false
51
+ // for a page that draws its own edges
52
+ // fill true: the main is a flex column, so a child with `flex-1`
53
+ // (a list, a table) grows into the height instead of stopping
54
+ // where its rows end. With the side beside it, or alone; with
55
+ // the side under it (narrow) the page is one scroll and there
56
+ // is no height to grow into
57
+ // className, mainClassName, sideClassName spacing and token backgrounds
58
+ // (bg-muted). Never a height or an overflow: the layout owns those
59
+ const px = (value, fallback, min, max) => {
60
+ const n = Number(value);
61
+ return `${Number.isFinite(n) && n > 0 ? Math.min(max, Math.max(min, Math.round(n))) : fallback}px`;
62
+ };
63
+
64
+ // Tailwind reads class names whole from the source, so every size is written
65
+ // out. md is a page 42rem wide, lg 48rem, xl 64rem (the AppLayout's
66
+ // inspectorIn="frame" sizes).
67
+ const BESIDE = {
68
+ md: {
69
+ grid: "@2xl:grid-cols-[minmax(0,1fr)_var(--page-side)] @2xl:grid-rows-[minmax(0,1fr)] @2xl:overflow-hidden",
70
+ column: "@2xl:min-h-0 @2xl:overflow-y-auto @2xl:overscroll-contain",
71
+ side: "@2xl:border-l @2xl:border-t-0 @2xl:[scrollbar-width:thin]",
72
+ },
73
+ lg: {
74
+ grid: "@3xl:grid-cols-[minmax(0,1fr)_var(--page-side)] @3xl:grid-rows-[minmax(0,1fr)] @3xl:overflow-hidden",
75
+ column: "@3xl:min-h-0 @3xl:overflow-y-auto @3xl:overscroll-contain",
76
+ side: "@3xl:border-l @3xl:border-t-0 @3xl:[scrollbar-width:thin]",
77
+ },
78
+ xl: {
79
+ grid: "@5xl:grid-cols-[minmax(0,1fr)_var(--page-side)] @5xl:grid-rows-[minmax(0,1fr)] @5xl:overflow-hidden",
80
+ column: "@5xl:min-h-0 @5xl:overflow-y-auto @5xl:overscroll-contain",
81
+ side: "@5xl:border-l @5xl:border-t-0 @5xl:[scrollbar-width:thin]",
82
+ },
83
+ };
84
+
85
+ const REGION = "outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring";
86
+ const LETS_GO = "print:block print:h-auto print:min-h-0 print:overflow-visible";
87
+
88
+ export function PageLayout({ children, side, sideWidth, sideAt = "lg", mainLabel = "Content", sideLabel = "Details", padded = true, fill = false, className, mainClassName, sideClassName }) {
89
+ const has = side != null && side !== false;
90
+ const at = BESIDE[sideAt] ?? BESIDE.lg;
91
+ return (
92
+ <div data-page-layout className={cx("@container flex min-h-0 min-w-0 flex-1 flex-col", LETS_GO, className)}>
93
+ <div
94
+ data-page-scroll
95
+ style={{ "--page-side": px(sideWidth, 304, 220, 560) }}
96
+ className={cx(
97
+ "grid min-h-0 min-w-0 flex-1 grid-cols-[minmax(0,1fr)] content-start",
98
+ has ? cx("overflow-y-auto overscroll-contain", at.grid) : "grid-rows-[minmax(0,1fr)] overflow-hidden",
99
+ LETS_GO,
100
+ )}
101
+ >
102
+ <div
103
+ data-page-main
104
+ role="region"
105
+ aria-label={mainLabel}
106
+ tabIndex={0}
107
+ className={cx("min-w-0", REGION, has ? at.column : "min-h-0 overflow-y-auto overscroll-contain", fill && "flex flex-col", padded && "p-4 sm:p-6", LETS_GO, mainClassName)}
108
+ >
109
+ {children}
110
+ </div>
111
+ {has ? (
112
+ <aside
113
+ data-page-side
114
+ aria-label={sideLabel}
115
+ tabIndex={0}
116
+ className={cx("min-w-0 border-t border-border print:hidden", REGION, at.column, at.side, padded && "p-4", sideClassName)}
117
+ >
118
+ {side}
119
+ </aside>
120
+ ) : null}
121
+ </div>
122
+ </div>
123
+ );
124
+ }
@@ -355,6 +355,17 @@ const METER_SIZES = { thin: { track: "h-1", mark: "h-3" }, md: { track: "h-2", m
355
355
  * bar's
356
356
  * center a ring's middle instead of the percent: a string or a node
357
357
  * ("4.2 GB", an Icon); null leaves it empty
358
+ * compact the bar alone (the ring alone, for shape="ring"): no label,
359
+ * no numbers, no caption, no target line, so it fits where
360
+ * words spill: a top bar, a table cell, a card corner. The
361
+ * label and the numbers are not lost: a screen reader hears
362
+ * them as always, and the bar's tooltip (`title`) shows
363
+ * "label: used of limit". Give it its width in className
364
+ * (w-14, w-24); size thin reads best in a top bar. Without
365
+ * compact a Meter draws its label as visible text, which
366
+ * spills in a box under about 8rem (the Newsletter's "15,000
367
+ * cr left" ran into Find, UI review X1; check rule 20,
368
+ * meter, refuses it)
358
369
  */
359
370
  export function Meter({
360
371
  value,
@@ -373,6 +384,7 @@ export function Meter({
373
384
  size = "md",
374
385
  shape = "bar",
375
386
  center,
387
+ compact = false,
376
388
  className,
377
389
  ...rest
378
390
  }) {
@@ -416,21 +428,24 @@ export function Meter({
416
428
  "aria-valuetext": said,
417
429
  };
418
430
 
431
+ // The tooltip of a compact meter: the name, then the numbers a reader hears.
432
+ const tip = compact ? (label ? `${label}: ${said}` : said) : undefined;
433
+
419
434
  if (shape === "ring") {
420
435
  return (
421
436
  <MeterRing
422
- {...{ pct, over, overBad, barTone, valueTone, valueClass, label, shown, caption, hasTarget, targetMark, targetPct, center, size, className, meterProps, rest }}
437
+ {...{ pct, over, overBad, barTone, valueTone, valueClass, label, shown, caption, hasTarget, targetMark, targetPct, center, size, className, meterProps, rest, compact, tip }}
423
438
  targetText={hasTarget ? `Target ${format(target)}${u}` : null}
424
439
  />
425
440
  );
426
441
  }
427
442
 
428
443
  const s = METER_SIZES[size] ?? METER_SIZES.md;
429
- const footer = caption || (hasTarget && size === "md");
444
+ const footer = !compact && (caption || (hasTarget && size === "md"));
430
445
 
431
446
  return (
432
- <div className={cx("grid gap-1.5", className)}>
433
- {label || shown ? (
447
+ <div className={cx("grid min-w-0 gap-1.5", className)} title={tip}>
448
+ {!compact && (label || shown) ? (
434
449
  <div aria-hidden="true" className="flex items-baseline justify-between gap-3 text-sm">
435
450
  <span className="min-w-0 truncate font-medium text-foreground">{label}</span>
436
451
  {shown ? (
@@ -499,7 +514,7 @@ const RING_SIZES = {
499
514
  RING_SIZES.thin = RING_SIZES.sm;
500
515
 
501
516
  // Meter shape="ring": the same numbers, drawn as an arc from twelve o'clock.
502
- function MeterRing({ pct, overBad, barTone, valueTone, valueClass, label, shown, caption, hasTarget, targetMark, targetPct, targetText, center, size, className, meterProps, rest }) {
517
+ function MeterRing({ pct, overBad, barTone, valueTone, valueClass, label, shown, caption, hasTarget, targetMark, targetPct, targetText, center, size, className, meterProps, rest, compact, tip }) {
503
518
  const g = RING_SIZES[size] ?? RING_SIZES.md;
504
519
  const c = g.px / 2;
505
520
  const r = c - g.w / 2;
@@ -521,10 +536,10 @@ function MeterRing({ pct, overBad, barTone, valueTone, valueClass, label, shown,
521
536
  const tick = (d) => [c + Math.cos(a) * d, c + Math.sin(a) * d];
522
537
  const [x1, y1] = tick(r - g.w / 2 - 1.5);
523
538
  const [x2, y2] = tick(r + g.w / 2 + 1.5);
524
- const side = label || shown || caption || (hasTarget && size !== "sm");
539
+ const side = !compact && (label || shown || caption || (hasTarget && size !== "sm"));
525
540
 
526
541
  return (
527
- <div className={cx("flex min-w-0 items-center", g.gap, className)}>
542
+ <div className={cx("flex min-w-0 items-center", g.gap, className)} title={tip}>
528
543
  <div {...meterProps} className="relative shrink-0" style={{ width: g.px, height: g.px }} {...rest}>
529
544
  <svg aria-hidden="true" width={g.px} height={g.px} viewBox={`0 0 ${g.px} ${g.px}`} className="block overflow-visible">
530
545
  {/* raw: an SVG gauge — the kit has no smaller part to draw an arc. */}
@@ -37,7 +37,8 @@ import { Spinner } from "./feedback";
37
37
  //
38
38
  // Newest in front; the rest stack behind and fan out on hover or focus,
39
39
  // and every timer pauses while they do (and while the tab is hidden).
40
- // Close with the ×, Escape, or a sideways swipe. Screen readers hear each
40
+ // Close with the ×, Escape, or a sideways swipe (touch and pen; a mouse
41
+ // selects the text instead, so an error can be copied). Screen readers hear each
41
42
  // toast once through a live region (assertive for .error). A toast is
42
43
  // never the only record of something that matters: an error the user
43
44
  // must act on is a Notice on the surface.
@@ -343,7 +344,8 @@ function ToastItem({ t, index, top, beyond, offset, expanded, clip, paused, onHe
343
344
  }
344
345
 
345
346
  function onPointerDown(e) {
346
- if (e.button !== 0 || e.target.closest("button, a, input, textarea, select")) return;
347
+ // A mouse selects the words (to copy an error); only touch and pen swipe.
348
+ if (e.pointerType === "mouse" || e.button !== 0 || e.target.closest("button, a, input, textarea, select")) return;
347
349
  drag.current = { x: e.clientX, at: e.timeStamp };
348
350
  e.currentTarget.setPointerCapture(e.pointerId);
349
351
  }
@@ -392,7 +394,8 @@ function ToastItem({ t, index, top, beyond, offset, expanded, clip, paused, onHe
392
394
  if (e.key === "Escape") dismiss(t.id);
393
395
  }}
394
396
  className={cx(
395
- "pointer-events-auto absolute inset-x-0 select-none",
397
+ "pointer-events-auto absolute inset-x-0 select-text",
398
+ dragging && "select-none",
396
399
  "transition-[opacity,translate,transform,height] duration-300 ease-out motion-reduce:transition-none",
397
400
  top ? "top-0 starting:-translate-y-full" : "bottom-0 starting:translate-y-full",
398
401
  "starting:opacity-0",