makersclaw 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/cli.mjs +19 -6
- package/src/install.mjs +18 -0
- package/src/registry.mjs +38 -4
- package/src/shadcn.mjs +14 -1
- 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,349 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useId, useState } from "react";
|
|
4
|
+
import { Badge, Button, Card, Confirm, Empty, Icon, IconButton, Kicker, Menu, Notice, Select, Skeleton, Switch, cx } from "../../ui";
|
|
5
|
+
import { Failure, Saving, useSaves } from "./row-state";
|
|
6
|
+
import { SettingsMatrix } from "./settings-matrix";
|
|
7
|
+
|
|
8
|
+
// SettingsList — a card of settings, one row each: an icon, a label, a
|
|
9
|
+
// description, meta lines, a badge, and the row's control (a Switch, a
|
|
10
|
+
// Select, a Button, or a menu of actions). Every change saves on its own
|
|
11
|
+
// through an async callback; the row shows its new value at once, a
|
|
12
|
+
// spinner while it saves, and — when the save fails — the old value back
|
|
13
|
+
// and why, with Try again. `variant="matrix"` is the notification grid:
|
|
14
|
+
// events down the side, channels across the top.
|
|
15
|
+
|
|
16
|
+
/** A badge from a string or { label, tone, hue, icon }. */
|
|
17
|
+
function RowBadge({ badge }) {
|
|
18
|
+
if (!badge) return null;
|
|
19
|
+
const b = typeof badge === "string" ? { label: badge } : badge;
|
|
20
|
+
return (
|
|
21
|
+
<Badge tone={b.tone} hue={b.hue} variant={b.variant ?? "soft"}>
|
|
22
|
+
{b.icon ? <Icon name={b.icon} size={12} className="-ml-0.5 mr-1 inline-block align-[-0.125em]" /> : null}
|
|
23
|
+
{b.label}
|
|
24
|
+
</Badge>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The meta lines: strings, or { icon, text } for "globe London". */
|
|
29
|
+
function Meta({ meta }) {
|
|
30
|
+
const list = (Array.isArray(meta) ? meta : [meta]).filter(Boolean);
|
|
31
|
+
if (list.length === 0) return null;
|
|
32
|
+
return (
|
|
33
|
+
<ul className="mt-1 flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground">
|
|
34
|
+
{list.map((m, i) => {
|
|
35
|
+
const item = typeof m === "object" && !Array.isArray(m) && m !== null && "text" in m ? m : { text: m };
|
|
36
|
+
return (
|
|
37
|
+
<li key={i} className="inline-flex min-w-0 items-center gap-1.5">
|
|
38
|
+
{item.icon ? <Icon name={item.icon} size={14} className="shrink-0" /> : null}
|
|
39
|
+
<span className="min-w-0 break-words">{item.text}</span>
|
|
40
|
+
</li>
|
|
41
|
+
);
|
|
42
|
+
})}
|
|
43
|
+
</ul>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function Header({ title, description, icon, badge, actions }) {
|
|
48
|
+
if (!title && !description && !actions && !badge) return null;
|
|
49
|
+
return (
|
|
50
|
+
<div className="flex flex-wrap items-start justify-between gap-3 px-4 pb-3 pt-4">
|
|
51
|
+
<div className="flex min-w-0 flex-1 items-start gap-3">
|
|
52
|
+
{icon ? (
|
|
53
|
+
<span className="grid size-10 shrink-0 place-items-center rounded-md bg-muted text-muted-foreground">
|
|
54
|
+
<Icon name={icon} size={18} />
|
|
55
|
+
</span>
|
|
56
|
+
) : null}
|
|
57
|
+
<div className="min-w-0">
|
|
58
|
+
{title ? <h2 className="text-base font-semibold leading-tight">{title}</h2> : null}
|
|
59
|
+
{description ? <p className="mt-0.5 text-sm text-muted-foreground">{description}</p> : null}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
{badge || actions ? (
|
|
63
|
+
<div className="flex shrink-0 flex-wrap items-center gap-2">
|
|
64
|
+
<RowBadge badge={badge} />
|
|
65
|
+
{actions}
|
|
66
|
+
</div>
|
|
67
|
+
) : null}
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Rows under their `group` headings, in the order groups first appear. */
|
|
73
|
+
export function grouped(rows) {
|
|
74
|
+
const out = [];
|
|
75
|
+
for (const r of rows) {
|
|
76
|
+
const g = r.group ?? null;
|
|
77
|
+
let bucket = out.find((b) => b.group === g);
|
|
78
|
+
if (!bucket) out.push((bucket = { group: g, rows: [] }));
|
|
79
|
+
bucket.rows.push(r);
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function GroupHeading({ children }) {
|
|
85
|
+
return (
|
|
86
|
+
<li className="border-t border-border bg-muted/50 px-4 py-2" role="presentation">
|
|
87
|
+
<Kicker>{children}</Kicker>
|
|
88
|
+
</li>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function Row({ row, saves, onChange, onAction, ask, disabled }) {
|
|
93
|
+
const id = useId();
|
|
94
|
+
const [open, setOpen] = useState(row.defaultOpen ?? false);
|
|
95
|
+
const c = row.control ?? null;
|
|
96
|
+
const key = row.key;
|
|
97
|
+
const busy = saves.isBusy(key);
|
|
98
|
+
const failure = saves.failure(key);
|
|
99
|
+
const off = disabled || row.disabled;
|
|
100
|
+
const detailsId = `${id}-details`;
|
|
101
|
+
const details = typeof row.details === "function" ? row.details(row) : row.details;
|
|
102
|
+
const inline = c?.type === "switch";
|
|
103
|
+
const switchId = `${id}-switch`;
|
|
104
|
+
const noAction = !onAction;
|
|
105
|
+
|
|
106
|
+
function change(value) {
|
|
107
|
+
if (!onChange) return;
|
|
108
|
+
saves.run(key, () => onChange(row, value), { value, stored: c.value });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function act(action) {
|
|
112
|
+
const go = () => saves.run(key, () => onAction(row, action.key ?? action.label), { fallback: `${action.label} did not go through.` });
|
|
113
|
+
if (action.confirm) ask({ ...action.confirm, run: go, tone: action.confirm.tone ?? (action.tone === "danger" ? "danger" : undefined) });
|
|
114
|
+
else go();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let control = null;
|
|
118
|
+
if (c?.type === "switch") {
|
|
119
|
+
const on = saves.valueOf(key, c.value) === true;
|
|
120
|
+
control = (
|
|
121
|
+
<Switch id={switchId} checked={on} disabled={off || busy || !onChange} onChange={(e) => change(e.target.checked)} />
|
|
122
|
+
);
|
|
123
|
+
} else if (c?.type === "select") {
|
|
124
|
+
control = (
|
|
125
|
+
<Select
|
|
126
|
+
aria-label={row.label}
|
|
127
|
+
value={saves.valueOf(key, c.value) ?? ""}
|
|
128
|
+
options={c.options}
|
|
129
|
+
disabled={off || busy || !onChange}
|
|
130
|
+
onChange={(e) => change(e.target.value)}
|
|
131
|
+
className="sm:w-48"
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
} else if (c?.type === "button") {
|
|
135
|
+
const action = { key: c.key ?? "button", label: c.label, tone: c.tone, confirm: c.confirm };
|
|
136
|
+
control = (
|
|
137
|
+
<Button
|
|
138
|
+
size="sm"
|
|
139
|
+
icon={c.icon}
|
|
140
|
+
variant={c.variant ?? (c.tone === "danger" ? "danger" : "secondary")}
|
|
141
|
+
loading={busy}
|
|
142
|
+
disabled={off || noAction}
|
|
143
|
+
onClick={() => act(action)}
|
|
144
|
+
>
|
|
145
|
+
{c.label}
|
|
146
|
+
</Button>
|
|
147
|
+
);
|
|
148
|
+
} else if (c?.type === "actions") {
|
|
149
|
+
const items = (c.items ?? []).filter(Boolean);
|
|
150
|
+
control = (
|
|
151
|
+
<div className="flex items-center gap-1">
|
|
152
|
+
{busy ? <Saving label="Working" /> : null}
|
|
153
|
+
{c.menu || items.length > 2 ? (
|
|
154
|
+
<Menu
|
|
155
|
+
label={`${row.label}, actions`}
|
|
156
|
+
items={items.map((a) => ({ label: a.label, icon: a.icon, tone: a.tone, disabled: off || busy || noAction, onSelect: () => act(a) }))}
|
|
157
|
+
/>
|
|
158
|
+
) : (
|
|
159
|
+
items.map((a) => (
|
|
160
|
+
<Button key={a.key ?? a.label} size="sm" variant={a.tone === "danger" ? "danger" : "quiet"} icon={a.icon} disabled={off || busy || noAction} onClick={() => act(a)}>
|
|
161
|
+
{a.label}
|
|
162
|
+
</Button>
|
|
163
|
+
))
|
|
164
|
+
)}
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
} else if (c?.type === "remove") {
|
|
168
|
+
control = (
|
|
169
|
+
<IconButton
|
|
170
|
+
icon="x"
|
|
171
|
+
label={c.label ?? `Remove ${row.label}`}
|
|
172
|
+
variant="secondary"
|
|
173
|
+
size="sm"
|
|
174
|
+
disabled={off || busy || noAction}
|
|
175
|
+
onClick={() => act({ key: "remove", label: c.label ?? "Remove", tone: "danger", confirm: c.confirm })}
|
|
176
|
+
/>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<li className="border-t border-border px-4 py-4">
|
|
182
|
+
<div className={cx("flex items-start gap-3", !inline && "flex-wrap")}>
|
|
183
|
+
{row.media ? (
|
|
184
|
+
<span className="shrink-0">{row.media}</span>
|
|
185
|
+
) : row.icon ? (
|
|
186
|
+
<span className="grid size-10 shrink-0 place-items-center rounded-md bg-muted text-muted-foreground">
|
|
187
|
+
<Icon name={row.icon} size={18} />
|
|
188
|
+
</span>
|
|
189
|
+
) : null}
|
|
190
|
+
<div className={cx("min-w-0 flex-1", !inline && "basis-52")}>
|
|
191
|
+
<div className="flex flex-wrap items-center gap-x-2 gap-y-1">
|
|
192
|
+
{inline ? (
|
|
193
|
+
<label htmlFor={switchId} className="font-medium leading-tight text-foreground">
|
|
194
|
+
{row.label}
|
|
195
|
+
</label>
|
|
196
|
+
) : (
|
|
197
|
+
<p className="font-medium leading-tight text-foreground">{row.label}</p>
|
|
198
|
+
)}
|
|
199
|
+
<RowBadge badge={row.badge} />
|
|
200
|
+
</div>
|
|
201
|
+
{row.description ? <p className="mt-1 text-sm text-muted-foreground">{row.description}</p> : null}
|
|
202
|
+
{row.value ? (
|
|
203
|
+
<p className={cx("mt-1 inline-flex items-center gap-1.5 text-sm", row.valueTone === "set" ? "font-medium text-foreground" : "text-muted-foreground")}>
|
|
204
|
+
{row.valueTone === "set" ? <Icon name="circle-check" size={14} className="shrink-0 text-success" /> : null}
|
|
205
|
+
{row.value}
|
|
206
|
+
</p>
|
|
207
|
+
) : null}
|
|
208
|
+
<Meta meta={row.meta} />
|
|
209
|
+
</div>
|
|
210
|
+
{control || details ? (
|
|
211
|
+
<div className={cx("flex shrink-0 items-center gap-2", !inline && (row.icon || row.media) && "max-sm:ml-13")}>
|
|
212
|
+
{busy && c?.type !== "button" && c?.type !== "actions" ? <Saving /> : null}
|
|
213
|
+
{control}
|
|
214
|
+
{details ? (
|
|
215
|
+
<IconButton
|
|
216
|
+
icon={open ? "chevron-up" : "chevron-down"}
|
|
217
|
+
label={`${open ? "Hide" : "Show"} details for ${row.label}`}
|
|
218
|
+
size="sm"
|
|
219
|
+
aria-expanded={open}
|
|
220
|
+
aria-controls={detailsId}
|
|
221
|
+
onClick={() => setOpen((v) => !v)}
|
|
222
|
+
/>
|
|
223
|
+
) : null}
|
|
224
|
+
</div>
|
|
225
|
+
) : null}
|
|
226
|
+
</div>
|
|
227
|
+
<Failure failure={failure} className="mt-2 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-destructive" />
|
|
228
|
+
{details ? (
|
|
229
|
+
<div id={detailsId} hidden={!open} className="mt-3 rounded-md border border-border bg-muted/40 p-3 text-sm">
|
|
230
|
+
{details}
|
|
231
|
+
</div>
|
|
232
|
+
) : null}
|
|
233
|
+
</li>
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function SettingsList({
|
|
238
|
+
rows = [],
|
|
239
|
+
variant = "list",
|
|
240
|
+
channels = [],
|
|
241
|
+
onChange,
|
|
242
|
+
onAction,
|
|
243
|
+
title,
|
|
244
|
+
description,
|
|
245
|
+
icon,
|
|
246
|
+
badge,
|
|
247
|
+
actions,
|
|
248
|
+
footer,
|
|
249
|
+
loading = false,
|
|
250
|
+
error,
|
|
251
|
+
onRetry,
|
|
252
|
+
emptyTitle = "Nothing here yet",
|
|
253
|
+
emptyBody,
|
|
254
|
+
emptyAction,
|
|
255
|
+
disabled = false,
|
|
256
|
+
failedText = "Not saved. The old value is back.",
|
|
257
|
+
className,
|
|
258
|
+
}) {
|
|
259
|
+
const saves = useSaves(failedText);
|
|
260
|
+
const [asking, setAsking] = useState(null);
|
|
261
|
+
const [confirming, setConfirming] = useState(false);
|
|
262
|
+
|
|
263
|
+
async function confirmNow() {
|
|
264
|
+
if (!asking) return;
|
|
265
|
+
setConfirming(true);
|
|
266
|
+
await asking.run();
|
|
267
|
+
setConfirming(false);
|
|
268
|
+
setAsking(null);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
let body;
|
|
272
|
+
if (error) {
|
|
273
|
+
body = (
|
|
274
|
+
<div className="border-t border-border p-4">
|
|
275
|
+
<Notice tone="danger" title="These settings could not be loaded" action={onRetry ? <Button size="sm" onClick={onRetry}>Try again</Button> : null}>
|
|
276
|
+
{error}
|
|
277
|
+
</Notice>
|
|
278
|
+
</div>
|
|
279
|
+
);
|
|
280
|
+
} else if (loading) {
|
|
281
|
+
body = (
|
|
282
|
+
<ul aria-busy="true" aria-label="Loading">
|
|
283
|
+
{[0, 1, 2].map((i) => (
|
|
284
|
+
<li key={i} className="flex items-center gap-3 border-t border-border px-4 py-4">
|
|
285
|
+
<Skeleton shape="rect" className="size-10 shrink-0" />
|
|
286
|
+
<div className="grid min-w-0 flex-1 gap-2">
|
|
287
|
+
<Skeleton className="w-1/3" />
|
|
288
|
+
<Skeleton className="w-2/3" />
|
|
289
|
+
</div>
|
|
290
|
+
<Skeleton shape="rect" className="h-6 w-10 shrink-0 rounded-full" />
|
|
291
|
+
</li>
|
|
292
|
+
))}
|
|
293
|
+
</ul>
|
|
294
|
+
);
|
|
295
|
+
} else if (rows.length === 0) {
|
|
296
|
+
body = (
|
|
297
|
+
<div className="border-t border-border p-4">
|
|
298
|
+
<Empty icon={icon ?? "settings"} title={emptyTitle} body={emptyBody} action={emptyAction} />
|
|
299
|
+
</div>
|
|
300
|
+
);
|
|
301
|
+
} else if (variant === "matrix") {
|
|
302
|
+
body = <SettingsMatrix rows={rows} channels={channels} onChange={onChange} saves={saves} disabled={disabled} />;
|
|
303
|
+
} else {
|
|
304
|
+
body = (
|
|
305
|
+
<ul>
|
|
306
|
+
{grouped(rows).map((b) => (
|
|
307
|
+
<GroupRows key={b.group ?? "_"} bucket={b}>
|
|
308
|
+
{b.rows.map((row) => (
|
|
309
|
+
<Row key={row.key} row={row} saves={saves} onChange={onChange} onAction={onAction} ask={setAsking} disabled={disabled} />
|
|
310
|
+
))}
|
|
311
|
+
</GroupRows>
|
|
312
|
+
))}
|
|
313
|
+
</ul>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const headed = Boolean(title || description || actions || badge);
|
|
318
|
+
return (
|
|
319
|
+
<Card padding="none" className={cx(!headed && "[&>ul>li:first-child]:border-t-0", className)}>
|
|
320
|
+
<Header title={title} description={description} icon={icon} badge={badge} actions={actions} />
|
|
321
|
+
{body}
|
|
322
|
+
{footer ? <div className="border-t border-border p-4">{footer}</div> : null}
|
|
323
|
+
<Confirm
|
|
324
|
+
open={Boolean(asking)}
|
|
325
|
+
onClose={() => {
|
|
326
|
+
if (!confirming) setAsking(null);
|
|
327
|
+
}}
|
|
328
|
+
onConfirm={confirmNow}
|
|
329
|
+
busy={confirming}
|
|
330
|
+
tone={asking?.tone ?? "neutral"}
|
|
331
|
+
title={asking?.title ?? "Are you sure?"}
|
|
332
|
+
body={asking?.body}
|
|
333
|
+
confirmLabel={asking?.confirmLabel ?? "Confirm"}
|
|
334
|
+
consequences={asking?.consequences}
|
|
335
|
+
requireText={asking?.requireText}
|
|
336
|
+
acknowledge={asking?.acknowledge}
|
|
337
|
+
/>
|
|
338
|
+
</Card>
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function GroupRows({ bucket, children }) {
|
|
343
|
+
return (
|
|
344
|
+
<>
|
|
345
|
+
{bucket.group ? <GroupHeading>{bucket.group}</GroupHeading> : null}
|
|
346
|
+
{children}
|
|
347
|
+
</>
|
|
348
|
+
);
|
|
349
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { Icon, Kicker, Switch, cx } from "../../ui";
|
|
5
|
+
import { Failure, Saving } from "./row-state";
|
|
6
|
+
|
|
7
|
+
// The notification grid of a SettingsList (variant="matrix"): events down
|
|
8
|
+
// the side, grouped; channels (email, push, SMS…) across the top; a Switch
|
|
9
|
+
// in every cell that saves on its own. From 768px it is a grid with the
|
|
10
|
+
// channels as column heads. On a phone each event's switches stack under
|
|
11
|
+
// it, each one named by its channel, so nothing scrolls sideways.
|
|
12
|
+
|
|
13
|
+
function groupsOf(rows) {
|
|
14
|
+
const out = [];
|
|
15
|
+
for (const r of rows) {
|
|
16
|
+
const g = r.group ?? null;
|
|
17
|
+
let b = out.find((x) => x.group === g);
|
|
18
|
+
if (!b) out.push((b = { group: g, rows: [] }));
|
|
19
|
+
b.rows.push(r);
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// The grid's columns: the event, then one fixed column per channel. The
|
|
25
|
+
// count comes in as a custom property so one class serves any number.
|
|
26
|
+
const GRID = "md:grid md:items-center md:gap-x-2 md:[grid-template-columns:minmax(0,1fr)_repeat(var(--channels),5.5rem)]";
|
|
27
|
+
|
|
28
|
+
function Cell({ row, channel, saves, onChange, disabled }) {
|
|
29
|
+
const id = useId();
|
|
30
|
+
const key = `${row.key}:${channel.key}`;
|
|
31
|
+
const stored = row.values?.[channel.key];
|
|
32
|
+
if (stored === undefined || stored === null) {
|
|
33
|
+
// This event cannot be sent on this channel.
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex min-h-11 items-center gap-2 text-sm text-muted-foreground md:justify-center">
|
|
36
|
+
<span className="md:sr-only">{channel.label}</span>
|
|
37
|
+
<span aria-hidden="true">—</span>
|
|
38
|
+
<span className="sr-only">not offered</span>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const locked = (row.locked ?? []).includes(channel.key);
|
|
43
|
+
const busy = saves.isBusy(key);
|
|
44
|
+
const on = saves.valueOf(key, stored) === true;
|
|
45
|
+
return (
|
|
46
|
+
<div className="flex min-h-11 items-center gap-2 md:justify-center">
|
|
47
|
+
<Switch
|
|
48
|
+
id={id}
|
|
49
|
+
checked={on}
|
|
50
|
+
disabled={disabled || locked || busy || !onChange}
|
|
51
|
+
onChange={(e) => {
|
|
52
|
+
const value = e.target.checked;
|
|
53
|
+
saves.run(key, () => onChange(row, value, channel.key), { value, stored });
|
|
54
|
+
}}
|
|
55
|
+
label={
|
|
56
|
+
<span className="md:sr-only">
|
|
57
|
+
{channel.label}
|
|
58
|
+
{locked ? <span className="sr-only"> (always on)</span> : null}
|
|
59
|
+
</span>
|
|
60
|
+
}
|
|
61
|
+
/>
|
|
62
|
+
{locked ? <Icon name="lock" size={12} className="shrink-0 text-muted-foreground" /> : null}
|
|
63
|
+
{busy ? <Saving /> : null}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function SettingsMatrix({ rows, channels, onChange, saves, disabled }) {
|
|
69
|
+
const base = useId();
|
|
70
|
+
return (
|
|
71
|
+
<div style={{ "--channels": channels.length }}>
|
|
72
|
+
<div className={cx("hidden border-t border-border px-4 py-2", GRID)} aria-hidden="true">
|
|
73
|
+
<Kicker>Event</Kicker>
|
|
74
|
+
{channels.map((c) => (
|
|
75
|
+
<span key={c.key} className="inline-flex items-center justify-center gap-1.5 text-xs font-medium text-muted-foreground">
|
|
76
|
+
{c.icon ? <Icon name={c.icon} size={14} /> : null}
|
|
77
|
+
{c.label}
|
|
78
|
+
</span>
|
|
79
|
+
))}
|
|
80
|
+
</div>
|
|
81
|
+
{groupsOf(rows).map((g) => (
|
|
82
|
+
<section key={g.group ?? "_"} aria-label={g.group ?? undefined}>
|
|
83
|
+
{g.group ? (
|
|
84
|
+
<div className="border-t border-border bg-muted/50 px-4 py-2">
|
|
85
|
+
<Kicker>{g.group}</Kicker>
|
|
86
|
+
</div>
|
|
87
|
+
) : null}
|
|
88
|
+
<ul>
|
|
89
|
+
{g.rows.map((row) => {
|
|
90
|
+
const labelId = `${base}-${row.key}`;
|
|
91
|
+
const failures = channels.map((c) => ({ c, f: saves.failure(`${row.key}:${c.key}`) })).filter((x) => x.f);
|
|
92
|
+
return (
|
|
93
|
+
<li key={row.key} role="group" aria-labelledby={labelId} className="border-t border-border px-4 py-3">
|
|
94
|
+
<div className={GRID}>
|
|
95
|
+
<div className="min-w-0 pb-1 md:pb-0">
|
|
96
|
+
<p id={labelId} className="text-sm font-medium text-foreground">
|
|
97
|
+
{row.label}
|
|
98
|
+
</p>
|
|
99
|
+
{row.description ? <p className="text-sm text-muted-foreground">{row.description}</p> : null}
|
|
100
|
+
</div>
|
|
101
|
+
<div className="flex flex-wrap gap-x-5 md:contents">
|
|
102
|
+
{channels.map((c) => (
|
|
103
|
+
<Cell key={c.key} row={row} channel={c} saves={saves} onChange={onChange} disabled={disabled} />
|
|
104
|
+
))}
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
{failures.map(({ c, f }) => (
|
|
108
|
+
<Failure key={c.key} failure={{ ...f, error: `${c.label}: ${f.error}` }} className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-destructive" />
|
|
109
|
+
))}
|
|
110
|
+
</li>
|
|
111
|
+
);
|
|
112
|
+
})}
|
|
113
|
+
</ul>
|
|
114
|
+
</section>
|
|
115
|
+
))}
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# SetupChecklist
|
|
2
|
+
|
|
3
|
+
The steps to get set up, which of them are done, how far along the whole
|
|
4
|
+
is, and the button for the next one. The steps are yours: their `done`
|
|
5
|
+
comes from the app's data (the profile has a name, a teammate was
|
|
6
|
+
invited), so the list is never a second record of the truth. A step's
|
|
7
|
+
button goes out through `onAction`; while it runs the button spins, and
|
|
8
|
+
when it fails the step says why.
|
|
9
|
+
|
|
10
|
+
```jsx
|
|
11
|
+
import { SetupChecklist } from "../components/blocks/setup-checklist"; // a Makersclaw app ("./blocks/setup-checklist" from components/)
|
|
12
|
+
import { SetupChecklist } from "@/components/makersclaw/blocks/setup-checklist"; // a shadcn project
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
A client component. Work out `done` for each step in the server surface
|
|
16
|
+
(README §4) and pass the steps in.
|
|
17
|
+
|
|
18
|
+
## The data
|
|
19
|
+
|
|
20
|
+
`steps` — in order:
|
|
21
|
+
`[{ key, title, description?, actionLabel?, href?, icon?, summary?, done }]`.
|
|
22
|
+
|
|
23
|
+
- `key` — unique, stable.
|
|
24
|
+
- `actionLabel` — the step's button ("Send invites"); default "Start"
|
|
25
|
+
("Open" once done).
|
|
26
|
+
- `href` — the button is a link to the page where the step is done;
|
|
27
|
+
`onAction` still hears about the click.
|
|
28
|
+
- `icon` — a kit `Icon` name: on the right of a card and in its button
|
|
29
|
+
(`cards`), above the text (`accordion`).
|
|
30
|
+
- `summary` — `accordion`: the bold line in the step's panel.
|
|
31
|
+
|
|
32
|
+
The next step is the first one not done.
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
- `steps` — as above. Required.
|
|
37
|
+
- `variant` — default `"collapsible"`:
|
|
38
|
+
- `collapsible` — a card: the title, a ring with "2 of 6 done", a "⋯"
|
|
39
|
+
menu (Dismiss and `menuItems`), then each step a folding row with its
|
|
40
|
+
description and button. The next step starts open, and when the open
|
|
41
|
+
step gets done the next one opens.
|
|
42
|
+
- `cards` — the title, "1 of 4 done" and a bar, then a numbered card
|
|
43
|
+
per step. Only the next step shows its button.
|
|
44
|
+
- `list` — the title, "Step 2 of 4" and a short bar, then a row per
|
|
45
|
+
step, numbered "1.", "2."; the next one is outlined and shows its
|
|
46
|
+
button. `footer` sits in a filled panel below ("Need a hand?").
|
|
47
|
+
- `accordion` — each step a bordered folding row; its panel is centred:
|
|
48
|
+
icon, `summary`, description, button. Pair it with `sequential`.
|
|
49
|
+
- `onAction(step)` — the step's button (or a click on its link). Do the
|
|
50
|
+
thing, or open your `Sheet` for it; return `{ ok: true }` or
|
|
51
|
+
`{ ok: false, error }` (a throw counts as failed) and the step shows the
|
|
52
|
+
error under its button. Mark it done by passing the step back with
|
|
53
|
+
`done: true`; the block never marks a step itself. Without `onAction`
|
|
54
|
+
only steps with an `href` have a button.
|
|
55
|
+
- `sequential` — a step's button stays disabled, with "Finish the steps
|
|
56
|
+
before this one first", until every step before it is done. Default
|
|
57
|
+
`false`: any step can be done in any order.
|
|
58
|
+
- `title` — default "Get set up". `description` — a line under it.
|
|
59
|
+
- `onDismiss()` — adds Dismiss to the "⋯" menu (`collapsible` shows the
|
|
60
|
+
menu in its header, the others beside the title). Hide the checklist
|
|
61
|
+
and remember that you did; return `{ ok: false, error }` to show why it
|
|
62
|
+
could not.
|
|
63
|
+
- `menuItems` — more "⋯" items, kit `Menu` shape: `[{ label, onSelect,
|
|
64
|
+
icon? }]` ("Send feedback").
|
|
65
|
+
- `footer` — a node under the steps: help, a link to the docs.
|
|
66
|
+
- `doneLabel` — what the header says when every step is done, default
|
|
67
|
+
"All set" (the bar turns to the success tone).
|
|
68
|
+
- `loading` — skeleton rows while the steps load.
|
|
69
|
+
- `error` — a string: the steps did not load. Shown in a notice with
|
|
70
|
+
Retry when `onRetry` is given.
|
|
71
|
+
- `className` — layout around it (width, margin). Never colour.
|
|
72
|
+
|
|
73
|
+
With no steps it says "Nothing to set up".
|
|
74
|
+
|
|
75
|
+
## Example
|
|
76
|
+
|
|
77
|
+
```jsx
|
|
78
|
+
// surfaces/home.jsx — server: work out what is done
|
|
79
|
+
import { loadRows } from "../lib/data";
|
|
80
|
+
import GettingStarted from "../components/GettingStarted";
|
|
81
|
+
|
|
82
|
+
export default async function Home() {
|
|
83
|
+
const [{ rows: members }, { rows: deals }] = await Promise.all([
|
|
84
|
+
loadRows({ source: "public.members" }),
|
|
85
|
+
loadRows({ source: "public.deals", limit: 1 }),
|
|
86
|
+
]);
|
|
87
|
+
return <GettingStarted invited={members.length > 1} hasDeal={deals.length > 0} />;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```jsx
|
|
92
|
+
// components/GettingStarted.jsx — client
|
|
93
|
+
"use client";
|
|
94
|
+
import { SetupChecklist } from "./blocks/setup-checklist";
|
|
95
|
+
|
|
96
|
+
export default function GettingStarted({ invited, hasDeal, onHide }) {
|
|
97
|
+
return (
|
|
98
|
+
<SetupChecklist
|
|
99
|
+
title="Get started"
|
|
100
|
+
steps={[
|
|
101
|
+
{ key: "invite", title: "Invite your team", description: "Bring in the people who own accounts.", actionLabel: "Invite", href: "/team", done: invited },
|
|
102
|
+
{ key: "deal", title: "Add your first deal", description: "One deal is enough to see the pipeline work.", actionLabel: "Add a deal", href: "/deals?new=1", done: hasDeal },
|
|
103
|
+
]}
|
|
104
|
+
onDismiss={onHide}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
In order, with buttons that do the work in place:
|
|
111
|
+
|
|
112
|
+
```jsx
|
|
113
|
+
<SetupChecklist
|
|
114
|
+
variant="accordion"
|
|
115
|
+
sequential
|
|
116
|
+
title="Quick start"
|
|
117
|
+
steps={steps}
|
|
118
|
+
onAction={async (step) => {
|
|
119
|
+
const res = await runSetupStep(step.key); // your server action, { ok, error }
|
|
120
|
+
if (res.ok) router.refresh(); // the step comes back done
|
|
121
|
+
return res;
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## What it will not do
|
|
127
|
+
|
|
128
|
+
- Decide a step is done: `done` is yours, from your data.
|
|
129
|
+
- Remember that it was dismissed: `onDismiss` is where you save that.
|
|
130
|
+
- Nest steps inside steps, or show a running job's stages: that is the kit
|
|
131
|
+
`Steps` or the `job-panel` block.
|
|
132
|
+
- Page through a wizard of forms: each step's button goes where the work
|
|
133
|
+
is.
|
|
134
|
+
|
|
135
|
+
A checklist it cannot be is your own component in `components/`, built
|
|
136
|
+
from the kit — not an edit to this block. Its files are fixed: `npm run
|
|
137
|
+
check` refuses a change, and `makersclaw add setup-checklist` restores
|
|
138
|
+
them.
|
|
139
|
+
|
|
140
|
+
## Credits
|
|
141
|
+
|
|
142
|
+
Ported from blocks.so (https://blocks.so, onboarding 01–04, MIT), rewritten on the Makersclaw kit.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "setup-checklist",
|
|
3
|
+
"title": "SetupChecklist",
|
|
4
|
+
"description": "The steps to get set up: which are done, how far along the whole is (a ring, a bar, or \"Step 2 of 4\"), and the button for the next one, sent out through an async onAction that can fail on the step. Four shapes: folding rows in a card with a dismiss menu, numbered step cards, a plain step list with a help panel, and bordered accordion rows that can be locked until the step before is done.",
|
|
5
|
+
"useWhen": "A new account, workspace or shop has a few things to do before it is useful (complete the profile, invite the team, connect a tool, launch) and the founder should see what is left. Not for a running job's stages (kit Steps or job-panel), and not for a multi-page form wizard.",
|
|
6
|
+
"tags": ["onboarding", "checklist", "setup", "getting started", "steps", "progress", "tasks", "welcome", "quick start", "wizard", "dismiss"],
|
|
7
|
+
"exports": ["SetupChecklist"],
|
|
8
|
+
"files": ["index.js", "setup-checklist.jsx"],
|
|
9
|
+
"requires": []
|
|
10
|
+
}
|