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
@@ -0,0 +1,260 @@
1
+ "use client";
2
+
3
+ import { useRef, useState } from "react";
4
+ import { Button, Notice, Skeleton, cx } from "../../ui";
5
+ import { clockOf, countMarks, lengthOf, marksOf, nextMark, pctOf, rangeOf, rangesOf, secondsAt, shareOf, stripWords, ticksFor, toSeconds } from "./strip-model";
6
+
7
+ // One bar for a span that has a length (a call, a recording, a shift), with
8
+ // marks at the times that matter on it. The marks are the app's: a cut, a
9
+ // comment, a decision. The bar can show the stretch somebody was away
10
+ // (hatched), and can let a person drag out a part of it.
11
+ //
12
+ // Props in, callbacks out (`onMark`, `onSelect`): the block never reads or
13
+ // writes data. Positions are percentages of the length, so the server draws
14
+ // what the browser draws. README.md beside this file lists every prop.
15
+
16
+ // Literal class names, so Tailwind sees every one of them.
17
+ const COLOR = {
18
+ neutral: "bg-muted-foreground",
19
+ primary: "bg-primary",
20
+ info: "bg-info",
21
+ success: "bg-success",
22
+ warning: "bg-warning",
23
+ danger: "bg-destructive",
24
+ };
25
+ const HUE = { 1: "bg-chart-1", 2: "bg-chart-2", 3: "bg-chart-3", 4: "bg-chart-4", 5: "bg-chart-5" };
26
+
27
+ const SIZE = {
28
+ sm: { track: "h-[22px]", mark: "inset-y-[3px] w-[5px]", on: "inset-y-0 w-[7px]", handle: "inset-y-0 w-2" },
29
+ lg: { track: "h-11", mark: "inset-y-1.5 w-1.5", on: "inset-y-0.5 w-2", handle: "inset-y-0 w-2.5" },
30
+ };
31
+
32
+ const HATCH = { backgroundImage: "repeating-linear-gradient(135deg, currentColor 0 1px, transparent 1px 5px)" };
33
+
34
+ const colorOf = (m) => (m.hue && HUE[m.hue] ? HUE[m.hue] : COLOR[m.tone] ?? "bg-foreground");
35
+
36
+ /**
37
+ * The strip.
38
+ *
39
+ * Props: `length` (seconds, or "mm:ss"), `marks` `[{ id, at, hue?, tone?,
40
+ * label? }]`, `away` `[[from, to]]`, `selection` `{ from, to }`,
41
+ * `onSelect(range | null)`, `selected` (a mark id), `onMark(mark)`, `size`
42
+ * (sm | lg), `axis` (true, false, or `[{ at, label? }]`), `step`, `noun`,
43
+ * `label`, `status`, `error`, `onRetry`, `className`.
44
+ */
45
+ export function TimeStrip({
46
+ length,
47
+ marks,
48
+ away,
49
+ selection,
50
+ onSelect,
51
+ selected,
52
+ onMark,
53
+ size = "sm",
54
+ axis = true,
55
+ ticks = 5,
56
+ step = 1,
57
+ noun = "mark",
58
+ label = "Timeline",
59
+ status = "ready",
60
+ error,
61
+ onRetry,
62
+ className,
63
+ }) {
64
+ const track = useRef(null);
65
+ const [drag, setDrag] = useState(null);
66
+ const total = lengthOf(length);
67
+ const look = SIZE[size] ?? SIZE.sm;
68
+ const placed = marksOf(marks, total);
69
+ const gaps = rangesOf(away, total);
70
+ const shown = drag ?? (selection ? rangeOf(selection.from, selection.to, total) : null);
71
+ const canPick = Boolean(onSelect) && total > 0;
72
+
73
+ if (status === "loading") {
74
+ return (
75
+ <div role="status" aria-label={`${label}, loading`} className={cx("grid gap-1", className)}>
76
+ <Skeleton className={cx("w-full", look.track)} />
77
+ {axis ? <Skeleton className="h-3 w-full" /> : null}
78
+ </div>
79
+ );
80
+ }
81
+ if (status === "failed") {
82
+ return (
83
+ <Notice
84
+ tone="danger"
85
+ className={className}
86
+ action={
87
+ onRetry ? (
88
+ <Button size="sm" onClick={onRetry}>
89
+ Try again
90
+ </Button>
91
+ ) : undefined
92
+ }
93
+ >
94
+ {error || "The timeline could not be read."}
95
+ </Notice>
96
+ );
97
+ }
98
+
99
+ // The bar's own ticks, or the app's.
100
+ const labels = (() => {
101
+ if (axis === false || total <= 0) return [];
102
+ if (Array.isArray(axis)) {
103
+ const list = axis
104
+ .map((t) => ({ ...t, seconds: toSeconds(t?.at) }))
105
+ .filter((t) => t.seconds != null)
106
+ .sort((a, b) => a.seconds - b.seconds);
107
+ return list.map((t, i) => ({ at: t.seconds, label: t.label ?? clockOf(t.seconds), pct: pctOf(shareOf(t.seconds, total)), edge: i === 0 && t.seconds <= 0 ? "start" : i === list.length - 1 && t.seconds >= total ? "end" : null }));
108
+ }
109
+ return ticksFor(total, ticks);
110
+ })();
111
+
112
+ function secondsFromPointer(e) {
113
+ const box = track.current?.getBoundingClientRect();
114
+ if (!box || !box.width) return 0;
115
+ return secondsAt((e.clientX - box.left) / box.width, total, step);
116
+ }
117
+
118
+ function down(e) {
119
+ if (!canPick || e.button !== 0) return;
120
+ const at = secondsFromPointer(e);
121
+ e.currentTarget.setPointerCapture?.(e.pointerId);
122
+ setDrag({ anchor: at, from: at, to: at, fromPct: 0, widthPct: 0, moving: false });
123
+ }
124
+ function move(e) {
125
+ if (!drag) return;
126
+ const at = secondsFromPointer(e);
127
+ const r = rangeOf(drag.anchor, at, total);
128
+ setDrag({ ...drag, moving: true, ...(r ?? { from: at, to: at, fromPct: pctOf(at / total), widthPct: 0 }) });
129
+ }
130
+ function up(e) {
131
+ if (!drag) return;
132
+ const at = secondsFromPointer(e);
133
+ const r = rangeOf(drag.anchor, at, total, { min: Math.max(1, Number(step) || 1) - 1 });
134
+ setDrag(null);
135
+ e.currentTarget.releasePointerCapture?.(e.pointerId);
136
+ // A press that went nowhere clears the part; a drag picks one.
137
+ onSelect(r ? { from: r.from, to: r.to } : null);
138
+ }
139
+
140
+ function nudge(which, e) {
141
+ if (!shown) return;
142
+ const unit = Math.max(1, Number(step) || 1) * (e.shiftKey ? 10 : 1);
143
+ const keys = { ArrowLeft: -unit, ArrowDown: -unit, ArrowRight: unit, ArrowUp: unit };
144
+ let from = shown.from;
145
+ let to = shown.to;
146
+ const move = which === "from" ? "from" : "to";
147
+ let value = move === "from" ? from : to;
148
+ if (e.key in keys) value += keys[e.key];
149
+ else if (e.key === "Home") value = 0;
150
+ else if (e.key === "End") value = total;
151
+ else if (e.key === "Escape") {
152
+ e.preventDefault();
153
+ onSelect(null);
154
+ return;
155
+ } else return;
156
+ e.preventDefault();
157
+ if (move === "from") from = value;
158
+ else to = value;
159
+ const r = rangeOf(from, to, total, { min: 0 });
160
+ if (r) onSelect({ from: r.from, to: r.to });
161
+ }
162
+
163
+ const words = stripWords({ length: total, marks: placed, noun });
164
+ const kinds = countMarks(placed);
165
+
166
+ return (
167
+ <div role="group" aria-label={label} className={cx("relative grid min-w-0 gap-1", className)}>
168
+ <div
169
+ ref={track}
170
+ className={cx("relative overflow-hidden rounded-[4px] border border-border bg-muted", look.track, canPick && "cursor-crosshair touch-none select-none")}
171
+ onPointerDown={down}
172
+ onPointerMove={move}
173
+ onPointerUp={up}
174
+ onPointerCancel={() => setDrag(null)}
175
+ >
176
+ {gaps.map((g, i) => (
177
+ <span key={`away-${i}`} aria-hidden="true" title={g.label} className="absolute inset-y-0 left-(--at) w-(--width) text-input" style={{ ...HATCH, "--at": `${g.fromPct}%`, "--width": `${g.widthPct}%` }} />
178
+ ))}
179
+ {shown && shown.widthPct > 0 ? (
180
+ <span aria-hidden="true" className="absolute inset-y-0 left-(--at) w-(--width) rounded-[4px] border-2 border-primary bg-primary/10" style={{ "--at": `${shown.fromPct}%`, "--width": `${shown.widthPct}%` }} />
181
+ ) : null}
182
+ {placed.map((m) => {
183
+ const on = selected != null && m.id === selected;
184
+ const name = `${m.label ? `${m.label}, ` : ""}${noun} at ${clockOf(m.seconds)}`;
185
+ const className = cx(
186
+ "absolute left-(--at) -translate-x-1/2 rounded-[2px] outline-none before:absolute before:inset-y-0 before:-inset-x-1.5 before:content-[''] focus-visible:ring-2 focus-visible:ring-ring",
187
+ on ? look.on : look.mark,
188
+ colorOf(m),
189
+ on && "ring-2 ring-background",
190
+ );
191
+ const style = { "--at": `${m.pct}%` };
192
+ return onMark ? (
193
+ <button
194
+ key={m.id}
195
+ type="button"
196
+ aria-label={name}
197
+ aria-pressed={on}
198
+ title={name}
199
+ className={className}
200
+ style={style}
201
+ onPointerDown={(e) => e.stopPropagation()}
202
+ onClick={() => onMark(m)}
203
+ onKeyDown={(e) => {
204
+ if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
205
+ const to = nextMark(placed, m.id, e.key === "ArrowRight" ? 1 : -1);
206
+ const el = e.currentTarget.parentElement?.querySelector(`[data-mark="${CSS.escape(String(to))}"]`);
207
+ if (el && to !== m.id) {
208
+ e.preventDefault();
209
+ el.focus();
210
+ }
211
+ }}
212
+ data-mark={m.id}
213
+ />
214
+ ) : (
215
+ <span key={m.id} role="img" aria-label={name} title={name} className={className} style={style} />
216
+ );
217
+ })}
218
+ {canPick && shown && shown.widthPct > 0
219
+ ? [
220
+ ["from", shown.from, shown.fromPct],
221
+ ["to", shown.to, shown.fromPct + shown.widthPct],
222
+ ].map(([which, value, at]) => (
223
+ <button
224
+ key={which}
225
+ type="button"
226
+ role="slider"
227
+ aria-label={which === "from" ? "Part starts at" : "Part ends at"}
228
+ aria-valuemin={0}
229
+ aria-valuemax={total}
230
+ aria-valuenow={Math.round(value)}
231
+ aria-valuetext={clockOf(value)}
232
+ className={cx("absolute left-(--at) -translate-x-1/2 cursor-ew-resize rounded-[2px] bg-primary outline-none focus-visible:ring-2 focus-visible:ring-ring", look.handle)}
233
+ style={{ "--at": `${at}%` }}
234
+ onPointerDown={(e) => e.stopPropagation()}
235
+ onKeyDown={(e) => nudge(which, e)}
236
+ />
237
+ ))
238
+ : null}
239
+ </div>
240
+ {labels.length ? (
241
+ <div aria-hidden="true" className="relative h-4 text-[11px] tabular-nums text-muted-foreground">
242
+ {labels.map((t, i) => (
243
+ <span
244
+ key={`${t.at}-${i}`}
245
+ className={cx("absolute left-(--at) top-0 whitespace-nowrap", t.edge === "end" ? "-translate-x-full" : t.edge === "start" ? "" : "-translate-x-1/2")}
246
+ style={{ "--at": `${t.pct}%` }}
247
+ >
248
+ {t.label}
249
+ </span>
250
+ ))}
251
+ </div>
252
+ ) : null}
253
+ <span className="sr-only">
254
+ {words}
255
+ {Object.keys(kinds).length > 1 ? `, in ${Object.keys(kinds).length} kinds` : ""}
256
+ {shown && shown.widthPct > 0 ? `. Part picked: ${clockOf(shown.from)} to ${clockOf(shown.to)}.` : ""}
257
+ </span>
258
+ </div>
259
+ );
260
+ }
@@ -0,0 +1,149 @@
1
+ # TopBar
2
+
3
+ The one bar every app draws over its work (0.8.1): where you are, the week's
4
+ allowance, Find, Ask and the screen's main action.
5
+
6
+ Until now fourteen apps drew their own (`components/<app>/frame.jsx`,
7
+ `TopBar`). So a fix to one never reached the others, and each broke in its own
8
+ way. The founder's review of 2026-10-12: Newsletter's "15,000 cr left" ran
9
+ into Find; Gantt Planner mounted the agent's dock and had no button that
10
+ opened it. This is the bar, once.
11
+
12
+ - **It never overlaps.** Every piece has a width it may take, and the bar
13
+ gives way in a fixed order as the app's window narrows. The sizes are
14
+ measures of the BAR (a container query), not of the screen: an open agent
15
+ dock takes a quarter of the window.
16
+
17
+ | The bar is | It draws |
18
+ | --- | --- |
19
+ | any width | the lead, the last crumb, Find and Ask as icons, the action as an icon |
20
+ | 32rem | the words on Find, Ask and the action |
21
+ | 36rem | the earlier crumbs and the note |
22
+ | 42rem | the ⌘K key on Find |
23
+ | 48rem | `extra` |
24
+ | 56rem | the allowance, as a bar |
25
+ | 64rem | the allowance in words ("this week") |
26
+
27
+ The table is `PIECES` in `top-bar-model.js`; a test walks every width from
28
+ 18rem to 100rem and checks that what is drawn fits.
29
+ - **Ask can't be left out.** When the app has an agent to ask (a `dock` from
30
+ `useAgentDock()`, an `onAsk`, or an `AskProvider` above the bar) the bar
31
+ draws Ask and it opens the agent. No prop turns it off. `npm run check`
32
+ (rule `ask`) refuses an app that mounts an `AgentDock` with no way to open
33
+ it.
34
+ - **The allowance is the kit's compact Meter**: the bar alone, with its label
35
+ and numbers for a screen reader and the tooltip.
36
+
37
+ ```jsx
38
+ import { AskProvider, BarText, TopBar, TopBarSlot } from "../components/blocks/top-bar"; // a Makersclaw app ("./blocks/top-bar" from components/)
39
+ import { TopBar } from "@/components/makersclaw/blocks/top-bar"; // a shadcn project
40
+ ```
41
+
42
+ A client component. It needs the kit (Button, Icon, Kbd, Meter) and nothing
43
+ else.
44
+
45
+ ## Adopting it (an app that drew its own)
46
+
47
+ 1. In the shell, wrap the layout in `AskProvider` with the dock:
48
+ `<AskProvider dock={dock}>…</AskProvider>`, where `dock = useAgentDock({ storageKey })`.
49
+ Delete the shell's old Ask handling (the `app:ask` window event, the
50
+ `toggleAgent()` bus) that only the old bar called.
51
+ 2. Delete the app's own `TopBar` from `components/<app>/frame.jsx` (and its
52
+ `allowanceOf`, `Meter` and `Find`/`Ask` buttons). Keep the rail.
53
+ 3. Say what every screen's bar repeats **once, on the `AskProvider`**: the
54
+ platform's budget as `allowance={{ used, cap }}` (and `allowanceLabel`,
55
+ `allowanceUnit`, `allowancePeriod` if they are not the defaults), and how
56
+ Find is reached, `findEvent="issues:find"` if the app's finder listens for a
57
+ window event (`findLabel`, `findWord`, or an `onFind`). Every `<TopBar>`
58
+ below uses them unless it passes its own (`allowance={null}` leaves the
59
+ allowance out on one screen).
60
+ 4. Import `TopBar` from `blocks/top-bar` and give each screen's bar only what is
61
+ that screen's: `crumb`, `note`, `extra`, `action`, `back`, `lead`.
62
+ 5. The action's words go in `<BarText>`: `<Button variant="primary" size="sm"
63
+ icon="plus"><BarText>New issue</BarText></Button>`. Under 32rem the button
64
+ is its icon and the words stay for a screen reader (`sr-only`). The button
65
+ must have an `icon`: `npm run check` (rule `barlabel`) refuses a `BarText`
66
+ button without one, because under 32rem it would draw nothing. Keep the
67
+ words to about 12 characters.
68
+ 6. If the old bar rendered through a portal into the shell's header slot, keep
69
+ the slot and provide it: `<TopBarSlot.Provider value={slotEl}>` (an
70
+ element; `null` until it has mounted). With no provider the bar draws where
71
+ it is rendered, as an `AppLayout` `header`.
72
+
73
+ ## Props
74
+
75
+ - `lead`: a node before everything (the sidebar trigger, a period picker).
76
+ - `back`: a path; a back button before the crumb.
77
+ - `crumb`: `[{ label, href?, muted? }]`; the last is this screen. The last
78
+ label truncates last.
79
+ - `note`: muted words after the crumb (from 36rem).
80
+ - `extra`: nodes before the allowance (from 48rem). Keep it to about 12rem
81
+ (a switch, a chip).
82
+ - `allowance`: `{ used, cap }` (the platform's budget); nothing when null.
83
+ `allowanceLabel`, `allowanceUnit` (`"cr"`), `allowancePeriod` (`"this
84
+ week"`). Left out, the `AskProvider`'s (below).
85
+ - `find`: `false` leaves Find out. `onFind`, or `findEvent` (a window event;
86
+ default `"app:find"`); `findLabel` (a screen reader's), `findWord`. Left
87
+ out, the `AskProvider`'s.
88
+ - `dock`: what `useAgentDock()` returns. `onAsk`: or your own opener, with
89
+ `asking` for its state. Neither: the nearest `AskProvider`'s. `askLabel`.
90
+ - `action`: the screen's main action, last in the bar.
91
+ - `className`: spacing only.
92
+
93
+ `AskProvider({ dock, onAsk, open, …defaults })`, `useAsk()` (`{ toggle, open }`
94
+ or null), `AskButton`, `FindButton` and `BarText` are exported.
95
+
96
+ **Bar defaults.** The provider also carries the props the bars of an app
97
+ repeat: `allowance`, `allowanceLabel`, `allowanceUnit`, `allowancePeriod`,
98
+ `findEvent`, `onFind`, `findLabel`, `findWord` and `askLabel`. A `TopBar` uses
99
+ them for any of those it does not pass; a prop it does pass (even `null`) wins.
100
+ The resolution is `resolveBar(own, defaults)` in the model. `useAsk()` reads
101
+ the agent (`open` is whether it is open; `toggle` toggles it); to **open** it
102
+ from a screen, call `openAgent()` (blocks/agent-dock), not `useAsk()`. `AskButton` is for a bar
103
+ that cannot be a `TopBar` (the check accepts it as a way to open the dock).
104
+
105
+ ## The model (plain functions)
106
+
107
+ `PIECES`, `SIZES`, `SHOW`, `visibleAt(rem)`, `usedAt(rem)`, `fitsAt(rem)`,
108
+ `floorRem()`, `askDrawn({ dock, onAsk, context })`, `askAction(...)`,
109
+ `askOpen(...)`, `allowanceOf({ used, cap })`, `allowanceWords(...)`,
110
+ `BAR_DEFAULTS`, `barDefaultsOf(props)`, `resolveBar(own, defaults)`.
111
+
112
+ ## Example
113
+
114
+ ```jsx
115
+ // app/shell.jsx
116
+ "use client";
117
+ import { AppLayout, Button } from "../components/ui";
118
+ import { AgentDock, useAgentDock } from "../components/blocks/agent-dock";
119
+ import { AskProvider, BarText, TopBar } from "../components/blocks/top-bar";
120
+
121
+ export default function Shell({ children, budget }) {
122
+ const dock = useAgentDock({ storageKey: "issues" });
123
+ return (
124
+ <AskProvider dock={dock} allowance={{ used: budget.used, cap: budget.cap }} findEvent="issues:find" findLabel="Find an issue">
125
+ <AppLayout
126
+ header={
127
+ <TopBar
128
+ crumb={[{ label: "Issues", href: "/s/issues" }, { label: "Issue 14" }]}
129
+ action={
130
+ <Button variant="primary" size="sm" icon="plus">
131
+ <BarText>New issue</BarText>
132
+ </Button>
133
+ }
134
+ />
135
+ }
136
+ dock={<AgentDock dock={dock} label="Ask the agent" />}
137
+ >
138
+ {children}
139
+ </AppLayout>
140
+ </AskProvider>
141
+ );
142
+ }
143
+ ```
144
+
145
+ ## States drawn in the demo
146
+
147
+ The same bar at 320, 480, 640, 800 and 1100 px; Ask with the dock closed and
148
+ open; a dock passed straight to the bar; an app with no agent (no Ask); a long
149
+ title with a back button and no Find.
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "top-bar",
3
+ "title": "TopBar",
4
+ "description": "The one bar every app draws over its work: where you are (a back button, a breadcrumb that keeps its last label and gives up the earlier ones first, a note), the week's allowance (words and the kit's compact Meter), Find, Ask and the screen's main action. It gives way in a set order as the app's window narrows, measured by the bar's own width (a container query, not the window: an open agent dock takes a quarter of it): under 32rem Find, Ask and the action are icons; from 32rem their words; from 36rem the earlier crumbs and the note; from 42rem the ⌘K key; from 48rem `extra`; from 56rem the allowance bar; from 64rem the allowance in words. A table of every piece's width is the single source (top-bar-model.js), and a test walks every width from a phone to a wide desk and checks what is drawn fits, so nothing overlaps. Ask is never optional: when the app has an agent to ask (a dock from useAgentDock, an onAsk, or an AskProvider above) the bar draws Ask and it opens the agent; no prop leaves it out, and `npm run check` refuses an app that mounts an AgentDock with no way to open it. It draws where it is rendered (an AppLayout header) or into the shell's header slot (TopBarSlot). AskProvider, AskButton, FindButton, BarText and the model's plain functions are exported.",
5
+ "useWhen": "Every app's top bar, replacing each app's own components/<app>/frame.jsx TopBar: the shell or each screen's AppLayout header. Any app that mounts an AgentDock uses it (or AskButton in a bar it cannot replace) so the agent can be opened. Not for a bar inside a card or a sheet (use the parts), and not for the rail or the navigation (sidebar, navigation-menu).",
6
+ "tags": ["top bar", "header", "breadcrumb", "find", "ask", "agent", "allowance", "credits", "action", "shell", "chrome", "responsive", "dock", "search"],
7
+ "exports": [
8
+ "AskButton",
9
+ "AskProvider",
10
+ "BAR_DEFAULTS",
11
+ "BarText",
12
+ "FindButton",
13
+ "GAP",
14
+ "PIECES",
15
+ "SHOW",
16
+ "SIZES",
17
+ "TopBar",
18
+ "TopBarSlot",
19
+ "allowanceOf",
20
+ "allowanceWords",
21
+ "askAction",
22
+ "askDrawn",
23
+ "askOpen",
24
+ "barDefaultsOf",
25
+ "fitsAt",
26
+ "floorRem",
27
+ "resolveBar",
28
+ "useAsk",
29
+ "usedAt",
30
+ "visibleAt"
31
+ ],
32
+ "files": ["index.js", "top-bar.jsx", "top-bar-model.js", "probe-rules.js"],
33
+ "requires": [],
34
+ "offer": { "since": "0.8.1", "why": "the one top bar (where you are, the allowance, Find, Ask, the action), in place of the app's own TopBar in components/<app>/frame.jsx" }
35
+ }
@@ -0,0 +1,78 @@
1
+ "use client";
2
+
3
+ // TopBar in every state — the gallery's and the smoke test's surface. Not
4
+ // installed into apps: `makersclaw add top-bar` lays index.js, top-bar.jsx and
5
+ // top-bar-model.js only.
6
+ // Widths the same bar at 320, 480, 640, 800 and 1100 px, so the order
7
+ // it gives way in can be read: words on Find, Ask and the
8
+ // action go first, then the earlier crumbs and the note, the
9
+ // ⌘K key, `extra`, the allowance's bar, the allowance's words.
10
+ // Ask an agent is in reach (AskProvider): Ask is drawn at every
11
+ // width and opens the dock; the dock's open state shows on it.
12
+ // No agent no dock, no Ask. The only way to have no Ask.
13
+ // Long crumb a long title truncates; nothing runs into Find.
14
+ // Back a back button before the crumb.
15
+ // Find off find={false}.
16
+ import { useState } from "react";
17
+ import { Button, Card } from "../components/ui";
18
+ import { AskProvider, BarText, TopBar } from "../components/blocks/top-bar";
19
+
20
+ const WIDTHS = [320, 480, 640, 800, 1100];
21
+ const ALLOWANCE = { used: 4120, cap: 15000 };
22
+ const CRUMB = [{ label: "Issues", href: "/s/issues" }, { label: "Issue 14" }];
23
+
24
+ function Framed({ width, children }) {
25
+ return (
26
+ <div style={{ width }} className="max-w-full overflow-hidden rounded-md border border-border bg-background">
27
+ {children}
28
+ </div>
29
+ );
30
+ }
31
+
32
+ const newIssue = (
33
+ <Button variant="primary" size="sm" icon="plus">
34
+ <BarText>New issue</BarText>
35
+ </Button>
36
+ );
37
+
38
+ export default function TopBarDemo() {
39
+ const [open, setOpen] = useState(false);
40
+ const dock = { open, toggle: () => setOpen((v) => !v) };
41
+ return (
42
+ <div className="grid gap-6">
43
+ <section className="grid gap-3">
44
+ <h2 className="text-sm font-semibold">The same bar at five widths (agent in reach: Ask {open ? "open" : "closed"})</h2>
45
+ <AskProvider dock={dock}>
46
+ {WIDTHS.map((w) => (
47
+ <div key={w} className="grid gap-1">
48
+ <p className="text-xs text-muted-foreground">{w}px</p>
49
+ <Framed width={w}>
50
+ <TopBar crumb={CRUMB} note="Draft · saved" extra={<Button variant="quiet" size="sm">Week</Button>} allowance={ALLOWANCE} findLabel="Find an issue" action={newIssue} />
51
+ </Framed>
52
+ </div>
53
+ ))}
54
+ </AskProvider>
55
+ </section>
56
+
57
+ <Card title="A dock passed straight to the bar" description="No provider: the bar's own dock prop.">
58
+ <Framed width={640}>
59
+ <TopBar crumb={[{ label: "Home" }]} dock={dock} />
60
+ </Framed>
61
+ </Card>
62
+
63
+ <Card title="No agent in this app" description="No dock, no provider: no Ask. Find stays.">
64
+ <Framed width={640}>
65
+ <TopBar crumb={[{ label: "Ledger" }]} action={newIssue} />
66
+ </Framed>
67
+ </Card>
68
+
69
+ <Card title="A long title, a back button, no Find" description="The title truncates before it reaches the buttons.">
70
+ <AskProvider dock={dock}>
71
+ <Framed width={480}>
72
+ <TopBar back="/s/issues" find={false} crumb={[{ label: "Issues", href: "/s/issues" }, { label: "Turn a developer's line into a customer's: the Monday issue that nobody wanted to write" }]} action={newIssue} />
73
+ </Framed>
74
+ </AskProvider>
75
+ </Card>
76
+ </div>
77
+ );
78
+ }
@@ -0,0 +1,5 @@
1
+ // The TopBar block — `makersclaw add top-bar`. Fixed: compose it through its
2
+ // props (README.md beside this file). The model's helpers are plain
3
+ // functions; they work on the server too.
4
+ export { AskButton, AskProvider, BarText, FindButton, TopBar, TopBarSlot, useAsk } from "./top-bar";
5
+ export { BAR_DEFAULTS, GAP, PIECES, SHOW, SIZES, allowanceOf, allowanceWords, askAction, askDrawn, askOpen, barDefaultsOf, fitsAt, floorRem, resolveBar, usedAt, visibleAt } from "./top-bar-model";
@@ -0,0 +1,74 @@
1
+ // The layout rules this block ships for the store's probe (makersclaw-store
2
+ // scripts/probe.mjs --suite). They are data: the probe reads them from this
3
+ // block in the app (components/blocks/top-bar/probe-rules.js) and checks each
4
+ // one on every screen, at every window size, with the agent column shut and
5
+ // open. Nothing in the app imports this file; it costs a few hundred bytes.
6
+ //
7
+ // `pieces` and `target` name the bar's parts by their data-bar-piece hook;
8
+ // the second selector in each is the accessible name an older copy of the bar
9
+ // (before the hooks) already has. Each finding is a UI-review number
10
+ // (docs/UI-REVIEW-2026-10-12.md) turned into a measure.
11
+ export default {
12
+ block: "top-bar",
13
+ rules: [
14
+ {
15
+ id: "pieces-never-intersect",
16
+ kind: "disjoint",
17
+ note: "UI review 1.1, 1.4: the bar's pieces overlapped",
18
+ scope: "[data-top-bar]",
19
+ pieces: {
20
+ "Where you are": '[data-bar-piece="crumb"], nav[aria-label="Where you are"]',
21
+ "the note": '[data-bar-piece="note"]',
22
+ "the extra": '[data-bar-piece="extra"]',
23
+ "the allowance": '[data-bar-piece="allowance"]',
24
+ Find: '[data-bar-piece="find"], button[aria-label^="Find"]',
25
+ Ask: '[data-bar-piece="ask"], button[aria-label="Ask the agent"]',
26
+ "the action": '[data-bar-piece="action"]',
27
+ },
28
+ },
29
+ {
30
+ id: "ask-reachable",
31
+ kind: "clickable",
32
+ note: "UI review X8: no way to open the agent",
33
+ scope: "[data-top-bar]",
34
+ target: '[data-bar-piece="ask"], button[aria-label="Ask the agent"]',
35
+ name: "Ask",
36
+ minSize: 24,
37
+ },
38
+ {
39
+ id: "find-reachable",
40
+ kind: "clickable",
41
+ note: "UI review 1.1: Find pushed out or covered",
42
+ scope: "[data-top-bar]",
43
+ target: '[data-bar-piece="find"], button[aria-label^="Find"]',
44
+ name: "Find",
45
+ minSize: 24,
46
+ },
47
+ {
48
+ id: "action-reachable",
49
+ kind: "clickable",
50
+ note: "the screen's main action stays inside the window",
51
+ scope: "[data-top-bar]",
52
+ target: '[data-bar-piece="action"] button, [data-bar-piece="action"] a',
53
+ name: "the action",
54
+ minSize: 24,
55
+ },
56
+ {
57
+ id: "crumb-label-not-cut-to-nothing",
58
+ kind: "visible-text",
59
+ note: "UI review 1.2, X3: a label cut to nothing",
60
+ scope: "[data-top-bar]",
61
+ target: '[data-bar-piece="crumb"] [aria-current="page"], nav[aria-label="Where you are"] [aria-current="page"]',
62
+ min: 3,
63
+ },
64
+ {
65
+ id: "an-agent-has-a-way-in",
66
+ kind: "clickable",
67
+ note: "UI review X8: a dock is mounted and nothing opens it",
68
+ target: '[data-bar-piece="ask"], button[aria-label="Ask the agent"], [data-ask]',
69
+ name: "a control that opens the agent",
70
+ requiredWhen: "[data-agent-dock]",
71
+ minSize: 24,
72
+ },
73
+ ],
74
+ };