makersclaw 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +3 -2
- package/r/annotate.json +62 -0
- package/r/approval-request.json +52 -0
- package/r/audio-player.json +74 -0
- package/r/auth-form.json +55 -0
- package/r/board.json +10 -6
- package/r/calendar-view.json +105 -0
- package/r/cart.json +62 -0
- package/r/chart.json +83 -0
- package/r/chat.json +95 -0
- package/r/code-editor.json +94 -0
- package/r/comment-box.json +64 -0
- package/r/contact-section.json +53 -0
- package/r/core.json +205 -8
- package/r/csv-import.json +63 -0
- package/r/data-table.json +69 -0
- package/r/diagram.json +74 -0
- package/r/doc-editor.json +82 -0
- package/r/doc-page.json +61 -0
- package/r/email-render.json +73 -0
- package/r/faq.json +50 -0
- package/r/file-upload.json +54 -0
- package/r/flow-canvas.json +93 -0
- package/r/footer.json +52 -0
- package/r/gantt.json +70 -0
- package/r/job-panel.json +12 -7
- package/r/json-editor.json +66 -0
- package/r/map.json +89 -0
- package/r/menubar.json +52 -0
- package/r/mind-map.json +67 -0
- package/r/navigation-menu.json +52 -0
- package/r/order-detail.json +54 -0
- package/r/org-chart.json +66 -0
- package/r/page-builder.json +105 -0
- package/r/payment-methods.json +51 -0
- package/r/pdf-document.json +79 -0
- package/r/pdf-viewer.json +88 -0
- package/r/product-detail.json +76 -0
- package/r/product-grid.json +65 -0
- package/r/record-form.json +67 -0
- package/r/record-notes.json +55 -0
- package/r/registry.json +3411 -29
- package/r/search-dialog.json +51 -0
- package/r/settings-list.json +66 -0
- package/r/setup-checklist.json +51 -0
- package/r/share-dialog.json +52 -0
- package/r/sidebar.json +69 -0
- package/r/signature-pad.json +72 -0
- package/r/sketch-canvas.json +99 -0
- package/r/spreadsheet.json +90 -0
- package/r/stat-cards.json +66 -0
- package/r/task-list.json +63 -0
- package/r/task-model.json +98 -0
- package/r/testimonials.json +52 -0
- package/r/transaction-list.json +53 -0
- package/r/whiteboard.json +66 -0
- package/registry/blocks/annotate/README.md +179 -0
- package/registry/blocks/annotate/annotate-data.js +250 -0
- package/registry/blocks/annotate/annotate.jsx +646 -0
- package/registry/blocks/annotate/block.json +10 -0
- package/registry/blocks/annotate/demo.jsx +135 -0
- package/registry/blocks/annotate/index.js +15 -0
- package/registry/blocks/approval-request/README.md +116 -0
- package/registry/blocks/approval-request/approval-request.jsx +386 -0
- package/registry/blocks/approval-request/block.json +10 -0
- package/registry/blocks/approval-request/demo.jsx +127 -0
- package/registry/blocks/approval-request/index.js +4 -0
- package/registry/blocks/audio-player/README.md +167 -0
- package/registry/blocks/audio-player/audio-player.jsx +623 -0
- package/registry/blocks/audio-player/block.json +14 -0
- package/registry/blocks/audio-player/colors.js +109 -0
- package/registry/blocks/audio-player/demo.jsx +209 -0
- package/registry/blocks/audio-player/index.js +6 -0
- package/registry/blocks/audio-player/time.js +67 -0
- package/registry/blocks/audio-player/wavesurfer.js +9 -0
- package/registry/blocks/auth-form/README.md +126 -0
- package/registry/blocks/auth-form/auth-form.jsx +568 -0
- package/registry/blocks/auth-form/block.json +10 -0
- package/registry/blocks/auth-form/demo.jsx +131 -0
- package/registry/blocks/auth-form/index.js +3 -0
- package/registry/blocks/board/README.md +55 -5
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +230 -86
- package/registry/blocks/board/demo.jsx +103 -24
- package/registry/blocks/calendar-view/README.md +180 -0
- package/registry/blocks/calendar-view/agenda.jsx +147 -0
- package/registry/blocks/calendar-view/block.json +76 -0
- package/registry/blocks/calendar-view/calendar-model.js +442 -0
- package/registry/blocks/calendar-view/calendar.jsx +627 -0
- package/registry/blocks/calendar-view/demo.jsx +195 -0
- package/registry/blocks/calendar-view/draft.jsx +49 -0
- package/registry/blocks/calendar-view/index.js +39 -0
- package/registry/blocks/calendar-view/month.jsx +346 -0
- package/registry/blocks/calendar-view/paint.js +69 -0
- package/registry/blocks/calendar-view/time-grid.jsx +527 -0
- package/registry/blocks/calendar-view/tray.jsx +87 -0
- package/registry/blocks/cart/README.md +146 -0
- package/registry/blocks/cart/block.json +10 -0
- package/registry/blocks/cart/cart.jsx +597 -0
- package/registry/blocks/cart/demo.jsx +98 -0
- package/registry/blocks/cart/index.js +4 -0
- package/registry/blocks/cart/money.js +28 -0
- package/registry/blocks/chart/README.md +316 -0
- package/registry/blocks/chart/block.json +10 -0
- package/registry/blocks/chart/cartesian.jsx +642 -0
- package/registry/blocks/chart/core.jsx +262 -0
- package/registry/blocks/chart/demo.jsx +357 -0
- package/registry/blocks/chart/heatmap.jsx +336 -0
- package/registry/blocks/chart/index.js +8 -0
- package/registry/blocks/chart/pie.jsx +245 -0
- package/registry/blocks/chart/sparkline.jsx +88 -0
- package/registry/blocks/chat/README.md +273 -0
- package/registry/blocks/chat/attachment.jsx +95 -0
- package/registry/blocks/chat/block.json +10 -0
- package/registry/blocks/chat/chat.jsx +132 -0
- package/registry/blocks/chat/composer.jsx +364 -0
- package/registry/blocks/chat/demo.jsx +578 -0
- package/registry/blocks/chat/header.jsx +34 -0
- package/registry/blocks/chat/index.js +9 -0
- package/registry/blocks/chat/message.jsx +450 -0
- package/registry/blocks/chat/scroller.jsx +247 -0
- package/registry/blocks/chat/text.jsx +104 -0
- package/registry/blocks/code-editor/README.md +210 -0
- package/registry/blocks/code-editor/block.json +22 -0
- package/registry/blocks/code-editor/code-editor.jsx +534 -0
- package/registry/blocks/code-editor/codemirror.js +38 -0
- package/registry/blocks/code-editor/demo.jsx +205 -0
- package/registry/blocks/code-editor/index.js +8 -0
- package/registry/blocks/code-editor/json.js +317 -0
- package/registry/blocks/code-editor/sql.js +136 -0
- package/registry/blocks/code-editor/text.js +101 -0
- package/registry/blocks/code-editor/theme.js +186 -0
- package/registry/blocks/comment-box/README.md +123 -0
- package/registry/blocks/comment-box/block.json +10 -0
- package/registry/blocks/comment-box/comment-body.jsx +217 -0
- package/registry/blocks/comment-box/comment-box.jsx +198 -0
- package/registry/blocks/comment-box/comment-time.jsx +77 -0
- package/registry/blocks/comment-box/demo.jsx +141 -0
- package/registry/blocks/comment-box/index.js +8 -0
- package/registry/blocks/contact-section/README.md +152 -0
- package/registry/blocks/contact-section/block.json +11 -0
- package/registry/blocks/contact-section/contact-section.jsx +509 -0
- package/registry/blocks/contact-section/demo.jsx +93 -0
- package/registry/blocks/contact-section/index.js +4 -0
- package/registry/blocks/csv-import/README.md +133 -0
- package/registry/blocks/csv-import/block.json +13 -0
- package/registry/blocks/csv-import/csv-import.jsx +479 -0
- package/registry/blocks/csv-import/demo.jsx +106 -0
- package/registry/blocks/csv-import/import.js +200 -0
- package/registry/blocks/csv-import/index.js +7 -0
- package/registry/blocks/data-table/README.md +386 -0
- package/registry/blocks/data-table/block.json +10 -0
- package/registry/blocks/data-table/data-table.jsx +1164 -0
- package/registry/blocks/data-table/demo.jsx +588 -0
- package/registry/blocks/data-table/index.js +5 -0
- package/registry/blocks/data-table/model.js +169 -0
- package/registry/blocks/diagram/README.md +108 -0
- package/registry/blocks/diagram/block.json +13 -0
- package/registry/blocks/diagram/demo.jsx +113 -0
- package/registry/blocks/diagram/diagram.jsx +481 -0
- package/registry/blocks/diagram/index.js +7 -0
- package/registry/blocks/diagram/mermaid.js +52 -0
- package/registry/blocks/diagram/palette.js +313 -0
- package/registry/blocks/diagram/source.js +98 -0
- package/registry/blocks/doc-editor/README.md +215 -0
- package/registry/blocks/doc-editor/block.json +15 -0
- package/registry/blocks/doc-editor/demo.jsx +225 -0
- package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
- package/registry/blocks/doc-editor/doc.js +309 -0
- package/registry/blocks/doc-editor/index.js +7 -0
- package/registry/blocks/doc-editor/schema.jsx +56 -0
- package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
- package/registry/blocks/doc-editor/theme.js +82 -0
- package/registry/blocks/doc-page/README.md +119 -0
- package/registry/blocks/doc-page/autosave.js +104 -0
- package/registry/blocks/doc-page/block.json +10 -0
- package/registry/blocks/doc-page/demo.jsx +137 -0
- package/registry/blocks/doc-page/doc-page.jsx +276 -0
- package/registry/blocks/doc-page/index.js +4 -0
- package/registry/blocks/email-render/README.md +151 -0
- package/registry/blocks/email-render/block.json +14 -0
- package/registry/blocks/email-render/demo.jsx +153 -0
- package/registry/blocks/email-render/doc-email.jsx +210 -0
- package/registry/blocks/email-render/email.jsx +221 -0
- package/registry/blocks/email-render/index.js +10 -0
- package/registry/blocks/email-render/render.js +50 -0
- package/registry/blocks/email-render/theme.js +215 -0
- package/registry/blocks/faq/README.md +101 -0
- package/registry/blocks/faq/block.json +11 -0
- package/registry/blocks/faq/demo.jsx +89 -0
- package/registry/blocks/faq/faq.jsx +220 -0
- package/registry/blocks/faq/index.js +4 -0
- package/registry/blocks/file-upload/README.md +138 -0
- package/registry/blocks/file-upload/block.json +10 -0
- package/registry/blocks/file-upload/demo.jsx +204 -0
- package/registry/blocks/file-upload/file-upload.jsx +635 -0
- package/registry/blocks/file-upload/index.js +4 -0
- package/registry/blocks/flow-canvas/README.md +420 -0
- package/registry/blocks/flow-canvas/block.json +13 -0
- package/registry/blocks/flow-canvas/board.js +819 -0
- package/registry/blocks/flow-canvas/chrome.jsx +649 -0
- package/registry/blocks/flow-canvas/context.jsx +35 -0
- package/registry/blocks/flow-canvas/demo.jsx +249 -0
- package/registry/blocks/flow-canvas/edges.jsx +107 -0
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
- package/registry/blocks/flow-canvas/index.js +41 -0
- package/registry/blocks/flow-canvas/nodes.jsx +392 -0
- package/registry/blocks/flow-canvas/theme.js +174 -0
- package/registry/blocks/footer/README.md +133 -0
- package/registry/blocks/footer/block.json +11 -0
- package/registry/blocks/footer/demo.jsx +119 -0
- package/registry/blocks/footer/footer.jsx +406 -0
- package/registry/blocks/footer/index.js +4 -0
- package/registry/blocks/gantt/README.md +220 -0
- package/registry/blocks/gantt/block.json +10 -0
- package/registry/blocks/gantt/demo.jsx +148 -0
- package/registry/blocks/gantt/gantt.jsx +923 -0
- package/registry/blocks/gantt/index.js +7 -0
- package/registry/blocks/gantt/rows.jsx +468 -0
- package/registry/blocks/gantt/schedule.js +278 -0
- package/registry/blocks/job-panel/README.md +80 -0
- package/registry/blocks/job-panel/block.json +3 -3
- package/registry/blocks/job-panel/demo.jsx +230 -3
- package/registry/blocks/job-panel/job-panel.jsx +169 -3
- package/registry/blocks/json-editor/README.md +133 -0
- package/registry/blocks/json-editor/block.json +10 -0
- package/registry/blocks/json-editor/demo.jsx +92 -0
- package/registry/blocks/json-editor/index.js +7 -0
- package/registry/blocks/json-editor/json-editor.jsx +305 -0
- package/registry/blocks/json-editor/json-tree.jsx +393 -0
- package/registry/blocks/json-editor/tree.js +225 -0
- package/registry/blocks/map/README.md +221 -0
- package/registry/blocks/map/block.json +14 -0
- package/registry/blocks/map/demo.jsx +201 -0
- package/registry/blocks/map/geo.js +198 -0
- package/registry/blocks/map/index.js +8 -0
- package/registry/blocks/map/list.jsx +128 -0
- package/registry/blocks/map/map-view.jsx +715 -0
- package/registry/blocks/map/maplibre.js +30 -0
- package/registry/blocks/map/marks.jsx +146 -0
- package/registry/blocks/map/theme.js +142 -0
- package/registry/blocks/menubar/README.md +109 -0
- package/registry/blocks/menubar/block.json +10 -0
- package/registry/blocks/menubar/demo.jsx +128 -0
- package/registry/blocks/menubar/index.js +4 -0
- package/registry/blocks/menubar/menubar.jsx +199 -0
- package/registry/blocks/mind-map/README.md +206 -0
- package/registry/blocks/mind-map/block.json +10 -0
- package/registry/blocks/mind-map/demo.jsx +103 -0
- package/registry/blocks/mind-map/index.js +31 -0
- package/registry/blocks/mind-map/mind-map.jsx +1125 -0
- package/registry/blocks/mind-map/topic.jsx +143 -0
- package/registry/blocks/mind-map/tree.js +645 -0
- package/registry/blocks/navigation-menu/README.md +124 -0
- package/registry/blocks/navigation-menu/block.json +10 -0
- package/registry/blocks/navigation-menu/demo.jsx +84 -0
- package/registry/blocks/navigation-menu/index.js +4 -0
- package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
- package/registry/blocks/order-detail/README.md +109 -0
- package/registry/blocks/order-detail/block.json +10 -0
- package/registry/blocks/order-detail/demo.jsx +88 -0
- package/registry/blocks/order-detail/index.js +4 -0
- package/registry/blocks/order-detail/order-detail.jsx +354 -0
- package/registry/blocks/org-chart/README.md +145 -0
- package/registry/blocks/org-chart/block.json +10 -0
- package/registry/blocks/org-chart/demo.jsx +94 -0
- package/registry/blocks/org-chart/index.js +7 -0
- package/registry/blocks/org-chart/org-chart.jsx +631 -0
- package/registry/blocks/org-chart/org.js +245 -0
- package/registry/blocks/org-chart/person.jsx +96 -0
- package/registry/blocks/page-builder/README.md +257 -0
- package/registry/blocks/page-builder/block.json +14 -0
- package/registry/blocks/page-builder/demo.jsx +145 -0
- package/registry/blocks/page-builder/grapes.js +18 -0
- package/registry/blocks/page-builder/index.js +11 -0
- package/registry/blocks/page-builder/page-builder.jsx +704 -0
- package/registry/blocks/page-builder/page-view.jsx +33 -0
- package/registry/blocks/page-builder/page.js +118 -0
- package/registry/blocks/page-builder/panels.jsx +588 -0
- package/registry/blocks/page-builder/sections.js +209 -0
- package/registry/blocks/page-builder/theme.js +87 -0
- package/registry/blocks/page-builder/thumbs.jsx +189 -0
- package/registry/blocks/page-builder/tokens.js +329 -0
- package/registry/blocks/payment-methods/README.md +104 -0
- package/registry/blocks/payment-methods/block.json +10 -0
- package/registry/blocks/payment-methods/demo.jsx +71 -0
- package/registry/blocks/payment-methods/index.js +4 -0
- package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
- package/registry/blocks/pdf-document/README.md +213 -0
- package/registry/blocks/pdf-document/block.json +13 -0
- package/registry/blocks/pdf-document/demo.jsx +136 -0
- package/registry/blocks/pdf-document/index.js +33 -0
- package/registry/blocks/pdf-document/money.js +83 -0
- package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
- package/registry/blocks/pdf-document/primitives.jsx +271 -0
- package/registry/blocks/pdf-document/quote.jsx +179 -0
- package/registry/blocks/pdf-document/theme.js +193 -0
- package/registry/blocks/pdf-viewer/README.md +191 -0
- package/registry/blocks/pdf-viewer/block.json +14 -0
- package/registry/blocks/pdf-viewer/demo.jsx +252 -0
- package/registry/blocks/pdf-viewer/helpers.js +270 -0
- package/registry/blocks/pdf-viewer/index.js +8 -0
- package/registry/blocks/pdf-viewer/notes.jsx +195 -0
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
- package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
- package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
- package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
- package/registry/blocks/product-detail/README.md +217 -0
- package/registry/blocks/product-detail/block.json +10 -0
- package/registry/blocks/product-detail/demo.jsx +233 -0
- package/registry/blocks/product-detail/index.js +7 -0
- package/registry/blocks/product-detail/price.jsx +115 -0
- package/registry/blocks/product-detail/product-detail.jsx +348 -0
- package/registry/blocks/product-detail/product-media.jsx +102 -0
- package/registry/blocks/product-detail/product-options.jsx +144 -0
- package/registry/blocks/product-grid/README.md +162 -0
- package/registry/blocks/product-grid/block.json +10 -0
- package/registry/blocks/product-grid/demo.jsx +255 -0
- package/registry/blocks/product-grid/index.js +5 -0
- package/registry/blocks/product-grid/product-card.jsx +232 -0
- package/registry/blocks/product-grid/product-grid.jsx +235 -0
- package/registry/blocks/record-form/README.md +196 -0
- package/registry/blocks/record-form/block.json +10 -0
- package/registry/blocks/record-form/demo.jsx +525 -0
- package/registry/blocks/record-form/index.js +4 -0
- package/registry/blocks/record-form/record-fields.jsx +457 -0
- package/registry/blocks/record-form/record-form.jsx +415 -0
- package/registry/blocks/record-form/rules.js +81 -0
- package/registry/blocks/record-notes/README.md +139 -0
- package/registry/blocks/record-notes/block.json +10 -0
- package/registry/blocks/record-notes/demo.jsx +179 -0
- package/registry/blocks/record-notes/index.js +4 -0
- package/registry/blocks/record-notes/record-notes.jsx +266 -0
- package/registry/blocks/search-dialog/README.md +108 -0
- package/registry/blocks/search-dialog/block.json +10 -0
- package/registry/blocks/search-dialog/demo.jsx +116 -0
- package/registry/blocks/search-dialog/index.js +3 -0
- package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
- package/registry/blocks/settings-list/README.md +171 -0
- package/registry/blocks/settings-list/block.json +10 -0
- package/registry/blocks/settings-list/demo.jsx +333 -0
- package/registry/blocks/settings-list/index.js +4 -0
- package/registry/blocks/settings-list/row-state.jsx +93 -0
- package/registry/blocks/settings-list/settings-list.jsx +349 -0
- package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
- package/registry/blocks/setup-checklist/README.md +142 -0
- package/registry/blocks/setup-checklist/block.json +10 -0
- package/registry/blocks/setup-checklist/demo.jsx +159 -0
- package/registry/blocks/setup-checklist/index.js +4 -0
- package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
- package/registry/blocks/share-dialog/README.md +113 -0
- package/registry/blocks/share-dialog/block.json +10 -0
- package/registry/blocks/share-dialog/demo.jsx +140 -0
- package/registry/blocks/share-dialog/index.js +3 -0
- package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
- package/registry/blocks/sidebar/README.md +190 -0
- package/registry/blocks/sidebar/block.json +43 -0
- package/registry/blocks/sidebar/demo.jsx +577 -0
- package/registry/blocks/sidebar/index.js +4 -0
- package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
- package/registry/blocks/sidebar/sidebar.jsx +864 -0
- package/registry/blocks/signature-pad/README.md +137 -0
- package/registry/blocks/signature-pad/block.json +13 -0
- package/registry/blocks/signature-pad/colors.js +115 -0
- package/registry/blocks/signature-pad/demo.jsx +94 -0
- package/registry/blocks/signature-pad/index.js +6 -0
- package/registry/blocks/signature-pad/pad.js +7 -0
- package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
- package/registry/blocks/signature-pad/signature.js +68 -0
- package/registry/blocks/sketch-canvas/README.md +280 -0
- package/registry/blocks/sketch-canvas/block.json +13 -0
- package/registry/blocks/sketch-canvas/demo.jsx +159 -0
- package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
- package/registry/blocks/sketch-canvas/index.js +9 -0
- package/registry/blocks/sketch-canvas/palette.js +226 -0
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
- package/registry/blocks/sketch-canvas/sketch.js +179 -0
- package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
- package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
- package/registry/blocks/sketch-canvas/stamps.js +104 -0
- package/registry/blocks/sketch-canvas/theme.js +131 -0
- package/registry/blocks/spreadsheet/README.md +307 -0
- package/registry/blocks/spreadsheet/block.json +13 -0
- package/registry/blocks/spreadsheet/cells.jsx +455 -0
- package/registry/blocks/spreadsheet/chrome.jsx +325 -0
- package/registry/blocks/spreadsheet/demo.jsx +177 -0
- package/registry/blocks/spreadsheet/grid.js +387 -0
- package/registry/blocks/spreadsheet/index.js +34 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
- package/registry/blocks/spreadsheet/types.js +473 -0
- package/registry/blocks/stat-cards/README.md +173 -0
- package/registry/blocks/stat-cards/block.json +10 -0
- package/registry/blocks/stat-cards/demo.jsx +257 -0
- package/registry/blocks/stat-cards/index.js +4 -0
- package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
- package/registry/blocks/stat-cards/usage.jsx +243 -0
- package/registry/blocks/task-list/README.md +176 -0
- package/registry/blocks/task-list/block.json +10 -0
- package/registry/blocks/task-list/demo.jsx +134 -0
- package/registry/blocks/task-list/index.js +5 -0
- package/registry/blocks/task-list/task-list.jsx +907 -0
- package/registry/blocks/task-model/README.md +455 -0
- package/registry/blocks/task-model/block.json +167 -0
- package/registry/blocks/task-model/changes.js +89 -0
- package/registry/blocks/task-model/dates.js +371 -0
- package/registry/blocks/task-model/demo.jsx +215 -0
- package/registry/blocks/task-model/dnd.jsx +240 -0
- package/registry/blocks/task-model/index.js +97 -0
- package/registry/blocks/task-model/model.js +919 -0
- package/registry/blocks/task-model/parts.jsx +449 -0
- package/registry/blocks/task-model/toolbar.jsx +271 -0
- package/registry/blocks/testimonials/README.md +139 -0
- package/registry/blocks/testimonials/block.json +11 -0
- package/registry/blocks/testimonials/demo.jsx +137 -0
- package/registry/blocks/testimonials/index.js +4 -0
- package/registry/blocks/testimonials/testimonials.jsx +430 -0
- package/registry/blocks/transaction-list/README.md +126 -0
- package/registry/blocks/transaction-list/block.json +10 -0
- package/registry/blocks/transaction-list/demo.jsx +79 -0
- package/registry/blocks/transaction-list/index.js +4 -0
- package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
- package/registry/blocks/whiteboard/README.md +179 -0
- package/registry/blocks/whiteboard/block.json +10 -0
- package/registry/blocks/whiteboard/demo.jsx +169 -0
- package/registry/blocks/whiteboard/index.js +6 -0
- package/registry/blocks/whiteboard/templates.js +150 -0
- package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
- package/src/cli.mjs +19 -6
- package/src/install.mjs +18 -0
- package/src/registry.mjs +38 -4
- package/src/shadcn.mjs +14 -1
- package/templates/next/files/README.md +145 -11
- package/templates/next/files/app/globals.css +55 -4
- package/templates/next/files/check/run.mjs +3 -3
- package/templates/next/files/components/ui/avatar.jsx +141 -0
- package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
- package/templates/next/files/components/ui/button-group.jsx +70 -0
- package/templates/next/files/components/ui/button.jsx +132 -12
- package/templates/next/files/components/ui/calendar.jsx +609 -0
- package/templates/next/files/components/ui/carousel.jsx +281 -0
- package/templates/next/files/components/ui/collapsible.jsx +208 -0
- package/templates/next/files/components/ui/combobox.jsx +608 -0
- package/templates/next/files/components/ui/command.jsx +577 -0
- package/templates/next/files/components/ui/context-menu.jsx +191 -0
- package/templates/next/files/components/ui/date-picker.jsx +360 -0
- package/templates/next/files/components/ui/distribution.jsx +117 -0
- package/templates/next/files/components/ui/feedback.jsx +143 -0
- package/templates/next/files/components/ui/field.jsx +115 -3
- package/templates/next/files/components/ui/file-input.jsx +234 -0
- package/templates/next/files/components/ui/icon.jsx +130 -8
- package/templates/next/files/components/ui/image.jsx +143 -0
- package/templates/next/files/components/ui/index.js +47 -2
- package/templates/next/files/components/ui/input-group.jsx +213 -0
- package/templates/next/files/components/ui/input-otp.jsx +170 -0
- package/templates/next/files/components/ui/item.jsx +206 -0
- package/templates/next/files/components/ui/menu.jsx +454 -82
- package/templates/next/files/components/ui/notice.jsx +126 -14
- package/templates/next/files/components/ui/pagination.jsx +156 -0
- package/templates/next/files/components/ui/popover.jsx +284 -0
- package/templates/next/files/components/ui/radio.jsx +193 -0
- package/templates/next/files/components/ui/rating.jsx +131 -0
- package/templates/next/files/components/ui/resizable.jsx +338 -0
- package/templates/next/files/components/ui/scroll-area.jsx +123 -0
- package/templates/next/files/components/ui/separator.jsx +119 -0
- package/templates/next/files/components/ui/sheet.jsx +96 -11
- package/templates/next/files/components/ui/slider.jsx +174 -0
- package/templates/next/files/components/ui/stat.jsx +574 -0
- package/templates/next/files/components/ui/steps.jsx +338 -0
- package/templates/next/files/components/ui/swatch.jsx +33 -0
- package/templates/next/files/components/ui/table.jsx +130 -0
- package/templates/next/files/components/ui/toast.jsx +440 -0
- package/templates/next/files/components/ui/toggle.jsx +195 -0
- package/templates/next/files/components/ui/tooltip.jsx +270 -0
- package/templates/next/template.json +264 -8
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Avatar, Button, Calendar, Icon, Menu, Popover, StatusDot, cx } from "../../ui";
|
|
5
|
+
import { addDays, dayOf, dueBucket, endOfWeek, formatDay, formatTime, minutesOf, withTime } from "./dates";
|
|
6
|
+
import { NONE, PRIORITIES, createTaskContext, isDone } from "./model";
|
|
7
|
+
|
|
8
|
+
// The small pieces every task view draws the same way: a status, the
|
|
9
|
+
// people on it, its due date, its priority, a compact chip. Each is a
|
|
10
|
+
// label by default and a picker when given `onChange` — the view hands
|
|
11
|
+
// the picked value to its commit. Tokens only: a status says its tone,
|
|
12
|
+
// a project its hue (chart-1…5).
|
|
13
|
+
|
|
14
|
+
const ctxOf = (ctx) => (ctx && ctx.statusById ? ctx : createTaskContext(ctx ?? {}));
|
|
15
|
+
|
|
16
|
+
export const TONE_TEXT = {
|
|
17
|
+
neutral: "text-muted-foreground",
|
|
18
|
+
primary: "text-primary",
|
|
19
|
+
info: "text-info",
|
|
20
|
+
success: "text-success",
|
|
21
|
+
warning: "text-warning",
|
|
22
|
+
danger: "text-destructive",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const HUE_EDGE = {
|
|
26
|
+
1: "border-s-chart-1",
|
|
27
|
+
2: "border-s-chart-2",
|
|
28
|
+
3: "border-s-chart-3",
|
|
29
|
+
4: "border-s-chart-4",
|
|
30
|
+
5: "border-s-chart-5",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const HUE_BG = {
|
|
34
|
+
1: "bg-chart-1",
|
|
35
|
+
2: "bg-chart-2",
|
|
36
|
+
3: "bg-chart-3",
|
|
37
|
+
4: "bg-chart-4",
|
|
38
|
+
5: "bg-chart-5",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// A trigger that looks like its label until hovered: the pickers' face.
|
|
42
|
+
const PICK = "rounded-md px-1.5 hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring";
|
|
43
|
+
|
|
44
|
+
/** A status as a dot and its words. With `onChange(id)`, a menu of the
|
|
45
|
+
* statuses. `size` sm (a row) · md. `hideLabel` for a dense cell. */
|
|
46
|
+
export function StatusPill({ status, ctx, onChange, size = "sm", hideLabel = false, className }) {
|
|
47
|
+
const c = ctxOf(ctx);
|
|
48
|
+
const s = c.statusById.get(String(status));
|
|
49
|
+
const face = (
|
|
50
|
+
<span className={cx("relative inline-flex min-w-0 items-center gap-1.5", size === "sm" ? "text-xs" : "text-sm")}>
|
|
51
|
+
<StatusDot tone={s ? s.tone ?? (s.hue ? undefined : "neutral") : "neutral"} hue={s?.hue} size={size === "sm" ? "sm" : "md"} />
|
|
52
|
+
<span className={cx("truncate", hideLabel && "sr-only", s ? "text-foreground" : "text-muted-foreground")}>{s?.label ?? "No status"}</span>
|
|
53
|
+
</span>
|
|
54
|
+
);
|
|
55
|
+
if (!onChange) return <span className={cx("inline-flex min-w-0", className)}>{face}</span>;
|
|
56
|
+
return (
|
|
57
|
+
<Menu
|
|
58
|
+
label={`Status: ${s?.label ?? "none"}. Change status`}
|
|
59
|
+
trigger={face}
|
|
60
|
+
align="start"
|
|
61
|
+
className={cx(PICK, className)}
|
|
62
|
+
items={[
|
|
63
|
+
{
|
|
64
|
+
type: "radio",
|
|
65
|
+
value: s?.id ?? "",
|
|
66
|
+
onValueChange: (v) => v !== s?.id && onChange(v),
|
|
67
|
+
options: c.statuses.map((x) => ({ value: x.id, label: x.label })),
|
|
68
|
+
},
|
|
69
|
+
]}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The round check that completes a task (not the square one that
|
|
75
|
+
* selects it). Shows the done state; `onToggle()` when pressed. */
|
|
76
|
+
export function CompleteToggle({ done, onToggle, label = "task", disabled, size = "md", className }) {
|
|
77
|
+
const box = size === "sm" ? "size-4" : "size-[18px]";
|
|
78
|
+
return (
|
|
79
|
+
// raw: a completion check is round and toggles a status, not a form
|
|
80
|
+
// value — the kit's Checkbox is the square selection box beside it.
|
|
81
|
+
<button
|
|
82
|
+
type="button"
|
|
83
|
+
role="checkbox"
|
|
84
|
+
aria-checked={Boolean(done)}
|
|
85
|
+
aria-label={done ? `Mark ${label} not done` : `Complete ${label}`}
|
|
86
|
+
disabled={disabled || !onToggle}
|
|
87
|
+
onClick={onToggle}
|
|
88
|
+
className={cx(
|
|
89
|
+
"group/check inline-flex size-9 shrink-0 items-center justify-center rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default",
|
|
90
|
+
className,
|
|
91
|
+
)}
|
|
92
|
+
>
|
|
93
|
+
<span
|
|
94
|
+
className={cx(
|
|
95
|
+
"inline-flex items-center justify-center rounded-full border transition-colors duration-150",
|
|
96
|
+
box,
|
|
97
|
+
done ? "border-success bg-success text-background" : "border-muted-foreground/50 text-transparent group-hover/check:border-success group-hover/check:text-success",
|
|
98
|
+
)}
|
|
99
|
+
>
|
|
100
|
+
<Icon name="check" size={size === "sm" ? 10 : 12} />
|
|
101
|
+
</span>
|
|
102
|
+
</button>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** The people on a task: overlapping faces, or a dashed "assign" circle.
|
|
107
|
+
* With `onChange(ids)`, a menu of people to tick (it stays open). */
|
|
108
|
+
export function AssigneeStack({ ids, ctx, onChange, max = 3, size = "xs", className }) {
|
|
109
|
+
const c = ctxOf(ctx);
|
|
110
|
+
const list = (ids ?? []).map((id) => c.personById.get(String(id)) ?? { id, name: String(id) });
|
|
111
|
+
// Spans, not the kit's AvatarGroup (a div): the faces sit inside the
|
|
112
|
+
// picker's button, where a div is invalid HTML.
|
|
113
|
+
const shown = list.slice(0, max);
|
|
114
|
+
const rest = list.length - shown.length;
|
|
115
|
+
const face = list.length ? (
|
|
116
|
+
<span className="inline-flex items-center -space-x-1.5" title={list.map((p) => p.name).join(", ")}>
|
|
117
|
+
{shown.map((p) => (
|
|
118
|
+
<Avatar key={p.id} name={p.name} src={p.src} size={size} className="ring-2 ring-card" />
|
|
119
|
+
))}
|
|
120
|
+
{rest > 0 ? (
|
|
121
|
+
<span data-nums className="relative inline-flex size-6 items-center justify-center rounded-full bg-muted text-2xs font-medium text-muted-foreground ring-2 ring-card">
|
|
122
|
+
+{rest}
|
|
123
|
+
</span>
|
|
124
|
+
) : null}
|
|
125
|
+
</span>
|
|
126
|
+
) : (
|
|
127
|
+
<span aria-hidden="true" className="inline-flex size-6 items-center justify-center rounded-full border border-dashed border-muted-foreground/50 text-muted-foreground">
|
|
128
|
+
<Icon name="user" size={12} />
|
|
129
|
+
</span>
|
|
130
|
+
);
|
|
131
|
+
if (!onChange) {
|
|
132
|
+
return list.length ? (
|
|
133
|
+
<span className={cx("inline-flex", className)}>{face}</span>
|
|
134
|
+
) : (
|
|
135
|
+
<span className={cx("relative inline-flex", className)}>
|
|
136
|
+
{face}
|
|
137
|
+
<span className="sr-only">Unassigned</span>
|
|
138
|
+
</span>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const set = new Set((ids ?? []).map(String));
|
|
142
|
+
return (
|
|
143
|
+
<Menu
|
|
144
|
+
label={list.length ? `Assigned to ${list.map((p) => p.name).join(", ")}. Change` : "Assign"}
|
|
145
|
+
trigger={face}
|
|
146
|
+
className={cx(PICK, className)}
|
|
147
|
+
items={
|
|
148
|
+
c.people.length
|
|
149
|
+
? c.people.map((p) => ({
|
|
150
|
+
type: "checkbox",
|
|
151
|
+
label: p.name,
|
|
152
|
+
checked: set.has(p.id),
|
|
153
|
+
onCheckedChange: (on) => onChange(on ? [...set, p.id] : [...set].filter((x) => x !== p.id)),
|
|
154
|
+
}))
|
|
155
|
+
: [{ type: "label", label: "No people to assign yet" }]
|
|
156
|
+
}
|
|
157
|
+
/>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** One person: a face and a name (a group header, a workload row). */
|
|
162
|
+
export function PersonLabel({ id, ctx, size = "xs", className }) {
|
|
163
|
+
const c = ctxOf(ctx);
|
|
164
|
+
if (!id || id === NONE) {
|
|
165
|
+
return (
|
|
166
|
+
<span className={cx("inline-flex items-center gap-2", className)}>
|
|
167
|
+
<span aria-hidden="true" className="inline-flex size-6 items-center justify-center rounded-full border border-dashed border-muted-foreground/50 text-muted-foreground">
|
|
168
|
+
<Icon name="user" size={12} />
|
|
169
|
+
</span>
|
|
170
|
+
<span className="truncate">Unassigned</span>
|
|
171
|
+
</span>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const p = c.personById.get(String(id)) ?? { name: String(id) };
|
|
175
|
+
return (
|
|
176
|
+
<span className={cx("inline-flex min-w-0 items-center gap-2", className)}>
|
|
177
|
+
<Avatar name={p.name} src={p.src} size={size} />
|
|
178
|
+
<span className="truncate">{p.name}</span>
|
|
179
|
+
</span>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const DUE_TONE = { overdue: "text-destructive", today: "text-warning" };
|
|
184
|
+
|
|
185
|
+
/** A due date the way a person says it ("Today", "Fri", "Oct 30"), red
|
|
186
|
+
* when overdue and amber today — unless the task is done. With
|
|
187
|
+
* `onChange(day | null)`, a calendar with quick picks; an empty one
|
|
188
|
+
* shows only its glyph until the row is hovered (`quiet`, default) —
|
|
189
|
+
* pass quiet={false} to always say `placeholder`. */
|
|
190
|
+
export function DueLabel({ value, done = false, ctx, onChange, placeholder = "Due date", quiet = true, className }) {
|
|
191
|
+
const c = ctxOf(ctx);
|
|
192
|
+
const [open, setOpen] = useState(false);
|
|
193
|
+
const day = dayOf(value);
|
|
194
|
+
const bucket = dueBucket(value, c.today, { done, weekStartsOn: c.weekStartsOn });
|
|
195
|
+
const time = formatTime(value);
|
|
196
|
+
const words = day ? `${formatDay(day, c.today)}${time ? ` ${time}` : ""}` : "";
|
|
197
|
+
const face = (
|
|
198
|
+
<span className={cx("inline-flex items-center gap-1 whitespace-nowrap text-xs", day ? DUE_TONE[bucket] ?? "text-muted-foreground" : "text-muted-foreground")}>
|
|
199
|
+
<Icon name="calendar" size={14} className={day ? undefined : "opacity-60"} />
|
|
200
|
+
{day ? (
|
|
201
|
+
<span data-nums>{words}</span>
|
|
202
|
+
) : onChange ? (
|
|
203
|
+
<span className={quiet ? "sr-only sm:not-sr-only sm:opacity-0 sm:transition-opacity sm:duration-150 sm:group-hover/row:opacity-100 sm:group-focus-within/row:opacity-100" : undefined}>{placeholder}</span>
|
|
204
|
+
) : null}
|
|
205
|
+
</span>
|
|
206
|
+
);
|
|
207
|
+
if (!onChange) {
|
|
208
|
+
return day ? (
|
|
209
|
+
<span className={cx("inline-flex", className)} title={bucket === "overdue" ? "Overdue" : undefined}>
|
|
210
|
+
{face}
|
|
211
|
+
</span>
|
|
212
|
+
) : null;
|
|
213
|
+
}
|
|
214
|
+
const pick = (d) => {
|
|
215
|
+
setOpen(false);
|
|
216
|
+
onChange(d ? withTime(d, minutesOf(value)) : null);
|
|
217
|
+
};
|
|
218
|
+
const quick = [
|
|
219
|
+
{ label: "Today", day: c.today },
|
|
220
|
+
{ label: "Tomorrow", day: addDays(c.today, 1) },
|
|
221
|
+
{ label: "Next week", day: addDays(endOfWeek(c.today, c.weekStartsOn), 1) },
|
|
222
|
+
];
|
|
223
|
+
return (
|
|
224
|
+
<Popover
|
|
225
|
+
label={day ? `Due ${words}. Change due date` : "Set a due date"}
|
|
226
|
+
open={open}
|
|
227
|
+
onOpenChange={setOpen}
|
|
228
|
+
width="auto"
|
|
229
|
+
align="end"
|
|
230
|
+
className="p-2"
|
|
231
|
+
trigger={(props) => (
|
|
232
|
+
// raw: Popover hands its trigger props (ref, popoverTarget) to a
|
|
233
|
+
// button of ours; the face is a date's words, not a kit Button.
|
|
234
|
+
<button type="button" {...props} aria-label={day ? `Due ${words}. Change due date` : "Set a due date"} className={cx("inline-flex min-h-9 items-center outline-none", PICK, className)}>
|
|
235
|
+
{face}
|
|
236
|
+
</button>
|
|
237
|
+
)}
|
|
238
|
+
>
|
|
239
|
+
<div className="grid gap-2">
|
|
240
|
+
<div className="flex flex-wrap gap-1">
|
|
241
|
+
{quick.map((q) => (
|
|
242
|
+
<Button key={q.label} size="sm" variant={q.day === day ? "secondary" : "quiet"} onClick={() => pick(q.day)}>
|
|
243
|
+
{q.label}
|
|
244
|
+
</Button>
|
|
245
|
+
))}
|
|
246
|
+
</div>
|
|
247
|
+
<Calendar value={day} onChange={(d) => pick(d)} today={c.today} weekStartsOn={c.weekStartsOn} size="sm" autoFocus={open} label="Due date" />
|
|
248
|
+
{day ? (
|
|
249
|
+
<Button size="sm" variant="quiet" icon="x" align="start" onClick={() => pick(null)}>
|
|
250
|
+
Remove due date
|
|
251
|
+
</Button>
|
|
252
|
+
) : null}
|
|
253
|
+
</div>
|
|
254
|
+
</Popover>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** A priority as a flag in its tone. With `onChange(id | null)`, a menu. */
|
|
259
|
+
export function PriorityFlag({ value, onChange, showLabel = false, className }) {
|
|
260
|
+
const p = PRIORITIES.find((x) => x.id === value);
|
|
261
|
+
const face = (
|
|
262
|
+
<span className={cx("relative inline-flex items-center gap-1 text-xs", p ? TONE_TEXT[p.tone] : "text-muted-foreground")}>
|
|
263
|
+
<Icon name="flag" size={14} className={p ? undefined : "opacity-40"} />
|
|
264
|
+
{showLabel && p ? <span className="text-foreground">{p.label}</span> : null}
|
|
265
|
+
{!p ? <span className="sr-only">No priority</span> : null}
|
|
266
|
+
</span>
|
|
267
|
+
);
|
|
268
|
+
if (!onChange) {
|
|
269
|
+
if (!p) return null;
|
|
270
|
+
return (
|
|
271
|
+
// relative: its sr-only label is absolute, and without a positioned
|
|
272
|
+
// parent inside a sideways-scrolling row it escaped the scroller and
|
|
273
|
+
// widened the page (task-model at 390px, 2026-09-24).
|
|
274
|
+
<span className={cx("relative inline-flex", className)} title={`${p.label} priority`}>
|
|
275
|
+
{face}
|
|
276
|
+
<span className="sr-only">{p.label} priority</span>
|
|
277
|
+
</span>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
return (
|
|
281
|
+
<Menu
|
|
282
|
+
label={p ? `${p.label} priority. Change priority` : "Set priority"}
|
|
283
|
+
trigger={face}
|
|
284
|
+
className={cx(PICK, !p && "opacity-0 transition-opacity duration-150 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-visible:opacity-100 [@media(hover:none)]:opacity-100", className)}
|
|
285
|
+
items={[
|
|
286
|
+
{
|
|
287
|
+
type: "radio",
|
|
288
|
+
value: p?.id ?? NONE,
|
|
289
|
+
onValueChange: (v) => onChange(v === NONE ? null : v),
|
|
290
|
+
options: [...PRIORITIES.map((x) => ({ value: x.id, label: x.label })), { value: NONE, label: "No priority" }],
|
|
291
|
+
},
|
|
292
|
+
]}
|
|
293
|
+
/>
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/** Tags as quiet chips; the first `max`, then "+N". */
|
|
298
|
+
export function TagList({ tags, max = 2, className }) {
|
|
299
|
+
const list = tags ?? [];
|
|
300
|
+
if (!list.length) return null;
|
|
301
|
+
const shown = list.slice(0, max);
|
|
302
|
+
const rest = list.length - shown.length;
|
|
303
|
+
return (
|
|
304
|
+
<span className={cx("inline-flex min-w-0 items-center gap-1", className)}>
|
|
305
|
+
{shown.map((t) => (
|
|
306
|
+
<span key={t} className="max-w-28 truncate rounded-sm bg-muted px-1.5 py-0.5 text-2xs text-muted-foreground">
|
|
307
|
+
{t}
|
|
308
|
+
</span>
|
|
309
|
+
))}
|
|
310
|
+
{rest > 0 ? (
|
|
311
|
+
<span className="text-2xs text-muted-foreground" title={list.slice(max).join(", ")}>
|
|
312
|
+
+{rest}
|
|
313
|
+
</span>
|
|
314
|
+
) : null}
|
|
315
|
+
</span>
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** "2/5" subtasks done, with the list glyph. */
|
|
320
|
+
export function SubtaskCount({ done, total, className }) {
|
|
321
|
+
if (!total) return null;
|
|
322
|
+
return (
|
|
323
|
+
<span className={cx("inline-flex items-center gap-1 text-xs text-muted-foreground", className)} title={`${done} of ${total} subtasks done`}>
|
|
324
|
+
<Icon name="list" size={14} />
|
|
325
|
+
<span data-nums>
|
|
326
|
+
{done}/{total}
|
|
327
|
+
</span>
|
|
328
|
+
</span>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** A thin progress line (0–100) for a row or a bar. */
|
|
333
|
+
export function ProgressLine({ value, className }) {
|
|
334
|
+
const v = Math.max(0, Math.min(100, Number(value) || 0));
|
|
335
|
+
return (
|
|
336
|
+
<span className={cx("relative block h-1 w-full overflow-hidden rounded-full bg-muted", className)} role="img" aria-label={`${Math.round(v)}% done`}>
|
|
337
|
+
<span className={cx("absolute inset-y-0 start-0 rounded-full", v >= 100 ? "bg-success" : "bg-primary")} style={{ width: `${v}%` }} />
|
|
338
|
+
</span>
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** A task as one compact line: the chip a calendar day, a gantt label or
|
|
343
|
+
* a workload cell draws. Status dot, title, time (when it has one), the
|
|
344
|
+
* first face; a project's hue on its leading edge. `onOpen(task)` makes
|
|
345
|
+
* it a button. Spread drag props (`dragProps`) onto it for dragging. */
|
|
346
|
+
export function TaskChip({ task, ctx, onOpen, showTime = true, showPeople = true, dragging = false, lifted = false, dragProps, className }) {
|
|
347
|
+
const c = ctxOf(ctx);
|
|
348
|
+
const s = c.statusById.get(String(task.status));
|
|
349
|
+
const project = c.projectById.get(String(task.project));
|
|
350
|
+
const done = isDone(task, c);
|
|
351
|
+
const time = showTime ? formatTime(task.start ?? task.due) : "";
|
|
352
|
+
const first = task.assignees?.[0] ? c.personById.get(task.assignees[0]) : null;
|
|
353
|
+
const Tag = onOpen ? "button" : "div";
|
|
354
|
+
return (
|
|
355
|
+
// raw: a chip is a draggable, openable card-let; a kit Button would
|
|
356
|
+
// centre and pad it as an action.
|
|
357
|
+
<Tag
|
|
358
|
+
type={onOpen ? "button" : undefined}
|
|
359
|
+
onClick={onOpen ? () => onOpen(task) : undefined}
|
|
360
|
+
{...dragProps}
|
|
361
|
+
className={cx(
|
|
362
|
+
"flex w-full min-w-0 items-center gap-1.5 rounded-md border border-border bg-card px-2 py-1 text-left text-xs text-card-foreground outline-none transition-[box-shadow,opacity] duration-150",
|
|
363
|
+
project?.hue && HUE_EDGE[project.hue] ? cx("border-s-[3px]", HUE_EDGE[project.hue]) : null,
|
|
364
|
+
onOpen && "hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring",
|
|
365
|
+
dragging && "opacity-40",
|
|
366
|
+
lifted && "cursor-grabbing shadow-lg ring-1 ring-border",
|
|
367
|
+
className,
|
|
368
|
+
)}
|
|
369
|
+
>
|
|
370
|
+
<StatusDot tone={s?.tone ?? (s?.hue ? undefined : "neutral")} hue={s?.hue} size="sm" />
|
|
371
|
+
{time ? (
|
|
372
|
+
<span data-nums className="shrink-0 text-muted-foreground">
|
|
373
|
+
{time}
|
|
374
|
+
</span>
|
|
375
|
+
) : null}
|
|
376
|
+
<span className={cx("min-w-0 flex-1 truncate font-medium", done && "text-muted-foreground line-through")}>{task.title || "Untitled"}</span>
|
|
377
|
+
{showPeople && first ? <Avatar name={first.name} src={first.src} size="xs" /> : null}
|
|
378
|
+
</Tag>
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** A group's heading face: the status dot, a person, a flag, a project
|
|
383
|
+
* hue, or the plain words — whatever the view is grouped by. */
|
|
384
|
+
export function GroupLabel({ group, by, ctx, className }) {
|
|
385
|
+
const c = ctxOf(ctx);
|
|
386
|
+
const kind = by ? c.fields.find((f) => f.key === by)?.kind : null;
|
|
387
|
+
if (kind === "people") return <PersonLabel id={group.key} ctx={c} className={cx("text-sm font-semibold", className)} />;
|
|
388
|
+
let lead = null;
|
|
389
|
+
if (kind === "status") lead = <StatusDot tone={group.tone ?? (group.hue ? undefined : "neutral")} hue={group.hue} />;
|
|
390
|
+
else if (kind === "priority") lead = <Icon name="flag" size={14} className={group.tone ? TONE_TEXT[group.tone] : "text-muted-foreground opacity-50"} />;
|
|
391
|
+
else if (kind === "project" && group.hue && HUE_BG[group.hue]) lead = <span aria-hidden="true" className={cx("size-2 shrink-0 rounded-sm", HUE_BG[group.hue])} />;
|
|
392
|
+
else if (kind === "date") lead = <Icon name="calendar" size={14} className={group.tone ? TONE_TEXT[group.tone] : "text-muted-foreground"} />;
|
|
393
|
+
return (
|
|
394
|
+
<span className={cx("inline-flex min-w-0 items-center gap-2 text-sm font-semibold", className)}>
|
|
395
|
+
{lead}
|
|
396
|
+
<span className="truncate">{group.label}</span>
|
|
397
|
+
</span>
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** DataTable columns for toTableRows rows: name, status, assignees, due,
|
|
402
|
+
* priority, project, estimate, progress, tags — sortable, drawn with the
|
|
403
|
+
* parts above. `keys` picks and orders them. Pass `onChange(change)` to
|
|
404
|
+
* make status / people / due / priority cells pickers. */
|
|
405
|
+
export function taskColumns(ctx, { keys = ["title", "status", "assignees", "due", "priority"], onChange } = {}) {
|
|
406
|
+
const c = ctxOf(ctx);
|
|
407
|
+
const set = (row, patch) => onChange?.({ type: "update", id: row.id, patch });
|
|
408
|
+
const edit = typeof onChange === "function";
|
|
409
|
+
const all = {
|
|
410
|
+
title: { key: "title", header: "Name", sortable: true, hideable: false, cell: (r) => <span className={cx("font-medium", r.done && "text-muted-foreground line-through")}>{r.title}</span> },
|
|
411
|
+
status: {
|
|
412
|
+
key: "status",
|
|
413
|
+
header: "Status",
|
|
414
|
+
sortable: true,
|
|
415
|
+
sortValue: (r) => r.statusIndex,
|
|
416
|
+
searchValue: (r) => r.statusLabel,
|
|
417
|
+
cell: (r) => <StatusPill status={r.status} ctx={c} onChange={edit ? (v) => set(r, { status: v }) : undefined} />,
|
|
418
|
+
},
|
|
419
|
+
assignees: {
|
|
420
|
+
key: "assignees",
|
|
421
|
+
header: "Assignee",
|
|
422
|
+
sortable: true,
|
|
423
|
+
sortValue: (r) => r.assigneeNames || null,
|
|
424
|
+
searchValue: (r) => r.assigneeNames,
|
|
425
|
+
cell: (r) => <AssigneeStack ids={r.assignees} ctx={c} onChange={edit ? (v) => set(r, { assignees: v }) : undefined} />,
|
|
426
|
+
},
|
|
427
|
+
due: {
|
|
428
|
+
key: "due",
|
|
429
|
+
header: "Due",
|
|
430
|
+
sortable: true,
|
|
431
|
+
sortValue: (r) => r.dueDay,
|
|
432
|
+
cell: (r) => <DueLabel value={r.due} done={r.done} ctx={c} onChange={edit ? (v) => set(r, { due: v }) : undefined} />,
|
|
433
|
+
},
|
|
434
|
+
start: { key: "start", header: "Start", sortable: true, sortValue: (r) => dayOf(r.start), cell: (r) => (r.start ? formatDay(r.start, c.today) : "") },
|
|
435
|
+
priority: {
|
|
436
|
+
key: "priority",
|
|
437
|
+
header: "Priority",
|
|
438
|
+
sortable: true,
|
|
439
|
+
sortValue: (r) => r.priorityRank,
|
|
440
|
+
searchValue: (r) => r.priorityLabel,
|
|
441
|
+
cell: (r) => <PriorityFlag value={r.priority} showLabel onChange={edit ? (v) => set(r, { priority: v }) : undefined} />,
|
|
442
|
+
},
|
|
443
|
+
project: { key: "project", header: "Project", sortable: true, sortValue: (r) => r.projectName || null, searchValue: (r) => r.projectName, cell: (r) => r.projectName },
|
|
444
|
+
estimate: { key: "estimate", header: "Estimate", sortable: true, align: "end", cell: (r) => (r.estimate ? `${r.estimate}h` : "") },
|
|
445
|
+
progress: { key: "progress", header: "Progress", sortable: true, width: "8rem", cell: (r) => (typeof r.progress === "number" ? <ProgressLine value={r.progress} /> : null) },
|
|
446
|
+
tags: { key: "tags", header: "Tags", searchValue: (r) => (r.tags ?? []).join(" "), cell: (r) => <TagList tags={r.tags} /> },
|
|
447
|
+
};
|
|
448
|
+
return keys.map((k) => all[k]).filter(Boolean);
|
|
449
|
+
}
|