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,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// SearchDialog over an assistant's history — the gallery's and the smoke
|
|
4
|
+
// test's surface. Not installed into apps: `makersclaw add search-dialog`
|
|
5
|
+
// lays index.js and search-dialog.jsx only. Press ⌘K (Ctrl+K) anywhere on
|
|
6
|
+
// the page, or the button. "Server search" answers through onSearch after
|
|
7
|
+
// a delay; turn on "Fail the server" to see the error.
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { Button, Field, Kbd, Select, Switch } from "../components/ui";
|
|
10
|
+
import { SearchDialog, SearchPanel } from "../components/blocks/search-dialog";
|
|
11
|
+
|
|
12
|
+
const LAST_OPENED = [
|
|
13
|
+
{ id: "c1", kind: "chat", title: "Harbour St. lease renewal", snippet: "Counter at 4% over three years, and ask for the fit-out credit back.", date: "Today" },
|
|
14
|
+
{ id: "c2", kind: "chat", title: "Supplier emails for the spring range", snippet: "Two follow-ups a week apart, then call the account manager.", date: "Today" },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const RECENT = [
|
|
18
|
+
{ id: "c3", kind: "chat", title: "Weekly cash position", snippet: "Runway is 14 months at the current burn; payroll moves to the 25th.", date: "Yesterday" },
|
|
19
|
+
{ id: "c4", kind: "chat", title: "Why did March refunds spike", snippet: "Most refunds trace back to the courier switch in week two.", date: "Yesterday" },
|
|
20
|
+
{ id: "c5", kind: "chat", title: "Draft the hiring post for a bookkeeper", snippet: "Part-time, remote, Xero experience; lead with the four-day week.", date: "Sep 18" },
|
|
21
|
+
{ id: "c6", kind: "chat", title: "Compare three courier quotes", snippet: "Parcelwise is cheapest under 2 kg; Northline wins on next-day.", date: "Sep 15" },
|
|
22
|
+
{ id: "c7", kind: "chat", title: "Board update outline", snippet: "Revenue, cash, the two hires, and the one risk: the lease.", date: "Sep 11" },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const IMAGES = [
|
|
26
|
+
{ id: "i1", kind: "image", title: "spring-range-lookbook.jpg", snippet: "Image", date: "Sep 19" },
|
|
27
|
+
{ id: "i2", kind: "image", title: "shopfront-new-signage.png", snippet: "Image", date: "Sep 12" },
|
|
28
|
+
{ id: "i3", kind: "image", title: "packaging-mockup-v3.png", snippet: "Image", date: "Sep 3" },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const DOCS = [
|
|
32
|
+
{ id: "d1", kind: "document", title: "Harbour St. lease — draft 2.pdf", snippet: "PDF", date: "Sep 20" },
|
|
33
|
+
{ id: "d2", kind: "document", title: "Q3 cash flow.xlsx", snippet: "Spreadsheet", date: "Sep 17", icon: "chart" },
|
|
34
|
+
{ id: "d3", kind: "document", title: "Courier contract — Parcelwise.docx", snippet: "Document", date: "Sep 9" },
|
|
35
|
+
{ id: "d4", kind: "document", title: "Brand assets.zip", snippet: "Archive", date: "Aug 30", icon: "archive" },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const PROJECTS = [
|
|
39
|
+
{ id: "p1", kind: "project", title: "Spring range launch", snippet: "Project · 12 chats", date: "Sep 21" },
|
|
40
|
+
{ id: "p2", kind: "project", title: "Second shop — Harbour St.", snippet: "Project · 7 chats", date: "Sep 20" },
|
|
41
|
+
{ id: "p3", kind: "project", title: "Courier switch", snippet: "Project · 4 chats", date: "Aug 28" },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const ALL = [...LAST_OPENED, ...RECENT, ...IMAGES, ...DOCS, ...PROJECTS];
|
|
45
|
+
const SECTIONS = [
|
|
46
|
+
{ heading: "Last opened", results: LAST_OPENED },
|
|
47
|
+
{ heading: "Recent chats", results: RECENT },
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const VARIANTS = [
|
|
51
|
+
{ key: "local", label: "Your list, searched in the browser" },
|
|
52
|
+
{ key: "server", label: "Server search (onSearch)" },
|
|
53
|
+
{ key: "plain", label: "No sections, one kind" },
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const wait = (ms, signal) =>
|
|
57
|
+
new Promise((resolve, reject) => {
|
|
58
|
+
const t = setTimeout(resolve, ms);
|
|
59
|
+
signal?.addEventListener("abort", () => {
|
|
60
|
+
clearTimeout(t);
|
|
61
|
+
reject(new Error("aborted"));
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export default function SearchDialogDemo() {
|
|
66
|
+
const [key, setKey] = useState("local");
|
|
67
|
+
const [open, setOpen] = useState(false);
|
|
68
|
+
const [fail, setFail] = useState(false);
|
|
69
|
+
const [picked, setPicked] = useState(null);
|
|
70
|
+
|
|
71
|
+
async function onSearch(query, { signal }) {
|
|
72
|
+
await wait(500, signal);
|
|
73
|
+
if (fail) throw new Error("The search service did not answer.");
|
|
74
|
+
const q = query.toLowerCase();
|
|
75
|
+
return ALL.filter((r) => `${r.title} ${r.snippet}`.toLowerCase().includes(q));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const props =
|
|
79
|
+
key === "server"
|
|
80
|
+
? { sections: SECTIONS, onSearch, placeholder: "Search chats, images, documents and projects…" }
|
|
81
|
+
: key === "plain"
|
|
82
|
+
? { results: PROJECTS, placeholder: "Search projects…", hint: "Type a project's name." }
|
|
83
|
+
: { results: ALL, sections: SECTIONS, placeholder: "Search chats, images, documents and projects…" };
|
|
84
|
+
|
|
85
|
+
const onSelect = (r) => setPicked(`${r.kind} · ${r.title}`);
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className="grid gap-6">
|
|
89
|
+
<div className="flex flex-wrap items-end gap-x-6 gap-y-2">
|
|
90
|
+
<Field id="search-variant" label="Variant" className="w-full sm:w-80">
|
|
91
|
+
<Select id="search-variant" value={key} onChange={(e) => setKey(e.target.value)} options={VARIANTS.map((v) => ({ value: v.key, label: v.label }))} />
|
|
92
|
+
</Field>
|
|
93
|
+
{key === "server" ? <Switch id="search-fail" label="Fail the server" checked={fail} onChange={(e) => setFail(e.target.checked)} /> : null}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div>
|
|
97
|
+
<Button variant="secondary" icon="search" onClick={() => setOpen(true)} aria-keyshortcuts="Meta+K Control+K" align="start" className="w-full sm:w-72">
|
|
98
|
+
<span className="flex-1 text-left text-muted-foreground">Search…</span>
|
|
99
|
+
<span className="hidden md:inline-flex" aria-hidden="true">
|
|
100
|
+
<Kbd>⌘</Kbd>
|
|
101
|
+
<Kbd>K</Kbd>
|
|
102
|
+
</span>
|
|
103
|
+
</Button>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<SearchDialog key={key} open={open} onOpenChange={setOpen} hotkey="k" label="Global search" onSelect={onSelect} {...props} />
|
|
107
|
+
|
|
108
|
+
{/* The same box inline, so the page shows it without opening the dialog. */}
|
|
109
|
+
<SearchPanel key={`inline-${key}`} label="Search, inline" onSelect={onSelect} className="max-w-xl" {...props} />
|
|
110
|
+
|
|
111
|
+
<p className="min-h-5 text-xs text-muted-foreground" aria-live="polite">
|
|
112
|
+
{picked ? `Opened — ${picked}` : "Pick a result to see what onSelect receives."}
|
|
113
|
+
</p>
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { isValidElement, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { Command, IconButton, Image, Sheet, ToggleGroup, commandScore, cx } from "../../ui";
|
|
5
|
+
|
|
6
|
+
// SearchDialog — one ⌘K box over every kind of record: chats, documents,
|
|
7
|
+
// images, projects, people. Before anything is typed it shows your
|
|
8
|
+
// sections ("Last opened", "Recent"); while typing, the matches with the
|
|
9
|
+
// typed text marked, and kind chips (All, Chats, Images…) to narrow them.
|
|
10
|
+
// Built on the kit's Command (the list, keys and ARIA) inside the kit's
|
|
11
|
+
// Sheet. SearchPanel is the same box inline. See README.md beside this file.
|
|
12
|
+
|
|
13
|
+
const KINDS = {
|
|
14
|
+
chat: { label: "Chats", icon: "message-circle" },
|
|
15
|
+
document: { label: "Documents", icon: "file" },
|
|
16
|
+
image: { label: "Images", icon: "image" },
|
|
17
|
+
project: { label: "Projects", icon: "folder" },
|
|
18
|
+
person: { label: "People", icon: "user" },
|
|
19
|
+
company: { label: "Companies", icon: "building" },
|
|
20
|
+
task: { label: "Tasks", icon: "circle-check" },
|
|
21
|
+
page: { label: "Pages", icon: "file" },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const cap = (s) => String(s).charAt(0).toUpperCase() + String(s).slice(1);
|
|
25
|
+
|
|
26
|
+
function kindOf(kinds, value) {
|
|
27
|
+
return kinds.find((k) => k.value === value) ?? { value, label: KINDS[value]?.label ?? cap(value), icon: KINDS[value]?.icon ?? "file" };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The typed text marked inside `text`, once, ignoring case. */
|
|
31
|
+
function Marked({ text, needle }) {
|
|
32
|
+
const s = String(text ?? "");
|
|
33
|
+
const at = needle ? s.toLowerCase().indexOf(needle) : -1;
|
|
34
|
+
if (at < 0) return s;
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
{s.slice(0, at)}
|
|
38
|
+
<mark className="rounded-sm bg-transparent font-semibold text-foreground underline decoration-primary decoration-2 underline-offset-2">{s.slice(at, at + needle.length)}</mark>
|
|
39
|
+
{s.slice(at + needle.length)}
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function Thumb({ thumb, title }) {
|
|
45
|
+
if (isValidElement(thumb)) return <span className="flex size-8 shrink-0 overflow-hidden rounded-sm">{thumb}</span>;
|
|
46
|
+
return <Image src={thumb || undefined} alt="" ratio="square" rounded="sm" className="size-8 shrink-0" title={title} />;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The best of a result's fields against the query, 0 when none match.
|
|
50
|
+
function score(r, q) {
|
|
51
|
+
return Math.max(commandScore(r.title, q), r.snippet ? commandScore(r.snippet, q) * 0.7 : 0, ...(r.keywords ?? []).map((k) => commandScore(k, q) * 0.9));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** A server search: debounced, the older query aborted, failures kept. */
|
|
55
|
+
function useServerSearch(onSearch, query) {
|
|
56
|
+
const fn = useRef(onSearch);
|
|
57
|
+
fn.current = onSearch;
|
|
58
|
+
const on = Boolean(onSearch) && Boolean(query);
|
|
59
|
+
const [state, setState] = useState({ items: null, loading: false, error: null, query: "" });
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!on) return;
|
|
62
|
+
const ctl = new AbortController();
|
|
63
|
+
setState((s) => ({ ...s, loading: true, error: null }));
|
|
64
|
+
const timer = setTimeout(async () => {
|
|
65
|
+
try {
|
|
66
|
+
const items = await fn.current(query, { signal: ctl.signal });
|
|
67
|
+
if (!ctl.signal.aborted) setState({ items: items ?? [], loading: false, error: null, query });
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (!ctl.signal.aborted) setState((s) => ({ ...s, loading: false, error }));
|
|
70
|
+
}
|
|
71
|
+
}, 200);
|
|
72
|
+
return () => {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
ctl.abort();
|
|
75
|
+
};
|
|
76
|
+
}, [on, query]);
|
|
77
|
+
return state;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function SearchPanel({
|
|
81
|
+
results = [],
|
|
82
|
+
sections,
|
|
83
|
+
kinds: kindsProp,
|
|
84
|
+
onSelect,
|
|
85
|
+
onSearch,
|
|
86
|
+
loading = false,
|
|
87
|
+
placeholder = "Search…",
|
|
88
|
+
label = "Search",
|
|
89
|
+
hint = "Type to search.",
|
|
90
|
+
showDate = true,
|
|
91
|
+
onClose,
|
|
92
|
+
autoFocus = false,
|
|
93
|
+
bare = false,
|
|
94
|
+
className,
|
|
95
|
+
}) {
|
|
96
|
+
const [query, setQuery] = useState("");
|
|
97
|
+
const [kind, setKind] = useState("all");
|
|
98
|
+
const needle = query.trim().toLowerCase();
|
|
99
|
+
const server = useServerSearch(onSearch, needle);
|
|
100
|
+
|
|
101
|
+
// The chips: the kinds given, or every kind the data holds, in order.
|
|
102
|
+
const kinds = useMemo(() => {
|
|
103
|
+
if (kindsProp) return kindsProp;
|
|
104
|
+
const seen = [];
|
|
105
|
+
for (const r of [...results, ...(sections ?? []).flatMap((s) => s.results ?? [])]) if (r?.kind && !seen.includes(r.kind)) seen.push(r.kind);
|
|
106
|
+
return seen.map((v) => kindOf([], v));
|
|
107
|
+
}, [kindsProp, results, sections]);
|
|
108
|
+
|
|
109
|
+
const pass = (r) => kind === "all" || r.kind === kind;
|
|
110
|
+
|
|
111
|
+
// `at` keeps values unique when one result sits in two sections.
|
|
112
|
+
const toItem = (r, group, at = "") => {
|
|
113
|
+
const k = kindOf(kinds, r.kind);
|
|
114
|
+
const meta = [r.snippet, showDate && needle ? r.date : null].filter(Boolean);
|
|
115
|
+
return {
|
|
116
|
+
value: `${at}${r.id}`,
|
|
117
|
+
label: <Marked text={r.title} needle={needle} />,
|
|
118
|
+
description: meta.length ? (
|
|
119
|
+
<>
|
|
120
|
+
{r.snippet ? <Marked text={r.snippet} needle={needle} /> : null}
|
|
121
|
+
{meta.length > 1 ? " · " : null}
|
|
122
|
+
{showDate && needle && r.date ? r.date : null}
|
|
123
|
+
</>
|
|
124
|
+
) : undefined,
|
|
125
|
+
icon: r.kind === "image" || r.thumb ? <Thumb thumb={r.thumb} title={r.title} /> : r.icon ?? k.icon,
|
|
126
|
+
group,
|
|
127
|
+
result: r,
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
let items;
|
|
132
|
+
if (!needle) {
|
|
133
|
+
items = (sections ?? []).flatMap((s, n) => (s.results ?? []).filter(pass).map((r) => toItem(r, s.heading, `${n}:`)));
|
|
134
|
+
} else if (onSearch) {
|
|
135
|
+
items = (server.items ?? []).filter(pass).map((r) => toItem(r));
|
|
136
|
+
} else {
|
|
137
|
+
items = results
|
|
138
|
+
.map((r, i) => ({ r, i, s: pass(r) ? score(r, needle) : 0 }))
|
|
139
|
+
.filter((x) => x.s > 0)
|
|
140
|
+
.sort((a, b) => b.s - a.s || a.i - b.i)
|
|
141
|
+
.map((x) => toItem(x.r));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const busy = loading || (Boolean(onSearch) && Boolean(needle) && (server.loading || server.query !== needle) && !server.error);
|
|
145
|
+
const kindLabel = kind === "all" ? "" : ` in ${kindOf(kinds, kind).label.toLowerCase()}`;
|
|
146
|
+
const empty = server.error && needle
|
|
147
|
+
? "Search failed. Check your connection and try again."
|
|
148
|
+
: needle
|
|
149
|
+
? `No results for “${query.trim()}”${kindLabel}.`
|
|
150
|
+
: kind !== "all" && (sections ?? []).length
|
|
151
|
+
? `Nothing recent${kindLabel}. Type to search.`
|
|
152
|
+
: hint;
|
|
153
|
+
|
|
154
|
+
const chips = kinds.length > 1 ? [{ value: "all", label: "All" }, ...kinds.map((k) => ({ value: k.value, label: k.label }))] : null;
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<div className={cx("flex min-w-0 flex-col overflow-hidden bg-popover text-popover-foreground", !bare && "rounded-lg border border-border", className)}>
|
|
158
|
+
<Command
|
|
159
|
+
bare
|
|
160
|
+
label={label}
|
|
161
|
+
placeholder={placeholder}
|
|
162
|
+
items={items}
|
|
163
|
+
filter={false}
|
|
164
|
+
query={query}
|
|
165
|
+
onQueryChange={setQuery}
|
|
166
|
+
loading={busy}
|
|
167
|
+
empty={empty}
|
|
168
|
+
autoFocus={autoFocus}
|
|
169
|
+
listClassName="max-h-[min(24rem,55dvh)]"
|
|
170
|
+
onSelect={(item) => onSelect?.(item.result)}
|
|
171
|
+
/>
|
|
172
|
+
{chips || onClose ? (
|
|
173
|
+
<div className="flex items-center gap-2 border-t border-border px-2 py-1.5">
|
|
174
|
+
{chips ? (
|
|
175
|
+
<div className="min-w-0 flex-1 overflow-x-auto">
|
|
176
|
+
<ToggleGroup size="sm" aria-label="Show only" items={chips} value={kind} onChange={setKind} className="w-max" />
|
|
177
|
+
</div>
|
|
178
|
+
) : (
|
|
179
|
+
<span className="flex-1" />
|
|
180
|
+
)}
|
|
181
|
+
{onClose ? <IconButton icon="x" label="Close search" size="sm" onClick={onClose} /> : null}
|
|
182
|
+
</div>
|
|
183
|
+
) : null}
|
|
184
|
+
</div>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** SearchPanel in the kit's Sheet: a dialog near the top of a wide window,
|
|
189
|
+
* a bottom sheet on a phone. `open` + `onOpenChange`, or uncontrolled
|
|
190
|
+
* with `defaultOpen`; `hotkey="k"` binds ⌘K / Ctrl+K to open and close
|
|
191
|
+
* it. Choosing a result closes it. */
|
|
192
|
+
export function SearchDialog({ open, defaultOpen = false, onOpenChange, hotkey, label = "Search", onSelect, className, ...panel }) {
|
|
193
|
+
const controlled = open !== undefined;
|
|
194
|
+
const [own, setOwn] = useState(defaultOpen);
|
|
195
|
+
const isOpen = controlled ? open : own;
|
|
196
|
+
const openRef = useRef(isOpen);
|
|
197
|
+
openRef.current = isOpen;
|
|
198
|
+
const changeRef = useRef(null);
|
|
199
|
+
changeRef.current = (next) => {
|
|
200
|
+
if (next === openRef.current) return;
|
|
201
|
+
openRef.current = next;
|
|
202
|
+
if (!controlled) setOwn(next);
|
|
203
|
+
onOpenChange?.(next);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
if (!hotkey) return;
|
|
208
|
+
function onKey(e) {
|
|
209
|
+
if (e.key?.toLowerCase() !== String(hotkey).toLowerCase() || !(e.metaKey || e.ctrlKey) || e.altKey || e.shiftKey) return;
|
|
210
|
+
e.preventDefault();
|
|
211
|
+
changeRef.current(!openRef.current);
|
|
212
|
+
}
|
|
213
|
+
window.addEventListener("keydown", onKey);
|
|
214
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
215
|
+
}, [hotkey]);
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<Sheet bare label={label} open={isOpen} onClose={() => changeRef.current(false)} side="center" className={cx("sm:mt-[12dvh] sm:max-w-xl", className)}>
|
|
219
|
+
{/* Mounted only while open, so each opening starts empty on "All". */}
|
|
220
|
+
{isOpen ? (
|
|
221
|
+
<SearchPanel
|
|
222
|
+
bare
|
|
223
|
+
autoFocus
|
|
224
|
+
label={label}
|
|
225
|
+
onClose={() => changeRef.current(false)}
|
|
226
|
+
onSelect={(r) => {
|
|
227
|
+
changeRef.current(false);
|
|
228
|
+
onSelect?.(r);
|
|
229
|
+
}}
|
|
230
|
+
{...panel}
|
|
231
|
+
/>
|
|
232
|
+
) : null}
|
|
233
|
+
</Sheet>
|
|
234
|
+
);
|
|
235
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# SettingsList
|
|
2
|
+
|
|
3
|
+
A card of settings, one row each: an icon, a label, a description, a few
|
|
4
|
+
meta lines, a badge, and the row's control. Every change saves on its own —
|
|
5
|
+
no Save button. A flipped switch or a new choice shows at once, a spinner
|
|
6
|
+
sits beside it while it saves, and when the save fails the old value comes
|
|
7
|
+
back with the reason and Try again, on that row only. `variant="matrix"`
|
|
8
|
+
is the notification grid: events down the side, channels across the top.
|
|
9
|
+
|
|
10
|
+
```jsx
|
|
11
|
+
import { SettingsList } from "../components/blocks/settings-list"; // a Makersclaw app ("./blocks/settings-list" from components/)
|
|
12
|
+
import { SettingsList } from "@/components/makersclaw/blocks/settings-list"; // a shadcn project
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
It is a client component: render it from a `"use client"` component, and
|
|
16
|
+
load the settings in the server surface (README §4).
|
|
17
|
+
|
|
18
|
+
## The data
|
|
19
|
+
|
|
20
|
+
A row:
|
|
21
|
+
|
|
22
|
+
- `key` — unique in the list (required).
|
|
23
|
+
- `label` — what the setting is (required).
|
|
24
|
+
- `description` — a muted line under it.
|
|
25
|
+
- `icon` — a kit `Icon` name in a muted square; or `media`, any node (an
|
|
26
|
+
Avatar, a logo).
|
|
27
|
+
- `badge` — `"Current"` or `{ label, tone?, hue?, icon? }` beside the label.
|
|
28
|
+
`tone` for a status ("Recommended", success), `hue` 1–5 for a kind
|
|
29
|
+
("Development").
|
|
30
|
+
- `value` — a line saying what is set now ("+44 7700 900 461", "Not set
|
|
31
|
+
up"); `valueTone: "set"` draws it in full weight with a check.
|
|
32
|
+
- `meta` — small lines under it: strings, or `{ icon, text }` ("globe
|
|
33
|
+
Lisbon", "clock Active now").
|
|
34
|
+
- `group` — rows with the same group sit under one heading, in the order
|
|
35
|
+
the groups first appear.
|
|
36
|
+
- `control` — one of:
|
|
37
|
+
- `{ type: "switch", value: true }` — saves through `onChange(row, bool)`.
|
|
38
|
+
- `{ type: "select", value, options: [{ value, label }] }` — saves
|
|
39
|
+
through `onChange(row, value)`.
|
|
40
|
+
- `{ type: "button", label, icon?, variant?, tone?, confirm? }` — runs
|
|
41
|
+
`onAction(row, "button")` (or `key` if given).
|
|
42
|
+
- `{ type: "actions", items: [{ key, label, icon?, tone?, confirm? }],
|
|
43
|
+
menu? }` — up to two buttons, or a "⋯" menu for three or more (or
|
|
44
|
+
`menu: true`); runs `onAction(row, item.key)`.
|
|
45
|
+
- `{ type: "remove", label?, confirm? }` — an × button (sign a device out,
|
|
46
|
+
disconnect); runs `onAction(row, "remove")`.
|
|
47
|
+
- none — a row that only says something.
|
|
48
|
+
`confirm` asks first, with the kit Confirm: `{ title, body?,
|
|
49
|
+
confirmLabel?, tone?, consequences?, requireText?, acknowledge? }`.
|
|
50
|
+
- `details` — a node, or `(row) => node`, that opens under the row from a
|
|
51
|
+
chevron button (the connected account, a copyable code). `defaultOpen`
|
|
52
|
+
starts it open.
|
|
53
|
+
- `disabled` — the control is shown and cannot be used.
|
|
54
|
+
|
|
55
|
+
The matrix (`variant="matrix"`) rows are events:
|
|
56
|
+
|
|
57
|
+
- `key`, `label`, `description`, `group` — as above.
|
|
58
|
+
- `values` — `{ email: true, push: false, sms: null }`, one per channel
|
|
59
|
+
key. `null` (or missing) means the event is not sent on that channel: a
|
|
60
|
+
dash, not a switch.
|
|
61
|
+
- `locked` — channel keys that cannot be turned off (`["email"]` for a
|
|
62
|
+
security alert): the switch shows, disabled, with a lock.
|
|
63
|
+
|
|
64
|
+
## Props
|
|
65
|
+
|
|
66
|
+
- `rows` — the rows above. Keep them as the saved truth: when a save
|
|
67
|
+
succeeds, update the row (or let the server revalidate). Until the rows
|
|
68
|
+
change, the row shows the new value it saved.
|
|
69
|
+
- `onChange(row, value, channel?)` — save a switch or a select (in the
|
|
70
|
+
matrix, `channel` is the channel key). Return `{ ok: true }` or `{ ok:
|
|
71
|
+
false, error }`; a throw counts as failed. Without it, switches and
|
|
72
|
+
selects are shown and cannot be changed. In a Makersclaw app it is one
|
|
73
|
+
line over `saveSetting` (lib/actions.js):
|
|
74
|
+
`onChange={(row, value) => saveSetting({ source: "public.settings", key: row.key, value })}`.
|
|
75
|
+
- `onAction(row, actionKey)` — run a button, a menu item or a remove.
|
|
76
|
+
Return `{ ok }` like `onChange`. Remove the row from `rows` on success
|
|
77
|
+
when it is gone (a signed-out device).
|
|
78
|
+
- `variant` — `"list"` (default) or `"matrix"`.
|
|
79
|
+
- `channels` — the matrix's columns: `[{ key, label, icon? }]`.
|
|
80
|
+
- `title`, `description`, `icon` — the card's heading; `icon` in a muted
|
|
81
|
+
square before it.
|
|
82
|
+
- `badge` — a state beside the heading (`{ label: "On", tone: "success",
|
|
83
|
+
icon: "circle-check" }`).
|
|
84
|
+
- `actions` — nodes at the heading's end ("Add profile").
|
|
85
|
+
- `footer` — a node under the rows (a Notice with a tip).
|
|
86
|
+
- `loading` — skeleton rows.
|
|
87
|
+
- `error` — the settings could not be loaded: a Notice in place of the
|
|
88
|
+
rows; `onRetry` adds "Try again".
|
|
89
|
+
- `emptyTitle` (`"Nothing here yet"`) · `emptyBody` · `emptyAction` —
|
|
90
|
+
shown when `rows` is empty.
|
|
91
|
+
- `disabled` — every control shown and none usable.
|
|
92
|
+
- `failedText` — the reason shown when a save fails without an `error`.
|
|
93
|
+
- `className` — layout around it (width, margin). Never colour.
|
|
94
|
+
|
|
95
|
+
## Example
|
|
96
|
+
|
|
97
|
+
```jsx
|
|
98
|
+
// components/Preferences.jsx — client
|
|
99
|
+
"use client";
|
|
100
|
+
import { saveSetting } from "../lib/actions";
|
|
101
|
+
import { SettingsList } from "./blocks/settings-list";
|
|
102
|
+
|
|
103
|
+
export default function Preferences({ settings }) {
|
|
104
|
+
const rows = [
|
|
105
|
+
{ key: "digest", icon: "mail", label: "Weekly digest", description: "Every Monday at 8:00.", control: { type: "switch", value: settings.digest === true } },
|
|
106
|
+
{
|
|
107
|
+
key: "currency",
|
|
108
|
+
icon: "dollar",
|
|
109
|
+
label: "Currency",
|
|
110
|
+
control: { type: "select", value: settings.currency ?? "usd", options: [{ value: "usd", label: "US dollar" }, { value: "eur", label: "Euro" }] },
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
return (
|
|
114
|
+
<SettingsList
|
|
115
|
+
title="Preferences"
|
|
116
|
+
rows={rows}
|
|
117
|
+
onChange={(row, value) => saveSetting({ source: "public.settings", key: row.key, value })}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Notifications per channel:
|
|
124
|
+
|
|
125
|
+
```jsx
|
|
126
|
+
<SettingsList
|
|
127
|
+
variant="matrix"
|
|
128
|
+
title="Notifications"
|
|
129
|
+
channels={[{ key: "email", label: "Email", icon: "mail" }, { key: "push", label: "Push", icon: "smartphone" }]}
|
|
130
|
+
rows={[
|
|
131
|
+
{ key: "mentions", group: "Conversations", label: "Mentions", values: { email: true, push: true } },
|
|
132
|
+
{ key: "signin", group: "Security", label: "New sign-in", values: { email: true, push: false }, locked: ["email"] },
|
|
133
|
+
]}
|
|
134
|
+
onChange={(row, on, channel) => saveSetting({ mode: "json", source: "public.members", column: "notify", id: me.id, key: `${row.key}.${channel}`, value: on })}
|
|
135
|
+
/>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Signed-in devices, each with sign-out:
|
|
139
|
+
|
|
140
|
+
```jsx
|
|
141
|
+
<SettingsList
|
|
142
|
+
icon="shield-check"
|
|
143
|
+
title="Signed-in devices"
|
|
144
|
+
rows={sessions.map((s) => ({
|
|
145
|
+
key: s.id,
|
|
146
|
+
icon: s.kind === "phone" ? "smartphone" : "laptop",
|
|
147
|
+
label: s.device,
|
|
148
|
+
badge: s.current ? { label: "This device", tone: "info" } : null,
|
|
149
|
+
meta: [{ icon: "globe", text: s.place }, { icon: "clock", text: s.lastSeen }],
|
|
150
|
+
control: s.current ? null : { type: "remove", label: `Sign out ${s.device}`, confirm: { title: "Sign out this device?", confirmLabel: "Sign out" } },
|
|
151
|
+
}))}
|
|
152
|
+
onAction={(row) => deleteRow({ source: "public.sessions", id: row.key })}
|
|
153
|
+
/>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## What it will not do
|
|
157
|
+
|
|
158
|
+
- Save several settings with one button: that is `record-form`.
|
|
159
|
+
- Open a setup flow: a button's `onAction` is yours — open your `Sheet`
|
|
160
|
+
from it and return `{ ok: true }`.
|
|
161
|
+
- Scroll the matrix sideways on a phone: under 768px each event's switches
|
|
162
|
+
stack under it, named by channel.
|
|
163
|
+
|
|
164
|
+
A settings screen it cannot be is your own component in `components/`,
|
|
165
|
+
built from the kit — not an edit to this block. Its files are fixed: `npm
|
|
166
|
+
run check` refuses a change, and `makersclaw add settings-list` restores
|
|
167
|
+
them.
|
|
168
|
+
|
|
169
|
+
## Credits
|
|
170
|
+
|
|
171
|
+
Shapes from Creative Tim UI (https://github.com/creativetimofficial/ui, MIT); this is a rewrite on the Makersclaw kit.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "settings-list",
|
|
3
|
+
"title": "SettingsList",
|
|
4
|
+
"description": "A card of settings, one row each — icon, label, description, meta lines, a badge, and its control: a Switch, a Select, a Button, a remove button or a menu of actions, with optional details that open under the row. Every change saves on its own through an async callback; the row shows the new value at once, a spinner while it saves, and on failure the old value back with the reason and Try again. variant=\"matrix\" is the notification grid: events by group down the side, channels (email, push, SMS) across, a switch per cell, stacked on a phone.",
|
|
5
|
+
"useWhen": "An account or workspace settings screen where each setting applies the moment it is changed: preferences, two-step sign-in methods, signed-in devices, connected integrations, billing profiles, notification preferences per channel. Not for a form of fields saved together with one button (record-form).",
|
|
6
|
+
"tags": ["settings", "preferences", "toggle", "switch", "notifications", "channels", "matrix", "security", "sessions", "devices", "integrations", "two-factor", "billing", "account"],
|
|
7
|
+
"exports": ["SettingsList"],
|
|
8
|
+
"files": ["index.js", "settings-list.jsx", "settings-matrix.jsx", "row-state.jsx"],
|
|
9
|
+
"requires": []
|
|
10
|
+
}
|