makersclaw 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +41 -1
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +15 -8
- package/r/annotate.json +62 -0
- package/r/approval-request.json +52 -0
- package/r/audio-player.json +74 -0
- package/r/auth-form.json +55 -0
- package/r/board.json +55 -0
- package/r/calendar-view.json +105 -0
- package/r/cart.json +62 -0
- package/r/chart.json +83 -0
- package/r/chat.json +95 -0
- package/r/code-editor.json +94 -0
- package/r/comment-box.json +64 -0
- package/r/contact-section.json +53 -0
- package/r/core.json +341 -0
- package/r/csv-import.json +63 -0
- package/r/data-table.json +69 -0
- package/r/diagram.json +74 -0
- package/r/doc-editor.json +82 -0
- package/r/doc-page.json +61 -0
- package/r/email-render.json +73 -0
- package/r/faq.json +50 -0
- package/r/file-upload.json +54 -0
- package/r/flow-canvas.json +93 -0
- package/r/footer.json +52 -0
- package/r/gantt.json +70 -0
- package/r/job-panel.json +56 -0
- package/r/json-editor.json +66 -0
- package/r/map.json +89 -0
- package/r/menubar.json +52 -0
- package/r/mind-map.json +67 -0
- package/r/navigation-menu.json +52 -0
- package/r/order-detail.json +54 -0
- package/r/org-chart.json +66 -0
- package/r/page-builder.json +105 -0
- package/r/payment-methods.json +51 -0
- package/r/pdf-document.json +79 -0
- package/r/pdf-viewer.json +88 -0
- package/r/product-detail.json +76 -0
- package/r/product-grid.json +65 -0
- package/r/record-form.json +67 -0
- package/r/record-notes.json +55 -0
- package/r/registry.json +3612 -0
- package/r/search-dialog.json +51 -0
- package/r/settings-list.json +66 -0
- package/r/setup-checklist.json +51 -0
- package/r/share-dialog.json +52 -0
- package/r/sidebar.json +69 -0
- package/r/signature-pad.json +72 -0
- package/r/sketch-canvas.json +99 -0
- package/r/spreadsheet.json +90 -0
- package/r/stat-cards.json +66 -0
- package/r/task-list.json +63 -0
- package/r/task-model.json +98 -0
- package/r/testimonials.json +52 -0
- package/r/transaction-list.json +53 -0
- package/r/whiteboard.json +66 -0
- package/registry/blocks/annotate/README.md +179 -0
- package/registry/blocks/annotate/annotate-data.js +250 -0
- package/registry/blocks/annotate/annotate.jsx +646 -0
- package/registry/blocks/annotate/block.json +10 -0
- package/registry/blocks/annotate/demo.jsx +135 -0
- package/registry/blocks/annotate/index.js +15 -0
- package/registry/blocks/approval-request/README.md +116 -0
- package/registry/blocks/approval-request/approval-request.jsx +386 -0
- package/registry/blocks/approval-request/block.json +10 -0
- package/registry/blocks/approval-request/demo.jsx +127 -0
- package/registry/blocks/approval-request/index.js +4 -0
- package/registry/blocks/audio-player/README.md +167 -0
- package/registry/blocks/audio-player/audio-player.jsx +623 -0
- package/registry/blocks/audio-player/block.json +14 -0
- package/registry/blocks/audio-player/colors.js +109 -0
- package/registry/blocks/audio-player/demo.jsx +209 -0
- package/registry/blocks/audio-player/index.js +6 -0
- package/registry/blocks/audio-player/time.js +67 -0
- package/registry/blocks/audio-player/wavesurfer.js +9 -0
- package/registry/blocks/auth-form/README.md +126 -0
- package/registry/blocks/auth-form/auth-form.jsx +568 -0
- package/registry/blocks/auth-form/block.json +10 -0
- package/registry/blocks/auth-form/demo.jsx +131 -0
- package/registry/blocks/auth-form/index.js +3 -0
- package/registry/blocks/board/README.md +64 -13
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +237 -94
- package/registry/blocks/board/demo.jsx +103 -24
- package/registry/blocks/calendar-view/README.md +180 -0
- package/registry/blocks/calendar-view/agenda.jsx +147 -0
- package/registry/blocks/calendar-view/block.json +76 -0
- package/registry/blocks/calendar-view/calendar-model.js +442 -0
- package/registry/blocks/calendar-view/calendar.jsx +627 -0
- package/registry/blocks/calendar-view/demo.jsx +195 -0
- package/registry/blocks/calendar-view/draft.jsx +49 -0
- package/registry/blocks/calendar-view/index.js +39 -0
- package/registry/blocks/calendar-view/month.jsx +346 -0
- package/registry/blocks/calendar-view/paint.js +69 -0
- package/registry/blocks/calendar-view/time-grid.jsx +527 -0
- package/registry/blocks/calendar-view/tray.jsx +87 -0
- package/registry/blocks/cart/README.md +146 -0
- package/registry/blocks/cart/block.json +10 -0
- package/registry/blocks/cart/cart.jsx +597 -0
- package/registry/blocks/cart/demo.jsx +98 -0
- package/registry/blocks/cart/index.js +4 -0
- package/registry/blocks/cart/money.js +28 -0
- package/registry/blocks/chart/README.md +316 -0
- package/registry/blocks/chart/block.json +10 -0
- package/registry/blocks/chart/cartesian.jsx +642 -0
- package/registry/blocks/chart/core.jsx +262 -0
- package/registry/blocks/chart/demo.jsx +357 -0
- package/registry/blocks/chart/heatmap.jsx +336 -0
- package/registry/blocks/chart/index.js +8 -0
- package/registry/blocks/chart/pie.jsx +245 -0
- package/registry/blocks/chart/sparkline.jsx +88 -0
- package/registry/blocks/chat/README.md +273 -0
- package/registry/blocks/chat/attachment.jsx +95 -0
- package/registry/blocks/chat/block.json +10 -0
- package/registry/blocks/chat/chat.jsx +132 -0
- package/registry/blocks/chat/composer.jsx +364 -0
- package/registry/blocks/chat/demo.jsx +578 -0
- package/registry/blocks/chat/header.jsx +34 -0
- package/registry/blocks/chat/index.js +9 -0
- package/registry/blocks/chat/message.jsx +450 -0
- package/registry/blocks/chat/scroller.jsx +247 -0
- package/registry/blocks/chat/text.jsx +104 -0
- package/registry/blocks/code-editor/README.md +210 -0
- package/registry/blocks/code-editor/block.json +22 -0
- package/registry/blocks/code-editor/code-editor.jsx +534 -0
- package/registry/blocks/code-editor/codemirror.js +38 -0
- package/registry/blocks/code-editor/demo.jsx +205 -0
- package/registry/blocks/code-editor/index.js +8 -0
- package/registry/blocks/code-editor/json.js +317 -0
- package/registry/blocks/code-editor/sql.js +136 -0
- package/registry/blocks/code-editor/text.js +101 -0
- package/registry/blocks/code-editor/theme.js +186 -0
- package/registry/blocks/comment-box/README.md +123 -0
- package/registry/blocks/comment-box/block.json +10 -0
- package/registry/blocks/comment-box/comment-body.jsx +217 -0
- package/registry/blocks/comment-box/comment-box.jsx +198 -0
- package/registry/blocks/comment-box/comment-time.jsx +77 -0
- package/registry/blocks/comment-box/demo.jsx +141 -0
- package/registry/blocks/comment-box/index.js +8 -0
- package/registry/blocks/contact-section/README.md +152 -0
- package/registry/blocks/contact-section/block.json +11 -0
- package/registry/blocks/contact-section/contact-section.jsx +509 -0
- package/registry/blocks/contact-section/demo.jsx +93 -0
- package/registry/blocks/contact-section/index.js +4 -0
- package/registry/blocks/csv-import/README.md +133 -0
- package/registry/blocks/csv-import/block.json +13 -0
- package/registry/blocks/csv-import/csv-import.jsx +479 -0
- package/registry/blocks/csv-import/demo.jsx +106 -0
- package/registry/blocks/csv-import/import.js +200 -0
- package/registry/blocks/csv-import/index.js +7 -0
- package/registry/blocks/data-table/README.md +386 -0
- package/registry/blocks/data-table/block.json +10 -0
- package/registry/blocks/data-table/data-table.jsx +1164 -0
- package/registry/blocks/data-table/demo.jsx +588 -0
- package/registry/blocks/data-table/index.js +5 -0
- package/registry/blocks/data-table/model.js +169 -0
- package/registry/blocks/diagram/README.md +108 -0
- package/registry/blocks/diagram/block.json +13 -0
- package/registry/blocks/diagram/demo.jsx +113 -0
- package/registry/blocks/diagram/diagram.jsx +481 -0
- package/registry/blocks/diagram/index.js +7 -0
- package/registry/blocks/diagram/mermaid.js +52 -0
- package/registry/blocks/diagram/palette.js +313 -0
- package/registry/blocks/diagram/source.js +98 -0
- package/registry/blocks/doc-editor/README.md +215 -0
- package/registry/blocks/doc-editor/block.json +15 -0
- package/registry/blocks/doc-editor/demo.jsx +225 -0
- package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
- package/registry/blocks/doc-editor/doc.js +309 -0
- package/registry/blocks/doc-editor/index.js +7 -0
- package/registry/blocks/doc-editor/schema.jsx +56 -0
- package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
- package/registry/blocks/doc-editor/theme.js +82 -0
- package/registry/blocks/doc-page/README.md +119 -0
- package/registry/blocks/doc-page/autosave.js +104 -0
- package/registry/blocks/doc-page/block.json +10 -0
- package/registry/blocks/doc-page/demo.jsx +137 -0
- package/registry/blocks/doc-page/doc-page.jsx +276 -0
- package/registry/blocks/doc-page/index.js +4 -0
- package/registry/blocks/email-render/README.md +151 -0
- package/registry/blocks/email-render/block.json +14 -0
- package/registry/blocks/email-render/demo.jsx +153 -0
- package/registry/blocks/email-render/doc-email.jsx +210 -0
- package/registry/blocks/email-render/email.jsx +221 -0
- package/registry/blocks/email-render/index.js +10 -0
- package/registry/blocks/email-render/render.js +50 -0
- package/registry/blocks/email-render/theme.js +215 -0
- package/registry/blocks/faq/README.md +101 -0
- package/registry/blocks/faq/block.json +11 -0
- package/registry/blocks/faq/demo.jsx +89 -0
- package/registry/blocks/faq/faq.jsx +220 -0
- package/registry/blocks/faq/index.js +4 -0
- package/registry/blocks/file-upload/README.md +138 -0
- package/registry/blocks/file-upload/block.json +10 -0
- package/registry/blocks/file-upload/demo.jsx +204 -0
- package/registry/blocks/file-upload/file-upload.jsx +635 -0
- package/registry/blocks/file-upload/index.js +4 -0
- package/registry/blocks/flow-canvas/README.md +420 -0
- package/registry/blocks/flow-canvas/block.json +13 -0
- package/registry/blocks/flow-canvas/board.js +819 -0
- package/registry/blocks/flow-canvas/chrome.jsx +649 -0
- package/registry/blocks/flow-canvas/context.jsx +35 -0
- package/registry/blocks/flow-canvas/demo.jsx +249 -0
- package/registry/blocks/flow-canvas/edges.jsx +107 -0
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
- package/registry/blocks/flow-canvas/index.js +41 -0
- package/registry/blocks/flow-canvas/nodes.jsx +392 -0
- package/registry/blocks/flow-canvas/theme.js +174 -0
- package/registry/blocks/footer/README.md +133 -0
- package/registry/blocks/footer/block.json +11 -0
- package/registry/blocks/footer/demo.jsx +119 -0
- package/registry/blocks/footer/footer.jsx +406 -0
- package/registry/blocks/footer/index.js +4 -0
- package/registry/blocks/gantt/README.md +220 -0
- package/registry/blocks/gantt/block.json +10 -0
- package/registry/blocks/gantt/demo.jsx +148 -0
- package/registry/blocks/gantt/gantt.jsx +923 -0
- package/registry/blocks/gantt/index.js +7 -0
- package/registry/blocks/gantt/rows.jsx +468 -0
- package/registry/blocks/gantt/schedule.js +278 -0
- package/registry/blocks/job-panel/README.md +86 -2
- package/registry/blocks/job-panel/block.json +3 -3
- package/registry/blocks/job-panel/demo.jsx +230 -3
- package/registry/blocks/job-panel/job-panel.jsx +169 -3
- package/registry/blocks/json-editor/README.md +133 -0
- package/registry/blocks/json-editor/block.json +10 -0
- package/registry/blocks/json-editor/demo.jsx +92 -0
- package/registry/blocks/json-editor/index.js +7 -0
- package/registry/blocks/json-editor/json-editor.jsx +305 -0
- package/registry/blocks/json-editor/json-tree.jsx +393 -0
- package/registry/blocks/json-editor/tree.js +225 -0
- package/registry/blocks/map/README.md +221 -0
- package/registry/blocks/map/block.json +14 -0
- package/registry/blocks/map/demo.jsx +201 -0
- package/registry/blocks/map/geo.js +198 -0
- package/registry/blocks/map/index.js +8 -0
- package/registry/blocks/map/list.jsx +128 -0
- package/registry/blocks/map/map-view.jsx +715 -0
- package/registry/blocks/map/maplibre.js +30 -0
- package/registry/blocks/map/marks.jsx +146 -0
- package/registry/blocks/map/theme.js +142 -0
- package/registry/blocks/menubar/README.md +109 -0
- package/registry/blocks/menubar/block.json +10 -0
- package/registry/blocks/menubar/demo.jsx +128 -0
- package/registry/blocks/menubar/index.js +4 -0
- package/registry/blocks/menubar/menubar.jsx +199 -0
- package/registry/blocks/mind-map/README.md +206 -0
- package/registry/blocks/mind-map/block.json +10 -0
- package/registry/blocks/mind-map/demo.jsx +103 -0
- package/registry/blocks/mind-map/index.js +31 -0
- package/registry/blocks/mind-map/mind-map.jsx +1125 -0
- package/registry/blocks/mind-map/topic.jsx +143 -0
- package/registry/blocks/mind-map/tree.js +645 -0
- package/registry/blocks/navigation-menu/README.md +124 -0
- package/registry/blocks/navigation-menu/block.json +10 -0
- package/registry/blocks/navigation-menu/demo.jsx +84 -0
- package/registry/blocks/navigation-menu/index.js +4 -0
- package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
- package/registry/blocks/order-detail/README.md +109 -0
- package/registry/blocks/order-detail/block.json +10 -0
- package/registry/blocks/order-detail/demo.jsx +88 -0
- package/registry/blocks/order-detail/index.js +4 -0
- package/registry/blocks/order-detail/order-detail.jsx +354 -0
- package/registry/blocks/org-chart/README.md +145 -0
- package/registry/blocks/org-chart/block.json +10 -0
- package/registry/blocks/org-chart/demo.jsx +94 -0
- package/registry/blocks/org-chart/index.js +7 -0
- package/registry/blocks/org-chart/org-chart.jsx +631 -0
- package/registry/blocks/org-chart/org.js +245 -0
- package/registry/blocks/org-chart/person.jsx +96 -0
- package/registry/blocks/page-builder/README.md +257 -0
- package/registry/blocks/page-builder/block.json +14 -0
- package/registry/blocks/page-builder/demo.jsx +145 -0
- package/registry/blocks/page-builder/grapes.js +18 -0
- package/registry/blocks/page-builder/index.js +11 -0
- package/registry/blocks/page-builder/page-builder.jsx +704 -0
- package/registry/blocks/page-builder/page-view.jsx +33 -0
- package/registry/blocks/page-builder/page.js +118 -0
- package/registry/blocks/page-builder/panels.jsx +588 -0
- package/registry/blocks/page-builder/sections.js +209 -0
- package/registry/blocks/page-builder/theme.js +87 -0
- package/registry/blocks/page-builder/thumbs.jsx +189 -0
- package/registry/blocks/page-builder/tokens.js +329 -0
- package/registry/blocks/payment-methods/README.md +104 -0
- package/registry/blocks/payment-methods/block.json +10 -0
- package/registry/blocks/payment-methods/demo.jsx +71 -0
- package/registry/blocks/payment-methods/index.js +4 -0
- package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
- package/registry/blocks/pdf-document/README.md +213 -0
- package/registry/blocks/pdf-document/block.json +13 -0
- package/registry/blocks/pdf-document/demo.jsx +136 -0
- package/registry/blocks/pdf-document/index.js +33 -0
- package/registry/blocks/pdf-document/money.js +83 -0
- package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
- package/registry/blocks/pdf-document/primitives.jsx +271 -0
- package/registry/blocks/pdf-document/quote.jsx +179 -0
- package/registry/blocks/pdf-document/theme.js +193 -0
- package/registry/blocks/pdf-viewer/README.md +191 -0
- package/registry/blocks/pdf-viewer/block.json +14 -0
- package/registry/blocks/pdf-viewer/demo.jsx +252 -0
- package/registry/blocks/pdf-viewer/helpers.js +270 -0
- package/registry/blocks/pdf-viewer/index.js +8 -0
- package/registry/blocks/pdf-viewer/notes.jsx +195 -0
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
- package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
- package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
- package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
- package/registry/blocks/product-detail/README.md +217 -0
- package/registry/blocks/product-detail/block.json +10 -0
- package/registry/blocks/product-detail/demo.jsx +233 -0
- package/registry/blocks/product-detail/index.js +7 -0
- package/registry/blocks/product-detail/price.jsx +115 -0
- package/registry/blocks/product-detail/product-detail.jsx +348 -0
- package/registry/blocks/product-detail/product-media.jsx +102 -0
- package/registry/blocks/product-detail/product-options.jsx +144 -0
- package/registry/blocks/product-grid/README.md +162 -0
- package/registry/blocks/product-grid/block.json +10 -0
- package/registry/blocks/product-grid/demo.jsx +255 -0
- package/registry/blocks/product-grid/index.js +5 -0
- package/registry/blocks/product-grid/product-card.jsx +232 -0
- package/registry/blocks/product-grid/product-grid.jsx +235 -0
- package/registry/blocks/record-form/README.md +196 -0
- package/registry/blocks/record-form/block.json +10 -0
- package/registry/blocks/record-form/demo.jsx +525 -0
- package/registry/blocks/record-form/index.js +4 -0
- package/registry/blocks/record-form/record-fields.jsx +457 -0
- package/registry/blocks/record-form/record-form.jsx +415 -0
- package/registry/blocks/record-form/rules.js +81 -0
- package/registry/blocks/record-notes/README.md +139 -0
- package/registry/blocks/record-notes/block.json +10 -0
- package/registry/blocks/record-notes/demo.jsx +179 -0
- package/registry/blocks/record-notes/index.js +4 -0
- package/registry/blocks/record-notes/record-notes.jsx +266 -0
- package/registry/blocks/search-dialog/README.md +108 -0
- package/registry/blocks/search-dialog/block.json +10 -0
- package/registry/blocks/search-dialog/demo.jsx +116 -0
- package/registry/blocks/search-dialog/index.js +3 -0
- package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
- package/registry/blocks/settings-list/README.md +171 -0
- package/registry/blocks/settings-list/block.json +10 -0
- package/registry/blocks/settings-list/demo.jsx +333 -0
- package/registry/blocks/settings-list/index.js +4 -0
- package/registry/blocks/settings-list/row-state.jsx +93 -0
- package/registry/blocks/settings-list/settings-list.jsx +349 -0
- package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
- package/registry/blocks/setup-checklist/README.md +142 -0
- package/registry/blocks/setup-checklist/block.json +10 -0
- package/registry/blocks/setup-checklist/demo.jsx +159 -0
- package/registry/blocks/setup-checklist/index.js +4 -0
- package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
- package/registry/blocks/share-dialog/README.md +113 -0
- package/registry/blocks/share-dialog/block.json +10 -0
- package/registry/blocks/share-dialog/demo.jsx +140 -0
- package/registry/blocks/share-dialog/index.js +3 -0
- package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
- package/registry/blocks/sidebar/README.md +190 -0
- package/registry/blocks/sidebar/block.json +43 -0
- package/registry/blocks/sidebar/demo.jsx +577 -0
- package/registry/blocks/sidebar/index.js +4 -0
- package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
- package/registry/blocks/sidebar/sidebar.jsx +864 -0
- package/registry/blocks/signature-pad/README.md +137 -0
- package/registry/blocks/signature-pad/block.json +13 -0
- package/registry/blocks/signature-pad/colors.js +115 -0
- package/registry/blocks/signature-pad/demo.jsx +94 -0
- package/registry/blocks/signature-pad/index.js +6 -0
- package/registry/blocks/signature-pad/pad.js +7 -0
- package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
- package/registry/blocks/signature-pad/signature.js +68 -0
- package/registry/blocks/sketch-canvas/README.md +280 -0
- package/registry/blocks/sketch-canvas/block.json +13 -0
- package/registry/blocks/sketch-canvas/demo.jsx +159 -0
- package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
- package/registry/blocks/sketch-canvas/index.js +9 -0
- package/registry/blocks/sketch-canvas/palette.js +226 -0
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
- package/registry/blocks/sketch-canvas/sketch.js +179 -0
- package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
- package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
- package/registry/blocks/sketch-canvas/stamps.js +104 -0
- package/registry/blocks/sketch-canvas/theme.js +131 -0
- package/registry/blocks/spreadsheet/README.md +307 -0
- package/registry/blocks/spreadsheet/block.json +13 -0
- package/registry/blocks/spreadsheet/cells.jsx +455 -0
- package/registry/blocks/spreadsheet/chrome.jsx +325 -0
- package/registry/blocks/spreadsheet/demo.jsx +177 -0
- package/registry/blocks/spreadsheet/grid.js +387 -0
- package/registry/blocks/spreadsheet/index.js +34 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
- package/registry/blocks/spreadsheet/types.js +473 -0
- package/registry/blocks/stat-cards/README.md +173 -0
- package/registry/blocks/stat-cards/block.json +10 -0
- package/registry/blocks/stat-cards/demo.jsx +257 -0
- package/registry/blocks/stat-cards/index.js +4 -0
- package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
- package/registry/blocks/stat-cards/usage.jsx +243 -0
- package/registry/blocks/task-list/README.md +176 -0
- package/registry/blocks/task-list/block.json +10 -0
- package/registry/blocks/task-list/demo.jsx +134 -0
- package/registry/blocks/task-list/index.js +5 -0
- package/registry/blocks/task-list/task-list.jsx +907 -0
- package/registry/blocks/task-model/README.md +455 -0
- package/registry/blocks/task-model/block.json +167 -0
- package/registry/blocks/task-model/changes.js +89 -0
- package/registry/blocks/task-model/dates.js +371 -0
- package/registry/blocks/task-model/demo.jsx +215 -0
- package/registry/blocks/task-model/dnd.jsx +240 -0
- package/registry/blocks/task-model/index.js +97 -0
- package/registry/blocks/task-model/model.js +919 -0
- package/registry/blocks/task-model/parts.jsx +449 -0
- package/registry/blocks/task-model/toolbar.jsx +271 -0
- package/registry/blocks/testimonials/README.md +139 -0
- package/registry/blocks/testimonials/block.json +11 -0
- package/registry/blocks/testimonials/demo.jsx +137 -0
- package/registry/blocks/testimonials/index.js +4 -0
- package/registry/blocks/testimonials/testimonials.jsx +430 -0
- package/registry/blocks/transaction-list/README.md +126 -0
- package/registry/blocks/transaction-list/block.json +10 -0
- package/registry/blocks/transaction-list/demo.jsx +79 -0
- package/registry/blocks/transaction-list/index.js +4 -0
- package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
- package/registry/blocks/whiteboard/README.md +179 -0
- package/registry/blocks/whiteboard/block.json +10 -0
- package/registry/blocks/whiteboard/demo.jsx +169 -0
- package/registry/blocks/whiteboard/index.js +6 -0
- package/registry/blocks/whiteboard/templates.js +150 -0
- package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
- package/src/install.mjs +18 -0
- package/src/shadcn.mjs +171 -0
- package/templates/next/files/README.md +145 -11
- package/templates/next/files/app/globals.css +55 -4
- package/templates/next/files/check/run.mjs +3 -3
- package/templates/next/files/components/parts/fixture.jsx +1 -1
- package/templates/next/files/components/parts/sample.js +15 -0
- package/templates/next/files/components/ui/avatar.jsx +141 -0
- package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
- package/templates/next/files/components/ui/button-group.jsx +70 -0
- package/templates/next/files/components/ui/button.jsx +132 -12
- package/templates/next/files/components/ui/calendar.jsx +609 -0
- package/templates/next/files/components/ui/carousel.jsx +281 -0
- package/templates/next/files/components/ui/collapsible.jsx +208 -0
- package/templates/next/files/components/ui/combobox.jsx +608 -0
- package/templates/next/files/components/ui/command.jsx +577 -0
- package/templates/next/files/components/ui/context-menu.jsx +191 -0
- package/templates/next/files/components/ui/date-picker.jsx +360 -0
- package/templates/next/files/components/ui/distribution.jsx +117 -0
- package/templates/next/files/components/ui/feedback.jsx +143 -0
- package/templates/next/files/components/ui/field.jsx +115 -3
- package/templates/next/files/components/ui/file-input.jsx +234 -0
- package/templates/next/files/components/ui/icon.jsx +130 -8
- package/templates/next/files/components/ui/image.jsx +143 -0
- package/templates/next/files/components/ui/index.js +47 -2
- package/templates/next/files/components/ui/input-group.jsx +213 -0
- package/templates/next/files/components/ui/input-otp.jsx +170 -0
- package/templates/next/files/components/ui/item.jsx +206 -0
- package/templates/next/files/components/ui/menu.jsx +454 -82
- package/templates/next/files/components/ui/notice.jsx +126 -14
- package/templates/next/files/components/ui/pagination.jsx +156 -0
- package/templates/next/files/components/ui/popover.jsx +284 -0
- package/templates/next/files/components/ui/radio.jsx +193 -0
- package/templates/next/files/components/ui/rating.jsx +131 -0
- package/templates/next/files/components/ui/resizable.jsx +338 -0
- package/templates/next/files/components/ui/scroll-area.jsx +123 -0
- package/templates/next/files/components/ui/separator.jsx +119 -0
- package/templates/next/files/components/ui/sheet.jsx +96 -11
- package/templates/next/files/components/ui/slider.jsx +174 -0
- package/templates/next/files/components/ui/stat.jsx +574 -0
- package/templates/next/files/components/ui/steps.jsx +338 -0
- package/templates/next/files/components/ui/swatch.jsx +33 -0
- package/templates/next/files/components/ui/table.jsx +130 -0
- package/templates/next/files/components/ui/toast.jsx +440 -0
- package/templates/next/files/components/ui/toggle.jsx +195 -0
- package/templates/next/files/components/ui/tooltip.jsx +270 -0
- package/templates/next/files/lib/sample.js +4 -12
- package/templates/next/template.json +264 -8
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// CommentBox — a minimal rich comment field (DocEditor in minimal mode)
|
|
4
|
+
// with @mentions and Cmd/Ctrl+Enter to post, and, when `comments` is
|
|
5
|
+
// given, the thread above it. CommentComposer is the field alone: record-
|
|
6
|
+
// notes uses it to add a note and to edit one in place.
|
|
7
|
+
//
|
|
8
|
+
// A post goes out through an async callback that answers { ok }. While it
|
|
9
|
+
// runs the box is locked and Post spins; a refusal (or a throw) keeps the
|
|
10
|
+
// draft and says why under the box. Only a post that came back ok clears.
|
|
11
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
12
|
+
import { Avatar, Button, KbdGroup, cx } from "../../ui";
|
|
13
|
+
import { DocEditor, isDocEmpty, useDocEditor } from "../doc-editor";
|
|
14
|
+
import { CommentBody } from "./comment-body";
|
|
15
|
+
import { CommentTime } from "./comment-time";
|
|
16
|
+
|
|
17
|
+
const nameOf = (author) => (typeof author === "string" ? author : author?.name) || "Someone";
|
|
18
|
+
const srcOf = (author) => (typeof author === "object" && author ? author.src : undefined);
|
|
19
|
+
|
|
20
|
+
/** ⌘ on a Mac, Ctrl elsewhere — known only in the browser. */
|
|
21
|
+
function useModKey() {
|
|
22
|
+
const [mac, setMac] = useState(null);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const p = navigator.userAgentData?.platform || navigator.platform || "";
|
|
25
|
+
setMac(/mac|iphone|ipad/i.test(p));
|
|
26
|
+
}, []);
|
|
27
|
+
return mac === null ? null : mac ? "⌘" : "Ctrl";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function CommentComposer({
|
|
31
|
+
onSubmit,
|
|
32
|
+
author,
|
|
33
|
+
mentions,
|
|
34
|
+
defaultValue,
|
|
35
|
+
placeholder = "Write a comment…",
|
|
36
|
+
submitLabel = "Post",
|
|
37
|
+
submitIcon = "send",
|
|
38
|
+
busyLabel,
|
|
39
|
+
failedText = "Couldn't post. Your comment is still here; try again.",
|
|
40
|
+
onCancel,
|
|
41
|
+
cancelLabel = "Cancel",
|
|
42
|
+
label = "Comment",
|
|
43
|
+
autoFocus = false,
|
|
44
|
+
disabled = false,
|
|
45
|
+
clearOnSubmit = true,
|
|
46
|
+
className,
|
|
47
|
+
}) {
|
|
48
|
+
const box = useDocEditor();
|
|
49
|
+
const [draft, setDraft] = useState(defaultValue ?? null);
|
|
50
|
+
const [busy, setBusy] = useState(false);
|
|
51
|
+
const [error, setError] = useState(null);
|
|
52
|
+
const running = useRef(false);
|
|
53
|
+
const mod = useModKey();
|
|
54
|
+
const errorId = useId();
|
|
55
|
+
const empty = !draft || isDocEmpty(draft);
|
|
56
|
+
|
|
57
|
+
async function submit(doc) {
|
|
58
|
+
if (running.current || disabled || !doc || isDocEmpty(doc)) return;
|
|
59
|
+
running.current = true;
|
|
60
|
+
setBusy(true);
|
|
61
|
+
setError(null);
|
|
62
|
+
let res;
|
|
63
|
+
try {
|
|
64
|
+
res = await onSubmit?.(doc);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
res = { ok: false, error: e?.message };
|
|
67
|
+
}
|
|
68
|
+
running.current = false;
|
|
69
|
+
setBusy(false);
|
|
70
|
+
if (res && res.ok === false) {
|
|
71
|
+
setError(res.error || failedText);
|
|
72
|
+
box.current?.focus();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (clearOnSubmit) {
|
|
76
|
+
box.current?.clear();
|
|
77
|
+
setDraft(null);
|
|
78
|
+
}
|
|
79
|
+
box.current?.focus();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div className={cx("flex items-start gap-3", className)}>
|
|
84
|
+
{author ? (
|
|
85
|
+
<div className="mt-1 hidden shrink-0 sm:block">
|
|
86
|
+
<Avatar name={nameOf(author)} src={srcOf(author)} size="sm" />
|
|
87
|
+
</div>
|
|
88
|
+
) : null}
|
|
89
|
+
<div className="min-w-0 flex-1">
|
|
90
|
+
<div
|
|
91
|
+
className={cx(
|
|
92
|
+
"rounded-md border bg-background px-3 py-2 focus-within:ring-2 focus-within:ring-ring",
|
|
93
|
+
error ? "border-destructive" : "border-input",
|
|
94
|
+
(busy || disabled) && "opacity-60",
|
|
95
|
+
)}
|
|
96
|
+
aria-describedby={error ? errorId : undefined}
|
|
97
|
+
>
|
|
98
|
+
<DocEditor
|
|
99
|
+
minimal
|
|
100
|
+
editorRef={box}
|
|
101
|
+
defaultValue={defaultValue}
|
|
102
|
+
onChange={(d) => {
|
|
103
|
+
setDraft(d);
|
|
104
|
+
if (error) setError(null);
|
|
105
|
+
}}
|
|
106
|
+
onSubmit={submit}
|
|
107
|
+
mentions={mentions}
|
|
108
|
+
placeholder={placeholder}
|
|
109
|
+
label={label}
|
|
110
|
+
autoFocus={autoFocus}
|
|
111
|
+
editable={!busy && !disabled}
|
|
112
|
+
/>
|
|
113
|
+
</div>
|
|
114
|
+
{error ? (
|
|
115
|
+
<p id={errorId} role="alert" className="mt-1.5 text-xs text-destructive">
|
|
116
|
+
{error}
|
|
117
|
+
</p>
|
|
118
|
+
) : null}
|
|
119
|
+
<div className="mt-2 flex flex-wrap items-center justify-end gap-2">
|
|
120
|
+
{mod ? (
|
|
121
|
+
<span className="me-auto hidden items-center gap-1.5 text-xs text-muted-foreground sm:inline-flex">
|
|
122
|
+
<KbdGroup keys={[mod, "Enter"]} />
|
|
123
|
+
<span>to {submitLabel.toLowerCase()}</span>
|
|
124
|
+
</span>
|
|
125
|
+
) : null}
|
|
126
|
+
{onCancel ? (
|
|
127
|
+
<Button variant="quiet" onClick={onCancel} disabled={busy}>
|
|
128
|
+
{cancelLabel}
|
|
129
|
+
</Button>
|
|
130
|
+
) : null}
|
|
131
|
+
<Button variant="primary" icon={submitIcon || undefined} loading={busy} disabled={empty || disabled} onClick={() => submit(box.current?.getDoc() ?? draft)}>
|
|
132
|
+
{busy && busyLabel ? busyLabel : submitLabel}
|
|
133
|
+
</Button>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** One comment in the thread: avatar, name, time, the body. */
|
|
141
|
+
function CommentItem({ comment }) {
|
|
142
|
+
const name = nameOf(comment.author);
|
|
143
|
+
return (
|
|
144
|
+
<li className="flex gap-3">
|
|
145
|
+
<Avatar name={name} src={srcOf(comment.author)} size="sm" className="shrink-0" />
|
|
146
|
+
<div className="min-w-0 flex-1">
|
|
147
|
+
<p className="flex flex-wrap items-baseline gap-x-2 text-sm">
|
|
148
|
+
<span className="font-medium">{name}</span>
|
|
149
|
+
<CommentTime date={comment.createdAt} />
|
|
150
|
+
{comment.edited ? <span className="text-xs text-muted-foreground">(edited)</span> : null}
|
|
151
|
+
</p>
|
|
152
|
+
<CommentBody doc={comment.body} className="mt-0.5 text-foreground" />
|
|
153
|
+
</div>
|
|
154
|
+
</li>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function CommentBox({
|
|
159
|
+
onPost,
|
|
160
|
+
comments,
|
|
161
|
+
author,
|
|
162
|
+
mentions,
|
|
163
|
+
placeholder = "Write a comment…",
|
|
164
|
+
postLabel = "Post",
|
|
165
|
+
label = "Comment",
|
|
166
|
+
emptyText = "No comments yet.",
|
|
167
|
+
threadLabel = "Comments",
|
|
168
|
+
autoFocus = false,
|
|
169
|
+
disabled = false,
|
|
170
|
+
className,
|
|
171
|
+
}) {
|
|
172
|
+
const list = Array.isArray(comments) ? comments : null;
|
|
173
|
+
return (
|
|
174
|
+
<div className={cx("grid gap-4", className)}>
|
|
175
|
+
{list ? (
|
|
176
|
+
list.length ? (
|
|
177
|
+
<ul aria-label={threadLabel} className="grid gap-4">
|
|
178
|
+
{list.map((c, i) => (
|
|
179
|
+
<CommentItem key={c.id ?? i} comment={c} />
|
|
180
|
+
))}
|
|
181
|
+
</ul>
|
|
182
|
+
) : (
|
|
183
|
+
<p className="text-sm text-muted-foreground">{emptyText}</p>
|
|
184
|
+
)
|
|
185
|
+
) : null}
|
|
186
|
+
<CommentComposer
|
|
187
|
+
onSubmit={onPost}
|
|
188
|
+
author={author}
|
|
189
|
+
mentions={mentions}
|
|
190
|
+
placeholder={placeholder}
|
|
191
|
+
submitLabel={postLabel}
|
|
192
|
+
label={label}
|
|
193
|
+
autoFocus={autoFocus}
|
|
194
|
+
disabled={disabled}
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// CommentTime — when a comment was written, as a <time>.
|
|
4
|
+
//
|
|
5
|
+
// Relative words ("5 min ago") need the clock, and the server's clock and
|
|
6
|
+
// time zone are not the reader's. So the server and the first paint show
|
|
7
|
+
// the absolute date; after mount it turns relative, and one shared minute
|
|
8
|
+
// tick (not a timer per comment) keeps every label current. The full date
|
|
9
|
+
// is always in the title.
|
|
10
|
+
import { useEffect, useState } from "react";
|
|
11
|
+
import { cx } from "../../ui";
|
|
12
|
+
|
|
13
|
+
const listeners = new Set();
|
|
14
|
+
let timer = null;
|
|
15
|
+
function subscribe(fn) {
|
|
16
|
+
listeners.add(fn);
|
|
17
|
+
if (!timer) timer = setInterval(() => listeners.forEach((l) => l(Date.now())), 60_000);
|
|
18
|
+
return () => {
|
|
19
|
+
listeners.delete(fn);
|
|
20
|
+
if (!listeners.size && timer) {
|
|
21
|
+
clearInterval(timer);
|
|
22
|
+
timer = null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Date.now(), refreshed each minute — null until mounted. */
|
|
28
|
+
export function useNow() {
|
|
29
|
+
const [now, setNow] = useState(null);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setNow(Date.now());
|
|
32
|
+
return subscribe(setNow);
|
|
33
|
+
}, []);
|
|
34
|
+
return now;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const toDate = (v) => {
|
|
38
|
+
if (v === undefined || v === null || v === "") return null;
|
|
39
|
+
const d = v instanceof Date ? v : new Date(v);
|
|
40
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const fmt = (opts) => new Intl.DateTimeFormat(undefined, opts);
|
|
44
|
+
const TIME = { hour: "numeric", minute: "2-digit" };
|
|
45
|
+
const startOfDay = (ms) => {
|
|
46
|
+
const d = new Date(ms);
|
|
47
|
+
d.setHours(0, 0, 0, 0);
|
|
48
|
+
return d.getTime();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** "12 Sep 2026, 14:05" — the title, and the label before mount. */
|
|
52
|
+
export function fullDate(d) {
|
|
53
|
+
return fmt({ day: "numeric", month: "short", year: "numeric", ...TIME }).format(d);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** "just now" · "5 min ago" · "3 h ago" (today) · "Yesterday, 14:05" · "12 Sep, 14:05" · "12 Sep 2025". */
|
|
57
|
+
export function relativeDate(d, now) {
|
|
58
|
+
const diff = now - d.getTime();
|
|
59
|
+
if (diff < 45_000 && diff > -60_000) return "just now";
|
|
60
|
+
const today = startOfDay(now);
|
|
61
|
+
if (diff > 0 && diff < 60 * 60_000) return `${Math.round(diff / 60_000)} min ago`;
|
|
62
|
+
if (d.getTime() >= today && diff > 0) return `${Math.floor(diff / 3_600_000)} h ago`;
|
|
63
|
+
if (d.getTime() >= today - 86_400_000 && d.getTime() < today) return `Yesterday, ${fmt(TIME).format(d)}`;
|
|
64
|
+
if (new Date(d).getFullYear() === new Date(now).getFullYear()) return fmt({ day: "numeric", month: "short", ...TIME }).format(d);
|
|
65
|
+
return fmt({ day: "numeric", month: "short", year: "numeric" }).format(d);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function CommentTime({ date, className }) {
|
|
69
|
+
const now = useNow();
|
|
70
|
+
const d = toDate(date);
|
|
71
|
+
if (!d) return null;
|
|
72
|
+
return (
|
|
73
|
+
<time dateTime={d.toISOString()} title={fullDate(d)} suppressHydrationWarning className={cx("text-xs text-muted-foreground", className)}>
|
|
74
|
+
{now === null ? fullDate(d) : relativeDate(d, now)}
|
|
75
|
+
</time>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// CommentBox three ways — the gallery's and the smoke test's surface. Not
|
|
4
|
+
// installed into apps. Posts are pretend: a switch makes them fail.
|
|
5
|
+
// Thread comments on a design review, the box under them.
|
|
6
|
+
// Field alone no thread: a reply field that reports what it posted.
|
|
7
|
+
// Empty a thread with nothing in it yet, and a locked box.
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { Card, Switch, TabPanel, Tabs } from "../components/ui";
|
|
10
|
+
import { CommentBox } from "../components/blocks/comment-box";
|
|
11
|
+
import { docToText } from "../components/blocks/doc-editor";
|
|
12
|
+
|
|
13
|
+
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
14
|
+
const ago = (min) => new Date(Date.now() - min * 60_000).toISOString();
|
|
15
|
+
|
|
16
|
+
const TEAM = [
|
|
17
|
+
{ id: "u-priya", label: "Priya Raman", description: "Design" },
|
|
18
|
+
{ id: "u-tomas", label: "Tomás Ortega", description: "Engineering" },
|
|
19
|
+
{ id: "u-june", label: "June Okafor", description: "Growth" },
|
|
20
|
+
{ id: "u-lena", label: "Lena Fischer", description: "Sales" },
|
|
21
|
+
];
|
|
22
|
+
const findPeople = async (query) => {
|
|
23
|
+
const q = query.toLowerCase();
|
|
24
|
+
return TEAM.filter((p) => p.label.toLowerCase().includes(q));
|
|
25
|
+
};
|
|
26
|
+
const ME = { id: "u-june", name: "June Okafor" };
|
|
27
|
+
|
|
28
|
+
const t = (text, styles = {}) => ({ type: "text", text, styles });
|
|
29
|
+
const at = (id) => ({ type: "mention", props: { id, label: TEAM.find((p) => p.id === id).label } });
|
|
30
|
+
|
|
31
|
+
const REVIEW_THREAD = [
|
|
32
|
+
{
|
|
33
|
+
id: "c1",
|
|
34
|
+
author: { id: "u-priya", name: "Priya Raman" },
|
|
35
|
+
createdAt: ago(60 * 26),
|
|
36
|
+
body: [
|
|
37
|
+
{ type: "paragraph", content: [t("New pricing page is up for review. Two open questions:")] },
|
|
38
|
+
{ type: "numberedListItem", content: [t("Do we show the "), t("annual", { bold: true }), t(" price first?")] },
|
|
39
|
+
{ type: "numberedListItem", content: [t("Is the comparison table too long on a phone?")] },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "c2",
|
|
44
|
+
author: { id: "u-tomas", name: "Tomás Ortega" },
|
|
45
|
+
createdAt: ago(95),
|
|
46
|
+
edited: true,
|
|
47
|
+
body: [
|
|
48
|
+
{ type: "paragraph", content: [at("u-priya"), t(" annual first, monthly as the toggle. The table collapses to cards under 640px already.")] },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "c3",
|
|
53
|
+
author: { id: "u-lena", name: "Lena Fischer" },
|
|
54
|
+
createdAt: ago(12),
|
|
55
|
+
body: [{ type: "paragraph", content: [t("From sales: people ask about "), t("seats", { italic: true }), t(" before price. Can the seat line go above the fold?")] }],
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
function ThreadDemo() {
|
|
60
|
+
const [comments, setComments] = useState(REVIEW_THREAD);
|
|
61
|
+
const [failing, setFailing] = useState(false);
|
|
62
|
+
const post = async (doc) => {
|
|
63
|
+
await wait(700);
|
|
64
|
+
if (failing) return { ok: false, error: "The server is not answering. Your comment is still here; try again." };
|
|
65
|
+
setComments((c) => [...c, { id: `c${c.length + 1}`, author: ME, body: doc, createdAt: new Date().toISOString() }]);
|
|
66
|
+
return { ok: true };
|
|
67
|
+
};
|
|
68
|
+
return (
|
|
69
|
+
<Card
|
|
70
|
+
title="Pricing page review"
|
|
71
|
+
description="Type @ to mention someone. ⌘/Ctrl+Enter posts."
|
|
72
|
+
actions={<Switch id="cb-fail" label="Posts fail" checked={failing} onChange={(e) => setFailing(e.target.checked)} />}
|
|
73
|
+
className="max-w-2xl"
|
|
74
|
+
>
|
|
75
|
+
<CommentBox comments={comments} onPost={post} author={ME} mentions={findPeople} />
|
|
76
|
+
</Card>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function FieldDemo() {
|
|
81
|
+
const [last, setLast] = useState(null);
|
|
82
|
+
const post = async (doc) => {
|
|
83
|
+
await wait(400);
|
|
84
|
+
setLast(docToText(doc));
|
|
85
|
+
return { ok: true };
|
|
86
|
+
};
|
|
87
|
+
return (
|
|
88
|
+
<Card title="Reply" description="The field alone: no thread above it." className="max-w-2xl">
|
|
89
|
+
<CommentBox onPost={post} mentions={findPeople} postLabel="Reply" placeholder="Reply to Lena…" label="Reply" />
|
|
90
|
+
{last !== null ? (
|
|
91
|
+
<p className="mt-3 whitespace-pre-wrap break-words rounded-md bg-muted p-3 text-sm text-muted-foreground">Posted as text: {last}</p>
|
|
92
|
+
) : null}
|
|
93
|
+
</Card>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function EmptyDemo() {
|
|
98
|
+
const [comments, setComments] = useState([]);
|
|
99
|
+
const [locked, setLocked] = useState(false);
|
|
100
|
+
const post = async (doc) => {
|
|
101
|
+
await wait(400);
|
|
102
|
+
setComments((c) => [...c, { id: `e${c.length + 1}`, author: ME, body: doc, createdAt: new Date().toISOString() }]);
|
|
103
|
+
return { ok: true };
|
|
104
|
+
};
|
|
105
|
+
return (
|
|
106
|
+
<Card
|
|
107
|
+
title="Q4 onboarding email"
|
|
108
|
+
actions={<Switch id="cb-lock" label="Locked" checked={locked} onChange={(e) => setLocked(e.target.checked)} />}
|
|
109
|
+
className="max-w-2xl"
|
|
110
|
+
>
|
|
111
|
+
<CommentBox comments={comments} onPost={post} author={ME} mentions={findPeople} disabled={locked} emptyText="No comments yet. Start the conversation." />
|
|
112
|
+
</Card>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export default function CommentBoxDemo() {
|
|
117
|
+
const [tab, setTab] = useState("thread");
|
|
118
|
+
return (
|
|
119
|
+
<div className="grid gap-4">
|
|
120
|
+
<Tabs
|
|
121
|
+
aria-label="CommentBox variants"
|
|
122
|
+
value={tab}
|
|
123
|
+
onChange={setTab}
|
|
124
|
+
tabs={[
|
|
125
|
+
{ key: "thread", label: "Thread" },
|
|
126
|
+
{ key: "field", label: "Field alone" },
|
|
127
|
+
{ key: "empty", label: "Empty" },
|
|
128
|
+
]}
|
|
129
|
+
/>
|
|
130
|
+
<TabPanel tab="thread" value={tab}>
|
|
131
|
+
<ThreadDemo />
|
|
132
|
+
</TabPanel>
|
|
133
|
+
<TabPanel tab="field" value={tab}>
|
|
134
|
+
<FieldDemo />
|
|
135
|
+
</TabPanel>
|
|
136
|
+
<TabPanel tab="empty" value={tab}>
|
|
137
|
+
<EmptyDemo />
|
|
138
|
+
</TabPanel>
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// The CommentBox block — `makersclaw add comment-box`. Fixed: compose it
|
|
2
|
+
// through its props (README.md beside this file). CommentComposer is the
|
|
3
|
+
// field alone, CommentBody draws a posted doc, CommentTime a timestamp;
|
|
4
|
+
// record-notes is built from them. The editor is doc-editor's, in its
|
|
5
|
+
// minimal mode.
|
|
6
|
+
export { CommentBox, CommentComposer } from "./comment-box";
|
|
7
|
+
export { CommentBody } from "./comment-body";
|
|
8
|
+
export { CommentTime } from "./comment-time";
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Contact Section
|
|
2
|
+
|
|
3
|
+
A public "contact us" section. It holds a form, the ways to reach you, or
|
|
4
|
+
both. The form asks for a name, an email and a message, and optionally a
|
|
5
|
+
phone, a company, a subject, a topic (chips or radios) and a consent box.
|
|
6
|
+
The ways to reach you are details (email, phone, address, hours) and
|
|
7
|
+
offices.
|
|
8
|
+
|
|
9
|
+
Three layouts:
|
|
10
|
+
- **form** — the form alone, with the details on one line above it, or
|
|
11
|
+
a picture beside or behind it;
|
|
12
|
+
- **split** — the form beside an info panel (plain, or filled with the
|
|
13
|
+
primary colour);
|
|
14
|
+
- **cards** — the details as icon cards, alone, above the form or beside
|
|
15
|
+
it.
|
|
16
|
+
|
|
17
|
+
The form checks itself as it is sent. A missing or malformed field gets
|
|
18
|
+
its message under it, and the focus moves to the first one. It then
|
|
19
|
+
calls `onSubmit(values)`, which is async and returns `{ ok }`. While it
|
|
20
|
+
runs, the button spins and a second press does nothing. `{ ok: false,
|
|
21
|
+
error }` (or a throw) shows the error above the button and keeps
|
|
22
|
+
everything typed. `{ ok: true }` replaces the form with a "Message
|
|
23
|
+
sent" notice and a "Send another" button. It is a full-width section: it
|
|
24
|
+
pads itself and centres its content.
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
27
|
+
import { ContactSection } from "../components/blocks/contact-section"; // a Makersclaw app ("./blocks/contact-section" from components/)
|
|
28
|
+
import { ContactSection } from "@/components/makersclaw/blocks/contact-section"; // a shadcn project
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
It is a client component: render it from a `"use client"` component.
|
|
32
|
+
|
|
33
|
+
## The data
|
|
34
|
+
|
|
35
|
+
`details` is the ways to reach you:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
{
|
|
39
|
+
icon: "mail", // a name from the kit's Icon
|
|
40
|
+
label: "Email", // what it is ("Call sales" on a card)
|
|
41
|
+
value: "hello@fieldline.io", // what is shown
|
|
42
|
+
href?: "mailto:hello@fieldline.io", // a link: mailto:, tel:, a map, a page
|
|
43
|
+
description?: "A person replies within a working day.", // a card's and a panel row's second line
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`offices` (split only): `[{ name: "Lisbon", lines: ["Rua da Prata 88", …], icon? }]`.
|
|
48
|
+
|
|
49
|
+
`onSubmit` receives the values, trimmed:
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
{
|
|
53
|
+
firstName, lastName, // or `name` with nameFields="one"
|
|
54
|
+
email, message,
|
|
55
|
+
phone?, company?, subject?, // the ones named in `fields`
|
|
56
|
+
topic?, // the chosen option's value, "" for none
|
|
57
|
+
consent?, // true: it was required and ticked
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Props
|
|
62
|
+
|
|
63
|
+
- `onSubmit(values)` — async, returns `{ ok: true }` or `{ ok: false,
|
|
64
|
+
error? }`. Without it there is no form (a cards-only or panel-only
|
|
65
|
+
section).
|
|
66
|
+
- `layout` — `split` (default) · `form` · `cards`.
|
|
67
|
+
- `kicker`, `title`, `description` — the header. `title` defaults to
|
|
68
|
+
"Get in touch".
|
|
69
|
+
- `align` — the header, and the cards' content: `center` (default for
|
|
70
|
+
form and cards) · `start` (default for split).
|
|
71
|
+
- `details` — the ways to reach you, as above. A panel's rows in
|
|
72
|
+
`split`, one line above the form in `form`, the cards in `cards`.
|
|
73
|
+
- `offices` — `split`: the offices, under the details in the panel.
|
|
74
|
+
- `panel` — `split`: `plain` (default, a quiet bordered box) · `filled`
|
|
75
|
+
(the primary colour).
|
|
76
|
+
- `panelTitle`, `panelBody` — `split`: the panel's heading and a line
|
|
77
|
+
under it.
|
|
78
|
+
- `cardsPosition` — `cards` with a form: `above` (default) · `beside`
|
|
79
|
+
(the cards stacked in a column beside the form from `lg` up).
|
|
80
|
+
- `cardColumns` — `cards`: `1` · `2` · `3` · `4`. Default the number of
|
|
81
|
+
cards, at most 3.
|
|
82
|
+
- `image`, `imageAlt` — `form`: a picture. `imageAlt` defaults to ""
|
|
83
|
+
(decoration).
|
|
84
|
+
- `imagePosition` — `side` (default: beside the form from `md` up,
|
|
85
|
+
hidden on a phone) · `background` (behind the form card, under a veil
|
|
86
|
+
of the background colour).
|
|
87
|
+
- `nameFields` — `split` (default: first name, required, and last name)
|
|
88
|
+
· `one` (a single "Name").
|
|
89
|
+
- `fields` — the optional fields to add: any of `"phone"`, `"company"`,
|
|
90
|
+
`"subject"`. Phone and company are marked optional; subject is not
|
|
91
|
+
required either.
|
|
92
|
+
- `topics` — `{ label?, options, style?, required? }`: `options` are
|
|
93
|
+
strings or `{ value, label }`; `style` `chips` (default: pressable
|
|
94
|
+
chips above the name) · `radio` (a radio row after the email).
|
|
95
|
+
- `consent` — the label of a consent checkbox (a string or a node with
|
|
96
|
+
your policy link). When given, it must be ticked to send.
|
|
97
|
+
- `messageLabel` — default "Message". `messageRows` — default `5`.
|
|
98
|
+
- `submitLabel` — default "Send message".
|
|
99
|
+
- `sent` — `{ title?, body? }` for the sent notice.
|
|
100
|
+
- `defaultValues` — values to start with (a signed-in visitor's name and
|
|
101
|
+
email).
|
|
102
|
+
- `labels` — override field labels: `{ firstName, lastName, name, email,
|
|
103
|
+
phone, company, subject }`.
|
|
104
|
+
- `label` — what a screen reader calls the section. Default the title.
|
|
105
|
+
- `className` — the section's spacing and width. Never colour.
|
|
106
|
+
|
|
107
|
+
## Example
|
|
108
|
+
|
|
109
|
+
```jsx
|
|
110
|
+
// components/Contact.jsx
|
|
111
|
+
"use client";
|
|
112
|
+
import { ContactSection } from "./blocks/contact-section";
|
|
113
|
+
import { sendContactMessage } from "../lib/actions"; // your server action
|
|
114
|
+
|
|
115
|
+
export default function Contact() {
|
|
116
|
+
return (
|
|
117
|
+
<ContactSection
|
|
118
|
+
title="Talk to a person"
|
|
119
|
+
description="We reply within one working day."
|
|
120
|
+
details={[
|
|
121
|
+
{ icon: "mail", label: "Email", value: "hello@fieldline.io", href: "mailto:hello@fieldline.io" },
|
|
122
|
+
{ icon: "phone", label: "Phone", value: "+44 20 7946 0321", href: "tel:+442079460321" },
|
|
123
|
+
{ icon: "clock", label: "Hours", value: "Mon–Fri, 9:00–18:00 GMT" },
|
|
124
|
+
]}
|
|
125
|
+
topics={{ options: ["Sales", "Support", "Partnerships"], required: true }}
|
|
126
|
+
consent="I agree to the privacy policy."
|
|
127
|
+
onSubmit={async (values) => {
|
|
128
|
+
const res = await sendContactMessage(values);
|
|
129
|
+
return res.ok ? { ok: true } : { ok: false, error: res.error };
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## What it will not do
|
|
137
|
+
|
|
138
|
+
- Send anything: `onSubmit` is yours (save a row, email the team).
|
|
139
|
+
- Stop spam: add a captcha or a honeypot in your own `onSubmit` path.
|
|
140
|
+
- Upload files, or take a card number.
|
|
141
|
+
- Draw a map: link the address (`href`) to one.
|
|
142
|
+
|
|
143
|
+
A section it cannot be is your own component in `components/`, built
|
|
144
|
+
from the kit — not an edit to this block. Its files are fixed: `npm run
|
|
145
|
+
check` refuses a change, and `makersclaw add contact-section` restores
|
|
146
|
+
them.
|
|
147
|
+
|
|
148
|
+
## Credits
|
|
149
|
+
|
|
150
|
+
Layouts ported from Creative Tim UI's contact-section blocks
|
|
151
|
+
(https://github.com/creativetimofficial/ui, MIT), rewritten on the
|
|
152
|
+
Makersclaw kit.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "contact-section",
|
|
3
|
+
"title": "Contact Section",
|
|
4
|
+
"description": "A public \"contact us\" section: a form (name, email, message; optional phone, company, subject, a topic as chips or radios, a consent box) and/or the ways to reach you (email, phone, address, hours, offices). The form alone, beside an info panel (plain or filled), or with info cards above or beside it; an optional picture beside or behind the form. Validates in place, submits through an async onSubmit that returns { ok }, and shows the failure or a sent state.",
|
|
5
|
+
"useWhen": "The contact page or contact section of a public site: sales enquiries, support requests, a studio's \"start a project\" form. Not for a signed-in user's support inbox or ticket thread, or a general-purpose record form (use a form of your own from the kit).",
|
|
6
|
+
"tags": ["contact", "contact us", "form", "enquiry", "support", "get in touch", "email", "phone", "address", "offices", "marketing", "landing page", "lead"],
|
|
7
|
+
"exports": ["ContactSection"],
|
|
8
|
+
"files": ["index.js", "contact-section.jsx"],
|
|
9
|
+
"requires": [],
|
|
10
|
+
"frame": "bleed"
|
|
11
|
+
}
|