makersclaw 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +3 -2
- package/r/annotate.json +62 -0
- package/r/approval-request.json +52 -0
- package/r/audio-player.json +74 -0
- package/r/auth-form.json +55 -0
- package/r/board.json +10 -6
- package/r/calendar-view.json +105 -0
- package/r/cart.json +62 -0
- package/r/chart.json +83 -0
- package/r/chat.json +95 -0
- package/r/code-editor.json +94 -0
- package/r/comment-box.json +64 -0
- package/r/contact-section.json +53 -0
- package/r/core.json +205 -8
- package/r/csv-import.json +63 -0
- package/r/data-table.json +69 -0
- package/r/diagram.json +74 -0
- package/r/doc-editor.json +82 -0
- package/r/doc-page.json +61 -0
- package/r/email-render.json +73 -0
- package/r/faq.json +50 -0
- package/r/file-upload.json +54 -0
- package/r/flow-canvas.json +93 -0
- package/r/footer.json +52 -0
- package/r/gantt.json +70 -0
- package/r/job-panel.json +12 -7
- package/r/json-editor.json +66 -0
- package/r/map.json +89 -0
- package/r/menubar.json +52 -0
- package/r/mind-map.json +67 -0
- package/r/navigation-menu.json +52 -0
- package/r/order-detail.json +54 -0
- package/r/org-chart.json +66 -0
- package/r/page-builder.json +105 -0
- package/r/payment-methods.json +51 -0
- package/r/pdf-document.json +79 -0
- package/r/pdf-viewer.json +88 -0
- package/r/product-detail.json +76 -0
- package/r/product-grid.json +65 -0
- package/r/record-form.json +67 -0
- package/r/record-notes.json +55 -0
- package/r/registry.json +3411 -29
- package/r/search-dialog.json +51 -0
- package/r/settings-list.json +66 -0
- package/r/setup-checklist.json +51 -0
- package/r/share-dialog.json +52 -0
- package/r/sidebar.json +69 -0
- package/r/signature-pad.json +72 -0
- package/r/sketch-canvas.json +99 -0
- package/r/spreadsheet.json +90 -0
- package/r/stat-cards.json +66 -0
- package/r/task-list.json +63 -0
- package/r/task-model.json +98 -0
- package/r/testimonials.json +52 -0
- package/r/transaction-list.json +53 -0
- package/r/whiteboard.json +66 -0
- package/registry/blocks/annotate/README.md +179 -0
- package/registry/blocks/annotate/annotate-data.js +250 -0
- package/registry/blocks/annotate/annotate.jsx +646 -0
- package/registry/blocks/annotate/block.json +10 -0
- package/registry/blocks/annotate/demo.jsx +135 -0
- package/registry/blocks/annotate/index.js +15 -0
- package/registry/blocks/approval-request/README.md +116 -0
- package/registry/blocks/approval-request/approval-request.jsx +386 -0
- package/registry/blocks/approval-request/block.json +10 -0
- package/registry/blocks/approval-request/demo.jsx +127 -0
- package/registry/blocks/approval-request/index.js +4 -0
- package/registry/blocks/audio-player/README.md +167 -0
- package/registry/blocks/audio-player/audio-player.jsx +623 -0
- package/registry/blocks/audio-player/block.json +14 -0
- package/registry/blocks/audio-player/colors.js +109 -0
- package/registry/blocks/audio-player/demo.jsx +209 -0
- package/registry/blocks/audio-player/index.js +6 -0
- package/registry/blocks/audio-player/time.js +67 -0
- package/registry/blocks/audio-player/wavesurfer.js +9 -0
- package/registry/blocks/auth-form/README.md +126 -0
- package/registry/blocks/auth-form/auth-form.jsx +568 -0
- package/registry/blocks/auth-form/block.json +10 -0
- package/registry/blocks/auth-form/demo.jsx +131 -0
- package/registry/blocks/auth-form/index.js +3 -0
- package/registry/blocks/board/README.md +55 -5
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +230 -86
- package/registry/blocks/board/demo.jsx +103 -24
- package/registry/blocks/calendar-view/README.md +180 -0
- package/registry/blocks/calendar-view/agenda.jsx +147 -0
- package/registry/blocks/calendar-view/block.json +76 -0
- package/registry/blocks/calendar-view/calendar-model.js +442 -0
- package/registry/blocks/calendar-view/calendar.jsx +627 -0
- package/registry/blocks/calendar-view/demo.jsx +195 -0
- package/registry/blocks/calendar-view/draft.jsx +49 -0
- package/registry/blocks/calendar-view/index.js +39 -0
- package/registry/blocks/calendar-view/month.jsx +346 -0
- package/registry/blocks/calendar-view/paint.js +69 -0
- package/registry/blocks/calendar-view/time-grid.jsx +527 -0
- package/registry/blocks/calendar-view/tray.jsx +87 -0
- package/registry/blocks/cart/README.md +146 -0
- package/registry/blocks/cart/block.json +10 -0
- package/registry/blocks/cart/cart.jsx +597 -0
- package/registry/blocks/cart/demo.jsx +98 -0
- package/registry/blocks/cart/index.js +4 -0
- package/registry/blocks/cart/money.js +28 -0
- package/registry/blocks/chart/README.md +316 -0
- package/registry/blocks/chart/block.json +10 -0
- package/registry/blocks/chart/cartesian.jsx +642 -0
- package/registry/blocks/chart/core.jsx +262 -0
- package/registry/blocks/chart/demo.jsx +357 -0
- package/registry/blocks/chart/heatmap.jsx +336 -0
- package/registry/blocks/chart/index.js +8 -0
- package/registry/blocks/chart/pie.jsx +245 -0
- package/registry/blocks/chart/sparkline.jsx +88 -0
- package/registry/blocks/chat/README.md +273 -0
- package/registry/blocks/chat/attachment.jsx +95 -0
- package/registry/blocks/chat/block.json +10 -0
- package/registry/blocks/chat/chat.jsx +132 -0
- package/registry/blocks/chat/composer.jsx +364 -0
- package/registry/blocks/chat/demo.jsx +578 -0
- package/registry/blocks/chat/header.jsx +34 -0
- package/registry/blocks/chat/index.js +9 -0
- package/registry/blocks/chat/message.jsx +450 -0
- package/registry/blocks/chat/scroller.jsx +247 -0
- package/registry/blocks/chat/text.jsx +104 -0
- package/registry/blocks/code-editor/README.md +210 -0
- package/registry/blocks/code-editor/block.json +22 -0
- package/registry/blocks/code-editor/code-editor.jsx +534 -0
- package/registry/blocks/code-editor/codemirror.js +38 -0
- package/registry/blocks/code-editor/demo.jsx +205 -0
- package/registry/blocks/code-editor/index.js +8 -0
- package/registry/blocks/code-editor/json.js +317 -0
- package/registry/blocks/code-editor/sql.js +136 -0
- package/registry/blocks/code-editor/text.js +101 -0
- package/registry/blocks/code-editor/theme.js +186 -0
- package/registry/blocks/comment-box/README.md +123 -0
- package/registry/blocks/comment-box/block.json +10 -0
- package/registry/blocks/comment-box/comment-body.jsx +217 -0
- package/registry/blocks/comment-box/comment-box.jsx +198 -0
- package/registry/blocks/comment-box/comment-time.jsx +77 -0
- package/registry/blocks/comment-box/demo.jsx +141 -0
- package/registry/blocks/comment-box/index.js +8 -0
- package/registry/blocks/contact-section/README.md +152 -0
- package/registry/blocks/contact-section/block.json +11 -0
- package/registry/blocks/contact-section/contact-section.jsx +509 -0
- package/registry/blocks/contact-section/demo.jsx +93 -0
- package/registry/blocks/contact-section/index.js +4 -0
- package/registry/blocks/csv-import/README.md +133 -0
- package/registry/blocks/csv-import/block.json +13 -0
- package/registry/blocks/csv-import/csv-import.jsx +479 -0
- package/registry/blocks/csv-import/demo.jsx +106 -0
- package/registry/blocks/csv-import/import.js +200 -0
- package/registry/blocks/csv-import/index.js +7 -0
- package/registry/blocks/data-table/README.md +386 -0
- package/registry/blocks/data-table/block.json +10 -0
- package/registry/blocks/data-table/data-table.jsx +1164 -0
- package/registry/blocks/data-table/demo.jsx +588 -0
- package/registry/blocks/data-table/index.js +5 -0
- package/registry/blocks/data-table/model.js +169 -0
- package/registry/blocks/diagram/README.md +108 -0
- package/registry/blocks/diagram/block.json +13 -0
- package/registry/blocks/diagram/demo.jsx +113 -0
- package/registry/blocks/diagram/diagram.jsx +481 -0
- package/registry/blocks/diagram/index.js +7 -0
- package/registry/blocks/diagram/mermaid.js +52 -0
- package/registry/blocks/diagram/palette.js +313 -0
- package/registry/blocks/diagram/source.js +98 -0
- package/registry/blocks/doc-editor/README.md +215 -0
- package/registry/blocks/doc-editor/block.json +15 -0
- package/registry/blocks/doc-editor/demo.jsx +225 -0
- package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
- package/registry/blocks/doc-editor/doc.js +309 -0
- package/registry/blocks/doc-editor/index.js +7 -0
- package/registry/blocks/doc-editor/schema.jsx +56 -0
- package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
- package/registry/blocks/doc-editor/theme.js +82 -0
- package/registry/blocks/doc-page/README.md +119 -0
- package/registry/blocks/doc-page/autosave.js +104 -0
- package/registry/blocks/doc-page/block.json +10 -0
- package/registry/blocks/doc-page/demo.jsx +137 -0
- package/registry/blocks/doc-page/doc-page.jsx +276 -0
- package/registry/blocks/doc-page/index.js +4 -0
- package/registry/blocks/email-render/README.md +151 -0
- package/registry/blocks/email-render/block.json +14 -0
- package/registry/blocks/email-render/demo.jsx +153 -0
- package/registry/blocks/email-render/doc-email.jsx +210 -0
- package/registry/blocks/email-render/email.jsx +221 -0
- package/registry/blocks/email-render/index.js +10 -0
- package/registry/blocks/email-render/render.js +50 -0
- package/registry/blocks/email-render/theme.js +215 -0
- package/registry/blocks/faq/README.md +101 -0
- package/registry/blocks/faq/block.json +11 -0
- package/registry/blocks/faq/demo.jsx +89 -0
- package/registry/blocks/faq/faq.jsx +220 -0
- package/registry/blocks/faq/index.js +4 -0
- package/registry/blocks/file-upload/README.md +138 -0
- package/registry/blocks/file-upload/block.json +10 -0
- package/registry/blocks/file-upload/demo.jsx +204 -0
- package/registry/blocks/file-upload/file-upload.jsx +635 -0
- package/registry/blocks/file-upload/index.js +4 -0
- package/registry/blocks/flow-canvas/README.md +420 -0
- package/registry/blocks/flow-canvas/block.json +13 -0
- package/registry/blocks/flow-canvas/board.js +819 -0
- package/registry/blocks/flow-canvas/chrome.jsx +649 -0
- package/registry/blocks/flow-canvas/context.jsx +35 -0
- package/registry/blocks/flow-canvas/demo.jsx +249 -0
- package/registry/blocks/flow-canvas/edges.jsx +107 -0
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
- package/registry/blocks/flow-canvas/index.js +41 -0
- package/registry/blocks/flow-canvas/nodes.jsx +392 -0
- package/registry/blocks/flow-canvas/theme.js +174 -0
- package/registry/blocks/footer/README.md +133 -0
- package/registry/blocks/footer/block.json +11 -0
- package/registry/blocks/footer/demo.jsx +119 -0
- package/registry/blocks/footer/footer.jsx +406 -0
- package/registry/blocks/footer/index.js +4 -0
- package/registry/blocks/gantt/README.md +220 -0
- package/registry/blocks/gantt/block.json +10 -0
- package/registry/blocks/gantt/demo.jsx +148 -0
- package/registry/blocks/gantt/gantt.jsx +923 -0
- package/registry/blocks/gantt/index.js +7 -0
- package/registry/blocks/gantt/rows.jsx +468 -0
- package/registry/blocks/gantt/schedule.js +278 -0
- package/registry/blocks/job-panel/README.md +80 -0
- package/registry/blocks/job-panel/block.json +3 -3
- package/registry/blocks/job-panel/demo.jsx +230 -3
- package/registry/blocks/job-panel/job-panel.jsx +169 -3
- package/registry/blocks/json-editor/README.md +133 -0
- package/registry/blocks/json-editor/block.json +10 -0
- package/registry/blocks/json-editor/demo.jsx +92 -0
- package/registry/blocks/json-editor/index.js +7 -0
- package/registry/blocks/json-editor/json-editor.jsx +305 -0
- package/registry/blocks/json-editor/json-tree.jsx +393 -0
- package/registry/blocks/json-editor/tree.js +225 -0
- package/registry/blocks/map/README.md +221 -0
- package/registry/blocks/map/block.json +14 -0
- package/registry/blocks/map/demo.jsx +201 -0
- package/registry/blocks/map/geo.js +198 -0
- package/registry/blocks/map/index.js +8 -0
- package/registry/blocks/map/list.jsx +128 -0
- package/registry/blocks/map/map-view.jsx +715 -0
- package/registry/blocks/map/maplibre.js +30 -0
- package/registry/blocks/map/marks.jsx +146 -0
- package/registry/blocks/map/theme.js +142 -0
- package/registry/blocks/menubar/README.md +109 -0
- package/registry/blocks/menubar/block.json +10 -0
- package/registry/blocks/menubar/demo.jsx +128 -0
- package/registry/blocks/menubar/index.js +4 -0
- package/registry/blocks/menubar/menubar.jsx +199 -0
- package/registry/blocks/mind-map/README.md +206 -0
- package/registry/blocks/mind-map/block.json +10 -0
- package/registry/blocks/mind-map/demo.jsx +103 -0
- package/registry/blocks/mind-map/index.js +31 -0
- package/registry/blocks/mind-map/mind-map.jsx +1125 -0
- package/registry/blocks/mind-map/topic.jsx +143 -0
- package/registry/blocks/mind-map/tree.js +645 -0
- package/registry/blocks/navigation-menu/README.md +124 -0
- package/registry/blocks/navigation-menu/block.json +10 -0
- package/registry/blocks/navigation-menu/demo.jsx +84 -0
- package/registry/blocks/navigation-menu/index.js +4 -0
- package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
- package/registry/blocks/order-detail/README.md +109 -0
- package/registry/blocks/order-detail/block.json +10 -0
- package/registry/blocks/order-detail/demo.jsx +88 -0
- package/registry/blocks/order-detail/index.js +4 -0
- package/registry/blocks/order-detail/order-detail.jsx +354 -0
- package/registry/blocks/org-chart/README.md +145 -0
- package/registry/blocks/org-chart/block.json +10 -0
- package/registry/blocks/org-chart/demo.jsx +94 -0
- package/registry/blocks/org-chart/index.js +7 -0
- package/registry/blocks/org-chart/org-chart.jsx +631 -0
- package/registry/blocks/org-chart/org.js +245 -0
- package/registry/blocks/org-chart/person.jsx +96 -0
- package/registry/blocks/page-builder/README.md +257 -0
- package/registry/blocks/page-builder/block.json +14 -0
- package/registry/blocks/page-builder/demo.jsx +145 -0
- package/registry/blocks/page-builder/grapes.js +18 -0
- package/registry/blocks/page-builder/index.js +11 -0
- package/registry/blocks/page-builder/page-builder.jsx +704 -0
- package/registry/blocks/page-builder/page-view.jsx +33 -0
- package/registry/blocks/page-builder/page.js +118 -0
- package/registry/blocks/page-builder/panels.jsx +588 -0
- package/registry/blocks/page-builder/sections.js +209 -0
- package/registry/blocks/page-builder/theme.js +87 -0
- package/registry/blocks/page-builder/thumbs.jsx +189 -0
- package/registry/blocks/page-builder/tokens.js +329 -0
- package/registry/blocks/payment-methods/README.md +104 -0
- package/registry/blocks/payment-methods/block.json +10 -0
- package/registry/blocks/payment-methods/demo.jsx +71 -0
- package/registry/blocks/payment-methods/index.js +4 -0
- package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
- package/registry/blocks/pdf-document/README.md +213 -0
- package/registry/blocks/pdf-document/block.json +13 -0
- package/registry/blocks/pdf-document/demo.jsx +136 -0
- package/registry/blocks/pdf-document/index.js +33 -0
- package/registry/blocks/pdf-document/money.js +83 -0
- package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
- package/registry/blocks/pdf-document/primitives.jsx +271 -0
- package/registry/blocks/pdf-document/quote.jsx +179 -0
- package/registry/blocks/pdf-document/theme.js +193 -0
- package/registry/blocks/pdf-viewer/README.md +191 -0
- package/registry/blocks/pdf-viewer/block.json +14 -0
- package/registry/blocks/pdf-viewer/demo.jsx +252 -0
- package/registry/blocks/pdf-viewer/helpers.js +270 -0
- package/registry/blocks/pdf-viewer/index.js +8 -0
- package/registry/blocks/pdf-viewer/notes.jsx +195 -0
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
- package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
- package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
- package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
- package/registry/blocks/product-detail/README.md +217 -0
- package/registry/blocks/product-detail/block.json +10 -0
- package/registry/blocks/product-detail/demo.jsx +233 -0
- package/registry/blocks/product-detail/index.js +7 -0
- package/registry/blocks/product-detail/price.jsx +115 -0
- package/registry/blocks/product-detail/product-detail.jsx +348 -0
- package/registry/blocks/product-detail/product-media.jsx +102 -0
- package/registry/blocks/product-detail/product-options.jsx +144 -0
- package/registry/blocks/product-grid/README.md +162 -0
- package/registry/blocks/product-grid/block.json +10 -0
- package/registry/blocks/product-grid/demo.jsx +255 -0
- package/registry/blocks/product-grid/index.js +5 -0
- package/registry/blocks/product-grid/product-card.jsx +232 -0
- package/registry/blocks/product-grid/product-grid.jsx +235 -0
- package/registry/blocks/record-form/README.md +196 -0
- package/registry/blocks/record-form/block.json +10 -0
- package/registry/blocks/record-form/demo.jsx +525 -0
- package/registry/blocks/record-form/index.js +4 -0
- package/registry/blocks/record-form/record-fields.jsx +457 -0
- package/registry/blocks/record-form/record-form.jsx +415 -0
- package/registry/blocks/record-form/rules.js +81 -0
- package/registry/blocks/record-notes/README.md +139 -0
- package/registry/blocks/record-notes/block.json +10 -0
- package/registry/blocks/record-notes/demo.jsx +179 -0
- package/registry/blocks/record-notes/index.js +4 -0
- package/registry/blocks/record-notes/record-notes.jsx +266 -0
- package/registry/blocks/search-dialog/README.md +108 -0
- package/registry/blocks/search-dialog/block.json +10 -0
- package/registry/blocks/search-dialog/demo.jsx +116 -0
- package/registry/blocks/search-dialog/index.js +3 -0
- package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
- package/registry/blocks/settings-list/README.md +171 -0
- package/registry/blocks/settings-list/block.json +10 -0
- package/registry/blocks/settings-list/demo.jsx +333 -0
- package/registry/blocks/settings-list/index.js +4 -0
- package/registry/blocks/settings-list/row-state.jsx +93 -0
- package/registry/blocks/settings-list/settings-list.jsx +349 -0
- package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
- package/registry/blocks/setup-checklist/README.md +142 -0
- package/registry/blocks/setup-checklist/block.json +10 -0
- package/registry/blocks/setup-checklist/demo.jsx +159 -0
- package/registry/blocks/setup-checklist/index.js +4 -0
- package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
- package/registry/blocks/share-dialog/README.md +113 -0
- package/registry/blocks/share-dialog/block.json +10 -0
- package/registry/blocks/share-dialog/demo.jsx +140 -0
- package/registry/blocks/share-dialog/index.js +3 -0
- package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
- package/registry/blocks/sidebar/README.md +190 -0
- package/registry/blocks/sidebar/block.json +43 -0
- package/registry/blocks/sidebar/demo.jsx +577 -0
- package/registry/blocks/sidebar/index.js +4 -0
- package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
- package/registry/blocks/sidebar/sidebar.jsx +864 -0
- package/registry/blocks/signature-pad/README.md +137 -0
- package/registry/blocks/signature-pad/block.json +13 -0
- package/registry/blocks/signature-pad/colors.js +115 -0
- package/registry/blocks/signature-pad/demo.jsx +94 -0
- package/registry/blocks/signature-pad/index.js +6 -0
- package/registry/blocks/signature-pad/pad.js +7 -0
- package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
- package/registry/blocks/signature-pad/signature.js +68 -0
- package/registry/blocks/sketch-canvas/README.md +280 -0
- package/registry/blocks/sketch-canvas/block.json +13 -0
- package/registry/blocks/sketch-canvas/demo.jsx +159 -0
- package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
- package/registry/blocks/sketch-canvas/index.js +9 -0
- package/registry/blocks/sketch-canvas/palette.js +226 -0
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
- package/registry/blocks/sketch-canvas/sketch.js +179 -0
- package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
- package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
- package/registry/blocks/sketch-canvas/stamps.js +104 -0
- package/registry/blocks/sketch-canvas/theme.js +131 -0
- package/registry/blocks/spreadsheet/README.md +307 -0
- package/registry/blocks/spreadsheet/block.json +13 -0
- package/registry/blocks/spreadsheet/cells.jsx +455 -0
- package/registry/blocks/spreadsheet/chrome.jsx +325 -0
- package/registry/blocks/spreadsheet/demo.jsx +177 -0
- package/registry/blocks/spreadsheet/grid.js +387 -0
- package/registry/blocks/spreadsheet/index.js +34 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
- package/registry/blocks/spreadsheet/types.js +473 -0
- package/registry/blocks/stat-cards/README.md +173 -0
- package/registry/blocks/stat-cards/block.json +10 -0
- package/registry/blocks/stat-cards/demo.jsx +257 -0
- package/registry/blocks/stat-cards/index.js +4 -0
- package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
- package/registry/blocks/stat-cards/usage.jsx +243 -0
- package/registry/blocks/task-list/README.md +176 -0
- package/registry/blocks/task-list/block.json +10 -0
- package/registry/blocks/task-list/demo.jsx +134 -0
- package/registry/blocks/task-list/index.js +5 -0
- package/registry/blocks/task-list/task-list.jsx +907 -0
- package/registry/blocks/task-model/README.md +455 -0
- package/registry/blocks/task-model/block.json +167 -0
- package/registry/blocks/task-model/changes.js +89 -0
- package/registry/blocks/task-model/dates.js +371 -0
- package/registry/blocks/task-model/demo.jsx +215 -0
- package/registry/blocks/task-model/dnd.jsx +240 -0
- package/registry/blocks/task-model/index.js +97 -0
- package/registry/blocks/task-model/model.js +919 -0
- package/registry/blocks/task-model/parts.jsx +449 -0
- package/registry/blocks/task-model/toolbar.jsx +271 -0
- package/registry/blocks/testimonials/README.md +139 -0
- package/registry/blocks/testimonials/block.json +11 -0
- package/registry/blocks/testimonials/demo.jsx +137 -0
- package/registry/blocks/testimonials/index.js +4 -0
- package/registry/blocks/testimonials/testimonials.jsx +430 -0
- package/registry/blocks/transaction-list/README.md +126 -0
- package/registry/blocks/transaction-list/block.json +10 -0
- package/registry/blocks/transaction-list/demo.jsx +79 -0
- package/registry/blocks/transaction-list/index.js +4 -0
- package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
- package/registry/blocks/whiteboard/README.md +179 -0
- package/registry/blocks/whiteboard/block.json +10 -0
- package/registry/blocks/whiteboard/demo.jsx +169 -0
- package/registry/blocks/whiteboard/index.js +6 -0
- package/registry/blocks/whiteboard/templates.js +150 -0
- package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
- package/src/install.mjs +18 -0
- package/src/shadcn.mjs +8 -0
- package/templates/next/files/README.md +145 -11
- package/templates/next/files/app/globals.css +55 -4
- package/templates/next/files/check/run.mjs +3 -3
- package/templates/next/files/components/ui/avatar.jsx +141 -0
- package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
- package/templates/next/files/components/ui/button-group.jsx +70 -0
- package/templates/next/files/components/ui/button.jsx +132 -12
- package/templates/next/files/components/ui/calendar.jsx +609 -0
- package/templates/next/files/components/ui/carousel.jsx +281 -0
- package/templates/next/files/components/ui/collapsible.jsx +208 -0
- package/templates/next/files/components/ui/combobox.jsx +608 -0
- package/templates/next/files/components/ui/command.jsx +577 -0
- package/templates/next/files/components/ui/context-menu.jsx +191 -0
- package/templates/next/files/components/ui/date-picker.jsx +360 -0
- package/templates/next/files/components/ui/distribution.jsx +117 -0
- package/templates/next/files/components/ui/feedback.jsx +143 -0
- package/templates/next/files/components/ui/field.jsx +115 -3
- package/templates/next/files/components/ui/file-input.jsx +234 -0
- package/templates/next/files/components/ui/icon.jsx +130 -8
- package/templates/next/files/components/ui/image.jsx +143 -0
- package/templates/next/files/components/ui/index.js +47 -2
- package/templates/next/files/components/ui/input-group.jsx +213 -0
- package/templates/next/files/components/ui/input-otp.jsx +170 -0
- package/templates/next/files/components/ui/item.jsx +206 -0
- package/templates/next/files/components/ui/menu.jsx +454 -82
- package/templates/next/files/components/ui/notice.jsx +126 -14
- package/templates/next/files/components/ui/pagination.jsx +156 -0
- package/templates/next/files/components/ui/popover.jsx +284 -0
- package/templates/next/files/components/ui/radio.jsx +193 -0
- package/templates/next/files/components/ui/rating.jsx +131 -0
- package/templates/next/files/components/ui/resizable.jsx +338 -0
- package/templates/next/files/components/ui/scroll-area.jsx +123 -0
- package/templates/next/files/components/ui/separator.jsx +119 -0
- package/templates/next/files/components/ui/sheet.jsx +96 -11
- package/templates/next/files/components/ui/slider.jsx +174 -0
- package/templates/next/files/components/ui/stat.jsx +574 -0
- package/templates/next/files/components/ui/steps.jsx +338 -0
- package/templates/next/files/components/ui/swatch.jsx +33 -0
- package/templates/next/files/components/ui/table.jsx +130 -0
- package/templates/next/files/components/ui/toast.jsx +440 -0
- package/templates/next/files/components/ui/toggle.jsx +195 -0
- package/templates/next/files/components/ui/tooltip.jsx +270 -0
- package/templates/next/template.json +264 -8
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/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)",
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useId, useRef } from "react";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { cx } from "./cx";
|
|
6
|
+
import { Icon } from "./icon";
|
|
7
|
+
import { usePopoverPosition } from "./popover";
|
|
8
|
+
|
|
9
|
+
// Breadcrumb — where this page sits: Deals › Acme Corp › Renewal. Items
|
|
10
|
+
// are data; each with an `href` is a next/link (base path applied), the
|
|
11
|
+
// last is the page you are on (aria-current) and is never a link.
|
|
12
|
+
// A client part (a server surface renders it as it is; items are plain
|
|
13
|
+
// data): the "…" that stands in for the middle is a native popover
|
|
14
|
+
// (popovertarget), kept under its button by usePopoverPosition — CSS
|
|
15
|
+
// anchoring where the browser has it, measured where it does not.
|
|
16
|
+
//
|
|
17
|
+
// items [{ label, href? }] — first is the root, last is this page
|
|
18
|
+
// max how many slots on a wide window before the middle folds
|
|
19
|
+
// into "…" (default 4, the "…" counts as one); a narrow
|
|
20
|
+
// window shows first › … › last once there are four or more
|
|
21
|
+
// separator chevron (default) · slash
|
|
22
|
+
//
|
|
23
|
+
// Long labels truncate, the full text on hover. Earlier crumbs are capped
|
|
24
|
+
// (max-w-40, 56 on sm+); the current page takes the rest of the row. One item or none: nothing
|
|
25
|
+
// to place the page within, so nothing is drawn.
|
|
26
|
+
|
|
27
|
+
const SEP = {
|
|
28
|
+
chevron: <Icon name="chevron-right" size={14} />,
|
|
29
|
+
slash: <span className="px-0.5">/</span>,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Shown at one width and not the other: the "…", each crumb, each entry
|
|
33
|
+
// in the popover. Whole class names, so Tailwind sees them.
|
|
34
|
+
const SHOW = {
|
|
35
|
+
flex: { both: "flex", narrow: "flex sm:hidden", wide: "hidden sm:flex", none: "hidden" },
|
|
36
|
+
block: { both: "block", narrow: "block sm:hidden", wide: "hidden sm:block", none: "hidden" },
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Every crumb truncates; only the earlier ones carry a cap. The current
|
|
40
|
+
// page is the one worth reading, so it takes whatever the row has left
|
|
41
|
+
// and cuts off only when the row really runs out. It is clamped to one
|
|
42
|
+
// line rather than kept on one (nowrap), so its narrowest size is a
|
|
43
|
+
// letter, not the whole title: a card or grid cell sized by its content
|
|
44
|
+
// still shrinks to the window instead of being pushed wide by the title.
|
|
45
|
+
const CRUMB = "min-w-0 rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
46
|
+
const CAP = "block max-w-40 truncate sm:max-w-56";
|
|
47
|
+
const REST = "line-clamp-1 [overflow-wrap:anywhere]";
|
|
48
|
+
|
|
49
|
+
export function Breadcrumb({ items, max = 4, separator = "chevron", label = "Breadcrumb", className }) {
|
|
50
|
+
const auto = useId();
|
|
51
|
+
const more = useRef(null);
|
|
52
|
+
const panel = useRef(null);
|
|
53
|
+
usePopoverPosition(more, panel, { side: "bottom", align: "start", offset: 4 });
|
|
54
|
+
const list = (items ?? []).filter(Boolean);
|
|
55
|
+
if (list.length < 2) return null;
|
|
56
|
+
|
|
57
|
+
const id = `crumbs-${auto.replace(/[^a-zA-Z0-9]/g, "")}`;
|
|
58
|
+
const n = list.length;
|
|
59
|
+
const keep = Math.max(1, max - 2); // trailing items kept beside the first and the "…"
|
|
60
|
+
// Middle item i folds on a wide window when there are more than `max`;
|
|
61
|
+
// on a narrow one every middle item folds once there are four or more
|
|
62
|
+
// (three fit, truncated).
|
|
63
|
+
const foldsWide = (i) => n > max && i > 0 && i < n - keep;
|
|
64
|
+
const foldsNarrow = n > 3;
|
|
65
|
+
const middle = list.slice(1, -1).map((item, k) => ({ item, i: k + 1 }));
|
|
66
|
+
const wideFold = middle.some(({ i }) => foldsWide(i));
|
|
67
|
+
const at = (narrow, wide, display = "flex") => SHOW[display][narrow ? (wide ? "both" : "narrow") : wide ? "wide" : "none"];
|
|
68
|
+
const sep = (
|
|
69
|
+
<span aria-hidden="true" className="shrink-0 text-muted-foreground/70">
|
|
70
|
+
{SEP[separator] ?? SEP.chevron}
|
|
71
|
+
</span>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const crumb = (item, current) =>
|
|
75
|
+
current || !item.href ? (
|
|
76
|
+
<span aria-current={current ? "page" : undefined} title={item.label} className={cx(CRUMB, current ? cx(REST, "font-medium text-foreground") : CAP)}>
|
|
77
|
+
{item.label}
|
|
78
|
+
</span>
|
|
79
|
+
) : (
|
|
80
|
+
<Link href={item.href} title={item.label} className={cx(CRUMB, CAP, "transition-colors hover:text-foreground")}>
|
|
81
|
+
{item.label}
|
|
82
|
+
</Link>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<nav aria-label={label} className={cx("min-w-0", className)}>
|
|
87
|
+
<ol className="flex min-w-0 items-center gap-1.5 text-sm text-muted-foreground">
|
|
88
|
+
<li className="flex min-w-0 items-center">{crumb(list[0], false)}</li>
|
|
89
|
+
|
|
90
|
+
{middle.length > 0 ? (
|
|
91
|
+
<li className={cx("shrink-0 items-center gap-1.5", at(foldsNarrow, wideFold))}>
|
|
92
|
+
{sep}
|
|
93
|
+
<button
|
|
94
|
+
type="button"
|
|
95
|
+
ref={more}
|
|
96
|
+
popoverTarget={id}
|
|
97
|
+
aria-label="Show the full path"
|
|
98
|
+
title="Show the full path"
|
|
99
|
+
className="-mx-1 inline-flex h-8 w-8 items-center justify-center rounded-md outline-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
|
|
100
|
+
>
|
|
101
|
+
<Icon name="more" size={18} />
|
|
102
|
+
</button>
|
|
103
|
+
{/* Keyed by the page, so a client navigation lands with it closed. */}
|
|
104
|
+
<div
|
|
105
|
+
key={list[n - 1].href ?? list[n - 1].label}
|
|
106
|
+
ref={panel}
|
|
107
|
+
id={id}
|
|
108
|
+
popover="auto"
|
|
109
|
+
className="min-w-44 max-w-[calc(100vw-2rem)] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg"
|
|
110
|
+
>
|
|
111
|
+
<ul>
|
|
112
|
+
{middle.map(({ item, i }) => (
|
|
113
|
+
<li key={i} className={at(foldsNarrow, foldsWide(i), "block")}>
|
|
114
|
+
{item.href ? (
|
|
115
|
+
<Link
|
|
116
|
+
href={item.href}
|
|
117
|
+
className="flex min-h-10 items-center rounded-sm px-2 text-sm outline-none hover:bg-accent focus-visible:bg-accent"
|
|
118
|
+
>
|
|
119
|
+
<span className="truncate">{item.label}</span>
|
|
120
|
+
</Link>
|
|
121
|
+
) : (
|
|
122
|
+
<span className="flex min-h-10 items-center px-2 text-sm text-muted-foreground">
|
|
123
|
+
<span className="truncate">{item.label}</span>
|
|
124
|
+
</span>
|
|
125
|
+
)}
|
|
126
|
+
</li>
|
|
127
|
+
))}
|
|
128
|
+
</ul>
|
|
129
|
+
</div>
|
|
130
|
+
</li>
|
|
131
|
+
) : null}
|
|
132
|
+
|
|
133
|
+
{middle.map(({ item, i }) => (
|
|
134
|
+
<li key={i} className={cx("min-w-0 items-center gap-1.5", at(!foldsNarrow, !foldsWide(i)))}>
|
|
135
|
+
{sep}
|
|
136
|
+
{crumb(item, false)}
|
|
137
|
+
</li>
|
|
138
|
+
))}
|
|
139
|
+
|
|
140
|
+
{/* The rest of the row, and never less than 10rem (or half a narrow
|
|
141
|
+
row): long earlier crumbs give way before this page's title. */}
|
|
142
|
+
<li className="flex min-w-[min(10rem,50%)] flex-1 items-center gap-1.5">
|
|
143
|
+
{sep}
|
|
144
|
+
{crumb(list[n - 1], true)}
|
|
145
|
+
</li>
|
|
146
|
+
</ol>
|
|
147
|
+
</nav>
|
|
148
|
+
);
|
|
149
|
+
}
|