makersclaw 0.2.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/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +3 -2
- 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 +10 -6
- 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 +205 -8
- 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 +12 -7
- 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 +3411 -29
- 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 +55 -5
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +230 -86
- 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 +80 -0
- 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 +8 -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/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/template.json +264 -8
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useId, useState } from "react";
|
|
4
|
+
import { Badge, Button, DatePicker, Empty, Icon, IconButton, Notice, Skeleton, cx, todayString } from "../../ui";
|
|
5
|
+
|
|
6
|
+
// Money records as a plain list: one row per charge, payment or invoice,
|
|
7
|
+
// optionally grouped by month, with a date-range filter, an export and a
|
|
8
|
+
// per-row download. A list, not a table: no columns, no sorting — rows
|
|
9
|
+
// come in in the order they should show.
|
|
10
|
+
|
|
11
|
+
// Server and browser may differ in locale, time zone and even the day:
|
|
12
|
+
// the first render uses fixed ones (en-US, UTC) so it matches the server's
|
|
13
|
+
// HTML, then the reader's own take over.
|
|
14
|
+
function useHydrated() {
|
|
15
|
+
const [hydrated, setHydrated] = useState(false);
|
|
16
|
+
useEffect(() => setHydrated(true), []);
|
|
17
|
+
return hydrated;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const formats = new Map();
|
|
21
|
+
function money(amount, currency = "USD", locale) {
|
|
22
|
+
const key = `${locale ?? ""}|${currency}`;
|
|
23
|
+
let f = formats.get(key);
|
|
24
|
+
if (!f) {
|
|
25
|
+
try {
|
|
26
|
+
f = new Intl.NumberFormat(locale, { style: "currency", currency });
|
|
27
|
+
} catch {
|
|
28
|
+
f = new Intl.NumberFormat(locale, { style: "currency", currency: "USD" });
|
|
29
|
+
}
|
|
30
|
+
formats.set(key, f);
|
|
31
|
+
}
|
|
32
|
+
return f.format(Math.abs(Number(amount) || 0));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
36
|
+
const dayOf = (value) => (typeof value === "string" ? value.slice(0, 10) : "");
|
|
37
|
+
|
|
38
|
+
// "Sep 21, 2026", or "Sep 21, 2026, 12:30 PM" when the row has a time.
|
|
39
|
+
function when(value, locale, timeZone) {
|
|
40
|
+
if (!value) return "";
|
|
41
|
+
if (typeof value === "string" && DAY.test(value)) {
|
|
42
|
+
const [y, m, d] = value.split("-").map(Number);
|
|
43
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeZone: "UTC" }).format(Date.UTC(y, m - 1, d));
|
|
44
|
+
}
|
|
45
|
+
const d = new Date(value);
|
|
46
|
+
if (Number.isNaN(d.getTime())) return String(value);
|
|
47
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeStyle: "short", timeZone }).format(d);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function monthLabel(key, locale) {
|
|
51
|
+
const [y, m] = key.split("-").map(Number);
|
|
52
|
+
if (!y || !m) return "Undated";
|
|
53
|
+
return new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(Date.UTC(y, m - 1, 1));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const daysBetween = (from, to) => {
|
|
57
|
+
const a = Date.parse(`${from}T00:00:00Z`);
|
|
58
|
+
const b = Date.parse(`${to}T00:00:00Z`);
|
|
59
|
+
return Math.round((b - a) / 86400000);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// An invoice's badge: paid, void, or how long until (or since) it is due.
|
|
63
|
+
function invoiceBadge(row, today) {
|
|
64
|
+
const status = String(row.status ?? "").toLowerCase();
|
|
65
|
+
if (status === "paid") return { tone: "success", text: "Paid" };
|
|
66
|
+
if (status === "void" || status === "cancelled") return { tone: "neutral", text: status === "void" ? "Void" : "Cancelled" };
|
|
67
|
+
if (status === "draft") return { tone: "neutral", text: "Draft" };
|
|
68
|
+
const due = dayOf(row.dueDate);
|
|
69
|
+
if (!DAY.test(due)) return status === "overdue" ? { tone: "danger", text: "Overdue" } : { tone: "info", text: "Open" };
|
|
70
|
+
const left = daysBetween(today, due);
|
|
71
|
+
if (left > 0) return { tone: "info", text: `Due in ${left} ${left === 1 ? "day" : "days"}` };
|
|
72
|
+
if (left === 0) return { tone: "warning", text: "Due today" };
|
|
73
|
+
return { tone: "danger", text: `${-left} ${left === -1 ? "day" : "days"} overdue` };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// A history row's direction and state.
|
|
77
|
+
function flowOf(row) {
|
|
78
|
+
const status = String(row.status ?? "").toLowerCase();
|
|
79
|
+
const incoming = row.direction ? row.direction === "in" : Number(row.amount) >= 0;
|
|
80
|
+
if (status === "pending") return { key: "pending", icon: "clock", word: "Pending", incoming };
|
|
81
|
+
if (status === "failed" || status === "declined") return { key: "failed", icon: "x", word: "Failed", incoming };
|
|
82
|
+
if (status === "refunded") return { key: "refunded", icon: "refresh", word: "Refunded", incoming };
|
|
83
|
+
return { key: incoming ? "in" : "out", icon: incoming ? "arrow-down" : "arrow-up", word: incoming ? "Received" : "Paid", incoming };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const MARK = {
|
|
87
|
+
in: "text-success",
|
|
88
|
+
out: "text-foreground",
|
|
89
|
+
pending: "text-muted-foreground",
|
|
90
|
+
failed: "text-destructive",
|
|
91
|
+
refunded: "text-muted-foreground",
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
async function attempt(fn) {
|
|
95
|
+
try {
|
|
96
|
+
const res = await fn();
|
|
97
|
+
return res && res.ok === false ? res.error || "That did not work." : null;
|
|
98
|
+
} catch (e) {
|
|
99
|
+
return e?.message || "That did not work.";
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function RowAction({ row, onDownload, downloadHref, label, onError }) {
|
|
104
|
+
const [busy, setBusy] = useState(false);
|
|
105
|
+
const href = downloadHref?.(row);
|
|
106
|
+
if (!href && !onDownload) return null;
|
|
107
|
+
async function run() {
|
|
108
|
+
setBusy(true);
|
|
109
|
+
onError(null);
|
|
110
|
+
onError(await attempt(() => onDownload(row)));
|
|
111
|
+
setBusy(false);
|
|
112
|
+
}
|
|
113
|
+
return href ? (
|
|
114
|
+
<Button iconOnly variant="quiet" href={href} aria-label={label} title={label} className="shrink-0">
|
|
115
|
+
<Icon name="download" size={18} />
|
|
116
|
+
</Button>
|
|
117
|
+
) : (
|
|
118
|
+
<IconButton icon="download" label={label} onClick={run} loading={busy} />
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function RowError({ error }) {
|
|
123
|
+
return error ? (
|
|
124
|
+
<p role="alert" className="basis-full text-xs text-destructive">
|
|
125
|
+
{error}
|
|
126
|
+
</p>
|
|
127
|
+
) : null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function HistoryRow({ row, currency, locale, timeZone, onOpen, onDownload, downloadHref }) {
|
|
131
|
+
const [error, setError] = useState(null);
|
|
132
|
+
const flow = flowOf(row);
|
|
133
|
+
const amount = money(row.amount, row.currency ?? currency, locale);
|
|
134
|
+
const sign = flow.key === "in" ? "+" : flow.key === "out" ? "−" : "";
|
|
135
|
+
const title = onOpen ? (
|
|
136
|
+
<Button variant="link" size="inherit" onClick={() => onOpen(row)} className="text-left font-medium">
|
|
137
|
+
{row.name}
|
|
138
|
+
</Button>
|
|
139
|
+
) : (
|
|
140
|
+
<span className="font-medium">{row.name}</span>
|
|
141
|
+
);
|
|
142
|
+
return (
|
|
143
|
+
<li className="flex flex-wrap items-center gap-3 rounded-lg border border-border p-3 sm:gap-4 sm:p-4">
|
|
144
|
+
<span className={cx("grid size-10 shrink-0 place-items-center rounded-md border border-border bg-card", MARK[flow.key])}>
|
|
145
|
+
<Icon name={flow.icon} size={18} />
|
|
146
|
+
<span className="sr-only">{flow.word}</span>
|
|
147
|
+
</span>
|
|
148
|
+
<div className="grid min-w-0 flex-1 gap-0.5">
|
|
149
|
+
<p className="truncate">{title}</p>
|
|
150
|
+
<p className="truncate text-sm text-muted-foreground">
|
|
151
|
+
{row.description ? `${row.description} · ` : ""}
|
|
152
|
+
{when(row.date, locale, timeZone)}
|
|
153
|
+
</p>
|
|
154
|
+
</div>
|
|
155
|
+
<div className="grid shrink-0 justify-items-end gap-0.5 text-right">
|
|
156
|
+
<p
|
|
157
|
+
className={cx(
|
|
158
|
+
"text-sm font-semibold tabular-nums",
|
|
159
|
+
MARK[flow.key],
|
|
160
|
+
flow.key === "failed" && "line-through",
|
|
161
|
+
)}
|
|
162
|
+
>
|
|
163
|
+
{sign}
|
|
164
|
+
{amount}
|
|
165
|
+
</p>
|
|
166
|
+
{flow.key === "pending" || flow.key === "failed" || flow.key === "refunded" ? (
|
|
167
|
+
<p className="text-xs text-muted-foreground">{flow.word}</p>
|
|
168
|
+
) : null}
|
|
169
|
+
</div>
|
|
170
|
+
<RowAction row={row} onDownload={onDownload} downloadHref={downloadHref} label={`Download ${row.name}`} onError={setError} />
|
|
171
|
+
<RowError error={error} />
|
|
172
|
+
</li>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function InvoiceRow({ row, currency, locale, timeZone, today, onOpen, onDownload, downloadHref }) {
|
|
177
|
+
const [error, setError] = useState(null);
|
|
178
|
+
const badge = invoiceBadge(row, today);
|
|
179
|
+
const name = row.number ?? row.name;
|
|
180
|
+
return (
|
|
181
|
+
<li className="flex flex-wrap items-center gap-x-4 gap-y-2 py-4">
|
|
182
|
+
<div className="grid min-w-0 basis-full gap-0.5 sm:flex-1 sm:basis-auto">
|
|
183
|
+
{onOpen ? (
|
|
184
|
+
<Button variant="link" size="inherit" onClick={() => onOpen(row)} className="justify-self-start text-left font-semibold">
|
|
185
|
+
{name}
|
|
186
|
+
</Button>
|
|
187
|
+
) : (
|
|
188
|
+
<p className="truncate font-semibold">{name}</p>
|
|
189
|
+
)}
|
|
190
|
+
<p className="truncate text-sm text-muted-foreground">
|
|
191
|
+
{row.number && row.name ? `${row.name} · ` : ""}
|
|
192
|
+
{when(row.date, locale, timeZone)}
|
|
193
|
+
</p>
|
|
194
|
+
</div>
|
|
195
|
+
<Badge tone={badge.tone} variant="soft">
|
|
196
|
+
{badge.text}
|
|
197
|
+
</Badge>
|
|
198
|
+
<p className="ml-auto text-sm font-semibold tabular-nums">{money(row.amount, row.currency ?? currency, locale)}</p>
|
|
199
|
+
<RowAction row={row} onDownload={onDownload} downloadHref={downloadHref} label={`Download ${name}`} onError={setError} />
|
|
200
|
+
<RowError error={error} />
|
|
201
|
+
</li>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function Loading({ variant }) {
|
|
206
|
+
return (
|
|
207
|
+
<ul aria-busy="true" aria-label="Loading" className={cx("grid", variant === "history" ? "gap-2" : "divide-y divide-border")}>
|
|
208
|
+
{[0, 1, 2].map((i) => (
|
|
209
|
+
<li key={i} className={cx("flex items-center gap-3", variant === "history" ? "rounded-lg border border-border p-4" : "py-4")}>
|
|
210
|
+
{variant === "history" ? <Skeleton shape="rect" className="size-10" /> : null}
|
|
211
|
+
<div className="grid flex-1 gap-2">
|
|
212
|
+
<Skeleton className="w-1/3" />
|
|
213
|
+
<Skeleton className="w-1/4" />
|
|
214
|
+
</div>
|
|
215
|
+
<Skeleton className="w-16" />
|
|
216
|
+
</li>
|
|
217
|
+
))}
|
|
218
|
+
</ul>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function TransactionList({
|
|
223
|
+
rows,
|
|
224
|
+
variant = "history",
|
|
225
|
+
currency = "USD",
|
|
226
|
+
locale: localeProp,
|
|
227
|
+
groupBy,
|
|
228
|
+
title,
|
|
229
|
+
description,
|
|
230
|
+
loading = false,
|
|
231
|
+
error,
|
|
232
|
+
dateFilter = false,
|
|
233
|
+
range: rangeProp,
|
|
234
|
+
onRangeChange,
|
|
235
|
+
onExport,
|
|
236
|
+
exportLabel = "Export",
|
|
237
|
+
onOpen,
|
|
238
|
+
onDownload,
|
|
239
|
+
downloadHref,
|
|
240
|
+
emptyTitle,
|
|
241
|
+
emptyBody,
|
|
242
|
+
today,
|
|
243
|
+
className,
|
|
244
|
+
}) {
|
|
245
|
+
const hydrated = useHydrated();
|
|
246
|
+
const locale = localeProp ?? (hydrated ? undefined : "en-US");
|
|
247
|
+
const timeZone = hydrated ? undefined : "UTC";
|
|
248
|
+
const invoices = variant === "invoices";
|
|
249
|
+
const headingId = useId();
|
|
250
|
+
const [ownRange, setOwnRange] = useState(null);
|
|
251
|
+
const [exporting, setExporting] = useState(false);
|
|
252
|
+
const [exportError, setExportError] = useState(null);
|
|
253
|
+
const range = rangeProp !== undefined ? rangeProp : ownRange;
|
|
254
|
+
const setRange = (next) => {
|
|
255
|
+
if (rangeProp === undefined) setOwnRange(next);
|
|
256
|
+
onRangeChange?.(next);
|
|
257
|
+
};
|
|
258
|
+
const now = today ?? (hydrated ? todayString() : new Date().toISOString().slice(0, 10));
|
|
259
|
+
const group = (groupBy ?? (invoices ? "none" : "month")) === "month";
|
|
260
|
+
const heading = title ?? (invoices ? "Invoices" : "Transactions");
|
|
261
|
+
|
|
262
|
+
const all = (rows ?? []).filter(Boolean);
|
|
263
|
+
const shown = range?.from
|
|
264
|
+
? all.filter((r) => {
|
|
265
|
+
const d = dayOf(r.date);
|
|
266
|
+
return d >= range.from && d <= (range.to ?? range.from);
|
|
267
|
+
})
|
|
268
|
+
: all;
|
|
269
|
+
|
|
270
|
+
const groups = [];
|
|
271
|
+
if (group) {
|
|
272
|
+
const at = new Map();
|
|
273
|
+
for (const r of shown) {
|
|
274
|
+
const key = dayOf(r.date).slice(0, 7) || "none";
|
|
275
|
+
if (!at.has(key)) {
|
|
276
|
+
at.set(key, groups.length);
|
|
277
|
+
groups.push({ key, rows: [] });
|
|
278
|
+
}
|
|
279
|
+
groups[at.get(key)].rows.push(r);
|
|
280
|
+
}
|
|
281
|
+
} else groups.push({ key: "all", rows: shown });
|
|
282
|
+
|
|
283
|
+
async function runExport() {
|
|
284
|
+
setExporting(true);
|
|
285
|
+
setExportError(null);
|
|
286
|
+
setExportError(await attempt(() => onExport(shown, range)));
|
|
287
|
+
setExporting(false);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const rowProps = { currency, locale, timeZone, today: now, onOpen, onDownload, downloadHref };
|
|
291
|
+
const Row = invoices ? InvoiceRow : HistoryRow;
|
|
292
|
+
const listClass = invoices ? "divide-y divide-border" : "grid gap-2";
|
|
293
|
+
|
|
294
|
+
let body;
|
|
295
|
+
if (loading) body = <Loading variant={variant} />;
|
|
296
|
+
else if (!all.length)
|
|
297
|
+
body = (
|
|
298
|
+
<Empty
|
|
299
|
+
icon={invoices ? "receipt" : "dollar"}
|
|
300
|
+
title={emptyTitle ?? (invoices ? "No invoices yet" : "No transactions yet")}
|
|
301
|
+
body={emptyBody ?? (invoices ? "Invoices appear here once they are issued." : "Payments in and out appear here.")}
|
|
302
|
+
/>
|
|
303
|
+
);
|
|
304
|
+
else if (!shown.length)
|
|
305
|
+
body = (
|
|
306
|
+
<Empty
|
|
307
|
+
icon="calendar"
|
|
308
|
+
title="Nothing in these dates"
|
|
309
|
+
body="Pick a wider range, or clear it to see everything."
|
|
310
|
+
action={
|
|
311
|
+
<Button variant="secondary" onClick={() => setRange(null)}>
|
|
312
|
+
Clear dates
|
|
313
|
+
</Button>
|
|
314
|
+
}
|
|
315
|
+
/>
|
|
316
|
+
);
|
|
317
|
+
else
|
|
318
|
+
body = (
|
|
319
|
+
<div className="grid gap-5">
|
|
320
|
+
{groups.map((g) =>
|
|
321
|
+
group ? (
|
|
322
|
+
<section key={g.key} aria-label={g.key === "none" ? "Undated" : monthLabel(g.key, locale)} className="grid gap-2">
|
|
323
|
+
<h3 className="px-1 text-sm font-semibold text-muted-foreground">
|
|
324
|
+
{g.key === "none" ? "Undated" : monthLabel(g.key, locale)}
|
|
325
|
+
</h3>
|
|
326
|
+
<ul className={listClass}>
|
|
327
|
+
{g.rows.map((r) => (
|
|
328
|
+
<Row key={r.id} row={r} {...rowProps} />
|
|
329
|
+
))}
|
|
330
|
+
</ul>
|
|
331
|
+
</section>
|
|
332
|
+
) : (
|
|
333
|
+
<ul key={g.key} aria-labelledby={headingId} className={listClass}>
|
|
334
|
+
{g.rows.map((r) => (
|
|
335
|
+
<Row key={r.id} row={r} {...rowProps} />
|
|
336
|
+
))}
|
|
337
|
+
</ul>
|
|
338
|
+
),
|
|
339
|
+
)}
|
|
340
|
+
</div>
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
return (
|
|
344
|
+
<section aria-labelledby={headingId} className={cx("grid gap-4 rounded-lg border border-border bg-card p-4 text-card-foreground sm:p-6", className)}>
|
|
345
|
+
<header className="flex flex-wrap items-start justify-between gap-3">
|
|
346
|
+
<div className="min-w-0">
|
|
347
|
+
<h2 id={headingId} className="font-semibold">
|
|
348
|
+
{heading}
|
|
349
|
+
</h2>
|
|
350
|
+
{description ? <p className="mt-0.5 text-sm text-muted-foreground">{description}</p> : null}
|
|
351
|
+
</div>
|
|
352
|
+
{dateFilter || onExport ? (
|
|
353
|
+
<div className="flex w-full flex-wrap items-center gap-2 sm:w-auto">
|
|
354
|
+
{dateFilter ? (
|
|
355
|
+
<DatePicker
|
|
356
|
+
mode="range"
|
|
357
|
+
value={range}
|
|
358
|
+
onChange={setRange}
|
|
359
|
+
placeholder="All dates"
|
|
360
|
+
presets
|
|
361
|
+
size="sm"
|
|
362
|
+
label="Show dates"
|
|
363
|
+
className="min-w-0 flex-1 sm:w-56 sm:flex-none"
|
|
364
|
+
/>
|
|
365
|
+
) : null}
|
|
366
|
+
{onExport ? (
|
|
367
|
+
<Button size="sm" icon="download" onClick={runExport} loading={exporting} disabled={loading || !shown.length}>
|
|
368
|
+
{exportLabel}
|
|
369
|
+
</Button>
|
|
370
|
+
) : null}
|
|
371
|
+
</div>
|
|
372
|
+
) : null}
|
|
373
|
+
</header>
|
|
374
|
+
{error ? <Notice tone="danger">{error}</Notice> : null}
|
|
375
|
+
{exportError ? (
|
|
376
|
+
<Notice tone="danger" onDismiss={() => setExportError(null)}>
|
|
377
|
+
{exportError}
|
|
378
|
+
</Notice>
|
|
379
|
+
) : null}
|
|
380
|
+
{body}
|
|
381
|
+
</section>
|
|
382
|
+
);
|
|
383
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Whiteboard
|
|
2
|
+
|
|
3
|
+
A full-page board to think on, friendly like Miro. A top bar holds the
|
|
4
|
+
board's title (click it to rename), the save state, a Board / Text view
|
|
5
|
+
switch, Export PNG and, when you give it `onShare`, a Share button. Under
|
|
6
|
+
it is the canvas from `sketch-canvas`: the tool rail (a bottom bar on a
|
|
7
|
+
phone), the toolbar that floats over a selection, zoom, undo and redo.
|
|
8
|
+
|
|
9
|
+
Give it `onCreateTask` and a selected note or text becomes a task from
|
|
10
|
+
the top bar; the note keeps a small **Task** badge from then on.
|
|
11
|
+
|
|
12
|
+
An empty board offers three starting points: **Blank**, **Grid** (six
|
|
13
|
+
titled areas, three by two) and **2×2 matrix** (impact against effort,
|
|
14
|
+
four tinted quadrants with axes). The **Text view** lists every word on
|
|
15
|
+
the board, grouped by frame — the reading of the board for a screen
|
|
16
|
+
reader, and what you hand an agent.
|
|
17
|
+
|
|
18
|
+
```jsx
|
|
19
|
+
import { Whiteboard } from "../components/blocks/whiteboard"; // a Makersclaw app ("./blocks/whiteboard" from components/)
|
|
20
|
+
import { Whiteboard } from "@/components/makersclaw/blocks/whiteboard"; // a shadcn project
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
It is a client component: render it from a `"use client"` component.
|
|
24
|
+
`makersclaw add whiteboard` adds `sketch-canvas` with it (and its npm
|
|
25
|
+
package, `@excalidraw/excalidraw`: run `npm install` after). The helpers
|
|
26
|
+
for reading a board — `sketchToText`, `sketchItems`, `isSketchEmpty` —
|
|
27
|
+
come from `sketch-canvas`.
|
|
28
|
+
|
|
29
|
+
## The data
|
|
30
|
+
|
|
31
|
+
A board is two things you store: its **title** (a string) and its
|
|
32
|
+
**sketch** (plain JSON, a `jsonb` column) — the sketch format is
|
|
33
|
+
`sketch-canvas`'s (its README, "The data"). Colours in a sketch are theme
|
|
34
|
+
tokens, so a board repaints when the workspace theme changes.
|
|
35
|
+
|
|
36
|
+
One table does it: `boards(id, title text, sketch jsonb, sketch_text text,
|
|
37
|
+
updated_at)`. Keep `sketch_text` (`sketchToText(sketch)`) for search and
|
|
38
|
+
for agents.
|
|
39
|
+
|
|
40
|
+
## Props
|
|
41
|
+
|
|
42
|
+
- `title` — the board's name, controlled. Change it when `onRename`
|
|
43
|
+
answers ok.
|
|
44
|
+
- `defaultTitle` — the name, uncontrolled (default "Untitled board").
|
|
45
|
+
- `onRename(title)` — `async`, returns `{ ok: true }` or
|
|
46
|
+
`{ ok: false, error? }`. Called when the reader renames the board (Enter
|
|
47
|
+
or leaving the field; Esc puts the old name back). While it runs the
|
|
48
|
+
new name shows; a failure keeps it and shows the error with Retry.
|
|
49
|
+
Without it the title still edits, in memory.
|
|
50
|
+
- `value` — the sketch, controlled (see sketch-canvas: pass back exactly
|
|
51
|
+
what `onChange` gave you).
|
|
52
|
+
- `defaultValue` — the sketch, uncontrolled. With neither, the board
|
|
53
|
+
starts empty and shows the templates.
|
|
54
|
+
- `onChange(sketch)` — the whole sketch after an edit settles (debounced).
|
|
55
|
+
- `onSave(sketch)` — `async`, `{ ok }`. Called with every settled edit and
|
|
56
|
+
on Cmd/Ctrl+S. The top bar shows "Saving…", "Saved", or the error with a
|
|
57
|
+
Retry. A throw counts as a failure.
|
|
58
|
+
- `changeDelay` — ms of quiet before `onChange` / `onSave` (default 600).
|
|
59
|
+
- `templates` — the starting points an empty board offers (default
|
|
60
|
+
`WHITEBOARD_TEMPLATES`: blank, grid, matrix). Each is
|
|
61
|
+
`{ id, label, description?, create(), preview?, icon? }`: `create()`
|
|
62
|
+
returns a sketch (or an element array) to lay on the board, or `null`
|
|
63
|
+
for "start blank". `preview` is a small node drawn in the tile (else an
|
|
64
|
+
`icon`, else a frame glyph; the three built-ins draw their own). `[]`
|
|
65
|
+
shows sketch-canvas's plain hint instead.
|
|
66
|
+
- `onShare()` — shows a Share button (primary) that calls it: open your
|
|
67
|
+
`share-dialog`. Without it there is no Share button. `shareLabel`
|
|
68
|
+
renames it (default "Share").
|
|
69
|
+
- `onExport(blob, { title, fileName })` — `async`, `{ ok }`: take the PNG
|
|
70
|
+
yourself (attach it, upload it). Without it, Export downloads
|
|
71
|
+
`<title>.png`. Either way a failure shows on the button.
|
|
72
|
+
- `onCreateTask({ title, sourceIds })` — turns notes into tasks. With it,
|
|
73
|
+
selecting a note (a shape with words in it) or a text shows **Create
|
|
74
|
+
task** in the top bar: a small form with the words as the title, ready
|
|
75
|
+
to edit (Enter creates). Several selected notes make one task each.
|
|
76
|
+
`async`, return `{ ok: true, id? }` or `{ ok: false, error? }` (a throw
|
|
77
|
+
counts as failed). `sourceIds` are the board elements it came from (the
|
|
78
|
+
note and its words). While it runs the note shows "Creating…"; on
|
|
79
|
+
success the note keeps a **Task** badge (stored in the sketch, as
|
|
80
|
+
`customData.task: { id, title }` on those elements) and is not offered
|
|
81
|
+
again; a failure says so and leaves the note as it was. `taskLabel`
|
|
82
|
+
renames the button (default "Create task").
|
|
83
|
+
- `onOpenTask({ id, title, sourceIds })` — makes each Task badge (and the
|
|
84
|
+
success toast) a link: open the task. Without it the badges only mark.
|
|
85
|
+
- `onBack()` — shows a back arrow at the left of the top bar; `backLabel`
|
|
86
|
+
is its name (default "Back").
|
|
87
|
+
- `meta` — a short node beside the title on wide screens ("Edited by Priya
|
|
88
|
+
Raman", "View only").
|
|
89
|
+
- `readOnly` — `false` (default). `true`: the title is plain text, the
|
|
90
|
+
canvas pans and zooms but does not edit, no templates.
|
|
91
|
+
- `defaultView` — `"board"` (default) or `"text"`: which view opens.
|
|
92
|
+
- `canvasRef` — a ref (`useSketchCanvas()` from sketch-canvas) that
|
|
93
|
+
receives the canvas handle: `exportImage()`, `getScene()`,
|
|
94
|
+
`insertElements()`… (sketch-canvas README, "The handle").
|
|
95
|
+
- `className` — layout: width, margin, height. The default height is
|
|
96
|
+
`h-[40rem]`; a height class of yours (`h-dvh` for a full page, `h-full`,
|
|
97
|
+
`flex-1`) replaces it. Never colour.
|
|
98
|
+
|
|
99
|
+
### Templates
|
|
100
|
+
|
|
101
|
+
`WHITEBOARD_TEMPLATES` is the default list. `gridSketch(opts)` and
|
|
102
|
+
`matrixSketch(opts)` build the two drawn ones, so your own templates can
|
|
103
|
+
reuse them:
|
|
104
|
+
|
|
105
|
+
- `gridSketch({ columns = 3, rows = 2, width = 360, height = 260, gap = 48, names })`
|
|
106
|
+
— titled frames; `names` overrides "Area 1", "Area 2"…
|
|
107
|
+
- `matrixSketch({ x = "Effort", y = "Impact", quadrants = ["Quick wins", "Big bets", "Fill-ins", "Not now"], size = 360 })`
|
|
108
|
+
— four locked, tinted quadrants (notes land on them without moving
|
|
109
|
+
them), two axes, the quadrant names as editable text.
|
|
110
|
+
|
|
111
|
+
## Example
|
|
112
|
+
|
|
113
|
+
A board page that saves itself:
|
|
114
|
+
|
|
115
|
+
```jsx
|
|
116
|
+
"use client";
|
|
117
|
+
import { useState } from "react";
|
|
118
|
+
import { Whiteboard } from "./blocks/whiteboard";
|
|
119
|
+
import { sketchToText } from "./blocks/sketch-canvas";
|
|
120
|
+
import { updateRow } from "../lib/actions";
|
|
121
|
+
|
|
122
|
+
export default function BoardPage({ board, onShare }) {
|
|
123
|
+
const [title, setTitle] = useState(board.title);
|
|
124
|
+
return (
|
|
125
|
+
<Whiteboard
|
|
126
|
+
title={title}
|
|
127
|
+
onRename={async (next) => {
|
|
128
|
+
const res = await updateRow({ source: "public.boards", id: board.id, patch: { title: next } });
|
|
129
|
+
if (res.ok) setTitle(next);
|
|
130
|
+
return res;
|
|
131
|
+
}}
|
|
132
|
+
defaultValue={board.sketch} // jsonb, may be null
|
|
133
|
+
onSave={(sketch) => updateRow({ source: "public.boards", id: board.id, patch: { sketch, sketch_text: sketchToText(sketch) } })}
|
|
134
|
+
onShare={onShare}
|
|
135
|
+
className="h-dvh rounded-none border-0"
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Notes that become tasks (a `tasks` table of your own):
|
|
142
|
+
|
|
143
|
+
```jsx
|
|
144
|
+
<Whiteboard
|
|
145
|
+
defaultValue={board.sketch}
|
|
146
|
+
onSave={save}
|
|
147
|
+
onCreateTask={({ title, sourceIds }) => insertRow({ source: "public.tasks", values: { title, board_id: board.id, source_ids: sourceIds } })}
|
|
148
|
+
onOpenTask={(task) => router.push(`/tasks/${task.id}`)}
|
|
149
|
+
/>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`insertRow` answers `{ ok, id }`; the id is what the badge keeps.
|
|
153
|
+
|
|
154
|
+
A retro template of your own, beside the built-in ones:
|
|
155
|
+
|
|
156
|
+
```jsx
|
|
157
|
+
import { WHITEBOARD_TEMPLATES, gridSketch } from "./blocks/whiteboard";
|
|
158
|
+
|
|
159
|
+
const templates = [
|
|
160
|
+
...WHITEBOARD_TEMPLATES,
|
|
161
|
+
{ id: "retro", label: "Retro", description: "Went well, to improve, actions", icon: "history",
|
|
162
|
+
create: () => gridSketch({ columns: 3, rows: 1, height: 520, names: ["Went well", "To improve", "Actions"] }) },
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
<Whiteboard templates={templates} onSave={save} />
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## What it will not do
|
|
169
|
+
|
|
170
|
+
- Collaborate live: no cursors of others, saves are last-write-wins (as
|
|
171
|
+
sketch-canvas).
|
|
172
|
+
- Share by itself: `onShare` is yours — open `share-dialog`, copy a link.
|
|
173
|
+
- Keep a list of boards: one board per component; the list is your page.
|
|
174
|
+
- Turn on snap-to-grid from a template: the canvas menu has it.
|
|
175
|
+
- Show a minimap (sketch-canvas has none).
|
|
176
|
+
|
|
177
|
+
A board it cannot be is your own component in `components/` — not an edit
|
|
178
|
+
to this block. Its files are fixed: `npm run check` refuses a change, and
|
|
179
|
+
`makersclaw add whiteboard` restores them.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "whiteboard",
|
|
3
|
+
"title": "Whiteboard",
|
|
4
|
+
"description": "A full-page freeform whiteboard on sketch-canvas: a top bar with the board's title (click to rename), the save state (Saving…, Saved, or the error with Retry), a Board / Text view switch, Export PNG and an optional Share button; under it the Miro-style canvas (tool rail, floating toolbar, zoom, undo). An empty board offers starter templates — blank, a grid of titled areas, a 2×2 matrix — and the Text view lists every word on the board for a screen reader or an agent. With onCreateTask, a selected note or text becomes a task from the top bar (\"Create task\", editable title; several notes make one task each), and a small badge marks it on the board from then on. The sketch is plain JSON; saves are async callbacks answering { ok }.",
|
|
5
|
+
"useWhen": "A screen is one board to think on: a team whiteboard, a planning or prioritisation board, a place to sketch an idea and keep it with a record. Not for marking up a screenshot (annotate), sketching a UI to build (sketch-to-app), a structured board of cards and connectors (flow-canvas), or a kanban (board).",
|
|
6
|
+
"tags": ["whiteboard", "board", "sketch", "draw", "drawing", "canvas", "excalidraw", "miro", "brainstorm", "matrix", "2x2", "grid", "template", "export", "png", "share", "task", "create task", "action items"],
|
|
7
|
+
"exports": ["Whiteboard", "WHITEBOARD_TEMPLATES", "gridSketch", "matrixSketch"],
|
|
8
|
+
"files": ["index.js", "whiteboard.jsx", "templates.js"],
|
|
9
|
+
"requires": ["sketch-canvas"]
|
|
10
|
+
}
|