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,245 @@
|
|
|
1
|
+
// The org chart's data and layout — plain functions, no React, no DOM.
|
|
2
|
+
// They run anywhere (the server, an agent's tool, a test).
|
|
3
|
+
//
|
|
4
|
+
// People come in flat, the way a table holds them: each row names its
|
|
5
|
+
// manager. buildOrg turns them into a tree; layoutOrg places the tree top
|
|
6
|
+
// down, managers centred over their reports, and a manager whose reports
|
|
7
|
+
// have no reports of their own gets them as a compact column (a wide row
|
|
8
|
+
// of twelve cards reads worse than a list).
|
|
9
|
+
|
|
10
|
+
/** Department (or any group) colours, in order: chart hues, which every
|
|
11
|
+
* theme derives from its own primary. As hue numbers for Legend/Badge. */
|
|
12
|
+
export const GROUP_HUES = [2, 3, 4, 5, 1];
|
|
13
|
+
|
|
14
|
+
export const CARD = { width: 248, height: 72 };
|
|
15
|
+
const GAP_X = 20; // between side-by-side teams
|
|
16
|
+
const GAP_Y = 52; // between a manager and the row of reports
|
|
17
|
+
const STACK_INDENT = 32; // a column of reports sits this far in
|
|
18
|
+
const STACK_GAP = 10;
|
|
19
|
+
const ROOT_GAP = 64; // between separate trees
|
|
20
|
+
/** A manager's reports stack as a column when there are at least this
|
|
21
|
+
* many and none of them manages anyone. */
|
|
22
|
+
export const STACK_FROM = 3;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Flat people → a tree. Returns { roots, byId }; each node is
|
|
26
|
+
* { id, person, parentId, depth, children, total } (total: everyone under
|
|
27
|
+
* them). Someone whose manager is missing, or whose chain of managers
|
|
28
|
+
* loops, becomes a root.
|
|
29
|
+
*
|
|
30
|
+
* managerKey the field naming the manager's id (default "managerId")
|
|
31
|
+
*/
|
|
32
|
+
export function buildOrg(people, { managerKey = "managerId" } = {}) {
|
|
33
|
+
const list = Array.isArray(people) ? people.filter((p) => p && p.id != null) : [];
|
|
34
|
+
const byId = new Map();
|
|
35
|
+
for (const p of list) {
|
|
36
|
+
const id = String(p.id);
|
|
37
|
+
if (!byId.has(id)) byId.set(id, { id, person: p, parentId: null, depth: 0, children: [], total: 0 });
|
|
38
|
+
}
|
|
39
|
+
const managerOf = (id) => {
|
|
40
|
+
const m = byId.get(id)?.person?.[managerKey];
|
|
41
|
+
return m != null && byId.has(String(m)) && String(m) !== id ? String(m) : null;
|
|
42
|
+
};
|
|
43
|
+
// A chain that comes back to itself: whoever closes the loop is a root.
|
|
44
|
+
const loops = new Set();
|
|
45
|
+
for (const id of byId.keys()) {
|
|
46
|
+
const seen = new Set([id]);
|
|
47
|
+
let cur = managerOf(id);
|
|
48
|
+
while (cur) {
|
|
49
|
+
if (seen.has(cur)) {
|
|
50
|
+
if (cur === id) loops.add(id);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
seen.add(cur);
|
|
54
|
+
cur = managerOf(cur);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const roots = [];
|
|
58
|
+
for (const n of byId.values()) {
|
|
59
|
+
const m = loops.has(n.id) ? null : managerOf(n.id);
|
|
60
|
+
if (m && !loops.has(n.id)) {
|
|
61
|
+
n.parentId = m;
|
|
62
|
+
byId.get(m).children.push(n);
|
|
63
|
+
} else roots.push(n);
|
|
64
|
+
}
|
|
65
|
+
// Anyone still unreached sits in a loop not broken above: a root too.
|
|
66
|
+
const reached = new Set();
|
|
67
|
+
const walk = (n, depth) => {
|
|
68
|
+
if (reached.has(n.id)) return 0;
|
|
69
|
+
reached.add(n.id);
|
|
70
|
+
n.depth = depth;
|
|
71
|
+
n.total = n.children.reduce((s, c) => s + 1 + walk(c, depth + 1), 0);
|
|
72
|
+
return n.total;
|
|
73
|
+
};
|
|
74
|
+
for (const r of roots) walk(r, 0);
|
|
75
|
+
for (const n of byId.values()) {
|
|
76
|
+
if (reached.has(n.id)) continue;
|
|
77
|
+
if (n.parentId) byId.get(n.parentId).children = byId.get(n.parentId).children.filter((c) => c.id !== n.id);
|
|
78
|
+
n.parentId = null;
|
|
79
|
+
roots.push(n);
|
|
80
|
+
walk(n, 0);
|
|
81
|
+
}
|
|
82
|
+
return { roots, byId };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** [root, …, the person's node] — their chain of managers, top first. */
|
|
86
|
+
export function chainOf(byId, id) {
|
|
87
|
+
const out = [];
|
|
88
|
+
let n = byId.get(String(id));
|
|
89
|
+
const seen = new Set();
|
|
90
|
+
while (n && !seen.has(n.id)) {
|
|
91
|
+
seen.add(n.id);
|
|
92
|
+
out.unshift(n);
|
|
93
|
+
n = n.parentId ? byId.get(n.parentId) : null;
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** The colour group of each value of `key` ("department"): the first
|
|
99
|
+
* seen gets the first hue. Map(value → hue number 1..5). */
|
|
100
|
+
export function groupHues(people, key) {
|
|
101
|
+
const out = new Map();
|
|
102
|
+
if (!key) return out;
|
|
103
|
+
for (const p of people ?? []) {
|
|
104
|
+
const v = typeof key === "function" ? key(p) : p?.[key];
|
|
105
|
+
if (v == null || v === "" || out.has(v)) continue;
|
|
106
|
+
out.set(v, GROUP_HUES[out.size % GROUP_HUES.length]);
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Rounded right-angle lines through points (a corner radius r).
|
|
112
|
+
export function elbowPath(points, r = 8) {
|
|
113
|
+
if (points.length < 2) return "";
|
|
114
|
+
let d = `M${points[0].x},${points[0].y}`;
|
|
115
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
116
|
+
const a = points[i - 1];
|
|
117
|
+
const b = points[i];
|
|
118
|
+
const c = points[i + 1];
|
|
119
|
+
const r1 = Math.min(r, Math.hypot(b.x - a.x, b.y - a.y) / 2, Math.hypot(c.x - b.x, c.y - b.y) / 2);
|
|
120
|
+
const u = { x: Math.sign(b.x - a.x), y: Math.sign(b.y - a.y) };
|
|
121
|
+
const v = { x: Math.sign(c.x - b.x), y: Math.sign(c.y - b.y) };
|
|
122
|
+
d += ` L${b.x - u.x * r1},${b.y - u.y * r1} Q${b.x},${b.y} ${b.x + v.x * r1},${b.y + v.y * r1}`;
|
|
123
|
+
}
|
|
124
|
+
const z = points[points.length - 1];
|
|
125
|
+
return `${d} L${z.x},${z.y}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Where every visible card goes. Top down; a manager centred over the
|
|
130
|
+
* cards of their reports; a folded manager's team hidden; separate trees
|
|
131
|
+
* side by side.
|
|
132
|
+
*
|
|
133
|
+
* collapsed(node) → true when the node's team is folded
|
|
134
|
+
* stack true (default): reports with no reports of their own
|
|
135
|
+
* become a column once there are STACK_FROM of them
|
|
136
|
+
*
|
|
137
|
+
* Returns { items, bounds }. Each item: { id, node, x, y, width, height,
|
|
138
|
+
* depth, parentId, folded, link } — `link` the line up to the manager, as
|
|
139
|
+
* points in board px ([] for a root).
|
|
140
|
+
*/
|
|
141
|
+
export function layoutOrg(roots, { collapsed = () => false, stack = true, card = CARD } = {}) {
|
|
142
|
+
const W = card.width;
|
|
143
|
+
const H = card.height;
|
|
144
|
+
const info = new Map();
|
|
145
|
+
const shown = (n) => (collapsed(n) ? [] : n.children);
|
|
146
|
+
const measure = (n) => {
|
|
147
|
+
const kids = shown(n);
|
|
148
|
+
let mode = "none";
|
|
149
|
+
let width = W;
|
|
150
|
+
if (kids.length) {
|
|
151
|
+
for (const k of kids) measure(k);
|
|
152
|
+
if (stack && kids.length >= STACK_FROM && kids.every((k) => !k.children.length)) {
|
|
153
|
+
mode = "stack";
|
|
154
|
+
width = STACK_INDENT + W;
|
|
155
|
+
} else {
|
|
156
|
+
mode = "row";
|
|
157
|
+
const total = kids.reduce((s, k) => s + info.get(k.id).width, 0) + GAP_X * (kids.length - 1);
|
|
158
|
+
width = Math.max(W, total);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
info.set(n.id, { mode, width });
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const items = [];
|
|
165
|
+
const place = (n, left, top, parent) => {
|
|
166
|
+
const { mode, width } = info.get(n.id);
|
|
167
|
+
const kids = shown(n);
|
|
168
|
+
const me = { id: n.id, node: n, x: left, y: top, width: W, height: H, depth: n.depth, parentId: parent?.id ?? null, folded: kids.length === 0 && n.children.length > 0, link: [] };
|
|
169
|
+
items.push(me);
|
|
170
|
+
if (mode === "none") {
|
|
171
|
+
me.x = left + (width - W) / 2;
|
|
172
|
+
return me;
|
|
173
|
+
}
|
|
174
|
+
if (mode === "stack") {
|
|
175
|
+
me.x = left;
|
|
176
|
+
let y = top + H + GAP_Y / 2 + 6;
|
|
177
|
+
const spine = me.x + STACK_INDENT / 2;
|
|
178
|
+
for (const k of kids) {
|
|
179
|
+
const c = place(k, left + STACK_INDENT, y, me);
|
|
180
|
+
c.link = [
|
|
181
|
+
{ x: spine, y: top + H },
|
|
182
|
+
{ x: spine, y: y + H / 2 },
|
|
183
|
+
{ x: c.x, y: y + H / 2 },
|
|
184
|
+
];
|
|
185
|
+
y += H + STACK_GAP;
|
|
186
|
+
}
|
|
187
|
+
return me;
|
|
188
|
+
}
|
|
189
|
+
const total = kids.reduce((s, k) => s + info.get(k.id).width, 0) + GAP_X * (kids.length - 1);
|
|
190
|
+
let x = left + (width - total) / 2;
|
|
191
|
+
const placed = [];
|
|
192
|
+
for (const k of kids) {
|
|
193
|
+
placed.push(place(k, x, top + H + GAP_Y, me));
|
|
194
|
+
x += info.get(k.id).width + GAP_X;
|
|
195
|
+
}
|
|
196
|
+
const a = placed[0].x + W / 2;
|
|
197
|
+
const b = placed[placed.length - 1].x + W / 2;
|
|
198
|
+
me.x = (a + b) / 2 - W / 2;
|
|
199
|
+
const mid = top + H + GAP_Y / 2;
|
|
200
|
+
for (const c of placed) {
|
|
201
|
+
c.link = [
|
|
202
|
+
{ x: me.x + W / 2, y: top + H },
|
|
203
|
+
{ x: me.x + W / 2, y: mid },
|
|
204
|
+
{ x: c.x + W / 2, y: mid },
|
|
205
|
+
{ x: c.x + W / 2, y: c.y },
|
|
206
|
+
];
|
|
207
|
+
// Straight down: two points are enough.
|
|
208
|
+
if (Math.abs(c.link[0].x - c.link[3].x) < 0.5) c.link = [c.link[0], c.link[3]];
|
|
209
|
+
}
|
|
210
|
+
return me;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
for (const r of roots) measure(r);
|
|
214
|
+
let x = 0;
|
|
215
|
+
for (const r of roots) {
|
|
216
|
+
place(r, x, 0, null);
|
|
217
|
+
x += info.get(r.id).width + ROOT_GAP;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
let x1 = Infinity;
|
|
221
|
+
let y1 = Infinity;
|
|
222
|
+
let x2 = -Infinity;
|
|
223
|
+
let y2 = -Infinity;
|
|
224
|
+
for (const it of items) {
|
|
225
|
+
x1 = Math.min(x1, it.x);
|
|
226
|
+
y1 = Math.min(y1, it.y);
|
|
227
|
+
x2 = Math.max(x2, it.x + it.width);
|
|
228
|
+
y2 = Math.max(y2, it.y + it.height);
|
|
229
|
+
}
|
|
230
|
+
return { items, bounds: items.length ? { x: x1, y: y1, width: x2 - x1, height: y2 - y1 } : { x: 0, y: 0, width: 0, height: 0 } };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** The org as plain text, one person a line, indented under their
|
|
234
|
+
* manager: "Maya Chen — VP Engineering (12)". For an agent or search. */
|
|
235
|
+
export function orgToText(people, opts) {
|
|
236
|
+
const { roots } = buildOrg(people, opts);
|
|
237
|
+
const out = [];
|
|
238
|
+
const walk = (n, depth) => {
|
|
239
|
+
const p = n.person;
|
|
240
|
+
out.push(`${" ".repeat(depth)}${depth ? "- " : ""}${p.name ?? n.id}${p.title ? ` — ${p.title}` : ""}${n.total ? ` (${n.total})` : ""}`);
|
|
241
|
+
for (const c of n.children) walk(c, depth + 1);
|
|
242
|
+
};
|
|
243
|
+
for (const r of roots) walk(r, 0);
|
|
244
|
+
return out.join("\n");
|
|
245
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// One person on the chart, as a FlowCanvas node type: a card (face, name,
|
|
4
|
+
// title, a strip in their group's colour), the line up to their manager
|
|
5
|
+
// (an SVG reaching outside the card, so the canvas needs no connectors),
|
|
6
|
+
// and — for a manager — the chip at the card's foot that folds the team
|
|
7
|
+
// and says how big it is.
|
|
8
|
+
//
|
|
9
|
+
// What the chart knows (the selection, the chain being lit, a drag in
|
|
10
|
+
// progress, what a click does) comes from OrgContext, which OrgChart
|
|
11
|
+
// provides around the canvas.
|
|
12
|
+
import { createContext, useContext } from "react";
|
|
13
|
+
import { Avatar, Icon, cx } from "../../ui";
|
|
14
|
+
import { elbowPath } from "./org";
|
|
15
|
+
|
|
16
|
+
export const OrgContext = createContext(null);
|
|
17
|
+
|
|
18
|
+
// Group hue → the strip's class, written out whole so Tailwind makes them.
|
|
19
|
+
const STRIP = { 1: "bg-chart-1", 2: "bg-chart-2", 3: "bg-chart-3", 4: "bg-chart-4", 5: "bg-chart-5" };
|
|
20
|
+
|
|
21
|
+
export function PersonNode({ id, data }) {
|
|
22
|
+
const o = useContext(OrgContext);
|
|
23
|
+
if (!o) return null;
|
|
24
|
+
const { name, title, avatar, hue, direct = 0, total = 0, folded = false, link, parentId } = data ?? {};
|
|
25
|
+
const selected = o.selectedId === id;
|
|
26
|
+
const lit = o.chain.has(id) && parentId && o.chain.has(parentId);
|
|
27
|
+
const isDrop = o.dropId === id;
|
|
28
|
+
const dragged = o.dragId === id;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div data-person={id} className="group/person relative size-full">
|
|
32
|
+
{link ? (
|
|
33
|
+
<svg aria-hidden="true" width="1" height="1" className="pointer-events-none absolute top-0 left-0 overflow-visible">
|
|
34
|
+
<path d={elbowPath(link)} className={cx("fill-none transition-[stroke] duration-150 motion-reduce:transition-none", lit ? "stroke-primary" : "stroke-border")} strokeWidth={lit ? 2 : 1.5} strokeLinecap="round" strokeLinejoin="round" />
|
|
35
|
+
</svg>
|
|
36
|
+
) : null}
|
|
37
|
+
{/* raw: the person's card on the canvas — it takes the pointer
|
|
38
|
+
(a click selects, a click on the selected card opens it, a drag
|
|
39
|
+
moves them to a new manager); the keys arrive through OrgChart's
|
|
40
|
+
handler on the canvas. */}
|
|
41
|
+
<div
|
|
42
|
+
className={cx(
|
|
43
|
+
"relative flex size-full items-center gap-3 overflow-hidden rounded-xl border border-border bg-card py-2 pr-3 pl-4 text-card-foreground shadow-xs",
|
|
44
|
+
"transition-[box-shadow,opacity,outline-color] duration-150 hover:shadow-md motion-reduce:transition-none",
|
|
45
|
+
o.coarse ? "" : "nopan",
|
|
46
|
+
o.draggable ? "cursor-grab" : "cursor-pointer",
|
|
47
|
+
selected && "ring-2 ring-primary ring-offset-2 ring-offset-background",
|
|
48
|
+
isDrop && "outline-2 outline-offset-4 outline-primary [outline-style:dashed]",
|
|
49
|
+
dragged && "opacity-40",
|
|
50
|
+
)}
|
|
51
|
+
onPointerDown={(e) => {
|
|
52
|
+
if (e.button === 0) o.onCardPointerDown(e, id);
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
{hue ? <span aria-hidden="true" className={cx("absolute inset-y-0 left-0 w-1", STRIP[hue])} /> : null}
|
|
56
|
+
<Avatar name={name} src={avatar} size="md" />
|
|
57
|
+
<div className="min-w-0 flex-1">
|
|
58
|
+
<p className="truncate text-sm font-medium" title={name}>
|
|
59
|
+
{name || "Unnamed"}
|
|
60
|
+
</p>
|
|
61
|
+
<p className="truncate text-xs text-muted-foreground" title={title}>
|
|
62
|
+
{title || " "}
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
{direct > 0 ? (
|
|
68
|
+
// raw: a 22px chip on the card's foot, smaller than any kit button
|
|
69
|
+
// — the canvas is zoomed out on a big org, and a 36px button would
|
|
70
|
+
// cover the line to the team. Out of the tab order: Space folds.
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
tabIndex={-1}
|
|
74
|
+
aria-label={`${folded ? "Show" : "Hide"} ${name}'s team: ${direct} direct, ${total} in all`}
|
|
75
|
+
title={`${direct} direct report${direct === 1 ? "" : "s"}${total > direct ? ` · ${total} in the team` : ""} — ${folded ? "show" : "hide"}`}
|
|
76
|
+
onMouseDown={(e) => e.preventDefault()}
|
|
77
|
+
onPointerDown={(e) => e.stopPropagation()}
|
|
78
|
+
onClick={(e) => {
|
|
79
|
+
e.stopPropagation();
|
|
80
|
+
o.toggle(id);
|
|
81
|
+
}}
|
|
82
|
+
className={cx(
|
|
83
|
+
"nodrag nopan absolute top-full left-1/2 z-10 flex h-[22px] -translate-x-1/2 -translate-y-1/2 items-center gap-0.5 rounded-full border px-2 text-[11px] leading-none font-medium tabular-nums shadow-xs",
|
|
84
|
+
"transition-colors duration-150 motion-reduce:transition-none",
|
|
85
|
+
folded ? "border-primary/50 bg-card text-foreground hover:bg-accent" : "border-border bg-card text-muted-foreground hover:text-foreground",
|
|
86
|
+
)}
|
|
87
|
+
>
|
|
88
|
+
{folded ? `+${total}` : direct}
|
|
89
|
+
<Icon name={folded ? "chevron-down" : "chevron-up"} size={12} />
|
|
90
|
+
</button>
|
|
91
|
+
) : null}
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const NODE_TYPES = { person: PersonNode };
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# PageBuilder
|
|
2
|
+
|
|
3
|
+
A visual page editor in the workspace theme, calm like Webflow's canvas
|
|
4
|
+
without its cockpit. The page sits in the middle at desktop, tablet or
|
|
5
|
+
phone width. On the left, **Add** lists blocks as small wireframes —
|
|
6
|
+
sections (hero, features, logos, quote, pricing, questions, call to action,
|
|
7
|
+
footer) and basics (heading, text, button, image, two columns, list,
|
|
8
|
+
divider, space). Click one to add it below the selection, or drag it onto
|
|
9
|
+
the page. **Layers** shows the page as a tree: select, fold, hide while
|
|
10
|
+
editing. On the right, **Design** changes the selected element's look,
|
|
11
|
+
limited to the theme's choices: text colour, background, text size,
|
|
12
|
+
weight, typeface, alignment, spacing, width, corners and border. It also
|
|
13
|
+
edits a link's address or a picture's source and description, and moves,
|
|
14
|
+
duplicates or deletes the element. The top bar has the save state, the
|
|
15
|
+
device toggle, undo and redo, Preview and Save. A new page opens on a
|
|
16
|
+
friendly empty state with starter templates. On a narrow screen the
|
|
17
|
+
panels move to a bottom bar and open as sheets.
|
|
18
|
+
|
|
19
|
+
It is [GrapesJS](https://github.com/GrapesJS/grapesjs) (BSD-3-Clause, the
|
|
20
|
+
free core — never the commercial Studio SDK) with its React wrapper
|
|
21
|
+
[@grapesjs/react](https://github.com/GrapesJS/react) (MIT). GrapesJS does
|
|
22
|
+
the page model, the canvas, selection, drag and drop, text editing, undo
|
|
23
|
+
and the export. The panels, the top bar, the empty state and the Design
|
|
24
|
+
choices are ours, built from the kit. GrapesJS's own panels, style manager,
|
|
25
|
+
trait manager, asset modal and code viewer are never created. The blocks
|
|
26
|
+
built on this one — `landing-builder` first — import it, never `grapesjs`
|
|
27
|
+
directly.
|
|
28
|
+
|
|
29
|
+
```jsx
|
|
30
|
+
import { PageBuilder, PageView } from "../components/blocks/page-builder"; // a Makersclaw app ("./blocks/page-builder" from components/)
|
|
31
|
+
import { PageBuilder, PageView } from "@/components/makersclaw/blocks/page-builder"; // a shadcn project
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`PageBuilder` is a client component: render it from a `"use client"`
|
|
35
|
+
component. `PageView` and the helpers (`pageDocument`, `cleanHtml`,
|
|
36
|
+
`cleanCss`, `isPageEmpty`, `projectSections`…) work on the server too.
|
|
37
|
+
|
|
38
|
+
`makersclaw add page-builder` adds `grapesjs` and `@grapesjs/react`
|
|
39
|
+
(pinned, exact) to package.json: run `npm install` after. They load with
|
|
40
|
+
the page, with no `import()`. The editor is created after the first render.
|
|
41
|
+
Until then, and on the server, the frame shows a skeleton.
|
|
42
|
+
|
|
43
|
+
## The data
|
|
44
|
+
|
|
45
|
+
The builder hands out a page as three things. You get it from `onSave`,
|
|
46
|
+
from `onChange`, and from the handle's `getPage()`:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
{
|
|
50
|
+
html: "<section class=\"pb-section pb-center\" …>…</section>…", // the body's content, cleaned
|
|
51
|
+
css: ".pb-section{padding:88px 24px;background-color:var(--color-background);…}#i4kd{…}",
|
|
52
|
+
project: { pages: [ … ], styles: [ … ], assets: [], … }, // GrapesJS project JSON
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- **Store `project`** (a `jsonb` column). It is what reopens the page for
|
|
57
|
+
editing: pass it back as `page={{ project }}`.
|
|
58
|
+
- **Show `html` + `css`** with `PageView`, or publish them. They are the
|
|
59
|
+
source of truth for what visitors see. They are derived from `project`
|
|
60
|
+
at save time, so store them next to it instead of recomputing them.
|
|
61
|
+
- `page={{ html, css }}` also opens, as a fresh project. This is how a
|
|
62
|
+
template, an import or an agent-written page starts.
|
|
63
|
+
- The HTML is cleaned: no `<script>`, no `on*` handlers, no `javascript:`
|
|
64
|
+
links. The CSS has no `body`, `html` or `*` rules. Only rules the page
|
|
65
|
+
uses are exported.
|
|
66
|
+
|
|
67
|
+
### Pages keep the theme
|
|
68
|
+
|
|
69
|
+
**A page never holds a colour. It names theme tokens, so it repaints when
|
|
70
|
+
the theme changes.** Every Design choice writes a CSS variable:
|
|
71
|
+
`var(--color-primary)`, `var(--color-muted-foreground)`,
|
|
72
|
+
`var(--theme-font-display)`, `var(--theme-radius)`. These are the same
|
|
73
|
+
variables the app's Tailwind utilities read. The built-in blocks' CSS
|
|
74
|
+
(`BASE_CSS`, `pb-` classes) uses them too. Sizes and spacing are plain
|
|
75
|
+
`rem`/`px` steps.
|
|
76
|
+
|
|
77
|
+
- **In the editor**, the canvas is an iframe that cannot see the app's
|
|
78
|
+
stylesheet. The builder resolves each token where it sits (its light or
|
|
79
|
+
dark scheme and any `[data-theme]` scope) and writes the values into the
|
|
80
|
+
frame. It does this again when the theme changes. It also copies the
|
|
81
|
+
app's `@font-face` rules, so the page uses the theme's typefaces.
|
|
82
|
+
- **In the app**, `PageView` shows the page. The tokens resolve to the
|
|
83
|
+
workspace theme. Tailwind emits a theme variable only when some source
|
|
84
|
+
names it, so this block names every token a page may use
|
|
85
|
+
(`KEEP_TOKENS`). Installing the block is enough.
|
|
86
|
+
- **Outside the app** (a download, a static host),
|
|
87
|
+
`standaloneDocument(page, { root })` returns a full HTML document with
|
|
88
|
+
the tokens resolved and inlined. `pageDocument(page, { tokens })` is the
|
|
89
|
+
same function for the server, if you pass it the `:root{…}` string
|
|
90
|
+
yourself.
|
|
91
|
+
|
|
92
|
+
## Props
|
|
93
|
+
|
|
94
|
+
| Prop | Default | |
|
|
95
|
+
| --- | --- | --- |
|
|
96
|
+
| `page` | empty | The page to open: `{ project }` or `{ html, css }`. Read once, when the editor is created. To open another page, change the component's `key` or call the handle's `setPage`. |
|
|
97
|
+
| `onSave` | — | `async (page) => ({ ok, error? })`. Called by Save and ⌘/Ctrl+S with `{ html, css, project }`. On `{ ok: false }`, the page stays unsaved and a toast shows your `error` with "Try again". The top bar says "Not saved". |
|
|
98
|
+
| `onChange` | — | `(page) => void`, 500 ms after the last edit. Use it for autosave or a live preview elsewhere. |
|
|
99
|
+
| `title` | `"Untitled page"` | The name in the top bar. |
|
|
100
|
+
| `blocks` | `[]` | Your own blocks, added after the built-ins. See "Your own sections". |
|
|
101
|
+
| `builtIns` | `true` | Which built-in blocks to offer: `true` (sections and basics), `"sections"`, `"basics"` or `false`. |
|
|
102
|
+
| `templates` | `STARTER_TEMPLATES` | Whole pages offered in the empty state and in "Start from a template". Pass `[]` for none. |
|
|
103
|
+
| `styles` | `STYLE_GROUPS` | The Design panel's choices. See "The Design choices". |
|
|
104
|
+
| `onUploadImage` | — | `async (file) => ({ ok, url, error? })`. When given, a picture's field gets an Upload button. Without it, people paste an address. |
|
|
105
|
+
| `actions` | — | Extra top-bar controls before Save, such as landing-builder's Publish. Use kit `Button`s at `size="sm"`. |
|
|
106
|
+
| `saveLabel` | `"Save"` | The Save button's words. |
|
|
107
|
+
| `builderRef` | — | A ref from `usePageBuilder()`. It receives the handle. |
|
|
108
|
+
| `height` | `720` | The builder's height: a number (px) or any CSS length (`"min(760px, 88dvh)"`). It fills its width. |
|
|
109
|
+
| `className` | — | Added to the frame. |
|
|
110
|
+
|
|
111
|
+
### The handle
|
|
112
|
+
|
|
113
|
+
```jsx
|
|
114
|
+
const builder = usePageBuilder();
|
|
115
|
+
<PageBuilder builderRef={builder} … />
|
|
116
|
+
builder.current?.getPage(); // { html, css, project }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`getPage()` · `save()` (runs `onSave`, returns its result) ·
|
|
120
|
+
`addBlock(id)` · `loadTemplate(idOrTemplate)` · `setPage({ html, css } |
|
|
121
|
+
{ project })` · `undo()` · `redo()` · `setDevice("desktop" | "tablet" |
|
|
122
|
+
"mobile")` · `preview(on = true)` · `editor` (the GrapesJS editor, for what
|
|
123
|
+
this block does not wrap; changes made through it are yours to keep
|
|
124
|
+
token-only).
|
|
125
|
+
|
|
126
|
+
## Your own sections
|
|
127
|
+
|
|
128
|
+
This is how `landing-builder` builds on this block. A block is plain data:
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
const HERO_WAITLIST = {
|
|
132
|
+
id: "hero-waitlist", // unique across built-ins and yours
|
|
133
|
+
label: "Waitlist hero", // the tile's name
|
|
134
|
+
category: "Hero", // the Add panel's group heading
|
|
135
|
+
thumb: "split", // a wireframe from THUMB_NAMES
|
|
136
|
+
description: "Headline, one line and an email button.", // the tile's tooltip
|
|
137
|
+
level: "section", // "section": added between top-level sections ·
|
|
138
|
+
// "element": added inside the selected box
|
|
139
|
+
// (default: "section" when category is "Sections")
|
|
140
|
+
html: `<section class="lb-hero" data-gjs-name="Waitlist hero">…</section>`,
|
|
141
|
+
css: `.lb-hero{padding:96px 24px;background-color:var(--color-muted);color:var(--color-foreground)}`,
|
|
142
|
+
};
|
|
143
|
+
<PageBuilder blocks={[HERO_WAITLIST]} builtIns="basics" templates={LANDING_TEMPLATES} />
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
- `html` is the markup, or use `content`, a GrapesJS component definition,
|
|
147
|
+
in its place. `data-gjs-name` names the element in Layers. Any
|
|
148
|
+
`data-gjs-*` attribute sets that GrapesJS property: for example,
|
|
149
|
+
`data-gjs-draggable="false"` or `data-gjs-removable="false"` lock a part.
|
|
150
|
+
- `css` is added to the page once, when the editor opens. **Name only
|
|
151
|
+
tokens for colour** (`var(--color-…)`, from `COLOR_TOKENS`) and
|
|
152
|
+
`--theme-font-*` / `--theme-radius` for faces and corners. Then your
|
|
153
|
+
sections repaint with the theme. Prefix your classes (`lb-`), and reuse
|
|
154
|
+
the built-in `pb-` classes (`pb-button`, `pb-h2`, `pb-lead`,
|
|
155
|
+
`pb-container`…) when they fit. Add an `@media (max-width: 768px)` rule
|
|
156
|
+
for the phone layout. The canvas's phone width is a real narrow frame,
|
|
157
|
+
so media queries work there.
|
|
158
|
+
- Several blocks may share one `css` string. The same rule added twice is
|
|
159
|
+
one rule.
|
|
160
|
+
|
|
161
|
+
A **template** is a whole page:
|
|
162
|
+
`{ id, label, description?, thumbs?: ["hero", "features", "cta"], html, css? }`
|
|
163
|
+
or `{ id, label, project }`. `thumbs` draws its card, up to four sections
|
|
164
|
+
tall. Picking a template replaces the page. A toast offers Undo when there
|
|
165
|
+
was something to replace.
|
|
166
|
+
|
|
167
|
+
`BlockThumb` and `PageThumb` draw the same wireframes elsewhere, for
|
|
168
|
+
example in a landing-builder gallery of templates.
|
|
169
|
+
|
|
170
|
+
## The Design choices
|
|
171
|
+
|
|
172
|
+
`STYLE_GROUPS` is a list of groups. Each group is one row of choices:
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
{
|
|
176
|
+
id: "fill", label: "Background", kind: "swatch" | "segmented" | "select",
|
|
177
|
+
for: ["link", "box"], // which elements show it: text · link · image · box (all if left out)
|
|
178
|
+
match: "background-color", // the property read back to show the current choice
|
|
179
|
+
options: [
|
|
180
|
+
{ value: "", label: "Default", css: { "background-color": "" } }, // "" = reset: the block's own CSS applies
|
|
181
|
+
{ value: "primary", label: "Primary", css: { "background-color": "var(--color-primary)" } },
|
|
182
|
+
],
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Picking an option writes its `css` onto that element only (an `#id`
|
|
187
|
+
rule). Any property another option of the group sets is cleared. "Reset"
|
|
188
|
+
beside a group removes the group's properties. "Clear this element's
|
|
189
|
+
style" removes all of them. To offer fewer or different choices, pass
|
|
190
|
+
your own list, filtered from or modelled on `STYLE_GROUPS`. A swatch
|
|
191
|
+
option's `value` is the token name it paints (`primary` →
|
|
192
|
+
`var(--color-primary)`). `groupsFor`, `currentOption` and `patchFor` are
|
|
193
|
+
the helpers the panel uses.
|
|
194
|
+
|
|
195
|
+
## Mouse, keyboard and touch
|
|
196
|
+
|
|
197
|
+
- Click an element to select it. Double-click text to edit the words
|
|
198
|
+
(bold, italic and link in the small toolbar). Double-click a picture to
|
|
199
|
+
jump to its field. Drag the selected element's handle to move it.
|
|
200
|
+
- ⌘/Ctrl+S saves. ⌘/Ctrl+Z undoes, ⇧⌘Z redoes. Backspace or Delete
|
|
201
|
+
removes the selection (with Undo in a toast when done from the panel).
|
|
202
|
+
Esc leaves Preview.
|
|
203
|
+
- The block tiles, the layer tree (↑ ↓ to move, ← → to fold), the swatches
|
|
204
|
+
(arrow keys) and every control are reachable by keyboard. A tile adds
|
|
205
|
+
on Enter.
|
|
206
|
+
- On a phone, tap a tile to add it. Dragging is for a mouse.
|
|
207
|
+
|
|
208
|
+
## Example
|
|
209
|
+
|
|
210
|
+
```jsx
|
|
211
|
+
"use client";
|
|
212
|
+
import { useState } from "react";
|
|
213
|
+
import { PageBuilder, PageView } from "../components/blocks/page-builder";
|
|
214
|
+
import { saveRow } from "../lib/db";
|
|
215
|
+
|
|
216
|
+
export function LandingEditor({ row }) {
|
|
217
|
+
return (
|
|
218
|
+
<PageBuilder
|
|
219
|
+
key={row.id}
|
|
220
|
+
title={row.title}
|
|
221
|
+
page={row.project ? { project: row.project } : { html: row.html, css: row.css }}
|
|
222
|
+
onSave={async ({ html, css, project }) => {
|
|
223
|
+
const res = await saveRow("pages", row.id, { html, css, project });
|
|
224
|
+
return res.ok ? { ok: true } : { ok: false, error: "The page was not saved. Check your connection and try again." };
|
|
225
|
+
}}
|
|
226
|
+
/>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// the public page, on the server:
|
|
231
|
+
export function LandingPage({ row }) {
|
|
232
|
+
return <PageView page={row} label={row.title} />;
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## What it will not do
|
|
237
|
+
|
|
238
|
+
- No live multiplayer. Two people editing the same page is last save wins.
|
|
239
|
+
- No free colour picker, hex field or arbitrary CSS. The Design panel
|
|
240
|
+
offers the theme's choices only, by design. A block's own `css` is where
|
|
241
|
+
a fixed design lives.
|
|
242
|
+
- Styles apply at every width. The canvas's device toggle previews the
|
|
243
|
+
page's own media queries. It does not keep per-device overrides.
|
|
244
|
+
- No forms that submit, and no scripts. The HTML is cleaned of them. A
|
|
245
|
+
signup form belongs to the app (a block beside `PageView`), not to the
|
|
246
|
+
page.
|
|
247
|
+
- No asset library. Pictures are an address, or an upload through
|
|
248
|
+
`onUploadImage`.
|
|
249
|
+
- No publishing, domains or SEO fields. Those belong to `landing-builder`
|
|
250
|
+
and the app.
|
|
251
|
+
|
|
252
|
+
## Credits
|
|
253
|
+
|
|
254
|
+
GrapesJS © Artur Arseniev, BSD-3-Clause. @grapesjs/react © Artur
|
|
255
|
+
Arseniev, MIT. Both are used unmodified, as npm dependencies. The block
|
|
256
|
+
ships none of their code. GrapesJS's stylesheet is imported from the
|
|
257
|
+
package and repainted with the workspace's tokens.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "page-builder",
|
|
3
|
+
"title": "PageBuilder",
|
|
4
|
+
"description": "A visual page editor (GrapesJS core) in the workspace theme: our own clean panels instead of GrapesJS's chrome — an Add panel of section and basic blocks (click or drag), a Layers tree, a Design panel limited to theme-token choices (colours, type, spacing, width, corners, borders), a device toggle (desktop, tablet, phone), undo/redo, preview, and a friendly empty state with starter templates. Pages style with CSS variables, so a saved page repaints with the theme. Saves out as { html, css, project }; PageView shows a saved page in an app.",
|
|
5
|
+
"useWhen": "A screen where someone builds or edits a web page visually: a landing page, a waitlist or launch page, a simple site section, an announcement page. landing-builder is built on it (section templates, publishing). Not for rich text in a document (doc-editor), an email body (newsletter-builder), a form of fields (record-form) or a freeform drawing (sketch-canvas).",
|
|
6
|
+
"tags": ["page builder", "website builder", "landing page", "grapesjs", "visual editor", "drag and drop", "sections", "templates", "wysiwyg", "html", "css", "no-code", "web page", "layers"],
|
|
7
|
+
"exports": ["PageBuilder", "usePageBuilder", "readPage", "DEVICES", "PageView", "standaloneDocument", "BlockThumb", "PageThumb", "THUMB_NAMES", "BASE_CSS", "SECTION_BLOCKS", "BASIC_BLOCKS", "STARTER_TEMPLATES", "STYLE_GROUPS", "COLOR_TOKENS", "groupsFor", "currentOption", "patchFor", "tokenCss", "fontFaceCss", "fontLinks", "PAGE_BASE_CSS", "emptyPage", "isPageEmpty", "cleanHtml", "cleanCss", "normalizeBlock", "templatePage", "pageDocument", "projectSections"],
|
|
8
|
+
"files": ["index.js", "page-builder.jsx", "panels.jsx", "page-view.jsx", "thumbs.jsx", "grapes.js", "theme.js", "tokens.js", "sections.js", "page.js"],
|
|
9
|
+
"requires": [],
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"grapesjs": "0.22.16",
|
|
12
|
+
"@grapesjs/react": "2.0.0"
|
|
13
|
+
}
|
|
14
|
+
}
|