makersclaw 0.2.0 → 0.3.1
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/cli.mjs +19 -6
- package/src/install.mjs +18 -0
- package/src/registry.mjs +38 -4
- package/src/shadcn.mjs +14 -1
- 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,193 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, useEffect, useId, useState } from "react";
|
|
4
|
+
import { cx } from "./cx";
|
|
5
|
+
import { Icon } from "./icon";
|
|
6
|
+
|
|
7
|
+
// RadioGroup — one choice out of a few, all of them visible. Real
|
|
8
|
+
// <input type="radio"> sharing one name, so the browser supplies the
|
|
9
|
+
// behaviour: arrow keys move AND select, Tab enters at the checked one,
|
|
10
|
+
// forms submit the value. Options as data (`options`) or as <Radio>
|
|
11
|
+
// children. Controlled (`value` + `onChange(value)`) or not (`defaultValue`).
|
|
12
|
+
//
|
|
13
|
+
// options [{ value, label, description?, icon?, disabled? }]
|
|
14
|
+
// variant list (a dot beside each label; the default) · card (each
|
|
15
|
+
// option a selectable card — plans, templates, modes)
|
|
16
|
+
// orientation vertical (the default) · horizontal (wraps; cards stack
|
|
17
|
+
// on a narrow window and share the row from sm up)
|
|
18
|
+
// size md (44px rows) · sm (36px, dense rails); list only
|
|
19
|
+
// invalid marks every option; <Field error> sets the text
|
|
20
|
+
//
|
|
21
|
+
// In a <Field id="x" label hint error>, give the group the same `id`: a
|
|
22
|
+
// <label> cannot name a group, so the group borrows Field's label (and
|
|
23
|
+
// its hint or error) by aria-labelledby / aria-describedby. More than
|
|
24
|
+
// ~6 options, or options that are records: a <Select>.
|
|
25
|
+
|
|
26
|
+
const Group = createContext(null);
|
|
27
|
+
|
|
28
|
+
const ROW = {
|
|
29
|
+
md: "min-h-11 py-3",
|
|
30
|
+
sm: "min-h-9 py-2",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function RadioGroup({
|
|
34
|
+
id,
|
|
35
|
+
name,
|
|
36
|
+
value,
|
|
37
|
+
defaultValue,
|
|
38
|
+
onChange,
|
|
39
|
+
options,
|
|
40
|
+
variant = "list",
|
|
41
|
+
orientation = "vertical",
|
|
42
|
+
size = "md",
|
|
43
|
+
invalid,
|
|
44
|
+
disabled,
|
|
45
|
+
required,
|
|
46
|
+
className,
|
|
47
|
+
children,
|
|
48
|
+
"aria-label": ariaLabel,
|
|
49
|
+
"aria-labelledby": ariaLabelledby,
|
|
50
|
+
}) {
|
|
51
|
+
const auto = useId();
|
|
52
|
+
const [own, setOwn] = useState(defaultValue);
|
|
53
|
+
const [named, setNamed] = useState({});
|
|
54
|
+
const current = value !== undefined ? value : own;
|
|
55
|
+
|
|
56
|
+
// Field's label and hint point at `id`; wire them to the group.
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (!id || typeof document === "undefined") return;
|
|
59
|
+
const label = document.querySelector(`label[for="${CSS.escape(id)}"]`);
|
|
60
|
+
const note = document.getElementById(`${id}-error`) ?? document.getElementById(`${id}-hint`);
|
|
61
|
+
if (label && !label.id) label.id = `${id}-label`;
|
|
62
|
+
setNamed({ labelledby: label?.id, describedby: note?.id });
|
|
63
|
+
if (!label) return;
|
|
64
|
+
// Clicking the label lands on the group, as it would on an input.
|
|
65
|
+
const focus = () => {
|
|
66
|
+
const box = document.getElementById(id);
|
|
67
|
+
(box?.querySelector("input:checked:not(:disabled)") ?? box?.querySelector("input:not(:disabled)"))?.focus();
|
|
68
|
+
};
|
|
69
|
+
label.addEventListener("click", focus);
|
|
70
|
+
return () => label.removeEventListener("click", focus);
|
|
71
|
+
}, [id, invalid]);
|
|
72
|
+
|
|
73
|
+
const ctx = {
|
|
74
|
+
name: name ?? id ?? auto,
|
|
75
|
+
current,
|
|
76
|
+
variant,
|
|
77
|
+
size,
|
|
78
|
+
invalid,
|
|
79
|
+
disabled,
|
|
80
|
+
required,
|
|
81
|
+
select(next) {
|
|
82
|
+
if (value === undefined) setOwn(next);
|
|
83
|
+
onChange?.(next);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const card = variant === "card";
|
|
88
|
+
return (
|
|
89
|
+
<Group.Provider value={ctx}>
|
|
90
|
+
<div
|
|
91
|
+
id={id}
|
|
92
|
+
role="radiogroup"
|
|
93
|
+
aria-label={ariaLabel}
|
|
94
|
+
aria-labelledby={ariaLabel ? undefined : ariaLabelledby ?? named.labelledby}
|
|
95
|
+
aria-describedby={named.describedby}
|
|
96
|
+
aria-invalid={invalid ? true : undefined}
|
|
97
|
+
aria-required={required ? true : undefined}
|
|
98
|
+
aria-orientation={orientation}
|
|
99
|
+
className={cx(
|
|
100
|
+
card
|
|
101
|
+
? orientation === "horizontal"
|
|
102
|
+
? "grid gap-3 sm:auto-cols-fr sm:grid-flow-col"
|
|
103
|
+
: "grid gap-3"
|
|
104
|
+
: orientation === "horizontal"
|
|
105
|
+
? "flex flex-wrap gap-x-6"
|
|
106
|
+
: "grid",
|
|
107
|
+
className,
|
|
108
|
+
)}
|
|
109
|
+
>
|
|
110
|
+
{options ? options.map((o) => <Radio key={o.value} {...o} />) : children}
|
|
111
|
+
</div>
|
|
112
|
+
</Group.Provider>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** One option; only inside a <RadioGroup>. */
|
|
117
|
+
export function Radio({ value, label, description, icon, disabled, className }) {
|
|
118
|
+
const g = useContext(Group);
|
|
119
|
+
const auto = useId();
|
|
120
|
+
if (!g) return null;
|
|
121
|
+
const off = g.disabled || disabled;
|
|
122
|
+
const inputId = `${g.name}-${auto}`;
|
|
123
|
+
const card = g.variant === "card";
|
|
124
|
+
|
|
125
|
+
const dot = (
|
|
126
|
+
<span className="relative mt-0.5 flex h-4 w-4 shrink-0">
|
|
127
|
+
<input
|
|
128
|
+
id={inputId}
|
|
129
|
+
type="radio"
|
|
130
|
+
name={g.name}
|
|
131
|
+
value={value}
|
|
132
|
+
checked={g.current === value}
|
|
133
|
+
onChange={() => g.select(value)}
|
|
134
|
+
disabled={off}
|
|
135
|
+
required={g.required}
|
|
136
|
+
aria-describedby={description ? `${inputId}-d` : undefined}
|
|
137
|
+
className={cx(
|
|
138
|
+
"peer h-4 w-4 appearance-none rounded-full border bg-background outline-none transition-colors checked:border-primary disabled:cursor-not-allowed",
|
|
139
|
+
g.invalid ? "border-destructive" : "border-input",
|
|
140
|
+
!card && "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
141
|
+
)}
|
|
142
|
+
/>
|
|
143
|
+
<span aria-hidden="true" className="pointer-events-none absolute inset-0 m-auto h-2 w-2 scale-0 rounded-full bg-primary transition-transform peer-checked:scale-100" />
|
|
144
|
+
</span>
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const text = (
|
|
148
|
+
<span className="grid min-w-0 flex-1 gap-0.5">
|
|
149
|
+
<span className={cx("leading-5 text-foreground", card && "font-medium")}>{label ?? value}</span>
|
|
150
|
+
{description ? (
|
|
151
|
+
<span id={`${inputId}-d`} className="text-sm leading-5 text-muted-foreground">
|
|
152
|
+
{description}
|
|
153
|
+
</span>
|
|
154
|
+
) : null}
|
|
155
|
+
</span>
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
if (card) {
|
|
159
|
+
return (
|
|
160
|
+
<label
|
|
161
|
+
htmlFor={inputId}
|
|
162
|
+
className={cx(
|
|
163
|
+
"flex min-h-11 cursor-pointer items-start gap-3 rounded-lg border bg-card p-4 text-sm text-card-foreground transition-colors",
|
|
164
|
+
"hover:bg-accent/50 has-[:checked]:bg-accent/50 has-[:checked]:ring-1",
|
|
165
|
+
g.invalid ? "border-destructive has-[:checked]:ring-destructive" : "border-border has-[:checked]:border-primary has-[:checked]:ring-primary",
|
|
166
|
+
"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-ring",
|
|
167
|
+
off && "cursor-not-allowed opacity-50 hover:bg-card",
|
|
168
|
+
className,
|
|
169
|
+
)}
|
|
170
|
+
>
|
|
171
|
+
{icon ? <Icon name={icon} size={18} className="mt-px shrink-0 text-muted-foreground" /> : null}
|
|
172
|
+
{text}
|
|
173
|
+
{dot}
|
|
174
|
+
</label>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<label
|
|
180
|
+
htmlFor={inputId}
|
|
181
|
+
className={cx(
|
|
182
|
+
"flex cursor-pointer items-start gap-3 text-sm",
|
|
183
|
+
ROW[g.size] ?? ROW.md,
|
|
184
|
+
off && "cursor-not-allowed opacity-50",
|
|
185
|
+
className,
|
|
186
|
+
)}
|
|
187
|
+
>
|
|
188
|
+
{dot}
|
|
189
|
+
{icon ? <Icon name={icon} className="mt-0.5 shrink-0 text-muted-foreground" /> : null}
|
|
190
|
+
{text}
|
|
191
|
+
</label>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useId, useState } from "react";
|
|
4
|
+
import { cx } from "./cx";
|
|
5
|
+
|
|
6
|
+
// Rating — stars. Read-only it shows a score (4.5 of 5, halves drawn);
|
|
7
|
+
// with `onChange` it is an input: a native radio group underneath, one
|
|
8
|
+
// radio per star, so arrow keys, Tab, forms and screen readers are the
|
|
9
|
+
// browser's. The stars are drawn from tokens: filled in `text-primary`,
|
|
10
|
+
// empty in the border colour. Never a colour prop.
|
|
11
|
+
//
|
|
12
|
+
// value the score: a number from 0 to `max`. Read-only it may be
|
|
13
|
+
// fractional (shown to the nearest half, read to one decimal);
|
|
14
|
+
// as an input it is a whole number (0 = none chosen yet)
|
|
15
|
+
// max how many stars (5)
|
|
16
|
+
// onChange (n) → the chosen whole number; not an event. Present = input
|
|
17
|
+
// readOnly true: show it, even when onChange is passed
|
|
18
|
+
// size sm (16px stars) · md (20px stars; as an input each star is a
|
|
19
|
+
// 44px target)
|
|
20
|
+
// label what is rated ("Support quality"); a reader hears
|
|
21
|
+
// "Support quality, 4.5 out of 5". Without it: "4.5 out of 5"
|
|
22
|
+
// name the form field the input submits under
|
|
23
|
+
// disabled the input, greyed and still
|
|
24
|
+
//
|
|
25
|
+
// A reader hears the number, never "star star star": the read-only row is
|
|
26
|
+
// one image named "4.5 out of 5", and each radio is named "3 out of 5".
|
|
27
|
+
|
|
28
|
+
const STAR = "m12 3 2.8 5.7 6.2.9-4.5 4.4 1.1 6.2L12 17.3 6.4 20.2l1.1-6.2L3 9.6l6.2-.9L12 3Z";
|
|
29
|
+
|
|
30
|
+
const PX = { sm: 16, md: 20 };
|
|
31
|
+
// Each star's box as an input: 44px at md, the thumb's target.
|
|
32
|
+
const TARGET = { sm: "size-8", md: "size-11" };
|
|
33
|
+
|
|
34
|
+
function Star({ size, className }) {
|
|
35
|
+
return (
|
|
36
|
+
<svg
|
|
37
|
+
width={size}
|
|
38
|
+
height={size}
|
|
39
|
+
viewBox="0 0 24 24"
|
|
40
|
+
fill="currentColor"
|
|
41
|
+
stroke="currentColor"
|
|
42
|
+
strokeWidth="1.8"
|
|
43
|
+
strokeLinejoin="round"
|
|
44
|
+
aria-hidden="true"
|
|
45
|
+
className={cx("block shrink-0", className)}
|
|
46
|
+
>
|
|
47
|
+
<path d={STAR} />
|
|
48
|
+
</svg>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// One star filled by `part` (0, 0.5 or 1): an empty star with the filled
|
|
53
|
+
// one laid over it, cut to that width from the start edge.
|
|
54
|
+
function PartStar({ part, size }) {
|
|
55
|
+
return (
|
|
56
|
+
<span className="relative block shrink-0" style={{ width: size, height: size }}>
|
|
57
|
+
<Star size={size} className="text-border" />
|
|
58
|
+
{part > 0 ? (
|
|
59
|
+
<span className="absolute inset-y-0 start-0 overflow-hidden" style={{ width: `${part * 100}%` }}>
|
|
60
|
+
<Star size={size} className="text-primary" />
|
|
61
|
+
</span>
|
|
62
|
+
) : null}
|
|
63
|
+
</span>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const spoken = (n) => String(Math.round(n * 10) / 10);
|
|
68
|
+
|
|
69
|
+
export function Rating({ value = 0, max = 5, onChange, readOnly = false, size = "md", label, name, disabled, id, className }) {
|
|
70
|
+
const px = PX[size] ?? PX.md;
|
|
71
|
+
const group = useId();
|
|
72
|
+
const [hover, setHover] = useState(null);
|
|
73
|
+
const count = Math.max(1, Math.round(max));
|
|
74
|
+
const score = Math.min(Math.max(Number(value) || 0, 0), count);
|
|
75
|
+
const stars = Array.from({ length: count }, (_, i) => i + 1);
|
|
76
|
+
|
|
77
|
+
if (!onChange || readOnly) {
|
|
78
|
+
const halves = Math.round(score * 2) / 2;
|
|
79
|
+
const said = `${spoken(score)} out of ${count}`;
|
|
80
|
+
return (
|
|
81
|
+
<span
|
|
82
|
+
id={id}
|
|
83
|
+
role="img"
|
|
84
|
+
aria-label={label ? `${label}, ${said}` : said}
|
|
85
|
+
className={cx("inline-flex items-center gap-0.5 align-middle", className)}
|
|
86
|
+
>
|
|
87
|
+
{stars.map((n) => (
|
|
88
|
+
<PartStar key={n} size={px} part={Math.min(Math.max(halves - (n - 1), 0), 1)} />
|
|
89
|
+
))}
|
|
90
|
+
</span>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const chosen = Math.round(score);
|
|
95
|
+
const shown = hover ?? chosen;
|
|
96
|
+
return (
|
|
97
|
+
<div
|
|
98
|
+
id={id}
|
|
99
|
+
role="radiogroup"
|
|
100
|
+
aria-label={label ?? "Rating"}
|
|
101
|
+
aria-disabled={disabled || undefined}
|
|
102
|
+
className={cx("inline-flex items-center", size === "sm" ? "-mx-2" : "-mx-3", disabled && "opacity-50", className)}
|
|
103
|
+
onMouseLeave={() => setHover(null)}
|
|
104
|
+
>
|
|
105
|
+
{stars.map((n) => (
|
|
106
|
+
<label
|
|
107
|
+
key={n}
|
|
108
|
+
className={cx(
|
|
109
|
+
"grid shrink-0 place-items-center rounded-md",
|
|
110
|
+
"has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring",
|
|
111
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
112
|
+
TARGET[size] ?? TARGET.md,
|
|
113
|
+
)}
|
|
114
|
+
onMouseEnter={() => !disabled && setHover(n)}
|
|
115
|
+
>
|
|
116
|
+
<input
|
|
117
|
+
type="radio"
|
|
118
|
+
name={name ?? group}
|
|
119
|
+
value={n}
|
|
120
|
+
checked={chosen === n}
|
|
121
|
+
onChange={() => onChange(n)}
|
|
122
|
+
disabled={disabled}
|
|
123
|
+
aria-label={`${n} out of ${count}`}
|
|
124
|
+
className="sr-only"
|
|
125
|
+
/>
|
|
126
|
+
<Star size={px} className={cx("transition-colors", n <= shown ? "text-primary" : "text-border")} />
|
|
127
|
+
</label>
|
|
128
|
+
))}
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Children, createContext, isValidElement, useCallback, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
4
|
+
import { cx } from "./cx";
|
|
5
|
+
import { Icon } from "./icon";
|
|
6
|
+
|
|
7
|
+
// Resizable — panes the user sizes by dragging the line between them: a
|
|
8
|
+
// list beside its record, an editor above its preview. Sizes are
|
|
9
|
+
// percentages of the group; a handle moves only the two panes either
|
|
10
|
+
// side of it. Mobile first: below md (768px) a horizontal group stacks
|
|
11
|
+
// its panes top to bottom at their natural height and hides the handles
|
|
12
|
+
// (there is no room to share, and a thumb cannot hit a 1px line).
|
|
13
|
+
//
|
|
14
|
+
// <ResizablePanelGroup direction="horizontal" storageKey="inbox" className="h-[32rem]">
|
|
15
|
+
// <ResizablePanel defaultSize={35} minSize={20}>…list…</ResizablePanel>
|
|
16
|
+
// <ResizableHandle grip />
|
|
17
|
+
// <ResizablePanel>…record…</ResizablePanel>
|
|
18
|
+
// </ResizablePanelGroup>
|
|
19
|
+
//
|
|
20
|
+
// ResizablePanelGroup
|
|
21
|
+
// direction horizontal (side by side; the default) · vertical
|
|
22
|
+
// storageKey remember the sizes in this browser (localStorage)
|
|
23
|
+
// onResize (sizes) → percentages, one per panel
|
|
24
|
+
// className its height (h-[32rem]); without one it fills its parent
|
|
25
|
+
// (h-full), so the parent needs a height. A vertical
|
|
26
|
+
// group has no height of its own to fall back on
|
|
27
|
+
// ResizablePanel
|
|
28
|
+
// defaultSize %, of the group; panels without one share what is left
|
|
29
|
+
// minSize % it never shrinks below (10) · maxSize % (100)
|
|
30
|
+
// ResizableHandle
|
|
31
|
+
// grip draw a visible grip on the line
|
|
32
|
+
// label what a screen reader calls it ("Resize")
|
|
33
|
+
//
|
|
34
|
+
// Panels and handles are the group's DIRECT children, in order. A handle
|
|
35
|
+
// is a separator a keyboard can move: arrows by 2% (Shift: 10%), Home and
|
|
36
|
+
// End to the limits, Enter to fold the pane before it to its minimum and
|
|
37
|
+
// back; double-click resets the pair.
|
|
38
|
+
//
|
|
39
|
+
// The group never asks what TYPE a child is: from a server surface a
|
|
40
|
+
// child's type is a client reference, not the ResizablePanel function,
|
|
41
|
+
// so a type test finds no panels. Each child gets its slot through
|
|
42
|
+
// context and the panels register themselves (kind, sizes) there.
|
|
43
|
+
|
|
44
|
+
const STEP = 2;
|
|
45
|
+
const BIG = 10;
|
|
46
|
+
|
|
47
|
+
const GroupContext = createContext(null);
|
|
48
|
+
const SlotContext = createContext(-1);
|
|
49
|
+
|
|
50
|
+
// Register this child in its group under its slot; returns the group's
|
|
51
|
+
// wiring for it (undefined until the group has seen the registration).
|
|
52
|
+
function useSlot(entry) {
|
|
53
|
+
const group = useContext(GroupContext);
|
|
54
|
+
const slot = useContext(SlotContext);
|
|
55
|
+
const register = group?.register;
|
|
56
|
+
const key = JSON.stringify(entry);
|
|
57
|
+
useLayoutEffect(() => {
|
|
58
|
+
if (!register || slot < 0) return;
|
|
59
|
+
return register(slot, JSON.parse(key));
|
|
60
|
+
}, [register, slot, key]);
|
|
61
|
+
return group && slot >= 0 ? group.bySlot[slot] : undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function initial(panels) {
|
|
65
|
+
const given = panels.reduce((s, p) => s + (p.defaultSize ?? 0), 0);
|
|
66
|
+
const open = panels.filter((p) => p.defaultSize == null).length;
|
|
67
|
+
const share = open ? Math.max(0, 100 - given) / open : 0;
|
|
68
|
+
const raw = panels.map((p) => p.defaultSize ?? share);
|
|
69
|
+
const total = raw.reduce((s, n) => s + n, 0) || 1;
|
|
70
|
+
return raw.map((n) => (n / total) * 100);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function ResizablePanelGroup({ direction = "horizontal", storageKey, onResize, className, children }) {
|
|
74
|
+
const base = useId();
|
|
75
|
+
const group = useRef(null);
|
|
76
|
+
const items = Children.toArray(children).filter(isValidElement);
|
|
77
|
+
// slot → { kind: "panel" | "handle", defaultSize?, minSize?, maxSize? }
|
|
78
|
+
const [reg, setReg] = useState({});
|
|
79
|
+
const register = useCallback((slot, entry) => {
|
|
80
|
+
setReg((r) => (JSON.stringify(r[slot]) === JSON.stringify(entry) ? r : { ...r, [slot]: entry }));
|
|
81
|
+
return () =>
|
|
82
|
+
setReg((r) => {
|
|
83
|
+
if (!(slot in r)) return r;
|
|
84
|
+
const { [slot]: _, ...rest } = r;
|
|
85
|
+
return rest;
|
|
86
|
+
});
|
|
87
|
+
}, []);
|
|
88
|
+
const slots = Object.keys(reg).map(Number).sort((a, b) => a - b);
|
|
89
|
+
const panelSlots = slots.filter((k) => reg[k].kind === "panel");
|
|
90
|
+
const panels = panelSlots.map((k) => ({ minSize: 10, maxSize: 100, ...reg[k] }));
|
|
91
|
+
const defaults = useRef(null);
|
|
92
|
+
if (!defaults.current || defaults.current.length !== panels.length) defaults.current = initial(panels);
|
|
93
|
+
const [own, setSizes] = useState(null);
|
|
94
|
+
const sizes = own && own.length === panels.length ? own : defaults.current;
|
|
95
|
+
const loaded = useRef(false);
|
|
96
|
+
const horizontal = direction !== "vertical";
|
|
97
|
+
|
|
98
|
+
// The remembered sizes, before first paint, when they still fit (once
|
|
99
|
+
// the panels have registered — their layout effects run before ours,
|
|
100
|
+
// the re-render they cause before paint).
|
|
101
|
+
useLayoutEffect(() => {
|
|
102
|
+
if (!panels.length) return;
|
|
103
|
+
if (storageKey) {
|
|
104
|
+
try {
|
|
105
|
+
const saved = JSON.parse(localStorage.getItem(`resizable:${storageKey}`) ?? "null");
|
|
106
|
+
if (Array.isArray(saved) && saved.length === panels.length && saved.every((n) => Number.isFinite(n) && n >= 0)) setSizes(saved);
|
|
107
|
+
} catch {}
|
|
108
|
+
}
|
|
109
|
+
loaded.current = true;
|
|
110
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
111
|
+
}, [storageKey, panels.length]);
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (!loaded.current || !panels.length) return;
|
|
115
|
+
onResize?.(sizes);
|
|
116
|
+
if (!storageKey) return;
|
|
117
|
+
const h = setTimeout(() => {
|
|
118
|
+
try {
|
|
119
|
+
localStorage.setItem(`resizable:${storageKey}`, JSON.stringify(sizes.map((n) => Math.round(n * 100) / 100)));
|
|
120
|
+
} catch {}
|
|
121
|
+
}, 150);
|
|
122
|
+
return () => clearTimeout(h);
|
|
123
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
124
|
+
}, [sizes, storageKey]);
|
|
125
|
+
|
|
126
|
+
// Move the line between panel a and a + 1 so a is `want` %; the pair's
|
|
127
|
+
// total stays put and each side keeps its min and max.
|
|
128
|
+
function place(a, want) {
|
|
129
|
+
setSizes((mine) => {
|
|
130
|
+
const prev = mine && mine.length === panels.length ? mine : defaults.current;
|
|
131
|
+
const b = a + 1;
|
|
132
|
+
const pair = prev[a] + prev[b];
|
|
133
|
+
const pa = panels[a];
|
|
134
|
+
const pb = panels[b];
|
|
135
|
+
const lo = Math.max(pa.minSize, pair - pb.maxSize, 0);
|
|
136
|
+
const hi = Math.min(pa.maxSize, pair - pb.minSize, pair);
|
|
137
|
+
const next = Math.min(hi, Math.max(lo, want));
|
|
138
|
+
if (Math.abs(next - prev[a]) < 0.01) return prev;
|
|
139
|
+
const out = [...prev];
|
|
140
|
+
out[a] = next;
|
|
141
|
+
out[b] = pair - next;
|
|
142
|
+
return out;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function limits(a) {
|
|
147
|
+
const pair = sizes[a] + sizes[a + 1];
|
|
148
|
+
return {
|
|
149
|
+
lo: Math.max(panels[a].minSize, pair - panels[a + 1].maxSize, 0),
|
|
150
|
+
hi: Math.min(panels[a].maxSize, pair - panels[a + 1].minSize, pair),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// The panels' own length along the axis, handles excluded: what 100% is.
|
|
155
|
+
function span() {
|
|
156
|
+
const nodes = group.current?.querySelectorAll(":scope > [data-panel]") ?? [];
|
|
157
|
+
let px = 0;
|
|
158
|
+
for (const n of nodes) px += horizontal ? n.offsetWidth : n.offsetHeight;
|
|
159
|
+
return px || 1;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// What each registered slot is given: a panel its id and size, a
|
|
163
|
+
// handle the pair either side of it (none when it is not between two).
|
|
164
|
+
const bySlot = {};
|
|
165
|
+
let p = -1;
|
|
166
|
+
for (const k of slots) {
|
|
167
|
+
if (reg[k].kind === "panel") {
|
|
168
|
+
p += 1;
|
|
169
|
+
bySlot[k] = { _id: `${base}-${p}`, _size: sizes[p], _horizontal: horizontal };
|
|
170
|
+
} else if (reg[k].kind === "handle") {
|
|
171
|
+
const a = p;
|
|
172
|
+
if (a < 0 || a >= panels.length - 1) {
|
|
173
|
+
bySlot[k] = { _horizontal: horizontal, _orphan: true };
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
bySlot[k] = {
|
|
177
|
+
_horizontal: horizontal,
|
|
178
|
+
_controls: `${base}-${a}`,
|
|
179
|
+
_value: sizes[a],
|
|
180
|
+
_limits: () => limits(a),
|
|
181
|
+
_start: () => ({ from: sizes[a], span: span() }),
|
|
182
|
+
_place: (want) => place(a, want),
|
|
183
|
+
_reset: () => {
|
|
184
|
+
const d = defaults.current;
|
|
185
|
+
const pair = sizes[a] + sizes[a + 1];
|
|
186
|
+
place(a, (d[a] / (d[a] + d[a + 1])) * pair);
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<div
|
|
194
|
+
ref={group}
|
|
195
|
+
data-direction={horizontal ? "horizontal" : "vertical"}
|
|
196
|
+
className={cx(
|
|
197
|
+
"flex w-full min-h-0 min-w-0",
|
|
198
|
+
!/(?:^|\s)h-/.test(className ?? "") && "h-full",
|
|
199
|
+
horizontal ? "flex-row max-md:h-auto max-md:flex-col" : "flex-col",
|
|
200
|
+
className,
|
|
201
|
+
)}
|
|
202
|
+
>
|
|
203
|
+
<GroupContext.Provider value={{ register, bySlot, horizontal }}>
|
|
204
|
+
{items.map((child, i) => (
|
|
205
|
+
<SlotContext.Provider key={child.key ?? i} value={i}>
|
|
206
|
+
{child}
|
|
207
|
+
</SlotContext.Provider>
|
|
208
|
+
))}
|
|
209
|
+
</GroupContext.Provider>
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function ResizablePanel({ defaultSize, minSize, maxSize, className, children }) {
|
|
215
|
+
const group = useContext(GroupContext);
|
|
216
|
+
const wired = useSlot({ kind: "panel", defaultSize, minSize, maxSize });
|
|
217
|
+
const _horizontal = wired?._horizontal ?? group?.horizontal ?? true;
|
|
218
|
+
// Before the group has counted its panels (the server render, the first
|
|
219
|
+
// client pass) a panel with a defaultSize takes that share, the rest
|
|
220
|
+
// split what is left: the layout the counted sizes will give.
|
|
221
|
+
const style = wired
|
|
222
|
+
? { flexGrow: wired._size ?? 1, flexShrink: 1, flexBasis: 0 }
|
|
223
|
+
: defaultSize != null
|
|
224
|
+
? { flexGrow: 0, flexShrink: 1, flexBasis: `${defaultSize}%` }
|
|
225
|
+
: { flexGrow: 1, flexShrink: 1, flexBasis: 0 };
|
|
226
|
+
return (
|
|
227
|
+
<div
|
|
228
|
+
id={wired?._id}
|
|
229
|
+
data-panel=""
|
|
230
|
+
style={style}
|
|
231
|
+
className={cx("min-h-0 min-w-0 overflow-auto", _horizontal && "max-md:flex-none! max-md:overflow-visible", className)}
|
|
232
|
+
>
|
|
233
|
+
{children}
|
|
234
|
+
</div>
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function ResizableHandle({ grip = false, label = "Resize", className }) {
|
|
239
|
+
const group = useContext(GroupContext);
|
|
240
|
+
const wired = useSlot({ kind: "handle" });
|
|
241
|
+
const [dragging, setDragging] = useState(false);
|
|
242
|
+
const drag = useRef(null);
|
|
243
|
+
const folded = useRef(null);
|
|
244
|
+
const _horizontal = wired?._horizontal ?? group?.horizontal ?? true;
|
|
245
|
+
if (!group || wired?._orphan) return null;
|
|
246
|
+
const { _controls, _value, _limits, _start, _place, _reset } = wired ?? {};
|
|
247
|
+
const live = Boolean(_place);
|
|
248
|
+
const { lo, hi } = live ? _limits() : { lo: 0, hi: 100 };
|
|
249
|
+
|
|
250
|
+
function onPointerDown(e) {
|
|
251
|
+
if (e.button !== 0 || !live) return;
|
|
252
|
+
e.preventDefault();
|
|
253
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
254
|
+
e.currentTarget.focus();
|
|
255
|
+
drag.current = { at: _horizontal ? e.clientX : e.clientY, ..._start() };
|
|
256
|
+
setDragging(true);
|
|
257
|
+
document.documentElement.style.cursor = _horizontal ? "col-resize" : "row-resize";
|
|
258
|
+
document.documentElement.style.userSelect = "none";
|
|
259
|
+
}
|
|
260
|
+
function onPointerMove(e) {
|
|
261
|
+
const d = drag.current;
|
|
262
|
+
if (!d) return;
|
|
263
|
+
const moved = (_horizontal ? e.clientX : e.clientY) - d.at;
|
|
264
|
+
_place(d.from + (moved / d.span) * 100);
|
|
265
|
+
}
|
|
266
|
+
function end() {
|
|
267
|
+
if (!drag.current) return;
|
|
268
|
+
drag.current = null;
|
|
269
|
+
setDragging(false);
|
|
270
|
+
document.documentElement.style.cursor = "";
|
|
271
|
+
document.documentElement.style.userSelect = "";
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function onKeyDown(e) {
|
|
275
|
+
if (!live) return;
|
|
276
|
+
const step = e.shiftKey ? BIG : STEP;
|
|
277
|
+
const back = _horizontal ? "ArrowLeft" : "ArrowUp";
|
|
278
|
+
const fwd = _horizontal ? "ArrowRight" : "ArrowDown";
|
|
279
|
+
if (e.key === back) _place(_value - step);
|
|
280
|
+
else if (e.key === fwd) _place(_value + step);
|
|
281
|
+
else if (e.key === "Home") _place(lo);
|
|
282
|
+
else if (e.key === "End") _place(hi);
|
|
283
|
+
else if (e.key === "Enter") {
|
|
284
|
+
if (folded.current != null && _value <= lo + 0.01) {
|
|
285
|
+
_place(folded.current);
|
|
286
|
+
folded.current = null;
|
|
287
|
+
} else {
|
|
288
|
+
folded.current = _value;
|
|
289
|
+
_place(lo);
|
|
290
|
+
}
|
|
291
|
+
} else return;
|
|
292
|
+
e.preventDefault();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return (
|
|
296
|
+
<div
|
|
297
|
+
// Until the group wires it (the server render), a plain line.
|
|
298
|
+
role={live ? "separator" : undefined}
|
|
299
|
+
aria-hidden={live ? undefined : true}
|
|
300
|
+
tabIndex={live ? 0 : undefined}
|
|
301
|
+
aria-label={live ? label : undefined}
|
|
302
|
+
aria-orientation={live ? (_horizontal ? "vertical" : "horizontal") : undefined}
|
|
303
|
+
aria-controls={_controls}
|
|
304
|
+
aria-valuenow={live ? Math.round(_value) : undefined}
|
|
305
|
+
aria-valuemin={live ? Math.round(lo) : undefined}
|
|
306
|
+
aria-valuemax={live ? Math.round(hi) : undefined}
|
|
307
|
+
data-dragging={dragging || undefined}
|
|
308
|
+
onPointerDown={onPointerDown}
|
|
309
|
+
onPointerMove={onPointerMove}
|
|
310
|
+
onPointerUp={end}
|
|
311
|
+
onPointerCancel={end}
|
|
312
|
+
onLostPointerCapture={end}
|
|
313
|
+
onKeyDown={onKeyDown}
|
|
314
|
+
onDoubleClick={_reset}
|
|
315
|
+
className={cx(
|
|
316
|
+
"relative z-10 flex shrink-0 touch-none items-center justify-center bg-border outline-none transition-colors",
|
|
317
|
+
"hover:bg-ring/60 focus-visible:bg-ring data-[dragging]:bg-ring motion-reduce:transition-none",
|
|
318
|
+
"after:absolute after:content-['']",
|
|
319
|
+
_horizontal
|
|
320
|
+
? "w-px cursor-col-resize after:inset-y-0 after:left-1/2 after:w-4 after:-translate-x-1/2 max-md:hidden"
|
|
321
|
+
: "h-px w-full cursor-row-resize after:inset-x-0 after:top-1/2 after:h-4 after:-translate-y-1/2",
|
|
322
|
+
className,
|
|
323
|
+
)}
|
|
324
|
+
>
|
|
325
|
+
{grip ? (
|
|
326
|
+
<span
|
|
327
|
+
aria-hidden="true"
|
|
328
|
+
className={cx(
|
|
329
|
+
"grid place-items-center rounded-sm border border-border bg-background text-muted-foreground shadow-sm",
|
|
330
|
+
_horizontal ? "h-6 w-3.5" : "h-3.5 w-6",
|
|
331
|
+
)}
|
|
332
|
+
>
|
|
333
|
+
<Icon name="grip" size={12} className={_horizontal ? undefined : "rotate-90"} />
|
|
334
|
+
</span>
|
|
335
|
+
) : null}
|
|
336
|
+
</div>
|
|
337
|
+
);
|
|
338
|
+
}
|