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,645 @@
|
|
|
1
|
+
// The mind map's data and its layout — plain functions, no React, no DOM.
|
|
2
|
+
// They run anywhere (the server, an agent's tool, a test).
|
|
3
|
+
//
|
|
4
|
+
// A map is one tree of topics:
|
|
5
|
+
//
|
|
6
|
+
// { id: "root", text: "Launch plan", children: [
|
|
7
|
+
// { id: "a", text: "Research", side: "right", color: "chart-3", children: [...] },
|
|
8
|
+
// { id: "b", text: "Pricing", collapsed: true, children: [...] },
|
|
9
|
+
// ] }
|
|
10
|
+
//
|
|
11
|
+
// id any string, unique in the map
|
|
12
|
+
// text the words (a newline is allowed)
|
|
13
|
+
// children the subtopics, in order
|
|
14
|
+
// collapsed true: the branch is folded (its subtopics hidden)
|
|
15
|
+
// color a colour TOKEN ("chart-3"), the branch's hue; subtopics
|
|
16
|
+
// inherit it. Unset on a main branch: the next in the palette
|
|
17
|
+
// side "left" | "right", only on main branches (the root's
|
|
18
|
+
// children): which side of the centre it grows on. Unset:
|
|
19
|
+
// balanced by size
|
|
20
|
+
// note any extra text you keep with it (shown nowhere by the map)
|
|
21
|
+
//
|
|
22
|
+
// Every operation returns a NEW tree (the old one is left as it was), so
|
|
23
|
+
// a tree is safe to keep for undo.
|
|
24
|
+
|
|
25
|
+
/** The branch colours, in order: chart hues, which every theme derives
|
|
26
|
+
* from its own primary. The root wears the primary itself. */
|
|
27
|
+
export const BRANCH_COLORS = ["chart-2", "chart-3", "chart-4", "chart-5", "chart-1"];
|
|
28
|
+
|
|
29
|
+
let seq = 0;
|
|
30
|
+
/** A fresh topic id: `t-lx3k9f2a`. */
|
|
31
|
+
export function topicId() {
|
|
32
|
+
seq = (seq + 1) % 1296;
|
|
33
|
+
return `t-${Date.now().toString(36)}${seq.toString(36).padStart(2, "0")}${Math.floor(Math.random() * 1296)
|
|
34
|
+
.toString(36)
|
|
35
|
+
.padStart(2, "0")}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A new topic. */
|
|
39
|
+
export function createTopic(text = "", extra) {
|
|
40
|
+
return { id: topicId(), text, children: [], ...(extra ?? {}) };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const isObj = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Anything map-shaped → a clean tree: an object with `text`/`children`
|
|
47
|
+
* (also `title`/`label`/`name` for the words and `topics`/`items` for the
|
|
48
|
+
* children), an outline string (see outlineToMindMap), or nothing (a
|
|
49
|
+
* fresh map). Missing and repeated ids are made unique. Never throws.
|
|
50
|
+
*/
|
|
51
|
+
export function normalizeMap(value, { rootText = "Central topic" } = {}) {
|
|
52
|
+
if (typeof value === "string") return outlineToMindMap(value, { rootText });
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
const walk = (t, depth) => {
|
|
55
|
+
const text = typeof t?.text === "string" ? t.text : String(t?.title ?? t?.label ?? t?.name ?? "");
|
|
56
|
+
let id = t?.id != null && t.id !== "" ? String(t.id) : depth === 0 ? "root" : topicId();
|
|
57
|
+
while (seen.has(id)) id = topicId();
|
|
58
|
+
seen.add(id);
|
|
59
|
+
const kids = Array.isArray(t?.children) ? t.children : Array.isArray(t?.topics) ? t.topics : Array.isArray(t?.items) ? t.items : [];
|
|
60
|
+
const out = { ...t, id, text, children: kids.filter((k) => isObj(k) || typeof k === "string").map((k) => walk(typeof k === "string" ? { text: k } : k, depth + 1)) };
|
|
61
|
+
delete out.topics;
|
|
62
|
+
delete out.items;
|
|
63
|
+
if (depth !== 1) delete out.side;
|
|
64
|
+
else if (out.side !== "left" && out.side !== "right") delete out.side;
|
|
65
|
+
if (!out.collapsed) delete out.collapsed;
|
|
66
|
+
if (!out.color) delete out.color;
|
|
67
|
+
return out;
|
|
68
|
+
};
|
|
69
|
+
if (!isObj(value)) return { id: "root", text: rootText, children: [] };
|
|
70
|
+
return walk(value, 0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── reading ──────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
/** Every topic, depth first, with its parent and depth. */
|
|
76
|
+
export function flattenMap(root) {
|
|
77
|
+
const out = [];
|
|
78
|
+
const walk = (t, parent, depth, index) => {
|
|
79
|
+
out.push({ topic: t, parent, depth, index });
|
|
80
|
+
(t.children ?? []).forEach((c, i) => walk(c, t, depth + 1, i));
|
|
81
|
+
};
|
|
82
|
+
if (root) walk(root, null, 0, 0);
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The topic with this id, or null. */
|
|
87
|
+
export function findTopic(root, id) {
|
|
88
|
+
if (!root) return null;
|
|
89
|
+
if (root.id === id) return root;
|
|
90
|
+
for (const c of root.children ?? []) {
|
|
91
|
+
const hit = findTopic(c, id);
|
|
92
|
+
if (hit) return hit;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** [root, …, the topic] — the path down to it, or [] when it is not there. */
|
|
98
|
+
export function pathTo(root, id) {
|
|
99
|
+
if (!root) return [];
|
|
100
|
+
if (root.id === id) return [root];
|
|
101
|
+
for (const c of root.children ?? []) {
|
|
102
|
+
const p = pathTo(c, id);
|
|
103
|
+
if (p.length) return [root, ...p];
|
|
104
|
+
}
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The parent of a topic (null for the root or a stranger). */
|
|
109
|
+
export function parentOf(root, id) {
|
|
110
|
+
const p = pathTo(root, id);
|
|
111
|
+
return p.length > 1 ? p[p.length - 2] : null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** How many topics sit under this one, at every depth. */
|
|
115
|
+
export function countTopics(topic) {
|
|
116
|
+
let n = 0;
|
|
117
|
+
for (const c of topic?.children ?? []) n += 1 + countTopics(c);
|
|
118
|
+
return n;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Is `id` the topic `ancestor` or anywhere under it? */
|
|
122
|
+
export function isWithin(root, ancestorId, id) {
|
|
123
|
+
const a = findTopic(root, ancestorId);
|
|
124
|
+
return Boolean(a && findTopic(a, id));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ── changing ─────────────────────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
/** A copy of the tree with one topic replaced by fn(topic). */
|
|
130
|
+
export function mapTopic(root, id, fn) {
|
|
131
|
+
if (!root) return root;
|
|
132
|
+
if (root.id === id) return fn(root);
|
|
133
|
+
let changed = false;
|
|
134
|
+
const kids = (root.children ?? []).map((c) => {
|
|
135
|
+
const next = mapTopic(c, id, fn);
|
|
136
|
+
if (next !== c) changed = true;
|
|
137
|
+
return next;
|
|
138
|
+
});
|
|
139
|
+
return changed ? { ...root, children: kids } : root;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Merge a patch into one topic (`{ text }`, `{ color }`, `{ collapsed }`…). */
|
|
143
|
+
export function updateTopic(root, id, patch) {
|
|
144
|
+
return mapTopic(root, id, (t) => {
|
|
145
|
+
const next = { ...t, ...(typeof patch === "function" ? patch(t) : patch) };
|
|
146
|
+
for (const k of ["color", "collapsed", "side", "note"]) if (next[k] === undefined || next[k] === false || next[k] === "") delete next[k];
|
|
147
|
+
return next;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Main branches keep the side they are on once the map changes around
|
|
152
|
+
// them, so adding one never flips the others across the centre.
|
|
153
|
+
function pinSides(root) {
|
|
154
|
+
const kids = root.children ?? [];
|
|
155
|
+
if (kids.every((c) => c.side)) return root;
|
|
156
|
+
const sides = splitSides(root);
|
|
157
|
+
return { ...root, children: kids.map((c) => (c.side ? c : { ...c, side: sides.get(c.id) })) };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Put `topic` under `parentId` at `index` (default: last). A new main
|
|
161
|
+
* branch goes on the lighter side unless it names one. */
|
|
162
|
+
export function insertTopic(root, parentId, topic, index) {
|
|
163
|
+
const t = topic ?? createTopic();
|
|
164
|
+
if (parentId === root.id) {
|
|
165
|
+
const pinned = pinSides(root);
|
|
166
|
+
const kids = [...(pinned.children ?? [])];
|
|
167
|
+
let side = t.side;
|
|
168
|
+
if (!side) {
|
|
169
|
+
const l = kids.filter((c) => c.side === "left").reduce((n, c) => n + 1 + visibleCount(c), 0);
|
|
170
|
+
const r = kids.filter((c) => c.side !== "left").reduce((n, c) => n + 1 + visibleCount(c), 0);
|
|
171
|
+
side = l < r ? "left" : "right";
|
|
172
|
+
}
|
|
173
|
+
const at = index === undefined ? kids.length : Math.max(0, Math.min(kids.length, index));
|
|
174
|
+
kids.splice(at, 0, { ...t, side });
|
|
175
|
+
return { ...pinned, children: kids };
|
|
176
|
+
}
|
|
177
|
+
return mapTopic(root, parentId, (p) => {
|
|
178
|
+
const kids = [...(p.children ?? [])];
|
|
179
|
+
const { side: _s, ...rest } = t;
|
|
180
|
+
const at = index === undefined ? kids.length : Math.max(0, Math.min(kids.length, index));
|
|
181
|
+
kids.splice(at, 0, rest);
|
|
182
|
+
const next = { ...p, children: kids };
|
|
183
|
+
delete next.collapsed;
|
|
184
|
+
return next;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function visibleCount(t) {
|
|
189
|
+
if (t.collapsed) return 0;
|
|
190
|
+
let n = 0;
|
|
191
|
+
for (const c of t.children ?? []) n += 1 + visibleCount(c);
|
|
192
|
+
return n;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** A new topic next to `id` (after it, or before with `before`). On the
|
|
196
|
+
* root there is no next to: it becomes a child. */
|
|
197
|
+
export function insertSibling(root, id, topic, { before = false } = {}) {
|
|
198
|
+
const parent = parentOf(root, id);
|
|
199
|
+
if (!parent) return insertTopic(root, root.id, topic);
|
|
200
|
+
const i = parent.children.findIndex((c) => c.id === id);
|
|
201
|
+
const me = parent.children[i];
|
|
202
|
+
const t = parent.id === root.id && me?.side ? { ...topic, side: topic.side ?? me.side } : topic;
|
|
203
|
+
return insertTopic(root, parent.id, t, before ? i : i + 1);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Take a topic (and its branch) out. The root stays. */
|
|
207
|
+
export function removeTopic(root, id) {
|
|
208
|
+
if (!root || root.id === id) return root;
|
|
209
|
+
const parent = parentOf(root, id);
|
|
210
|
+
if (!parent) return root;
|
|
211
|
+
return mapTopic(root, parent.id, (p) => ({ ...p, children: p.children.filter((c) => c.id !== id) }));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Move a topic (with its branch) under `parentId` at `index` (default
|
|
215
|
+
* last). Refused (the same tree back) into its own branch. */
|
|
216
|
+
export function moveTopic(root, id, parentId, index) {
|
|
217
|
+
if (id === root.id || isWithin(root, id, parentId)) return root;
|
|
218
|
+
const t = findTopic(root, id);
|
|
219
|
+
if (!t) return root;
|
|
220
|
+
const from = parentOf(root, id);
|
|
221
|
+
let at = index;
|
|
222
|
+
if (from?.id === parentId && at !== undefined) {
|
|
223
|
+
const was = from.children.findIndex((c) => c.id === id);
|
|
224
|
+
if (was < at) at -= 1;
|
|
225
|
+
}
|
|
226
|
+
const without = removeTopic(root, id);
|
|
227
|
+
const moved = { ...t };
|
|
228
|
+
if (parentId !== root.id) delete moved.side;
|
|
229
|
+
else if (from?.id !== root.id) delete moved.side;
|
|
230
|
+
return insertTopic(without, parentId, moved, at);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Swap a topic with its neighbour: `delta` -1 (up) or +1 (down). A main
|
|
234
|
+
* branch trades places with the next one on its own side. */
|
|
235
|
+
export function shiftTopic(root, id, delta) {
|
|
236
|
+
const parent = parentOf(root, id);
|
|
237
|
+
if (!parent) return root;
|
|
238
|
+
const base = parent.id === root.id ? pinSides(root) : parent;
|
|
239
|
+
const kids = base.children;
|
|
240
|
+
const i = kids.findIndex((c) => c.id === id);
|
|
241
|
+
const sameSide = (c) => parent.id !== root.id || (c.side ?? "right") === (kids[i].side ?? "right");
|
|
242
|
+
let j = i + delta;
|
|
243
|
+
while (j >= 0 && j < kids.length && !sameSide(kids[j])) j += delta;
|
|
244
|
+
if (j < 0 || j >= kids.length) return root;
|
|
245
|
+
const next = [...kids];
|
|
246
|
+
[next[i], next[j]] = [next[j], next[i]];
|
|
247
|
+
if (parent.id === root.id) return { ...base, children: next };
|
|
248
|
+
return mapTopic(root, parent.id, (p) => ({ ...p, children: next }));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Tab on an outline: the topic becomes the last child of the topic
|
|
252
|
+
* before it. Nothing before it: the same tree back. */
|
|
253
|
+
export function indentTopic(root, id) {
|
|
254
|
+
const parent = parentOf(root, id);
|
|
255
|
+
if (!parent) return root;
|
|
256
|
+
const kids = parent.id === root.id ? pinSides(root).children : parent.children;
|
|
257
|
+
const i = kids.findIndex((c) => c.id === id);
|
|
258
|
+
const me = kids[i];
|
|
259
|
+
let j = i - 1;
|
|
260
|
+
if (parent.id === root.id) while (j >= 0 && (kids[j].side ?? "right") !== (me.side ?? "right")) j -= 1;
|
|
261
|
+
if (j < 0) return root;
|
|
262
|
+
return moveTopic(root, id, kids[j].id);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Shift+Tab: the topic moves up a level, to just after its parent. */
|
|
266
|
+
export function outdentTopic(root0, id) {
|
|
267
|
+
const root = pinSides(root0);
|
|
268
|
+
const path = pathTo(root, id);
|
|
269
|
+
if (path.length < 3) return root0;
|
|
270
|
+
const parent = path[path.length - 2];
|
|
271
|
+
const grand = path[path.length - 3];
|
|
272
|
+
const at = grand.children.findIndex((c) => c.id === parent.id) + 1;
|
|
273
|
+
const t = findTopic(root, id);
|
|
274
|
+
const moved = grand.id === root.id ? { ...t, side: parent.side } : t;
|
|
275
|
+
const without = removeTopic(root, id);
|
|
276
|
+
return insertTopic(without, grand.id, moved, at);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** A copy of a branch with fresh ids, placed right after it. */
|
|
280
|
+
export function duplicateTopic(root, id) {
|
|
281
|
+
const t = findTopic(root, id);
|
|
282
|
+
if (!t || id === root.id) return { root, id: null };
|
|
283
|
+
const copy = (x) => ({ ...x, id: topicId(), children: (x.children ?? []).map(copy) });
|
|
284
|
+
const c = copy(t);
|
|
285
|
+
return { root: insertSibling(root, id, c), id: c.id };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Fold (or unfold) every branch that has subtopics, the root aside. */
|
|
289
|
+
export function setAllCollapsed(root, collapsed) {
|
|
290
|
+
const walk = (t, depth) => {
|
|
291
|
+
const kids = (t.children ?? []).map((c) => walk(c, depth + 1));
|
|
292
|
+
const next = { ...t, children: kids };
|
|
293
|
+
if (depth > 0 && collapsed && kids.length) next.collapsed = true;
|
|
294
|
+
else delete next.collapsed;
|
|
295
|
+
return next;
|
|
296
|
+
};
|
|
297
|
+
return walk(root, 0);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// ── outline in, outline out ──────────────────────────────────────────────
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* An indented outline → topics (a forest: an array of top-level topics).
|
|
304
|
+
* Bullets (-, *, •, 1.), markdown headings (# is the top), tabs or spaces;
|
|
305
|
+
* blank lines skipped. What an agent writes, or a list pasted from notes.
|
|
306
|
+
*/
|
|
307
|
+
export function outlineToTopics(text) {
|
|
308
|
+
const lines = String(text ?? "")
|
|
309
|
+
.replace(/\r\n?/g, "\n")
|
|
310
|
+
.split("\n")
|
|
311
|
+
.filter((l) => l.trim());
|
|
312
|
+
if (!lines.length) return [];
|
|
313
|
+
const rows = lines.map((l) => {
|
|
314
|
+
const heading = /^\s*(#{1,6})\s+(.*)$/.exec(l);
|
|
315
|
+
if (heading) return { level: heading[1].length - 7, text: heading[2].trim() };
|
|
316
|
+
const lead = /^[\t ]*/.exec(l)[0].replace(/\t/g, " ").length;
|
|
317
|
+
const body = l.trim().replace(/^(?:[-*+•]|\d+[.)])\s+/, "").replace(/^\[[ xX]\]\s+/, "");
|
|
318
|
+
return { level: lead, text: body.trim() };
|
|
319
|
+
});
|
|
320
|
+
// Headings sit above every indented line; indents rank by their width.
|
|
321
|
+
const levels = [...new Set(rows.map((r) => r.level))].sort((a, b) => a - b);
|
|
322
|
+
const rank = new Map(levels.map((l, i) => [l, i]));
|
|
323
|
+
const forest = [];
|
|
324
|
+
const stack = [];
|
|
325
|
+
for (const r of rows) {
|
|
326
|
+
const depth = rank.get(r.level);
|
|
327
|
+
const t = createTopic(r.text);
|
|
328
|
+
while (stack.length && stack[stack.length - 1].depth >= depth) stack.pop();
|
|
329
|
+
if (stack.length) stack[stack.length - 1].topic.children.push(t);
|
|
330
|
+
else forest.push(t);
|
|
331
|
+
stack.push({ depth, topic: t });
|
|
332
|
+
}
|
|
333
|
+
return forest;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** An outline → a map. One top line: it is the centre. Several: they
|
|
337
|
+
* hang off a centre called `rootText`. */
|
|
338
|
+
export function outlineToMindMap(text, { rootText = "Central topic" } = {}) {
|
|
339
|
+
const forest = outlineToTopics(text);
|
|
340
|
+
if (forest.length === 1) return { ...forest[0], id: "root" };
|
|
341
|
+
return { id: "root", text: rootText, children: forest };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** The map as an indented outline, two spaces a level — for an agent, a
|
|
345
|
+
* clipboard, a search column. Folded branches are included. */
|
|
346
|
+
export function mindMapToText(topic) {
|
|
347
|
+
const out = [];
|
|
348
|
+
const walk = (t, depth) => {
|
|
349
|
+
out.push(`${" ".repeat(depth)}${depth ? "- " : ""}${String(t.text ?? "").replace(/\n/g, " ") || "Untitled"}`);
|
|
350
|
+
for (const c of t.children ?? []) walk(c, depth + 1);
|
|
351
|
+
};
|
|
352
|
+
if (topic) walk(topic, 0);
|
|
353
|
+
return out.join("\n");
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** The map as Markdown: the centre as a heading, the branches as a
|
|
357
|
+
* nested list. */
|
|
358
|
+
export function mindMapToMarkdown(root) {
|
|
359
|
+
if (!root) return "";
|
|
360
|
+
const lines = [`# ${String(root.text ?? "").replace(/\n/g, " ") || "Untitled"}`, ""];
|
|
361
|
+
const walk = (t, depth) => {
|
|
362
|
+
lines.push(`${" ".repeat(depth)}- ${String(t.text ?? "").replace(/\n/g, " ") || "Untitled"}`);
|
|
363
|
+
for (const c of t.children ?? []) walk(c, depth + 1);
|
|
364
|
+
};
|
|
365
|
+
for (const c of root.children ?? []) walk(c, 0);
|
|
366
|
+
return lines.join("\n");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// ── layout ───────────────────────────────────────────────────────────────
|
|
370
|
+
|
|
371
|
+
// Type and box per level, in px. The node draws with exactly these, so
|
|
372
|
+
// what is laid out is what is shown. level 0 = the centre, 1 = a main
|
|
373
|
+
// branch (a tinted pill), 2+ = a subtopic (words over a coloured line).
|
|
374
|
+
export const LEVELS = [
|
|
375
|
+
{ font: 18, weight: 600, line: 26, padX: 20, padY: 12, min: 120, max: 280, gap: 56 },
|
|
376
|
+
{ font: 14, weight: 500, line: 20, padX: 14, padY: 8, min: 64, max: 220, gap: 36 },
|
|
377
|
+
{ font: 14, weight: 400, line: 20, padX: 6, padY: 5, min: 44, max: 240, gap: 28 },
|
|
378
|
+
];
|
|
379
|
+
export const levelOf = (depth) => LEVELS[Math.min(depth, LEVELS.length - 1)];
|
|
380
|
+
const SIBLING_GAP = [0, 20, 8];
|
|
381
|
+
const siblingGap = (depth) => SIBLING_GAP[Math.min(depth, SIBLING_GAP.length - 1)];
|
|
382
|
+
/** Room left under a subtopic for its coloured line. */
|
|
383
|
+
export const UNDERLINE = 2;
|
|
384
|
+
|
|
385
|
+
/** A width guess without a DOM: average glyph widths for a UI sans. */
|
|
386
|
+
export function estimateText(text, { font = 14, weight = 400 } = {}) {
|
|
387
|
+
let w = 0;
|
|
388
|
+
for (const ch of String(text ?? "")) w += /[A-Z]/.test(ch) ? 0.66 : /[mwMW]/.test(ch) ? 0.8 : /[ilj.,:;'!|]/.test(ch) ? 0.28 : ch === " " ? 0.28 : 0.54;
|
|
389
|
+
return w * font * (weight >= 600 ? 1.05 : weight >= 500 ? 1.02 : 1);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/** Words wrapped at `max` px → { width, lines }. */
|
|
393
|
+
export function wrapText(text, max, measure, style) {
|
|
394
|
+
const paras = String(text ?? "").split("\n");
|
|
395
|
+
let width = 0;
|
|
396
|
+
let lines = 0;
|
|
397
|
+
const space = measure(" ", style);
|
|
398
|
+
for (const para of paras) {
|
|
399
|
+
const words = para.split(/\s+/).filter(Boolean);
|
|
400
|
+
if (!words.length) {
|
|
401
|
+
lines += 1;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
let line = 0;
|
|
405
|
+
for (const w of words) {
|
|
406
|
+
const ww = measure(w, style);
|
|
407
|
+
if (line && line + space + ww > max) {
|
|
408
|
+
width = Math.max(width, line);
|
|
409
|
+
lines += 1;
|
|
410
|
+
line = 0;
|
|
411
|
+
}
|
|
412
|
+
if (ww > max) {
|
|
413
|
+
// One word longer than the line: it breaks where it must.
|
|
414
|
+
const extra = Math.floor(ww / max);
|
|
415
|
+
lines += extra;
|
|
416
|
+
width = max;
|
|
417
|
+
line = ww - extra * max;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
line = line ? line + space + ww : ww;
|
|
421
|
+
}
|
|
422
|
+
width = Math.max(width, line);
|
|
423
|
+
lines += 1;
|
|
424
|
+
}
|
|
425
|
+
return { width: Math.min(max, width), lines: Math.max(1, lines) };
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/** The box a topic needs at a depth: { width, height }. `placeholder`
|
|
429
|
+
* sizes an empty topic. */
|
|
430
|
+
export function topicSize(text, depth, measure = estimateText, placeholder = "New topic") {
|
|
431
|
+
const L = levelOf(depth);
|
|
432
|
+
const style = { font: L.font, weight: L.weight };
|
|
433
|
+
const words = String(text ?? "").trim() ? text : placeholder;
|
|
434
|
+
const { width, lines } = wrapText(words, L.max - L.padX * 2, measure, style);
|
|
435
|
+
// +2: a browser wraps a hair sooner than the sum of the words' widths.
|
|
436
|
+
const w = Math.max(L.min, Math.ceil(width + 2) + L.padX * 2);
|
|
437
|
+
const h = lines * L.line + L.padY * 2 + (depth >= 2 ? UNDERLINE : 0);
|
|
438
|
+
return { width: w, height: h };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/** Which side each main branch grows on: its own `side`, else split in
|
|
442
|
+
* order so the two sides hold about as many rows. Counted in topics, not
|
|
443
|
+
* pixels, so the answer never depends on the font. Map(id → side). */
|
|
444
|
+
export function splitSides(root) {
|
|
445
|
+
const kids = root?.children ?? [];
|
|
446
|
+
const rows = (t) => (t.collapsed || !t.children?.length ? 1 : t.children.reduce((n, c) => n + rows(c), 0));
|
|
447
|
+
const w = kids.map(rows);
|
|
448
|
+
const out = new Map();
|
|
449
|
+
let L = 0;
|
|
450
|
+
let R = 0;
|
|
451
|
+
const free = [];
|
|
452
|
+
kids.forEach((c, i) => {
|
|
453
|
+
if (c.side === "left") (L += w[i]), out.set(c.id, "left");
|
|
454
|
+
else if (c.side === "right") (R += w[i]), out.set(c.id, "right");
|
|
455
|
+
else free.push(i);
|
|
456
|
+
});
|
|
457
|
+
// The first k free branches go right, the rest left: the k that leaves
|
|
458
|
+
// the two sides closest wins (a tie: more on the right).
|
|
459
|
+
let best = 0;
|
|
460
|
+
let bestDiff = Infinity;
|
|
461
|
+
const total = free.reduce((n, i) => n + w[i], 0);
|
|
462
|
+
let acc = 0;
|
|
463
|
+
for (let k = 0; k <= free.length; k++) {
|
|
464
|
+
const diff = Math.abs(R + acc - (L + total - acc));
|
|
465
|
+
if (diff <= bestDiff) {
|
|
466
|
+
bestDiff = diff;
|
|
467
|
+
best = k;
|
|
468
|
+
}
|
|
469
|
+
if (k < free.length) acc += w[free[k]];
|
|
470
|
+
}
|
|
471
|
+
free.forEach((i, n) => out.set(kids[i].id, n < best ? "right" : "left"));
|
|
472
|
+
return out;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Where every visible topic goes. The centre at (0, 0); main branches
|
|
477
|
+
* on both sides, balanced; each branch a tidy tree growing outwards, a
|
|
478
|
+
* topic centred on its subtopics. Folded branches stop at the fold.
|
|
479
|
+
*
|
|
480
|
+
* measure(text, { font, weight }) → px (default: estimateText)
|
|
481
|
+
* colors the branch palette (default BRANCH_COLORS)
|
|
482
|
+
*
|
|
483
|
+
* Returns { items, bounds }. Each item: { id, topic, parentId, depth,
|
|
484
|
+
* side ("root" | "left" | "right"), color, x, y, width, height (top-left
|
|
485
|
+
* box), hidden (topics folded away under it), from / to (where the line
|
|
486
|
+
* from the parent leaves and arrives, board px) }.
|
|
487
|
+
*/
|
|
488
|
+
export function layoutMindMap(root, { measure = estimateText, colors = BRANCH_COLORS } = {}) {
|
|
489
|
+
if (!root) return { items: [], bounds: { x: 0, y: 0, width: 0, height: 0 } };
|
|
490
|
+
const sizes = new Map();
|
|
491
|
+
const sizeOf = (t, depth) => {
|
|
492
|
+
const k = t.id;
|
|
493
|
+
if (!sizes.has(k)) sizes.set(k, topicSize(t.text, depth, measure));
|
|
494
|
+
return sizes.get(k);
|
|
495
|
+
};
|
|
496
|
+
const block = new Map();
|
|
497
|
+
const blockOf = (t, depth) => {
|
|
498
|
+
if (block.has(t.id)) return block.get(t.id);
|
|
499
|
+
const own = sizeOf(t, depth).height;
|
|
500
|
+
let h = own;
|
|
501
|
+
if (!t.collapsed && t.children?.length) {
|
|
502
|
+
const sum = t.children.reduce((n, c) => n + blockOf(c, depth + 1), 0) + siblingGap(depth + 1) * (t.children.length - 1);
|
|
503
|
+
h = Math.max(own, sum);
|
|
504
|
+
}
|
|
505
|
+
block.set(t.id, h);
|
|
506
|
+
return h;
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
const items = [];
|
|
510
|
+
const rs = sizeOf(root, 0);
|
|
511
|
+
const rootItem = { id: root.id, topic: root, parentId: null, depth: 0, side: "root", color: null, x: -rs.width / 2, y: -rs.height / 2, width: rs.width, height: rs.height, hidden: root.collapsed ? countTopics(root) : 0 };
|
|
512
|
+
items.push(rootItem);
|
|
513
|
+
|
|
514
|
+
// Where a line leaves a topic towards its children on `side`, and where
|
|
515
|
+
// a line arrives at it.
|
|
516
|
+
const outAnchor = (it, side) => {
|
|
517
|
+
const dir = side === "left" ? -1 : 1;
|
|
518
|
+
const x = dir > 0 ? it.x + it.width : it.x;
|
|
519
|
+
const y = it.depth >= 2 ? it.y + it.height - UNDERLINE / 2 : it.y + it.height / 2;
|
|
520
|
+
return { x, y, dir };
|
|
521
|
+
};
|
|
522
|
+
const inAnchor = (it) => {
|
|
523
|
+
const x = it.side === "left" ? it.x + it.width : it.x;
|
|
524
|
+
const y = it.depth >= 2 ? it.y + it.height - UNDERLINE / 2 : it.y + it.height / 2;
|
|
525
|
+
return { x, y };
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const place = (t, parentItem, depth, side, top, color) => {
|
|
529
|
+
const s = sizeOf(t, depth);
|
|
530
|
+
const b = blockOf(t, depth);
|
|
531
|
+
const from = outAnchor(parentItem, side);
|
|
532
|
+
const gap = levelOf(depth - 1).gap;
|
|
533
|
+
const cy = top + b / 2;
|
|
534
|
+
const x = side === "left" ? from.x - gap - s.width : from.x + gap;
|
|
535
|
+
// A subtopic's line is its foot: centre the words so the line sits
|
|
536
|
+
// at the middle of its children.
|
|
537
|
+
const y = cy - s.height / 2;
|
|
538
|
+
const it = { id: t.id, topic: t, parentId: parentItem.id, depth, side, color, x, y, width: s.width, height: s.height, hidden: t.collapsed ? countTopics(t) : 0 };
|
|
539
|
+
it.from = { x: from.x, y: from.y };
|
|
540
|
+
it.to = inAnchor(it);
|
|
541
|
+
items.push(it);
|
|
542
|
+
if (!t.collapsed && t.children?.length) {
|
|
543
|
+
const sum = t.children.reduce((n, c) => n + blockOf(c, depth + 1), 0) + siblingGap(depth + 1) * (t.children.length - 1);
|
|
544
|
+
let y2 = cy - sum / 2;
|
|
545
|
+
for (const c of t.children) {
|
|
546
|
+
place(c, it, depth + 1, side, y2, c.color ?? color);
|
|
547
|
+
y2 += blockOf(c, depth + 1) + siblingGap(depth + 1);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
if (!root.collapsed) {
|
|
553
|
+
const sides = splitSides(root);
|
|
554
|
+
const kids = root.children ?? [];
|
|
555
|
+
for (const side of ["right", "left"]) {
|
|
556
|
+
const mine = kids.map((c, i) => ({ c, i })).filter(({ c }) => sides.get(c.id) === side);
|
|
557
|
+
if (!mine.length) continue;
|
|
558
|
+
const sum = mine.reduce((n, { c }) => n + blockOf(c, 1), 0) + siblingGap(1) * (mine.length - 1);
|
|
559
|
+
let y = -sum / 2;
|
|
560
|
+
for (const { c, i } of mine) {
|
|
561
|
+
place(c, rootItem, 1, side, y, c.color ?? colors[i % colors.length]);
|
|
562
|
+
y += blockOf(c, 1) + siblingGap(1);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
let x1 = Infinity;
|
|
568
|
+
let y1 = Infinity;
|
|
569
|
+
let x2 = -Infinity;
|
|
570
|
+
let y2 = -Infinity;
|
|
571
|
+
for (const it of items) {
|
|
572
|
+
x1 = Math.min(x1, it.x);
|
|
573
|
+
y1 = Math.min(y1, it.y);
|
|
574
|
+
x2 = Math.max(x2, it.x + it.width);
|
|
575
|
+
y2 = Math.max(y2, it.y + it.height);
|
|
576
|
+
}
|
|
577
|
+
return { items, bounds: { x: x1, y: y1, width: x2 - x1, height: y2 - y1 } };
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/** The map as a FlowCanvas board: one `topic` node per visible topic,
|
|
581
|
+
* laid out (layoutMindMap), no connectors (each topic draws the line to
|
|
582
|
+
* its parent). What MindMap hands the canvas. */
|
|
583
|
+
export function mindMapToBoard(root, opts) {
|
|
584
|
+
const { items } = layoutMindMap(root, opts);
|
|
585
|
+
const round = (n) => Math.round(n * 100) / 100;
|
|
586
|
+
return {
|
|
587
|
+
nodes: items.map((it) => ({
|
|
588
|
+
id: it.id,
|
|
589
|
+
type: "topic",
|
|
590
|
+
position: { x: round(it.x), y: round(it.y) },
|
|
591
|
+
width: Math.round(it.width),
|
|
592
|
+
height: Math.round(it.height),
|
|
593
|
+
draggable: false,
|
|
594
|
+
connectable: false,
|
|
595
|
+
data: {
|
|
596
|
+
text: it.topic.text,
|
|
597
|
+
depth: it.depth,
|
|
598
|
+
side: it.side,
|
|
599
|
+
color: it.color,
|
|
600
|
+
kids: it.topic.children?.length ?? 0,
|
|
601
|
+
collapsed: Boolean(it.topic.collapsed),
|
|
602
|
+
hidden: it.hidden,
|
|
603
|
+
link: it.from ? { x1: round(it.from.x - it.x), y1: round(it.from.y - it.y), x2: round(it.to.x - it.x), y2: round(it.to.y - it.y) } : null,
|
|
604
|
+
},
|
|
605
|
+
})),
|
|
606
|
+
edges: [],
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/** The curve from a parent to a child, in the child's own coordinates. */
|
|
611
|
+
export function branchPath({ x1, y1, x2, y2 }) {
|
|
612
|
+
const dx = (x2 - x1) * 0.55;
|
|
613
|
+
return `M${x1},${y1} C${x1 + dx},${y1} ${x2 - dx},${y2} ${x2},${y2}`;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// ── starters ─────────────────────────────────────────────────────────────
|
|
617
|
+
|
|
618
|
+
const t = (text, children = []) => ({ text, children: children.map((c) => (typeof c === "string" ? t(c) : c)) });
|
|
619
|
+
|
|
620
|
+
/** What an empty map offers. Each `map()` makes a fresh tree. */
|
|
621
|
+
export function mindMapTemplates() {
|
|
622
|
+
return [
|
|
623
|
+
{
|
|
624
|
+
id: "project",
|
|
625
|
+
label: "Project plan",
|
|
626
|
+
icon: "flag",
|
|
627
|
+
description: "Goals, scope, people, risks",
|
|
628
|
+
map: () => normalizeMap(t("Project", [t("Goals", ["Why now", "What success looks like"]), t("Scope", ["In", "Out"]), t("People", ["Owner", "Helpers"]), t("Milestones"), t("Risks")])),
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
id: "brainstorm",
|
|
632
|
+
label: "Brainstorm",
|
|
633
|
+
icon: "lightbulb",
|
|
634
|
+
description: "One question, ideas around it",
|
|
635
|
+
map: () => normalizeMap(t("How might we…?", ["Idea", "Idea", "Idea", "Idea"])),
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
id: "meeting",
|
|
639
|
+
label: "Meeting notes",
|
|
640
|
+
icon: "message-square",
|
|
641
|
+
description: "Agenda, decisions, actions",
|
|
642
|
+
map: () => normalizeMap(t("Meeting", [t("Agenda"), t("Notes"), t("Decisions"), t("Actions")])),
|
|
643
|
+
},
|
|
644
|
+
];
|
|
645
|
+
}
|