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,144 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { Badge, ButtonGroup, Field, IconButton, RadioGroup, Select, Swatch, ToggleGroup, cx } from "../../ui";
|
|
5
|
+
import { formatPrice, labelOf, valuesOf } from "./price";
|
|
6
|
+
|
|
7
|
+
// One option's control. How it is drawn follows the values unless the
|
|
8
|
+
// option says (`display`):
|
|
9
|
+
// swatches values carry a `color` → colour squares, the name in the heading
|
|
10
|
+
// buttons up to 6 short values → a segmented row (sizes)
|
|
11
|
+
// select more, or longer, values → the native select
|
|
12
|
+
// plans values carry a `price` or a `description` → a card per value
|
|
13
|
+
function displayOf(option, values) {
|
|
14
|
+
if (option.display) return option.display;
|
|
15
|
+
if (values.some((v) => v.color)) return "swatches";
|
|
16
|
+
if (values.some((v) => typeof v.price === "number" || v.description)) return "plans";
|
|
17
|
+
const long = values.reduce((n, v) => n + labelOf(v).length, 0) > 30;
|
|
18
|
+
return values.length <= 6 && !long ? "buttons" : "select";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function OptionPicker({ option, value, onChange, currency, locale }) {
|
|
22
|
+
const id = useId();
|
|
23
|
+
const values = valuesOf(option);
|
|
24
|
+
if (values.length === 0) return null;
|
|
25
|
+
const display = displayOf(option, values);
|
|
26
|
+
const current = values.find((v) => v.value === value);
|
|
27
|
+
const heading = option.label ?? option.key;
|
|
28
|
+
|
|
29
|
+
if (display === "select") {
|
|
30
|
+
return (
|
|
31
|
+
<Field id={id} label={heading}>
|
|
32
|
+
<Select id={id} value={value ?? ""} onChange={(e) => onChange(e.target.value)}>
|
|
33
|
+
{values.map((v) => (
|
|
34
|
+
<option key={v.value} value={v.value} disabled={v.disabled}>
|
|
35
|
+
{labelOf(v)}
|
|
36
|
+
{v.disabled ? " — sold out" : ""}
|
|
37
|
+
</option>
|
|
38
|
+
))}
|
|
39
|
+
</Select>
|
|
40
|
+
</Field>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (display === "plans") {
|
|
45
|
+
return (
|
|
46
|
+
<div className="grid gap-2">
|
|
47
|
+
<p id={`${id}-l`} className="text-sm font-medium text-foreground">
|
|
48
|
+
{heading}
|
|
49
|
+
</p>
|
|
50
|
+
<RadioGroup
|
|
51
|
+
aria-labelledby={`${id}-l`}
|
|
52
|
+
variant="card"
|
|
53
|
+
value={value ?? undefined}
|
|
54
|
+
onChange={onChange}
|
|
55
|
+
options={values.map((v) => ({
|
|
56
|
+
value: v.value,
|
|
57
|
+
disabled: v.disabled,
|
|
58
|
+
description: v.description,
|
|
59
|
+
label: (
|
|
60
|
+
<span className="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1">
|
|
61
|
+
<span className="inline-flex flex-wrap items-center gap-2">
|
|
62
|
+
{labelOf(v)}
|
|
63
|
+
{v.badge ? (
|
|
64
|
+
<Badge tone="primary" variant="soft">
|
|
65
|
+
{v.badge}
|
|
66
|
+
</Badge>
|
|
67
|
+
) : null}
|
|
68
|
+
</span>
|
|
69
|
+
{typeof v.price === "number" ? (
|
|
70
|
+
<span data-nums className="font-semibold">
|
|
71
|
+
{formatPrice(v.price, currency, locale)}
|
|
72
|
+
{v.per ? <span className="text-xs font-normal text-muted-foreground"> {v.per}</span> : null}
|
|
73
|
+
</span>
|
|
74
|
+
) : null}
|
|
75
|
+
</span>
|
|
76
|
+
),
|
|
77
|
+
}))}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const swatches = display === "swatches";
|
|
84
|
+
return (
|
|
85
|
+
<div className="grid gap-2">
|
|
86
|
+
<p id={`${id}-l`} className="text-sm font-medium text-foreground">
|
|
87
|
+
{heading}
|
|
88
|
+
{swatches && current ? <span className="font-normal text-muted-foreground">: {labelOf(current)}</span> : null}
|
|
89
|
+
</p>
|
|
90
|
+
<ToggleGroup
|
|
91
|
+
aria-label={heading}
|
|
92
|
+
value={value ?? undefined}
|
|
93
|
+
onChange={onChange}
|
|
94
|
+
className={swatches ? "flex-wrap" : undefined}
|
|
95
|
+
items={values.map((v) => ({
|
|
96
|
+
value: v.value,
|
|
97
|
+
disabled: v.disabled,
|
|
98
|
+
label: swatches ? (
|
|
99
|
+
<Swatch color={v.color} label={`${labelOf(v)}${v.disabled ? ", sold out" : ""}`} />
|
|
100
|
+
) : (
|
|
101
|
+
<span className={cx(v.disabled && "line-through")}>{labelOf(v)}</span>
|
|
102
|
+
),
|
|
103
|
+
}))}
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** − n + as one attached control. The count is announced as it changes. */
|
|
110
|
+
export function QuantityControl({ value, onChange, min = 1, max = 10, disabled, label = "Quantity" }) {
|
|
111
|
+
const id = useId();
|
|
112
|
+
return (
|
|
113
|
+
<div className="grid gap-2">
|
|
114
|
+
<p id={id} className="text-sm font-medium text-foreground">
|
|
115
|
+
{label}
|
|
116
|
+
</p>
|
|
117
|
+
<ButtonGroup aria-labelledby={id} className="w-fit">
|
|
118
|
+
<IconButton
|
|
119
|
+
icon="minus"
|
|
120
|
+
label="Decrease quantity"
|
|
121
|
+
variant="secondary"
|
|
122
|
+
disabled={disabled || value <= min}
|
|
123
|
+
onClick={() => onChange(Math.max(min, value - 1))}
|
|
124
|
+
/>
|
|
125
|
+
<output
|
|
126
|
+
aria-live="polite"
|
|
127
|
+
aria-label={`${label} ${value}`}
|
|
128
|
+
data-nums
|
|
129
|
+
className="grid min-w-12 place-items-center border border-border bg-background px-2 text-sm font-medium text-foreground"
|
|
130
|
+
>
|
|
131
|
+
{value}
|
|
132
|
+
</output>
|
|
133
|
+
<IconButton
|
|
134
|
+
icon="plus"
|
|
135
|
+
label="Increase quantity"
|
|
136
|
+
variant="secondary"
|
|
137
|
+
disabled={disabled || value >= max}
|
|
138
|
+
onClick={() => onChange(Math.min(max, value + 1))}
|
|
139
|
+
/>
|
|
140
|
+
</ButtonGroup>
|
|
141
|
+
{value >= max && max > min ? <p className="text-xs text-muted-foreground">{max} is the most you can add at once.</p> : null}
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Product grid
|
|
2
|
+
|
|
3
|
+
Products as cards in a grid — picture, badge, heart, brand, name, stars,
|
|
4
|
+
price — with a quick **Add to cart** on each. Over the grid: facet filters,
|
|
5
|
+
a sort and a live count. A lead tile (a picture or a muted looping video)
|
|
6
|
+
can take a double cell, and `card="promo"` turns the cards into collection
|
|
7
|
+
tiles ("New", "Sale"). The add goes out through `onAddToCart(line)`; while
|
|
8
|
+
it runs the card's button spins, when it fails the card says why.
|
|
9
|
+
|
|
10
|
+
```jsx
|
|
11
|
+
import { ProductGrid } from "../components/blocks/product-grid"; // a Makersclaw app ("./blocks/product-grid" from components/)
|
|
12
|
+
import { ProductGrid } from "@/components/makersclaw/blocks/product-grid"; // a shadcn project
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
It is a client component: render it from a `"use client"` component, and
|
|
16
|
+
load the rows in the server surface (README §4). It requires
|
|
17
|
+
`product-detail` (added with it): the cards share its price and cart line.
|
|
18
|
+
|
|
19
|
+
## The data
|
|
20
|
+
|
|
21
|
+
`products` are the same objects `ProductDetail` takes (see its README):
|
|
22
|
+
`{ id, name, price }` required; `compareAt`, `currency`, `image` (or
|
|
23
|
+
`images`), `brand`, `badge`, `rating`, `reviews`, `href`, `available:
|
|
24
|
+
false` (sold out), `options` all draw on the card when present. A product
|
|
25
|
+
with an option that has more than one value cannot be added blind: its
|
|
26
|
+
button says **Choose options** and opens it (`onOpen`, else its `href`).
|
|
27
|
+
|
|
28
|
+
Filters look for a value in three places on each product: its own field
|
|
29
|
+
(`product.category`, a string or a list), `product.facets[key]`, and the
|
|
30
|
+
values of its option with that key (so a **size** filter keeps what is
|
|
31
|
+
sold in that size, skipping sold-out sizes).
|
|
32
|
+
|
|
33
|
+
With `card="promo"` each item is a tile: `{ id, title, kicker?, body?,
|
|
34
|
+
image, href?, actionLabel?, action?: { label, href?, onClick? } }`.
|
|
35
|
+
|
|
36
|
+
### The cart line
|
|
37
|
+
|
|
38
|
+
`onAddToCart` gets one line, the shape the `cart` block takes as an item:
|
|
39
|
+
`{ id, key, name, price, compareAt?, currency, image, href?, quantity: 1,
|
|
40
|
+
selected: {}, variant: "" }`. `key` is the product id (plus its choices on
|
|
41
|
+
a product page), so adding the same thing twice is one row — merge
|
|
42
|
+
quantities by `key`.
|
|
43
|
+
|
|
44
|
+
## Props
|
|
45
|
+
|
|
46
|
+
- `products` — the rows. Pass `useFixture(rows, SAMPLE).rows` to show
|
|
47
|
+
example cards before there is data.
|
|
48
|
+
- `onAddToCart(line)` — return `{ ok: true }` or `{ ok: false, error }` (a
|
|
49
|
+
throw counts as failed). Without it the cards have no button.
|
|
50
|
+
- `onOpen(product)` — the card becomes a button that opens the product (a
|
|
51
|
+
`Sheet`, a route). A product's own `href` makes it a link instead.
|
|
52
|
+
- `onFavorite(product, next)` — a heart on each picture; flips at once,
|
|
53
|
+
flips back with the error when the save fails. `favorites` — the ids
|
|
54
|
+
saved now.
|
|
55
|
+
- `filters` — `[{ key, label, options, all?, value? }]`: one select per
|
|
56
|
+
facet, first choice "All …" (`all` renames it, `value` starts it set).
|
|
57
|
+
`options` are strings or `{ value, label }`.
|
|
58
|
+
- `sort` — `true` for Featured, price up, price down, top rated; or a
|
|
59
|
+
list of those keys (`"featured"`, `"price-asc"`, `"price-desc"`,
|
|
60
|
+
`"rating"`, `"newest"` by `createdAt`) and your own `{ value, label,
|
|
61
|
+
compare(a, b) }`. `defaultSort` — the key it starts on.
|
|
62
|
+
- `manual` — the loader filters and sorts (a big catalogue): the block
|
|
63
|
+
shows `products` as they come, reports each change through
|
|
64
|
+
`onQueryChange({ filters, sort })`, and counts `total`.
|
|
65
|
+
- `feature` — the lead tile, `{ kicker, title, body?, image | video +
|
|
66
|
+
poster, href | onOpen, actionLabel }`, or any node. Two cells wide (and
|
|
67
|
+
two tall from lg up). A video is muted and looping, has a pause, and
|
|
68
|
+
never plays for a reader who asks for reduced motion.
|
|
69
|
+
- `card` — `"product"` (default) or `"promo"`.
|
|
70
|
+
- `columns` — how many from lg up: `2` · `3` · `4` (default 4 for
|
|
71
|
+
products, 3 for tiles). A phone shows two product cards a row, one tile.
|
|
72
|
+
- `currency` (`"USD"`) · `locale` — for prices and counts.
|
|
73
|
+
- `countLabel(n)` — `"12 products"` by default. `addLabel` — the button's
|
|
74
|
+
words.
|
|
75
|
+
- `loading` — skeleton cards. `error` (a string) with `onRetry` — "Try
|
|
76
|
+
again". `emptyTitle` · `emptyBody` — when there are no products; when
|
|
77
|
+
filters hide them all it offers **Clear filters**.
|
|
78
|
+
- `label` — what the grid is called to a screen reader.
|
|
79
|
+
- `className` — layout around it (width, margin). Never colour.
|
|
80
|
+
|
|
81
|
+
`ProductCard({ product, onAddToCart, onOpen, onFavorite, favorite })` and
|
|
82
|
+
`PromoTile({ item, large })` are exported for a row of your own.
|
|
83
|
+
|
|
84
|
+
## Example
|
|
85
|
+
|
|
86
|
+
```jsx
|
|
87
|
+
// surfaces/shop.jsx — server: load, hand over
|
|
88
|
+
import { loadRows } from "../lib/data";
|
|
89
|
+
import Shop from "../components/Shop";
|
|
90
|
+
|
|
91
|
+
export default async function ShopSurface() {
|
|
92
|
+
const { rows, error } = await loadRows({ source: "public.products", orderBy: "created_at desc" });
|
|
93
|
+
return <Shop products={rows} error={error} />;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```jsx
|
|
98
|
+
// components/Shop.jsx — client: the grid and the cart write
|
|
99
|
+
"use client";
|
|
100
|
+
import { useRouter } from "next/navigation";
|
|
101
|
+
import { insertRow } from "../lib/actions";
|
|
102
|
+
import { ProductGrid } from "./blocks/product-grid";
|
|
103
|
+
|
|
104
|
+
export default function Shop({ products, error }) {
|
|
105
|
+
const router = useRouter();
|
|
106
|
+
return (
|
|
107
|
+
<ProductGrid
|
|
108
|
+
products={products}
|
|
109
|
+
error={error}
|
|
110
|
+
onRetry={() => router.refresh()}
|
|
111
|
+
filters={[
|
|
112
|
+
{ key: "category", label: "Category", options: ["Shirts", "Sweaters", "Jackets"] },
|
|
113
|
+
{ key: "size", label: "Size", options: ["S", "M", "L", "XL"] },
|
|
114
|
+
]}
|
|
115
|
+
sort
|
|
116
|
+
onAddToCart={(line) =>
|
|
117
|
+
insertRow({ source: "public.cart_items", values: { product_id: line.id, line_key: line.key, quantity: 1 }, detail: line.name })
|
|
118
|
+
}
|
|
119
|
+
label="Shop"
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Collection tiles, and a lead picture beside four products:
|
|
126
|
+
|
|
127
|
+
```jsx
|
|
128
|
+
<ProductGrid
|
|
129
|
+
card="promo"
|
|
130
|
+
products={[
|
|
131
|
+
{ id: "new", kicker: "New", title: "The autumn edit", image: "/tiles/autumn.jpg", href: "/shop/new" },
|
|
132
|
+
{ id: "sale", kicker: "Sale", title: "Summer linen", image: "/tiles/linen.jpg", href: "/shop/sale" },
|
|
133
|
+
]}
|
|
134
|
+
label="Collections"
|
|
135
|
+
/>
|
|
136
|
+
|
|
137
|
+
<ProductGrid
|
|
138
|
+
products={skincare}
|
|
139
|
+
feature={{ kicker: "Skincare", title: "The morning routine", image: "/hero.jpg", href: "/routine", actionLabel: "Shop the routine" }}
|
|
140
|
+
onAddToCart={addToCart}
|
|
141
|
+
/>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## What it will not do
|
|
145
|
+
|
|
146
|
+
- Choose options on a card: that is the product page's job
|
|
147
|
+
(`product-detail`); the card sends the customer there.
|
|
148
|
+
- Page through a catalogue: pass a page of rows with `manual` and put the
|
|
149
|
+
kit's `Pagination` under it.
|
|
150
|
+
- Load a third-party player: a lead video is a plain `<video>` file, never
|
|
151
|
+
a YouTube embed or script.
|
|
152
|
+
- Colour itself: the tiles' words sit on the theme's background, so any
|
|
153
|
+
picture reads in any theme.
|
|
154
|
+
|
|
155
|
+
A catalogue it cannot be is your own component in `components/`, built
|
|
156
|
+
from the kit (and `ProductCard`) — not an edit to this block. Its files
|
|
157
|
+
are fixed: `npm run check` refuses a change, and `makersclaw add
|
|
158
|
+
product-grid` restores them.
|
|
159
|
+
|
|
160
|
+
## Credits
|
|
161
|
+
|
|
162
|
+
Ported from Creative Tim UI (https://github.com/creativetimofficial/ui), MIT — a rewrite on the Makersclaw kit, none of its code, copy or pictures.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "product-grid",
|
|
3
|
+
"title": "Product grid",
|
|
4
|
+
"description": "Products as cards in a grid: picture, badge, favourite heart, brand, name, star rating, price with the old one struck through, and a quick add to cart through an async callback that may fail (\"Choose options\" when the product has sizes or colours). Facet filters as selects that also match a product's option values, a sort, a live count, a lead tile that takes a double cell (a picture or a muted looping video), and a promo card for collection tiles. Loading, error, empty and no-matches states; two columns on a phone.",
|
|
5
|
+
"useWhen": "A shop's catalogue, a collection page, related products under a product page, a row of promotions ('New', 'Sale'). Not for records to scan and act on in columns (data-table), one product's page (product-detail), or the cart (cart).",
|
|
6
|
+
"tags": ["products", "shop", "store", "ecommerce", "commerce", "catalogue", "catalog", "grid", "cards", "filter", "facets", "sort", "add to cart", "favourite", "collection", "promo", "listing", "plp"],
|
|
7
|
+
"exports": ["ProductGrid", "ProductCard", "PromoTile", "productMatches"],
|
|
8
|
+
"files": ["index.js", "product-grid.jsx", "product-card.jsx"],
|
|
9
|
+
"requires": ["product-detail"]
|
|
10
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// The product grid with its data in memory — the gallery's and the smoke
|
|
4
|
+
// test's surface. Not installed into apps: `makersclaw add product-grid`
|
|
5
|
+
// lays the block's files only. Each layout it was ported from is one
|
|
6
|
+
// choice in the switcher.
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { Field, Select, ToggleGroup } from "../components/ui";
|
|
9
|
+
import { ProductGrid } from "../components/blocks/product-grid";
|
|
10
|
+
|
|
11
|
+
const pic = (seed, w = 800, h = 800) => `https://picsum.photos/seed/${seed}/${w}/${h}`;
|
|
12
|
+
|
|
13
|
+
const PRODUCTS = [
|
|
14
|
+
{
|
|
15
|
+
id: "cardigan",
|
|
16
|
+
brand: "Northfold",
|
|
17
|
+
name: "Cable-knit merino cardigan",
|
|
18
|
+
category: "sweaters",
|
|
19
|
+
material: "wool",
|
|
20
|
+
price: 240,
|
|
21
|
+
rating: 4.6,
|
|
22
|
+
reviews: 58,
|
|
23
|
+
badge: "Exclusive",
|
|
24
|
+
image: pic("mc-grid-cardigan"),
|
|
25
|
+
options: [{ key: "size", values: ["S", "M", "L"] }],
|
|
26
|
+
createdAt: "2026-08-02",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "oxford",
|
|
30
|
+
brand: "Harbor & Pine",
|
|
31
|
+
name: "Brushed cotton oxford shirt",
|
|
32
|
+
category: "shirts",
|
|
33
|
+
material: "cotton",
|
|
34
|
+
price: 72,
|
|
35
|
+
rating: 4.2,
|
|
36
|
+
reviews: 131,
|
|
37
|
+
image: pic("mc-grid-oxford"),
|
|
38
|
+
createdAt: "2026-06-11",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "trousers",
|
|
42
|
+
brand: "Northfold",
|
|
43
|
+
name: "Wool straight trousers",
|
|
44
|
+
category: "trousers",
|
|
45
|
+
material: "wool",
|
|
46
|
+
price: 165,
|
|
47
|
+
compareAt: 210,
|
|
48
|
+
rating: 4.8,
|
|
49
|
+
reviews: 44,
|
|
50
|
+
badge: "Sale",
|
|
51
|
+
image: pic("mc-grid-trousers"),
|
|
52
|
+
createdAt: "2026-05-20",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "crewneck",
|
|
56
|
+
brand: "Atelier Rue",
|
|
57
|
+
name: "Cashmere crewneck",
|
|
58
|
+
category: "sweaters",
|
|
59
|
+
material: "cashmere",
|
|
60
|
+
price: 310,
|
|
61
|
+
rating: 5,
|
|
62
|
+
reviews: 12,
|
|
63
|
+
badge: "New",
|
|
64
|
+
image: pic("mc-grid-crewneck"),
|
|
65
|
+
options: [{ key: "size", values: ["XS", "S", { value: "M", disabled: true }] }],
|
|
66
|
+
createdAt: "2026-09-10",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "overshirt",
|
|
70
|
+
brand: "Harbor & Pine",
|
|
71
|
+
name: "Linen overshirt",
|
|
72
|
+
category: "shirts",
|
|
73
|
+
material: "linen",
|
|
74
|
+
price: 98,
|
|
75
|
+
rating: 3.9,
|
|
76
|
+
reviews: 27,
|
|
77
|
+
image: pic("mc-grid-overshirt"),
|
|
78
|
+
createdAt: "2026-07-01",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "chore",
|
|
82
|
+
brand: "Kiln Street",
|
|
83
|
+
name: "Canvas chore jacket",
|
|
84
|
+
category: "jackets",
|
|
85
|
+
material: "cotton",
|
|
86
|
+
price: 185,
|
|
87
|
+
rating: 4.4,
|
|
88
|
+
reviews: 90,
|
|
89
|
+
available: false,
|
|
90
|
+
image: pic("mc-grid-chore"),
|
|
91
|
+
createdAt: "2026-04-18",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "silk-scarf",
|
|
95
|
+
brand: "Atelier Rue",
|
|
96
|
+
name: "Printed silk scarf",
|
|
97
|
+
category: "accessories",
|
|
98
|
+
material: "silk",
|
|
99
|
+
price: 60,
|
|
100
|
+
rating: 4.7,
|
|
101
|
+
reviews: 203,
|
|
102
|
+
image: pic("mc-grid-scarf"),
|
|
103
|
+
createdAt: "2026-08-28",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: "field-jacket",
|
|
107
|
+
brand: "Northfold",
|
|
108
|
+
name: "Waxed field jacket",
|
|
109
|
+
category: "jackets",
|
|
110
|
+
material: "cotton",
|
|
111
|
+
price: 280,
|
|
112
|
+
rating: 4.5,
|
|
113
|
+
reviews: 66,
|
|
114
|
+
image: pic("mc-grid-field"),
|
|
115
|
+
options: [{ key: "size", values: ["M", "L", "XL"] }],
|
|
116
|
+
createdAt: "2026-03-30",
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const FILTERS = [
|
|
121
|
+
{ key: "category", label: "Category", all: "All categories", options: [{ value: "shirts", label: "Shirts" }, { value: "sweaters", label: "Sweaters" }, { value: "trousers", label: "Trousers" }, { value: "jackets", label: "Jackets" }, { value: "accessories", label: "Accessories" }] },
|
|
122
|
+
{ key: "size", label: "Size", all: "All sizes", options: ["XS", "S", "M", "L", "XL"] },
|
|
123
|
+
{ key: "material", label: "Material", all: "All materials", options: [{ value: "cotton", label: "Cotton" }, { value: "wool", label: "Wool" }, { value: "cashmere", label: "Cashmere" }, { value: "linen", label: "Linen" }, { value: "silk", label: "Silk" }] },
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
const COLLECTIONS = [
|
|
127
|
+
{ id: "new", kicker: "New", title: "The autumn edit", image: pic("mc-tile-autumn", 800, 1000), href: "#new", actionLabel: "See what's new" },
|
|
128
|
+
{ id: "sale", kicker: "Sale", title: "Last of the summer linen", image: pic("mc-tile-linen", 800, 1000), href: "#sale", actionLabel: "Shop the sale" },
|
|
129
|
+
{ id: "half", kicker: "Half price", title: "Knitwear, one week only", image: pic("mc-tile-knit", 800, 1000), href: "#knit", actionLabel: "Shop knitwear" },
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
const SKINCARE = [
|
|
133
|
+
{ id: "toner", name: "Balancing toner", price: 32, rating: 4.4, reviews: 212, image: pic("mc-skin-toner") },
|
|
134
|
+
{ id: "serum", name: "Hydrating serum", price: 45, rating: 4.8, reviews: 540, badge: "Best seller", image: pic("mc-skin-serum") },
|
|
135
|
+
{ id: "cream", name: "Daily moisturiser", price: 38, rating: 4.5, reviews: 318, image: pic("mc-skin-cream") },
|
|
136
|
+
{ id: "balm", name: "Overnight lip balm", price: 16, compareAt: 20, rating: 4.1, reviews: 97, image: pic("mc-skin-balm") },
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
const HEADPHONES = [
|
|
140
|
+
{ id: "hp-1", brand: "Loop Audio", name: "Over-ear headphones, noise cancelling", price: 299, rating: 4, reviews: 128, badge: "New", image: pic("mc-audio-1") },
|
|
141
|
+
{ id: "hp-2", brand: "Loop Audio", name: "Wireless earbuds", price: 149, rating: 4.3, reviews: 402, image: pic("mc-audio-2") },
|
|
142
|
+
{ id: "hp-3", brand: "Loop Audio", name: "Bookshelf speaker pair", price: 420, compareAt: 499, rating: 4.7, reviews: 61, image: pic("mc-audio-3") },
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
const VARIANTS = [
|
|
146
|
+
{ value: "filters", label: "Filters, sort and count" },
|
|
147
|
+
{ value: "tiles", label: "Collection tiles" },
|
|
148
|
+
{ value: "promo", label: "Promotion beside products" },
|
|
149
|
+
{ value: "spotlight", label: "Video spotlight" },
|
|
150
|
+
{ value: "cards", label: "Product cards" },
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
154
|
+
|
|
155
|
+
export default function ProductGridDemo() {
|
|
156
|
+
const [variant, setVariant] = useState("filters");
|
|
157
|
+
const [state, setState] = useState("ready");
|
|
158
|
+
const [favorites, setFavorites] = useState(["oxford"]);
|
|
159
|
+
const [cart, setCart] = useState([]);
|
|
160
|
+
const failing = state === "fails";
|
|
161
|
+
|
|
162
|
+
async function addToCart(line) {
|
|
163
|
+
await wait(600);
|
|
164
|
+
if (failing) return { ok: false, error: "The cart did not answer." };
|
|
165
|
+
setCart((all) => {
|
|
166
|
+
const hit = all.find((l) => l.key === line.key);
|
|
167
|
+
return hit ? all.map((l) => (l.key === line.key ? { ...l, quantity: l.quantity + 1 } : l)) : [...all, line];
|
|
168
|
+
});
|
|
169
|
+
return { ok: true };
|
|
170
|
+
}
|
|
171
|
+
async function favorite(product, next) {
|
|
172
|
+
await wait(300);
|
|
173
|
+
if (failing) return { ok: false, error: "Favourites are not saving." };
|
|
174
|
+
setFavorites((all) => (next ? [...all, product.id] : all.filter((id) => id !== product.id)));
|
|
175
|
+
return { ok: true };
|
|
176
|
+
}
|
|
177
|
+
const open = () => {};
|
|
178
|
+
|
|
179
|
+
const common = {
|
|
180
|
+
loading: state === "loading",
|
|
181
|
+
error: state === "error" ? "The catalogue did not answer." : undefined,
|
|
182
|
+
onRetry: () => setState("ready"),
|
|
183
|
+
onAddToCart: addToCart,
|
|
184
|
+
onFavorite: favorite,
|
|
185
|
+
favorites,
|
|
186
|
+
onOpen: open,
|
|
187
|
+
};
|
|
188
|
+
const pick = (list) => (state === "empty" ? [] : list);
|
|
189
|
+
const count = cart.reduce((n, l) => n + l.quantity, 0);
|
|
190
|
+
|
|
191
|
+
let grid;
|
|
192
|
+
if (variant === "tiles") {
|
|
193
|
+
grid = <ProductGrid key="tiles" card="promo" products={pick(COLLECTIONS)} {...common} label="Collections" emptyTitle="No collections yet" />;
|
|
194
|
+
} else if (variant === "promo") {
|
|
195
|
+
grid = (
|
|
196
|
+
<ProductGrid
|
|
197
|
+
key="promo"
|
|
198
|
+
products={pick(SKINCARE)}
|
|
199
|
+
columns={4}
|
|
200
|
+
feature={{ kicker: "Skincare", title: "Glow, from plants up", body: "Four steps, morning and night.", image: pic("mc-skin-hero", 1200, 1200), href: "#skincare", actionLabel: "Shop the routine" }}
|
|
201
|
+
{...common}
|
|
202
|
+
label="Skincare"
|
|
203
|
+
/>
|
|
204
|
+
);
|
|
205
|
+
} else if (variant === "spotlight") {
|
|
206
|
+
grid = (
|
|
207
|
+
<ProductGrid
|
|
208
|
+
key="spotlight"
|
|
209
|
+
products={pick(HEADPHONES)}
|
|
210
|
+
columns={3}
|
|
211
|
+
feature={{
|
|
212
|
+
kicker: "In the studio",
|
|
213
|
+
title: "Sound you can work in",
|
|
214
|
+
video: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
|
|
215
|
+
poster: pic("mc-audio-hero", 1200, 900),
|
|
216
|
+
href: "#audio",
|
|
217
|
+
actionLabel: "See all audio",
|
|
218
|
+
}}
|
|
219
|
+
{...common}
|
|
220
|
+
label="Audio"
|
|
221
|
+
/>
|
|
222
|
+
);
|
|
223
|
+
} else if (variant === "cards") {
|
|
224
|
+
grid = <ProductGrid key="cards" products={pick(HEADPHONES)} columns={3} {...common} label="Headphones" />;
|
|
225
|
+
} else {
|
|
226
|
+
grid = <ProductGrid key="filters" products={pick(PRODUCTS)} filters={FILTERS} sort={["featured", "price-asc", "price-desc", "rating", "newest"]} {...common} label="Menswear" />;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<div className="grid gap-6">
|
|
231
|
+
<div className="flex flex-wrap items-end gap-3">
|
|
232
|
+
<Field id="pg-variant" label="Layout" className="w-full sm:w-64">
|
|
233
|
+
<Select id="pg-variant" value={variant} onChange={(e) => setVariant(e.target.value)} options={VARIANTS} />
|
|
234
|
+
</Field>
|
|
235
|
+
<ToggleGroup
|
|
236
|
+
size="sm"
|
|
237
|
+
aria-label="Demo state"
|
|
238
|
+
value={state}
|
|
239
|
+
onChange={setState}
|
|
240
|
+
items={[
|
|
241
|
+
{ value: "ready", label: "Ready" },
|
|
242
|
+
{ value: "fails", label: "Fails" },
|
|
243
|
+
{ value: "loading", label: "Loading" },
|
|
244
|
+
{ value: "error", label: "Error" },
|
|
245
|
+
{ value: "empty", label: "Empty" },
|
|
246
|
+
]}
|
|
247
|
+
/>
|
|
248
|
+
<p data-nums className="text-sm text-muted-foreground sm:ml-auto">
|
|
249
|
+
Cart: {count} {count === 1 ? "item" : "items"}
|
|
250
|
+
</p>
|
|
251
|
+
</div>
|
|
252
|
+
{grid}
|
|
253
|
+
</div>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The Product grid block — `makersclaw add product-grid`. Fixed: compose
|
|
2
|
+
// it through its props (README.md beside this file); a catalogue it cannot
|
|
3
|
+
// be is your own component in components/.
|
|
4
|
+
export { ProductGrid, productMatches } from "./product-grid";
|
|
5
|
+
export { ProductCard, PromoTile } from "./product-card";
|