makersclaw 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +3 -2
- package/r/annotate.json +62 -0
- package/r/approval-request.json +52 -0
- package/r/audio-player.json +74 -0
- package/r/auth-form.json +55 -0
- package/r/board.json +10 -6
- package/r/calendar-view.json +105 -0
- package/r/cart.json +62 -0
- package/r/chart.json +83 -0
- package/r/chat.json +95 -0
- package/r/code-editor.json +94 -0
- package/r/comment-box.json +64 -0
- package/r/contact-section.json +53 -0
- package/r/core.json +205 -8
- package/r/csv-import.json +63 -0
- package/r/data-table.json +69 -0
- package/r/diagram.json +74 -0
- package/r/doc-editor.json +82 -0
- package/r/doc-page.json +61 -0
- package/r/email-render.json +73 -0
- package/r/faq.json +50 -0
- package/r/file-upload.json +54 -0
- package/r/flow-canvas.json +93 -0
- package/r/footer.json +52 -0
- package/r/gantt.json +70 -0
- package/r/job-panel.json +12 -7
- package/r/json-editor.json +66 -0
- package/r/map.json +89 -0
- package/r/menubar.json +52 -0
- package/r/mind-map.json +67 -0
- package/r/navigation-menu.json +52 -0
- package/r/order-detail.json +54 -0
- package/r/org-chart.json +66 -0
- package/r/page-builder.json +105 -0
- package/r/payment-methods.json +51 -0
- package/r/pdf-document.json +79 -0
- package/r/pdf-viewer.json +88 -0
- package/r/product-detail.json +76 -0
- package/r/product-grid.json +65 -0
- package/r/record-form.json +67 -0
- package/r/record-notes.json +55 -0
- package/r/registry.json +3411 -29
- package/r/search-dialog.json +51 -0
- package/r/settings-list.json +66 -0
- package/r/setup-checklist.json +51 -0
- package/r/share-dialog.json +52 -0
- package/r/sidebar.json +69 -0
- package/r/signature-pad.json +72 -0
- package/r/sketch-canvas.json +99 -0
- package/r/spreadsheet.json +90 -0
- package/r/stat-cards.json +66 -0
- package/r/task-list.json +63 -0
- package/r/task-model.json +98 -0
- package/r/testimonials.json +52 -0
- package/r/transaction-list.json +53 -0
- package/r/whiteboard.json +66 -0
- package/registry/blocks/annotate/README.md +179 -0
- package/registry/blocks/annotate/annotate-data.js +250 -0
- package/registry/blocks/annotate/annotate.jsx +646 -0
- package/registry/blocks/annotate/block.json +10 -0
- package/registry/blocks/annotate/demo.jsx +135 -0
- package/registry/blocks/annotate/index.js +15 -0
- package/registry/blocks/approval-request/README.md +116 -0
- package/registry/blocks/approval-request/approval-request.jsx +386 -0
- package/registry/blocks/approval-request/block.json +10 -0
- package/registry/blocks/approval-request/demo.jsx +127 -0
- package/registry/blocks/approval-request/index.js +4 -0
- package/registry/blocks/audio-player/README.md +167 -0
- package/registry/blocks/audio-player/audio-player.jsx +623 -0
- package/registry/blocks/audio-player/block.json +14 -0
- package/registry/blocks/audio-player/colors.js +109 -0
- package/registry/blocks/audio-player/demo.jsx +209 -0
- package/registry/blocks/audio-player/index.js +6 -0
- package/registry/blocks/audio-player/time.js +67 -0
- package/registry/blocks/audio-player/wavesurfer.js +9 -0
- package/registry/blocks/auth-form/README.md +126 -0
- package/registry/blocks/auth-form/auth-form.jsx +568 -0
- package/registry/blocks/auth-form/block.json +10 -0
- package/registry/blocks/auth-form/demo.jsx +131 -0
- package/registry/blocks/auth-form/index.js +3 -0
- package/registry/blocks/board/README.md +55 -5
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +230 -86
- package/registry/blocks/board/demo.jsx +103 -24
- package/registry/blocks/calendar-view/README.md +180 -0
- package/registry/blocks/calendar-view/agenda.jsx +147 -0
- package/registry/blocks/calendar-view/block.json +76 -0
- package/registry/blocks/calendar-view/calendar-model.js +442 -0
- package/registry/blocks/calendar-view/calendar.jsx +627 -0
- package/registry/blocks/calendar-view/demo.jsx +195 -0
- package/registry/blocks/calendar-view/draft.jsx +49 -0
- package/registry/blocks/calendar-view/index.js +39 -0
- package/registry/blocks/calendar-view/month.jsx +346 -0
- package/registry/blocks/calendar-view/paint.js +69 -0
- package/registry/blocks/calendar-view/time-grid.jsx +527 -0
- package/registry/blocks/calendar-view/tray.jsx +87 -0
- package/registry/blocks/cart/README.md +146 -0
- package/registry/blocks/cart/block.json +10 -0
- package/registry/blocks/cart/cart.jsx +597 -0
- package/registry/blocks/cart/demo.jsx +98 -0
- package/registry/blocks/cart/index.js +4 -0
- package/registry/blocks/cart/money.js +28 -0
- package/registry/blocks/chart/README.md +316 -0
- package/registry/blocks/chart/block.json +10 -0
- package/registry/blocks/chart/cartesian.jsx +642 -0
- package/registry/blocks/chart/core.jsx +262 -0
- package/registry/blocks/chart/demo.jsx +357 -0
- package/registry/blocks/chart/heatmap.jsx +336 -0
- package/registry/blocks/chart/index.js +8 -0
- package/registry/blocks/chart/pie.jsx +245 -0
- package/registry/blocks/chart/sparkline.jsx +88 -0
- package/registry/blocks/chat/README.md +273 -0
- package/registry/blocks/chat/attachment.jsx +95 -0
- package/registry/blocks/chat/block.json +10 -0
- package/registry/blocks/chat/chat.jsx +132 -0
- package/registry/blocks/chat/composer.jsx +364 -0
- package/registry/blocks/chat/demo.jsx +578 -0
- package/registry/blocks/chat/header.jsx +34 -0
- package/registry/blocks/chat/index.js +9 -0
- package/registry/blocks/chat/message.jsx +450 -0
- package/registry/blocks/chat/scroller.jsx +247 -0
- package/registry/blocks/chat/text.jsx +104 -0
- package/registry/blocks/code-editor/README.md +210 -0
- package/registry/blocks/code-editor/block.json +22 -0
- package/registry/blocks/code-editor/code-editor.jsx +534 -0
- package/registry/blocks/code-editor/codemirror.js +38 -0
- package/registry/blocks/code-editor/demo.jsx +205 -0
- package/registry/blocks/code-editor/index.js +8 -0
- package/registry/blocks/code-editor/json.js +317 -0
- package/registry/blocks/code-editor/sql.js +136 -0
- package/registry/blocks/code-editor/text.js +101 -0
- package/registry/blocks/code-editor/theme.js +186 -0
- package/registry/blocks/comment-box/README.md +123 -0
- package/registry/blocks/comment-box/block.json +10 -0
- package/registry/blocks/comment-box/comment-body.jsx +217 -0
- package/registry/blocks/comment-box/comment-box.jsx +198 -0
- package/registry/blocks/comment-box/comment-time.jsx +77 -0
- package/registry/blocks/comment-box/demo.jsx +141 -0
- package/registry/blocks/comment-box/index.js +8 -0
- package/registry/blocks/contact-section/README.md +152 -0
- package/registry/blocks/contact-section/block.json +11 -0
- package/registry/blocks/contact-section/contact-section.jsx +509 -0
- package/registry/blocks/contact-section/demo.jsx +93 -0
- package/registry/blocks/contact-section/index.js +4 -0
- package/registry/blocks/csv-import/README.md +133 -0
- package/registry/blocks/csv-import/block.json +13 -0
- package/registry/blocks/csv-import/csv-import.jsx +479 -0
- package/registry/blocks/csv-import/demo.jsx +106 -0
- package/registry/blocks/csv-import/import.js +200 -0
- package/registry/blocks/csv-import/index.js +7 -0
- package/registry/blocks/data-table/README.md +386 -0
- package/registry/blocks/data-table/block.json +10 -0
- package/registry/blocks/data-table/data-table.jsx +1164 -0
- package/registry/blocks/data-table/demo.jsx +588 -0
- package/registry/blocks/data-table/index.js +5 -0
- package/registry/blocks/data-table/model.js +169 -0
- package/registry/blocks/diagram/README.md +108 -0
- package/registry/blocks/diagram/block.json +13 -0
- package/registry/blocks/diagram/demo.jsx +113 -0
- package/registry/blocks/diagram/diagram.jsx +481 -0
- package/registry/blocks/diagram/index.js +7 -0
- package/registry/blocks/diagram/mermaid.js +52 -0
- package/registry/blocks/diagram/palette.js +313 -0
- package/registry/blocks/diagram/source.js +98 -0
- package/registry/blocks/doc-editor/README.md +215 -0
- package/registry/blocks/doc-editor/block.json +15 -0
- package/registry/blocks/doc-editor/demo.jsx +225 -0
- package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
- package/registry/blocks/doc-editor/doc.js +309 -0
- package/registry/blocks/doc-editor/index.js +7 -0
- package/registry/blocks/doc-editor/schema.jsx +56 -0
- package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
- package/registry/blocks/doc-editor/theme.js +82 -0
- package/registry/blocks/doc-page/README.md +119 -0
- package/registry/blocks/doc-page/autosave.js +104 -0
- package/registry/blocks/doc-page/block.json +10 -0
- package/registry/blocks/doc-page/demo.jsx +137 -0
- package/registry/blocks/doc-page/doc-page.jsx +276 -0
- package/registry/blocks/doc-page/index.js +4 -0
- package/registry/blocks/email-render/README.md +151 -0
- package/registry/blocks/email-render/block.json +14 -0
- package/registry/blocks/email-render/demo.jsx +153 -0
- package/registry/blocks/email-render/doc-email.jsx +210 -0
- package/registry/blocks/email-render/email.jsx +221 -0
- package/registry/blocks/email-render/index.js +10 -0
- package/registry/blocks/email-render/render.js +50 -0
- package/registry/blocks/email-render/theme.js +215 -0
- package/registry/blocks/faq/README.md +101 -0
- package/registry/blocks/faq/block.json +11 -0
- package/registry/blocks/faq/demo.jsx +89 -0
- package/registry/blocks/faq/faq.jsx +220 -0
- package/registry/blocks/faq/index.js +4 -0
- package/registry/blocks/file-upload/README.md +138 -0
- package/registry/blocks/file-upload/block.json +10 -0
- package/registry/blocks/file-upload/demo.jsx +204 -0
- package/registry/blocks/file-upload/file-upload.jsx +635 -0
- package/registry/blocks/file-upload/index.js +4 -0
- package/registry/blocks/flow-canvas/README.md +420 -0
- package/registry/blocks/flow-canvas/block.json +13 -0
- package/registry/blocks/flow-canvas/board.js +819 -0
- package/registry/blocks/flow-canvas/chrome.jsx +649 -0
- package/registry/blocks/flow-canvas/context.jsx +35 -0
- package/registry/blocks/flow-canvas/demo.jsx +249 -0
- package/registry/blocks/flow-canvas/edges.jsx +107 -0
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
- package/registry/blocks/flow-canvas/index.js +41 -0
- package/registry/blocks/flow-canvas/nodes.jsx +392 -0
- package/registry/blocks/flow-canvas/theme.js +174 -0
- package/registry/blocks/footer/README.md +133 -0
- package/registry/blocks/footer/block.json +11 -0
- package/registry/blocks/footer/demo.jsx +119 -0
- package/registry/blocks/footer/footer.jsx +406 -0
- package/registry/blocks/footer/index.js +4 -0
- package/registry/blocks/gantt/README.md +220 -0
- package/registry/blocks/gantt/block.json +10 -0
- package/registry/blocks/gantt/demo.jsx +148 -0
- package/registry/blocks/gantt/gantt.jsx +923 -0
- package/registry/blocks/gantt/index.js +7 -0
- package/registry/blocks/gantt/rows.jsx +468 -0
- package/registry/blocks/gantt/schedule.js +278 -0
- package/registry/blocks/job-panel/README.md +80 -0
- package/registry/blocks/job-panel/block.json +3 -3
- package/registry/blocks/job-panel/demo.jsx +230 -3
- package/registry/blocks/job-panel/job-panel.jsx +169 -3
- package/registry/blocks/json-editor/README.md +133 -0
- package/registry/blocks/json-editor/block.json +10 -0
- package/registry/blocks/json-editor/demo.jsx +92 -0
- package/registry/blocks/json-editor/index.js +7 -0
- package/registry/blocks/json-editor/json-editor.jsx +305 -0
- package/registry/blocks/json-editor/json-tree.jsx +393 -0
- package/registry/blocks/json-editor/tree.js +225 -0
- package/registry/blocks/map/README.md +221 -0
- package/registry/blocks/map/block.json +14 -0
- package/registry/blocks/map/demo.jsx +201 -0
- package/registry/blocks/map/geo.js +198 -0
- package/registry/blocks/map/index.js +8 -0
- package/registry/blocks/map/list.jsx +128 -0
- package/registry/blocks/map/map-view.jsx +715 -0
- package/registry/blocks/map/maplibre.js +30 -0
- package/registry/blocks/map/marks.jsx +146 -0
- package/registry/blocks/map/theme.js +142 -0
- package/registry/blocks/menubar/README.md +109 -0
- package/registry/blocks/menubar/block.json +10 -0
- package/registry/blocks/menubar/demo.jsx +128 -0
- package/registry/blocks/menubar/index.js +4 -0
- package/registry/blocks/menubar/menubar.jsx +199 -0
- package/registry/blocks/mind-map/README.md +206 -0
- package/registry/blocks/mind-map/block.json +10 -0
- package/registry/blocks/mind-map/demo.jsx +103 -0
- package/registry/blocks/mind-map/index.js +31 -0
- package/registry/blocks/mind-map/mind-map.jsx +1125 -0
- package/registry/blocks/mind-map/topic.jsx +143 -0
- package/registry/blocks/mind-map/tree.js +645 -0
- package/registry/blocks/navigation-menu/README.md +124 -0
- package/registry/blocks/navigation-menu/block.json +10 -0
- package/registry/blocks/navigation-menu/demo.jsx +84 -0
- package/registry/blocks/navigation-menu/index.js +4 -0
- package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
- package/registry/blocks/order-detail/README.md +109 -0
- package/registry/blocks/order-detail/block.json +10 -0
- package/registry/blocks/order-detail/demo.jsx +88 -0
- package/registry/blocks/order-detail/index.js +4 -0
- package/registry/blocks/order-detail/order-detail.jsx +354 -0
- package/registry/blocks/org-chart/README.md +145 -0
- package/registry/blocks/org-chart/block.json +10 -0
- package/registry/blocks/org-chart/demo.jsx +94 -0
- package/registry/blocks/org-chart/index.js +7 -0
- package/registry/blocks/org-chart/org-chart.jsx +631 -0
- package/registry/blocks/org-chart/org.js +245 -0
- package/registry/blocks/org-chart/person.jsx +96 -0
- package/registry/blocks/page-builder/README.md +257 -0
- package/registry/blocks/page-builder/block.json +14 -0
- package/registry/blocks/page-builder/demo.jsx +145 -0
- package/registry/blocks/page-builder/grapes.js +18 -0
- package/registry/blocks/page-builder/index.js +11 -0
- package/registry/blocks/page-builder/page-builder.jsx +704 -0
- package/registry/blocks/page-builder/page-view.jsx +33 -0
- package/registry/blocks/page-builder/page.js +118 -0
- package/registry/blocks/page-builder/panels.jsx +588 -0
- package/registry/blocks/page-builder/sections.js +209 -0
- package/registry/blocks/page-builder/theme.js +87 -0
- package/registry/blocks/page-builder/thumbs.jsx +189 -0
- package/registry/blocks/page-builder/tokens.js +329 -0
- package/registry/blocks/payment-methods/README.md +104 -0
- package/registry/blocks/payment-methods/block.json +10 -0
- package/registry/blocks/payment-methods/demo.jsx +71 -0
- package/registry/blocks/payment-methods/index.js +4 -0
- package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
- package/registry/blocks/pdf-document/README.md +213 -0
- package/registry/blocks/pdf-document/block.json +13 -0
- package/registry/blocks/pdf-document/demo.jsx +136 -0
- package/registry/blocks/pdf-document/index.js +33 -0
- package/registry/blocks/pdf-document/money.js +83 -0
- package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
- package/registry/blocks/pdf-document/primitives.jsx +271 -0
- package/registry/blocks/pdf-document/quote.jsx +179 -0
- package/registry/blocks/pdf-document/theme.js +193 -0
- package/registry/blocks/pdf-viewer/README.md +191 -0
- package/registry/blocks/pdf-viewer/block.json +14 -0
- package/registry/blocks/pdf-viewer/demo.jsx +252 -0
- package/registry/blocks/pdf-viewer/helpers.js +270 -0
- package/registry/blocks/pdf-viewer/index.js +8 -0
- package/registry/blocks/pdf-viewer/notes.jsx +195 -0
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
- package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
- package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
- package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
- package/registry/blocks/product-detail/README.md +217 -0
- package/registry/blocks/product-detail/block.json +10 -0
- package/registry/blocks/product-detail/demo.jsx +233 -0
- package/registry/blocks/product-detail/index.js +7 -0
- package/registry/blocks/product-detail/price.jsx +115 -0
- package/registry/blocks/product-detail/product-detail.jsx +348 -0
- package/registry/blocks/product-detail/product-media.jsx +102 -0
- package/registry/blocks/product-detail/product-options.jsx +144 -0
- package/registry/blocks/product-grid/README.md +162 -0
- package/registry/blocks/product-grid/block.json +10 -0
- package/registry/blocks/product-grid/demo.jsx +255 -0
- package/registry/blocks/product-grid/index.js +5 -0
- package/registry/blocks/product-grid/product-card.jsx +232 -0
- package/registry/blocks/product-grid/product-grid.jsx +235 -0
- package/registry/blocks/record-form/README.md +196 -0
- package/registry/blocks/record-form/block.json +10 -0
- package/registry/blocks/record-form/demo.jsx +525 -0
- package/registry/blocks/record-form/index.js +4 -0
- package/registry/blocks/record-form/record-fields.jsx +457 -0
- package/registry/blocks/record-form/record-form.jsx +415 -0
- package/registry/blocks/record-form/rules.js +81 -0
- package/registry/blocks/record-notes/README.md +139 -0
- package/registry/blocks/record-notes/block.json +10 -0
- package/registry/blocks/record-notes/demo.jsx +179 -0
- package/registry/blocks/record-notes/index.js +4 -0
- package/registry/blocks/record-notes/record-notes.jsx +266 -0
- package/registry/blocks/search-dialog/README.md +108 -0
- package/registry/blocks/search-dialog/block.json +10 -0
- package/registry/blocks/search-dialog/demo.jsx +116 -0
- package/registry/blocks/search-dialog/index.js +3 -0
- package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
- package/registry/blocks/settings-list/README.md +171 -0
- package/registry/blocks/settings-list/block.json +10 -0
- package/registry/blocks/settings-list/demo.jsx +333 -0
- package/registry/blocks/settings-list/index.js +4 -0
- package/registry/blocks/settings-list/row-state.jsx +93 -0
- package/registry/blocks/settings-list/settings-list.jsx +349 -0
- package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
- package/registry/blocks/setup-checklist/README.md +142 -0
- package/registry/blocks/setup-checklist/block.json +10 -0
- package/registry/blocks/setup-checklist/demo.jsx +159 -0
- package/registry/blocks/setup-checklist/index.js +4 -0
- package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
- package/registry/blocks/share-dialog/README.md +113 -0
- package/registry/blocks/share-dialog/block.json +10 -0
- package/registry/blocks/share-dialog/demo.jsx +140 -0
- package/registry/blocks/share-dialog/index.js +3 -0
- package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
- package/registry/blocks/sidebar/README.md +190 -0
- package/registry/blocks/sidebar/block.json +43 -0
- package/registry/blocks/sidebar/demo.jsx +577 -0
- package/registry/blocks/sidebar/index.js +4 -0
- package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
- package/registry/blocks/sidebar/sidebar.jsx +864 -0
- package/registry/blocks/signature-pad/README.md +137 -0
- package/registry/blocks/signature-pad/block.json +13 -0
- package/registry/blocks/signature-pad/colors.js +115 -0
- package/registry/blocks/signature-pad/demo.jsx +94 -0
- package/registry/blocks/signature-pad/index.js +6 -0
- package/registry/blocks/signature-pad/pad.js +7 -0
- package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
- package/registry/blocks/signature-pad/signature.js +68 -0
- package/registry/blocks/sketch-canvas/README.md +280 -0
- package/registry/blocks/sketch-canvas/block.json +13 -0
- package/registry/blocks/sketch-canvas/demo.jsx +159 -0
- package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
- package/registry/blocks/sketch-canvas/index.js +9 -0
- package/registry/blocks/sketch-canvas/palette.js +226 -0
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
- package/registry/blocks/sketch-canvas/sketch.js +179 -0
- package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
- package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
- package/registry/blocks/sketch-canvas/stamps.js +104 -0
- package/registry/blocks/sketch-canvas/theme.js +131 -0
- package/registry/blocks/spreadsheet/README.md +307 -0
- package/registry/blocks/spreadsheet/block.json +13 -0
- package/registry/blocks/spreadsheet/cells.jsx +455 -0
- package/registry/blocks/spreadsheet/chrome.jsx +325 -0
- package/registry/blocks/spreadsheet/demo.jsx +177 -0
- package/registry/blocks/spreadsheet/grid.js +387 -0
- package/registry/blocks/spreadsheet/index.js +34 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
- package/registry/blocks/spreadsheet/types.js +473 -0
- package/registry/blocks/stat-cards/README.md +173 -0
- package/registry/blocks/stat-cards/block.json +10 -0
- package/registry/blocks/stat-cards/demo.jsx +257 -0
- package/registry/blocks/stat-cards/index.js +4 -0
- package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
- package/registry/blocks/stat-cards/usage.jsx +243 -0
- package/registry/blocks/task-list/README.md +176 -0
- package/registry/blocks/task-list/block.json +10 -0
- package/registry/blocks/task-list/demo.jsx +134 -0
- package/registry/blocks/task-list/index.js +5 -0
- package/registry/blocks/task-list/task-list.jsx +907 -0
- package/registry/blocks/task-model/README.md +455 -0
- package/registry/blocks/task-model/block.json +167 -0
- package/registry/blocks/task-model/changes.js +89 -0
- package/registry/blocks/task-model/dates.js +371 -0
- package/registry/blocks/task-model/demo.jsx +215 -0
- package/registry/blocks/task-model/dnd.jsx +240 -0
- package/registry/blocks/task-model/index.js +97 -0
- package/registry/blocks/task-model/model.js +919 -0
- package/registry/blocks/task-model/parts.jsx +449 -0
- package/registry/blocks/task-model/toolbar.jsx +271 -0
- package/registry/blocks/testimonials/README.md +139 -0
- package/registry/blocks/testimonials/block.json +11 -0
- package/registry/blocks/testimonials/demo.jsx +137 -0
- package/registry/blocks/testimonials/index.js +4 -0
- package/registry/blocks/testimonials/testimonials.jsx +430 -0
- package/registry/blocks/transaction-list/README.md +126 -0
- package/registry/blocks/transaction-list/block.json +10 -0
- package/registry/blocks/transaction-list/demo.jsx +79 -0
- package/registry/blocks/transaction-list/index.js +4 -0
- package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
- package/registry/blocks/whiteboard/README.md +179 -0
- package/registry/blocks/whiteboard/block.json +10 -0
- package/registry/blocks/whiteboard/demo.jsx +169 -0
- package/registry/blocks/whiteboard/index.js +6 -0
- package/registry/blocks/whiteboard/templates.js +150 -0
- package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
- package/src/install.mjs +18 -0
- package/src/shadcn.mjs +8 -0
- package/templates/next/files/README.md +145 -11
- package/templates/next/files/app/globals.css +55 -4
- package/templates/next/files/check/run.mjs +3 -3
- package/templates/next/files/components/ui/avatar.jsx +141 -0
- package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
- package/templates/next/files/components/ui/button-group.jsx +70 -0
- package/templates/next/files/components/ui/button.jsx +132 -12
- package/templates/next/files/components/ui/calendar.jsx +609 -0
- package/templates/next/files/components/ui/carousel.jsx +281 -0
- package/templates/next/files/components/ui/collapsible.jsx +208 -0
- package/templates/next/files/components/ui/combobox.jsx +608 -0
- package/templates/next/files/components/ui/command.jsx +577 -0
- package/templates/next/files/components/ui/context-menu.jsx +191 -0
- package/templates/next/files/components/ui/date-picker.jsx +360 -0
- package/templates/next/files/components/ui/distribution.jsx +117 -0
- package/templates/next/files/components/ui/feedback.jsx +143 -0
- package/templates/next/files/components/ui/field.jsx +115 -3
- package/templates/next/files/components/ui/file-input.jsx +234 -0
- package/templates/next/files/components/ui/icon.jsx +130 -8
- package/templates/next/files/components/ui/image.jsx +143 -0
- package/templates/next/files/components/ui/index.js +47 -2
- package/templates/next/files/components/ui/input-group.jsx +213 -0
- package/templates/next/files/components/ui/input-otp.jsx +170 -0
- package/templates/next/files/components/ui/item.jsx +206 -0
- package/templates/next/files/components/ui/menu.jsx +454 -82
- package/templates/next/files/components/ui/notice.jsx +126 -14
- package/templates/next/files/components/ui/pagination.jsx +156 -0
- package/templates/next/files/components/ui/popover.jsx +284 -0
- package/templates/next/files/components/ui/radio.jsx +193 -0
- package/templates/next/files/components/ui/rating.jsx +131 -0
- package/templates/next/files/components/ui/resizable.jsx +338 -0
- package/templates/next/files/components/ui/scroll-area.jsx +123 -0
- package/templates/next/files/components/ui/separator.jsx +119 -0
- package/templates/next/files/components/ui/sheet.jsx +96 -11
- package/templates/next/files/components/ui/slider.jsx +174 -0
- package/templates/next/files/components/ui/stat.jsx +574 -0
- package/templates/next/files/components/ui/steps.jsx +338 -0
- package/templates/next/files/components/ui/swatch.jsx +33 -0
- package/templates/next/files/components/ui/table.jsx +130 -0
- package/templates/next/files/components/ui/toast.jsx +440 -0
- package/templates/next/files/components/ui/toggle.jsx +195 -0
- package/templates/next/files/components/ui/tooltip.jsx +270 -0
- package/templates/next/template.json +264 -8
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// Annotate four ways — the gallery's and the smoke test's surface. Not
|
|
4
|
+
// installed into apps.
|
|
5
|
+
// Bug report a dashboard screenshot already marked up: a box, a
|
|
6
|
+
// highlight, two numbered notes with words; saves and
|
|
7
|
+
// sends through callbacks (a switch makes them fail),
|
|
8
|
+
// and beside it what an agent receives.
|
|
9
|
+
// Fresh screenshot the screenshot alone: the starter templates.
|
|
10
|
+
// No screenshot the drop zone (drop, browse or paste).
|
|
11
|
+
// Read-only the marked-up screenshot to look at.
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import { Card, Switch, TabPanel, Tabs } from "../components/ui";
|
|
14
|
+
import { Annotate, annotationToText } from "../components/blocks/annotate";
|
|
15
|
+
|
|
16
|
+
// A small made-up analytics dashboard (480 × 300), drawn as flat blocks and
|
|
17
|
+
// encoded as a PNG — a stand-in for a real screenshot.
|
|
18
|
+
const DASHBOARD_PNG = "data:image/png;base64,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";
|
|
19
|
+
const SHOT = { src: DASHBOARD_PNG, width: 480, height: 300 };
|
|
20
|
+
|
|
21
|
+
// Marks written by hand, colours as TOKENS only (customData.tokens). A pin
|
|
22
|
+
// is an ellipse carrying customData.note, with its number as a bound label.
|
|
23
|
+
const tok = (strokeColor, backgroundColor) => ({ tokens: { strokeColor, ...(backgroundColor ? { backgroundColor } : {}) } });
|
|
24
|
+
const pin = (n, x, y) => [
|
|
25
|
+
{
|
|
26
|
+
id: `pin-${n}`,
|
|
27
|
+
type: "ellipse",
|
|
28
|
+
x,
|
|
29
|
+
y,
|
|
30
|
+
width: 28,
|
|
31
|
+
height: 28,
|
|
32
|
+
fillStyle: "solid",
|
|
33
|
+
strokeWidth: 2,
|
|
34
|
+
roughness: 0,
|
|
35
|
+
boundElements: [{ type: "text", id: `pin-${n}-label` }],
|
|
36
|
+
customData: { note: n, ...tok("destructive", "destructive:soft") },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: `pin-${n}-label`,
|
|
40
|
+
type: "text",
|
|
41
|
+
x: x + 9,
|
|
42
|
+
y: y + 5,
|
|
43
|
+
width: 10,
|
|
44
|
+
height: 18,
|
|
45
|
+
text: String(n),
|
|
46
|
+
fontSize: 14,
|
|
47
|
+
containerId: `pin-${n}`,
|
|
48
|
+
textAlign: "center",
|
|
49
|
+
verticalAlign: "middle",
|
|
50
|
+
customData: { note: n, ...tok("destructive") },
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const MARKED = {
|
|
55
|
+
type: "annotation",
|
|
56
|
+
version: 1,
|
|
57
|
+
image: SHOT,
|
|
58
|
+
sketch: {
|
|
59
|
+
elements: [
|
|
60
|
+
{ id: "box", type: "rectangle", x: 276, y: 156, width: 36, height: 120, strokeWidth: 3, roughness: 0, roundness: { type: 3 }, customData: tok("destructive", "none") },
|
|
61
|
+
...pin(1, 300, 124),
|
|
62
|
+
{ id: "band", type: "rectangle", x: 356, y: 219, width: 108, height: 16, fillStyle: "solid", strokeWidth: 1, roughness: 0, opacity: 35, customData: tok("warning", "warning") },
|
|
63
|
+
...pin(2, 440, 186),
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
notes: [
|
|
67
|
+
{ n: 1, text: "September is amber and nothing says why. Label it, or keep it blue like the rest." },
|
|
68
|
+
{ n: 2, text: "This refund row shows red with no reason — add a status column so it reads without the colour." },
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function BugReport() {
|
|
73
|
+
const [value, setValue] = useState(MARKED);
|
|
74
|
+
const [fail, setFail] = useState(false);
|
|
75
|
+
const [sent, setSent] = useState(null);
|
|
76
|
+
const wait = () => new Promise((r) => setTimeout(r, 500));
|
|
77
|
+
const save = async () => {
|
|
78
|
+
await wait();
|
|
79
|
+
return fail ? { ok: false, error: "The network dropped" } : { ok: true };
|
|
80
|
+
};
|
|
81
|
+
const submit = async ({ image, notes, text }) => {
|
|
82
|
+
await wait();
|
|
83
|
+
if (fail) return { ok: false, error: "The ticket couldn't be filed" };
|
|
84
|
+
setSent({ size: Math.max(1, Math.round(image.size / 1024)), count: notes.length, text });
|
|
85
|
+
return { ok: true };
|
|
86
|
+
};
|
|
87
|
+
return (
|
|
88
|
+
<div className="grid gap-4 xl:grid-cols-[minmax(0,1fr)_18rem]">
|
|
89
|
+
<Annotate title="Revenue dashboard — feedback" value={value} onChange={setValue} onSave={save} onSubmit={submit} submitLabel="File the bug" />
|
|
90
|
+
<div className="grid content-start gap-4">
|
|
91
|
+
<Card title="Callbacks">
|
|
92
|
+
<Switch id="annotate-fail" label="Make saves and sends fail" checked={fail} onChange={(e) => setFail(e.target.checked)} />
|
|
93
|
+
</Card>
|
|
94
|
+
<Card title="What an agent reads">
|
|
95
|
+
<pre className="whitespace-pre-wrap break-words font-mono text-xs">{annotationToText(value) || "Nothing yet."}</pre>
|
|
96
|
+
{sent ? (
|
|
97
|
+
<p className="mt-2 text-xs text-muted-foreground">
|
|
98
|
+
Sent: a PNG of {sent.size} KB and {sent.count} notes.
|
|
99
|
+
</p>
|
|
100
|
+
) : null}
|
|
101
|
+
</Card>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export default function AnnotateDemo() {
|
|
108
|
+
const [tab, setTab] = useState("bug");
|
|
109
|
+
return (
|
|
110
|
+
<div className="grid gap-4">
|
|
111
|
+
<Tabs
|
|
112
|
+
aria-label="Annotate variants"
|
|
113
|
+
value={tab}
|
|
114
|
+
onChange={setTab}
|
|
115
|
+
tabs={[
|
|
116
|
+
{ key: "bug", label: "Bug report" },
|
|
117
|
+
{ key: "fresh", label: "Fresh screenshot" },
|
|
118
|
+
{ key: "none", label: "No screenshot" },
|
|
119
|
+
{ key: "read", label: "Read-only" },
|
|
120
|
+
]}
|
|
121
|
+
/>
|
|
122
|
+
<TabPanel tab={tab} value={tab}>
|
|
123
|
+
{tab === "bug" ? (
|
|
124
|
+
<BugReport />
|
|
125
|
+
) : tab === "fresh" ? (
|
|
126
|
+
<Annotate title="Onboarding screen" defaultValue={{ image: SHOT }} onSubmit={async () => ({ ok: true })} />
|
|
127
|
+
) : tab === "none" ? (
|
|
128
|
+
<Annotate title="Report a problem" onSubmit={async () => ({ ok: true })} submitLabel="Send to support" />
|
|
129
|
+
) : (
|
|
130
|
+
<Annotate title="Revenue dashboard — feedback" defaultValue={MARKED} readOnly />
|
|
131
|
+
)}
|
|
132
|
+
</TabPanel>
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// The Annotate block — `makersclaw add annotate`. Fixed: compose it
|
|
2
|
+
// through its props (README.md beside this file). Built on sketch-canvas
|
|
3
|
+
// (the canvas underneath); the helpers read an annotation anywhere, the
|
|
4
|
+
// server included.
|
|
5
|
+
export { Annotate, ANNOTATE_TOOLS } from "./annotate";
|
|
6
|
+
export {
|
|
7
|
+
ANNOTATE_TEMPLATES,
|
|
8
|
+
emptyAnnotation,
|
|
9
|
+
toAnnotation,
|
|
10
|
+
annotationNotes,
|
|
11
|
+
annotationToText,
|
|
12
|
+
noteMarkers,
|
|
13
|
+
nextNoteNumber,
|
|
14
|
+
markerSkeleton,
|
|
15
|
+
} from "./annotate-data";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# ApprovalRequest
|
|
2
|
+
|
|
3
|
+
One request waiting on a decision: what is asked for (label and value
|
|
4
|
+
facts, the amount in large type), who asked and when, why, and Approve /
|
|
5
|
+
Reject. Reject asks for a reason the requester will see. The decision
|
|
6
|
+
goes out through your callbacks; while one runs its button spins, when it
|
|
7
|
+
fails the card says why and the buttons stay, and once it lands the card
|
|
8
|
+
shows the outcome ("Approved by you · 23 September 2026") in their place.
|
|
9
|
+
|
|
10
|
+
```jsx
|
|
11
|
+
import { ApprovalRequest } from "../components/blocks/approval-request"; // a Makersclaw app ("./blocks/approval-request" from components/)
|
|
12
|
+
import { ApprovalRequest } from "@/components/makersclaw/blocks/approval-request"; // a shadcn project
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
A client component. Load the request in the server surface (README §4)
|
|
16
|
+
and pass its fields in.
|
|
17
|
+
|
|
18
|
+
## The data
|
|
19
|
+
|
|
20
|
+
- `details` — the card's facts, in order:
|
|
21
|
+
`[{ label, value, icon?, emphasis? }]`. `value` is a string or a node;
|
|
22
|
+
`icon` is a kit `Icon` name; `emphasis` sets the value large (the
|
|
23
|
+
amount).
|
|
24
|
+
- `sections` — `variant="page"` only, the detail beside the card:
|
|
25
|
+
`[{ title, fields: [{ label, value, emphasis? }] }]`.
|
|
26
|
+
- `requester` — `{ name, role?, src? }` (`src` a picture URL).
|
|
27
|
+
|
|
28
|
+
## Props
|
|
29
|
+
|
|
30
|
+
- `title` — what is asked for ("Linear Business", "Refund for order
|
|
31
|
+
20931"). Without it (and not `loading`) the block shows `emptyLabel`.
|
|
32
|
+
- `onApprove()` — save the yes. Return `{ ok: true }` or
|
|
33
|
+
`{ ok: false, error }`; a throw counts as failed and its message shows.
|
|
34
|
+
- `onReject(reason)` — save the no, with the reason typed (a trimmed
|
|
35
|
+
string, "" when `reasonRequired` is off). Same return as `onApprove`.
|
|
36
|
+
Leave either out and its button is not drawn.
|
|
37
|
+
- `variant` — `"card"` (default: the card alone, with the requester, the
|
|
38
|
+
date and the reason why) or `"page"`: a heading, the `sections` and "The
|
|
39
|
+
request" (requester, date, why) on the left, the card on the right
|
|
40
|
+
(under them on a phone), sticky from 1024px.
|
|
41
|
+
- `status` — `"pending"` (default) · `"approved"` · `"rejected"`. The
|
|
42
|
+
block shows its own outcome as soon as a decision saves; a new
|
|
43
|
+
`status` from you replaces it.
|
|
44
|
+
- `decidedBy` · `decidedAt` · `decisionNote` — for a request decided
|
|
45
|
+
before: who, when, and the reason, shown under the outcome.
|
|
46
|
+
- `kind` — a small badge beside the title ("Per seat", "Refund").
|
|
47
|
+
- `requestedAt` — an ISO date or a `Date`.
|
|
48
|
+
- `justification` — the requester's reason, as a paragraph.
|
|
49
|
+
- `reasonRequired` — default `true`: Reject opens a reason field and
|
|
50
|
+
sends only when it is filled. `false`: Reject sends at once.
|
|
51
|
+
- `approveLabel` · `rejectLabel` — default "Approve" / "Reject"
|
|
52
|
+
("Refund €149.00", "Decline").
|
|
53
|
+
- `heading` · `description` — `page`: the page's title (default `title`)
|
|
54
|
+
and the line under it.
|
|
55
|
+
- `formatDate(value)` — how a date reads; default the viewer's long date
|
|
56
|
+
("21 September 2026").
|
|
57
|
+
- `loading` — a skeleton card while the request loads.
|
|
58
|
+
- `emptyLabel` — default "Nothing is waiting for a decision.".
|
|
59
|
+
- `className` — layout around it (width, margin). Never colour.
|
|
60
|
+
|
|
61
|
+
## Example
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
// components/PurchaseApproval.jsx — client
|
|
65
|
+
"use client";
|
|
66
|
+
import { useRouter } from "next/navigation";
|
|
67
|
+
import { updateRow } from "../lib/actions";
|
|
68
|
+
import { ApprovalRequest } from "./blocks/approval-request";
|
|
69
|
+
|
|
70
|
+
const usd = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
|
|
71
|
+
|
|
72
|
+
export default function PurchaseApproval({ request }) {
|
|
73
|
+
const router = useRouter();
|
|
74
|
+
const decide = (status, reason) =>
|
|
75
|
+
updateRow({ source: "public.purchase_requests", id: request.id, patch: { status, reason: reason ?? null }, detail: request.product }).then(
|
|
76
|
+
(res) => (res.ok && router.refresh(), res),
|
|
77
|
+
);
|
|
78
|
+
return (
|
|
79
|
+
<ApprovalRequest
|
|
80
|
+
title={request.product}
|
|
81
|
+
kind={request.pricing}
|
|
82
|
+
details={[
|
|
83
|
+
{ label: "Starts", value: request.starts_on, icon: "calendar" },
|
|
84
|
+
{ label: "Seats", value: `${request.seats} people`, icon: "users" },
|
|
85
|
+
{ label: "Yearly cost", value: usd.format(request.amount), icon: "dollar", emphasis: true },
|
|
86
|
+
]}
|
|
87
|
+
requester={{ name: request.requested_by, role: request.team }}
|
|
88
|
+
requestedAt={request.created_at}
|
|
89
|
+
justification={request.why}
|
|
90
|
+
status={request.status}
|
|
91
|
+
decidedBy={request.decided_by}
|
|
92
|
+
decidedAt={request.decided_at}
|
|
93
|
+
decisionNote={request.reason}
|
|
94
|
+
onApprove={() => decide("approved")}
|
|
95
|
+
onReject={(reason) => decide("rejected", reason)}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## What it will not do
|
|
102
|
+
|
|
103
|
+
- List many requests: put them in a `data-table` and open one in this
|
|
104
|
+
block (a `Sheet`), or render one per row.
|
|
105
|
+
- Take a decision in several steps (two approvers, a delegate): `status`
|
|
106
|
+
is one of three.
|
|
107
|
+
- Edit the request: its facts are read-only here.
|
|
108
|
+
|
|
109
|
+
A request it cannot be is your own component in `components/`, built
|
|
110
|
+
from the kit — not an edit to this block. Its files are fixed: `npm run
|
|
111
|
+
check` refuses a change, and `makersclaw add approval-request` restores
|
|
112
|
+
them.
|
|
113
|
+
|
|
114
|
+
## Credits
|
|
115
|
+
|
|
116
|
+
Ported from Creative Tim UI (https://github.com/creativetimofficial/ui, software-purchase-01 and software-purchase-card, MIT), rewritten on the Makersclaw kit.
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useId, useState } from "react";
|
|
4
|
+
import { Avatar, Badge, Button, Empty, Field, Icon, Notice, Separator, Skeleton, Textarea, cx } from "../../ui";
|
|
5
|
+
|
|
6
|
+
// ApprovalRequest — one request waiting on a decision: what is asked for
|
|
7
|
+
// (label/value facts), who asked and when, why, and Approve / Reject. The
|
|
8
|
+
// decision goes out through `onApprove()` / `onReject(reason)`; the
|
|
9
|
+
// block shows it working, shows a failure, and once it lands shows the
|
|
10
|
+
// outcome in place of the buttons.
|
|
11
|
+
|
|
12
|
+
const STATUS = {
|
|
13
|
+
pending: { tone: "warning", label: "Pending approval" },
|
|
14
|
+
approved: { tone: "success", label: "Approved" },
|
|
15
|
+
rejected: { tone: "danger", label: "Rejected" },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function defaultFormat(value) {
|
|
19
|
+
if (!value) return "";
|
|
20
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
21
|
+
if (Number.isNaN(d.getTime())) return String(value);
|
|
22
|
+
return new Intl.DateTimeFormat(undefined, { dateStyle: "long" }).format(d);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function When({ value, format }) {
|
|
26
|
+
if (!value) return null;
|
|
27
|
+
const iso = value instanceof Date ? value.toISOString() : String(value);
|
|
28
|
+
return (
|
|
29
|
+
<time dateTime={iso} suppressHydrationWarning>
|
|
30
|
+
{format(value)}
|
|
31
|
+
</time>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function StatusBadge({ status }) {
|
|
36
|
+
const s = STATUS[status] ?? STATUS.pending;
|
|
37
|
+
return (
|
|
38
|
+
<Badge tone={s.tone} variant="soft">
|
|
39
|
+
{s.label}
|
|
40
|
+
</Badge>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function Requester({ requester, requestedAt, format }) {
|
|
45
|
+
if (!requester && !requestedAt) return null;
|
|
46
|
+
return (
|
|
47
|
+
<div className="flex min-w-0 items-center gap-2 text-sm text-muted-foreground">
|
|
48
|
+
{requester ? <Avatar name={requester.name} src={requester.src} size="xs" /> : null}
|
|
49
|
+
<p className="min-w-0">
|
|
50
|
+
{requester ? (
|
|
51
|
+
<>
|
|
52
|
+
<span className="font-medium text-foreground">{requester.name}</span>
|
|
53
|
+
{requester.role ? `, ${requester.role}` : ""}
|
|
54
|
+
</>
|
|
55
|
+
) : null}
|
|
56
|
+
{requester && requestedAt ? " · " : null}
|
|
57
|
+
<When value={requestedAt} format={format} />
|
|
58
|
+
</p>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ------------------------------------------------------------------------
|
|
64
|
+
The card: facts and the decision
|
|
65
|
+
------------------------------------------------------------------------ */
|
|
66
|
+
|
|
67
|
+
function DecisionCard({
|
|
68
|
+
title,
|
|
69
|
+
kind,
|
|
70
|
+
details,
|
|
71
|
+
requester,
|
|
72
|
+
requestedAt,
|
|
73
|
+
justification,
|
|
74
|
+
status,
|
|
75
|
+
decidedBy,
|
|
76
|
+
decidedAt,
|
|
77
|
+
decisionNote,
|
|
78
|
+
onApprove,
|
|
79
|
+
onReject,
|
|
80
|
+
reasonRequired,
|
|
81
|
+
approveLabel,
|
|
82
|
+
rejectLabel,
|
|
83
|
+
format,
|
|
84
|
+
showContext,
|
|
85
|
+
className,
|
|
86
|
+
}) {
|
|
87
|
+
const [local, setLocal] = useState(null);
|
|
88
|
+
const [mode, setMode] = useState("idle"); // idle · rejecting
|
|
89
|
+
const [busy, setBusy] = useState(null); // approve · reject
|
|
90
|
+
const [reason, setReason] = useState("");
|
|
91
|
+
const [error, setError] = useState(null);
|
|
92
|
+
const reasonId = useId();
|
|
93
|
+
|
|
94
|
+
// A new status from the app wins over what the block showed meanwhile.
|
|
95
|
+
useEffect(() => setLocal(null), [status]);
|
|
96
|
+
|
|
97
|
+
const shown = local?.status ?? status ?? "pending";
|
|
98
|
+
const pending = shown === "pending";
|
|
99
|
+
const facts = (details ?? []).filter(Boolean);
|
|
100
|
+
|
|
101
|
+
async function decide(kindOf) {
|
|
102
|
+
const fn = kindOf === "approve" ? onApprove : onReject;
|
|
103
|
+
if (!fn) return;
|
|
104
|
+
setBusy(kindOf);
|
|
105
|
+
setError(null);
|
|
106
|
+
let res;
|
|
107
|
+
try {
|
|
108
|
+
res = await fn(kindOf === "reject" ? reason.trim() : undefined);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
res = { ok: false, error: e?.message };
|
|
111
|
+
}
|
|
112
|
+
setBusy(null);
|
|
113
|
+
if (res?.ok) {
|
|
114
|
+
setLocal({ status: kindOf === "approve" ? "approved" : "rejected", note: kindOf === "reject" ? reason.trim() : undefined, at: new Date() });
|
|
115
|
+
setMode("idle");
|
|
116
|
+
} else {
|
|
117
|
+
setError(res?.error || (kindOf === "approve" ? "The approval was not saved. Try again." : "The rejection was not saved. Try again."));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const note = local?.note ?? decisionNote;
|
|
122
|
+
const at = local?.at ?? decidedAt;
|
|
123
|
+
const by = local ? "you" : decidedBy;
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<section aria-label={title} className={cx("grid gap-4 rounded-lg border border-border bg-card p-4 text-card-foreground sm:p-5", className)}>
|
|
127
|
+
<header className="grid gap-2">
|
|
128
|
+
<div className="flex flex-wrap items-start justify-between gap-2">
|
|
129
|
+
<h2 className="min-w-0 text-lg font-semibold leading-tight">{title}</h2>
|
|
130
|
+
<div className="flex flex-wrap gap-1.5">
|
|
131
|
+
{kind ? <Badge variant="soft">{kind}</Badge> : null}
|
|
132
|
+
<StatusBadge status={shown} />
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
{showContext ? <Requester requester={requester} requestedAt={requestedAt} format={format} /> : null}
|
|
136
|
+
</header>
|
|
137
|
+
|
|
138
|
+
{facts.length ? (
|
|
139
|
+
<dl className="grid gap-4">
|
|
140
|
+
{facts.map((f, i) => (
|
|
141
|
+
<div key={f.label ?? i} className="flex items-center gap-3">
|
|
142
|
+
{f.icon ? (
|
|
143
|
+
<span className="flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground">
|
|
144
|
+
<Icon name={f.icon} size={16} />
|
|
145
|
+
</span>
|
|
146
|
+
) : null}
|
|
147
|
+
<div className="grid min-w-0 gap-0.5">
|
|
148
|
+
<dt className="text-xs text-muted-foreground">{f.label}</dt>
|
|
149
|
+
<dd data-nums className={cx("min-w-0 break-words", f.emphasis ? "text-xl font-semibold" : "text-sm font-medium")}>
|
|
150
|
+
{f.value}
|
|
151
|
+
</dd>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
))}
|
|
155
|
+
</dl>
|
|
156
|
+
) : null}
|
|
157
|
+
|
|
158
|
+
{showContext && justification ? (
|
|
159
|
+
<div className="grid gap-1">
|
|
160
|
+
<p className="text-xs text-muted-foreground">Why</p>
|
|
161
|
+
<p className="text-sm leading-relaxed text-foreground">{justification}</p>
|
|
162
|
+
</div>
|
|
163
|
+
) : null}
|
|
164
|
+
|
|
165
|
+
<Separator />
|
|
166
|
+
|
|
167
|
+
{pending ? (
|
|
168
|
+
mode === "rejecting" ? (
|
|
169
|
+
<form
|
|
170
|
+
className="grid gap-3"
|
|
171
|
+
onSubmit={(e) => {
|
|
172
|
+
e.preventDefault();
|
|
173
|
+
if (reasonRequired && !reason.trim()) return;
|
|
174
|
+
decide("reject");
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
<Field id={reasonId} label="Why is it rejected?" hint="The requester sees this." required={reasonRequired}>
|
|
178
|
+
<Textarea
|
|
179
|
+
id={reasonId}
|
|
180
|
+
rows={3}
|
|
181
|
+
value={reason}
|
|
182
|
+
onChange={(e) => setReason(e.target.value)}
|
|
183
|
+
autoFocus
|
|
184
|
+
disabled={busy !== null}
|
|
185
|
+
placeholder="Over this quarter's budget; ask again in January."
|
|
186
|
+
/>
|
|
187
|
+
</Field>
|
|
188
|
+
<div className="flex flex-wrap justify-end gap-2">
|
|
189
|
+
<Button
|
|
190
|
+
variant="quiet"
|
|
191
|
+
onClick={() => {
|
|
192
|
+
setMode("idle");
|
|
193
|
+
setError(null);
|
|
194
|
+
}}
|
|
195
|
+
disabled={busy !== null}
|
|
196
|
+
>
|
|
197
|
+
Back
|
|
198
|
+
</Button>
|
|
199
|
+
<Button type="submit" variant="danger" loading={busy === "reject"} disabled={reasonRequired && !reason.trim()}>
|
|
200
|
+
{rejectLabel}
|
|
201
|
+
</Button>
|
|
202
|
+
</div>
|
|
203
|
+
</form>
|
|
204
|
+
) : (
|
|
205
|
+
<div className="flex gap-3">
|
|
206
|
+
{onReject ? (
|
|
207
|
+
<Button
|
|
208
|
+
className="flex-1"
|
|
209
|
+
onClick={() => {
|
|
210
|
+
setError(null);
|
|
211
|
+
if (reasonRequired) setMode("rejecting");
|
|
212
|
+
else decide("reject");
|
|
213
|
+
}}
|
|
214
|
+
loading={busy === "reject"}
|
|
215
|
+
disabled={busy !== null}
|
|
216
|
+
>
|
|
217
|
+
{rejectLabel}
|
|
218
|
+
</Button>
|
|
219
|
+
) : null}
|
|
220
|
+
{onApprove ? (
|
|
221
|
+
<Button className="flex-1" variant="primary" icon="check" onClick={() => decide("approve")} loading={busy === "approve"} disabled={busy !== null}>
|
|
222
|
+
{approveLabel}
|
|
223
|
+
</Button>
|
|
224
|
+
) : null}
|
|
225
|
+
</div>
|
|
226
|
+
)
|
|
227
|
+
) : (
|
|
228
|
+
<div role="status" className="flex items-start gap-3 text-sm">
|
|
229
|
+
<Icon name={shown === "approved" ? "circle-check" : "circle-x"} size={20} className={cx("mt-0.5 shrink-0", shown === "approved" ? "text-success" : "text-destructive")} />
|
|
230
|
+
<div className="min-w-0">
|
|
231
|
+
<p className="font-medium">
|
|
232
|
+
{shown === "approved" ? "Approved" : "Rejected"}
|
|
233
|
+
{by ? ` by ${by}` : ""}
|
|
234
|
+
{at ? (
|
|
235
|
+
<span className="font-normal text-muted-foreground">
|
|
236
|
+
{" · "}
|
|
237
|
+
<When value={at} format={format} />
|
|
238
|
+
</span>
|
|
239
|
+
) : null}
|
|
240
|
+
</p>
|
|
241
|
+
{note ? <p className="mt-0.5 text-muted-foreground">{note}</p> : null}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
)}
|
|
245
|
+
|
|
246
|
+
{error ? (
|
|
247
|
+
<Notice tone="danger" onDismiss={() => setError(null)}>
|
|
248
|
+
{error}
|
|
249
|
+
</Notice>
|
|
250
|
+
) : null}
|
|
251
|
+
</section>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* ------------------------------------------------------------------------
|
|
256
|
+
ApprovalRequest
|
|
257
|
+
------------------------------------------------------------------------ */
|
|
258
|
+
|
|
259
|
+
export function ApprovalRequest({
|
|
260
|
+
variant = "card",
|
|
261
|
+
title,
|
|
262
|
+
kind,
|
|
263
|
+
details,
|
|
264
|
+
sections,
|
|
265
|
+
requester,
|
|
266
|
+
requestedAt,
|
|
267
|
+
justification,
|
|
268
|
+
status = "pending",
|
|
269
|
+
decidedBy,
|
|
270
|
+
decidedAt,
|
|
271
|
+
decisionNote,
|
|
272
|
+
onApprove,
|
|
273
|
+
onReject,
|
|
274
|
+
reasonRequired = true,
|
|
275
|
+
approveLabel = "Approve",
|
|
276
|
+
rejectLabel = "Reject",
|
|
277
|
+
heading,
|
|
278
|
+
description,
|
|
279
|
+
formatDate = defaultFormat,
|
|
280
|
+
loading = false,
|
|
281
|
+
emptyLabel = "Nothing is waiting for a decision.",
|
|
282
|
+
className,
|
|
283
|
+
}) {
|
|
284
|
+
const card = {
|
|
285
|
+
title,
|
|
286
|
+
kind,
|
|
287
|
+
details,
|
|
288
|
+
requester,
|
|
289
|
+
requestedAt,
|
|
290
|
+
justification,
|
|
291
|
+
status,
|
|
292
|
+
decidedBy,
|
|
293
|
+
decidedAt,
|
|
294
|
+
decisionNote,
|
|
295
|
+
onApprove,
|
|
296
|
+
onReject,
|
|
297
|
+
reasonRequired,
|
|
298
|
+
approveLabel,
|
|
299
|
+
rejectLabel,
|
|
300
|
+
format: formatDate,
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
if (loading) {
|
|
304
|
+
return (
|
|
305
|
+
<div aria-busy="true" aria-label="Loading the request" className={cx("grid w-full max-w-md gap-4 rounded-lg border border-border bg-card p-5", className)}>
|
|
306
|
+
<Skeleton className="w-2/3" />
|
|
307
|
+
{[0, 1, 2].map((i) => (
|
|
308
|
+
<div key={i} className="flex items-center gap-3">
|
|
309
|
+
<Skeleton shape="rect" className="size-8" />
|
|
310
|
+
<Skeleton className="w-1/2" />
|
|
311
|
+
</div>
|
|
312
|
+
))}
|
|
313
|
+
<div className="flex gap-3">
|
|
314
|
+
<Skeleton shape="rect" className="h-11 flex-1" />
|
|
315
|
+
<Skeleton shape="rect" className="h-11 flex-1" />
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
if (!title) return <Empty icon="inbox" title="No request" body={emptyLabel} className={className} />;
|
|
321
|
+
|
|
322
|
+
if (variant !== "page") {
|
|
323
|
+
return <DecisionCard {...card} showContext className={cx("w-full max-w-md", className)} />;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const groups = (sections ?? []).filter(Boolean);
|
|
327
|
+
return (
|
|
328
|
+
<div className={cx("grid gap-8 lg:grid-cols-[minmax(0,1fr)_24rem] lg:items-start", className)}>
|
|
329
|
+
<div className="grid min-w-0 gap-6">
|
|
330
|
+
<div className="grid gap-1">
|
|
331
|
+
<h1 className="text-2xl font-semibold leading-tight">{heading ?? title}</h1>
|
|
332
|
+
{description ? <p className="text-muted-foreground">{description}</p> : null}
|
|
333
|
+
</div>
|
|
334
|
+
{groups.map((g, gi) => (
|
|
335
|
+
<section key={g.title ?? gi} className="grid gap-4 border-t border-border pt-6">
|
|
336
|
+
{g.title ? <h2 className="text-lg font-semibold">{g.title}</h2> : null}
|
|
337
|
+
<dl className="grid gap-4 sm:grid-cols-2">
|
|
338
|
+
{(g.fields ?? []).filter(Boolean).map((f, fi) => (
|
|
339
|
+
<div key={f.label ?? fi} className="grid min-w-0 gap-1">
|
|
340
|
+
<dt className="text-sm font-medium">{f.label}</dt>
|
|
341
|
+
<dd className={cx("min-w-0 break-words text-muted-foreground", f.emphasis && "font-semibold text-foreground")}>{f.value}</dd>
|
|
342
|
+
</div>
|
|
343
|
+
))}
|
|
344
|
+
</dl>
|
|
345
|
+
</section>
|
|
346
|
+
))}
|
|
347
|
+
{requester || requestedAt || justification ? (
|
|
348
|
+
<section className="grid gap-4 border-t border-border pt-6">
|
|
349
|
+
<h2 className="text-lg font-semibold">The request</h2>
|
|
350
|
+
<dl className="grid gap-4 sm:grid-cols-2">
|
|
351
|
+
{requester ? (
|
|
352
|
+
<div className="grid min-w-0 gap-1">
|
|
353
|
+
<dt className="text-sm font-medium">Requested by</dt>
|
|
354
|
+
<dd className="flex min-w-0 items-center gap-2 text-muted-foreground">
|
|
355
|
+
<Avatar name={requester.name} src={requester.src} size="xs" />
|
|
356
|
+
<span className="min-w-0">
|
|
357
|
+
{requester.name}
|
|
358
|
+
{requester.role ? ` (${requester.role})` : ""}
|
|
359
|
+
</span>
|
|
360
|
+
</dd>
|
|
361
|
+
</div>
|
|
362
|
+
) : null}
|
|
363
|
+
{requestedAt ? (
|
|
364
|
+
<div className="grid gap-1">
|
|
365
|
+
<dt className="text-sm font-medium">Requested on</dt>
|
|
366
|
+
<dd className="text-muted-foreground">
|
|
367
|
+
<When value={requestedAt} format={formatDate} />
|
|
368
|
+
</dd>
|
|
369
|
+
</div>
|
|
370
|
+
) : null}
|
|
371
|
+
{justification ? (
|
|
372
|
+
<div className="grid gap-1 sm:col-span-2">
|
|
373
|
+
<dt className="text-sm font-medium">Why</dt>
|
|
374
|
+
<dd className="text-sm leading-relaxed text-muted-foreground">{justification}</dd>
|
|
375
|
+
</div>
|
|
376
|
+
) : null}
|
|
377
|
+
</dl>
|
|
378
|
+
</section>
|
|
379
|
+
) : null}
|
|
380
|
+
</div>
|
|
381
|
+
<div className="lg:sticky lg:top-6">
|
|
382
|
+
<DecisionCard {...card} showContext={false} />
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
);
|
|
386
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "approval-request",
|
|
3
|
+
"title": "ApprovalRequest",
|
|
4
|
+
"description": "One request waiting on a decision: what is asked for as label/value facts (an amount in large type), who asked and when, why, a status badge, and Approve / Reject (reject asks for a reason). The decision goes out through async onApprove / onReject; the block shows it working, a failure, then the outcome in place of the buttons. A card alone, or a page of detail sections beside the card.",
|
|
5
|
+
"useWhen": "Someone must say yes or no to one thing another person asked for: a purchase, a refund, time off, a discount, an access request, a published post. Not for a queue of many requests (a data-table with row actions) or a yes/no about the founder's own action (kit Confirm).",
|
|
6
|
+
"tags": ["approval", "approve", "reject", "request", "review", "decision", "purchase", "expense", "refund", "time off", "sign off", "pending"],
|
|
7
|
+
"exports": ["ApprovalRequest"],
|
|
8
|
+
"files": ["index.js", "approval-request.jsx"],
|
|
9
|
+
"requires": []
|
|
10
|
+
}
|