makersclaw 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/README.md +17 -4
  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 +4 -4
  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 +5 -5
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +3 -3
  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 +18 -6
  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 +3 -3
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +3 -3
  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 +4 -4
  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 +4 -4
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +3 -3
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +3 -3
  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 +4089 -1510
  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 +3 -3
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +3 -3
  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 +4 -4
  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 +225 -0
  143. package/registry/blocks/agent-pane/agent-pane.jsx +244 -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/annotate/README.md +14 -11
  159. package/registry/blocks/approval/README.md +145 -0
  160. package/registry/blocks/approval/approval.jsx +163 -0
  161. package/registry/blocks/approval/block.json +31 -0
  162. package/registry/blocks/approval/demo.jsx +121 -0
  163. package/registry/blocks/approval/index.js +3 -0
  164. package/registry/blocks/ask-bar/README.md +105 -0
  165. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  166. package/registry/blocks/ask-bar/block.json +26 -0
  167. package/registry/blocks/ask-bar/demo.jsx +78 -0
  168. package/registry/blocks/ask-bar/index.js +3 -0
  169. package/registry/blocks/automation-editor/README.md +291 -0
  170. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  171. package/registry/blocks/automation-editor/block.json +39 -0
  172. package/registry/blocks/automation-editor/demo.jsx +284 -0
  173. package/registry/blocks/automation-editor/index.js +4 -0
  174. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  175. package/registry/blocks/automation-list/README.md +129 -0
  176. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  177. package/registry/blocks/automation-list/block.json +35 -0
  178. package/registry/blocks/automation-list/demo.jsx +67 -0
  179. package/registry/blocks/automation-list/index.js +3 -0
  180. package/registry/blocks/automation-model/README.md +109 -0
  181. package/registry/blocks/automation-model/block.json +135 -0
  182. package/registry/blocks/automation-model/catalog.js +256 -0
  183. package/registry/blocks/automation-model/check.js +161 -0
  184. package/registry/blocks/automation-model/demo.jsx +42 -0
  185. package/registry/blocks/automation-model/edit.js +262 -0
  186. package/registry/blocks/automation-model/fixes.js +287 -0
  187. package/registry/blocks/automation-model/glyph.jsx +13 -0
  188. package/registry/blocks/automation-model/graph.js +410 -0
  189. package/registry/blocks/automation-model/index.js +33 -0
  190. package/registry/blocks/automation-model/overlay.js +175 -0
  191. package/registry/blocks/automation-model/parts.jsx +94 -0
  192. package/registry/blocks/automation-model/schedule.js +53 -0
  193. package/registry/blocks/automation-model/templates.js +128 -0
  194. package/registry/blocks/automation-model/values.js +29 -0
  195. package/registry/blocks/automation-model/words.js +439 -0
  196. package/registry/blocks/automations-screen/README.md +207 -0
  197. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  198. package/registry/blocks/automations-screen/block.json +47 -0
  199. package/registry/blocks/automations-screen/demo.jsx +364 -0
  200. package/registry/blocks/automations-screen/index.js +4 -0
  201. package/registry/blocks/automations-screen/screen-model.js +129 -0
  202. package/registry/blocks/chart/cartesian.jsx +1 -1
  203. package/registry/blocks/chart/core.jsx +33 -23
  204. package/registry/blocks/chart/pie.jsx +1 -1
  205. package/registry/blocks/chat/README.md +4 -1
  206. package/registry/blocks/chat/demo.jsx +2 -2
  207. package/registry/blocks/chat-pane/README.md +143 -0
  208. package/registry/blocks/chat-pane/block.json +48 -0
  209. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  210. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  211. package/registry/blocks/chat-pane/chat-context.js +17 -0
  212. package/registry/blocks/chat-pane/chat-model.js +43 -0
  213. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  214. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  215. package/registry/blocks/chat-pane/demo.jsx +103 -0
  216. package/registry/blocks/chat-pane/index.js +9 -0
  217. package/registry/blocks/connect-card/README.md +99 -0
  218. package/registry/blocks/connect-card/block.json +10 -0
  219. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  220. package/registry/blocks/connect-card/demo.jsx +49 -0
  221. package/registry/blocks/connect-card/index.js +3 -0
  222. package/registry/blocks/cost/README.md +115 -0
  223. package/registry/blocks/cost/block.json +10 -0
  224. package/registry/blocks/cost/cost.jsx +176 -0
  225. package/registry/blocks/cost/demo.jsx +66 -0
  226. package/registry/blocks/cost/index.js +3 -0
  227. package/registry/blocks/data-picker/README.md +81 -0
  228. package/registry/blocks/data-picker/block.json +38 -0
  229. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  230. package/registry/blocks/data-picker/demo.jsx +34 -0
  231. package/registry/blocks/data-picker/fields.js +89 -0
  232. package/registry/blocks/data-picker/index.js +4 -0
  233. package/registry/blocks/data-table/demo.jsx +1 -1
  234. package/registry/blocks/first-run/README.md +118 -0
  235. package/registry/blocks/first-run/block.json +11 -0
  236. package/registry/blocks/first-run/demo.jsx +88 -0
  237. package/registry/blocks/first-run/first-run-model.js +51 -0
  238. package/registry/blocks/first-run/first-run.jsx +156 -0
  239. package/registry/blocks/first-run/index.js +5 -0
  240. package/registry/blocks/first-run/probe-rules.js +26 -0
  241. package/registry/blocks/fix-note/README.md +79 -0
  242. package/registry/blocks/fix-note/block.json +35 -0
  243. package/registry/blocks/fix-note/demo.jsx +30 -0
  244. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  245. package/registry/blocks/fix-note/index.js +3 -0
  246. package/registry/blocks/flow-canvas/README.md +15 -8
  247. package/registry/blocks/flow-editor/README.md +108 -0
  248. package/registry/blocks/flow-editor/block.json +44 -0
  249. package/registry/blocks/flow-editor/demo.jsx +115 -0
  250. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  251. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  252. package/registry/blocks/flow-editor/index.js +6 -0
  253. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  254. package/registry/blocks/flow-editor/outline.jsx +134 -0
  255. package/registry/blocks/footer/README.md +3 -2
  256. package/registry/blocks/library-shelf/README.md +117 -0
  257. package/registry/blocks/library-shelf/block.json +28 -0
  258. package/registry/blocks/library-shelf/demo.jsx +68 -0
  259. package/registry/blocks/library-shelf/index.js +3 -0
  260. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  261. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  262. package/registry/blocks/margin-notes/README.md +222 -0
  263. package/registry/blocks/margin-notes/block.json +10 -0
  264. package/registry/blocks/margin-notes/demo.jsx +144 -0
  265. package/registry/blocks/margin-notes/index.js +20 -0
  266. package/registry/blocks/margin-notes/margin-model.js +224 -0
  267. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  268. package/registry/blocks/mind-map/README.md +4 -2
  269. package/registry/blocks/needs-you/README.md +177 -0
  270. package/registry/blocks/needs-you/block.json +34 -0
  271. package/registry/blocks/needs-you/demo.jsx +143 -0
  272. package/registry/blocks/needs-you/index.js +3 -0
  273. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  274. package/registry/blocks/org-chart/README.md +4 -2
  275. package/registry/blocks/pace-bar/README.md +230 -0
  276. package/registry/blocks/pace-bar/block.json +10 -0
  277. package/registry/blocks/pace-bar/demo.jsx +255 -0
  278. package/registry/blocks/pace-bar/index.js +22 -0
  279. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  280. package/registry/blocks/pace-bar/pace-model.js +288 -0
  281. package/registry/blocks/page-builder/README.md +1 -1
  282. package/registry/blocks/page-builder/demo.jsx +3 -3
  283. package/registry/blocks/pdf-viewer/README.md +4 -1
  284. package/registry/blocks/record-grid/README.md +100 -0
  285. package/registry/blocks/record-grid/block.json +28 -0
  286. package/registry/blocks/record-grid/demo.jsx +43 -0
  287. package/registry/blocks/record-grid/index.js +3 -0
  288. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  289. package/registry/blocks/run-history/README.md +138 -0
  290. package/registry/blocks/run-history/block.json +10 -0
  291. package/registry/blocks/run-history/demo.jsx +74 -0
  292. package/registry/blocks/run-history/index.js +3 -0
  293. package/registry/blocks/run-history/run-history.jsx +218 -0
  294. package/registry/blocks/run-view/README.md +174 -0
  295. package/registry/blocks/run-view/block.json +50 -0
  296. package/registry/blocks/run-view/demo.jsx +286 -0
  297. package/registry/blocks/run-view/index.js +5 -0
  298. package/registry/blocks/run-view/run-controls.jsx +266 -0
  299. package/registry/blocks/run-view/run-view.jsx +236 -0
  300. package/registry/blocks/run-view/runs-list.jsx +99 -0
  301. package/registry/blocks/schedule-card/README.md +121 -0
  302. package/registry/blocks/schedule-card/block.json +10 -0
  303. package/registry/blocks/schedule-card/demo.jsx +82 -0
  304. package/registry/blocks/schedule-card/index.js +3 -0
  305. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  306. package/registry/blocks/schedule-engine/README.md +137 -0
  307. package/registry/blocks/schedule-engine/block.json +10 -0
  308. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  309. package/registry/blocks/schedule-engine/engine.js +769 -0
  310. package/registry/blocks/schedule-engine/index.js +9 -0
  311. package/registry/blocks/schedule-engine/ops.js +71 -0
  312. package/registry/blocks/schedule-engine/place.js +294 -0
  313. package/registry/blocks/schedule-engine/tree.js +79 -0
  314. package/registry/blocks/schedule-engine/waits.js +80 -0
  315. package/registry/blocks/schedule-gantt/README.md +159 -0
  316. package/registry/blocks/schedule-gantt/block.json +10 -0
  317. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  318. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  319. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  320. package/registry/blocks/schedule-gantt/index.js +26 -0
  321. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  322. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  323. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  324. package/registry/blocks/schedule-ruler/README.md +148 -0
  325. package/registry/blocks/schedule-ruler/block.json +10 -0
  326. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  327. package/registry/blocks/schedule-ruler/index.js +21 -0
  328. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  329. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  330. package/registry/blocks/sidebar/README.md +23 -13
  331. package/registry/blocks/sketch-canvas/README.md +15 -9
  332. package/registry/blocks/source-receipt/README.md +97 -0
  333. package/registry/blocks/source-receipt/block.json +30 -0
  334. package/registry/blocks/source-receipt/demo.jsx +71 -0
  335. package/registry/blocks/source-receipt/index.js +3 -0
  336. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  337. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  338. package/registry/blocks/step-picker/README.md +78 -0
  339. package/registry/blocks/step-picker/block.json +31 -0
  340. package/registry/blocks/step-picker/demo.jsx +23 -0
  341. package/registry/blocks/step-picker/index.js +3 -0
  342. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  343. package/registry/blocks/step-settings/README.md +100 -0
  344. package/registry/blocks/step-settings/block.json +44 -0
  345. package/registry/blocks/step-settings/demo.jsx +93 -0
  346. package/registry/blocks/step-settings/fields.jsx +58 -0
  347. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  348. package/registry/blocks/step-settings/index.js +5 -0
  349. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  350. package/registry/blocks/suggestion/README.md +171 -0
  351. package/registry/blocks/suggestion/block.json +40 -0
  352. package/registry/blocks/suggestion/demo.jsx +91 -0
  353. package/registry/blocks/suggestion/index.js +3 -0
  354. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  355. package/registry/blocks/sum-bar/README.md +122 -0
  356. package/registry/blocks/sum-bar/block.json +10 -0
  357. package/registry/blocks/sum-bar/demo.jsx +110 -0
  358. package/registry/blocks/sum-bar/index.js +5 -0
  359. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  360. package/registry/blocks/sum-bar/sum-model.js +126 -0
  361. package/registry/blocks/tier-map/README.md +217 -0
  362. package/registry/blocks/tier-map/block.json +10 -0
  363. package/registry/blocks/tier-map/demo.jsx +222 -0
  364. package/registry/blocks/tier-map/index.js +24 -0
  365. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  366. package/registry/blocks/tier-map/tier-model.js +318 -0
  367. package/registry/blocks/time-grid/README.md +305 -0
  368. package/registry/blocks/time-grid/block.json +10 -0
  369. package/registry/blocks/time-grid/demo.jsx +279 -0
  370. package/registry/blocks/time-grid/grid-model.js +322 -0
  371. package/registry/blocks/time-grid/index.js +25 -0
  372. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  373. package/registry/blocks/time-strip/README.md +141 -0
  374. package/registry/blocks/time-strip/block.json +10 -0
  375. package/registry/blocks/time-strip/demo.jsx +129 -0
  376. package/registry/blocks/time-strip/index.js +19 -0
  377. package/registry/blocks/time-strip/strip-model.js +178 -0
  378. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  379. package/registry/blocks/top-bar/README.md +149 -0
  380. package/registry/blocks/top-bar/block.json +35 -0
  381. package/registry/blocks/top-bar/demo.jsx +78 -0
  382. package/registry/blocks/top-bar/index.js +5 -0
  383. package/registry/blocks/top-bar/probe-rules.js +74 -0
  384. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  385. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  386. package/registry/blocks/trigger-picker/README.md +98 -0
  387. package/registry/blocks/trigger-picker/block.json +38 -0
  388. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  389. package/registry/blocks/trigger-picker/index.js +3 -0
  390. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  391. package/registry/blocks/whiteboard/README.md +20 -14
  392. package/registry/blocks/workflow-view/README.md +123 -0
  393. package/registry/blocks/workflow-view/block.json +10 -0
  394. package/registry/blocks/workflow-view/demo.jsx +90 -0
  395. package/registry/blocks/workflow-view/index.js +3 -0
  396. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  397. package/src/cli.mjs +2 -2
  398. package/src/install.mjs +100 -22
  399. package/src/registry.mjs +37 -3
  400. package/templates/next/browser/lib/data.js +6 -1
  401. package/templates/next/files/README.md +909 -26
  402. package/templates/next/files/app/shell.jsx +54 -37
  403. package/templates/next/files/check/automation-format.ts +2103 -0
  404. package/templates/next/files/check/automation-package.ts +142 -0
  405. package/templates/next/files/check/run.mjs +1043 -12
  406. package/templates/next/files/components/ui/field.jsx +17 -4
  407. package/templates/next/files/components/ui/icon.jsx +13 -0
  408. package/templates/next/files/components/ui/index.js +3 -1
  409. package/templates/next/files/components/ui/layout.jsx +382 -0
  410. package/templates/next/files/components/ui/notice.jsx +70 -0
  411. package/templates/next/files/components/ui/page.jsx +124 -0
  412. package/templates/next/files/components/ui/stat.jsx +22 -7
  413. package/templates/next/files/components/ui/toast.jsx +6 -3
  414. package/templates/next/files/lib/automations.js +660 -0
  415. package/templates/next/files/lib/claw.js +244 -5
  416. package/templates/next/files/lib/door.js +92 -0
  417. package/templates/next/files/lib/hooks.js +1694 -6
  418. package/templates/next/files/lib/platform.js +611 -14
  419. package/templates/next/template.json +22 -3
@@ -0,0 +1,141 @@
1
+ # TimeStrip
2
+
3
+ One bar for a span that has a length, with marks at the times that matter.
4
+
5
+ A four-minute client call is a bar from `00:00` to `04:12`. Nine things were
6
+ cut from it, and each is a thin post on the bar at the time it was said, in the
7
+ colour of its kind. A person sees *where in the call* the sensitive things
8
+ happened, and presses one to go there. The stretch before the client joined is
9
+ hatched. The same bar sits small under a record's title and large as a
10
+ screen's signature.
11
+
12
+ It draws marks the app has already placed. It plays nothing, cuts nothing and
13
+ measures nothing. For a chain of dated phases with gates use `schedule-ruler`;
14
+ for progress against a clock `pace-bar`; for events on an hour grid
15
+ `time-grid`; for a waveform with a playhead `audio-player`.
16
+
17
+ Born in a minutes app that drew it by hand on three screens: a call's cuts under
18
+ its title, the same strip large with the transcript, and a part of the call
19
+ picked out to minute.
20
+
21
+ ```jsx
22
+ import { TimeStrip, toSeconds, clockOf } from "../components/blocks/time-strip"; // a Makersclaw app ("./blocks/time-strip" from components/)
23
+ import { TimeStrip } from "@/components/makersclaw/blocks/time-strip"; // a shadcn project
24
+ ```
25
+
26
+ A client component. No other block and no npm package. Positions are
27
+ percentages of the length, so the server and the browser draw the same picture;
28
+ nothing is measured except at the moment a person drags.
29
+
30
+ ## Times
31
+
32
+ A time is a number of seconds from the start, or a string: `"76"`, `"01:16"`,
33
+ `"1:02:03"`. A time that is none of these has no place on the bar: its mark is
34
+ left out, never rounded into one. A time past the end sits at the end.
35
+ `toSeconds("01:16")` is `76`; `clockOf(3723)` is `"1:02:03"` and `clockOf(252)`
36
+ is `"04:12"`.
37
+
38
+ ## Props
39
+
40
+ - `length` — how long the span is: seconds, or a time string. Required. With no
41
+ length the bar is empty and says "Nothing to show".
42
+ - `marks` — `[{ id, at, hue?, tone?, label? }]`. `at` is the mark's time.
43
+ - `hue` — `1` to `5`: a category colour (a reason, a speaker, a kind).
44
+ - `tone` — `neutral` · `primary` · `info` · `success` · `warning` ·
45
+ `danger`: a status. `hue` wins over `tone`. Neither: ink.
46
+ - `label` — what a reader hears: "Pricing". Spoken as "Pricing, mark at
47
+ 00:12".
48
+ - Any other key is kept and handed back to `onMark`.
49
+ - `away` — stretches somebody was away, hatched: `[[from, to]]` or `[{ from, to,
50
+ label? }]`. A stretch with nothing inside the bar is dropped.
51
+ - `selection` — `{ from, to }`: the part picked, drawn with a frame and a handle
52
+ at each end.
53
+ - `onSelect(range | null)` — makes the bar pick-able: drag across it to pick a
54
+ part (`{ from, to }`, in seconds, snapped to `step`); a press that goes nowhere
55
+ clears it (`null`). The two handles are sliders: ← → move one by `step`, with
56
+ Shift by ten steps, Home and End go to the ends, Esc clears. **Give a keyboard
57
+ path of your own as well** (two time fields) for a person who cannot drag.
58
+ - `selected` — the id of the mark to show pressed (taller, ringed).
59
+ - `onMark(mark)` — makes the marks buttons. Called with the mark as laid out
60
+ (`{ ...yours, seconds, share, pct }`). ← → on a focused mark moves to the next
61
+ or the one before. Without it the marks are plain pictures with a label.
62
+ - `size` — `sm` (22 px, default) or `lg` (44 px).
63
+ - `axis` — `true` (default): about `ticks` labels under the bar on whole steps,
64
+ always the start and the end. `false`: none. Or your own labels,
65
+ `[{ at, label? }]`: `[{ at: 0, label: "00:00 · before the client joined" },
66
+ { at: 252, label: "after they left · 04:12" }]`. The first label keeps to the
67
+ left edge and the last to the right, so a long word never leaves the bar.
68
+ - `ticks` — how many labels `axis: true` aims for (2 to 12). Default 5.
69
+ - `step` — seconds a drag snaps to and a key moves by. Default 1.
70
+ - `noun` — what a mark is called in the words a reader hears. Default `mark`.
71
+ - `label` — the bar's name for a reader. Default "Timeline".
72
+ - `status` — `ready` (default), `loading` (a grey bar) or `failed` (a notice
73
+ with `error` and, if you pass `onRetry`, Try again).
74
+ - `className` — layout: width and margin. Never colour.
75
+
76
+ ## Helpers
77
+
78
+ Plain functions from the same folder, safe on the server:
79
+
80
+ - `toSeconds(value)` → seconds or `null`; `clockOf(seconds)` → `"04:12"`.
81
+ - `marksOf(marks, length)` — the marks as laid out, in time order, each with
82
+ `seconds`, `share` (0..1) and `pct`.
83
+ - `rangeOf(a, b, length)` — two times as an ordered range kept inside the bar,
84
+ or `null` when they enclose nothing. `rangesOf(ranges, length)` for a list.
85
+ - `ticksFor(length, count)` — the axis ticks. `shareOf`, `pctOf`, `secondsAt`.
86
+ - `nextMark(marks, currentId, dir)` — where a key goes.
87
+ - `stripWords({ length, marks, noun })` — "9 marks in 04:12".
88
+
89
+ ## Example
90
+
91
+ A call's cuts under its title, large with the transcript, and a part to pick.
92
+
93
+ ```jsx
94
+ "use client";
95
+ import { useState } from "react";
96
+ import { TimeStrip } from "../components/blocks/time-strip";
97
+
98
+ const FAMILY = { pricing: 1, third_party: 2, off_record: 3, joke: 4 };
99
+
100
+ export function CallStrip({ call, cuts, onGoTo }) {
101
+ const [part, setPart] = useState(null);
102
+ return (
103
+ <>
104
+ <TimeStrip
105
+ label="The call, with every cut where it was said"
106
+ noun="cut"
107
+ length={call.length}
108
+ away={[[0, call.joinedAt], [call.leftAt, call.length]]}
109
+ marks={cuts.map((c) => ({ id: c.id, at: c.at, hue: FAMILY[c.reason] ?? 4, label: c.reasonLabel }))}
110
+ onMark={(m) => onGoTo(m.id)}
111
+ axis={[
112
+ { at: 0, label: "00:00 · before the client joined" },
113
+ { at: call.length, label: `after they left · ${call.lengthWords}` },
114
+ ]}
115
+ size="lg"
116
+ />
117
+ <TimeStrip length={call.length} selection={part} onSelect={setPart} step={5} />
118
+ </>
119
+ );
120
+ }
121
+ ```
122
+
123
+ ## States
124
+
125
+ Drawn in `demo.jsx`: a call with nine marks in four colours, large and small; a
126
+ stretch away at each end; a pressed mark; marks pressable and read-only; a part
127
+ picked, and the bar to pick one; an hour-long call with twenty marks; marks on
128
+ the same second; a mark past the end and one with a bad time; a call with no
129
+ marks; no length; the app's own axis labels; loading; failed; a 320 px
130
+ container.
131
+
132
+ ## What it will not do
133
+
134
+ - Play, scrub or cut the thing it shows. It is a picture of marks.
135
+ - Keep the marks. Add, move and remove them in your own data and pass the list.
136
+ - Draw two rows (one lane per speaker): use one strip per lane.
137
+ - Colour a mark by anything but `hue` or `tone`.
138
+
139
+ A strip it cannot be is your own component in `components/`, built from the
140
+ kit, not an edit to this block. Its files are fixed: `npm run check` refuses a
141
+ change, and `makersclaw add time-strip` restores them.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "time-strip",
3
+ "title": "TimeStrip",
4
+ "description": "One bar for a span that has a length (a call, a recording, a shift), from 0 to its end, with marks at the times that matter on it. Each mark is a thin coloured post at its time (a category colour 1 to 5, or a status tone); a pressed mark is taller and ringed, and arrow keys walk from one mark to the next. Stretches somebody was away are hatched; a part can be dragged out on the bar and its two ends nudged with the arrow keys (a slider each), and the bar says it back in words. An axis under it names the start, the end and the whole steps between (00:00, 15:00, 30:00, 58:40), or the app's own labels (\"before the client joined\"). A small bar (22 px) sits under a record's title; a large one (44 px) is the screen's signature. Positions are percentages of the length, so it draws the same on the server. Loading and failed are drawn; the sums (toSeconds, clockOf, marksOf, rangeOf, ticksFor, nextMark) are exported as plain functions.",
5
+ "useWhen": "A thing that has a length in time and events at moments inside it: the cuts, decisions and comments on a recorded call or meeting, the chapters of a video, the notes pinned to a recording, the incidents in a shift or a day, the stops in a route. It draws marks the app already placed; it does not play, cut or measure anything. Not a dated chain with gates (schedule-ruler), progress against a clock (pace-bar), a calendar of events on an hour grid (time-grid, calendar-view), or an audio waveform with a playhead (audio-player).",
6
+ "tags": ["time", "strip", "timeline", "marks", "markers", "call", "meeting", "recording", "transcript", "chapters", "cuts", "range", "select a part", "scrubber", "minutes", "duration", "axis", "agent"],
7
+ "exports": ["TimeStrip", "clockOf", "countMarks", "lengthOf", "marksOf", "nextMark", "pctOf", "rangeOf", "rangesOf", "secondsAt", "shareOf", "stripWords", "ticksFor", "toSeconds"],
8
+ "files": ["index.js", "time-strip.jsx", "strip-model.js"],
9
+ "requires": []
10
+ }
@@ -0,0 +1,129 @@
1
+ "use client";
2
+
3
+ // TimeStrip in every state — the gallery's and the smoke test's surface. Not
4
+ // installed into apps: `makersclaw add time-strip` lays index.js,
5
+ // time-strip.jsx and strip-model.js only.
6
+ // A call nine cuts in four colours, small and large, the stretch
7
+ // before the client joined and after they left hatched, a
8
+ // pressed mark, the app's own axis labels.
9
+ // Pressable onMark: the marks are buttons, one is pressed; read-only
10
+ // without it.
11
+ // A part the bar to pick one (drag, or the handles' keys), the part
12
+ // said back.
13
+ // An hour twenty marks on a 58:40 call; marks on the same second.
14
+ // Odd times a mark past the end, a mark with a bad time, no marks, no
15
+ // length.
16
+ // Loading, failed, and a 320 px container.
17
+ import { useState } from "react";
18
+ import { Button } from "../components/ui";
19
+ import { TimeStrip, clockOf, toSeconds } from "../components/blocks/time-strip";
20
+
21
+ const CALL = 252;
22
+ const CUTS = [
23
+ { id: "c1", at: "00:04", hue: 1, label: "Pricing" },
24
+ { id: "c2", at: "00:12", hue: 1, label: "Pricing" },
25
+ { id: "c3", at: "00:20", hue: 4, label: "Small talk" },
26
+ { id: "c4", at: "00:31", hue: 2, label: "Third party" },
27
+ { id: "c5", at: "00:58", hue: 2, label: "Another client" },
28
+ { id: "c6", at: "01:02", hue: 4, label: "Joke" },
29
+ { id: "c7", at: "02:44", hue: 2, label: "Third party" },
30
+ { id: "c8", at: "03:05", hue: 3, label: "Off the record" },
31
+ { id: "c9", at: "04:02", hue: 1, label: "Internal" },
32
+ ];
33
+ const AWAY = [
34
+ [0, 18],
35
+ [232, 252],
36
+ ];
37
+ const HOUR = 3520;
38
+ const MANY = Array.from({ length: 20 }, (_, i) => ({ id: `h${i}`, at: 30 + i * 172, hue: (i % 4) + 1, label: "Cut" }));
39
+
40
+ function Section({ title, note, children }) {
41
+ return (
42
+ <section className="grid min-w-0 gap-2">
43
+ <h2 className="text-sm font-semibold">{title}</h2>
44
+ {note ? <p className="text-xs text-muted-foreground">{note}</p> : null}
45
+ {children}
46
+ </section>
47
+ );
48
+ }
49
+
50
+ export default function Demo() {
51
+ const [on, setOn] = useState("c4");
52
+ const [part, setPart] = useState({ from: 0, to: 120 });
53
+ const [lastPart, setLastPart] = useState(null);
54
+ return (
55
+ <div className="grid min-w-0 gap-8 p-4">
56
+ <Section title="A call, small" note="Nine cuts in four colours; the first and last stretch away are hatched.">
57
+ <TimeStrip label="The call, with every cut where it was said" noun="cut" length={CALL} marks={CUTS} away={AWAY} />
58
+ </Section>
59
+
60
+ <Section title="A call, large, with the app's own axis" note="Press a cut: it stands taller, and ← → walk to the next.">
61
+ <TimeStrip
62
+ size="lg"
63
+ label="The call, large"
64
+ noun="cut"
65
+ length="04:12"
66
+ marks={CUTS}
67
+ away={AWAY}
68
+ selected={on}
69
+ onMark={(m) => setOn(m.id)}
70
+ axis={[
71
+ { at: 0, label: "00:00 · before the client joined" },
72
+ { at: 60 },
73
+ { at: 120 },
74
+ { at: 180 },
75
+ { at: CALL, label: "after they left · 04:12" },
76
+ ]}
77
+ />
78
+ <p className="text-xs text-muted-foreground">Pressed: {CUTS.find((c) => c.id === on)?.label} at {clockOf(toSeconds(CUTS.find((c) => c.id === on)?.at))}</p>
79
+ </Section>
80
+
81
+ <Section title="Read-only" note="No onMark: the marks are pictures with a label.">
82
+ <TimeStrip noun="cut" length={CALL} marks={CUTS} away={AWAY} />
83
+ </Section>
84
+
85
+ <Section title="Pick a part" note="Drag across the bar. The handles are sliders (← → one step, Shift ten, Esc clears).">
86
+ <TimeStrip length={CALL} marks={CUTS} selection={part} onSelect={(r) => { setPart(r); setLastPart(r); }} step={5} noun="cut" />
87
+ <div className="flex items-center gap-2 text-xs text-muted-foreground">
88
+ <span>{part ? `Part: ${clockOf(part.from)} to ${clockOf(part.to)}` : "The whole call"}</span>
89
+ <Button size="sm" onClick={() => setPart(null)}>Whole call</Button>
90
+ {lastPart === null ? <span>(cleared)</span> : null}
91
+ </div>
92
+ </Section>
93
+
94
+ <Section title="An hour, twenty marks" note="58:40 on one bar.">
95
+ <TimeStrip noun="cut" length={HOUR} marks={MANY} away={[[0, 60], [3400, HOUR]]} axis ticks={5} />
96
+ </Section>
97
+
98
+ <Section title="Two marks on the same second">
99
+ <TimeStrip noun="cut" length={CALL} marks={[{ id: "a", at: 90, hue: 1 }, { id: "b", at: 90, hue: 3 }, { id: "c", at: "01:31", hue: 2 }]} onMark={() => {}} />
100
+ </Section>
101
+
102
+ <Section title="Odd times" note="A mark past the end sits at the end; a mark with a bad time is left out.">
103
+ <TimeStrip noun="mark" length={CALL} marks={[{ id: "a", at: 9999, tone: "danger", label: "After the end" }, { id: "b", at: "soon", tone: "warning" }, { id: "c", at: 60, tone: "success" }, { id: "d", at: "1:02:03", tone: "info" }]} />
104
+ </Section>
105
+
106
+ <Section title="No marks">
107
+ <TimeStrip length={CALL} marks={[]} noun="cut" />
108
+ </Section>
109
+
110
+ <Section title="No length">
111
+ <TimeStrip length={0} marks={CUTS} />
112
+ </Section>
113
+
114
+ <Section title="Loading">
115
+ <TimeStrip status="loading" length={CALL} />
116
+ </Section>
117
+
118
+ <Section title="Failed">
119
+ <TimeStrip status="failed" error="The call's times could not be read." onRetry={() => {}} />
120
+ </Section>
121
+
122
+ <Section title="Narrow (320 px)">
123
+ <div className="w-80 max-w-full">
124
+ <TimeStrip size="lg" noun="cut" length={CALL} marks={CUTS} away={AWAY} onMark={() => {}} axis={[{ at: 0, label: "00:00 · before" }, { at: CALL, label: "after · 04:12" }]} />
125
+ </div>
126
+ </Section>
127
+ </div>
128
+ );
129
+ }
@@ -0,0 +1,19 @@
1
+ // The TimeStrip block — `makersclaw add time-strip`. Fixed: compose it
2
+ // through its props (README.md beside this file). The model's helpers are
3
+ // plain functions; they work on the server too.
4
+ export { TimeStrip } from "./time-strip";
5
+ export {
6
+ clockOf,
7
+ countMarks,
8
+ lengthOf,
9
+ marksOf,
10
+ nextMark,
11
+ pctOf,
12
+ rangeOf,
13
+ rangesOf,
14
+ secondsAt,
15
+ shareOf,
16
+ stripWords,
17
+ ticksFor,
18
+ toSeconds,
19
+ } from "./strip-model";
@@ -0,0 +1,178 @@
1
+ // time-strip: the arithmetic (registry/blocks/time-strip/strip-model.js).
2
+ //
3
+ // The block draws one bar for a span that has a length (a call, a recording,
4
+ // a shift) and puts marks on it. What has to be right is where a mark lands
5
+ // (a share of the length, clamped), how a time is read and said ("04:12",
6
+ // "1:02:03"), which ticks the axis shows, how a dragged range is ordered
7
+ // and kept inside the bar, and which mark a key moves to. All plain
8
+ // functions, no React, so the server draws what the browser draws.
9
+ //
10
+ // A time is a number of seconds from the start, or a string "mm:ss",
11
+ // "h:mm:ss" or "hh:mm:ss". Anything else is null: a bad time is never
12
+ // rounded into a place on the bar.
13
+
14
+ const MAX_LENGTH = 7 * 24 * 3600;
15
+
16
+ /** Seconds in a time: 76, "01:16", "1:02:03", "76" → 76, 76, 3723, 76. null when it is not a time. */
17
+ export function toSeconds(value) {
18
+ if (typeof value === "number") return Number.isFinite(value) && value >= 0 ? value : null;
19
+ if (typeof value !== "string") return null;
20
+ const text = value.trim();
21
+ if (!text) return null;
22
+ if (/^\d+(\.\d+)?$/.test(text)) return Number(text);
23
+ const parts = text.split(":");
24
+ if (parts.length < 2 || parts.length > 3 || !parts.every((p) => /^\d{1,2}(\.\d+)?$/.test(p))) return null;
25
+ const nums = parts.map(Number);
26
+ if (nums.slice(1).some((n) => n >= 60)) return null;
27
+ return nums.reduce((total, n) => total * 60 + n, 0);
28
+ }
29
+
30
+ /** A span's length in whole seconds, or 0 when it has none. */
31
+ export function lengthOf(value) {
32
+ const s = toSeconds(value);
33
+ if (s == null || s <= 0) return 0;
34
+ return Math.min(MAX_LENGTH, Math.round(s));
35
+ }
36
+
37
+ const two = (n) => String(n).padStart(2, "0");
38
+
39
+ /** Seconds as a clock: 252 → "04:12"; 3723 → "1:02:03". `long` forces hours: 252 → "0:04:12". */
40
+ export function clockOf(seconds, { long = false } = {}) {
41
+ const s = toSeconds(seconds);
42
+ if (s == null) return "";
43
+ const whole = Math.round(s);
44
+ const h = Math.floor(whole / 3600);
45
+ const m = Math.floor((whole % 3600) / 60);
46
+ const sec = whole % 60;
47
+ return h > 0 || long ? `${h}:${two(m)}:${two(sec)}` : `${two(m)}:${two(sec)}`;
48
+ }
49
+
50
+ /** Where a time sits on the bar, as a share 0..1 of `length`. null when it is not a time or there is no length. */
51
+ export function shareOf(at, length) {
52
+ const s = toSeconds(at);
53
+ const total = lengthOf(length);
54
+ if (s == null || total <= 0) return null;
55
+ return Math.min(1, Math.max(0, s / total));
56
+ }
57
+
58
+ /** A share as a percent of the bar, rounded to a thousandth so the markup is steady. */
59
+ export function pctOf(share) {
60
+ if (share == null) return null;
61
+ return Math.round(share * 100000) / 1000;
62
+ }
63
+
64
+ /**
65
+ * The marks a bar draws: `[{ id, at, ... }]` in time order, each with its
66
+ * `seconds`, `share` and `pct`. A mark with no readable time is left out (it
67
+ * has no place); a time past the end sits at the end. Ties keep the order
68
+ * given. `id` falls back to its index.
69
+ */
70
+ export function marksOf(marks, length) {
71
+ const total = lengthOf(length);
72
+ if (!Array.isArray(marks) || total <= 0) return [];
73
+ const out = [];
74
+ marks.forEach((m, index) => {
75
+ if (!m || typeof m !== "object") return;
76
+ const seconds = toSeconds(m.at);
77
+ if (seconds == null) return;
78
+ const share = shareOf(seconds, total);
79
+ out.push({ ...m, id: m.id ?? `m${index}`, index, seconds: Math.min(seconds, total), share, pct: pctOf(share) });
80
+ });
81
+ return out.sort((a, b) => a.seconds - b.seconds || a.index - b.index);
82
+ }
83
+
84
+ /**
85
+ * Stretches laid on the bar (the part the person was away, a selection):
86
+ * `[[from, to]]` or `[{ from, to, label? }]`. Each is ordered, kept inside
87
+ * [0, length] and dropped when nothing is left of it.
88
+ */
89
+ export function rangesOf(ranges, length) {
90
+ const total = lengthOf(length);
91
+ if (!Array.isArray(ranges) || total <= 0) return [];
92
+ const out = [];
93
+ for (const r of ranges) {
94
+ const raw = Array.isArray(r) ? { from: r[0], to: r[1] } : r;
95
+ const r2 = rangeOf(raw?.from, raw?.to, total);
96
+ if (r2) out.push({ ...(Array.isArray(r) ? {} : raw), ...r2 });
97
+ }
98
+ return out;
99
+ }
100
+
101
+ /** Two times as a range kept inside the bar and in order: { from, to, fromPct, widthPct } or null when they enclose nothing. */
102
+ export function rangeOf(a, b, length, { min = 0 } = {}) {
103
+ const total = lengthOf(length);
104
+ const x = toSeconds(a);
105
+ const y = toSeconds(b);
106
+ if (x == null || y == null || total <= 0) return null;
107
+ const from = Math.min(total, Math.max(0, Math.min(x, y)));
108
+ const to = Math.min(total, Math.max(0, Math.max(x, y)));
109
+ if (to - from <= min) return null;
110
+ return { from, to, fromPct: pctOf(from / total), widthPct: pctOf((to - from) / total) };
111
+ }
112
+
113
+ /** A pointer's place on the bar (0..1 across it) as a time, snapped to `step` seconds. */
114
+ export function secondsAt(fraction, length, step = 1) {
115
+ const total = lengthOf(length);
116
+ if (total <= 0 || !Number.isFinite(fraction)) return 0;
117
+ const raw = Math.min(1, Math.max(0, fraction)) * total;
118
+ const s = Math.max(1, Number(step) || 1);
119
+ return Math.min(total, Math.round(raw / s) * s);
120
+ }
121
+
122
+ /** A nice step under `want` seconds: 1, 2, 5, 10, 15, 30 s; 1, 2, 5, 10, 15, 30 min; 1, 2, 3, 6, 12 h. */
123
+ const STEPS = [1, 2, 5, 10, 15, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200, 10800, 21600, 43200];
124
+
125
+ /**
126
+ * Axis ticks for a bar: about `count` evenly spaced labels, always the start
127
+ * and the end. `[{ at, label, share, pct, edge }]`; `edge` is "start" or
128
+ * "end" for the two ends so a label can be kept inside the bar. The inner
129
+ * ticks fall on whole steps (a quarter hour, a minute) and are dropped when
130
+ * they would crowd the end.
131
+ */
132
+ export function ticksFor(length, count = 5) {
133
+ const total = lengthOf(length);
134
+ if (total <= 0) return [];
135
+ const want = Math.max(2, Math.min(12, Math.round(count)));
136
+ const raw = total / (want - 1);
137
+ // The whole step nearest the even spacing, a little over at most: 63 s apart is a minute, not two.
138
+ const step = [...STEPS].reverse().find((s) => s <= raw * 1.25) ?? STEPS[0];
139
+ const at = [0];
140
+ for (let t = step; t < total; t += step) {
141
+ if (total - t < step * 0.4) break;
142
+ at.push(t);
143
+ }
144
+ at.push(total);
145
+ return at.map((t, i) => ({ at: t, label: clockOf(t), share: t / total, pct: pctOf(t / total), edge: i === 0 ? "start" : i === at.length - 1 ? "end" : null }));
146
+ }
147
+
148
+ /**
149
+ * The mark a key moves to from `current` (an id, or null): `dir` 1 the next
150
+ * in time, -1 the one before; at either end it stays. With nothing current,
151
+ * 1 goes to the first and -1 to the last.
152
+ */
153
+ export function nextMark(marks, current, dir) {
154
+ if (!marks.length) return null;
155
+ const at = marks.findIndex((m) => m.id === current);
156
+ if (at < 0) return (dir < 0 ? marks[marks.length - 1] : marks[0]).id;
157
+ const to = Math.min(marks.length - 1, Math.max(0, at + (dir < 0 ? -1 : 1)));
158
+ return marks[to].id;
159
+ }
160
+
161
+ /** How many marks of each hue / tone: { 1: 2, danger: 1, none: 3 }, for the words a screen reader hears. */
162
+ export function countMarks(marks) {
163
+ const out = {};
164
+ for (const m of marks) {
165
+ const key = m.hue ? String(m.hue) : (m.tone ?? "none");
166
+ out[key] = (out[key] ?? 0) + 1;
167
+ }
168
+ return out;
169
+ }
170
+
171
+ /** One line for a reader: "9 marks on a 04:12 call", "No marks". */
172
+ export function stripWords({ length, marks, noun = "mark" }) {
173
+ const total = lengthOf(length);
174
+ const n = marks.length;
175
+ if (total <= 0) return "Nothing to show";
176
+ const word = n === 1 ? noun : `${noun}s`;
177
+ return n ? `${n} ${word} in ${clockOf(total)}` : `No ${noun}s in ${clockOf(total)}`;
178
+ }