makersclaw 0.8.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 (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 +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/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 +1627 -8
  400. package/templates/next/files/lib/platform.js +529 -21
  401. package/templates/next/template.json +13 -3
@@ -0,0 +1,461 @@
1
+ "use client";
2
+
3
+ import { Button, Empty, Notice, Skeleton, cx } from "../../ui";
4
+ import { AgentMark } from "../agent-marks";
5
+ import { axisOf, dayName, groupRows, marksOnWeeks, paceOf, paceSentence, paceWords, percent, share, shortDay, toneOf, weeksOf, WORDS } from "./pace-model";
6
+
7
+ // Progress against a clock. Four pieces that share one idea, "how far
8
+ // along, and how far along should it be by now":
9
+ //
10
+ // PaceBar one bar: filled to `value`, a hard upright tick at the pace,
11
+ // and the stretch between them hatched, so "behind" is a shape
12
+ // you see and not a sum you do.
13
+ // PaceList many bars on ONE axis: the period's months and Mondays above,
14
+ // one today line running through the whole list, and each
15
+ // row's gap said in weeks ("4 wk behind"). Rows can sit in
16
+ // groups.
17
+ // PaceRuler the axis alone (month names, a tick each Monday, a flag for
18
+ // today), for a screen that lays out its own rows.
19
+ // WeekStrip the period as its weeks in one row: the weeks gone filled,
20
+ // this one marked, a mark on the week each check-in was made,
21
+ // by a person, by the agent, or by no one.
22
+ //
23
+ // Props in, one callback out (`onOpen`); the block imports only React, the
24
+ // kit and the agent's mark. README.md beside this file lists every prop.
25
+ // Server-safe: nothing here measures the page, positions are percentages.
26
+
27
+ // ---- looks (literal class names, so Tailwind sees every one)
28
+
29
+ const FILL = {
30
+ ink: "bg-foreground",
31
+ quiet: "bg-muted-foreground",
32
+ info: "bg-info",
33
+ success: "bg-success",
34
+ warning: "bg-warning",
35
+ danger: "bg-destructive",
36
+ };
37
+ // The hatch is drawn in currentColor, so a text-* token paints it.
38
+ const HATCH_TEXT = {
39
+ ink: "text-foreground",
40
+ quiet: "text-muted-foreground",
41
+ info: "text-info",
42
+ success: "text-success",
43
+ warning: "text-warning",
44
+ danger: "text-destructive",
45
+ };
46
+ const GAP_TEXT = { ...HATCH_TEXT, ink: "text-muted-foreground" };
47
+ const HATCH = { backgroundImage: "repeating-linear-gradient(135deg, currentColor 0 2px, transparent 2px 5px)" };
48
+
49
+ const SIZE = {
50
+ lg: { track: "h-3.5", tick: "-inset-y-2" },
51
+ md: { track: "h-2.5", tick: "-inset-y-1" },
52
+ sm: { track: "h-1.5", tick: "-inset-y-1" },
53
+ };
54
+
55
+ const pct = (n) => `${Math.round(n * 1000) / 1000}%`;
56
+ const asTone = (tone, p, cut) => (tone === "auto" || tone == null ? toneOf(p, cut) : FILL[tone] ? tone : "ink");
57
+
58
+ /** What the bar is made of, without a meter's role: the fill, the hatched gap, and the tick when asked. */
59
+ function Bars({ p, tone, size, hatch, tick, animate, delay }) {
60
+ const s = SIZE[size] ?? SIZE.md;
61
+ const fill = (p.value ?? 0) * 100;
62
+ const mark = p.pace == null ? null : p.pace * 100;
63
+ const spend = p.kind === "spend";
64
+ let from = 0;
65
+ let width = 0;
66
+ if (hatch && mark != null) {
67
+ if (!spend && mark > fill) [from, width] = [fill, mark - fill];
68
+ if (spend && fill > mark) [from, width] = [mark, fill - mark];
69
+ }
70
+ const grow = animate ? "transition-[width] duration-700 ease-out starting:w-0 motion-reduce:transition-none" : "";
71
+ const wait = animate && delay ? { transitionDelay: `${Math.min(540, Math.max(0, Number(delay) || 0))}ms` } : undefined;
72
+ return (
73
+ <>
74
+ <span className={cx("relative block overflow-hidden rounded-[1px] bg-muted", s.track)}>
75
+ {width ? (
76
+ <span
77
+ aria-hidden="true"
78
+ className={cx("absolute inset-y-0 left-(--from) w-(--width) opacity-60", HATCH_TEXT[tone])}
79
+ style={{ ...HATCH, "--from": pct(from), "--width": pct(width) }}
80
+ />
81
+ ) : null}
82
+ <span aria-hidden="true" className={cx("absolute inset-y-0 left-0 w-(--fill) rounded-[1px]", FILL[tone], grow)} style={{ "--fill": pct(fill), ...wait }} />
83
+ </span>
84
+ {tick && mark != null ? (
85
+ <span aria-hidden="true" className={cx("absolute left-(--mark) w-0.5 -translate-x-1/2 bg-foreground ring-1 ring-background", s.tick)} style={{ "--mark": pct(mark) }} />
86
+ ) : null}
87
+ </>
88
+ );
89
+ }
90
+
91
+ /**
92
+ * One bar against a pace. Give `pace` (0..1) yourself, or give the period
93
+ * (`start`, `end`, `today`) and the share of the time gone is the pace.
94
+ *
95
+ * Props: see README.md. In short: `value`, `pace`, `start`, `end`, `today`,
96
+ * `kind` (progress | spend), `tone` (ink | quiet | info | success | warning
97
+ * | danger | auto), `size` (lg | md | sm), `hatch`, `animate`, `delay`,
98
+ * `words`, `label`, `className`.
99
+ */
100
+ export function PaceBar({ value, pace, start, end, today, kind = "progress", tone = "ink", size = "md", hatch = true, animate = false, delay = 0, words, tolerance, graceDays, graceFraction, label = "Progress", className }) {
101
+ const p = paceOf({ value, pace, start, end, today, kind, tolerance, graceDays, graceFraction });
102
+ const t = asTone(tone, p);
103
+ const valuetext = paceSentence(p, words) || (p.valuePct == null ? "not known" : `${p.valuePct}%`);
104
+ return (
105
+ <span
106
+ role="meter"
107
+ aria-label={label}
108
+ aria-valuemin={0}
109
+ aria-valuemax={100}
110
+ aria-valuenow={p.valuePct ?? 0}
111
+ aria-valuetext={`${valuetext}${p.state === "worse" || p.state === "better" || p.state === "on" ? `. ${paceWords(p, words)}` : ""}`}
112
+ className={cx("relative block min-w-0", className)}
113
+ >
114
+ <Bars p={p} tone={t} size={size} hatch={hatch} tick animate={animate} delay={delay} />
115
+ </span>
116
+ );
117
+ }
118
+
119
+ // ---- marks
120
+
121
+ const MARK_WORDS = { person: "A person", agent: "The agent" };
122
+
123
+ /**
124
+ * Who made a check-in: a filled dot for a person, the platform's mark for
125
+ * the agent, nothing for no one. With `empty` a mark made by no one is a
126
+ * hollow ring (the place a mark would be); with `missed` it is a dashed
127
+ * ring (a week that should have one and has none). `label` is what a
128
+ * screen reader hears; leave it out when words beside the mark already say it.
129
+ */
130
+ export function PaceMark({ by, label, empty = false, missed = false, size = "sm", className }) {
131
+ const aria = label ? { role: "img", "aria-label": label, title: label } : { "aria-hidden": "true" };
132
+ const dot = size === "sm" ? "size-2" : "size-2.5";
133
+ if (by === "agent") return <AgentMark size={size === "sm" ? "xs" : size} label={label} className={className} />;
134
+ if (by === "person") return <span {...aria} className={cx("inline-block shrink-0 rounded-full bg-foreground", dot, className)} />;
135
+ if (missed) return <span {...aria} className={cx("inline-block shrink-0 rounded-full border border-dashed border-muted-foreground", dot, className)} />;
136
+ if (empty) return <span {...aria} className={cx("inline-block shrink-0 rounded-full border border-muted-foreground", dot, className)} />;
137
+ return null;
138
+ }
139
+
140
+ // ---- the ruler
141
+
142
+ /** The flag's sides: a flag near the right edge hangs left of the line, near the left edge right of it. */
143
+ const flagSide = (at) => (at > 0.78 ? "-translate-x-full" : at < 0.22 ? "" : "-translate-x-1/2");
144
+
145
+ /**
146
+ * The axis of a period: month names, a tick each week start, the today
147
+ * line and its flag. Place it in the column your rows' bars share.
148
+ * Props: `start`, `end`, `today`, `weekStartsOn`, `words`, `showToday`,
149
+ * `label`, `className`.
150
+ */
151
+ export function PaceRuler({ start, end, today, weekStartsOn = 0, words, showToday = true, label = "Period", className }) {
152
+ const w = { ...WORDS, ...words };
153
+ const axis = axisOf({ start, end, today, weekStartsOn });
154
+ if (!axis) return null;
155
+ const { period } = axis;
156
+ const at = showToday ? axis.todayAt : null;
157
+ const flag =
158
+ at == null
159
+ ? period.where === "before"
160
+ ? w.before
161
+ : null
162
+ : period.where === "after"
163
+ ? w.after
164
+ : `${w.today} · ${w.gone(percent(period.share))}`;
165
+ const summary = `${label}: ${shortDay(period.s)} to ${shortDay(period.e)}${period.t != null ? `. ${dayName(period.t)}${period.where === "in" ? `, ${percent(period.share)}% of the time gone, ${period.left} ${period.left === 1 ? "day" : "days"} left` : period.where === "after" ? ", ended" : ", not started"}` : ""}`;
166
+ return (
167
+ <span role="img" aria-label={summary} className={cx("relative block h-11 min-w-0", className)}>
168
+ {flag ? (
169
+ <span
170
+ aria-hidden="true"
171
+ className={cx(
172
+ "absolute top-0 z-10 whitespace-nowrap rounded-sm px-1.5 text-xs font-semibold leading-4",
173
+ at == null ? "left-0 bg-muted text-muted-foreground" : cx("bg-foreground text-background", flagSide(at)),
174
+ )}
175
+ style={at == null ? undefined : { left: pct(at * 100) }}
176
+ >
177
+ {flag}
178
+ </span>
179
+ ) : null}
180
+ <span aria-hidden="true" className="absolute inset-x-0 bottom-0 h-px bg-border" />
181
+ {axis.weeks.map((d) => (
182
+ <span key={`w${d.day}`} aria-hidden="true" className="absolute bottom-0 h-1.5 w-px bg-border" style={{ left: pct(d.at * 100) }} />
183
+ ))}
184
+ {axis.months.map((m) => (
185
+ <span key={`m${m.day}`} aria-hidden="true">
186
+ <span className="absolute bottom-0 h-2.5 w-px bg-foreground" style={{ left: pct(m.at * 100) }} />
187
+ <span className="absolute bottom-3 whitespace-nowrap pl-1 text-xs font-semibold text-foreground" style={{ left: pct(m.at * 100) }}>
188
+ {m.label}
189
+ </span>
190
+ </span>
191
+ ))}
192
+ {at != null ? <span aria-hidden="true" className="absolute inset-y-0 w-0.5 -translate-x-1/2 bg-foreground" style={{ left: pct(at * 100) }} /> : null}
193
+ </span>
194
+ );
195
+ }
196
+
197
+ // ---- the list
198
+
199
+ // Rows are one grid, the same columns in every row, so the bars of every
200
+ // row start and end at the same x: that is the shared axis. Narrow, a row is
201
+ // its name on one line and the bar and number under it.
202
+ const ROW = "grid grid-cols-[minmax(0,1fr)_4rem] items-center gap-x-3 gap-y-1 px-3 py-2 @2xl:grid-cols-(--cols)";
203
+ // The name takes the whole narrow row; wide it is one column, or two (name and
204
+ // meta) in a heading, where nothing sits in the meta column.
205
+ const NAME = "col-span-2 @2xl:col-span-1";
206
+ const NAME_WIDE = "col-span-2";
207
+ const HEAD = "text-xs font-semibold uppercase tracking-wide text-muted-foreground";
208
+ // The today line reaches into the row's padding and its border, so the lines
209
+ // of the rows below one another read as one.
210
+ const LINE = "pointer-events-none absolute -top-2 -bottom-[calc(0.5rem+1px)] w-0.5 -translate-x-1/2 bg-foreground";
211
+
212
+ function Track({ children, at, className }) {
213
+ return (
214
+ <span className={cx("relative min-h-5 self-stretch", className)}>
215
+ {children}
216
+ {at != null ? <span aria-hidden="true" className={LINE} style={{ left: pct(at * 100) }} /> : null}
217
+ </span>
218
+ );
219
+ }
220
+
221
+ /**
222
+ * Many bars on one axis. `rows` are `{ id, label, sub, value, pace, kind,
223
+ * tone, by, byLabel, meta, note, group }`; `groups` are `{ id, label, sub,
224
+ * note, empty }`.
225
+ *
226
+ * Props: see README.md. In short: `rows`, `groups`, `start`, `end`,
227
+ * `today`, `pace`, `kind`, `tolerance`, `graceDays`, `graceFraction`, `unit`, `words`,
228
+ * `heads`, `ruler`, `metaWidth`, `trackWidth`, `gapWidth`, `size`, `selected`,
229
+ * `onOpen`, `loading`, `error`, `onRetry`, `empty`, `emptyAction`, `label`,
230
+ * `className`.
231
+ */
232
+ export function PaceList({
233
+ rows,
234
+ groups,
235
+ start,
236
+ end,
237
+ today,
238
+ pace,
239
+ kind = "progress",
240
+ tolerance,
241
+ graceDays,
242
+ graceFraction,
243
+ unit,
244
+ words: wordsIn,
245
+ heads,
246
+ ruler = true,
247
+ weekStartsOn = 0,
248
+ warnAt,
249
+ dangerAt,
250
+ metaWidth,
251
+ trackWidth = "24rem",
252
+ gapWidth = "9rem",
253
+ size = "sm",
254
+ selected,
255
+ onOpen,
256
+ loading = false,
257
+ error,
258
+ onRetry,
259
+ empty,
260
+ emptyAction,
261
+ label = "Progress against the clock",
262
+ className,
263
+ }) {
264
+ const words = { ...WORDS, ...wordsIn };
265
+ if (loading) {
266
+ return (
267
+ <div aria-busy="true" aria-label={`${label}, loading`} className={cx("@container grid min-w-0 gap-3 px-3 py-2", className)}>
268
+ <Skeleton shape="rect" className="h-8 w-full" />
269
+ {[0, 1, 2, 3].map((i) => (
270
+ <Skeleton key={i} shape="rect" className="h-5 w-full" />
271
+ ))}
272
+ </div>
273
+ );
274
+ }
275
+ if (error) {
276
+ return (
277
+ <div className={cx("@container min-w-0", className)}>
278
+ <Notice tone="danger" title={`${label} did not load`} action={onRetry ? <Button size="sm" onClick={onRetry}>Try again</Button> : null}>
279
+ {typeof error === "string" ? error : "Something went wrong reading the rows."}
280
+ </Notice>
281
+ </div>
282
+ );
283
+ }
284
+
285
+ const axis = axisOf({ start, end, today, weekStartsOn });
286
+ const sharedPace = pace === undefined ? undefined : share(pace);
287
+ // The line: the end of today on the period, or the pace given.
288
+ const lineAt = axis ? axis.todayAt : sharedPace ?? null;
289
+ const list = rows ?? [];
290
+ const cols = ["minmax(0,1fr)", metaWidth, `minmax(10rem,${trackWidth})`, "4rem", gapWidth].filter(Boolean).join(" ");
291
+ const style = { "--cols": cols };
292
+ // In a heading the name also takes the meta column's place.
293
+ const headName = cx("min-w-0", metaWidth ? NAME_WIDE : NAME);
294
+
295
+ if (!list.length && !(groups ?? []).length) {
296
+ return (
297
+ <div className={cx("@container min-w-0", className)}>
298
+ <Empty icon="clock" title={empty ?? "Nothing to measure yet"} action={emptyAction} />
299
+ </div>
300
+ );
301
+ }
302
+
303
+ const read = new Map(
304
+ list.map((r) => {
305
+ const p = paceOf({
306
+ value: r.value,
307
+ pace: r.pace === undefined ? sharedPace : r.pace,
308
+ start,
309
+ end,
310
+ today,
311
+ kind: r.kind ?? kind,
312
+ tolerance,
313
+ graceDays,
314
+ graceFraction,
315
+ unit: r.unit ?? unit,
316
+ });
317
+ return [r, { p, tone: asTone(r.tone, p, { warnAt, dangerAt }) }];
318
+ }),
319
+ );
320
+ const grouped = groupRows(list, groups);
321
+
322
+ const head = heads ?? {};
323
+ const showRuler = ruler && axis;
324
+ const summary = `${label}: ${list.length} ${list.length === 1 ? "row" : "rows"}${axis?.period.t != null && axis.period.where === "in" ? `, ${percent(axis.period.share)}% of the time gone` : ""}`;
325
+
326
+ return (
327
+ <div role="group" aria-label={summary} className={cx("@container min-w-0", className)}>
328
+ {showRuler || head.label || head.pct || head.gap ? (
329
+ <div className={cx(ROW, "border-b border-border bg-background")} style={style}>
330
+ <span className={cx(HEAD, "self-end", headName)}>{head.label}</span>
331
+ <span className="relative col-span-2 min-w-0 self-stretch @2xl:col-span-1">
332
+ {showRuler ? <PaceRuler start={start} end={end} today={today} weekStartsOn={weekStartsOn} words={words} label={label} /> : null}
333
+ {showRuler && lineAt != null ? <span aria-hidden="true" className="absolute top-full h-[calc(0.5rem+1px)] w-0.5 -translate-x-1/2 bg-foreground" style={{ left: pct(lineAt * 100) }} /> : null}
334
+ </span>
335
+ <span className={cx(HEAD, "hidden self-end text-right @2xl:block")}>{head.pct}</span>
336
+ <span className={cx(HEAD, "hidden self-end @2xl:block")}>{head.gap}</span>
337
+ </div>
338
+ ) : null}
339
+ {grouped.map(({ group, rows: inGroup }, gi) => (
340
+ <div key={group?.id ?? `rest-${gi}`} role="group" aria-label={group?.label ?? undefined}>
341
+ {group ? (
342
+ <div className={cx(ROW, "border-b border-border bg-background")} style={style}>
343
+ <div className={cx("flex flex-wrap items-baseline gap-x-3 gap-y-0.5", headName)}>
344
+ <h3 className="text-sm font-semibold">{group.label}</h3>
345
+ {group.sub ? <span className="text-xs text-muted-foreground">{group.sub}</span> : null}
346
+ {!inGroup.length && group.empty ? <span className="text-xs text-muted-foreground">{group.empty}</span> : null}
347
+ {group.note ? <span className="text-xs text-muted-foreground">{group.note}</span> : null}
348
+ </div>
349
+ <Track at={lineAt} className="hidden @2xl:block" />
350
+ <span className="hidden @2xl:block" />
351
+ <span className="hidden @2xl:block" />
352
+ </div>
353
+ ) : null}
354
+ <ul className="m-0 grid list-none p-0">
355
+ {inGroup.map((r, i) => {
356
+ const { p, tone } = read.get(r);
357
+ const said = r.note ?? paceWords(p, words);
358
+ const Tag = onOpen ? "button" : "div";
359
+ const on = selected != null && selected === r.id;
360
+ // A row with a pace of its own gets its own tick; one on the shared clock leaves it to the line.
361
+ const own = p.pace != null && lineAt != null && Math.abs(p.pace - lineAt) > 0.004;
362
+ return (
363
+ <li key={r.id ?? i} className="min-w-0">
364
+ <Tag
365
+ {...(onOpen ? { type: "button", onClick: () => onOpen(r), "aria-current": on ? "true" : undefined } : {})}
366
+ className={cx(
367
+ ROW,
368
+ "w-full border-b border-border text-left outline-none",
369
+ onOpen && "cursor-pointer hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
370
+ on && "bg-accent",
371
+ )}
372
+ style={style}
373
+ >
374
+ <span className={cx("min-w-0", NAME)}>
375
+ <span className="block break-words text-sm font-medium leading-snug">{r.label}</span>
376
+ {r.sub ? <span className="block break-words text-xs text-muted-foreground">{r.sub}</span> : null}
377
+ </span>
378
+ {metaWidth ? <span className="col-span-2 min-w-0 @2xl:col-span-1">{r.meta}</span> : null}
379
+ <Track at={lineAt} className="col-start-1 @2xl:col-start-auto">
380
+ <span className="absolute inset-x-0 top-1/2 block -translate-y-1/2">
381
+ <span className="relative block">
382
+ <Bars p={p} tone={tone} size={size} hatch tick={own} />
383
+ </span>
384
+ </span>
385
+ </Track>
386
+ <span className="col-start-2 flex items-center justify-end gap-1.5 text-sm font-semibold tabular-nums @2xl:col-start-auto">
387
+ <PaceMark by={r.by} label={r.byLabel ?? (r.by ? MARK_WORDS[r.by] : undefined)} />
388
+ <span>{p.valuePct == null ? "–" : `${p.valuePct}%`}</span>
389
+ </span>
390
+ <span className={cx("col-span-2 min-w-0 break-words text-xs @2xl:col-span-1", p.state === "worse" && tone !== "ink" ? cx("font-medium", GAP_TEXT[tone]) : "text-muted-foreground")}>{said}</span>
391
+ </Tag>
392
+ </li>
393
+ );
394
+ })}
395
+ </ul>
396
+ </div>
397
+ ))}
398
+ </div>
399
+ );
400
+ }
401
+
402
+ // ---- the week strip
403
+
404
+ const WEEK_WORD = "Week";
405
+
406
+ /**
407
+ * The period as its weeks in one row. A week gone is filled, the current
408
+ * one is marked, weeks to come are empty. A mark sits on the week its date
409
+ * falls in: a filled dot for a person, the agent's mark, or (with `missed`)
410
+ * a dashed ring on a past week with no mark at all.
411
+ *
412
+ * Props: `start`, `end`, `today`, `marks` [{ id, date, by, label }],
413
+ * `weekStartsOn`, `missed`, `onOpen(week)`, `words`, `label`, `className`.
414
+ */
415
+ export function WeekStrip({ start, end, today, marks, weekStartsOn = 0, missed = false, onOpen, words, label = "Weeks", className }) {
416
+ const w = { week: WEEK_WORD, ...words };
417
+ const base = weeksOf({ start, end, today, weekStartsOn });
418
+ if (!base.length) return null;
419
+ const { weeks, skipped } = marksOnWeeks(base, marks);
420
+ const current = weeks.find((x) => x.current);
421
+ const total = weeks.reduce((n, x) => n + x.marks.length, 0);
422
+ const summary = `${label}: ${weeks.length} ${weeks.length === 1 ? "week" : "weeks"}${current ? `, ${w.week.toLowerCase()} ${current.n} now` : ""}, ${total} ${total === 1 ? "mark" : "marks"}${skipped ? `, ${skipped} without a date left off` : ""}`;
423
+ return (
424
+ <div className={cx("@container min-w-0", className)}>
425
+ <div role="region" aria-label={`${label}, scrolls sideways`} tabIndex={0} className="overflow-x-auto rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring">
426
+ <ol aria-label={summary} className="m-0 grid list-none gap-0.5 p-0" style={{ gridTemplateColumns: `repeat(${weeks.length}, minmax(1.5rem, 1fr))` }}>
427
+ {weeks.map((x) => {
428
+ const Tag = onOpen ? "button" : "div";
429
+ const name = `${w.week} ${x.n}, ${shortDay(x.from)} to ${shortDay(x.to)}${x.current ? ", now" : ""}${x.marks.length ? `, ${x.marks.map((m) => m.label ?? MARK_WORDS[m.by] ?? "a mark").join(", ")}` : ""}`;
430
+ return (
431
+ <li key={x.n} className="min-w-0">
432
+ <Tag
433
+ {...(onOpen ? { type: "button", onClick: () => onOpen(x), "aria-label": name } : { role: "img", "aria-label": name })}
434
+ {...(x.current ? { "aria-current": "date" } : {})}
435
+ className={cx("grid w-full min-w-0 justify-items-center gap-1 rounded-sm px-0.5 py-1 outline-none", onOpen && "cursor-pointer hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring")}
436
+ >
437
+ <span aria-hidden="true" className={cx("text-xs tabular-nums", x.current ? "font-semibold text-foreground" : "text-muted-foreground")}>
438
+ {x.n}
439
+ </span>
440
+ <span
441
+ aria-hidden="true"
442
+ className={cx("block w-full rounded-[1px]", x.state === "past" ? "h-1.5 bg-muted-foreground" : x.current ? "h-2.5 bg-foreground" : "h-1.5 bg-muted")}
443
+ />
444
+ <span aria-hidden="true" className="flex min-h-3 flex-wrap items-center justify-center gap-0.5">
445
+ {x.marks.slice(0, 3).map((m) => (
446
+ <PaceMark key={m.id} by={m.by} empty />
447
+ ))}
448
+ {x.marks.length > 3 ? <span className="text-xs text-muted-foreground">+{x.marks.length - 3}</span> : null}
449
+ {missed && x.state === "past" && !x.marks.length ? <PaceMark missed /> : null}
450
+ </span>
451
+ </Tag>
452
+ </li>
453
+ );
454
+ })}
455
+ </ol>
456
+ </div>
457
+ </div>
458
+ );
459
+ }
460
+
461
+ export default PaceBar;