makersclaw 0.1.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/LICENSE +21 -0
- package/README.md +41 -1
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +15 -8
- 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 +55 -0
- 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 +341 -0
- 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 +56 -0
- 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 +3612 -0
- 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 +64 -13
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +237 -94
- 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 +86 -2
- 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 +171 -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/parts/fixture.jsx +1 -1
- package/templates/next/files/components/parts/sample.js +15 -0
- 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/files/lib/sample.js +4 -12
- package/templates/next/template.json +264 -8
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// RecordNotes three ways — the gallery's and the smoke test's surface. Not
|
|
4
|
+
// installed into apps. Saves are pretend: a switch makes them fail.
|
|
5
|
+
// Deal beside a deal's details: newest first, your notes editable.
|
|
6
|
+
// Log a contact's history read top to bottom, no card of its own.
|
|
7
|
+
// Empty a new record with no notes yet.
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { Badge, Card, Switch, TabPanel, Tabs } from "../components/ui";
|
|
10
|
+
import { RecordNotes } from "../components/blocks/record-notes";
|
|
11
|
+
|
|
12
|
+
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
13
|
+
const ago = (hours) => new Date(Date.now() - hours * 3_600_000).toISOString();
|
|
14
|
+
|
|
15
|
+
const TEAM = [
|
|
16
|
+
{ id: "u-priya", label: "Priya Raman", description: "Account executive" },
|
|
17
|
+
{ id: "u-tomas", label: "Tomás Ortega", description: "Solutions engineer" },
|
|
18
|
+
{ id: "u-june", label: "June Okafor", description: "Sales lead" },
|
|
19
|
+
{ id: "u-lena", label: "Lena Fischer", description: "Customer success" },
|
|
20
|
+
];
|
|
21
|
+
const findPeople = async (query) => {
|
|
22
|
+
const q = query.toLowerCase();
|
|
23
|
+
return TEAM.filter((p) => p.label.toLowerCase().includes(q));
|
|
24
|
+
};
|
|
25
|
+
const person = (id) => ({ id, name: TEAM.find((p) => p.id === id).label });
|
|
26
|
+
const ME = person("u-june");
|
|
27
|
+
|
|
28
|
+
const t = (text, styles = {}) => ({ type: "text", text, styles });
|
|
29
|
+
const at = (id) => ({ type: "mention", props: { id, label: TEAM.find((p) => p.id === id).label } });
|
|
30
|
+
|
|
31
|
+
const DEAL_NOTES = [
|
|
32
|
+
{
|
|
33
|
+
id: "n1",
|
|
34
|
+
author: person("u-priya"),
|
|
35
|
+
createdAt: ago(2),
|
|
36
|
+
body: [
|
|
37
|
+
{ type: "paragraph", content: [t("Call with Dana (Head of Ops). They want "), t("40 seats", { bold: true }), t(" from January, SSO is a must.")] },
|
|
38
|
+
{ type: "bulletListItem", content: [t("Budget signed off for Q1")] },
|
|
39
|
+
{ type: "bulletListItem", content: [t("Security review needs our SOC 2 report")] },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "n2",
|
|
44
|
+
author: ME,
|
|
45
|
+
createdAt: ago(5),
|
|
46
|
+
updatedAt: ago(4),
|
|
47
|
+
body: [{ type: "paragraph", content: [at("u-tomas"), t(" can you run the SSO demo on Thursday? Dana's IT lead will join.")] }],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "n3",
|
|
51
|
+
author: person("u-tomas"),
|
|
52
|
+
createdAt: ago(28),
|
|
53
|
+
body: [
|
|
54
|
+
{ type: "paragraph", content: [t("Sandbox is set up for them. Checklist before the demo:")] },
|
|
55
|
+
{ type: "checkListItem", props: { checked: true }, content: [t("Okta test tenant")] },
|
|
56
|
+
{ type: "checkListItem", content: [t("SCIM provisioning with 5 test users")] },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "n4",
|
|
61
|
+
author: ME,
|
|
62
|
+
createdAt: ago(24 * 6),
|
|
63
|
+
body: [{ type: "paragraph", content: [t("Inbound from the pricing page. Came in through the "), t("Teams", { italic: true }), t(" plan calculator.")] }],
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
function usePretendNotes(initial, failing) {
|
|
68
|
+
const [notes, setNotes] = useState(initial);
|
|
69
|
+
const answer = async () => {
|
|
70
|
+
await wait(600);
|
|
71
|
+
return failing ? { ok: false, error: "The server is not answering. Nothing was saved; try again." } : null;
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
notes,
|
|
75
|
+
onAdd: async (doc) => {
|
|
76
|
+
const bad = await answer();
|
|
77
|
+
if (bad) return bad;
|
|
78
|
+
setNotes((n) => [...n, { id: `n${Date.now()}`, author: ME, body: doc, createdAt: new Date().toISOString() }]);
|
|
79
|
+
return { ok: true };
|
|
80
|
+
},
|
|
81
|
+
onEdit: async (note, doc) => {
|
|
82
|
+
const bad = await answer();
|
|
83
|
+
if (bad) return bad;
|
|
84
|
+
setNotes((n) => n.map((x) => (x.id === note.id ? { ...x, body: doc, updatedAt: new Date().toISOString() } : x)));
|
|
85
|
+
return { ok: true };
|
|
86
|
+
},
|
|
87
|
+
onDelete: async (note) => {
|
|
88
|
+
const bad = await answer();
|
|
89
|
+
if (bad) return bad;
|
|
90
|
+
setNotes((n) => n.filter((x) => x.id !== note.id));
|
|
91
|
+
return { ok: true };
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function DealDemo() {
|
|
97
|
+
const [failing, setFailing] = useState(false);
|
|
98
|
+
const store = usePretendNotes(DEAL_NOTES, failing);
|
|
99
|
+
return (
|
|
100
|
+
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_26rem]">
|
|
101
|
+
<Card
|
|
102
|
+
title="Northwind Logistics — Teams plan"
|
|
103
|
+
description="Owner June Okafor · Close date 15 Dec"
|
|
104
|
+
actions={<Badge tone="info">Proposal</Badge>}
|
|
105
|
+
className="h-fit min-w-0"
|
|
106
|
+
>
|
|
107
|
+
<dl className="grid grid-cols-2 gap-x-4 gap-y-3 text-sm">
|
|
108
|
+
<div>
|
|
109
|
+
<dt className="text-muted-foreground">Amount</dt>
|
|
110
|
+
<dd className="font-medium">$38,400 / yr</dd>
|
|
111
|
+
</div>
|
|
112
|
+
<div>
|
|
113
|
+
<dt className="text-muted-foreground">Seats</dt>
|
|
114
|
+
<dd className="font-medium">40</dd>
|
|
115
|
+
</div>
|
|
116
|
+
<div>
|
|
117
|
+
<dt className="text-muted-foreground">Contact</dt>
|
|
118
|
+
<dd className="font-medium">Dana Whitfield</dd>
|
|
119
|
+
</div>
|
|
120
|
+
<div>
|
|
121
|
+
<dt className="text-muted-foreground">Source</dt>
|
|
122
|
+
<dd className="font-medium">Pricing page</dd>
|
|
123
|
+
</div>
|
|
124
|
+
</dl>
|
|
125
|
+
<div className="mt-4 border-t border-border pt-3">
|
|
126
|
+
<Switch id="rn-fail" label="Saves fail" checked={failing} onChange={(e) => setFailing(e.target.checked)} />
|
|
127
|
+
</div>
|
|
128
|
+
</Card>
|
|
129
|
+
<RecordNotes {...store} me={ME} mentions={findPeople} description="Only you can edit or delete your own notes." />
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const CONTACT_LOG = [
|
|
135
|
+
{ id: "l1", author: person("u-lena"), createdAt: ago(24 * 40), body: "Onboarded. Wants a monthly check-in, first Tuesday." },
|
|
136
|
+
{ id: "l2", author: person("u-lena"), createdAt: ago(24 * 9), body: [{ type: "paragraph", content: [t("Asked about exporting invoices to "), t("Xero", { bold: true }), t(". Logged a feature request.")] }] },
|
|
137
|
+
{ id: "l3", author: ME, createdAt: ago(3), body: [{ type: "paragraph", content: [t("Renewal call booked for Friday. "), at("u-lena"), t(" joins.")] }] },
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
function LogDemo() {
|
|
141
|
+
const store = usePretendNotes(CONTACT_LOG, false);
|
|
142
|
+
return (
|
|
143
|
+
<Card title="Dana Whitfield" description="Head of Operations, Northwind Logistics" className="max-w-2xl">
|
|
144
|
+
<RecordNotes {...store} me={ME} mentions={findPeople} order="oldest" frame="none" title="History" placeholder="Log a call, a meeting, a thought…" addLabel="Log it" />
|
|
145
|
+
</Card>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function EmptyDemo() {
|
|
150
|
+
const store = usePretendNotes([], false);
|
|
151
|
+
return <RecordNotes {...store} me={ME} mentions={findPeople} className="max-w-xl" />;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default function RecordNotesDemo() {
|
|
155
|
+
const [tab, setTab] = useState("deal");
|
|
156
|
+
return (
|
|
157
|
+
<div className="grid gap-4">
|
|
158
|
+
<Tabs
|
|
159
|
+
aria-label="RecordNotes variants"
|
|
160
|
+
value={tab}
|
|
161
|
+
onChange={setTab}
|
|
162
|
+
tabs={[
|
|
163
|
+
{ key: "deal", label: "Deal" },
|
|
164
|
+
{ key: "log", label: "Log" },
|
|
165
|
+
{ key: "empty", label: "Empty" },
|
|
166
|
+
]}
|
|
167
|
+
/>
|
|
168
|
+
<TabPanel tab="deal" value={tab}>
|
|
169
|
+
<DealDemo />
|
|
170
|
+
</TabPanel>
|
|
171
|
+
<TabPanel tab="log" value={tab}>
|
|
172
|
+
<LogDemo />
|
|
173
|
+
</TabPanel>
|
|
174
|
+
<TabPanel tab="empty" value={tab}>
|
|
175
|
+
<EmptyDemo />
|
|
176
|
+
</TabPanel>
|
|
177
|
+
</div>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// RecordNotes — the dated notes kept on one record (a deal, a contact), to
|
|
4
|
+
// sit beside record-form. A composer adds a note; the notes follow, grouped
|
|
5
|
+
// by day, each with its author and time; your own notes have Edit (in
|
|
6
|
+
// place, the same composer) and Delete (after a Confirm).
|
|
7
|
+
//
|
|
8
|
+
// Every save is an async callback answering { ok }. The block holds no
|
|
9
|
+
// copy of the notes: the page adds, replaces or drops the note in `notes`
|
|
10
|
+
// when its callback succeeds, and the block shows a failure where it
|
|
11
|
+
// happened (under the composer, or on the note).
|
|
12
|
+
//
|
|
13
|
+
// Days ("Today", "Yesterday") are the reader's, known only in the
|
|
14
|
+
// browser: the server draws the notes as one list, and the day headings
|
|
15
|
+
// appear once mounted — never a mismatch between the two renders.
|
|
16
|
+
import { useEffect, useRef, useState } from "react";
|
|
17
|
+
import { Avatar, Badge, Card, Confirm, Menu, cx } from "../../ui";
|
|
18
|
+
import { CommentBody, CommentComposer, CommentTime } from "../comment-box";
|
|
19
|
+
import { docToText } from "../doc-editor";
|
|
20
|
+
|
|
21
|
+
const nameOf = (author) => (typeof author === "string" ? author : author?.name) || "Someone";
|
|
22
|
+
const srcOf = (author) => (typeof author === "object" && author ? author.src : undefined);
|
|
23
|
+
const idOf = (author) => (typeof author === "object" && author ? author.id : undefined);
|
|
24
|
+
|
|
25
|
+
const toMs = (v) => {
|
|
26
|
+
if (v === undefined || v === null || v === "") return NaN;
|
|
27
|
+
return (v instanceof Date ? v : new Date(v)).getTime();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function useMounted() {
|
|
31
|
+
const [on, setOn] = useState(false);
|
|
32
|
+
useEffect(() => setOn(true), []);
|
|
33
|
+
return on;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function dayOf(ms) {
|
|
37
|
+
const d = new Date(ms);
|
|
38
|
+
d.setHours(0, 0, 0, 0);
|
|
39
|
+
return d.getTime();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function dayLabel(day, now) {
|
|
43
|
+
const today = dayOf(now);
|
|
44
|
+
if (day === today) return "Today";
|
|
45
|
+
if (day === today - 86_400_000) return "Yesterday";
|
|
46
|
+
const d = new Date(day);
|
|
47
|
+
const sameYear = d.getFullYear() === new Date(now).getFullYear();
|
|
48
|
+
return new Intl.DateTimeFormat(undefined, { weekday: "short", day: "numeric", month: "short", ...(sameYear ? {} : { year: "numeric" }) }).format(d);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Split sorted notes into runs of one day each: [{ day, label, notes }]. */
|
|
52
|
+
function byDay(notes, now) {
|
|
53
|
+
const out = [];
|
|
54
|
+
for (const n of notes) {
|
|
55
|
+
const ms = toMs(n.createdAt);
|
|
56
|
+
const day = Number.isNaN(ms) ? null : dayOf(ms);
|
|
57
|
+
const last = out[out.length - 1];
|
|
58
|
+
if (last && last.day === day) last.notes.push(n);
|
|
59
|
+
else out.push({ day, label: day === null ? "Undated" : dayLabel(day, now), notes: [n] });
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const snippet = (doc, max = 120) => {
|
|
65
|
+
const text = docToText(doc).replace(/\s+/g, " ").trim();
|
|
66
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
function Note({ note, own, editing, onStartEdit, onStopEdit, onEdit, onAskDelete, error, mentions }) {
|
|
70
|
+
const name = nameOf(note.author);
|
|
71
|
+
const self = useRef(null);
|
|
72
|
+
const was = useRef(editing);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
// Back from editing: the caret was in the composer, which is gone.
|
|
75
|
+
if (was.current && !editing) self.current?.focus();
|
|
76
|
+
was.current = editing;
|
|
77
|
+
}, [editing]);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<li>
|
|
81
|
+
<article ref={self} tabIndex={-1} aria-label={`Note by ${name}`} className="flex gap-3 rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring">
|
|
82
|
+
<Avatar name={name} src={srcOf(note.author)} size="sm" className="mt-0.5 shrink-0" />
|
|
83
|
+
<div className="min-w-0 flex-1">
|
|
84
|
+
<div className="flex items-start gap-2">
|
|
85
|
+
<p className="flex min-w-0 flex-1 flex-wrap items-baseline gap-x-2 pt-1 text-sm">
|
|
86
|
+
<span className="font-medium">{name}</span>
|
|
87
|
+
<CommentTime date={note.createdAt} />
|
|
88
|
+
{note.updatedAt || note.edited ? <span className="text-xs text-muted-foreground">(edited)</span> : null}
|
|
89
|
+
</p>
|
|
90
|
+
{own && !editing ? (
|
|
91
|
+
<Menu
|
|
92
|
+
size="md"
|
|
93
|
+
label={`Note by ${name}, actions`}
|
|
94
|
+
className="-me-2 -mt-2 shrink-0"
|
|
95
|
+
items={[
|
|
96
|
+
onEdit && { label: "Edit", icon: "pencil", onSelect: onStartEdit },
|
|
97
|
+
onAskDelete && { label: "Delete", icon: "trash", tone: "danger", onSelect: onAskDelete },
|
|
98
|
+
]}
|
|
99
|
+
/>
|
|
100
|
+
) : null}
|
|
101
|
+
</div>
|
|
102
|
+
{editing ? (
|
|
103
|
+
<CommentComposer
|
|
104
|
+
className="mt-2"
|
|
105
|
+
defaultValue={note.body}
|
|
106
|
+
onSubmit={(doc) => onEdit(note, doc)}
|
|
107
|
+
onCancel={onStopEdit}
|
|
108
|
+
mentions={mentions}
|
|
109
|
+
submitLabel="Save"
|
|
110
|
+
submitIcon={null}
|
|
111
|
+
busyLabel="Saving…"
|
|
112
|
+
failedText="Couldn't save the change. Your edit is still here; try again."
|
|
113
|
+
label={`Edit note by ${name}`}
|
|
114
|
+
clearOnSubmit={false}
|
|
115
|
+
autoFocus
|
|
116
|
+
/>
|
|
117
|
+
) : (
|
|
118
|
+
<CommentBody doc={note.body} className="mt-0.5" />
|
|
119
|
+
)}
|
|
120
|
+
{error ? (
|
|
121
|
+
<p role="alert" className="mt-1.5 text-xs text-destructive">
|
|
122
|
+
{error}
|
|
123
|
+
</p>
|
|
124
|
+
) : null}
|
|
125
|
+
</div>
|
|
126
|
+
</article>
|
|
127
|
+
</li>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function RecordNotes({
|
|
132
|
+
notes,
|
|
133
|
+
me,
|
|
134
|
+
onAdd,
|
|
135
|
+
onEdit,
|
|
136
|
+
onDelete,
|
|
137
|
+
canEdit,
|
|
138
|
+
mentions,
|
|
139
|
+
title = "Notes",
|
|
140
|
+
description,
|
|
141
|
+
placeholder = "Add a note…",
|
|
142
|
+
addLabel = "Add note",
|
|
143
|
+
emptyText = "No notes yet. The first one starts the record's history.",
|
|
144
|
+
order = "newest",
|
|
145
|
+
frame = "card",
|
|
146
|
+
className,
|
|
147
|
+
}) {
|
|
148
|
+
const mounted = useMounted();
|
|
149
|
+
const [editing, setEditing] = useState(null);
|
|
150
|
+
const [asking, setAsking] = useState(null);
|
|
151
|
+
const [deleting, setDeleting] = useState(false);
|
|
152
|
+
const [errors, setErrors] = useState({});
|
|
153
|
+
const listRef = useRef(null);
|
|
154
|
+
|
|
155
|
+
const list = (Array.isArray(notes) ? notes : [])
|
|
156
|
+
.map((n, i) => ({ n, i, ms: toMs(n.createdAt) }))
|
|
157
|
+
.sort((a, b) => {
|
|
158
|
+
const x = Number.isNaN(a.ms) ? -Infinity : a.ms;
|
|
159
|
+
const y = Number.isNaN(b.ms) ? -Infinity : b.ms;
|
|
160
|
+
return (order === "oldest" ? x - y : y - x) || a.i - b.i;
|
|
161
|
+
})
|
|
162
|
+
.map((x) => x.n);
|
|
163
|
+
|
|
164
|
+
const keyOf = (n, i) => n.id ?? `note-${i}`;
|
|
165
|
+
const isOwn = (n) => (canEdit ? !!canEdit(n) : n.mine === true || (me?.id !== undefined && idOf(n.author) === me.id));
|
|
166
|
+
const setError = (key, msg) => setErrors((e) => ({ ...e, [key]: msg }));
|
|
167
|
+
|
|
168
|
+
async function saveEdit(note, doc) {
|
|
169
|
+
let res;
|
|
170
|
+
try {
|
|
171
|
+
res = await onEdit(note, doc);
|
|
172
|
+
} catch (e) {
|
|
173
|
+
res = { ok: false, error: e?.message };
|
|
174
|
+
}
|
|
175
|
+
if (res && res.ok === false) return res;
|
|
176
|
+
setEditing(null);
|
|
177
|
+
setError(note.id, null);
|
|
178
|
+
return { ok: true };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function confirmDelete() {
|
|
182
|
+
const note = asking;
|
|
183
|
+
if (!note) return;
|
|
184
|
+
setDeleting(true);
|
|
185
|
+
let res;
|
|
186
|
+
try {
|
|
187
|
+
res = await onDelete(note);
|
|
188
|
+
} catch (e) {
|
|
189
|
+
res = { ok: false, error: e?.message };
|
|
190
|
+
}
|
|
191
|
+
setDeleting(false);
|
|
192
|
+
setAsking(null);
|
|
193
|
+
if (res && res.ok === false) {
|
|
194
|
+
setError(note.id, res.error || "Couldn't delete this note. Try again.");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
listRef.current?.focus();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const composer = onAdd ? (
|
|
201
|
+
<CommentComposer onSubmit={onAdd} author={me} mentions={mentions} placeholder={placeholder} submitLabel={addLabel} submitIcon="plus" busyLabel="Adding…" failedText="Couldn't add the note. It is still here; try again." label="New note" />
|
|
202
|
+
) : null;
|
|
203
|
+
|
|
204
|
+
const renderNote = (n, i) => {
|
|
205
|
+
const key = keyOf(n, i);
|
|
206
|
+
return (
|
|
207
|
+
<Note
|
|
208
|
+
key={key}
|
|
209
|
+
note={n}
|
|
210
|
+
own={isOwn(n)}
|
|
211
|
+
editing={editing === key}
|
|
212
|
+
onStartEdit={() => {
|
|
213
|
+
setError(n.id, null);
|
|
214
|
+
setEditing(key);
|
|
215
|
+
}}
|
|
216
|
+
onStopEdit={() => setEditing(null)}
|
|
217
|
+
onEdit={onEdit ? saveEdit : null}
|
|
218
|
+
onAskDelete={onDelete ? () => setAsking(n) : null}
|
|
219
|
+
error={errors[n.id]}
|
|
220
|
+
mentions={mentions}
|
|
221
|
+
/>
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const groups = mounted ? byDay(list, Date.now()) : [{ day: "all", label: null, notes: list }];
|
|
226
|
+
const body = (
|
|
227
|
+
<div className="grid gap-5">
|
|
228
|
+
{order !== "oldest" ? composer : null}
|
|
229
|
+
{list.length === 0 ? (
|
|
230
|
+
<p className="text-sm text-muted-foreground">{emptyText}</p>
|
|
231
|
+
) : (
|
|
232
|
+
<div ref={listRef} tabIndex={-1} aria-label={`${title}, ${list.length}`} role="region" className="grid gap-5 outline-none">
|
|
233
|
+
{groups.map((g) => (
|
|
234
|
+
<section key={g.day ?? "undated"} aria-label={g.label ?? undefined} className="grid gap-3">
|
|
235
|
+
{g.label ? (
|
|
236
|
+
<h3 className="flex items-center gap-3 text-xs font-medium text-muted-foreground">
|
|
237
|
+
<span className="shrink-0">{g.label}</span>
|
|
238
|
+
<span aria-hidden="true" className="h-px flex-1 bg-border" />
|
|
239
|
+
</h3>
|
|
240
|
+
) : null}
|
|
241
|
+
<ul className="grid gap-4">{g.notes.map((n) => renderNote(n, list.indexOf(n)))}</ul>
|
|
242
|
+
</section>
|
|
243
|
+
))}
|
|
244
|
+
</div>
|
|
245
|
+
)}
|
|
246
|
+
{order === "oldest" ? composer : null}
|
|
247
|
+
<Confirm
|
|
248
|
+
open={!!asking}
|
|
249
|
+
onClose={() => (deleting ? null : setAsking(null))}
|
|
250
|
+
onConfirm={confirmDelete}
|
|
251
|
+
title="Delete this note?"
|
|
252
|
+
body={asking ? `“${snippet(asking.body) || "Empty note"}” will be gone for everyone on this record.` : null}
|
|
253
|
+
confirmLabel="Delete note"
|
|
254
|
+
tone="danger"
|
|
255
|
+
busy={deleting}
|
|
256
|
+
/>
|
|
257
|
+
</div>
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
if (frame === "none") return <div className={className}>{body}</div>;
|
|
261
|
+
return (
|
|
262
|
+
<Card title={title} description={description} actions={list.length ? <Badge variant="soft">{list.length}</Badge> : null} className={cx("min-w-0", className)}>
|
|
263
|
+
{body}
|
|
264
|
+
</Card>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# SearchDialog
|
|
2
|
+
|
|
3
|
+
One search over every kind of record in an app: chats, documents, images,
|
|
4
|
+
projects, people. Before anything is typed it shows your sections ("Last
|
|
5
|
+
opened", "Recent chats"). While typing it shows the matches, best first,
|
|
6
|
+
with the typed text marked, a date, and a thumbnail for an image. Chips
|
|
7
|
+
under the list (All, Chats, Images, Documents, Projects) narrow it to one
|
|
8
|
+
kind. Arrow keys move, Enter opens, Esc closes, ⌘K / Ctrl+K toggles it.
|
|
9
|
+
|
|
10
|
+
It is the kit's `Command` (the list, the keys, the screen-reader wiring)
|
|
11
|
+
inside the kit's `Sheet`: a dialog near the top of a wide window, a
|
|
12
|
+
bottom sheet on a phone. `SearchPanel` is the same box inline, for a
|
|
13
|
+
search page or a sidebar.
|
|
14
|
+
|
|
15
|
+
```jsx
|
|
16
|
+
import { SearchDialog, SearchPanel } from "../components/blocks/search-dialog"; // a Makersclaw app ("./blocks/search-dialog" from components/)
|
|
17
|
+
import { SearchDialog, SearchPanel } from "@/components/makersclaw/blocks/search-dialog"; // a shadcn project
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
A client component: render it from a `"use client"` component.
|
|
21
|
+
|
|
22
|
+
## The data
|
|
23
|
+
|
|
24
|
+
A result is `{ id, kind, title, snippet?, date?, thumb?, icon?, keywords? }`.
|
|
25
|
+
|
|
26
|
+
- `id` — unique within its kind list.
|
|
27
|
+
- `kind` — `"chat"`, `"document"`, `"image"`, `"project"`, `"person"`,
|
|
28
|
+
`"company"`, `"task"`, `"page"`, or your own word. It picks the icon
|
|
29
|
+
and the chip.
|
|
30
|
+
- `title` — the line that is searched and marked.
|
|
31
|
+
- `snippet` — a line under it: an excerpt, a file type. Searched too.
|
|
32
|
+
- `date` — shown after the snippet while searching ("Sep 4", "Today").
|
|
33
|
+
Format it yourself.
|
|
34
|
+
- `thumb` — an image URL (or a node) shown instead of the icon. Every
|
|
35
|
+
`image` result gets a square, with an image glyph when there is no URL.
|
|
36
|
+
- `icon` — a kit `Icon` name, instead of the kind's.
|
|
37
|
+
- `keywords` — matched, never shown (a person's company, a project's client).
|
|
38
|
+
|
|
39
|
+
## Props
|
|
40
|
+
|
|
41
|
+
Both components take these.
|
|
42
|
+
|
|
43
|
+
- `results` — everything that can be found, searched in the browser. Leave
|
|
44
|
+
it out when `onSearch` does the searching.
|
|
45
|
+
- `onSelect(result)` — the result chosen (click or Enter). Open it here.
|
|
46
|
+
The dialog closes itself first.
|
|
47
|
+
- `sections` — what shows before anything is typed:
|
|
48
|
+
`[{ heading, results }]`, in order. A result may sit in two sections.
|
|
49
|
+
Leave it out and the empty box shows `hint`.
|
|
50
|
+
- `onSearch(query, { signal })` — async; return the results for `query`.
|
|
51
|
+
Called 200ms after typing stops. A newer query aborts the older one
|
|
52
|
+
(pass `signal` to `fetch`). A throw shows "Search failed". The chips
|
|
53
|
+
filter what comes back.
|
|
54
|
+
- `kinds` — the chips, in order: `[{ value, label, icon? }]`. Default:
|
|
55
|
+
every kind in `results` and `sections`, in order of first appearance,
|
|
56
|
+
labelled from the list above ("Chats", "Images"). One kind, no chips.
|
|
57
|
+
- `loading` — `true` while you fetch `results` yourself.
|
|
58
|
+
- `placeholder` — default "Search…".
|
|
59
|
+
- `hint` — what the empty box says before typing. Default "Type to search."
|
|
60
|
+
- `showDate` — default `true`.
|
|
61
|
+
- `label` — what a screen reader calls the box. Default "Search".
|
|
62
|
+
- `className` — on the box (`SearchPanel`) or the dialog (`SearchDialog`).
|
|
63
|
+
|
|
64
|
+
`SearchDialog` also takes:
|
|
65
|
+
|
|
66
|
+
- `open` · `onOpenChange(open)` — controlled; or `defaultOpen`.
|
|
67
|
+
- `hotkey` — `"k"` binds ⌘K / Ctrl+K anywhere on the page to open and
|
|
68
|
+
close it. Bind no key an input on the page already uses.
|
|
69
|
+
|
|
70
|
+
## Example
|
|
71
|
+
|
|
72
|
+
```jsx
|
|
73
|
+
"use client";
|
|
74
|
+
import { useRouter } from "next/navigation";
|
|
75
|
+
import { useState } from "react";
|
|
76
|
+
import { Button } from "../components/ui";
|
|
77
|
+
import { SearchDialog } from "../components/blocks/search-dialog";
|
|
78
|
+
|
|
79
|
+
export function GlobalSearch({ recent, search }) {
|
|
80
|
+
const router = useRouter();
|
|
81
|
+
const [open, setOpen] = useState(false);
|
|
82
|
+
return (
|
|
83
|
+
<>
|
|
84
|
+
<Button icon="search" onClick={() => setOpen(true)}>Search</Button>
|
|
85
|
+
<SearchDialog
|
|
86
|
+
open={open}
|
|
87
|
+
onOpenChange={setOpen}
|
|
88
|
+
hotkey="k"
|
|
89
|
+
sections={[{ heading: "Recent", results: recent }]}
|
|
90
|
+
onSearch={(q) => search(q)} // a server action returning results
|
|
91
|
+
onSelect={(r) => router.push(`/${r.kind}s/${r.id}`)}
|
|
92
|
+
/>
|
|
93
|
+
</>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## What it will not do
|
|
99
|
+
|
|
100
|
+
- Index anything. It searches the list you give it, or asks your server.
|
|
101
|
+
- Lay images out as a grid. An image result is a row with a thumbnail.
|
|
102
|
+
- Remember recent searches. Keep them yourself and pass them as a section.
|
|
103
|
+
- Run commands ("New invoice", "Go to settings"). For a command palette
|
|
104
|
+
use the kit's `CommandDialog`.
|
|
105
|
+
|
|
106
|
+
## Credits
|
|
107
|
+
|
|
108
|
+
Ported from blocks.so (https://blocks.so, command-menu-04, MIT), rewritten on the Makersclaw kit.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "search-dialog",
|
|
3
|
+
"title": "SearchDialog",
|
|
4
|
+
"description": "One ⌘K search over every kind of record — chats, documents, images, projects, people. Before typing it shows your sections (Last opened, Recent); while typing, ranked matches with the typed text marked, a date, image thumbnails, and kind chips (All, Chats, Images…) to narrow them. Searches your list in the browser, or your server through an async onSearch. Built on the kit's Command; SearchPanel is the same box inline.",
|
|
5
|
+
"useWhen": "An app has more than one kind of record and wants one global search box or ⌘K palette to find any of them, or a search page with type filters.",
|
|
6
|
+
"tags": ["search", "global search", "command", "cmdk", "command palette", "spotlight", "find", "filter", "recent", "quick open", "jump to"],
|
|
7
|
+
"exports": ["SearchDialog", "SearchPanel"],
|
|
8
|
+
"files": ["index.js", "search-dialog.jsx"],
|
|
9
|
+
"requires": []
|
|
10
|
+
}
|