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,262 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { Empty, Toggle, cx } from "../../ui";
|
|
5
|
+
|
|
6
|
+
// What every chart in this block shares: the series colours as classes,
|
|
7
|
+
// nice ticks, the width of the box it sits in, the reveal, the legend, the
|
|
8
|
+
// tooltip box and the hidden data table a screen reader reads. The charts
|
|
9
|
+
// themselves are in cartesian.jsx, pie.jsx and sparkline.jsx.
|
|
10
|
+
|
|
11
|
+
// ---- colours ---------------------------------------------------------------
|
|
12
|
+
// Written out whole so Tailwind finds every class. chart-1…5 are the series
|
|
13
|
+
// colours (app/globals.css); the rest are the theme's own tones, for the
|
|
14
|
+
// one series that means a status (churn in the destructive tone).
|
|
15
|
+
const TONES = {
|
|
16
|
+
"chart-1": { fill: "fill-chart-1", stroke: "stroke-chart-1", bg: "bg-chart-1", text: "text-chart-1" },
|
|
17
|
+
"chart-2": { fill: "fill-chart-2", stroke: "stroke-chart-2", bg: "bg-chart-2", text: "text-chart-2" },
|
|
18
|
+
"chart-3": { fill: "fill-chart-3", stroke: "stroke-chart-3", bg: "bg-chart-3", text: "text-chart-3" },
|
|
19
|
+
"chart-4": { fill: "fill-chart-4", stroke: "stroke-chart-4", bg: "bg-chart-4", text: "text-chart-4" },
|
|
20
|
+
"chart-5": { fill: "fill-chart-5", stroke: "stroke-chart-5", bg: "bg-chart-5", text: "text-chart-5" },
|
|
21
|
+
primary: { fill: "fill-primary", stroke: "stroke-primary", bg: "bg-primary", text: "text-primary" },
|
|
22
|
+
info: { fill: "fill-info", stroke: "stroke-info", bg: "bg-info", text: "text-info" },
|
|
23
|
+
success: { fill: "fill-success", stroke: "stroke-success", bg: "bg-success", text: "text-success" },
|
|
24
|
+
warning: { fill: "fill-warning", stroke: "stroke-warning", bg: "bg-warning", text: "text-warning" },
|
|
25
|
+
danger: { fill: "fill-destructive", stroke: "stroke-destructive", bg: "bg-destructive", text: "text-destructive" },
|
|
26
|
+
muted: { fill: "fill-muted-foreground", stroke: "stroke-muted-foreground", bg: "bg-muted-foreground", text: "text-muted-foreground" },
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** The tone a series (or a slice) wears: its own `tone` (chart-1…5, 1…5,
|
|
30
|
+
* or a theme tone), else the next chart colour in order. */
|
|
31
|
+
export function toneOf(item, index) {
|
|
32
|
+
const t = typeof item?.tone === "number" ? `chart-${item.tone}` : item?.tone;
|
|
33
|
+
return TONES[t] ? t : `chart-${(index % 5) + 1}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function tone(t, kind) {
|
|
37
|
+
return (TONES[t] ?? TONES["chart-1"])[kind];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ---- numbers ---------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
const COMPACT = new Intl.NumberFormat(undefined, { notation: "compact", maximumFractionDigits: 1 });
|
|
43
|
+
const PLAIN = new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 });
|
|
44
|
+
|
|
45
|
+
/** The default value formatter: 1,250 · 48.2K · 1.3M. */
|
|
46
|
+
export function defaultFormat(v) {
|
|
47
|
+
if (v == null || Number.isNaN(v)) return "—";
|
|
48
|
+
return Math.abs(v) >= 10000 ? COMPACT.format(v) : PLAIN.format(v);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function num(v) {
|
|
52
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
53
|
+
return Number.isFinite(n) ? n : null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Round numbers that cover [min, max] in about `count` steps. */
|
|
57
|
+
export function niceTicks(min, max, count = 5) {
|
|
58
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) return [0, 1];
|
|
59
|
+
if (min === max) {
|
|
60
|
+
if (min === 0) return [0, 1];
|
|
61
|
+
min = Math.min(0, min);
|
|
62
|
+
max = Math.max(0, max);
|
|
63
|
+
}
|
|
64
|
+
const raw = (max - min) / Math.max(1, count);
|
|
65
|
+
const mag = 10 ** Math.floor(Math.log10(raw));
|
|
66
|
+
const err = raw / mag;
|
|
67
|
+
const step = (err >= 7.5 ? 10 : err >= 3.5 ? 5 : err >= 1.5 ? 2 : 1) * mag;
|
|
68
|
+
const lo = Math.floor(min / step) * step;
|
|
69
|
+
const hi = Math.ceil(max / step) * step;
|
|
70
|
+
const out = [];
|
|
71
|
+
for (let v = lo; v <= hi + step / 2; v += step) out.push(Number(v.toPrecision(12)));
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function humanize(key) {
|
|
76
|
+
const text = String(key ?? "").replace(/[_-]+/g, " ").trim();
|
|
77
|
+
return text ? text.charAt(0).toUpperCase() + text.slice(1) : "";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** About how wide a label is at text-2xs, for margins and thinning. The
|
|
81
|
+
* axis text is small and the estimate generous, so nothing is clipped. */
|
|
82
|
+
export function textWidth(s) {
|
|
83
|
+
return String(s ?? "").length * 6.4 + 4;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** A safe id fragment for url(#…) from React's useId. */
|
|
87
|
+
export function idFrom(uid) {
|
|
88
|
+
return `c${String(uid).replace(/[^a-zA-Z0-9-]/g, "")}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---- the box ---------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
/** The width of the element, kept current by a ResizeObserver: a chart is
|
|
94
|
+
* drawn for the width it has, never scaled. A callback ref, so a box that
|
|
95
|
+
* comes back (after the empty state) is measured again. 0 until measured.
|
|
96
|
+
*
|
|
97
|
+
* const [boxRef, width] = useWidth(); <div ref={boxRef}>…</div> */
|
|
98
|
+
export function useWidth() {
|
|
99
|
+
const [el, setEl] = useState(null);
|
|
100
|
+
const [width, setWidth] = useState(0);
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (!el) return undefined;
|
|
103
|
+
setWidth(Math.floor(el.getBoundingClientRect().width));
|
|
104
|
+
if (typeof ResizeObserver === "undefined") return undefined;
|
|
105
|
+
const ro = new ResizeObserver(([entry]) => setWidth(Math.floor(entry.contentRect.width)));
|
|
106
|
+
ro.observe(el);
|
|
107
|
+
return () => ro.disconnect();
|
|
108
|
+
}, [el]);
|
|
109
|
+
return [setEl, width];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** false for the first frame once `ready`, then true: marks draw from
|
|
113
|
+
* nothing to their place. The transitions are motion-safe: classes, so
|
|
114
|
+
* with reduced motion they simply appear. */
|
|
115
|
+
export function useReveal(ready) {
|
|
116
|
+
const [shown, setShown] = useState(false);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (!ready || shown) return undefined;
|
|
119
|
+
// A frame, so the start is painted; the timer, because a hidden tab
|
|
120
|
+
// runs no frames and the chart must never stay empty.
|
|
121
|
+
const done = () => setShown(true);
|
|
122
|
+
const frame = requestAnimationFrame(() => requestAnimationFrame(done));
|
|
123
|
+
const timer = setTimeout(done, 120);
|
|
124
|
+
return () => {
|
|
125
|
+
cancelAnimationFrame(frame);
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
};
|
|
128
|
+
}, [ready, shown]);
|
|
129
|
+
return shown;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---- the parts every chart draws ----------------------------------------------
|
|
133
|
+
|
|
134
|
+
// A square of the series' colour; a dashed series gets a short dashed line.
|
|
135
|
+
function Swatch({ t, dim, dashed }) {
|
|
136
|
+
if (dashed) {
|
|
137
|
+
return (
|
|
138
|
+
<svg aria-hidden="true" width="12" height="10" viewBox="0 0 12 10" className={cx("shrink-0", dim && "opacity-30")}>
|
|
139
|
+
<line x1="0" y1="5" x2="12" y2="5" strokeWidth="2" strokeDasharray="3 2" className={tone(t, "stroke")} />
|
|
140
|
+
</svg>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
return <span aria-hidden="true" className={cx("size-2.5 shrink-0 rounded-sm", tone(t, "bg"), dim && "opacity-30")} />;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The key to a chart's colours. With `onToggle` each entry is a toggle
|
|
148
|
+
* (pressed = shown) that hides or shows its series; without it, a plain
|
|
149
|
+
* list. `items` [{ key, label, tone?, value?, dashed? }] — `value` is a
|
|
150
|
+
* muted note after the label (a slice's share); `dashed` draws the key as
|
|
151
|
+
* a dashed line (a comparison series).
|
|
152
|
+
*/
|
|
153
|
+
export function ChartLegend({ items, hidden, onToggle, className, label = "Legend" }) {
|
|
154
|
+
const list = (items ?? []).filter(Boolean);
|
|
155
|
+
if (!list.length) return null;
|
|
156
|
+
const off = hidden instanceof Set ? hidden : new Set(hidden ?? []);
|
|
157
|
+
if (!onToggle) {
|
|
158
|
+
return (
|
|
159
|
+
<ul aria-label={label} className={cx("flex flex-wrap items-center justify-center gap-x-4 gap-y-1 text-xs text-muted-foreground", className)}>
|
|
160
|
+
{list.map((it, i) => (
|
|
161
|
+
<li key={it.key} className="flex items-center gap-1.5">
|
|
162
|
+
<Swatch t={toneOf(it, i)} dashed={it.dashed} />
|
|
163
|
+
<span className="text-foreground">{it.label ?? humanize(it.key)}</span>
|
|
164
|
+
{it.value != null ? <span data-nums>{it.value}</span> : null}
|
|
165
|
+
</li>
|
|
166
|
+
))}
|
|
167
|
+
</ul>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return (
|
|
171
|
+
<div role="group" aria-label={label} className={cx("flex flex-wrap items-center justify-center gap-1", className)}>
|
|
172
|
+
{list.map((it, i) => {
|
|
173
|
+
const shown = !off.has(it.key);
|
|
174
|
+
return (
|
|
175
|
+
<Toggle
|
|
176
|
+
key={it.key}
|
|
177
|
+
size="sm"
|
|
178
|
+
variant="quiet"
|
|
179
|
+
pressed={shown}
|
|
180
|
+
onPressedChange={() => onToggle(it.key)}
|
|
181
|
+
className="gap-1.5 text-xs"
|
|
182
|
+
>
|
|
183
|
+
<Swatch t={toneOf(it, i)} dim={!shown} dashed={it.dashed} />
|
|
184
|
+
<span className={shown ? "text-foreground" : "line-through"}>{it.label ?? humanize(it.key)}</span>
|
|
185
|
+
{it.value != null ? <span data-nums className="text-muted-foreground">{it.value}</span> : null}
|
|
186
|
+
</Toggle>
|
|
187
|
+
);
|
|
188
|
+
})}
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** The floating box that says what is under the pointer (or the keyboard).
|
|
194
|
+
* `at` { x, y, flip } in the chart's pixels; flip puts it on the left. */
|
|
195
|
+
export function TooltipBox({ at, title, rows, footer }) {
|
|
196
|
+
if (!at) return null;
|
|
197
|
+
return (
|
|
198
|
+
<div
|
|
199
|
+
aria-hidden="true"
|
|
200
|
+
className="pointer-events-none absolute left-0 top-0 z-10 min-w-36 rounded-md border border-border bg-popover px-2.5 py-2 text-xs text-popover-foreground shadow-lg"
|
|
201
|
+
style={{
|
|
202
|
+
transform: `translate(${Math.round(at.x)}px, ${Math.round(at.y)}px) translate(${at.flip ? "calc(-100% - 12px)" : "12px"}, ${at.middle ? "-50%" : "0"})`,
|
|
203
|
+
}}
|
|
204
|
+
>
|
|
205
|
+
{title != null ? <p className="mb-1.5 font-medium">{title}</p> : null}
|
|
206
|
+
<div className="grid gap-1">
|
|
207
|
+
{rows.map((r) => (
|
|
208
|
+
<div key={r.key} className="flex items-center gap-2">
|
|
209
|
+
<Swatch t={r.tone} dashed={r.dashed} />
|
|
210
|
+
<span className="flex-1 text-muted-foreground">{r.label}</span>
|
|
211
|
+
<span data-nums className="font-medium">{r.value}</span>
|
|
212
|
+
</div>
|
|
213
|
+
))}
|
|
214
|
+
</div>
|
|
215
|
+
{footer ? (
|
|
216
|
+
<div className="mt-1.5 flex items-center justify-between gap-2 border-t border-border pt-1.5">
|
|
217
|
+
<span className="text-muted-foreground">{footer.label}</span>
|
|
218
|
+
<span data-nums className="font-medium">{footer.value}</span>
|
|
219
|
+
</div>
|
|
220
|
+
) : null}
|
|
221
|
+
</div>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** The numbers behind the picture, for a screen reader: a real table,
|
|
226
|
+
* visually hidden. `head` the column names, `body` rows of strings. */
|
|
227
|
+
export function DataTable({ caption, head, body }) {
|
|
228
|
+
return (
|
|
229
|
+
<table className="sr-only">
|
|
230
|
+
<caption>{caption}</caption>
|
|
231
|
+
<thead>
|
|
232
|
+
<tr>
|
|
233
|
+
{head.map((h, i) => (
|
|
234
|
+
<th key={i} scope="col">{h}</th>
|
|
235
|
+
))}
|
|
236
|
+
</tr>
|
|
237
|
+
</thead>
|
|
238
|
+
<tbody>
|
|
239
|
+
{body.map((cells, r) => (
|
|
240
|
+
<tr key={r}>
|
|
241
|
+
{cells.map((c, i) =>
|
|
242
|
+
i === 0 ? (
|
|
243
|
+
<th key={i} scope="row">{c}</th>
|
|
244
|
+
) : (
|
|
245
|
+
<td key={i}>{c}</td>
|
|
246
|
+
),
|
|
247
|
+
)}
|
|
248
|
+
</tr>
|
|
249
|
+
))}
|
|
250
|
+
</tbody>
|
|
251
|
+
</table>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** What a chart shows with nothing to draw, at the height it would have. */
|
|
256
|
+
export function ChartEmpty({ height, title, body }) {
|
|
257
|
+
return (
|
|
258
|
+
<div style={{ minHeight: height }} className="grid">
|
|
259
|
+
<Empty icon="chart" title={title} body={body} className="h-full content-center" />
|
|
260
|
+
</div>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// The charts with numbers in memory — the gallery's and the smoke test's
|
|
4
|
+
// surface. Not installed into apps: `makersclaw add chart` lays index.js
|
|
5
|
+
// and the chart files only.
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { Badge, Card, Stat, StatGroup, Toggle, ToggleGroup } from "../components/ui";
|
|
8
|
+
import { AreaChart, BarChart, HeatmapChart, LineChart, PieChart, ScaleLegend, Sparkline } from "../components/blocks/chart";
|
|
9
|
+
|
|
10
|
+
const REVENUE = [
|
|
11
|
+
{ month: "Oct", newBiz: 18400, expansion: 6200, services: 3100 },
|
|
12
|
+
{ month: "Nov", newBiz: 21300, expansion: 6900, services: 2800 },
|
|
13
|
+
{ month: "Dec", newBiz: 17800, expansion: 7400, services: 2200 },
|
|
14
|
+
{ month: "Jan", newBiz: 24600, expansion: 8100, services: 3900 },
|
|
15
|
+
{ month: "Feb", newBiz: 26900, expansion: 8800, services: 4100 },
|
|
16
|
+
{ month: "Mar", newBiz: 31200, expansion: 9600, services: 3600 },
|
|
17
|
+
{ month: "Apr", newBiz: 29400, expansion: 11200, services: 4400 },
|
|
18
|
+
{ month: "May", newBiz: 34800, expansion: 12100, services: 4800 },
|
|
19
|
+
{ month: "Jun", newBiz: 38100, expansion: 13900, services: 5200 },
|
|
20
|
+
{ month: "Jul", newBiz: 36500, expansion: 15400, services: 4700 },
|
|
21
|
+
{ month: "Aug", newBiz: 42700, expansion: 16800, services: 5600 },
|
|
22
|
+
{ month: "Sep", newBiz: 47900, expansion: 18300, services: 6100 },
|
|
23
|
+
];
|
|
24
|
+
const REVENUE_SERIES = [
|
|
25
|
+
{ key: "newBiz", label: "New business" },
|
|
26
|
+
{ key: "expansion", label: "Expansion" },
|
|
27
|
+
{ key: "services", label: "Services" },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const STAGES = [
|
|
31
|
+
{ stage: "Lead", thisQ: 142, lastQ: 118 },
|
|
32
|
+
{ stage: "Qualified", thisQ: 86, lastQ: 74 },
|
|
33
|
+
{ stage: "Demo", thisQ: 51, lastQ: 49 },
|
|
34
|
+
{ stage: "Proposal", thisQ: 29, lastQ: 31 },
|
|
35
|
+
{ stage: "Negotiation", thisQ: 17, lastQ: 12 },
|
|
36
|
+
{ stage: "Won", thisQ: 11, lastQ: 8 },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const SOURCES = [
|
|
40
|
+
{ source: "Outbound", amount: 412000 },
|
|
41
|
+
{ source: "Inbound", amount: 286000 },
|
|
42
|
+
{ source: "Referral", amount: 174000 },
|
|
43
|
+
{ source: "Partners", amount: 98000 },
|
|
44
|
+
{ source: "Events", amount: 61000 },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
// A distribution: each status's share of the tickets, a value label at the
|
|
48
|
+
// end of each bar and a track behind it.
|
|
49
|
+
const STATUS_SHARE = [
|
|
50
|
+
{ status: "Open", share: 42 },
|
|
51
|
+
{ status: "In progress", share: 27 },
|
|
52
|
+
{ status: "Waiting on customer", share: 13 },
|
|
53
|
+
{ status: "Resolved", share: 10 },
|
|
54
|
+
{ status: "Closed", share: 8 },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const REPLY = [
|
|
58
|
+
{ week: "W27", email: 4.1, linkedin: 7.8 },
|
|
59
|
+
{ week: "W28", email: 3.8, linkedin: 8.4 },
|
|
60
|
+
{ week: "W29", email: 4.6, linkedin: 8.1 },
|
|
61
|
+
{ week: "W30", email: 5.2, linkedin: 9.3 },
|
|
62
|
+
{ week: "W31", email: 4.9, linkedin: 10.2 },
|
|
63
|
+
{ week: "W32", email: 5.8, linkedin: 9.7 },
|
|
64
|
+
{ week: "W33", email: 6.3, linkedin: 11.4 },
|
|
65
|
+
{ week: "W34", email: 6.1, linkedin: 12.0 },
|
|
66
|
+
{ week: "W35", email: 7.0, linkedin: 11.6 },
|
|
67
|
+
{ week: "W36", email: 6.8, linkedin: 12.9 },
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
// A pivot: one row per time slot, one key per weekday.
|
|
71
|
+
const DAYS = [
|
|
72
|
+
{ key: "mon", label: "Mon" },
|
|
73
|
+
{ key: "tue", label: "Tue" },
|
|
74
|
+
{ key: "wed", label: "Wed" },
|
|
75
|
+
{ key: "thu", label: "Thu" },
|
|
76
|
+
{ key: "fri", label: "Fri" },
|
|
77
|
+
{ key: "sat", label: "Sat" },
|
|
78
|
+
{ key: "sun", label: "Sun" },
|
|
79
|
+
];
|
|
80
|
+
const TRAFFIC = [
|
|
81
|
+
{ slot: "00–04", mon: 2, tue: 1, wed: 3, thu: 2, fri: 4, sat: 6, sun: 5 },
|
|
82
|
+
{ slot: "04–08", mon: 8, tue: 9, wed: 7, thu: 10, fri: 8, sat: 3, sun: 2 },
|
|
83
|
+
{ slot: "08–12", mon: 41, tue: 52, wed: 48, thu: 55, fri: 44, sat: 12, sun: 9 },
|
|
84
|
+
{ slot: "12–16", mon: 38, tue: 61, wed: 65, thu: 58, fri: 36, sat: 18, sun: 14 },
|
|
85
|
+
{ slot: "16–20", mon: 27, tue: 33, wed: 29, thu: 31, fri: 22, sat: 25, sun: 21 },
|
|
86
|
+
{ slot: "20–24", mon: 11, tue: 14, wed: 12, thu: 9, fri: 16, sat: 19, sun: 17 },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
// Commits per weekday over the last four weeks: a compact grid, no numbers.
|
|
90
|
+
const WEEKS = ["w1", "w2", "w3", "w4"].map((key, i) => ({ key, label: `Wk ${i + 1}` }));
|
|
91
|
+
const COMMITS = [
|
|
92
|
+
{ day: "Mon", w1: 4, w2: 7, w3: 2, w4: 9 },
|
|
93
|
+
{ day: "Tue", w1: 6, w2: 3, w3: 8, w4: 11 },
|
|
94
|
+
{ day: "Wed", w1: 12, w2: 5, w3: 0, w4: 7 },
|
|
95
|
+
{ day: "Thu", w1: 3, w2: 9, w3: 6, w4: 13 },
|
|
96
|
+
{ day: "Fri", w1: 8, w2: 2, w3: 4, w4: 6 },
|
|
97
|
+
{ day: "Sat", w1: 0, w2: 1, w3: 0, w4: 2 },
|
|
98
|
+
{ day: "Sun", w1: 1, w2: 0, w3: 3, w4: null },
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const KPIS = [
|
|
102
|
+
{ label: "MRR", value: "$84.2k", change: "+6.1%", tone: "success", trend: [61.2, 62.8, 64.1, 66.9, 68.4, 70.2, 73.8, 75.1, 78.6, 79.4, 82.0, 84.2], line: "chart-1", unit: (v) => `$${v}k` },
|
|
103
|
+
{ label: "New deals", value: "38", change: "+9", tone: "success", trend: [22, 25, 21, 27, 29, 26, 31, 30, 34, 33, 29, 38], line: "chart-2", unit: (v) => String(v) },
|
|
104
|
+
{ label: "Win rate", value: "27%", change: "+2.4 pts", tone: "success", trend: [21.4, 22.0, 21.1, 23.5, 22.8, 24.1, 24.9, 23.7, 25.6, 26.0, 24.6, 27.0], line: "chart-3", unit: (v) => `${v}%` },
|
|
105
|
+
{ label: "Logo churn", value: "1.8%", change: "−0.3 pts", tone: "success", trend: [2.9, 2.7, 3.1, 2.6, 2.4, 2.5, 2.2, 2.3, 2.0, 2.1, 2.1, 1.8], line: "chart-4", unit: (v) => `${v}%` },
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
// This period against the last: the comparison is muted and dashed.
|
|
109
|
+
const SIGNUPS = [
|
|
110
|
+
{ day: "Mon", thisWeek: 42, lastWeek: 35 },
|
|
111
|
+
{ day: "Tue", thisWeek: 51, lastWeek: 39 },
|
|
112
|
+
{ day: "Wed", thisWeek: 47, lastWeek: 44 },
|
|
113
|
+
{ day: "Thu", thisWeek: 63, lastWeek: 41 },
|
|
114
|
+
{ day: "Fri", thisWeek: 58, lastWeek: 46 },
|
|
115
|
+
{ day: "Sat", thisWeek: 29, lastWeek: 24 },
|
|
116
|
+
{ day: "Sun", thisWeek: 33, lastWeek: 27 },
|
|
117
|
+
];
|
|
118
|
+
const PAID = [
|
|
119
|
+
{ month: "Apr", thisYear: 12400, lastYear: 8900 },
|
|
120
|
+
{ month: "May", thisYear: 14100, lastYear: 9800 },
|
|
121
|
+
{ month: "Jun", thisYear: 13600, lastYear: 11200 },
|
|
122
|
+
{ month: "Jul", thisYear: 16900, lastYear: 11900 },
|
|
123
|
+
{ month: "Aug", thisYear: 18800, lastYear: 12600 },
|
|
124
|
+
{ month: "Sep", thisYear: 21300, lastYear: 13100 },
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
const usd = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 0 });
|
|
128
|
+
const usdShort = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", notation: "compact", maximumFractionDigits: 1 });
|
|
129
|
+
|
|
130
|
+
export default function ChartDemo() {
|
|
131
|
+
const [empty, setEmpty] = useState(false);
|
|
132
|
+
const [stacked, setStacked] = useState(true);
|
|
133
|
+
const [orientation, setOrientation] = useState("vertical");
|
|
134
|
+
const [barsStacked, setBarsStacked] = useState(false);
|
|
135
|
+
const [picked, setPicked] = useState(null);
|
|
136
|
+
const pick = (rows) => (empty ? [] : rows);
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<div className="grid gap-4">
|
|
140
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
141
|
+
<p className="text-sm text-muted-foreground">Sales dashboard · last 12 months</p>
|
|
142
|
+
<ToggleGroup
|
|
143
|
+
size="sm"
|
|
144
|
+
aria-label="Data"
|
|
145
|
+
value={empty ? "empty" : "data"}
|
|
146
|
+
onChange={(v) => setEmpty(v === "empty")}
|
|
147
|
+
items={[
|
|
148
|
+
{ value: "data", label: "With data" },
|
|
149
|
+
{ value: "empty", label: "Empty" },
|
|
150
|
+
]}
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
|
|
155
|
+
{KPIS.map((k) => (
|
|
156
|
+
<Card key={k.label} className="grid gap-2">
|
|
157
|
+
<p className="text-xs text-muted-foreground">{k.label}</p>
|
|
158
|
+
<div className="flex flex-wrap items-baseline gap-x-2 gap-y-1">
|
|
159
|
+
<span data-nums className="text-2xl font-semibold leading-none">
|
|
160
|
+
{empty ? "—" : k.value}
|
|
161
|
+
</span>
|
|
162
|
+
{empty ? null : <Badge tone={k.tone}>{k.change}</Badge>}
|
|
163
|
+
</div>
|
|
164
|
+
<Sparkline data={pick(k.trend)} tone={k.line} label={`${k.label}, last 12 months`} format={k.unit} />
|
|
165
|
+
</Card>
|
|
166
|
+
))}
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<Card
|
|
170
|
+
title="Revenue by month"
|
|
171
|
+
description={empty ? "No invoices yet" : `${usd.format(REVENUE.reduce((s, r) => s + r.newBiz + r.expansion + r.services, 0))} over 12 months`}
|
|
172
|
+
actions={
|
|
173
|
+
<Toggle size="sm" pressed={stacked} onPressedChange={setStacked}>
|
|
174
|
+
Stacked
|
|
175
|
+
</Toggle>
|
|
176
|
+
}
|
|
177
|
+
>
|
|
178
|
+
<AreaChart
|
|
179
|
+
data={pick(REVENUE)}
|
|
180
|
+
x="month"
|
|
181
|
+
series={REVENUE_SERIES}
|
|
182
|
+
stacked={stacked}
|
|
183
|
+
format={(v) => usd.format(v)}
|
|
184
|
+
formatAxis={(v) => usdShort.format(v)}
|
|
185
|
+
label="Revenue by month"
|
|
186
|
+
height={260}
|
|
187
|
+
emptyLabel="No revenue yet"
|
|
188
|
+
emptyBody="Paid invoices appear here by the month they were paid."
|
|
189
|
+
/>
|
|
190
|
+
</Card>
|
|
191
|
+
|
|
192
|
+
<div className="grid gap-4 lg:grid-cols-2">
|
|
193
|
+
<Card
|
|
194
|
+
title="Deals by stage"
|
|
195
|
+
description={picked ? `${picked.stage}: ${picked.thisQ} deals this quarter` : "This quarter against last. Click a stage."}
|
|
196
|
+
actions={
|
|
197
|
+
<Toggle size="sm" pressed={barsStacked} onPressedChange={setBarsStacked}>
|
|
198
|
+
Stacked
|
|
199
|
+
</Toggle>
|
|
200
|
+
}
|
|
201
|
+
>
|
|
202
|
+
<div className="mb-3">
|
|
203
|
+
<ToggleGroup
|
|
204
|
+
size="sm"
|
|
205
|
+
aria-label="Orientation"
|
|
206
|
+
value={orientation}
|
|
207
|
+
onChange={setOrientation}
|
|
208
|
+
items={[
|
|
209
|
+
{ value: "vertical", label: "Columns" },
|
|
210
|
+
{ value: "horizontal", label: "Bars" },
|
|
211
|
+
]}
|
|
212
|
+
/>
|
|
213
|
+
</div>
|
|
214
|
+
<BarChart
|
|
215
|
+
data={pick(STAGES)}
|
|
216
|
+
x="stage"
|
|
217
|
+
series={[
|
|
218
|
+
{ key: "thisQ", label: "This quarter" },
|
|
219
|
+
{ key: "lastQ", label: "Last quarter", tone: "chart-5" },
|
|
220
|
+
]}
|
|
221
|
+
orientation={orientation}
|
|
222
|
+
stacked={barsStacked}
|
|
223
|
+
label="Deals by stage"
|
|
224
|
+
height={orientation === "horizontal" ? 280 : 240}
|
|
225
|
+
onSelect={(row) => setPicked(row)}
|
|
226
|
+
emptyLabel="No deals yet"
|
|
227
|
+
emptyBody="Deals show here by the stage they are in."
|
|
228
|
+
/>
|
|
229
|
+
</Card>
|
|
230
|
+
|
|
231
|
+
<Card title="Pipeline by source" description="Open pipeline value, by where the deal came from">
|
|
232
|
+
<PieChart
|
|
233
|
+
data={pick(SOURCES)}
|
|
234
|
+
name="source"
|
|
235
|
+
value="amount"
|
|
236
|
+
donut
|
|
237
|
+
format={(v) => usdShort.format(v)}
|
|
238
|
+
totalLabel="Open pipeline"
|
|
239
|
+
label="Pipeline by source"
|
|
240
|
+
height={240}
|
|
241
|
+
emptyLabel="No open pipeline"
|
|
242
|
+
/>
|
|
243
|
+
</Card>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<Card title="Tickets by status" description="Share of open tickets · value labels, a track, no grid or value axis">
|
|
247
|
+
<BarChart
|
|
248
|
+
data={pick(STATUS_SHARE)}
|
|
249
|
+
x="status"
|
|
250
|
+
series={[{ key: "share", label: "Share", tone: "muted" }]}
|
|
251
|
+
orientation="horizontal"
|
|
252
|
+
valueLabels
|
|
253
|
+
track
|
|
254
|
+
grid={false}
|
|
255
|
+
xAxis={false}
|
|
256
|
+
format={(v) => `${v}%`}
|
|
257
|
+
label="Tickets by status"
|
|
258
|
+
height={180}
|
|
259
|
+
emptyLabel="No tickets yet"
|
|
260
|
+
/>
|
|
261
|
+
</Card>
|
|
262
|
+
|
|
263
|
+
<div className="grid gap-4 lg:grid-cols-[2fr_1fr]">
|
|
264
|
+
<Card
|
|
265
|
+
title="Weekly traffic"
|
|
266
|
+
description="Visits by time slot and weekday · hover or arrow through a cell"
|
|
267
|
+
actions={empty ? null : <ScaleLegend min={0} max={65} steps={5} tone="chart-2" />}
|
|
268
|
+
>
|
|
269
|
+
<HeatmapChart
|
|
270
|
+
data={pick(TRAFFIC)}
|
|
271
|
+
y="slot"
|
|
272
|
+
columns={DAYS}
|
|
273
|
+
tone="chart-2"
|
|
274
|
+
showValues
|
|
275
|
+
rowTotals
|
|
276
|
+
colTotals
|
|
277
|
+
legend={false}
|
|
278
|
+
formatTooltip={(v, row, col) => `${col.label} ${row.slot}: ${v ?? 0} visits`}
|
|
279
|
+
label="Visits by time slot and weekday"
|
|
280
|
+
yLabel="Time slot"
|
|
281
|
+
emptyLabel="No visits yet"
|
|
282
|
+
/>
|
|
283
|
+
</Card>
|
|
284
|
+
|
|
285
|
+
<Card title="Contribution activity" description="Commits per day, last 4 weeks">
|
|
286
|
+
<HeatmapChart
|
|
287
|
+
data={pick(COMMITS)}
|
|
288
|
+
y="day"
|
|
289
|
+
columns={WEEKS}
|
|
290
|
+
cellShape="pill"
|
|
291
|
+
legendLabels={["Less", "More"]}
|
|
292
|
+
formatTooltip={(v, row, col) => (v == null ? `${row.day}, ${col.label}: no data` : `${row.day}, ${col.label}: ${v} commits`)}
|
|
293
|
+
label="Commits per weekday, last four weeks"
|
|
294
|
+
yLabel="Weekday"
|
|
295
|
+
emptyLabel="No commits yet"
|
|
296
|
+
/>
|
|
297
|
+
</Card>
|
|
298
|
+
</div>
|
|
299
|
+
|
|
300
|
+
<div className="grid gap-4 lg:grid-cols-2">
|
|
301
|
+
<Card title="Signups" description="This week against last · a muted, dashed comparison">
|
|
302
|
+
<LineChart
|
|
303
|
+
data={pick(SIGNUPS)}
|
|
304
|
+
x="day"
|
|
305
|
+
series={[
|
|
306
|
+
{ key: "thisWeek", label: "This week" },
|
|
307
|
+
{ key: "lastWeek", label: "Last week", muted: true, dashed: true },
|
|
308
|
+
]}
|
|
309
|
+
label="Signups per day, this week against last"
|
|
310
|
+
height={220}
|
|
311
|
+
/>
|
|
312
|
+
</Card>
|
|
313
|
+
<Card title="Paid invoices" description="This year against last · the comparison dashed, no fill">
|
|
314
|
+
<AreaChart
|
|
315
|
+
data={pick(PAID)}
|
|
316
|
+
x="month"
|
|
317
|
+
series={[
|
|
318
|
+
{ key: "thisYear", label: "2026" },
|
|
319
|
+
{ key: "lastYear", label: "2025", tone: "chart-3", dashed: true },
|
|
320
|
+
]}
|
|
321
|
+
format={(v) => usd.format(v)}
|
|
322
|
+
formatAxis={(v) => usdShort.format(v)}
|
|
323
|
+
label="Paid invoices by month, this year against last"
|
|
324
|
+
height={220}
|
|
325
|
+
/>
|
|
326
|
+
</Card>
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<Card title="Sparklines in stat tiles" description="Kit Stat with a Sparkline under it, height 28">
|
|
330
|
+
<StatGroup variant="divided" label="Weekly numbers">
|
|
331
|
+
{KPIS.slice(0, 3).map((k) => (
|
|
332
|
+
<div key={k.label} className="grid gap-2">
|
|
333
|
+
<Stat size="sm" label={k.label} value={empty ? "—" : k.value} />
|
|
334
|
+
<Sparkline data={pick(k.trend)} tone={k.line} height={28} area={false} label={`${k.label}, last 12 months`} format={k.unit} />
|
|
335
|
+
</div>
|
|
336
|
+
))}
|
|
337
|
+
</StatGroup>
|
|
338
|
+
</Card>
|
|
339
|
+
|
|
340
|
+
<Card title="Reply rate by channel" description="Share of first touches that got a reply, per week">
|
|
341
|
+
<LineChart
|
|
342
|
+
data={pick(REPLY)}
|
|
343
|
+
x="week"
|
|
344
|
+
series={[
|
|
345
|
+
{ key: "email", label: "Email" },
|
|
346
|
+
{ key: "linkedin", label: "LinkedIn" },
|
|
347
|
+
]}
|
|
348
|
+
format={(v) => `${v.toFixed(1)}%`}
|
|
349
|
+
formatAxis={(v) => `${v}%`}
|
|
350
|
+
dots
|
|
351
|
+
label="Reply rate by channel"
|
|
352
|
+
height={220}
|
|
353
|
+
/>
|
|
354
|
+
</Card>
|
|
355
|
+
</div>
|
|
356
|
+
);
|
|
357
|
+
}
|