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
package/src/cli.mjs
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
// agent reading a terminal: short lines, what changed, what to run next.
|
|
4
4
|
// --json is the same result as one object, for the platform.
|
|
5
5
|
|
|
6
|
-
import { resolve } from "node:path";
|
|
6
|
+
import { delimiter, resolve } from "node:path";
|
|
7
7
|
import { CliError, add, diff, init, remove, update } from "./install.mjs";
|
|
8
|
-
import { loadItems, loadTemplate, packageInfo, readmeOf, searchItems, suggest, templateNames } from "./registry.mjs";
|
|
8
|
+
import { loadItems, loadTemplate, packageInfo, readmeOf, searchItems, suggest, templateNames, useExtraBlockRoots } from "./registry.mjs";
|
|
9
9
|
|
|
10
10
|
const COMMANDS = {
|
|
11
11
|
init: "init",
|
|
@@ -139,8 +139,10 @@ function addText(r) {
|
|
|
139
139
|
return lines.join("\n");
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
const kind = (item) => (item.tier === "premium" ? "premium" : item.type);
|
|
143
|
+
|
|
142
144
|
function itemLine(item) {
|
|
143
|
-
return ` ${item.name.padEnd(18)} ${item.
|
|
145
|
+
return ` ${item.name.padEnd(18)} ${kind(item).padEnd(10)} ${clip(item.description, 72)}`;
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
function searchText(query, matches) {
|
|
@@ -155,7 +157,7 @@ function searchText(query, matches) {
|
|
|
155
157
|
|
|
156
158
|
function viewText(item, readme) {
|
|
157
159
|
const { version } = packageInfo();
|
|
158
|
-
const head = `${item.name} · ${item.type} · makersclaw ${version}`;
|
|
160
|
+
const head = `${item.name} · ${item.type}${item.tier === "premium" ? " · premium" : ""} · makersclaw ${version}`;
|
|
159
161
|
if (readme) return `${head}\n\n${readme.trimEnd()}`;
|
|
160
162
|
const folder = item.type === "part" ? "parts" : "ui";
|
|
161
163
|
return [
|
|
@@ -179,7 +181,7 @@ function listText(items) {
|
|
|
179
181
|
const of = items.filter((i) => i.type === type);
|
|
180
182
|
if (!of.length) continue;
|
|
181
183
|
lines.push("", label);
|
|
182
|
-
for (const i of of) lines.push(` ${i.name.padEnd(18)} ${clip(i.description, 80)}`);
|
|
184
|
+
for (const i of of) lines.push(` ${i.name.padEnd(18)} ${i.tier === "premium" ? "premium · " : ""}${clip(i.description, 80)}`);
|
|
183
185
|
}
|
|
184
186
|
return lines.join("\n");
|
|
185
187
|
}
|
|
@@ -271,6 +273,7 @@ function summary(item) {
|
|
|
271
273
|
return {
|
|
272
274
|
name: item.name,
|
|
273
275
|
type: item.type,
|
|
276
|
+
tier: item.tier,
|
|
274
277
|
title: item.title,
|
|
275
278
|
description: item.description,
|
|
276
279
|
useWhen: item.useWhen || undefined,
|
|
@@ -281,7 +284,17 @@ function summary(item) {
|
|
|
281
284
|
};
|
|
282
285
|
}
|
|
283
286
|
|
|
284
|
-
|
|
287
|
+
/** The block roots the platform names beside the package's own
|
|
288
|
+
* (MAKERSCLAW_BLOCKS_DIR, folders joined like PATH). */
|
|
289
|
+
export function blockRootsFromEnv(env = process.env) {
|
|
290
|
+
return String(env.MAKERSCLAW_BLOCKS_DIR ?? "")
|
|
291
|
+
.split(delimiter)
|
|
292
|
+
.map((d) => d.trim())
|
|
293
|
+
.filter(Boolean);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export function main(argv, { stdout = process.stdout, stderr = process.stderr, env = process.env } = {}) {
|
|
297
|
+
useExtraBlockRoots(blockRootsFromEnv(env));
|
|
285
298
|
let opts = { json: argv.includes("--json") };
|
|
286
299
|
try {
|
|
287
300
|
opts = parseArgs(argv);
|
package/src/install.mjs
CHANGED
|
@@ -147,6 +147,7 @@ function lay(dir, tpl, before) {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
const blocks = {};
|
|
150
|
+
const blockDeps = {};
|
|
150
151
|
const known = loadBlocks();
|
|
151
152
|
for (const [name, from] of Object.entries(before.manifest?.blocks ?? {})) {
|
|
152
153
|
if (!existsSync(join(dir, BLOCK_DIR, name))) {
|
|
@@ -170,6 +171,20 @@ function lay(dir, tpl, before) {
|
|
|
170
171
|
pins[f.to] = hash;
|
|
171
172
|
}
|
|
172
173
|
blocks[name] = v;
|
|
174
|
+
Object.assign(blockDeps, block.dependencies);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// The blocks' npm packages, at the versions this release pins them to
|
|
178
|
+
// (block.json `dependencies`): a block's files and its packages move
|
|
179
|
+
// together, or an update would lay files the installed package cannot run.
|
|
180
|
+
if (Object.keys(blockDeps).length && existsSync(join(dir, "package.json"))) {
|
|
181
|
+
const path = join(dir, "package.json");
|
|
182
|
+
const { out, changes } = mergePackage(readJson(path, {}), { dependencies: blockDeps });
|
|
183
|
+
if (changes.length) {
|
|
184
|
+
writeJson(path, out);
|
|
185
|
+
if (!written.includes("package.json")) written.push("package.json");
|
|
186
|
+
pkg = [...pkg, ...changes];
|
|
187
|
+
}
|
|
173
188
|
}
|
|
174
189
|
|
|
175
190
|
for (const p of Object.keys(before.pins)) {
|
|
@@ -446,6 +461,9 @@ export function diff(dir) {
|
|
|
446
461
|
const pkgPath = join(dir, "package.json");
|
|
447
462
|
const tplPkg = tpl.files.find((f) => f.class === "merged");
|
|
448
463
|
const pkg = existsSync(pkgPath) && tplPkg ? mergePackage(readJson(pkgPath), readJson(tplPkg.from)).changes : [];
|
|
464
|
+
// …and the installed blocks' npm packages, which update lays with them.
|
|
465
|
+
const blockDeps = Object.assign({}, ...Object.keys(manifest.blocks ?? {}).map((n) => known.find((b) => b.name === n)?.dependencies ?? {}));
|
|
466
|
+
if (existsSync(pkgPath) && Object.keys(blockDeps).length) pkg.push(...mergePackage(readJson(pkgPath), { dependencies: blockDeps }).changes);
|
|
449
467
|
return {
|
|
450
468
|
from: manifest.version,
|
|
451
469
|
to: v,
|
package/src/registry.mjs
CHANGED
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
// app has one until `add` puts it there, so the agent searches for what
|
|
8
8
|
// it needs and installs just that. Everything here ships inside this
|
|
9
9
|
// package, so the version you run is the version you get.
|
|
10
|
+
//
|
|
11
|
+
// One exception: extra block roots. The platform lays its premium blocks
|
|
12
|
+
// (never on npm) into the sandbox and names their folder; the CLI's entry
|
|
13
|
+
// point hands it to useExtraBlockRoots() from MAKERSCLAW_BLOCKS_DIR. Only
|
|
14
|
+
// that entry point does: the shadcn registry builder never calls it, so
|
|
15
|
+
// no environment variable can put a premium block into the npm package.
|
|
10
16
|
|
|
11
17
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
12
18
|
import { join } from "node:path";
|
|
@@ -79,13 +85,40 @@ export function loadTemplate(name) {
|
|
|
79
85
|
return { name, title: meta.title ?? name, description: meta.description ?? "", root, files, components };
|
|
80
86
|
}
|
|
81
87
|
|
|
88
|
+
let extraRoots = [];
|
|
89
|
+
|
|
90
|
+
/** Block folders outside this package (the platform's premium blocks),
|
|
91
|
+
* read after the package's own. Same shape as registry/blocks/. */
|
|
92
|
+
export function useExtraBlockRoots(dirs) {
|
|
93
|
+
extraRoots = (dirs ?? []).filter((d) => d && existsSync(d) && statSync(d).isDirectory());
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function extraBlockRoots() {
|
|
97
|
+
return [...extraRoots];
|
|
98
|
+
}
|
|
99
|
+
|
|
82
100
|
export function loadBlocks() {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
const blocks = [];
|
|
102
|
+
const seen = new Map();
|
|
103
|
+
for (const root of [BLOCKS, ...extraRoots]) {
|
|
104
|
+
for (const block of loadBlocksFrom(root, root === BLOCKS ? "free" : "premium")) {
|
|
105
|
+
if (seen.has(block.name)) {
|
|
106
|
+
throw new Error(`block ${block.name}: in both ${seen.get(block.name)} and ${root} — a block name is used once`);
|
|
107
|
+
}
|
|
108
|
+
seen.set(block.name, root);
|
|
109
|
+
blocks.push(block);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return blocks;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function loadBlocksFrom(root, defaultTier) {
|
|
116
|
+
if (!existsSync(root)) return [];
|
|
117
|
+
return readdirSync(root)
|
|
118
|
+
.filter((n) => statSync(join(root, n)).isDirectory())
|
|
86
119
|
.sort()
|
|
87
120
|
.map((folder) => {
|
|
88
|
-
const dir = join(
|
|
121
|
+
const dir = join(root, folder);
|
|
89
122
|
const meta = readJson(join(dir, "block.json"));
|
|
90
123
|
if (!meta) throw new Error(`block ${folder}: no block.json`);
|
|
91
124
|
if (meta.name !== folder || !NAME.test(folder)) throw new Error(`block ${folder}: name must be the folder's, lowercase and dashed`);
|
|
@@ -98,6 +131,7 @@ export function loadBlocks() {
|
|
|
98
131
|
return {
|
|
99
132
|
name: folder,
|
|
100
133
|
type: "block",
|
|
134
|
+
tier: meta.tier === "premium" || defaultTier === "premium" ? "premium" : "free",
|
|
101
135
|
title: meta.title ?? folder,
|
|
102
136
|
description: meta.description ?? "",
|
|
103
137
|
tags: meta.tags ?? [],
|
package/src/shadcn.mjs
CHANGED
|
@@ -40,6 +40,14 @@ const CSS_VARS = {
|
|
|
40
40
|
theme: {
|
|
41
41
|
"text-2xs": "0.6875rem",
|
|
42
42
|
"text-2xs--line-height": "1rem",
|
|
43
|
+
// The chart block's series colours. A shadcn theme already defines
|
|
44
|
+
// --chart-1…5 (light and dark); this only makes sure the utilities
|
|
45
|
+
// (fill-chart-1, stroke-chart-2…) read them.
|
|
46
|
+
"color-chart-1": "var(--chart-1)",
|
|
47
|
+
"color-chart-2": "var(--chart-2)",
|
|
48
|
+
"color-chart-3": "var(--chart-3)",
|
|
49
|
+
"color-chart-4": "var(--chart-4)",
|
|
50
|
+
"color-chart-5": "var(--chart-5)",
|
|
43
51
|
},
|
|
44
52
|
light: {
|
|
45
53
|
success: "oklch(0.627 0.194 149.214)",
|
|
@@ -142,7 +150,12 @@ function blockItem(block, base, version) {
|
|
|
142
150
|
/** Every item, with its files' content, and the index shadcn's `list` and
|
|
143
151
|
* `search` read (the same items, without content). */
|
|
144
152
|
export function buildRegistry({ base = defaultBase(), version = packageInfo().version } = {}) {
|
|
145
|
-
|
|
153
|
+
// Free blocks only. Extra roots are set by the CLI's entry point, never
|
|
154
|
+
// here — this refusal is the second lock on premium code reaching npm.
|
|
155
|
+
const blocks = loadBlocks();
|
|
156
|
+
const premium = blocks.filter((b) => b.tier === "premium").map((b) => b.name);
|
|
157
|
+
if (premium.length) throw new Error(`the public registry would carry premium blocks (${premium.join(", ")}) — build it without extra block roots`);
|
|
158
|
+
const items = [coreItem(), ...blocks.map((b) => blockItem(b, base, version))];
|
|
146
159
|
const index = {
|
|
147
160
|
$schema: INDEX_SCHEMA,
|
|
148
161
|
name: "makersclaw",
|
|
@@ -129,28 +129,162 @@ rarely does. `npm run check` refuses a raw `<select>`, `<dialog>`,
|
|
|
129
129
|
`<svg>`, `role="tab"`, `popover` or `window.confirm()` outside the kit.
|
|
130
130
|
|
|
131
131
|
```jsx
|
|
132
|
-
import { Button, IconButton,
|
|
133
|
-
|
|
132
|
+
import { Button, IconButton, ButtonGroup, ButtonGroupSeparator, Toggle, ToggleGroup,
|
|
133
|
+
Field, Input, TimeInput, Textarea, Select, Switch, Checkbox, RadioGroup, Radio, Rating,
|
|
134
|
+
InputGroup, PasswordInput, InputOTP, Slider, Image, FileInput, FileDrop, fileMatches, Combobox, Command, CommandDialog, Calendar, DatePicker, DateInput, DATE_PRESETS,
|
|
135
|
+
parseDate, isDateString, toDateString, todayString, addDays, addMonths,
|
|
136
|
+
startOfMonth, endOfMonth, dayOfWeek, formatDate, firstDayOfWeek,
|
|
137
|
+
Card, Notice, Badge, Kicker, Empty, Item, ItemGroup, Avatar, AvatarGroup,
|
|
138
|
+
Sheet, Confirm, Tabs, TabPanel, Menu, ContextMenu, Popover, Tooltip, HoverCard,
|
|
139
|
+
Breadcrumb, Pagination, Collapsible, Accordion, Carousel, ScrollArea,
|
|
140
|
+
ResizablePanelGroup, ResizablePanel, ResizableHandle,
|
|
141
|
+
Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption,
|
|
142
|
+
Spinner, Skeleton, Progress, Separator, Kbd, KbdGroup, AspectRatio,
|
|
143
|
+
Stat, StatGroup, Delta, StatusDot, Legend, Meter, Distribution, Swatch, Steps,
|
|
144
|
+
toast, Toaster, Depiction, Icon, ICON_NAMES, usePopoverPosition, panelClass, cx }
|
|
134
145
|
from "../components/ui"; // "./ui" from a component
|
|
135
146
|
import { RecordSwitcher, useFixture, FixtureNotice, isSample } from "../components/parts";
|
|
136
147
|
```
|
|
137
148
|
|
|
138
149
|
- `Button` — `variant` primary (one per surface) · secondary · quiet ·
|
|
139
|
-
danger · link
|
|
140
|
-
`
|
|
150
|
+
danger · link (inline text: no padding or height, wraps and truncates
|
|
151
|
+
with its sentence; `size="inherit"` takes the sentence's size;
|
|
152
|
+
`tone="muted"` for a secondary link) · nav (a full-width navigation row, start-aligned, normal
|
|
153
|
+
weight, filled by `aria-current="page"`); `size` md (44px) · sm;
|
|
154
|
+
`align` center · start; `icon="plus"`; `href` for a link.
|
|
155
|
+
`IconButton` for an icon alone (`label` required). `loading` while its
|
|
156
|
+
action runs: a spinner, the same width, `aria-busy`, disabled.
|
|
141
157
|
- `Field` wraps `Input`, `Textarea`, `Select`, `Switch`, `Checkbox` with
|
|
142
158
|
its label, hint and error. `Select` with empty `options` renders a
|
|
143
|
-
muted line, never a disabled dropdown.
|
|
159
|
+
muted line, never a disabled dropdown. `TimeInput` — a time of day
|
|
160
|
+
("HH:MM"; `min max step`), the kit's clock in place of the browser's.
|
|
161
|
+
- `Rating` — stars: read-only `value` of `max` (halves drawn, "4.5 out
|
|
162
|
+
of 5" to a reader), or with `onChange` a radio-group input; `size`, `label`.
|
|
163
|
+
- `InputGroup` — an input with `icon`, `prefix` ("https://"), `suffix`
|
|
164
|
+
("USD"), `kbd` and an `action` button (copy, search, show password);
|
|
165
|
+
one border, focus ring and `invalid` for the whole group; `multiline`
|
|
166
|
+
is the chat composer (a growing textarea, `minRows` `maxRows`, `tools`
|
|
167
|
+
and the action in a bar under it, `above` for attached files).
|
|
168
|
+
`PasswordInput` — the password field with a show/hide toggle
|
|
169
|
+
(`autoComplete` passes through; "new-password" on sign-up).
|
|
170
|
+
`Textarea autoGrow` grows with its text the same way. `InputOTP` —
|
|
171
|
+
a one-time code in boxes (`length` or `groups={[3, 3]}`, `digitsOnly`,
|
|
172
|
+
`onComplete(code)`, `invalid`; paste and SMS autofill fill every box).
|
|
173
|
+
`Slider` — a number, or a range with `value={[low, high]}`; `min max
|
|
174
|
+
step`, `showValue` + `format`. A number someone will type is an Input.
|
|
175
|
+
- `Combobox` — pick one or many from a searchable list (`options` with
|
|
176
|
+
`icon`, `description`, `group`, `count` at the right; `multiple` →
|
|
177
|
+
chips; `creatable`; `open` + `onOpenChange` or `defaultOpen`;
|
|
178
|
+
`onSearch` async; `clearable`; in a `Field` by `id`; a bottom sheet on a
|
|
179
|
+
phone). `searchable={false}` is the rich Select (icons, descriptions)
|
|
180
|
+
— a plain list of words stays the native `Select`. `Command` — a
|
|
181
|
+
searchable list of actions (`items` with `icon`, `shortcut`, `keywords`,
|
|
182
|
+
`group`, `onSelect`); `CommandDialog hotkey="k"` is the ⌘K palette.
|
|
144
183
|
- `Sheet` — the one overlay, a rail beside the work (`side="end"`), a
|
|
145
|
-
dialog (`center`) or a bottom sheet; on a narrow window every side
|
|
146
|
-
becomes a bottom sheet
|
|
184
|
+
navigation drawer (`start`), a dialog (`center`) or a bottom sheet; on a narrow window every side
|
|
185
|
+
becomes a bottom sheet; `bare` + `label` for a panel that draws its own
|
|
186
|
+
top (no header, flush body). `Confirm` is the "delete this?" case;
|
|
187
|
+
`consequences`, `requireText` and `acknowledge` hold it until met.
|
|
188
|
+
- `Image src alt ratio fit rounded` — a picture of a thing (thumbnail,
|
|
189
|
+
cover): Skeleton while it loads, a glyph when it fails, lazy, `alt`
|
|
190
|
+
required. Never a raw `<img>`; a face is an `Avatar`.
|
|
191
|
+
- `FileInput onFiles accept multiple` (a Button that opens the picker;
|
|
192
|
+
only a `label` → an IconButton) and `FileDrop` (a drop zone, `label`
|
|
193
|
+
`hint` `size` sm · md; a drop is filtered by `accept`, the rest go to
|
|
194
|
+
`onReject`). Never a raw `<input type="file">`.
|
|
147
195
|
- `Tabs` + `TabPanel` — views of ONE thing (a record's notes | history).
|
|
148
196
|
Never for the app's surfaces; those are the shell's nav.
|
|
149
|
-
- `Menu` — the "…" of a row
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
197
|
+
- `Menu` — the "…" of a row, a View or Account dropdown. `items` are
|
|
198
|
+
data: actions (`icon`, `tone`, `shortcut`, `description`), `{ group,
|
|
199
|
+
items }`, `{ type: "separator" }`, `{ type: "checkbox", checked,
|
|
200
|
+
onCheckedChange }`, `{ type: "radio", value, onValueChange, options }`
|
|
201
|
+
(choices keep it open) and submenus `{ label, items }`; `side` +
|
|
202
|
+
`align`; `size` sm (36px, default) · md (44px trigger). Empty `items` render nothing: a menu is earned by having
|
|
203
|
+
actions. `ContextMenu` opens the same `items` on a region's right-click,
|
|
204
|
+
long press or Shift+F10 — a shortcut, never the only door.
|
|
205
|
+
- `Popover` (a panel beside its `trigger`; `side`, `align`, `width`;
|
|
206
|
+
flips at the window's edge; `open` + `onOpenChange` or uncontrolled),
|
|
207
|
+
`Tooltip` (a short text `label` on hover or keyboard focus; never on
|
|
208
|
+
touch, so it only repeats what is visible) and `HoverCard` (a preview
|
|
209
|
+
of what a link points at; may hold links). `usePopoverPosition` is the
|
|
210
|
+
placement alone, for a floating part of your own.
|
|
211
|
+
- `DatePicker` (a field that opens a Calendar; `mode` single · range,
|
|
212
|
+
`presets`, `clearable`, `min max disabled`; in a `Field` with the same
|
|
213
|
+
`id`), `Calendar` (the grid inline; `mode` single · multiple · range,
|
|
214
|
+
`numberOfMonths`, `captionLayout` dropdown · none (you show and move a
|
|
215
|
+
controlled `month`), `showWeekNumbers`, `weekStartsOn`, `marked` with
|
|
216
|
+
`emphasizeMarked` and `onlyMarked`) and
|
|
217
|
+
`DateInput` (a typed date with the Calendar a button away). Dates are
|
|
218
|
+
`"YYYY-MM-DD"` strings in and out — never a Date — and `addDays`,
|
|
219
|
+
`addMonths`, `formatDate`… do the arithmetic.
|
|
220
|
+
- `RadioGroup` (`options` or `<Radio>` children, each with a
|
|
221
|
+
`description`; `variant` list · card; `orientation`; in a `Field` with
|
|
222
|
+
the same `id`), `Toggle` (`pressed` + `onPressedChange`, aria-pressed),
|
|
223
|
+
`ToggleGroup` (the segmented control; `type` single · multiple) and
|
|
224
|
+
`ButtonGroup` (buttons, icon buttons and a `Menu` joined into one
|
|
225
|
+
piece; `ButtonGroupSeparator` between primary or quiet ones).
|
|
226
|
+
- `Avatar name src size shape status` (initials while loading and when
|
|
227
|
+
the image fails) and `AvatarGroup people max` ("+N" past `max`);
|
|
228
|
+
`Breadcrumb items={[{ label, href }]}` (last is this page; the middle
|
|
229
|
+
folds into "…"; the current page takes the rest of the row); `Pagination page pageCount` with `hrefFor(page)` or
|
|
230
|
+
`onPageChange` (compact on a phone; `pageSize` + `onPageSizeChange`).
|
|
231
|
+
- `Collapsible` (title, meta, `open` + `onOpenChange` or `defaultOpen`;
|
|
232
|
+
`variant` plain · outline · flush for edge-to-edge rows inside a Card;
|
|
233
|
+
`chevron` down · right, the disclosure triangle that turns down)
|
|
234
|
+
and `Accordion` (`items`, `type` single · multiple) — show and hide,
|
|
235
|
+
never a raw `<details>`. `Item` / `ItemGroup` — the list row (media or
|
|
236
|
+
icon, title, description, meta, actions; `href` or `onClick` makes the
|
|
237
|
+
whole row the target; `aria-current`, `onClick`, `target`, `rel` reach
|
|
238
|
+
that link or button). `Table` + `TableHeader`, `TableBody`, `TableRow`
|
|
239
|
+
(`selected`), `TableHead` (`sort` + `onSort`; `sortIndex` when several
|
|
240
|
+
are sorted), `TableCell` (`numeric`)
|
|
241
|
+
— a table that scrolls inside itself on a phone.
|
|
242
|
+
- `Card` (`padding` md · sm · none — none for a table or rows that run
|
|
243
|
+
to the border, never `p-0!`; `titleSize` md · lg for a 20px title),
|
|
244
|
+
`Notice` (tone neutral · info · success · warning · danger),
|
|
245
|
+
`Badge` (tone neutral · primary · success · warning · danger · info;
|
|
246
|
+
`variant` label — small caps · soft — the case as written, every tone
|
|
247
|
+
tinted, primary too · outline — the case as written, a hairline, no
|
|
248
|
+
fill · code — a version tag or a commit hash in the mono face; `hue`
|
|
249
|
+
1..5 for a KIND of thing — a platform, a content type — never a state:
|
|
250
|
+
tone is status, hue is category), `Kicker` (the small line above a heading), `Empty` (a filter
|
|
153
251
|
or search with no matches — not the landing state, that is the fixture).
|
|
252
|
+
- `Spinner` (size sm · md · lg), `Skeleton` (shape line · circle · rect,
|
|
253
|
+
sized by className), `Progress` (`value` of `max`, no value for
|
|
254
|
+
indeterminate; tone; `label`) — waiting, never a hand-drawn loader.
|
|
255
|
+
- `Steps steps={[{ label, description, status, meta }]}` (or `current`)
|
|
256
|
+
— where a staged job has got: `variant` dots · bar (rollout phases);
|
|
257
|
+
status complete · current · pending · failed · skipped; `orientation`
|
|
258
|
+
horizontal · vertical; `pulse`; `label` + `valueText`;
|
|
259
|
+
`hideStepLabels` for bare dots (still pass every label: it is what a
|
|
260
|
+
reader hears); `onSelect`
|
|
261
|
+
only when a step opens something. Never a hand-drawn stepper.
|
|
262
|
+
- `Stat label value unit caption tone delta invert size` (sm · md · lg)
|
|
263
|
+
in a `StatGroup` (the 2–4 summary strip; card · divided · bare);
|
|
264
|
+
`Delta value suffix invert` (coloured by sign; zero is neutral);
|
|
265
|
+
`StatusDot tone pulse label`; `Legend items={[{ tone, label, count }]}`;
|
|
266
|
+
`Meter value max unit target thresholds` (a role=meter; over the limit
|
|
267
|
+
turns danger; `direction` higher · lower picks the tone against the
|
|
268
|
+
target; `valueTone`; `targetMark={false}`; tone `muted` for a plain
|
|
269
|
+
grey share) — numbers and states, never a hand-drawn tile or bar.
|
|
270
|
+
`Delta hideValue` is the arrow alone; `StatusDot` and Legend items take
|
|
271
|
+
`hue` (1..5) for a category. `Distribution segments={[{ label, value,
|
|
272
|
+
tone, hue }]} legend label size` (thin · md) — parts of one whole as
|
|
273
|
+
one stacked bar, a hue per segment, a tone for sentiment. `Swatch color
|
|
274
|
+
label size` — a colour that comes from data; the only inline colour.
|
|
275
|
+
- `Separator` (horizontal · vertical; `decorative={false}` for a real
|
|
276
|
+
one), `Kbd` / `KbdGroup keys={["⌘", "K"]}`, `AspectRatio ratio="video"`
|
|
277
|
+
(its child fills it), `ScrollArea` (a bounded scroller with themed
|
|
278
|
+
scrollbars, `fade`, keyboard-focusable while it overflows; `ref` is the
|
|
279
|
+
scrolling element, for a list that sets its own scrollTop).
|
|
280
|
+
- `toast("Saved")`, `toast.success/.error/.info/.warning(title, {
|
|
281
|
+
description, action, duration })`, `toast.promise(p, { loading,
|
|
282
|
+
success, error })` — nothing to mount; `<Toaster position />` only to
|
|
283
|
+
move the stack. A toast is never the only record of an error.
|
|
284
|
+
- `Carousel label itemsPerView` (scroll-snap; 1 on a phone; dots ·
|
|
285
|
+
counter; `loop`, `autoplay` only when asked), `ResizablePanelGroup`
|
|
286
|
+
+ `ResizablePanel defaultSize minSize` + `ResizableHandle grip`
|
|
287
|
+
(`storageKey` remembers; a horizontal group stacks below md).
|
|
154
288
|
- `Icon name="…"` — one sprite, `ICON_NAMES` lists it. Missing one? Add
|
|
155
289
|
the glyph to `components/ui/icon.jsx`; never an `<svg>` in a surface.
|
|
156
290
|
- `RecordSwitcher` — pick a saved record or make a new one. With nothing
|
|
@@ -100,6 +100,41 @@
|
|
|
100
100
|
border: 0;
|
|
101
101
|
background: transparent;
|
|
102
102
|
}
|
|
103
|
+
|
|
104
|
+
/* Status tones when the preset does not pin them (@theme below reads
|
|
105
|
+
these). The plain fallbacks there are for a dark canvas and read faint
|
|
106
|
+
on a light one, so a light page gets darker ones: by color-scheme (the
|
|
107
|
+
preset's), through light-dark(), where the browser has it; by
|
|
108
|
+
data-theme=light where it does not. Every one reads at 4.5:1 or more
|
|
109
|
+
as text on the Daylight background and card. */
|
|
110
|
+
[data-theme=light] {
|
|
111
|
+
--scheme-success: #15703a;
|
|
112
|
+
--scheme-warning: #9a4a06;
|
|
113
|
+
--scheme-info: #1d4ed8;
|
|
114
|
+
--scheme-destructive: #c01c1c;
|
|
115
|
+
}
|
|
116
|
+
@supports (color: light-dark(red, red)) {
|
|
117
|
+
:root,
|
|
118
|
+
[data-theme] {
|
|
119
|
+
--scheme-success: light-dark(#15703a, #4ade80);
|
|
120
|
+
--scheme-warning: light-dark(#9a4a06, #ffbd38);
|
|
121
|
+
--scheme-info: light-dark(#1d4ed8, #60a5fa);
|
|
122
|
+
--scheme-destructive: light-dark(#c01c1c, #fb2c36);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Chart series 2-5, derived with relative colour (oklch(from …)), which
|
|
127
|
+
Chrome before 119 and Safari before 16.4 lack. Set only where it
|
|
128
|
+
parses; elsewhere @theme falls back to plain colours that still stay
|
|
129
|
+
apart, rather than to no colour at all. */
|
|
130
|
+
@supports (color: oklch(from red l c h)) {
|
|
131
|
+
:root {
|
|
132
|
+
--chart-derived-2: oklch(from var(--primary, var(--midground-base)) clamp(0.55, l, 0.8) clamp(0.12, c, 0.2) calc(h + 144));
|
|
133
|
+
--chart-derived-3: oklch(from var(--primary, var(--midground-base)) clamp(0.55, l, 0.8) clamp(0.12, c, 0.2) calc(h + 288));
|
|
134
|
+
--chart-derived-4: oklch(from var(--primary, var(--midground-base)) clamp(0.55, l, 0.8) clamp(0.12, c, 0.2) calc(h + 72));
|
|
135
|
+
--chart-derived-5: oklch(from var(--primary, var(--midground-base)) clamp(0.55, l, 0.8) clamp(0.12, c, 0.2) calc(h + 216));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
103
138
|
}
|
|
104
139
|
|
|
105
140
|
/* The boundary where the workspace theme stops: a depiction (README §3c),
|
|
@@ -150,16 +185,32 @@
|
|
|
150
185
|
--color-accent: var(--accent, color-mix(in srgb, var(--midground-base) 12%, var(--background-base)));
|
|
151
186
|
--color-accent-foreground: var(--accent-foreground, var(--midground-base));
|
|
152
187
|
|
|
153
|
-
--color-destructive: var(--destructive, #fb2c36);
|
|
188
|
+
--color-destructive: var(--destructive, var(--scheme-destructive, #fb2c36));
|
|
154
189
|
--color-destructive-foreground: var(--destructive-foreground, #ffffff);
|
|
155
|
-
--color-success: var(--success, #4ade80);
|
|
156
|
-
--color-warning: var(--warning, #ffbd38);
|
|
157
|
-
--color-info: var(--info, #60a5fa);
|
|
190
|
+
--color-success: var(--success, var(--scheme-success, #4ade80));
|
|
191
|
+
--color-warning: var(--warning, var(--scheme-warning, #ffbd38));
|
|
192
|
+
--color-info: var(--info, var(--scheme-info, #60a5fa));
|
|
158
193
|
|
|
159
194
|
--color-border: var(--border, color-mix(in srgb, var(--midground-base) 15%, transparent));
|
|
160
195
|
--color-input: var(--input, color-mix(in srgb, var(--midground-base) 15%, transparent));
|
|
161
196
|
--color-ring: var(--ring, var(--midground-base));
|
|
162
197
|
|
|
198
|
+
/* Chart series (fill-chart-1, stroke-chart-2, bg-chart-3…), for the chart
|
|
199
|
+
block: several colours that must stay apart in every theme. A preset
|
|
200
|
+
(or a shadcn theme) may pin --chart-N. Otherwise chart-1 is the primary
|
|
201
|
+
and the others turn its hue round the wheel, 144° a step so neighbours
|
|
202
|
+
never sit close, keeping its lightness (the primary already reads on
|
|
203
|
+
this canvas) with a floor on chroma so a grey or pastel theme still
|
|
204
|
+
gets colours. Not success/warning/info: those are status, and a theme's
|
|
205
|
+
primary is often one of them (amber, mint, blue). The turn is worked
|
|
206
|
+
out in the base layer (--chart-derived-N); the hex after it is for a
|
|
207
|
+
browser without relative colour. */
|
|
208
|
+
--color-chart-1: var(--chart-1, var(--primary, var(--midground-base)));
|
|
209
|
+
--color-chart-2: var(--chart-2, var(--chart-derived-2, #14b8a6));
|
|
210
|
+
--color-chart-3: var(--chart-3, var(--chart-derived-3, #a78bfa));
|
|
211
|
+
--color-chart-4: var(--chart-4, var(--chart-derived-4, #f472b6));
|
|
212
|
+
--color-chart-5: var(--chart-5, var(--chart-derived-5, #38bdf8));
|
|
213
|
+
|
|
163
214
|
--radius-sm: calc(var(--theme-radius) - 4px);
|
|
164
215
|
--radius-md: calc(var(--theme-radius) - 2px);
|
|
165
216
|
--radius-lg: var(--theme-radius);
|
|
@@ -48,7 +48,7 @@ const STATIC_ONLY = process.argv.includes("--static");
|
|
|
48
48
|
// update` lays both folders again.
|
|
49
49
|
// Exact names AND extensions: Next resolves .js before .jsx, so a
|
|
50
50
|
// components/ui/depiction.js beside depiction.jsx would win unseen.
|
|
51
|
-
const KIT = /^components\/(?:ui\/(?:cx|index)\.js|ui\/(?:button|depiction|field|icon|menu|notice|sheet|tabs)\.jsx|parts\/(?:index|sample)\.js|parts\/(?:fixture|record-switcher)\.jsx)$/;
|
|
51
|
+
const KIT = /^components\/(?:ui\/(?:cx|index)\.js|ui\/(?:radio|toggle|button-group|avatar|breadcrumb|pagination|button|collapsible|item|table|depiction|feedback|stat|distribution|swatch|steps|separator|scroll-area|field|icon|menu|context-menu|popover|calendar|date-picker|tooltip|notice|sheet|tabs|slider|input-group|image|file-input|input-otp|command|combobox|rating|toast|carousel|resizable)\.jsx|parts\/(?:index|sample)\.js|parts\/(?:fixture|record-switcher)\.jsx)$/;
|
|
52
52
|
|
|
53
53
|
// The pins: sha256 of every fixed file, written by `makersclaw init` and
|
|
54
54
|
// `makersclaw add` (check/pins.json). Read first, because a BLOCK is
|
|
@@ -209,11 +209,11 @@ const ATTRS = String.raw`(?:"[^"]*"|'[^']*'|\{(?:[^{}]|\{[^{}]*\})*\}|[^>"'{])*`
|
|
|
209
209
|
const RULES = [
|
|
210
210
|
[/<select\b/, "Select from components/ui, or RecordSwitcher from components/parts", files],
|
|
211
211
|
[/<dialog\b/, "Sheet or Confirm from components/ui", files],
|
|
212
|
-
[/<details\b/, "
|
|
212
|
+
[/<details\b/, "Collapsible or Accordion from components/ui", files],
|
|
213
213
|
[/role=["']tab(?:list)?["']/, "Tabs from components/ui", files],
|
|
214
214
|
[/role=["']menu(?:item)?["']/, "Menu from components/ui", files],
|
|
215
215
|
[/role=["']dialog["']/, "Sheet from components/ui", files],
|
|
216
|
-
[/\bpopover=/, "Menu from components/ui", files],
|
|
216
|
+
[/\bpopover=/, "Popover, Tooltip, HoverCard or Menu from components/ui", files],
|
|
217
217
|
[/window\.confirm\(/, "Confirm from components/ui", files],
|
|
218
218
|
[/<svg\b/, "Icon from components/ui (add a glyph there if it is missing)", appFiles],
|
|
219
219
|
];
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { cx } from "./cx";
|
|
5
|
+
import { Icon } from "./icon";
|
|
6
|
+
|
|
7
|
+
// Avatar — a person's face, or their initials while it loads and when it
|
|
8
|
+
// fails. The initials are always drawn; the image lays over them only
|
|
9
|
+
// once it has loaded, so a slow, missing or broken `src` never shows a
|
|
10
|
+
// hole or the browser's broken-image glyph. No name either: a user icon.
|
|
11
|
+
//
|
|
12
|
+
// name "Jane Cooper" → JC; also the accessible name
|
|
13
|
+
// src the image; optional
|
|
14
|
+
// size xs (24px) · sm (32px) · md (40px) · lg (56px)
|
|
15
|
+
// shape round · square (a company, a bot, a workspace)
|
|
16
|
+
// status online · away · busy · offline — a dot, named to a reader
|
|
17
|
+
// label overrides what a screen reader says
|
|
18
|
+
//
|
|
19
|
+
// AvatarGroup below is the overlapping stack with "+N" after `max`.
|
|
20
|
+
|
|
21
|
+
const SIZES = {
|
|
22
|
+
xs: { box: "h-6 w-6 text-2xs", dot: "h-1.5 w-1.5", icon: 12, overlap: "-space-x-1.5" },
|
|
23
|
+
sm: { box: "h-8 w-8 text-xs", dot: "h-2 w-2", icon: 14, overlap: "-space-x-2" },
|
|
24
|
+
md: { box: "h-10 w-10 text-sm", dot: "h-2.5 w-2.5", icon: 18, overlap: "-space-x-2.5" },
|
|
25
|
+
lg: { box: "h-14 w-14 text-lg", dot: "h-3.5 w-3.5", icon: 24, overlap: "-space-x-3" },
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const SHAPES = { round: "rounded-full", square: "rounded-md" };
|
|
29
|
+
|
|
30
|
+
// Colour is the signal: the status tones are the workspace's status tokens.
|
|
31
|
+
const STATUS = {
|
|
32
|
+
online: { dot: "bg-success", say: "online" },
|
|
33
|
+
away: { dot: "bg-warning", say: "away" },
|
|
34
|
+
busy: { dot: "bg-destructive", say: "busy" },
|
|
35
|
+
offline: { dot: "bg-muted-foreground", say: "offline" },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** "Jane Cooper" → "JC", "jane@acme.com" → "J", "Priya" → "P". First and
|
|
39
|
+
* last word, by code point, so an accented or non-Latin name survives. */
|
|
40
|
+
function initials(name) {
|
|
41
|
+
const words = String(name ?? "").split("@")[0].trim().split(/[\s._-]+/).filter(Boolean);
|
|
42
|
+
if (words.length === 0) return "";
|
|
43
|
+
const first = Array.from(words[0])[0] ?? "";
|
|
44
|
+
const last = words.length > 1 ? Array.from(words[words.length - 1])[0] ?? "" : "";
|
|
45
|
+
return (first + last).toUpperCase();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function Avatar({ name, src, size = "md", shape = "round", status, label, className }) {
|
|
49
|
+
const s = SIZES[size] ?? SIZES.md;
|
|
50
|
+
const round = SHAPES[shape] ?? SHAPES.round;
|
|
51
|
+
const st = STATUS[status];
|
|
52
|
+
const img = useRef(null);
|
|
53
|
+
// Both hold the src they are about, so a new src starts fresh unreset.
|
|
54
|
+
const [loaded, setLoaded] = useState(null);
|
|
55
|
+
const [failed, setFailed] = useState(null);
|
|
56
|
+
|
|
57
|
+
// A server-rendered <img> can load or fail before React is listening.
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const i = img.current;
|
|
60
|
+
if (!i || !src || !i.complete) return;
|
|
61
|
+
if (i.naturalWidth > 0) setLoaded(src);
|
|
62
|
+
else setFailed(src);
|
|
63
|
+
}, [src]);
|
|
64
|
+
|
|
65
|
+
const text = initials(name);
|
|
66
|
+
const said = label ?? ([name, st?.say].filter(Boolean).join(", ") || undefined);
|
|
67
|
+
const showImg = src && failed !== src;
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<span
|
|
71
|
+
role={said ? "img" : undefined}
|
|
72
|
+
aria-label={said}
|
|
73
|
+
aria-hidden={said ? undefined : true}
|
|
74
|
+
title={name || undefined}
|
|
75
|
+
className={cx("relative inline-flex shrink-0 select-none", round, s.box, className)}
|
|
76
|
+
>
|
|
77
|
+
<span className={cx("relative flex h-full w-full items-center justify-center overflow-hidden bg-muted font-medium text-muted-foreground", round)}>
|
|
78
|
+
{/* Hidden, not removed, once the image is in: a transparent PNG must not show letters through it. */}
|
|
79
|
+
<span aria-hidden="true" className={cx("inline-flex leading-none", loaded === src && showImg && "invisible")}>
|
|
80
|
+
{text || <Icon name="user" size={s.icon} />}
|
|
81
|
+
</span>
|
|
82
|
+
{showImg ? (
|
|
83
|
+
<img
|
|
84
|
+
ref={img}
|
|
85
|
+
src={src}
|
|
86
|
+
alt=""
|
|
87
|
+
onLoad={() => setLoaded(src)}
|
|
88
|
+
onError={() => setFailed(src)}
|
|
89
|
+
className={cx("absolute inset-0 h-full w-full object-cover", loaded === src ? "opacity-100" : "opacity-0")}
|
|
90
|
+
/>
|
|
91
|
+
) : null}
|
|
92
|
+
</span>
|
|
93
|
+
{st ? (
|
|
94
|
+
<span
|
|
95
|
+
aria-hidden="true"
|
|
96
|
+
className={cx(
|
|
97
|
+
"absolute rounded-full ring-2 ring-background",
|
|
98
|
+
shape === "square" ? "-bottom-0.5 -right-0.5" : "bottom-0 right-0",
|
|
99
|
+
s.dot,
|
|
100
|
+
st.dot,
|
|
101
|
+
)}
|
|
102
|
+
/>
|
|
103
|
+
) : null}
|
|
104
|
+
</span>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Faces overlapping, the first `max` of `people`, then "+N" naming the
|
|
109
|
+
* rest on hover and to a reader. No status dots: the next face covers
|
|
110
|
+
* them. Empty `people` renders nothing.
|
|
111
|
+
*
|
|
112
|
+
* people [{ name, src? }]
|
|
113
|
+
* max how many faces before "+N" (default 4)
|
|
114
|
+
*/
|
|
115
|
+
export function AvatarGroup({ people, max = 4, size = "sm", shape = "round", label, className }) {
|
|
116
|
+
const list = (people ?? []).filter(Boolean);
|
|
117
|
+
if (list.length === 0) return null;
|
|
118
|
+
const s = SIZES[size] ?? SIZES.sm;
|
|
119
|
+
const round = SHAPES[shape] ?? SHAPES.round;
|
|
120
|
+
const shown = list.slice(0, Math.max(1, max));
|
|
121
|
+
const rest = list.slice(shown.length);
|
|
122
|
+
const restNames = rest.map((p) => p.name).filter(Boolean).join(", ");
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<div role="group" aria-label={label ?? `${list.length} people`} className={cx("flex items-center", s.overlap, className)}>
|
|
126
|
+
{shown.map((p, i) => (
|
|
127
|
+
<Avatar key={i} name={p.name} src={p.src} size={size} shape={shape} className="ring-2 ring-background" />
|
|
128
|
+
))}
|
|
129
|
+
{rest.length > 0 ? (
|
|
130
|
+
<span
|
|
131
|
+
role="img"
|
|
132
|
+
aria-label={`and ${rest.length} more${restNames ? `: ${restNames}` : ""}`}
|
|
133
|
+
title={restNames || undefined}
|
|
134
|
+
className={cx("relative inline-flex shrink-0 items-center justify-center bg-muted font-medium text-muted-foreground ring-2 ring-background", round, s.box)}
|
|
135
|
+
>
|
|
136
|
+
<span data-nums aria-hidden="true" className="leading-none">+{rest.length}</span>
|
|
137
|
+
</span>
|
|
138
|
+
) : null}
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
}
|