makersclaw 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +41 -1
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +15 -8
- package/r/annotate.json +62 -0
- package/r/approval-request.json +52 -0
- package/r/audio-player.json +74 -0
- package/r/auth-form.json +55 -0
- package/r/board.json +55 -0
- package/r/calendar-view.json +105 -0
- package/r/cart.json +62 -0
- package/r/chart.json +83 -0
- package/r/chat.json +95 -0
- package/r/code-editor.json +94 -0
- package/r/comment-box.json +64 -0
- package/r/contact-section.json +53 -0
- package/r/core.json +341 -0
- package/r/csv-import.json +63 -0
- package/r/data-table.json +69 -0
- package/r/diagram.json +74 -0
- package/r/doc-editor.json +82 -0
- package/r/doc-page.json +61 -0
- package/r/email-render.json +73 -0
- package/r/faq.json +50 -0
- package/r/file-upload.json +54 -0
- package/r/flow-canvas.json +93 -0
- package/r/footer.json +52 -0
- package/r/gantt.json +70 -0
- package/r/job-panel.json +56 -0
- package/r/json-editor.json +66 -0
- package/r/map.json +89 -0
- package/r/menubar.json +52 -0
- package/r/mind-map.json +67 -0
- package/r/navigation-menu.json +52 -0
- package/r/order-detail.json +54 -0
- package/r/org-chart.json +66 -0
- package/r/page-builder.json +105 -0
- package/r/payment-methods.json +51 -0
- package/r/pdf-document.json +79 -0
- package/r/pdf-viewer.json +88 -0
- package/r/product-detail.json +76 -0
- package/r/product-grid.json +65 -0
- package/r/record-form.json +67 -0
- package/r/record-notes.json +55 -0
- package/r/registry.json +3612 -0
- package/r/search-dialog.json +51 -0
- package/r/settings-list.json +66 -0
- package/r/setup-checklist.json +51 -0
- package/r/share-dialog.json +52 -0
- package/r/sidebar.json +69 -0
- package/r/signature-pad.json +72 -0
- package/r/sketch-canvas.json +99 -0
- package/r/spreadsheet.json +90 -0
- package/r/stat-cards.json +66 -0
- package/r/task-list.json +63 -0
- package/r/task-model.json +98 -0
- package/r/testimonials.json +52 -0
- package/r/transaction-list.json +53 -0
- package/r/whiteboard.json +66 -0
- package/registry/blocks/annotate/README.md +179 -0
- package/registry/blocks/annotate/annotate-data.js +250 -0
- package/registry/blocks/annotate/annotate.jsx +646 -0
- package/registry/blocks/annotate/block.json +10 -0
- package/registry/blocks/annotate/demo.jsx +135 -0
- package/registry/blocks/annotate/index.js +15 -0
- package/registry/blocks/approval-request/README.md +116 -0
- package/registry/blocks/approval-request/approval-request.jsx +386 -0
- package/registry/blocks/approval-request/block.json +10 -0
- package/registry/blocks/approval-request/demo.jsx +127 -0
- package/registry/blocks/approval-request/index.js +4 -0
- package/registry/blocks/audio-player/README.md +167 -0
- package/registry/blocks/audio-player/audio-player.jsx +623 -0
- package/registry/blocks/audio-player/block.json +14 -0
- package/registry/blocks/audio-player/colors.js +109 -0
- package/registry/blocks/audio-player/demo.jsx +209 -0
- package/registry/blocks/audio-player/index.js +6 -0
- package/registry/blocks/audio-player/time.js +67 -0
- package/registry/blocks/audio-player/wavesurfer.js +9 -0
- package/registry/blocks/auth-form/README.md +126 -0
- package/registry/blocks/auth-form/auth-form.jsx +568 -0
- package/registry/blocks/auth-form/block.json +10 -0
- package/registry/blocks/auth-form/demo.jsx +131 -0
- package/registry/blocks/auth-form/index.js +3 -0
- package/registry/blocks/board/README.md +64 -13
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +237 -94
- package/registry/blocks/board/demo.jsx +103 -24
- package/registry/blocks/calendar-view/README.md +180 -0
- package/registry/blocks/calendar-view/agenda.jsx +147 -0
- package/registry/blocks/calendar-view/block.json +76 -0
- package/registry/blocks/calendar-view/calendar-model.js +442 -0
- package/registry/blocks/calendar-view/calendar.jsx +627 -0
- package/registry/blocks/calendar-view/demo.jsx +195 -0
- package/registry/blocks/calendar-view/draft.jsx +49 -0
- package/registry/blocks/calendar-view/index.js +39 -0
- package/registry/blocks/calendar-view/month.jsx +346 -0
- package/registry/blocks/calendar-view/paint.js +69 -0
- package/registry/blocks/calendar-view/time-grid.jsx +527 -0
- package/registry/blocks/calendar-view/tray.jsx +87 -0
- package/registry/blocks/cart/README.md +146 -0
- package/registry/blocks/cart/block.json +10 -0
- package/registry/blocks/cart/cart.jsx +597 -0
- package/registry/blocks/cart/demo.jsx +98 -0
- package/registry/blocks/cart/index.js +4 -0
- package/registry/blocks/cart/money.js +28 -0
- package/registry/blocks/chart/README.md +316 -0
- package/registry/blocks/chart/block.json +10 -0
- package/registry/blocks/chart/cartesian.jsx +642 -0
- package/registry/blocks/chart/core.jsx +262 -0
- package/registry/blocks/chart/demo.jsx +357 -0
- package/registry/blocks/chart/heatmap.jsx +336 -0
- package/registry/blocks/chart/index.js +8 -0
- package/registry/blocks/chart/pie.jsx +245 -0
- package/registry/blocks/chart/sparkline.jsx +88 -0
- package/registry/blocks/chat/README.md +273 -0
- package/registry/blocks/chat/attachment.jsx +95 -0
- package/registry/blocks/chat/block.json +10 -0
- package/registry/blocks/chat/chat.jsx +132 -0
- package/registry/blocks/chat/composer.jsx +364 -0
- package/registry/blocks/chat/demo.jsx +578 -0
- package/registry/blocks/chat/header.jsx +34 -0
- package/registry/blocks/chat/index.js +9 -0
- package/registry/blocks/chat/message.jsx +450 -0
- package/registry/blocks/chat/scroller.jsx +247 -0
- package/registry/blocks/chat/text.jsx +104 -0
- package/registry/blocks/code-editor/README.md +210 -0
- package/registry/blocks/code-editor/block.json +22 -0
- package/registry/blocks/code-editor/code-editor.jsx +534 -0
- package/registry/blocks/code-editor/codemirror.js +38 -0
- package/registry/blocks/code-editor/demo.jsx +205 -0
- package/registry/blocks/code-editor/index.js +8 -0
- package/registry/blocks/code-editor/json.js +317 -0
- package/registry/blocks/code-editor/sql.js +136 -0
- package/registry/blocks/code-editor/text.js +101 -0
- package/registry/blocks/code-editor/theme.js +186 -0
- package/registry/blocks/comment-box/README.md +123 -0
- package/registry/blocks/comment-box/block.json +10 -0
- package/registry/blocks/comment-box/comment-body.jsx +217 -0
- package/registry/blocks/comment-box/comment-box.jsx +198 -0
- package/registry/blocks/comment-box/comment-time.jsx +77 -0
- package/registry/blocks/comment-box/demo.jsx +141 -0
- package/registry/blocks/comment-box/index.js +8 -0
- package/registry/blocks/contact-section/README.md +152 -0
- package/registry/blocks/contact-section/block.json +11 -0
- package/registry/blocks/contact-section/contact-section.jsx +509 -0
- package/registry/blocks/contact-section/demo.jsx +93 -0
- package/registry/blocks/contact-section/index.js +4 -0
- package/registry/blocks/csv-import/README.md +133 -0
- package/registry/blocks/csv-import/block.json +13 -0
- package/registry/blocks/csv-import/csv-import.jsx +479 -0
- package/registry/blocks/csv-import/demo.jsx +106 -0
- package/registry/blocks/csv-import/import.js +200 -0
- package/registry/blocks/csv-import/index.js +7 -0
- package/registry/blocks/data-table/README.md +386 -0
- package/registry/blocks/data-table/block.json +10 -0
- package/registry/blocks/data-table/data-table.jsx +1164 -0
- package/registry/blocks/data-table/demo.jsx +588 -0
- package/registry/blocks/data-table/index.js +5 -0
- package/registry/blocks/data-table/model.js +169 -0
- package/registry/blocks/diagram/README.md +108 -0
- package/registry/blocks/diagram/block.json +13 -0
- package/registry/blocks/diagram/demo.jsx +113 -0
- package/registry/blocks/diagram/diagram.jsx +481 -0
- package/registry/blocks/diagram/index.js +7 -0
- package/registry/blocks/diagram/mermaid.js +52 -0
- package/registry/blocks/diagram/palette.js +313 -0
- package/registry/blocks/diagram/source.js +98 -0
- package/registry/blocks/doc-editor/README.md +215 -0
- package/registry/blocks/doc-editor/block.json +15 -0
- package/registry/blocks/doc-editor/demo.jsx +225 -0
- package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
- package/registry/blocks/doc-editor/doc.js +309 -0
- package/registry/blocks/doc-editor/index.js +7 -0
- package/registry/blocks/doc-editor/schema.jsx +56 -0
- package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
- package/registry/blocks/doc-editor/theme.js +82 -0
- package/registry/blocks/doc-page/README.md +119 -0
- package/registry/blocks/doc-page/autosave.js +104 -0
- package/registry/blocks/doc-page/block.json +10 -0
- package/registry/blocks/doc-page/demo.jsx +137 -0
- package/registry/blocks/doc-page/doc-page.jsx +276 -0
- package/registry/blocks/doc-page/index.js +4 -0
- package/registry/blocks/email-render/README.md +151 -0
- package/registry/blocks/email-render/block.json +14 -0
- package/registry/blocks/email-render/demo.jsx +153 -0
- package/registry/blocks/email-render/doc-email.jsx +210 -0
- package/registry/blocks/email-render/email.jsx +221 -0
- package/registry/blocks/email-render/index.js +10 -0
- package/registry/blocks/email-render/render.js +50 -0
- package/registry/blocks/email-render/theme.js +215 -0
- package/registry/blocks/faq/README.md +101 -0
- package/registry/blocks/faq/block.json +11 -0
- package/registry/blocks/faq/demo.jsx +89 -0
- package/registry/blocks/faq/faq.jsx +220 -0
- package/registry/blocks/faq/index.js +4 -0
- package/registry/blocks/file-upload/README.md +138 -0
- package/registry/blocks/file-upload/block.json +10 -0
- package/registry/blocks/file-upload/demo.jsx +204 -0
- package/registry/blocks/file-upload/file-upload.jsx +635 -0
- package/registry/blocks/file-upload/index.js +4 -0
- package/registry/blocks/flow-canvas/README.md +420 -0
- package/registry/blocks/flow-canvas/block.json +13 -0
- package/registry/blocks/flow-canvas/board.js +819 -0
- package/registry/blocks/flow-canvas/chrome.jsx +649 -0
- package/registry/blocks/flow-canvas/context.jsx +35 -0
- package/registry/blocks/flow-canvas/demo.jsx +249 -0
- package/registry/blocks/flow-canvas/edges.jsx +107 -0
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
- package/registry/blocks/flow-canvas/index.js +41 -0
- package/registry/blocks/flow-canvas/nodes.jsx +392 -0
- package/registry/blocks/flow-canvas/theme.js +174 -0
- package/registry/blocks/footer/README.md +133 -0
- package/registry/blocks/footer/block.json +11 -0
- package/registry/blocks/footer/demo.jsx +119 -0
- package/registry/blocks/footer/footer.jsx +406 -0
- package/registry/blocks/footer/index.js +4 -0
- package/registry/blocks/gantt/README.md +220 -0
- package/registry/blocks/gantt/block.json +10 -0
- package/registry/blocks/gantt/demo.jsx +148 -0
- package/registry/blocks/gantt/gantt.jsx +923 -0
- package/registry/blocks/gantt/index.js +7 -0
- package/registry/blocks/gantt/rows.jsx +468 -0
- package/registry/blocks/gantt/schedule.js +278 -0
- package/registry/blocks/job-panel/README.md +86 -2
- package/registry/blocks/job-panel/block.json +3 -3
- package/registry/blocks/job-panel/demo.jsx +230 -3
- package/registry/blocks/job-panel/job-panel.jsx +169 -3
- package/registry/blocks/json-editor/README.md +133 -0
- package/registry/blocks/json-editor/block.json +10 -0
- package/registry/blocks/json-editor/demo.jsx +92 -0
- package/registry/blocks/json-editor/index.js +7 -0
- package/registry/blocks/json-editor/json-editor.jsx +305 -0
- package/registry/blocks/json-editor/json-tree.jsx +393 -0
- package/registry/blocks/json-editor/tree.js +225 -0
- package/registry/blocks/map/README.md +221 -0
- package/registry/blocks/map/block.json +14 -0
- package/registry/blocks/map/demo.jsx +201 -0
- package/registry/blocks/map/geo.js +198 -0
- package/registry/blocks/map/index.js +8 -0
- package/registry/blocks/map/list.jsx +128 -0
- package/registry/blocks/map/map-view.jsx +715 -0
- package/registry/blocks/map/maplibre.js +30 -0
- package/registry/blocks/map/marks.jsx +146 -0
- package/registry/blocks/map/theme.js +142 -0
- package/registry/blocks/menubar/README.md +109 -0
- package/registry/blocks/menubar/block.json +10 -0
- package/registry/blocks/menubar/demo.jsx +128 -0
- package/registry/blocks/menubar/index.js +4 -0
- package/registry/blocks/menubar/menubar.jsx +199 -0
- package/registry/blocks/mind-map/README.md +206 -0
- package/registry/blocks/mind-map/block.json +10 -0
- package/registry/blocks/mind-map/demo.jsx +103 -0
- package/registry/blocks/mind-map/index.js +31 -0
- package/registry/blocks/mind-map/mind-map.jsx +1125 -0
- package/registry/blocks/mind-map/topic.jsx +143 -0
- package/registry/blocks/mind-map/tree.js +645 -0
- package/registry/blocks/navigation-menu/README.md +124 -0
- package/registry/blocks/navigation-menu/block.json +10 -0
- package/registry/blocks/navigation-menu/demo.jsx +84 -0
- package/registry/blocks/navigation-menu/index.js +4 -0
- package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
- package/registry/blocks/order-detail/README.md +109 -0
- package/registry/blocks/order-detail/block.json +10 -0
- package/registry/blocks/order-detail/demo.jsx +88 -0
- package/registry/blocks/order-detail/index.js +4 -0
- package/registry/blocks/order-detail/order-detail.jsx +354 -0
- package/registry/blocks/org-chart/README.md +145 -0
- package/registry/blocks/org-chart/block.json +10 -0
- package/registry/blocks/org-chart/demo.jsx +94 -0
- package/registry/blocks/org-chart/index.js +7 -0
- package/registry/blocks/org-chart/org-chart.jsx +631 -0
- package/registry/blocks/org-chart/org.js +245 -0
- package/registry/blocks/org-chart/person.jsx +96 -0
- package/registry/blocks/page-builder/README.md +257 -0
- package/registry/blocks/page-builder/block.json +14 -0
- package/registry/blocks/page-builder/demo.jsx +145 -0
- package/registry/blocks/page-builder/grapes.js +18 -0
- package/registry/blocks/page-builder/index.js +11 -0
- package/registry/blocks/page-builder/page-builder.jsx +704 -0
- package/registry/blocks/page-builder/page-view.jsx +33 -0
- package/registry/blocks/page-builder/page.js +118 -0
- package/registry/blocks/page-builder/panels.jsx +588 -0
- package/registry/blocks/page-builder/sections.js +209 -0
- package/registry/blocks/page-builder/theme.js +87 -0
- package/registry/blocks/page-builder/thumbs.jsx +189 -0
- package/registry/blocks/page-builder/tokens.js +329 -0
- package/registry/blocks/payment-methods/README.md +104 -0
- package/registry/blocks/payment-methods/block.json +10 -0
- package/registry/blocks/payment-methods/demo.jsx +71 -0
- package/registry/blocks/payment-methods/index.js +4 -0
- package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
- package/registry/blocks/pdf-document/README.md +213 -0
- package/registry/blocks/pdf-document/block.json +13 -0
- package/registry/blocks/pdf-document/demo.jsx +136 -0
- package/registry/blocks/pdf-document/index.js +33 -0
- package/registry/blocks/pdf-document/money.js +83 -0
- package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
- package/registry/blocks/pdf-document/primitives.jsx +271 -0
- package/registry/blocks/pdf-document/quote.jsx +179 -0
- package/registry/blocks/pdf-document/theme.js +193 -0
- package/registry/blocks/pdf-viewer/README.md +191 -0
- package/registry/blocks/pdf-viewer/block.json +14 -0
- package/registry/blocks/pdf-viewer/demo.jsx +252 -0
- package/registry/blocks/pdf-viewer/helpers.js +270 -0
- package/registry/blocks/pdf-viewer/index.js +8 -0
- package/registry/blocks/pdf-viewer/notes.jsx +195 -0
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
- package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
- package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
- package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
- package/registry/blocks/product-detail/README.md +217 -0
- package/registry/blocks/product-detail/block.json +10 -0
- package/registry/blocks/product-detail/demo.jsx +233 -0
- package/registry/blocks/product-detail/index.js +7 -0
- package/registry/blocks/product-detail/price.jsx +115 -0
- package/registry/blocks/product-detail/product-detail.jsx +348 -0
- package/registry/blocks/product-detail/product-media.jsx +102 -0
- package/registry/blocks/product-detail/product-options.jsx +144 -0
- package/registry/blocks/product-grid/README.md +162 -0
- package/registry/blocks/product-grid/block.json +10 -0
- package/registry/blocks/product-grid/demo.jsx +255 -0
- package/registry/blocks/product-grid/index.js +5 -0
- package/registry/blocks/product-grid/product-card.jsx +232 -0
- package/registry/blocks/product-grid/product-grid.jsx +235 -0
- package/registry/blocks/record-form/README.md +196 -0
- package/registry/blocks/record-form/block.json +10 -0
- package/registry/blocks/record-form/demo.jsx +525 -0
- package/registry/blocks/record-form/index.js +4 -0
- package/registry/blocks/record-form/record-fields.jsx +457 -0
- package/registry/blocks/record-form/record-form.jsx +415 -0
- package/registry/blocks/record-form/rules.js +81 -0
- package/registry/blocks/record-notes/README.md +139 -0
- package/registry/blocks/record-notes/block.json +10 -0
- package/registry/blocks/record-notes/demo.jsx +179 -0
- package/registry/blocks/record-notes/index.js +4 -0
- package/registry/blocks/record-notes/record-notes.jsx +266 -0
- package/registry/blocks/search-dialog/README.md +108 -0
- package/registry/blocks/search-dialog/block.json +10 -0
- package/registry/blocks/search-dialog/demo.jsx +116 -0
- package/registry/blocks/search-dialog/index.js +3 -0
- package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
- package/registry/blocks/settings-list/README.md +171 -0
- package/registry/blocks/settings-list/block.json +10 -0
- package/registry/blocks/settings-list/demo.jsx +333 -0
- package/registry/blocks/settings-list/index.js +4 -0
- package/registry/blocks/settings-list/row-state.jsx +93 -0
- package/registry/blocks/settings-list/settings-list.jsx +349 -0
- package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
- package/registry/blocks/setup-checklist/README.md +142 -0
- package/registry/blocks/setup-checklist/block.json +10 -0
- package/registry/blocks/setup-checklist/demo.jsx +159 -0
- package/registry/blocks/setup-checklist/index.js +4 -0
- package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
- package/registry/blocks/share-dialog/README.md +113 -0
- package/registry/blocks/share-dialog/block.json +10 -0
- package/registry/blocks/share-dialog/demo.jsx +140 -0
- package/registry/blocks/share-dialog/index.js +3 -0
- package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
- package/registry/blocks/sidebar/README.md +190 -0
- package/registry/blocks/sidebar/block.json +43 -0
- package/registry/blocks/sidebar/demo.jsx +577 -0
- package/registry/blocks/sidebar/index.js +4 -0
- package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
- package/registry/blocks/sidebar/sidebar.jsx +864 -0
- package/registry/blocks/signature-pad/README.md +137 -0
- package/registry/blocks/signature-pad/block.json +13 -0
- package/registry/blocks/signature-pad/colors.js +115 -0
- package/registry/blocks/signature-pad/demo.jsx +94 -0
- package/registry/blocks/signature-pad/index.js +6 -0
- package/registry/blocks/signature-pad/pad.js +7 -0
- package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
- package/registry/blocks/signature-pad/signature.js +68 -0
- package/registry/blocks/sketch-canvas/README.md +280 -0
- package/registry/blocks/sketch-canvas/block.json +13 -0
- package/registry/blocks/sketch-canvas/demo.jsx +159 -0
- package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
- package/registry/blocks/sketch-canvas/index.js +9 -0
- package/registry/blocks/sketch-canvas/palette.js +226 -0
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
- package/registry/blocks/sketch-canvas/sketch.js +179 -0
- package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
- package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
- package/registry/blocks/sketch-canvas/stamps.js +104 -0
- package/registry/blocks/sketch-canvas/theme.js +131 -0
- package/registry/blocks/spreadsheet/README.md +307 -0
- package/registry/blocks/spreadsheet/block.json +13 -0
- package/registry/blocks/spreadsheet/cells.jsx +455 -0
- package/registry/blocks/spreadsheet/chrome.jsx +325 -0
- package/registry/blocks/spreadsheet/demo.jsx +177 -0
- package/registry/blocks/spreadsheet/grid.js +387 -0
- package/registry/blocks/spreadsheet/index.js +34 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
- package/registry/blocks/spreadsheet/types.js +473 -0
- package/registry/blocks/stat-cards/README.md +173 -0
- package/registry/blocks/stat-cards/block.json +10 -0
- package/registry/blocks/stat-cards/demo.jsx +257 -0
- package/registry/blocks/stat-cards/index.js +4 -0
- package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
- package/registry/blocks/stat-cards/usage.jsx +243 -0
- package/registry/blocks/task-list/README.md +176 -0
- package/registry/blocks/task-list/block.json +10 -0
- package/registry/blocks/task-list/demo.jsx +134 -0
- package/registry/blocks/task-list/index.js +5 -0
- package/registry/blocks/task-list/task-list.jsx +907 -0
- package/registry/blocks/task-model/README.md +455 -0
- package/registry/blocks/task-model/block.json +167 -0
- package/registry/blocks/task-model/changes.js +89 -0
- package/registry/blocks/task-model/dates.js +371 -0
- package/registry/blocks/task-model/demo.jsx +215 -0
- package/registry/blocks/task-model/dnd.jsx +240 -0
- package/registry/blocks/task-model/index.js +97 -0
- package/registry/blocks/task-model/model.js +919 -0
- package/registry/blocks/task-model/parts.jsx +449 -0
- package/registry/blocks/task-model/toolbar.jsx +271 -0
- package/registry/blocks/testimonials/README.md +139 -0
- package/registry/blocks/testimonials/block.json +11 -0
- package/registry/blocks/testimonials/demo.jsx +137 -0
- package/registry/blocks/testimonials/index.js +4 -0
- package/registry/blocks/testimonials/testimonials.jsx +430 -0
- package/registry/blocks/transaction-list/README.md +126 -0
- package/registry/blocks/transaction-list/block.json +10 -0
- package/registry/blocks/transaction-list/demo.jsx +79 -0
- package/registry/blocks/transaction-list/index.js +4 -0
- package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
- package/registry/blocks/whiteboard/README.md +179 -0
- package/registry/blocks/whiteboard/block.json +10 -0
- package/registry/blocks/whiteboard/demo.jsx +169 -0
- package/registry/blocks/whiteboard/index.js +6 -0
- package/registry/blocks/whiteboard/templates.js +150 -0
- package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
- package/src/install.mjs +18 -0
- package/src/shadcn.mjs +171 -0
- package/templates/next/files/README.md +145 -11
- package/templates/next/files/app/globals.css +55 -4
- package/templates/next/files/check/run.mjs +3 -3
- package/templates/next/files/components/parts/fixture.jsx +1 -1
- package/templates/next/files/components/parts/sample.js +15 -0
- package/templates/next/files/components/ui/avatar.jsx +141 -0
- package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
- package/templates/next/files/components/ui/button-group.jsx +70 -0
- package/templates/next/files/components/ui/button.jsx +132 -12
- package/templates/next/files/components/ui/calendar.jsx +609 -0
- package/templates/next/files/components/ui/carousel.jsx +281 -0
- package/templates/next/files/components/ui/collapsible.jsx +208 -0
- package/templates/next/files/components/ui/combobox.jsx +608 -0
- package/templates/next/files/components/ui/command.jsx +577 -0
- package/templates/next/files/components/ui/context-menu.jsx +191 -0
- package/templates/next/files/components/ui/date-picker.jsx +360 -0
- package/templates/next/files/components/ui/distribution.jsx +117 -0
- package/templates/next/files/components/ui/feedback.jsx +143 -0
- package/templates/next/files/components/ui/field.jsx +115 -3
- package/templates/next/files/components/ui/file-input.jsx +234 -0
- package/templates/next/files/components/ui/icon.jsx +130 -8
- package/templates/next/files/components/ui/image.jsx +143 -0
- package/templates/next/files/components/ui/index.js +47 -2
- package/templates/next/files/components/ui/input-group.jsx +213 -0
- package/templates/next/files/components/ui/input-otp.jsx +170 -0
- package/templates/next/files/components/ui/item.jsx +206 -0
- package/templates/next/files/components/ui/menu.jsx +454 -82
- package/templates/next/files/components/ui/notice.jsx +126 -14
- package/templates/next/files/components/ui/pagination.jsx +156 -0
- package/templates/next/files/components/ui/popover.jsx +284 -0
- package/templates/next/files/components/ui/radio.jsx +193 -0
- package/templates/next/files/components/ui/rating.jsx +131 -0
- package/templates/next/files/components/ui/resizable.jsx +338 -0
- package/templates/next/files/components/ui/scroll-area.jsx +123 -0
- package/templates/next/files/components/ui/separator.jsx +119 -0
- package/templates/next/files/components/ui/sheet.jsx +96 -11
- package/templates/next/files/components/ui/slider.jsx +174 -0
- package/templates/next/files/components/ui/stat.jsx +574 -0
- package/templates/next/files/components/ui/steps.jsx +338 -0
- package/templates/next/files/components/ui/swatch.jsx +33 -0
- package/templates/next/files/components/ui/table.jsx +130 -0
- package/templates/next/files/components/ui/toast.jsx +440 -0
- package/templates/next/files/components/ui/toggle.jsx +195 -0
- package/templates/next/files/components/ui/tooltip.jsx +270 -0
- package/templates/next/files/lib/sample.js +4 -12
- package/templates/next/template.json +264 -8
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { cx } from "./cx";
|
|
5
|
+
|
|
6
|
+
// ScrollArea — a box whose content scrolls inside it: a long list in a
|
|
7
|
+
// rail, a row of cards wider than the screen. The browser's own
|
|
8
|
+
// scrolling (touch, wheel, keys, momentum), with thin scrollbars in the
|
|
9
|
+
// workspace's colours. Give it a bound through className (max-h-80, h-64)
|
|
10
|
+
// or it simply grows.
|
|
11
|
+
//
|
|
12
|
+
// orientation vertical · horizontal · both
|
|
13
|
+
// fade true: the edges with more content past them fade out, so
|
|
14
|
+
// it is plain there is more — only while there is
|
|
15
|
+
// label the region's name for a screen reader ("Recent activity")
|
|
16
|
+
// ref the scrolling element itself (not the outer box): read and
|
|
17
|
+
// set scrollTop, call scrollTo — a message list that sticks
|
|
18
|
+
// to the bottom, a feed that keeps its place
|
|
19
|
+
// onScroll and every other prop (aria-busy, id, data-*) go on the
|
|
20
|
+
// scrolling element too
|
|
21
|
+
//
|
|
22
|
+
// When the content overflows, the box joins the tab order (a region with
|
|
23
|
+
// the label) so a keyboard can scroll it — Safari does not do that for a
|
|
24
|
+
// scroller on its own. When it fits, it is an ordinary box.
|
|
25
|
+
|
|
26
|
+
const AXES = {
|
|
27
|
+
vertical: "overflow-y-auto overflow-x-hidden",
|
|
28
|
+
horizontal: "overflow-x-auto overflow-y-hidden",
|
|
29
|
+
both: "overflow-auto",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Each edge fades over 2rem while there is content past it.
|
|
33
|
+
const FADES =
|
|
34
|
+
"data-[more-top]:mask-t-from-[calc(100%-2rem)] data-[more-bottom]:mask-b-from-[calc(100%-2rem)] " +
|
|
35
|
+
"data-[more-left]:mask-l-from-[calc(100%-2rem)] data-[more-right]:mask-r-from-[calc(100%-2rem)]";
|
|
36
|
+
|
|
37
|
+
export function ScrollArea({ orientation = "vertical", fade = false, label, className, children, ref: outer, ...rest }) {
|
|
38
|
+
const ref = useRef(null);
|
|
39
|
+
const setRef = useCallback(
|
|
40
|
+
(el) => {
|
|
41
|
+
ref.current = el;
|
|
42
|
+
if (typeof outer === "function") return outer(el);
|
|
43
|
+
if (outer) outer.current = el;
|
|
44
|
+
},
|
|
45
|
+
[outer],
|
|
46
|
+
);
|
|
47
|
+
const [edges, setEdges] = useState({ scrolls: false, top: false, bottom: false, left: false, right: false });
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const el = ref.current;
|
|
51
|
+
if (!el) return;
|
|
52
|
+
const measure = () => {
|
|
53
|
+
const x = Math.abs(el.scrollLeft);
|
|
54
|
+
const overX = el.scrollWidth - el.clientWidth > 1;
|
|
55
|
+
const overY = el.scrollHeight - el.clientHeight > 1;
|
|
56
|
+
const next = {
|
|
57
|
+
scrolls: (orientation !== "horizontal" && overY) || (orientation !== "vertical" && overX),
|
|
58
|
+
top: overY && el.scrollTop > 1,
|
|
59
|
+
bottom: overY && el.scrollTop + el.clientHeight < el.scrollHeight - 1,
|
|
60
|
+
left: overX && x > 1,
|
|
61
|
+
right: overX && x + el.clientWidth < el.scrollWidth - 1,
|
|
62
|
+
};
|
|
63
|
+
setEdges((prev) => (Object.keys(next).every((k) => prev[k] === next[k]) ? prev : next));
|
|
64
|
+
};
|
|
65
|
+
measure();
|
|
66
|
+
el.addEventListener("scroll", measure, { passive: true });
|
|
67
|
+
if (typeof ResizeObserver === "undefined") return () => el.removeEventListener("scroll", measure);
|
|
68
|
+
// The box and each child: content growing inside a fixed box changes
|
|
69
|
+
// the overflow without resizing the box.
|
|
70
|
+
const ro = new ResizeObserver(measure);
|
|
71
|
+
const watch = () => {
|
|
72
|
+
ro.disconnect();
|
|
73
|
+
ro.observe(el);
|
|
74
|
+
for (const child of el.children) ro.observe(child);
|
|
75
|
+
};
|
|
76
|
+
watch();
|
|
77
|
+
const mo = new MutationObserver(() => {
|
|
78
|
+
watch();
|
|
79
|
+
measure();
|
|
80
|
+
});
|
|
81
|
+
mo.observe(el, { childList: true });
|
|
82
|
+
return () => {
|
|
83
|
+
el.removeEventListener("scroll", measure);
|
|
84
|
+
ro.disconnect();
|
|
85
|
+
mo.disconnect();
|
|
86
|
+
};
|
|
87
|
+
}, [orientation]);
|
|
88
|
+
|
|
89
|
+
const show = (edge) => (fade && edges[edge] ? "" : undefined);
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
// The ring sits on this outer box: a mask on the scroller would cut
|
|
93
|
+
// off a ring drawn around it.
|
|
94
|
+
<div
|
|
95
|
+
className={cx(
|
|
96
|
+
"flex min-h-0 min-w-0 flex-col rounded-md",
|
|
97
|
+
"has-[>[data-scroller]:focus-visible]:ring-2 has-[>[data-scroller]:focus-visible]:ring-ring",
|
|
98
|
+
className,
|
|
99
|
+
)}
|
|
100
|
+
>
|
|
101
|
+
<div
|
|
102
|
+
{...rest}
|
|
103
|
+
ref={setRef}
|
|
104
|
+
data-scroller=""
|
|
105
|
+
tabIndex={edges.scrolls ? 0 : undefined}
|
|
106
|
+
role={edges.scrolls && label ? "region" : undefined}
|
|
107
|
+
aria-label={edges.scrolls ? label : undefined}
|
|
108
|
+
data-more-top={show("top")}
|
|
109
|
+
data-more-bottom={show("bottom")}
|
|
110
|
+
data-more-left={show("left")}
|
|
111
|
+
data-more-right={show("right")}
|
|
112
|
+
className={cx(
|
|
113
|
+
"min-h-0 flex-1 rounded-[inherit] outline-none",
|
|
114
|
+
"scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent",
|
|
115
|
+
AXES[orientation] ?? AXES.vertical,
|
|
116
|
+
fade && FADES,
|
|
117
|
+
)}
|
|
118
|
+
>
|
|
119
|
+
{children}
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { cx } from "./cx";
|
|
2
|
+
|
|
3
|
+
// Small static parts that shape a layout: a separator, a key cap, a box
|
|
4
|
+
// that keeps its ratio. Server-safe (no hooks).
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A hairline between groups. Decorative by default — most lines only
|
|
8
|
+
* group what spacing already groups, and a screen reader should not
|
|
9
|
+
* announce them. Pass `decorative={false}` when the line divides two
|
|
10
|
+
* sections a reader should know about (role=separator).
|
|
11
|
+
*
|
|
12
|
+
* orientation horizontal (full width) · vertical (full height of a
|
|
13
|
+
* flex row: toolbar groups, breadcrumb-like rows)
|
|
14
|
+
* decorative true (hidden from readers) · false (a separator)
|
|
15
|
+
* label horizontal only: a word on the line ("or")
|
|
16
|
+
*/
|
|
17
|
+
export function Separator({ orientation = "horizontal", decorative = true, label, className }) {
|
|
18
|
+
const vertical = orientation === "vertical";
|
|
19
|
+
const a11y = decorative
|
|
20
|
+
? { role: "none" }
|
|
21
|
+
: { role: "separator", "aria-orientation": vertical ? "vertical" : undefined };
|
|
22
|
+
if (vertical) {
|
|
23
|
+
return <div {...a11y} className={cx("w-px shrink-0 self-stretch bg-border", className)} />;
|
|
24
|
+
}
|
|
25
|
+
if (label) {
|
|
26
|
+
return (
|
|
27
|
+
<div {...a11y} className={cx("flex items-center gap-3 text-xs text-muted-foreground", className)}>
|
|
28
|
+
<span className="h-px flex-1 bg-border" />
|
|
29
|
+
<span>{label}</span>
|
|
30
|
+
<span className="h-px flex-1 bg-border" />
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return <div {...a11y} className={cx("h-px w-full shrink-0 bg-border", className)} />;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Symbols a reader cannot say; each is shown to the eye and spelled out
|
|
38
|
+
// to the ear.
|
|
39
|
+
const KEY_NAMES = {
|
|
40
|
+
"⌘": "Command",
|
|
41
|
+
"⌥": "Option",
|
|
42
|
+
"⇧": "Shift",
|
|
43
|
+
"⌃": "Control",
|
|
44
|
+
"↵": "Enter",
|
|
45
|
+
"⏎": "Return",
|
|
46
|
+
"⌫": "Backspace",
|
|
47
|
+
"⌦": "Delete",
|
|
48
|
+
"⎋": "Escape",
|
|
49
|
+
"⇥": "Tab",
|
|
50
|
+
"↑": "Up",
|
|
51
|
+
"↓": "Down",
|
|
52
|
+
"←": "Left",
|
|
53
|
+
"→": "Right",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** One key, as printed on the keyboard: ⌘, Esc, K. A native <kbd>. */
|
|
57
|
+
export function Kbd({ className, children }) {
|
|
58
|
+
const name = typeof children === "string" ? KEY_NAMES[children] : undefined;
|
|
59
|
+
return (
|
|
60
|
+
<kbd
|
|
61
|
+
className={cx(
|
|
62
|
+
"inline-flex h-5 min-w-5 items-center justify-center rounded-sm border border-border bg-muted px-1",
|
|
63
|
+
"font-sans text-2xs font-medium leading-none text-muted-foreground",
|
|
64
|
+
className,
|
|
65
|
+
)}
|
|
66
|
+
>
|
|
67
|
+
{name ? (
|
|
68
|
+
<>
|
|
69
|
+
<span aria-hidden="true">{children}</span>
|
|
70
|
+
<span className="sr-only">{name}</span>
|
|
71
|
+
</>
|
|
72
|
+
) : (
|
|
73
|
+
children
|
|
74
|
+
)}
|
|
75
|
+
</kbd>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** A combo pressed together (⌘ K). `keys` is ["⌘", "K"]; children work
|
|
80
|
+
* too. Nested <kbd>s, which is how HTML spells a key combination. */
|
|
81
|
+
export function KbdGroup({ keys, className, children }) {
|
|
82
|
+
return (
|
|
83
|
+
<kbd className={cx("inline-flex items-center gap-1 font-sans", className)}>
|
|
84
|
+
{keys ? keys.map((k, i) => <Kbd key={i}>{k}</Kbd>) : children}
|
|
85
|
+
</kbd>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const RATIOS = {
|
|
90
|
+
square: "aspect-square",
|
|
91
|
+
video: "aspect-video",
|
|
92
|
+
portrait: "aspect-3/4",
|
|
93
|
+
photo: "aspect-4/3",
|
|
94
|
+
wide: "aspect-21/9",
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* A box that keeps its shape as its width changes — a thumbnail, a video,
|
|
99
|
+
* a map. Its one child fills it (an <img> is cropped to cover).
|
|
100
|
+
*
|
|
101
|
+
* ratio square · video (16:9) · portrait (3:4) · photo (4:3) · wide
|
|
102
|
+
* (21:9), or a number (width / height, e.g. 2)
|
|
103
|
+
*/
|
|
104
|
+
export function AspectRatio({ ratio = "video", className, children }) {
|
|
105
|
+
const named = typeof ratio === "string" ? RATIOS[ratio] : undefined;
|
|
106
|
+
return (
|
|
107
|
+
<div
|
|
108
|
+
className={cx(
|
|
109
|
+
"relative w-full overflow-hidden",
|
|
110
|
+
named ?? (typeof ratio === "number" ? undefined : RATIOS.video),
|
|
111
|
+
"[&>*]:absolute [&>*]:inset-0 [&>*]:size-full [&>img]:object-cover",
|
|
112
|
+
className,
|
|
113
|
+
)}
|
|
114
|
+
style={typeof ratio === "number" && ratio > 0 ? { aspectRatio: ratio } : undefined}
|
|
115
|
+
>
|
|
116
|
+
{children}
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useEffect, useRef } from "react";
|
|
3
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
4
4
|
import { cx } from "./cx";
|
|
5
5
|
import { Button, IconButton } from "./button";
|
|
6
|
+
import { Checkbox, Input } from "./field";
|
|
6
7
|
|
|
7
8
|
// Sheet — the one overlay. A native <dialog> (focus trap, Esc, scroll
|
|
8
9
|
// lock and the top layer come from the browser), docked to the side the
|
|
9
10
|
// surface asks for. Mobile first: on a narrow window every side becomes
|
|
10
11
|
// a bottom sheet the thumb can reach. Controlled: `open` + `onClose`.
|
|
11
12
|
//
|
|
12
|
-
// side end (a rail beside the work; the default) ·
|
|
13
|
-
// ·
|
|
13
|
+
// side end (a rail beside the work; the default) · start (a drawer
|
|
14
|
+
// from the leading edge, as navigation opens) · center (a
|
|
15
|
+
// dialog) · bottom
|
|
16
|
+
// title, description the header; the title names the dialog
|
|
17
|
+
// footer a row of buttons under the body
|
|
18
|
+
// bare true: no header and a flush body (no padding) — for a panel
|
|
19
|
+
// that draws its own top, as CommandDialog does. Esc and a
|
|
20
|
+
// press outside still close it. Give it `label`.
|
|
21
|
+
// label the dialog's name for a screen reader when no `title` shows
|
|
14
22
|
//
|
|
15
23
|
// Confirm below is the "delete this?" case — never window.confirm().
|
|
16
24
|
|
|
@@ -18,12 +26,17 @@ const SIDES = {
|
|
|
18
26
|
end:
|
|
19
27
|
"inset-y-0 right-0 left-auto h-dvh max-h-none w-full max-w-md rounded-none border-l " +
|
|
20
28
|
"max-sm:inset-x-0 max-sm:top-auto max-sm:bottom-0 max-sm:h-auto max-sm:max-h-[85dvh] max-sm:max-w-none max-sm:rounded-t-xl max-sm:border-l-0 max-sm:border-t",
|
|
29
|
+
start:
|
|
30
|
+
"inset-y-0 left-0 right-auto h-dvh max-h-none w-full max-w-md rounded-none border-r " +
|
|
31
|
+
"max-sm:inset-x-0 max-sm:top-auto max-sm:bottom-0 max-sm:h-auto max-sm:max-h-[85dvh] max-sm:max-w-none max-sm:rounded-t-xl max-sm:border-r-0 max-sm:border-t",
|
|
21
32
|
center: "m-auto w-[calc(100%-2rem)] max-w-lg rounded-lg border max-sm:mb-0 max-sm:mt-auto max-sm:w-full max-sm:max-w-none max-sm:rounded-b-none max-sm:rounded-t-xl",
|
|
22
33
|
bottom: "inset-x-0 top-auto bottom-0 w-full max-w-none max-h-[85dvh] rounded-t-xl border-t",
|
|
23
34
|
};
|
|
24
35
|
|
|
25
|
-
export function Sheet({ open, onClose, title, description, side = "end", footer, className, children }) {
|
|
36
|
+
export function Sheet({ open, onClose, title, description, side = "end", footer, bare = false, label, className, children }) {
|
|
26
37
|
const ref = useRef(null);
|
|
38
|
+
const titleId = useId();
|
|
39
|
+
const named = Boolean(title) && !bare;
|
|
27
40
|
|
|
28
41
|
useEffect(() => {
|
|
29
42
|
const el = ref.current;
|
|
@@ -44,19 +57,20 @@ export function Sheet({ open, onClose, title, description, side = "end", footer,
|
|
|
44
57
|
SIDES[side] ?? SIDES.end,
|
|
45
58
|
className,
|
|
46
59
|
)}
|
|
47
|
-
aria-labelledby={
|
|
60
|
+
aria-labelledby={named ? titleId : undefined}
|
|
61
|
+
aria-label={named ? undefined : label}
|
|
48
62
|
>
|
|
49
63
|
<div className="flex min-h-0 flex-1 flex-col">
|
|
50
|
-
{title || onClose ? (
|
|
64
|
+
{!bare && (title || onClose) ? (
|
|
51
65
|
<header className="flex items-start justify-between gap-3 border-b border-border px-4 py-3">
|
|
52
66
|
<div className="min-w-0">
|
|
53
|
-
{title ? <h2 id=
|
|
67
|
+
{title ? <h2 id={titleId} className="text-base font-semibold leading-tight">{title}</h2> : null}
|
|
54
68
|
{description ? <p className="mt-0.5 text-sm text-muted-foreground">{description}</p> : null}
|
|
55
69
|
</div>
|
|
56
70
|
<IconButton icon="x" label="Close" size="sm" onClick={() => ref.current?.close()} className="-mr-2" />
|
|
57
71
|
</header>
|
|
58
72
|
) : null}
|
|
59
|
-
<div className="min-h-0 flex-1 overflow-y-auto px-4 py-4">{children}</div>
|
|
73
|
+
<div className={cx("min-h-0 flex-1 overflow-y-auto", !bare && "px-4 py-4")}>{children}</div>
|
|
60
74
|
{footer ? <footer className="flex flex-wrap justify-end gap-2 border-t border-border px-4 py-3">{footer}</footer> : null}
|
|
61
75
|
</div>
|
|
62
76
|
</dialog>
|
|
@@ -64,8 +78,45 @@ export function Sheet({ open, onClose, title, description, side = "end", footer,
|
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
/** A yes/no with the consequence spelled out. `tone="danger"` for a
|
|
67
|
-
* destructive confirm. Resolves through `onConfirm`; closes either way.
|
|
68
|
-
|
|
81
|
+
* destructive confirm. Resolves through `onConfirm`; closes either way.
|
|
82
|
+
*
|
|
83
|
+
* consequences lines that will happen ("14 contacts are deleted"), a
|
|
84
|
+
* muted bullet list under the body
|
|
85
|
+
* requireText the exact text to type ("acme-corp") before Confirm
|
|
86
|
+
* unlocks — for the one delete that cannot come back
|
|
87
|
+
* acknowledge a checkbox label that must be ticked first ("I have
|
|
88
|
+
* exported what I need")
|
|
89
|
+
*
|
|
90
|
+
* Confirm stays disabled until each gate given is met; both reset when
|
|
91
|
+
* the dialog opens again. Without them it is the plain yes/no. */
|
|
92
|
+
export function Confirm({
|
|
93
|
+
open,
|
|
94
|
+
onClose,
|
|
95
|
+
onConfirm,
|
|
96
|
+
title,
|
|
97
|
+
body,
|
|
98
|
+
confirmLabel = "Confirm",
|
|
99
|
+
cancelLabel = "Cancel",
|
|
100
|
+
tone = "neutral",
|
|
101
|
+
busy,
|
|
102
|
+
consequences,
|
|
103
|
+
requireText,
|
|
104
|
+
acknowledge,
|
|
105
|
+
}) {
|
|
106
|
+
const [typed, setTyped] = useState("");
|
|
107
|
+
const [ticked, setTicked] = useState(false);
|
|
108
|
+
const typeId = useId();
|
|
109
|
+
const tickId = useId();
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (!open) return;
|
|
113
|
+
setTyped("");
|
|
114
|
+
setTicked(false);
|
|
115
|
+
}, [open]);
|
|
116
|
+
|
|
117
|
+
const lines = Array.isArray(consequences) ? consequences.filter(Boolean) : [];
|
|
118
|
+
const held = (requireText ? typed !== requireText : false) || (acknowledge ? !ticked : false);
|
|
119
|
+
|
|
69
120
|
return (
|
|
70
121
|
<Sheet
|
|
71
122
|
open={open}
|
|
@@ -77,13 +128,47 @@ export function Confirm({ open, onClose, onConfirm, title, body, confirmLabel =
|
|
|
77
128
|
<Button variant="quiet" onClick={onClose} disabled={busy}>
|
|
78
129
|
{cancelLabel}
|
|
79
130
|
</Button>
|
|
80
|
-
<Button variant={tone === "danger" ? "danger" : "primary"} onClick={onConfirm} disabled={busy}>
|
|
131
|
+
<Button variant={tone === "danger" ? "danger" : "primary"} onClick={onConfirm} disabled={busy || held}>
|
|
81
132
|
{busy ? "Working…" : confirmLabel}
|
|
82
133
|
</Button>
|
|
83
134
|
</>
|
|
84
135
|
}
|
|
85
136
|
>
|
|
86
137
|
{body ? <p className="text-sm text-muted-foreground">{body}</p> : null}
|
|
138
|
+
{lines.length ? (
|
|
139
|
+
<ul className={cx("list-disc space-y-1 ps-5 text-sm text-muted-foreground marker:text-muted-foreground", body && "mt-3")}>
|
|
140
|
+
{lines.map((line, i) => (
|
|
141
|
+
<li key={i}>{line}</li>
|
|
142
|
+
))}
|
|
143
|
+
</ul>
|
|
144
|
+
) : null}
|
|
145
|
+
{requireText ? (
|
|
146
|
+
<div className={cx("grid gap-1.5", (body || lines.length) && "mt-4")}>
|
|
147
|
+
<label htmlFor={typeId} className="text-sm text-foreground">
|
|
148
|
+
Type <span className="break-all font-mono font-medium">{requireText}</span> to confirm
|
|
149
|
+
</label>
|
|
150
|
+
<Input
|
|
151
|
+
id={typeId}
|
|
152
|
+
value={typed}
|
|
153
|
+
onChange={(e) => setTyped(e.target.value)}
|
|
154
|
+
autoComplete="off"
|
|
155
|
+
autoCapitalize="off"
|
|
156
|
+
autoCorrect="off"
|
|
157
|
+
spellCheck={false}
|
|
158
|
+
disabled={busy}
|
|
159
|
+
/>
|
|
160
|
+
</div>
|
|
161
|
+
) : null}
|
|
162
|
+
{acknowledge ? (
|
|
163
|
+
<Checkbox
|
|
164
|
+
id={tickId}
|
|
165
|
+
checked={ticked}
|
|
166
|
+
onChange={(e) => setTicked(e.target.checked)}
|
|
167
|
+
label={acknowledge}
|
|
168
|
+
disabled={busy}
|
|
169
|
+
className={cx((body || lines.length || requireText) && "mt-2")}
|
|
170
|
+
/>
|
|
171
|
+
) : null}
|
|
87
172
|
</Sheet>
|
|
88
173
|
);
|
|
89
174
|
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useRef, useState } from "react";
|
|
4
|
+
import { cx } from "./cx";
|
|
5
|
+
|
|
6
|
+
// Slider — pick a number (or a span of numbers) by dragging. The native
|
|
7
|
+
// <input type="range"> underneath, so keyboard (arrows, Page Up/Down,
|
|
8
|
+
// Home/End), touch, forms and screen readers are the browser's; the
|
|
9
|
+
// track, the filled part and the thumb are drawn from tokens. The input
|
|
10
|
+
// is 44px tall however thin the track looks: the thumb is what a thumb
|
|
11
|
+
// hits. Controlled (`value` + `onChange`) or not (`defaultValue`).
|
|
12
|
+
//
|
|
13
|
+
// value a number — or [low, high] for a range: two thumbs on one
|
|
14
|
+
// track, each its own native input (labels "Minimum" and
|
|
15
|
+
// "Maximum"; `thumbLabels` renames them). A range can never
|
|
16
|
+
// cross: low stops at high - `minGap`.
|
|
17
|
+
// onChange (value) → the number, or [low, high]; not an event
|
|
18
|
+
// min, max, step as the native input (0, 100, 1)
|
|
19
|
+
// showValue print the value beside the track, through `format`
|
|
20
|
+
// format (n) → string — "$40", "12 seats"; also what a screen
|
|
21
|
+
// reader says (aria-valuetext)
|
|
22
|
+
// label the accessible name when no <Field> label points at `id`
|
|
23
|
+
// name the form field; a range submits two values under it
|
|
24
|
+
//
|
|
25
|
+
// Use it where the exact number matters less than its place in a span
|
|
26
|
+
// (budget, seats, a threshold). A value someone will type — a price, a
|
|
27
|
+
// quantity to the unit — is an Input with type="number".
|
|
28
|
+
|
|
29
|
+
// The native input, stripped to a transparent strip with a drawn thumb.
|
|
30
|
+
// Written out per engine: Tailwind reads classes literally, never a
|
|
31
|
+
// built string. The wrapper sets --rail (the input's height: 44px, the
|
|
32
|
+
// target) and --thumb (the drawn thumb): WebKit puts the thumb at the top
|
|
33
|
+
// of its track, so the margin centres it, and the fill below measures on
|
|
34
|
+
// --thumb to meet the thumb's centre.
|
|
35
|
+
const RANGE =
|
|
36
|
+
"absolute inset-0 h-full w-full appearance-none bg-transparent outline-none cursor-pointer disabled:cursor-not-allowed " +
|
|
37
|
+
"[&::-webkit-slider-runnable-track]:h-full [&::-webkit-slider-runnable-track]:bg-transparent " +
|
|
38
|
+
"[&::-webkit-slider-thumb]:mt-[calc((var(--rail)-var(--thumb))/2)] [&::-webkit-slider-thumb]:size-[var(--thumb)] [&::-webkit-slider-thumb]:appearance-none " +
|
|
39
|
+
"[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background " +
|
|
40
|
+
"[&::-webkit-slider-thumb]:shadow-sm [&::-webkit-slider-thumb]:transition-shadow " +
|
|
41
|
+
"hover:[&::-webkit-slider-thumb]:ring-4 hover:[&::-webkit-slider-thumb]:ring-ring/15 " +
|
|
42
|
+
"active:[&::-webkit-slider-thumb]:ring-4 active:[&::-webkit-slider-thumb]:ring-ring/25 " +
|
|
43
|
+
"focus-visible:[&::-webkit-slider-thumb]:ring-2 focus-visible:[&::-webkit-slider-thumb]:ring-ring focus-visible:[&::-webkit-slider-thumb]:ring-offset-2 focus-visible:[&::-webkit-slider-thumb]:ring-offset-background " +
|
|
44
|
+
"[&::-moz-range-track]:bg-transparent [&::-moz-range-progress]:bg-transparent " +
|
|
45
|
+
"[&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-[var(--thumb)] [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-2 " +
|
|
46
|
+
"[&::-moz-range-thumb]:border-primary [&::-moz-range-thumb]:bg-background [&::-moz-range-thumb]:shadow-sm [&::-moz-range-thumb]:transition-shadow " +
|
|
47
|
+
"hover:[&::-moz-range-thumb]:ring-4 hover:[&::-moz-range-thumb]:ring-ring/15 " +
|
|
48
|
+
"active:[&::-moz-range-thumb]:ring-4 active:[&::-moz-range-thumb]:ring-ring/25 " +
|
|
49
|
+
"focus-visible:[&::-moz-range-thumb]:ring-2 focus-visible:[&::-moz-range-thumb]:ring-ring focus-visible:[&::-moz-range-thumb]:ring-offset-2 focus-visible:[&::-moz-range-thumb]:ring-offset-background";
|
|
50
|
+
|
|
51
|
+
// Two inputs share one track: neither takes the pointer except at its
|
|
52
|
+
// own thumb, so each thumb drags on its own and the other stays put.
|
|
53
|
+
const TWIN =
|
|
54
|
+
"pointer-events-none [&::-webkit-slider-thumb]:pointer-events-auto [&::-moz-range-thumb]:pointer-events-auto";
|
|
55
|
+
|
|
56
|
+
const clamp = (n, lo, hi) => Math.min(hi, Math.max(lo, n));
|
|
57
|
+
|
|
58
|
+
export function Slider({
|
|
59
|
+
id,
|
|
60
|
+
value,
|
|
61
|
+
defaultValue,
|
|
62
|
+
onChange,
|
|
63
|
+
min = 0,
|
|
64
|
+
max = 100,
|
|
65
|
+
step = 1,
|
|
66
|
+
minGap = 0,
|
|
67
|
+
showValue,
|
|
68
|
+
format = String,
|
|
69
|
+
label,
|
|
70
|
+
thumbLabels = ["Minimum", "Maximum"],
|
|
71
|
+
name,
|
|
72
|
+
disabled,
|
|
73
|
+
className,
|
|
74
|
+
...rest
|
|
75
|
+
}) {
|
|
76
|
+
const [own, setOwn] = useState(defaultValue ?? min);
|
|
77
|
+
const current = value ?? own;
|
|
78
|
+
const range = Array.isArray(current);
|
|
79
|
+
const [low, high] = range ? current : [min, current];
|
|
80
|
+
const lowRef = useRef(null);
|
|
81
|
+
const highRef = useRef(null);
|
|
82
|
+
|
|
83
|
+
function set(next) {
|
|
84
|
+
if (value === undefined) setOwn(next);
|
|
85
|
+
onChange?.(next);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const span = max - min || 1;
|
|
89
|
+
const p = (n) => (clamp(n, min, max) - min) / span;
|
|
90
|
+
// The native thumb travels inside the track, half a thumb in from each
|
|
91
|
+
// end; the fill measures on that same inner span so it meets the
|
|
92
|
+
// thumb's centre at every value.
|
|
93
|
+
const at = (f) => `calc(var(--thumb) / 2 + ${f} * (100% - var(--thumb)))`;
|
|
94
|
+
const fill = range
|
|
95
|
+
? { left: at(p(low)), width: `calc(${p(high) - p(low)} * (100% - var(--thumb)))` }
|
|
96
|
+
: { left: 0, width: at(p(high)) };
|
|
97
|
+
|
|
98
|
+
// A press on the bare track (not a thumb) moves the nearer thumb there.
|
|
99
|
+
// A single slider needs none of this: its input takes the press itself.
|
|
100
|
+
function onTrackDown(e) {
|
|
101
|
+
if (!range || disabled || e.target !== e.currentTarget) return;
|
|
102
|
+
const box = e.currentTarget.getBoundingClientRect();
|
|
103
|
+
const thumb = parseFloat(getComputedStyle(e.currentTarget).getPropertyValue("--thumb")) * parseFloat(getComputedStyle(document.documentElement).fontSize) || 20;
|
|
104
|
+
const f = clamp((e.clientX - box.left - thumb / 2) / (box.width - thumb), 0, 1);
|
|
105
|
+
const n = clamp(Math.round((min + f * span - min) / step) * step + min, min, max);
|
|
106
|
+
if (Math.abs(n - low) <= Math.abs(n - high)) {
|
|
107
|
+
set([Math.min(n, high - minGap), high]);
|
|
108
|
+
lowRef.current?.focus();
|
|
109
|
+
} else {
|
|
110
|
+
set([low, Math.max(n, low + minGap)]);
|
|
111
|
+
highRef.current?.focus();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const shown = range ? `${format(low)} – ${format(high)}` : format(high);
|
|
116
|
+
const common = { type: "range", min, max, step, disabled, name };
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div className={cx("flex w-full items-center gap-3", disabled && "opacity-50", className)}>
|
|
120
|
+
<div
|
|
121
|
+
className="relative h-[var(--rail)] min-w-0 flex-1"
|
|
122
|
+
style={{ "--rail": "2.75rem", "--thumb": "1.25rem" }}
|
|
123
|
+
onPointerDown={onTrackDown}
|
|
124
|
+
>
|
|
125
|
+
<span aria-hidden="true" className="pointer-events-none absolute inset-x-0 top-1/2 h-1.5 -translate-y-1/2 rounded-full bg-muted" />
|
|
126
|
+
<span aria-hidden="true" className="pointer-events-none absolute top-1/2 h-1.5 -translate-y-1/2 rounded-full bg-primary" style={fill} />
|
|
127
|
+
{range ? (
|
|
128
|
+
<>
|
|
129
|
+
<input
|
|
130
|
+
{...common}
|
|
131
|
+
ref={lowRef}
|
|
132
|
+
id={id}
|
|
133
|
+
value={low}
|
|
134
|
+
aria-label={label ? `${label}, ${thumbLabels[0].toLowerCase()}` : thumbLabels[0]}
|
|
135
|
+
aria-valuetext={format(low)}
|
|
136
|
+
onChange={(e) => set([Math.min(Number(e.target.value), high - minGap), high])}
|
|
137
|
+
// The upper half of the track belongs to whichever thumb can
|
|
138
|
+
// still move there: when both sit at the top, low must be on
|
|
139
|
+
// top or it could never be dragged back down.
|
|
140
|
+
className={cx(RANGE, TWIN, p(low) > 0.5 ? "z-20" : "z-10")}
|
|
141
|
+
{...rest}
|
|
142
|
+
/>
|
|
143
|
+
<input
|
|
144
|
+
{...common}
|
|
145
|
+
ref={highRef}
|
|
146
|
+
id={id ? `${id}-max` : undefined}
|
|
147
|
+
value={high}
|
|
148
|
+
aria-label={label ? `${label}, ${thumbLabels[1].toLowerCase()}` : thumbLabels[1]}
|
|
149
|
+
aria-valuetext={format(high)}
|
|
150
|
+
onChange={(e) => set([low, Math.max(Number(e.target.value), low + minGap)])}
|
|
151
|
+
className={cx(RANGE, TWIN, "z-10")}
|
|
152
|
+
/>
|
|
153
|
+
</>
|
|
154
|
+
) : (
|
|
155
|
+
<input
|
|
156
|
+
{...common}
|
|
157
|
+
id={id}
|
|
158
|
+
value={high}
|
|
159
|
+
aria-label={label}
|
|
160
|
+
aria-valuetext={format === String ? undefined : format(high)}
|
|
161
|
+
onChange={(e) => set(Number(e.target.value))}
|
|
162
|
+
className={RANGE}
|
|
163
|
+
{...rest}
|
|
164
|
+
/>
|
|
165
|
+
)}
|
|
166
|
+
</div>
|
|
167
|
+
{showValue ? (
|
|
168
|
+
<output htmlFor={range && id ? `${id} ${id}-max` : id} data-nums className="shrink-0 text-right text-sm text-foreground">
|
|
169
|
+
{shown}
|
|
170
|
+
</output>
|
|
171
|
+
) : null}
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
}
|