makersclaw 0.1.0 → 0.3.0
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.
- package/LICENSE +21 -0
- package/README.md +41 -1
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +15 -8
- package/r/annotate.json +62 -0
- package/r/approval-request.json +52 -0
- package/r/audio-player.json +74 -0
- package/r/auth-form.json +55 -0
- package/r/board.json +55 -0
- package/r/calendar-view.json +105 -0
- package/r/cart.json +62 -0
- package/r/chart.json +83 -0
- package/r/chat.json +95 -0
- package/r/code-editor.json +94 -0
- package/r/comment-box.json +64 -0
- package/r/contact-section.json +53 -0
- package/r/core.json +341 -0
- package/r/csv-import.json +63 -0
- package/r/data-table.json +69 -0
- package/r/diagram.json +74 -0
- package/r/doc-editor.json +82 -0
- package/r/doc-page.json +61 -0
- package/r/email-render.json +73 -0
- package/r/faq.json +50 -0
- package/r/file-upload.json +54 -0
- package/r/flow-canvas.json +93 -0
- package/r/footer.json +52 -0
- package/r/gantt.json +70 -0
- package/r/job-panel.json +56 -0
- package/r/json-editor.json +66 -0
- package/r/map.json +89 -0
- package/r/menubar.json +52 -0
- package/r/mind-map.json +67 -0
- package/r/navigation-menu.json +52 -0
- package/r/order-detail.json +54 -0
- package/r/org-chart.json +66 -0
- package/r/page-builder.json +105 -0
- package/r/payment-methods.json +51 -0
- package/r/pdf-document.json +79 -0
- package/r/pdf-viewer.json +88 -0
- package/r/product-detail.json +76 -0
- package/r/product-grid.json +65 -0
- package/r/record-form.json +67 -0
- package/r/record-notes.json +55 -0
- package/r/registry.json +3612 -0
- package/r/search-dialog.json +51 -0
- package/r/settings-list.json +66 -0
- package/r/setup-checklist.json +51 -0
- package/r/share-dialog.json +52 -0
- package/r/sidebar.json +69 -0
- package/r/signature-pad.json +72 -0
- package/r/sketch-canvas.json +99 -0
- package/r/spreadsheet.json +90 -0
- package/r/stat-cards.json +66 -0
- package/r/task-list.json +63 -0
- package/r/task-model.json +98 -0
- package/r/testimonials.json +52 -0
- package/r/transaction-list.json +53 -0
- package/r/whiteboard.json +66 -0
- package/registry/blocks/annotate/README.md +179 -0
- package/registry/blocks/annotate/annotate-data.js +250 -0
- package/registry/blocks/annotate/annotate.jsx +646 -0
- package/registry/blocks/annotate/block.json +10 -0
- package/registry/blocks/annotate/demo.jsx +135 -0
- package/registry/blocks/annotate/index.js +15 -0
- package/registry/blocks/approval-request/README.md +116 -0
- package/registry/blocks/approval-request/approval-request.jsx +386 -0
- package/registry/blocks/approval-request/block.json +10 -0
- package/registry/blocks/approval-request/demo.jsx +127 -0
- package/registry/blocks/approval-request/index.js +4 -0
- package/registry/blocks/audio-player/README.md +167 -0
- package/registry/blocks/audio-player/audio-player.jsx +623 -0
- package/registry/blocks/audio-player/block.json +14 -0
- package/registry/blocks/audio-player/colors.js +109 -0
- package/registry/blocks/audio-player/demo.jsx +209 -0
- package/registry/blocks/audio-player/index.js +6 -0
- package/registry/blocks/audio-player/time.js +67 -0
- package/registry/blocks/audio-player/wavesurfer.js +9 -0
- package/registry/blocks/auth-form/README.md +126 -0
- package/registry/blocks/auth-form/auth-form.jsx +568 -0
- package/registry/blocks/auth-form/block.json +10 -0
- package/registry/blocks/auth-form/demo.jsx +131 -0
- package/registry/blocks/auth-form/index.js +3 -0
- package/registry/blocks/board/README.md +64 -13
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +237 -94
- package/registry/blocks/board/demo.jsx +103 -24
- package/registry/blocks/calendar-view/README.md +180 -0
- package/registry/blocks/calendar-view/agenda.jsx +147 -0
- package/registry/blocks/calendar-view/block.json +76 -0
- package/registry/blocks/calendar-view/calendar-model.js +442 -0
- package/registry/blocks/calendar-view/calendar.jsx +627 -0
- package/registry/blocks/calendar-view/demo.jsx +195 -0
- package/registry/blocks/calendar-view/draft.jsx +49 -0
- package/registry/blocks/calendar-view/index.js +39 -0
- package/registry/blocks/calendar-view/month.jsx +346 -0
- package/registry/blocks/calendar-view/paint.js +69 -0
- package/registry/blocks/calendar-view/time-grid.jsx +527 -0
- package/registry/blocks/calendar-view/tray.jsx +87 -0
- package/registry/blocks/cart/README.md +146 -0
- package/registry/blocks/cart/block.json +10 -0
- package/registry/blocks/cart/cart.jsx +597 -0
- package/registry/blocks/cart/demo.jsx +98 -0
- package/registry/blocks/cart/index.js +4 -0
- package/registry/blocks/cart/money.js +28 -0
- package/registry/blocks/chart/README.md +316 -0
- package/registry/blocks/chart/block.json +10 -0
- package/registry/blocks/chart/cartesian.jsx +642 -0
- package/registry/blocks/chart/core.jsx +262 -0
- package/registry/blocks/chart/demo.jsx +357 -0
- package/registry/blocks/chart/heatmap.jsx +336 -0
- package/registry/blocks/chart/index.js +8 -0
- package/registry/blocks/chart/pie.jsx +245 -0
- package/registry/blocks/chart/sparkline.jsx +88 -0
- package/registry/blocks/chat/README.md +273 -0
- package/registry/blocks/chat/attachment.jsx +95 -0
- package/registry/blocks/chat/block.json +10 -0
- package/registry/blocks/chat/chat.jsx +132 -0
- package/registry/blocks/chat/composer.jsx +364 -0
- package/registry/blocks/chat/demo.jsx +578 -0
- package/registry/blocks/chat/header.jsx +34 -0
- package/registry/blocks/chat/index.js +9 -0
- package/registry/blocks/chat/message.jsx +450 -0
- package/registry/blocks/chat/scroller.jsx +247 -0
- package/registry/blocks/chat/text.jsx +104 -0
- package/registry/blocks/code-editor/README.md +210 -0
- package/registry/blocks/code-editor/block.json +22 -0
- package/registry/blocks/code-editor/code-editor.jsx +534 -0
- package/registry/blocks/code-editor/codemirror.js +38 -0
- package/registry/blocks/code-editor/demo.jsx +205 -0
- package/registry/blocks/code-editor/index.js +8 -0
- package/registry/blocks/code-editor/json.js +317 -0
- package/registry/blocks/code-editor/sql.js +136 -0
- package/registry/blocks/code-editor/text.js +101 -0
- package/registry/blocks/code-editor/theme.js +186 -0
- package/registry/blocks/comment-box/README.md +123 -0
- package/registry/blocks/comment-box/block.json +10 -0
- package/registry/blocks/comment-box/comment-body.jsx +217 -0
- package/registry/blocks/comment-box/comment-box.jsx +198 -0
- package/registry/blocks/comment-box/comment-time.jsx +77 -0
- package/registry/blocks/comment-box/demo.jsx +141 -0
- package/registry/blocks/comment-box/index.js +8 -0
- package/registry/blocks/contact-section/README.md +152 -0
- package/registry/blocks/contact-section/block.json +11 -0
- package/registry/blocks/contact-section/contact-section.jsx +509 -0
- package/registry/blocks/contact-section/demo.jsx +93 -0
- package/registry/blocks/contact-section/index.js +4 -0
- package/registry/blocks/csv-import/README.md +133 -0
- package/registry/blocks/csv-import/block.json +13 -0
- package/registry/blocks/csv-import/csv-import.jsx +479 -0
- package/registry/blocks/csv-import/demo.jsx +106 -0
- package/registry/blocks/csv-import/import.js +200 -0
- package/registry/blocks/csv-import/index.js +7 -0
- package/registry/blocks/data-table/README.md +386 -0
- package/registry/blocks/data-table/block.json +10 -0
- package/registry/blocks/data-table/data-table.jsx +1164 -0
- package/registry/blocks/data-table/demo.jsx +588 -0
- package/registry/blocks/data-table/index.js +5 -0
- package/registry/blocks/data-table/model.js +169 -0
- package/registry/blocks/diagram/README.md +108 -0
- package/registry/blocks/diagram/block.json +13 -0
- package/registry/blocks/diagram/demo.jsx +113 -0
- package/registry/blocks/diagram/diagram.jsx +481 -0
- package/registry/blocks/diagram/index.js +7 -0
- package/registry/blocks/diagram/mermaid.js +52 -0
- package/registry/blocks/diagram/palette.js +313 -0
- package/registry/blocks/diagram/source.js +98 -0
- package/registry/blocks/doc-editor/README.md +215 -0
- package/registry/blocks/doc-editor/block.json +15 -0
- package/registry/blocks/doc-editor/demo.jsx +225 -0
- package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
- package/registry/blocks/doc-editor/doc.js +309 -0
- package/registry/blocks/doc-editor/index.js +7 -0
- package/registry/blocks/doc-editor/schema.jsx +56 -0
- package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
- package/registry/blocks/doc-editor/theme.js +82 -0
- package/registry/blocks/doc-page/README.md +119 -0
- package/registry/blocks/doc-page/autosave.js +104 -0
- package/registry/blocks/doc-page/block.json +10 -0
- package/registry/blocks/doc-page/demo.jsx +137 -0
- package/registry/blocks/doc-page/doc-page.jsx +276 -0
- package/registry/blocks/doc-page/index.js +4 -0
- package/registry/blocks/email-render/README.md +151 -0
- package/registry/blocks/email-render/block.json +14 -0
- package/registry/blocks/email-render/demo.jsx +153 -0
- package/registry/blocks/email-render/doc-email.jsx +210 -0
- package/registry/blocks/email-render/email.jsx +221 -0
- package/registry/blocks/email-render/index.js +10 -0
- package/registry/blocks/email-render/render.js +50 -0
- package/registry/blocks/email-render/theme.js +215 -0
- package/registry/blocks/faq/README.md +101 -0
- package/registry/blocks/faq/block.json +11 -0
- package/registry/blocks/faq/demo.jsx +89 -0
- package/registry/blocks/faq/faq.jsx +220 -0
- package/registry/blocks/faq/index.js +4 -0
- package/registry/blocks/file-upload/README.md +138 -0
- package/registry/blocks/file-upload/block.json +10 -0
- package/registry/blocks/file-upload/demo.jsx +204 -0
- package/registry/blocks/file-upload/file-upload.jsx +635 -0
- package/registry/blocks/file-upload/index.js +4 -0
- package/registry/blocks/flow-canvas/README.md +420 -0
- package/registry/blocks/flow-canvas/block.json +13 -0
- package/registry/blocks/flow-canvas/board.js +819 -0
- package/registry/blocks/flow-canvas/chrome.jsx +649 -0
- package/registry/blocks/flow-canvas/context.jsx +35 -0
- package/registry/blocks/flow-canvas/demo.jsx +249 -0
- package/registry/blocks/flow-canvas/edges.jsx +107 -0
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
- package/registry/blocks/flow-canvas/index.js +41 -0
- package/registry/blocks/flow-canvas/nodes.jsx +392 -0
- package/registry/blocks/flow-canvas/theme.js +174 -0
- package/registry/blocks/footer/README.md +133 -0
- package/registry/blocks/footer/block.json +11 -0
- package/registry/blocks/footer/demo.jsx +119 -0
- package/registry/blocks/footer/footer.jsx +406 -0
- package/registry/blocks/footer/index.js +4 -0
- package/registry/blocks/gantt/README.md +220 -0
- package/registry/blocks/gantt/block.json +10 -0
- package/registry/blocks/gantt/demo.jsx +148 -0
- package/registry/blocks/gantt/gantt.jsx +923 -0
- package/registry/blocks/gantt/index.js +7 -0
- package/registry/blocks/gantt/rows.jsx +468 -0
- package/registry/blocks/gantt/schedule.js +278 -0
- package/registry/blocks/job-panel/README.md +86 -2
- package/registry/blocks/job-panel/block.json +3 -3
- package/registry/blocks/job-panel/demo.jsx +230 -3
- package/registry/blocks/job-panel/job-panel.jsx +169 -3
- package/registry/blocks/json-editor/README.md +133 -0
- package/registry/blocks/json-editor/block.json +10 -0
- package/registry/blocks/json-editor/demo.jsx +92 -0
- package/registry/blocks/json-editor/index.js +7 -0
- package/registry/blocks/json-editor/json-editor.jsx +305 -0
- package/registry/blocks/json-editor/json-tree.jsx +393 -0
- package/registry/blocks/json-editor/tree.js +225 -0
- package/registry/blocks/map/README.md +221 -0
- package/registry/blocks/map/block.json +14 -0
- package/registry/blocks/map/demo.jsx +201 -0
- package/registry/blocks/map/geo.js +198 -0
- package/registry/blocks/map/index.js +8 -0
- package/registry/blocks/map/list.jsx +128 -0
- package/registry/blocks/map/map-view.jsx +715 -0
- package/registry/blocks/map/maplibre.js +30 -0
- package/registry/blocks/map/marks.jsx +146 -0
- package/registry/blocks/map/theme.js +142 -0
- package/registry/blocks/menubar/README.md +109 -0
- package/registry/blocks/menubar/block.json +10 -0
- package/registry/blocks/menubar/demo.jsx +128 -0
- package/registry/blocks/menubar/index.js +4 -0
- package/registry/blocks/menubar/menubar.jsx +199 -0
- package/registry/blocks/mind-map/README.md +206 -0
- package/registry/blocks/mind-map/block.json +10 -0
- package/registry/blocks/mind-map/demo.jsx +103 -0
- package/registry/blocks/mind-map/index.js +31 -0
- package/registry/blocks/mind-map/mind-map.jsx +1125 -0
- package/registry/blocks/mind-map/topic.jsx +143 -0
- package/registry/blocks/mind-map/tree.js +645 -0
- package/registry/blocks/navigation-menu/README.md +124 -0
- package/registry/blocks/navigation-menu/block.json +10 -0
- package/registry/blocks/navigation-menu/demo.jsx +84 -0
- package/registry/blocks/navigation-menu/index.js +4 -0
- package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
- package/registry/blocks/order-detail/README.md +109 -0
- package/registry/blocks/order-detail/block.json +10 -0
- package/registry/blocks/order-detail/demo.jsx +88 -0
- package/registry/blocks/order-detail/index.js +4 -0
- package/registry/blocks/order-detail/order-detail.jsx +354 -0
- package/registry/blocks/org-chart/README.md +145 -0
- package/registry/blocks/org-chart/block.json +10 -0
- package/registry/blocks/org-chart/demo.jsx +94 -0
- package/registry/blocks/org-chart/index.js +7 -0
- package/registry/blocks/org-chart/org-chart.jsx +631 -0
- package/registry/blocks/org-chart/org.js +245 -0
- package/registry/blocks/org-chart/person.jsx +96 -0
- package/registry/blocks/page-builder/README.md +257 -0
- package/registry/blocks/page-builder/block.json +14 -0
- package/registry/blocks/page-builder/demo.jsx +145 -0
- package/registry/blocks/page-builder/grapes.js +18 -0
- package/registry/blocks/page-builder/index.js +11 -0
- package/registry/blocks/page-builder/page-builder.jsx +704 -0
- package/registry/blocks/page-builder/page-view.jsx +33 -0
- package/registry/blocks/page-builder/page.js +118 -0
- package/registry/blocks/page-builder/panels.jsx +588 -0
- package/registry/blocks/page-builder/sections.js +209 -0
- package/registry/blocks/page-builder/theme.js +87 -0
- package/registry/blocks/page-builder/thumbs.jsx +189 -0
- package/registry/blocks/page-builder/tokens.js +329 -0
- package/registry/blocks/payment-methods/README.md +104 -0
- package/registry/blocks/payment-methods/block.json +10 -0
- package/registry/blocks/payment-methods/demo.jsx +71 -0
- package/registry/blocks/payment-methods/index.js +4 -0
- package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
- package/registry/blocks/pdf-document/README.md +213 -0
- package/registry/blocks/pdf-document/block.json +13 -0
- package/registry/blocks/pdf-document/demo.jsx +136 -0
- package/registry/blocks/pdf-document/index.js +33 -0
- package/registry/blocks/pdf-document/money.js +83 -0
- package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
- package/registry/blocks/pdf-document/primitives.jsx +271 -0
- package/registry/blocks/pdf-document/quote.jsx +179 -0
- package/registry/blocks/pdf-document/theme.js +193 -0
- package/registry/blocks/pdf-viewer/README.md +191 -0
- package/registry/blocks/pdf-viewer/block.json +14 -0
- package/registry/blocks/pdf-viewer/demo.jsx +252 -0
- package/registry/blocks/pdf-viewer/helpers.js +270 -0
- package/registry/blocks/pdf-viewer/index.js +8 -0
- package/registry/blocks/pdf-viewer/notes.jsx +195 -0
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
- package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
- package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
- package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
- package/registry/blocks/product-detail/README.md +217 -0
- package/registry/blocks/product-detail/block.json +10 -0
- package/registry/blocks/product-detail/demo.jsx +233 -0
- package/registry/blocks/product-detail/index.js +7 -0
- package/registry/blocks/product-detail/price.jsx +115 -0
- package/registry/blocks/product-detail/product-detail.jsx +348 -0
- package/registry/blocks/product-detail/product-media.jsx +102 -0
- package/registry/blocks/product-detail/product-options.jsx +144 -0
- package/registry/blocks/product-grid/README.md +162 -0
- package/registry/blocks/product-grid/block.json +10 -0
- package/registry/blocks/product-grid/demo.jsx +255 -0
- package/registry/blocks/product-grid/index.js +5 -0
- package/registry/blocks/product-grid/product-card.jsx +232 -0
- package/registry/blocks/product-grid/product-grid.jsx +235 -0
- package/registry/blocks/record-form/README.md +196 -0
- package/registry/blocks/record-form/block.json +10 -0
- package/registry/blocks/record-form/demo.jsx +525 -0
- package/registry/blocks/record-form/index.js +4 -0
- package/registry/blocks/record-form/record-fields.jsx +457 -0
- package/registry/blocks/record-form/record-form.jsx +415 -0
- package/registry/blocks/record-form/rules.js +81 -0
- package/registry/blocks/record-notes/README.md +139 -0
- package/registry/blocks/record-notes/block.json +10 -0
- package/registry/blocks/record-notes/demo.jsx +179 -0
- package/registry/blocks/record-notes/index.js +4 -0
- package/registry/blocks/record-notes/record-notes.jsx +266 -0
- package/registry/blocks/search-dialog/README.md +108 -0
- package/registry/blocks/search-dialog/block.json +10 -0
- package/registry/blocks/search-dialog/demo.jsx +116 -0
- package/registry/blocks/search-dialog/index.js +3 -0
- package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
- package/registry/blocks/settings-list/README.md +171 -0
- package/registry/blocks/settings-list/block.json +10 -0
- package/registry/blocks/settings-list/demo.jsx +333 -0
- package/registry/blocks/settings-list/index.js +4 -0
- package/registry/blocks/settings-list/row-state.jsx +93 -0
- package/registry/blocks/settings-list/settings-list.jsx +349 -0
- package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
- package/registry/blocks/setup-checklist/README.md +142 -0
- package/registry/blocks/setup-checklist/block.json +10 -0
- package/registry/blocks/setup-checklist/demo.jsx +159 -0
- package/registry/blocks/setup-checklist/index.js +4 -0
- package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
- package/registry/blocks/share-dialog/README.md +113 -0
- package/registry/blocks/share-dialog/block.json +10 -0
- package/registry/blocks/share-dialog/demo.jsx +140 -0
- package/registry/blocks/share-dialog/index.js +3 -0
- package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
- package/registry/blocks/sidebar/README.md +190 -0
- package/registry/blocks/sidebar/block.json +43 -0
- package/registry/blocks/sidebar/demo.jsx +577 -0
- package/registry/blocks/sidebar/index.js +4 -0
- package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
- package/registry/blocks/sidebar/sidebar.jsx +864 -0
- package/registry/blocks/signature-pad/README.md +137 -0
- package/registry/blocks/signature-pad/block.json +13 -0
- package/registry/blocks/signature-pad/colors.js +115 -0
- package/registry/blocks/signature-pad/demo.jsx +94 -0
- package/registry/blocks/signature-pad/index.js +6 -0
- package/registry/blocks/signature-pad/pad.js +7 -0
- package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
- package/registry/blocks/signature-pad/signature.js +68 -0
- package/registry/blocks/sketch-canvas/README.md +280 -0
- package/registry/blocks/sketch-canvas/block.json +13 -0
- package/registry/blocks/sketch-canvas/demo.jsx +159 -0
- package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
- package/registry/blocks/sketch-canvas/index.js +9 -0
- package/registry/blocks/sketch-canvas/palette.js +226 -0
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
- package/registry/blocks/sketch-canvas/sketch.js +179 -0
- package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
- package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
- package/registry/blocks/sketch-canvas/stamps.js +104 -0
- package/registry/blocks/sketch-canvas/theme.js +131 -0
- package/registry/blocks/spreadsheet/README.md +307 -0
- package/registry/blocks/spreadsheet/block.json +13 -0
- package/registry/blocks/spreadsheet/cells.jsx +455 -0
- package/registry/blocks/spreadsheet/chrome.jsx +325 -0
- package/registry/blocks/spreadsheet/demo.jsx +177 -0
- package/registry/blocks/spreadsheet/grid.js +387 -0
- package/registry/blocks/spreadsheet/index.js +34 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
- package/registry/blocks/spreadsheet/types.js +473 -0
- package/registry/blocks/stat-cards/README.md +173 -0
- package/registry/blocks/stat-cards/block.json +10 -0
- package/registry/blocks/stat-cards/demo.jsx +257 -0
- package/registry/blocks/stat-cards/index.js +4 -0
- package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
- package/registry/blocks/stat-cards/usage.jsx +243 -0
- package/registry/blocks/task-list/README.md +176 -0
- package/registry/blocks/task-list/block.json +10 -0
- package/registry/blocks/task-list/demo.jsx +134 -0
- package/registry/blocks/task-list/index.js +5 -0
- package/registry/blocks/task-list/task-list.jsx +907 -0
- package/registry/blocks/task-model/README.md +455 -0
- package/registry/blocks/task-model/block.json +167 -0
- package/registry/blocks/task-model/changes.js +89 -0
- package/registry/blocks/task-model/dates.js +371 -0
- package/registry/blocks/task-model/demo.jsx +215 -0
- package/registry/blocks/task-model/dnd.jsx +240 -0
- package/registry/blocks/task-model/index.js +97 -0
- package/registry/blocks/task-model/model.js +919 -0
- package/registry/blocks/task-model/parts.jsx +449 -0
- package/registry/blocks/task-model/toolbar.jsx +271 -0
- package/registry/blocks/testimonials/README.md +139 -0
- package/registry/blocks/testimonials/block.json +11 -0
- package/registry/blocks/testimonials/demo.jsx +137 -0
- package/registry/blocks/testimonials/index.js +4 -0
- package/registry/blocks/testimonials/testimonials.jsx +430 -0
- package/registry/blocks/transaction-list/README.md +126 -0
- package/registry/blocks/transaction-list/block.json +10 -0
- package/registry/blocks/transaction-list/demo.jsx +79 -0
- package/registry/blocks/transaction-list/index.js +4 -0
- package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
- package/registry/blocks/whiteboard/README.md +179 -0
- package/registry/blocks/whiteboard/block.json +10 -0
- package/registry/blocks/whiteboard/demo.jsx +169 -0
- package/registry/blocks/whiteboard/index.js +6 -0
- package/registry/blocks/whiteboard/templates.js +150 -0
- package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
- package/src/install.mjs +18 -0
- package/src/shadcn.mjs +171 -0
- package/templates/next/files/README.md +145 -11
- package/templates/next/files/app/globals.css +55 -4
- package/templates/next/files/check/run.mjs +3 -3
- package/templates/next/files/components/parts/fixture.jsx +1 -1
- package/templates/next/files/components/parts/sample.js +15 -0
- package/templates/next/files/components/ui/avatar.jsx +141 -0
- package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
- package/templates/next/files/components/ui/button-group.jsx +70 -0
- package/templates/next/files/components/ui/button.jsx +132 -12
- package/templates/next/files/components/ui/calendar.jsx +609 -0
- package/templates/next/files/components/ui/carousel.jsx +281 -0
- package/templates/next/files/components/ui/collapsible.jsx +208 -0
- package/templates/next/files/components/ui/combobox.jsx +608 -0
- package/templates/next/files/components/ui/command.jsx +577 -0
- package/templates/next/files/components/ui/context-menu.jsx +191 -0
- package/templates/next/files/components/ui/date-picker.jsx +360 -0
- package/templates/next/files/components/ui/distribution.jsx +117 -0
- package/templates/next/files/components/ui/feedback.jsx +143 -0
- package/templates/next/files/components/ui/field.jsx +115 -3
- package/templates/next/files/components/ui/file-input.jsx +234 -0
- package/templates/next/files/components/ui/icon.jsx +130 -8
- package/templates/next/files/components/ui/image.jsx +143 -0
- package/templates/next/files/components/ui/index.js +47 -2
- package/templates/next/files/components/ui/input-group.jsx +213 -0
- package/templates/next/files/components/ui/input-otp.jsx +170 -0
- package/templates/next/files/components/ui/item.jsx +206 -0
- package/templates/next/files/components/ui/menu.jsx +454 -82
- package/templates/next/files/components/ui/notice.jsx +126 -14
- package/templates/next/files/components/ui/pagination.jsx +156 -0
- package/templates/next/files/components/ui/popover.jsx +284 -0
- package/templates/next/files/components/ui/radio.jsx +193 -0
- package/templates/next/files/components/ui/rating.jsx +131 -0
- package/templates/next/files/components/ui/resizable.jsx +338 -0
- package/templates/next/files/components/ui/scroll-area.jsx +123 -0
- package/templates/next/files/components/ui/separator.jsx +119 -0
- package/templates/next/files/components/ui/sheet.jsx +96 -11
- package/templates/next/files/components/ui/slider.jsx +174 -0
- package/templates/next/files/components/ui/stat.jsx +574 -0
- package/templates/next/files/components/ui/steps.jsx +338 -0
- package/templates/next/files/components/ui/swatch.jsx +33 -0
- package/templates/next/files/components/ui/table.jsx +130 -0
- package/templates/next/files/components/ui/toast.jsx +440 -0
- package/templates/next/files/components/ui/toggle.jsx +195 -0
- package/templates/next/files/components/ui/tooltip.jsx +270 -0
- package/templates/next/files/lib/sample.js +4 -12
- package/templates/next/template.json +264 -8
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useId, useState } from "react";
|
|
4
|
+
import { Button, Card, Delta, Distribution, Field, Icon, InputGroup, Meter, Notice, Sheet, Stat, cx } from "../../ui";
|
|
5
|
+
|
|
6
|
+
// The `usage` shape of StatCards: an amount against a limit, one tile
|
|
7
|
+
// each — a bar or a ring, or a split by kind with what is left, a warning
|
|
8
|
+
// line near the cap, an action along the tile's foot, and a limit the
|
|
9
|
+
// founder can change in a Sheet (the save goes out through
|
|
10
|
+
// onLimitChange and may fail). The LIST of meters with a summary strip is
|
|
11
|
+
// not this block: that is a different job.
|
|
12
|
+
|
|
13
|
+
const EN = "en-US";
|
|
14
|
+
const plain = (n) => (typeof n === "number" ? n.toLocaleString(EN, { maximumFractionDigits: 2 }) : String(n ?? ""));
|
|
15
|
+
const finite = (n) => typeof n === "number" && Number.isFinite(n);
|
|
16
|
+
const NOTE_TONES = { muted: "text-muted-foreground", success: "text-success", warning: "text-warning", danger: "text-destructive", info: "text-info" };
|
|
17
|
+
|
|
18
|
+
// "View more →": an href is a link, onSelect a button.
|
|
19
|
+
export function MoreLink({ item, fallback }) {
|
|
20
|
+
const text = item.linkLabel ?? fallback;
|
|
21
|
+
const common = { variant: "link", size: "sm", "aria-label": `${text}: ${item.label}` };
|
|
22
|
+
const body = (
|
|
23
|
+
<>
|
|
24
|
+
{text}
|
|
25
|
+
<Icon name="arrow-right" size={14} className="ml-1 inline-block align-[-0.125em]" />
|
|
26
|
+
</>
|
|
27
|
+
);
|
|
28
|
+
if (item.href) return <Button href={item.href} {...common}>{body}</Button>;
|
|
29
|
+
return (
|
|
30
|
+
<Button onClick={() => item.onSelect?.(item)} {...common}>
|
|
31
|
+
{body}
|
|
32
|
+
</Button>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// The numbers a tile shows, worked out once.
|
|
37
|
+
function readUsage(item, format, warnAt) {
|
|
38
|
+
const fmt = format ?? plain;
|
|
39
|
+
const u = item.unit ? ` ${item.unit}` : "";
|
|
40
|
+
const used = finite(item.used) ? item.used : 0;
|
|
41
|
+
const capped = finite(item.limit) && item.limit > 0;
|
|
42
|
+
const pct = capped ? (used / item.limit) * 100 : null;
|
|
43
|
+
const usedText = item.value ?? `${fmt(used)}${u}`;
|
|
44
|
+
const limitText = item.limitText ?? (capped ? `${fmt(item.limit)}${u}` : "Unlimited");
|
|
45
|
+
const near = pct !== null && pct >= warnAt;
|
|
46
|
+
const noteTone = item.noteTone ?? (pct !== null && pct > 100 ? "danger" : near ? "warning" : "muted");
|
|
47
|
+
// A limit is shown when there is one, when it is named ("Unlimited",
|
|
48
|
+
// "$150 budget"), or when limit is null: no cap, said so.
|
|
49
|
+
const showLimit = capped || item.limit === null || item.limitText !== undefined;
|
|
50
|
+
return { fmt, u, used, capped, pct, usedText, limitText, near, noteTone, showLimit };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const pctText = (pct) => `${pct < 10 && pct > 0 ? Math.round(pct * 10) / 10 : Math.round(pct)}%`;
|
|
54
|
+
|
|
55
|
+
export function UsageTile({ item, meter, format, warnAt, linkLabel, limitLabel, onEditLimit }) {
|
|
56
|
+
const r = readUsage(item, format, warnAt);
|
|
57
|
+
const parts = Array.isArray(item.parts) && item.parts.length ? item.parts : null;
|
|
58
|
+
const thresholds = item.thresholds ?? [{ at: warnAt, tone: "warning" }];
|
|
59
|
+
const ring = meter === "ring" && r.capped && !parts;
|
|
60
|
+
const d = item.delta === null || item.delta === undefined ? null : typeof item.delta === "number" ? { value: item.delta, suffix: "%" } : item.delta;
|
|
61
|
+
const buttons = [
|
|
62
|
+
item.action ? { key: "action", label: item.action.label, icon: item.action.icon, run: () => item.action.onSelect?.(item) } : null,
|
|
63
|
+
onEditLimit ? { key: "limit", label: limitLabel, icon: "pencil", run: onEditLimit } : null,
|
|
64
|
+
].filter(Boolean);
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<Card as="div" padding="none" className="flex h-full min-w-0 flex-col">
|
|
68
|
+
<div className="grid flex-1 content-start gap-3 p-4 [overflow-wrap:anywhere]">
|
|
69
|
+
{ring ? (
|
|
70
|
+
<Meter
|
|
71
|
+
shape="ring"
|
|
72
|
+
size="md"
|
|
73
|
+
value={r.used}
|
|
74
|
+
max={item.limit}
|
|
75
|
+
label={item.label}
|
|
76
|
+
format={r.fmt}
|
|
77
|
+
unit={item.unit}
|
|
78
|
+
valueText={item.valueText ?? `${r.usedText} of ${r.limitText}`}
|
|
79
|
+
caption={item.caption}
|
|
80
|
+
thresholds={thresholds}
|
|
81
|
+
/>
|
|
82
|
+
) : (
|
|
83
|
+
<>
|
|
84
|
+
<div className="flex min-w-0 items-start justify-between gap-3">
|
|
85
|
+
<span className="min-w-0 truncate text-sm font-medium text-muted-foreground">{item.label}</span>
|
|
86
|
+
{d ? <Delta invert={item.invert} variant="badge" {...d} className="shrink-0" /> : null}
|
|
87
|
+
</div>
|
|
88
|
+
<Stat value={r.usedText} unit={r.showLimit ? `/ ${r.limitText}` : item.suffix} caption={item.caption} size="md" className="-mt-2" />
|
|
89
|
+
{parts ? (
|
|
90
|
+
<Distribution
|
|
91
|
+
segments={parts}
|
|
92
|
+
total={r.capped ? item.limit : undefined}
|
|
93
|
+
restLabel={r.capped ? item.restLabel ?? "Free" : undefined}
|
|
94
|
+
legend
|
|
95
|
+
size="thin"
|
|
96
|
+
label={`${item.label}: ${r.usedText} of ${r.limitText}`}
|
|
97
|
+
formatValue={(v) => `${r.fmt(v)}${r.u}`}
|
|
98
|
+
formatLegend={({ value, share, rest }) => (r.capped || rest ? `${r.fmt(value)}${r.u}` : `${r.fmt(value)}${r.u} · ${share}`)}
|
|
99
|
+
/>
|
|
100
|
+
) : r.capped ? (
|
|
101
|
+
<Meter
|
|
102
|
+
value={r.used}
|
|
103
|
+
max={item.limit}
|
|
104
|
+
format={r.fmt}
|
|
105
|
+
unit={item.unit}
|
|
106
|
+
valueText={null}
|
|
107
|
+
aria-label={item.label}
|
|
108
|
+
thresholds={thresholds}
|
|
109
|
+
caption={`${pctText(r.pct)} used`}
|
|
110
|
+
/>
|
|
111
|
+
) : null}
|
|
112
|
+
</>
|
|
113
|
+
)}
|
|
114
|
+
{item.note ? (
|
|
115
|
+
<p className={cx("text-sm", NOTE_TONES[r.noteTone] ?? NOTE_TONES.muted)}>
|
|
116
|
+
{r.noteTone === "warning" || r.noteTone === "danger" ? <Icon name="warning" size={14} className="mr-1 inline-block align-[-0.125em]" /> : null}
|
|
117
|
+
{item.note}
|
|
118
|
+
</p>
|
|
119
|
+
) : null}
|
|
120
|
+
</div>
|
|
121
|
+
{item.href || item.onSelect ? (
|
|
122
|
+
<div className="flex justify-end border-t border-border px-4 py-2.5">
|
|
123
|
+
<MoreLink item={item} fallback={linkLabel} />
|
|
124
|
+
</div>
|
|
125
|
+
) : null}
|
|
126
|
+
{buttons.length ? (
|
|
127
|
+
<div className="flex border-t border-border bg-muted/40">
|
|
128
|
+
{buttons.map((b, i) => (
|
|
129
|
+
<Button
|
|
130
|
+
key={b.key}
|
|
131
|
+
variant="quiet"
|
|
132
|
+
align="start"
|
|
133
|
+
icon={b.icon}
|
|
134
|
+
onClick={b.run}
|
|
135
|
+
aria-label={`${b.label}: ${item.label}`}
|
|
136
|
+
className={cx("min-w-0 flex-1 rounded-none", i > 0 && "border-l border-l-border")}
|
|
137
|
+
>
|
|
138
|
+
<span className="truncate">{b.label}</span>
|
|
139
|
+
</Button>
|
|
140
|
+
))}
|
|
141
|
+
</div>
|
|
142
|
+
) : null}
|
|
143
|
+
</Card>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// The limit editor's state: which tile, the draft, the save in flight and
|
|
148
|
+
// why it failed.
|
|
149
|
+
export function useLimitEditor(onLimitChange, format) {
|
|
150
|
+
const [item, setItem] = useState(null);
|
|
151
|
+
const [draft, setDraft] = useState("");
|
|
152
|
+
const [saving, setSaving] = useState(false);
|
|
153
|
+
const [error, setError] = useState(null);
|
|
154
|
+
const [invalid, setInvalid] = useState(null);
|
|
155
|
+
|
|
156
|
+
function open(it) {
|
|
157
|
+
setItem(it);
|
|
158
|
+
setDraft(finite(it.limit) ? String(it.limit) : "");
|
|
159
|
+
setError(null);
|
|
160
|
+
setInvalid(null);
|
|
161
|
+
}
|
|
162
|
+
function close() {
|
|
163
|
+
if (saving) return;
|
|
164
|
+
setItem(null);
|
|
165
|
+
}
|
|
166
|
+
async function save() {
|
|
167
|
+
const n = Number(String(draft).replace(/[,\s]/g, ""));
|
|
168
|
+
if (!String(draft).trim() || !Number.isFinite(n) || n <= 0) {
|
|
169
|
+
setInvalid("Enter a number above zero.");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
setInvalid(null);
|
|
173
|
+
setError(null);
|
|
174
|
+
setSaving(true);
|
|
175
|
+
let result;
|
|
176
|
+
try {
|
|
177
|
+
result = await onLimitChange?.(item, n);
|
|
178
|
+
} catch (e) {
|
|
179
|
+
result = { ok: false, error: e?.message ?? String(e) };
|
|
180
|
+
}
|
|
181
|
+
setSaving(false);
|
|
182
|
+
if (result && result.ok === false) {
|
|
183
|
+
setError(result.error ?? "The limit was not changed.");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
setItem(null);
|
|
187
|
+
}
|
|
188
|
+
return { item, draft, setDraft, saving, error, invalid, open, close, save, format };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function LimitSheet({ editor, label, hint }) {
|
|
192
|
+
const id = useId();
|
|
193
|
+
const item = editor.item;
|
|
194
|
+
const unit = item?.unit;
|
|
195
|
+
const fmt = editor.format ?? plain;
|
|
196
|
+
return (
|
|
197
|
+
<Sheet
|
|
198
|
+
open={Boolean(item)}
|
|
199
|
+
onClose={editor.close}
|
|
200
|
+
side="center"
|
|
201
|
+
title={item ? `${item.limitLabel ?? label}: ${item.label}` : label}
|
|
202
|
+
description={
|
|
203
|
+
item
|
|
204
|
+
? item.limitHint ?? hint ?? `Now ${finite(item.limit) ? `${fmt(item.limit)}${unit ? ` ${unit}` : ""}` : "unlimited"}; ${fmt(finite(item.used) ? item.used : 0)}${unit ? ` ${unit}` : ""} used.`
|
|
205
|
+
: undefined
|
|
206
|
+
}
|
|
207
|
+
footer={
|
|
208
|
+
<>
|
|
209
|
+
<Button onClick={editor.close} disabled={editor.saving}>
|
|
210
|
+
Cancel
|
|
211
|
+
</Button>
|
|
212
|
+
<Button variant="primary" type="submit" form={`${id}-form`} loading={editor.saving}>
|
|
213
|
+
Save
|
|
214
|
+
</Button>
|
|
215
|
+
</>
|
|
216
|
+
}
|
|
217
|
+
>
|
|
218
|
+
<form
|
|
219
|
+
id={`${id}-form`}
|
|
220
|
+
className="grid gap-3"
|
|
221
|
+
onSubmit={(e) => {
|
|
222
|
+
e.preventDefault();
|
|
223
|
+
editor.save();
|
|
224
|
+
}}
|
|
225
|
+
>
|
|
226
|
+
{editor.error ? <Notice tone="danger">{editor.error}</Notice> : null}
|
|
227
|
+
<Field id={`${id}-limit`} label={item?.limitField ?? "New limit"} error={editor.invalid}>
|
|
228
|
+
<InputGroup
|
|
229
|
+
id={`${id}-limit`}
|
|
230
|
+
inputMode="decimal"
|
|
231
|
+
autoComplete="off"
|
|
232
|
+
value={editor.draft}
|
|
233
|
+
onChange={(e) => editor.setDraft(e.target.value)}
|
|
234
|
+
prefix={item?.limitPrefix}
|
|
235
|
+
suffix={unit}
|
|
236
|
+
invalid={Boolean(editor.invalid)}
|
|
237
|
+
aria-describedby={editor.invalid ? `${id}-limit-error` : undefined}
|
|
238
|
+
/>
|
|
239
|
+
</Field>
|
|
240
|
+
</form>
|
|
241
|
+
</Sheet>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Task list
|
|
2
|
+
|
|
3
|
+
The List view of work. Tasks sit under headings that fold — by status,
|
|
4
|
+
assignee, priority, project, due date or any field. Each row has a round
|
|
5
|
+
check to complete it, a title you click to rename in place, its subtasks
|
|
6
|
+
indented under it (with their own fold and a "2/5" count), and the fields
|
|
7
|
+
you choose — people, due date, priority, tags, project, estimate — as
|
|
8
|
+
pickers right in the row. Every group ends in "Add task": type, Enter, and
|
|
9
|
+
the next one is ready. Drag a row by its grip to reorder it, or into
|
|
10
|
+
another group to change its status, assignee or due date. Tick several
|
|
11
|
+
(the row menu's "Select", or x on a focused title, shift for a range) and
|
|
12
|
+
a bar sets their status, assignee, due date or priority together, or
|
|
13
|
+
deletes them — with Undo in the toast. Search, filters (as chips), group,
|
|
14
|
+
sort and fields live in the toolbar above.
|
|
15
|
+
|
|
16
|
+
Every change saves through one async `onChange(change)` and shows at
|
|
17
|
+
once; when the save fails the list puts it back and says why.
|
|
18
|
+
|
|
19
|
+
```jsx
|
|
20
|
+
import { TaskList } from "../components/blocks/task-list"; // a Makersclaw app ("./blocks/task-list" from components/)
|
|
21
|
+
import { TaskList } from "@/components/makersclaw/blocks/task-list"; // a shadcn project
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
It is a client component: render it from a `"use client"` component, and
|
|
25
|
+
load the tasks in the server surface (README §4). It is built on
|
|
26
|
+
`task-model` (added with it): the task shape, the change shapes and the
|
|
27
|
+
helpers are documented there.
|
|
28
|
+
|
|
29
|
+
## The data
|
|
30
|
+
|
|
31
|
+
Tasks in task-model's shape — `{ id, title, status, assignees, due?,
|
|
32
|
+
priority?, parentId?, tags, project?, estimate?, order?, … }` — with the
|
|
33
|
+
statuses, people and projects they refer to. A task with `parentId` is a
|
|
34
|
+
subtask, drawn under its parent when both are in the same group (else in
|
|
35
|
+
its own group with "in Parent" beside it). `order` is the hand-made order
|
|
36
|
+
drag-to-reorder saves; tasks without one keep the order given.
|
|
37
|
+
|
|
38
|
+
## Props
|
|
39
|
+
|
|
40
|
+
- `tasks` — the tasks. Pass `useFixture(rows, SAMPLE).rows` and the
|
|
41
|
+
examples change on screen and save nothing (they are not rows).
|
|
42
|
+
- `statuses` — `[{ id, label, tone?, hue?, done? }]` in order; `done`
|
|
43
|
+
marks what the check completes to. Default: To do, In progress, In
|
|
44
|
+
review, Done.
|
|
45
|
+
- `people` — `[{ id, name, src? }]`: who can be assigned.
|
|
46
|
+
- `projects` — `[{ id, name, hue? }]`.
|
|
47
|
+
- `fields` — custom fields (`{ key, label, kind, options? }`), grouped and
|
|
48
|
+
filtered like the built-in ones.
|
|
49
|
+
- `onChange(change)` — save a change; return `{ ok: true }` or
|
|
50
|
+
`{ ok: false, error }` (a throw counts as failed). A change is
|
|
51
|
+
task-model's `create` / `update` / `delete` / `batch`; in a Makersclaw
|
|
52
|
+
app, loop over `changeWrites(change)` into insertRow / updateRow /
|
|
53
|
+
deleteRow (task-model README, "A change"). Without `onChange` the list
|
|
54
|
+
only shows: no checks, pickers, drag or quick-add.
|
|
55
|
+
- `onOpen(task)` — an "Open" button on each row (on hover; in the row's
|
|
56
|
+
menu on a phone) and in the menu: open your `Sheet` with the task.
|
|
57
|
+
Clicking a title renames it; with no `onChange`, it opens.
|
|
58
|
+
- `view` · `defaultView` · `onViewChange(view)` — what the list shows:
|
|
59
|
+
`{ search, filters, groupBy, sort, fields, hideDone }` (task-model's
|
|
60
|
+
`DEFAULT_VIEW`: grouped by status, showing assignees, due and priority).
|
|
61
|
+
Pass `defaultView` to start somewhere else; pass `view` + `onViewChange`
|
|
62
|
+
to keep it yourself (saved views, the URL).
|
|
63
|
+
- `today` — `"YYYY-MM-DD"`: what "Today" and "Overdue" are measured from.
|
|
64
|
+
Default the browser's today; fix it in a demo.
|
|
65
|
+
- `weekStartsOn` — 0 (Sunday) … 6; default Monday.
|
|
66
|
+
- `toolbar` — default true; false hides search, filter, group, sort and
|
|
67
|
+
fields (and the Add task button).
|
|
68
|
+
- `toolbarExtra` — your controls at the toolbar's end, before "Add task".
|
|
69
|
+
- `addLabel` — default `"Add task"`.
|
|
70
|
+
- `starters` — templates the empty state offers:
|
|
71
|
+
`[{ label: "Product launch", icon?: "sparkles", tasks: [{ title, priority?, … }] }]`.
|
|
72
|
+
A press creates them all in one change.
|
|
73
|
+
- `emptyTitle` · `emptyBody` — the empty state's words.
|
|
74
|
+
- `loading` — skeleton rows in place of the list.
|
|
75
|
+
- `error` — a danger Notice above the list (a failed read).
|
|
76
|
+
- `label` — what the list is called to a screen reader, default `"Tasks"`.
|
|
77
|
+
- `className` — layout around it (width, margin). Never colour.
|
|
78
|
+
|
|
79
|
+
## What it does, precisely
|
|
80
|
+
|
|
81
|
+
- Completing: the round check moves a task to the first `done` status,
|
|
82
|
+
and back to the first open one.
|
|
83
|
+
- Grouped by assignee (or tags), a task with two people is under both;
|
|
84
|
+
dragging it from one to another swaps that one person.
|
|
85
|
+
- Grouped by due date, "Overdue" takes no drops (the toast says to give a
|
|
86
|
+
date instead); dropping on "Tomorrow" sets tomorrow, and a start date
|
|
87
|
+
moves with it.
|
|
88
|
+
- Reordering needs the manual sort (Sort: Manual). With another sort, a
|
|
89
|
+
drag still moves a task to another group.
|
|
90
|
+
- Deleting a task deletes its subtasks; Undo brings all of them back.
|
|
91
|
+
- Keyboard: Tab reaches every control; on a title, ↑ ↓ move between
|
|
92
|
+
tasks, Enter renames (Enter saves, Escape cancels), x selects (shift
|
|
93
|
+
for a range). The grip picks a row up with Space; arrows move it; Space
|
|
94
|
+
drops; Escape cancels.
|
|
95
|
+
- On a phone the row's fields wrap under its title, the grip and menu
|
|
96
|
+
stay visible, and the bulk bar sits at the bottom of the list.
|
|
97
|
+
|
|
98
|
+
## Example
|
|
99
|
+
|
|
100
|
+
```jsx
|
|
101
|
+
// surfaces/tasks.jsx — server: load, hand over
|
|
102
|
+
import { loadRows } from "../lib/data";
|
|
103
|
+
import Tasks from "../components/Tasks";
|
|
104
|
+
|
|
105
|
+
export default async function TasksSurface() {
|
|
106
|
+
const { rows, error } = await loadRows({ source: "public.tasks", orderBy: "created_at asc" });
|
|
107
|
+
const people = await loadRows({ source: "public.people" });
|
|
108
|
+
return <Tasks tasks={rows} people={people.rows} error={error} />;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The list orders each group by `order` itself (Sort: Manual), so the read
|
|
113
|
+
order only breaks ties.
|
|
114
|
+
|
|
115
|
+
```jsx
|
|
116
|
+
// components/Tasks.jsx — client: the list, the task sheet
|
|
117
|
+
"use client";
|
|
118
|
+
import { useState } from "react";
|
|
119
|
+
import { deleteRow, insertRow, updateRow } from "../lib/actions";
|
|
120
|
+
import { Sheet } from "./ui";
|
|
121
|
+
import { TaskList } from "./blocks/task-list";
|
|
122
|
+
import { changeWrites } from "./blocks/task-model";
|
|
123
|
+
|
|
124
|
+
const STATUSES = [
|
|
125
|
+
{ id: "todo", label: "To do", tone: "neutral" },
|
|
126
|
+
{ id: "doing", label: "In progress", tone: "info" },
|
|
127
|
+
{ id: "done", label: "Done", tone: "success", done: true },
|
|
128
|
+
];
|
|
129
|
+
|
|
130
|
+
const COLUMNS = ["id", "title", "status", "assignees", "due", "priority", "tags", "parentId", "order"];
|
|
131
|
+
|
|
132
|
+
async function save(change) {
|
|
133
|
+
for (const w of changeWrites(change, { columns: COLUMNS, keepNewIds: false })) {
|
|
134
|
+
const r =
|
|
135
|
+
w.op === "insert" ? await insertRow({ source: "public.tasks", values: w.values, detail: w.values.title })
|
|
136
|
+
: w.op === "update" ? await updateRow({ source: "public.tasks", id: w.id, patch: w.patch })
|
|
137
|
+
: await deleteRow({ source: "public.tasks", id: w.id });
|
|
138
|
+
if (r?.ok === false) return r;
|
|
139
|
+
}
|
|
140
|
+
return { ok: true };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export default function Tasks({ tasks, people, error }) {
|
|
144
|
+
const [open, setOpen] = useState(null);
|
|
145
|
+
return (
|
|
146
|
+
<>
|
|
147
|
+
<TaskList tasks={tasks} statuses={STATUSES} people={people} onChange={save} onOpen={setOpen} error={error}
|
|
148
|
+
starters={[{ label: "Weekly planning", tasks: [{ title: "Review last week" }, { title: "Pick three priorities" }] }]} />
|
|
149
|
+
<Sheet open={Boolean(open)} onClose={() => setOpen(null)} title={open?.title}>{/* the task's fields */}</Sheet>
|
|
150
|
+
</>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Grouped by person, only open work, showing the project:
|
|
156
|
+
|
|
157
|
+
```jsx
|
|
158
|
+
<TaskList tasks={tasks} people={people} projects={projects} onChange={save}
|
|
159
|
+
defaultView={{ groupBy: "assignees", hideDone: true, fields: ["due", "priority", "project"] }} />
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## What it will not do
|
|
163
|
+
|
|
164
|
+
- Edit a task's description, comments or custom fields in the row: open
|
|
165
|
+
it (`onOpen`) in a Sheet.
|
|
166
|
+
- Drag a subtask out of its parent: use its menu ("Make it a task"), or
|
|
167
|
+
"Add subtask" on the new parent.
|
|
168
|
+
- Nest deeper than three levels from the menu (the data may be deeper;
|
|
169
|
+
it is drawn).
|
|
170
|
+
- Virtualise thousands of rows: filter, or page them in the surface.
|
|
171
|
+
- Fetch: tasks come in as props; the page re-reads after a save.
|
|
172
|
+
|
|
173
|
+
A list it cannot be is your own component in `components/`, built from
|
|
174
|
+
task-model's parts, toolbar and drag primitives — not an edit to this
|
|
175
|
+
block. Its files are fixed: `npm run check` refuses a change, and
|
|
176
|
+
`makersclaw add task-list` restores them.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "task-list",
|
|
3
|
+
"title": "Task list",
|
|
4
|
+
"description": "The List view of work, like ClickUp's or Linear's: tasks under headings that fold (group by status, assignee, priority, project, due date or any field), a round check to complete each, the title edited in place, subtasks indented under their parent with their own fold, the fields you choose (assignees, due date, priority, tags, project, estimate) as inline pickers, a quick-add row at the end of every group, drag to reorder and to move between groups (saving the new status, assignee or due date), multi-select with a bulk bar (status, assign, due, priority, delete with undo), a toolbar with search, filter chips, group by, sort and fields, and friendly empty states with starter templates. One async onChange saves every change; failures roll back with a notice.",
|
|
5
|
+
"useWhen": "A screen that lists work to get done and moves it along: a team's tasks, a launch checklist, a sprint, a personal to-do list, onboarding steps, content to publish. Not for records that are not work (data-table), for stage columns side by side (board), or for dates on a grid (calendar).",
|
|
6
|
+
"tags": ["tasks", "task list", "to-do", "todo", "list view", "checklist", "clickup", "linear", "asana", "things", "subtasks", "group", "fold", "inline edit", "quick add", "drag", "reorder", "bulk", "select", "undo", "project management", "sprint"],
|
|
7
|
+
"exports": ["TaskList"],
|
|
8
|
+
"files": ["index.js", "task-list.jsx"],
|
|
9
|
+
"requires": ["task-model"]
|
|
10
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// TaskList three ways — the gallery's and the smoke test's surface. Not
|
|
4
|
+
// installed into apps: `makersclaw add task-list` lays index.js and
|
|
5
|
+
// task-list.jsx only.
|
|
6
|
+
// Launch a team's work grouped by status, subtasks, people, due
|
|
7
|
+
// dates, priorities; saves in memory (a switch makes them
|
|
8
|
+
// fail, to show the rollback); a row opens a sheet.
|
|
9
|
+
// Empty no tasks yet: the empty state with starter templates.
|
|
10
|
+
// Read-only the same list with no onChange, grouped by assignee.
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import { Sheet, Switch, TabPanel, Tabs } from "../components/ui";
|
|
13
|
+
import { TaskList } from "../components/blocks/task-list";
|
|
14
|
+
import { applyChange, formatDay } from "../components/blocks/task-model";
|
|
15
|
+
|
|
16
|
+
const TODAY = "2026-09-23";
|
|
17
|
+
|
|
18
|
+
const STATUSES = [
|
|
19
|
+
{ id: "todo", label: "To do", tone: "neutral" },
|
|
20
|
+
{ id: "doing", label: "In progress", tone: "info" },
|
|
21
|
+
{ id: "review", label: "In review", tone: "warning" },
|
|
22
|
+
{ id: "done", label: "Done", tone: "success", done: true },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const PEOPLE = [
|
|
26
|
+
{ id: "maya", name: "Maya Chen" },
|
|
27
|
+
{ id: "leo", name: "Leo Park" },
|
|
28
|
+
{ id: "priya", name: "Priya Nair" },
|
|
29
|
+
{ id: "sam", name: "Sam Okafor" },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const PROJECTS = [
|
|
33
|
+
{ id: "site", name: "Website relaunch", hue: 1 },
|
|
34
|
+
{ id: "q4", name: "Q4 campaign", hue: 3 },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const START = [
|
|
38
|
+
{ id: "t1", title: "Finalise pricing page copy", status: "doing", assignees: ["maya"], due: "2026-09-23", priority: "high", project: "site", tags: ["copy"], estimate: 3, order: 1024 },
|
|
39
|
+
{ id: "t2", title: "Pick the hero illustration", status: "doing", assignees: ["priya", "leo"], due: "2026-09-25", priority: "medium", project: "site", tags: ["design"], estimate: 4, order: 2048 },
|
|
40
|
+
{ id: "t2a", title: "Shortlist three styles", status: "done", parentId: "t2", assignees: ["priya"], order: 1024 },
|
|
41
|
+
{ id: "t2b", title: "Get sign-off from Sam", status: "todo", parentId: "t2", assignees: ["priya"], due: "2026-09-24", order: 2048 },
|
|
42
|
+
{ id: "t3", title: "Write the launch email", status: "todo", assignees: ["sam"], due: "2026-09-29", priority: "high", project: "q4", tags: ["email", "copy"], estimate: 2, order: 1024 },
|
|
43
|
+
{ id: "t4", title: "Book the product photo shoot", status: "todo", assignees: ["leo"], due: "2026-09-21", priority: "urgent", project: "q4", estimate: 1, order: 2048 },
|
|
44
|
+
{ id: "t5", title: "Draft the customer story with Northwind", status: "todo", assignees: [], due: "2026-10-06", project: "q4", tags: ["story"], order: 3072 },
|
|
45
|
+
{ id: "t6", title: "Set up redirects from the old site", status: "review", assignees: ["leo"], due: "2026-09-24", priority: "medium", project: "site", tags: ["seo"], estimate: 2, order: 1024 },
|
|
46
|
+
{ id: "t7", title: "Accessibility pass on the new nav", status: "review", assignees: ["maya"], project: "site", estimate: 3, order: 2048 },
|
|
47
|
+
{ id: "t8", title: "Choose the analytics events", status: "done", assignees: ["sam"], due: "2026-09-18", project: "site", order: 1024 },
|
|
48
|
+
{ id: "t9", title: "Brief the paid social agency", status: "done", assignees: ["maya", "sam"], due: "2026-09-19", project: "q4", order: 2048 },
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const STARTERS = [
|
|
52
|
+
{
|
|
53
|
+
label: "Product launch",
|
|
54
|
+
icon: "sparkles",
|
|
55
|
+
tasks: [
|
|
56
|
+
{ title: "Agree the launch date", priority: "high" },
|
|
57
|
+
{ title: "Write the announcement" },
|
|
58
|
+
{ title: "Prepare the demo video" },
|
|
59
|
+
{ title: "Line up three customer quotes" },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: "Weekly planning",
|
|
64
|
+
icon: "calendar",
|
|
65
|
+
tasks: [{ title: "Review last week" }, { title: "Pick three priorities" }, { title: "Clear the inbox" }],
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
function useTasks(start, failRef) {
|
|
70
|
+
const [tasks, setTasks] = useState(start);
|
|
71
|
+
const onChange = async (change) => {
|
|
72
|
+
await new Promise((r) => setTimeout(r, 350));
|
|
73
|
+
if (failRef?.current) return { ok: false, error: "the server did not answer" };
|
|
74
|
+
setTasks((all) => applyChange(all, change));
|
|
75
|
+
return { ok: true };
|
|
76
|
+
};
|
|
77
|
+
return [tasks, onChange];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default function TaskListDemo() {
|
|
81
|
+
const [fail, setFail] = useState(false);
|
|
82
|
+
const failRef = { current: fail };
|
|
83
|
+
const [tasks, onChange] = useTasks(START, failRef);
|
|
84
|
+
const [none, onChangeNone] = useTasks([]);
|
|
85
|
+
const [open, setOpen] = useState(null);
|
|
86
|
+
const [tab, setTab] = useState("launch");
|
|
87
|
+
return (
|
|
88
|
+
<div className="grid grid-cols-1 gap-4">
|
|
89
|
+
<Tabs
|
|
90
|
+
aria-label="Task list examples"
|
|
91
|
+
value={tab}
|
|
92
|
+
onChange={setTab}
|
|
93
|
+
tabs={[
|
|
94
|
+
{ key: "launch", label: "Launch" },
|
|
95
|
+
{ key: "empty", label: "Empty" },
|
|
96
|
+
{ key: "read", label: "Read-only" },
|
|
97
|
+
]}
|
|
98
|
+
/>
|
|
99
|
+
<TabPanel tab="launch" value={tab}>
|
|
100
|
+
<div className="grid grid-cols-1 gap-4">
|
|
101
|
+
<Switch id="task-list-fail" label="Make saves fail" checked={fail} onChange={(e) => setFail(e.target.checked)} />
|
|
102
|
+
<TaskList
|
|
103
|
+
label="Launch tasks"
|
|
104
|
+
tasks={tasks}
|
|
105
|
+
statuses={STATUSES}
|
|
106
|
+
people={PEOPLE}
|
|
107
|
+
projects={PROJECTS}
|
|
108
|
+
today={TODAY}
|
|
109
|
+
onChange={onChange}
|
|
110
|
+
onOpen={setOpen}
|
|
111
|
+
defaultView={{ groupBy: "status", fields: ["assignees", "due", "priority", "tags"] }}
|
|
112
|
+
/>
|
|
113
|
+
<Sheet open={Boolean(open)} onClose={() => setOpen(null)} title={open?.title} description={open?.due ? `Due ${formatDay(open.due, TODAY)}` : "No due date"}>
|
|
114
|
+
<p className="text-sm text-muted-foreground">The task's own page goes here: its description, comments and history.</p>
|
|
115
|
+
</Sheet>
|
|
116
|
+
</div>
|
|
117
|
+
</TabPanel>
|
|
118
|
+
<TabPanel tab="empty" value={tab}>
|
|
119
|
+
<TaskList label="My tasks" tasks={none} statuses={STATUSES} people={PEOPLE} today={TODAY} onChange={onChangeNone} starters={STARTERS} />
|
|
120
|
+
</TabPanel>
|
|
121
|
+
<TabPanel tab="read" value={tab}>
|
|
122
|
+
<TaskList
|
|
123
|
+
label="Tasks by person"
|
|
124
|
+
tasks={tasks}
|
|
125
|
+
statuses={STATUSES}
|
|
126
|
+
people={PEOPLE}
|
|
127
|
+
projects={PROJECTS}
|
|
128
|
+
today={TODAY}
|
|
129
|
+
defaultView={{ groupBy: "assignees", fields: ["status", "due", "priority", "project"], hideDone: true }}
|
|
130
|
+
/>
|
|
131
|
+
</TabPanel>
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The TaskList block — `makersclaw add task-list` (it brings task-model).
|
|
2
|
+
// Fixed: compose it through its props (README.md beside this file); a
|
|
3
|
+
// list it cannot be is your own component in components/, built from
|
|
4
|
+
// task-model's parts.
|
|
5
|
+
export { TaskList } from "./task-list";
|