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,101 @@
|
|
|
1
|
+
// Positions in a text, and the problems ("diagnostics") drawn on it.
|
|
2
|
+
//
|
|
3
|
+
// Plain functions of strings, so they run in node and on the server. The
|
|
4
|
+
// editor counts in offsets (0-based characters from the start); people and
|
|
5
|
+
// databases count in lines and columns (1-based). Both are accepted here.
|
|
6
|
+
|
|
7
|
+
/** Offset → { line, col }, both 1-based. */
|
|
8
|
+
export function lineCol(text, offset) {
|
|
9
|
+
const s = String(text ?? "");
|
|
10
|
+
const at = Math.max(0, Math.min(s.length, offset | 0));
|
|
11
|
+
let line = 1;
|
|
12
|
+
let start = 0;
|
|
13
|
+
for (let i = 0; i < at; i++) {
|
|
14
|
+
if (s.charCodeAt(i) === 10) {
|
|
15
|
+
line++;
|
|
16
|
+
start = i + 1;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return { line, col: at - start + 1 };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** { line, col } (1-based) → offset, clamped into the text. A missing col
|
|
23
|
+
* is the start of the line. */
|
|
24
|
+
export function offsetOf(text, line, col = 1) {
|
|
25
|
+
const s = String(text ?? "");
|
|
26
|
+
let at = 0;
|
|
27
|
+
for (let n = 1; n < Math.max(1, line | 0); n++) {
|
|
28
|
+
const next = s.indexOf("\n", at);
|
|
29
|
+
if (next < 0) return s.length;
|
|
30
|
+
at = next + 1;
|
|
31
|
+
}
|
|
32
|
+
const end = s.indexOf("\n", at);
|
|
33
|
+
const lineEnd = end < 0 ? s.length : end;
|
|
34
|
+
return Math.min(lineEnd, at + Math.max(0, (col | 0) - 1));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The start and end offsets of line `line` (1-based). */
|
|
38
|
+
export function lineRange(text, line) {
|
|
39
|
+
const s = String(text ?? "");
|
|
40
|
+
const from = offsetOf(s, line, 1);
|
|
41
|
+
const end = s.indexOf("\n", from);
|
|
42
|
+
return { from, to: end < 0 ? s.length : end };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const SEVERITIES = new Set(["error", "warning", "info", "hint"]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The problems a caller hands the editor, made exact: each one gets
|
|
49
|
+
* `from`/`to` offsets inside the text. A problem may say where it is as
|
|
50
|
+
* { from, to } offsets, or
|
|
51
|
+
* { line, col?, endLine?, endCol? } 1-based; no col = the whole line,
|
|
52
|
+
* { position } a 1-based character position, as
|
|
53
|
+
* Postgres reports an error
|
|
54
|
+
* plus `message` and `severity` ("error" default · "warning" · "info").
|
|
55
|
+
* An empty range is widened to the word under it (or one character), so
|
|
56
|
+
* there is always something to underline.
|
|
57
|
+
*/
|
|
58
|
+
export function normalizeDiagnostics(text, list) {
|
|
59
|
+
const s = String(text ?? "");
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const d of list ?? []) {
|
|
62
|
+
if (!d || !d.message) continue;
|
|
63
|
+
let from;
|
|
64
|
+
let to;
|
|
65
|
+
if (Number.isFinite(d.from)) {
|
|
66
|
+
from = d.from;
|
|
67
|
+
to = Number.isFinite(d.to) ? d.to : d.from;
|
|
68
|
+
} else if (Number.isFinite(d.position)) {
|
|
69
|
+
from = d.position - 1;
|
|
70
|
+
to = from;
|
|
71
|
+
} else if (Number.isFinite(d.line)) {
|
|
72
|
+
if (Number.isFinite(d.col)) {
|
|
73
|
+
from = offsetOf(s, d.line, d.col);
|
|
74
|
+
to = Number.isFinite(d.endLine) ? offsetOf(s, d.endLine, d.endCol ?? 1) : Number.isFinite(d.endCol) ? offsetOf(s, d.line, d.endCol) : from;
|
|
75
|
+
} else {
|
|
76
|
+
({ from, to } = lineRange(s, d.line));
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
from = 0;
|
|
80
|
+
to = 0;
|
|
81
|
+
}
|
|
82
|
+
from = Math.max(0, Math.min(s.length, from));
|
|
83
|
+
to = Math.max(from, Math.min(s.length, to));
|
|
84
|
+
if (to === from) ({ from, to } = wordAt(s, from));
|
|
85
|
+
out.push({ from, to, severity: SEVERITIES.has(d.severity) ? d.severity : "error", message: String(d.message), source: d.source });
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** The word (letters, digits, _ $ .) at `at`, else one character. */
|
|
91
|
+
export function wordAt(text, at) {
|
|
92
|
+
const s = String(text ?? "");
|
|
93
|
+
const W = /[\w$.]/;
|
|
94
|
+
let from = at;
|
|
95
|
+
let to = at;
|
|
96
|
+
while (from > 0 && W.test(s[from - 1])) from--;
|
|
97
|
+
while (to < s.length && W.test(s[to])) to++;
|
|
98
|
+
if (to === from) to = Math.min(s.length, from + 1);
|
|
99
|
+
if (to === from && from > 0) from--;
|
|
100
|
+
return { from, to };
|
|
101
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// CodeMirror in the workspace theme — the one place its look is mapped.
|
|
2
|
+
//
|
|
3
|
+
// CodeMirror styles itself with CSS it writes at run time, so its theme is
|
|
4
|
+
// CSS too: every colour below is `var(--color-…)`, the workspace's own
|
|
5
|
+
// token, read by the browser. Nothing is resolved in JavaScript, so a
|
|
6
|
+
// change of theme or of light/dark repaints the editor with no work here.
|
|
7
|
+
//
|
|
8
|
+
// Syntax colours are categories, not status, so they come from the chart
|
|
9
|
+
// hues (--color-chart-1 is the primary): keywords chart-1 and a little
|
|
10
|
+
// heavier (in a theme whose primary is its ink, weight still sets them
|
|
11
|
+
// apart), text in quotes chart-2, numbers and true/false/null chart-3,
|
|
12
|
+
// functions chart-4, names of columns, keys and types chart-5. Comments
|
|
13
|
+
// and punctuation step back into muted-foreground.
|
|
14
|
+
import { EditorView, HighlightStyle, tags as t } from "./codemirror";
|
|
15
|
+
|
|
16
|
+
const v = (token) => `var(--color-${token})`;
|
|
17
|
+
|
|
18
|
+
export const editorTheme = EditorView.theme({
|
|
19
|
+
"&": {
|
|
20
|
+
color: v("foreground"),
|
|
21
|
+
backgroundColor: "transparent",
|
|
22
|
+
fontSize: "var(--code-editor-size, 13px)",
|
|
23
|
+
},
|
|
24
|
+
"&.cm-focused": { outline: "none" },
|
|
25
|
+
".cm-scroller": {
|
|
26
|
+
fontFamily: "var(--font-mono)",
|
|
27
|
+
lineHeight: "1.65",
|
|
28
|
+
overflow: "auto",
|
|
29
|
+
},
|
|
30
|
+
".cm-content": {
|
|
31
|
+
padding: "10px 0",
|
|
32
|
+
caretColor: v("foreground"),
|
|
33
|
+
},
|
|
34
|
+
".cm-line": { padding: "0 16px 0 12px" },
|
|
35
|
+
".cm-cursor, .cm-dropCursor": { borderLeftColor: v("foreground"), borderLeftWidth: "2px" },
|
|
36
|
+
// Selection sits under the text (drawSelection), so an opaque tint reads.
|
|
37
|
+
".cm-selectionBackground": { backgroundColor: v("accent") },
|
|
38
|
+
"&.cm-focused .cm-selectionBackground, &.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-content ::selection": {
|
|
39
|
+
backgroundColor: v("accent"),
|
|
40
|
+
},
|
|
41
|
+
".cm-selectionMatch": { backgroundColor: v("muted"), borderRadius: "2px" },
|
|
42
|
+
"&.cm-focused .cm-matchingBracket": { backgroundColor: "transparent", outline: `1px solid ${v("muted-foreground")}`, borderRadius: "2px" },
|
|
43
|
+
"&.cm-focused .cm-nonmatchingBracket": { backgroundColor: "transparent", outline: `1px solid ${v("destructive")}`, borderRadius: "2px" },
|
|
44
|
+
".cm-placeholder": { color: v("muted-foreground"), fontStyle: "normal" },
|
|
45
|
+
|
|
46
|
+
// The gutter: quiet numbers, the current one in ink.
|
|
47
|
+
".cm-gutters": {
|
|
48
|
+
backgroundColor: "transparent",
|
|
49
|
+
color: v("muted-foreground"),
|
|
50
|
+
border: "none",
|
|
51
|
+
fontVariantNumeric: "tabular-nums",
|
|
52
|
+
},
|
|
53
|
+
".cm-lineNumbers .cm-gutterElement": { padding: "0 4px 0 14px", minWidth: "36px", opacity: "0.7" },
|
|
54
|
+
".cm-activeLineGutter": { backgroundColor: "transparent", color: v("foreground") },
|
|
55
|
+
".cm-activeLineGutter.cm-gutterElement": { opacity: "1" },
|
|
56
|
+
".cm-foldGutter .cm-gutterElement": { padding: "0 2px", cursor: "pointer" },
|
|
57
|
+
".cm-fold-marker": {
|
|
58
|
+
display: "inline-grid",
|
|
59
|
+
placeItems: "center",
|
|
60
|
+
width: "14px",
|
|
61
|
+
height: "100%",
|
|
62
|
+
color: v("muted-foreground"),
|
|
63
|
+
transition: "transform 150ms ease, color 150ms ease",
|
|
64
|
+
},
|
|
65
|
+
".cm-fold-marker:hover": { color: v("foreground") },
|
|
66
|
+
".cm-fold-marker[data-open='false']": { transform: "rotate(-90deg)" },
|
|
67
|
+
".cm-foldPlaceholder": {
|
|
68
|
+
backgroundColor: v("muted"),
|
|
69
|
+
border: "none",
|
|
70
|
+
color: v("muted-foreground"),
|
|
71
|
+
borderRadius: "4px",
|
|
72
|
+
padding: "0 6px",
|
|
73
|
+
margin: "0 2px",
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
// Problems: a wavy line under the text, a dot in the gutter.
|
|
77
|
+
".cm-lintRange": { backgroundImage: "none", textDecorationLine: "underline", textDecorationStyle: "wavy", textDecorationSkipInk: "none", textUnderlineOffset: "3px" },
|
|
78
|
+
".cm-lintRange-error": { textDecorationColor: v("destructive") },
|
|
79
|
+
".cm-lintRange-warning": { textDecorationColor: v("warning") },
|
|
80
|
+
".cm-lintRange-info, .cm-lintRange-hint": { textDecorationColor: v("info") },
|
|
81
|
+
".cm-gutter-lint": { width: "14px" },
|
|
82
|
+
".cm-gutter-lint .cm-gutterElement": { padding: "0", display: "grid", placeItems: "center" },
|
|
83
|
+
".cm-lint-marker": { content: "normal", width: "6px", height: "6px", borderRadius: "9999px" },
|
|
84
|
+
// CodeMirror sets its icon as `content: url(…)` on each kind; ours is the dot.
|
|
85
|
+
".cm-lint-marker-error": { content: "normal", backgroundColor: v("destructive") },
|
|
86
|
+
".cm-lint-marker-warning": { content: "normal", backgroundColor: v("warning") },
|
|
87
|
+
".cm-lint-marker-info": { content: "normal", backgroundColor: v("info") },
|
|
88
|
+
|
|
89
|
+
// Every floating panel: the popover surface and a hairline (the shadow
|
|
90
|
+
// is the kit's shadow-lg, set on the wrapper in code-editor.jsx).
|
|
91
|
+
".cm-tooltip": {
|
|
92
|
+
backgroundColor: v("popover"),
|
|
93
|
+
color: v("popover-foreground"),
|
|
94
|
+
border: `1px solid ${v("border")}`,
|
|
95
|
+
borderRadius: "var(--radius-md)",
|
|
96
|
+
},
|
|
97
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
|
98
|
+
fontFamily: "var(--font-mono)",
|
|
99
|
+
maxHeight: "16em",
|
|
100
|
+
padding: "4px",
|
|
101
|
+
},
|
|
102
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {
|
|
103
|
+
padding: "3px 8px",
|
|
104
|
+
borderRadius: "4px",
|
|
105
|
+
lineHeight: "1.6",
|
|
106
|
+
display: "flex",
|
|
107
|
+
alignItems: "center",
|
|
108
|
+
gap: "6px",
|
|
109
|
+
},
|
|
110
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {
|
|
111
|
+
backgroundColor: v("accent"),
|
|
112
|
+
color: v("accent-foreground"),
|
|
113
|
+
},
|
|
114
|
+
".cm-completionLabel": { flex: "0 1 auto" },
|
|
115
|
+
".cm-completionMatchedText": { textDecoration: "none", fontWeight: "600", color: v("foreground") },
|
|
116
|
+
".cm-completionDetail": { marginLeft: "auto", paddingLeft: "12px", fontStyle: "normal", color: v("muted-foreground"), fontSize: "0.9em" },
|
|
117
|
+
".cm-completionIcon": { width: "1.1em", opacity: "0.7", paddingRight: "0", color: v("muted-foreground"), fontSize: "0.85em" },
|
|
118
|
+
".cm-completionIcon-keyword:after": { content: "'K'" },
|
|
119
|
+
".cm-completionIcon-type:after": { content: "'T'" },
|
|
120
|
+
".cm-completionIcon-property:after": { content: "'·'" },
|
|
121
|
+
".cm-completionIcon-namespace:after": { content: "'S'" },
|
|
122
|
+
".cm-completionInfo": {
|
|
123
|
+
backgroundColor: v("popover"),
|
|
124
|
+
color: v("popover-foreground"),
|
|
125
|
+
border: `1px solid ${v("border")}`,
|
|
126
|
+
borderRadius: "var(--radius-md)",
|
|
127
|
+
padding: "6px 10px",
|
|
128
|
+
fontFamily: "var(--font-sans)",
|
|
129
|
+
maxWidth: "280px",
|
|
130
|
+
},
|
|
131
|
+
".cm-tooltip-lint": { padding: "2px" },
|
|
132
|
+
".cm-diagnostic": { fontFamily: "var(--font-sans)", padding: "6px 10px", borderLeft: "3px solid transparent", borderRadius: "4px" },
|
|
133
|
+
".cm-diagnostic-error": { borderLeftColor: v("destructive") },
|
|
134
|
+
".cm-diagnostic-warning": { borderLeftColor: v("warning") },
|
|
135
|
+
".cm-diagnostic-info, .cm-diagnostic-hint": { borderLeftColor: v("info") },
|
|
136
|
+
|
|
137
|
+
// Find and replace (Cmd/Ctrl+F): our fields and buttons, not the default grey.
|
|
138
|
+
".cm-panels": { backgroundColor: v("card"), color: v("foreground") },
|
|
139
|
+
".cm-panels.cm-panels-top": { borderBottom: `1px solid ${v("border")}` },
|
|
140
|
+
".cm-panels.cm-panels-bottom": { borderTop: `1px solid ${v("border")}` },
|
|
141
|
+
".cm-panel.cm-search": { padding: "8px 12px", fontFamily: "var(--font-sans)", fontSize: "13px", display: "flex", flexWrap: "wrap", alignItems: "center", gap: "6px" },
|
|
142
|
+
".cm-panel.cm-search br": { display: "none" },
|
|
143
|
+
".cm-panel.cm-search label": { display: "inline-flex", alignItems: "center", gap: "4px", color: v("muted-foreground") },
|
|
144
|
+
".cm-panel.cm-search [name=close]": { position: "static", marginLeft: "auto", color: v("muted-foreground"), fontSize: "18px", padding: "0 6px" },
|
|
145
|
+
".cm-textfield": {
|
|
146
|
+
backgroundColor: v("background"),
|
|
147
|
+
color: v("foreground"),
|
|
148
|
+
border: `1px solid ${v("input")}`,
|
|
149
|
+
borderRadius: "var(--radius-sm)",
|
|
150
|
+
padding: "4px 8px",
|
|
151
|
+
margin: "0",
|
|
152
|
+
fontSize: "13px",
|
|
153
|
+
},
|
|
154
|
+
".cm-textfield:focus": { outline: `2px solid ${v("ring")}`, outlineOffset: "0" },
|
|
155
|
+
".cm-button": {
|
|
156
|
+
backgroundImage: "none",
|
|
157
|
+
backgroundColor: v("secondary"),
|
|
158
|
+
color: v("secondary-foreground"),
|
|
159
|
+
border: `1px solid ${v("border")}`,
|
|
160
|
+
borderRadius: "var(--radius-sm)",
|
|
161
|
+
padding: "4px 10px",
|
|
162
|
+
margin: "0",
|
|
163
|
+
fontSize: "13px",
|
|
164
|
+
},
|
|
165
|
+
".cm-button:hover": { backgroundColor: v("accent") },
|
|
166
|
+
".cm-button:active": { backgroundImage: "none" },
|
|
167
|
+
".cm-searchMatch": { backgroundColor: v("muted"), outline: `1px solid ${v("border")}`, borderRadius: "2px" },
|
|
168
|
+
".cm-searchMatch.cm-searchMatch-selected": { backgroundColor: v("accent"), outline: `1px solid ${v("muted-foreground")}` },
|
|
169
|
+
|
|
170
|
+
// The statement that just ran, lit for a moment.
|
|
171
|
+
".cm-ran": { backgroundColor: v("accent"), borderRadius: "2px", transition: "background-color 400ms ease" },
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export const highlightStyle = HighlightStyle.define([
|
|
175
|
+
{ tag: [t.keyword, t.operatorKeyword, t.modifier, t.controlKeyword, t.definitionKeyword], color: v("chart-1"), fontWeight: "600" },
|
|
176
|
+
{ tag: [t.string, t.special(t.string), t.regexp], color: v("chart-2") },
|
|
177
|
+
{ tag: [t.number, t.bool, t.null, t.atom], color: v("chart-3") },
|
|
178
|
+
{ tag: [t.function(t.variableName), t.function(t.propertyName), t.standard(t.name)], color: v("chart-4") },
|
|
179
|
+
{ tag: [t.propertyName, t.typeName, t.className, t.special(t.name), t.labelName], color: v("chart-5") },
|
|
180
|
+
{ tag: [t.comment, t.lineComment, t.blockComment], color: v("muted-foreground"), fontStyle: "italic" },
|
|
181
|
+
{ tag: [t.punctuation, t.separator, t.bracket, t.operator, t.derefOperator], color: v("muted-foreground") },
|
|
182
|
+
{ tag: t.invalid, color: v("destructive") },
|
|
183
|
+
{ tag: t.strong, fontWeight: "600" },
|
|
184
|
+
{ tag: t.emphasis, fontStyle: "italic" },
|
|
185
|
+
{ tag: t.link, textDecoration: "underline" },
|
|
186
|
+
]);
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# CommentBox
|
|
2
|
+
|
|
3
|
+
A comment field that takes rich text: select a word for bold, italic or a
|
|
4
|
+
link, start a line with `-` for a list, type `@` to mention a teammate
|
|
5
|
+
(they go in as a chip). Cmd/Ctrl+Enter posts, as does the Post button.
|
|
6
|
+
While a post is on its way the box is locked; when it fails the words
|
|
7
|
+
stay and the box says why; when it lands the box clears. Give it
|
|
8
|
+
`comments` and it draws the thread above: avatar, name, "5 min ago", the
|
|
9
|
+
body with its formatting and mentions.
|
|
10
|
+
|
|
11
|
+
It is `doc-editor` in its minimal mode (no `/` menu, no drag handles), so
|
|
12
|
+
a comment is BlockNote JSON — the same doc every text block uses.
|
|
13
|
+
|
|
14
|
+
```jsx
|
|
15
|
+
import { CommentBox } from "../components/blocks/comment-box"; // a Makersclaw app ("./blocks/comment-box" from components/)
|
|
16
|
+
import { CommentBox } from "@/components/makersclaw/blocks/comment-box"; // a shadcn project
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
It is a client component: render it from a `"use client"` component, and
|
|
20
|
+
load the thread in the server surface (README §4). `makersclaw add
|
|
21
|
+
comment-box` adds `doc-editor` with it (and its npm packages: run
|
|
22
|
+
`npm install` after).
|
|
23
|
+
|
|
24
|
+
## The data
|
|
25
|
+
|
|
26
|
+
A comment in `comments`:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
{
|
|
30
|
+
id: "c-81",
|
|
31
|
+
author: { id: "u-lena", name: "Lena Fischer", src: "https://…/lena.jpg" }, // or just "Lena Fischer"
|
|
32
|
+
body: [ /* the doc onPost gave you */ ], // or a plain string
|
|
33
|
+
createdAt: "2026-09-23T09:12:00Z", // ISO string, Date or ms
|
|
34
|
+
edited: false, // true adds "(edited)"
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Store `body` as it came out of `onPost` (a `jsonb` column). Keep a plain
|
|
39
|
+
copy beside it for search and notifications: `docToText(doc)` from
|
|
40
|
+
`doc-editor`. The people mentioned are `docMentions(doc)` — notify them.
|
|
41
|
+
|
|
42
|
+
## Props
|
|
43
|
+
|
|
44
|
+
- `onPost(doc)` — required. `async`, returns `{ ok: true }` or
|
|
45
|
+
`{ ok: false, error? }` (`error` is shown under the box; without it,
|
|
46
|
+
"Couldn't post…"). A throw counts as a failure. Only an ok clears the
|
|
47
|
+
box. An empty box never posts.
|
|
48
|
+
- `comments` — the thread, oldest first, drawn above the box. Leave it out
|
|
49
|
+
for the field alone; `[]` shows `emptyText`.
|
|
50
|
+
- `author` — `{ name, src? }`, who is writing: their avatar sits beside
|
|
51
|
+
the box from 640px.
|
|
52
|
+
- `mentions` — `async (query) => [{ id, label, description? }]`: turns on
|
|
53
|
+
`@` (doc-editor's `mentions`).
|
|
54
|
+
- `placeholder` — `"Write a comment…"`.
|
|
55
|
+
- `postLabel` — the button, `"Post"` ("Reply", "Send").
|
|
56
|
+
- `label` — the field's accessible name, `"Comment"`.
|
|
57
|
+
- `threadLabel` — the list's accessible name, `"Comments"`.
|
|
58
|
+
- `emptyText` — `"No comments yet."`.
|
|
59
|
+
- `autoFocus` — `false`.
|
|
60
|
+
- `disabled` — `false`; `true` locks the box (no edit, no post).
|
|
61
|
+
- `className` — layout around it.
|
|
62
|
+
|
|
63
|
+
The other exports, for a thread of your own:
|
|
64
|
+
|
|
65
|
+
- `CommentComposer` — the field and its buttons: `onSubmit(doc)` (same
|
|
66
|
+
answer as `onPost`), `author`, `mentions`, `defaultValue` (a doc to
|
|
67
|
+
start from — editing a comment), `placeholder`, `submitLabel`
|
|
68
|
+
(`"Post"`), `submitIcon` (a kit icon name, `"send"`; `null` for none),
|
|
69
|
+
`busyLabel` (shown while it runs), `failedText`,
|
|
70
|
+
`onCancel` (adds a Cancel button), `cancelLabel`, `label`,
|
|
71
|
+
`autoFocus`, `disabled`, `clearOnSubmit` (`true`; `false` when the
|
|
72
|
+
composer goes away after a save), `className`.
|
|
73
|
+
- `CommentBody` — `{ doc, className }`: a doc drawn read-only as plain
|
|
74
|
+
HTML (server too): paragraphs, headings, lists, checklists, quotes,
|
|
75
|
+
code, tables, links, image links, mentions and fields as chips.
|
|
76
|
+
- `CommentTime` — `{ date, className }`: a `<time>`; the absolute date on
|
|
77
|
+
the server, "5 min ago" once mounted, kept current each minute.
|
|
78
|
+
|
|
79
|
+
## Example
|
|
80
|
+
|
|
81
|
+
```jsx
|
|
82
|
+
// components/TaskComments.jsx — client
|
|
83
|
+
"use client";
|
|
84
|
+
import { useState } from "react";
|
|
85
|
+
import { insertRow } from "../lib/actions";
|
|
86
|
+
import { CommentBox } from "./blocks/comment-box";
|
|
87
|
+
import { docToText } from "./blocks/doc-editor";
|
|
88
|
+
|
|
89
|
+
export default function TaskComments({ task, me, team, initial }) {
|
|
90
|
+
const [comments, setComments] = useState(initial);
|
|
91
|
+
const findPeople = async (q) =>
|
|
92
|
+
team.filter((p) => p.name.toLowerCase().includes(q.toLowerCase())).map((p) => ({ id: p.id, label: p.name }));
|
|
93
|
+
|
|
94
|
+
async function post(doc) {
|
|
95
|
+
const res = await insertRow({
|
|
96
|
+
source: "public.comments",
|
|
97
|
+
values: { task_id: task.id, author_id: me.id, body: doc, body_text: docToText(doc) },
|
|
98
|
+
});
|
|
99
|
+
if (!res.ok) return { ok: false, error: res.error };
|
|
100
|
+
setComments((c) => [...c, { id: res.id, author: me, body: doc, createdAt: new Date() }]);
|
|
101
|
+
return { ok: true };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return <CommentBox comments={comments} onPost={post} author={me} mentions={findPeople} />;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## What it will not do
|
|
109
|
+
|
|
110
|
+
- Edit or delete a posted comment, react, or reply in a nested thread: the
|
|
111
|
+
thread is read-only. Notes you keep, edit and delete on a record are
|
|
112
|
+
`record-notes`; build a richer thread from `CommentComposer` +
|
|
113
|
+
`CommentBody` in your own component.
|
|
114
|
+
- Attach files or images, or offer a `/` menu: it is a comment, not a
|
|
115
|
+
document (`doc-editor` for that).
|
|
116
|
+
- Notify anyone: read the mentions off the doc (`docMentions`) and send
|
|
117
|
+
them yourself.
|
|
118
|
+
- Load older comments or scroll the thread: it draws what it is given;
|
|
119
|
+
put it in a scrolling box and page it yourself.
|
|
120
|
+
|
|
121
|
+
An editor it cannot be is your own component in `components/` — not an
|
|
122
|
+
edit to this block. Its files are fixed: `npm run check` refuses a
|
|
123
|
+
change, and `makersclaw add comment-box` restores them.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "comment-box",
|
|
3
|
+
"title": "CommentBox",
|
|
4
|
+
"description": "A minimal rich comment field (DocEditor in minimal mode): bold, italic, links and lists from the selection toolbar or markdown shortcuts, @mentions as chips, Cmd/Ctrl+Enter to post. It posts through an async onPost(doc) that answers { ok }, keeps the draft and says why when it fails, and clears when it lands. With `comments` it draws the thread above it: avatar, name, relative time, the rich body. Also exports the composer alone, the read-only body renderer and the timestamp.",
|
|
5
|
+
"useWhen": "People comment on something in the app: a task, a design, a document, an approval, a support ticket; a reply field with @mentions under a thread. Not dated notes kept on a record with edit and delete (record-notes), not a conversation with an assistant (chat), not a long document (doc-editor, doc-page).",
|
|
6
|
+
"tags": ["comment", "comments", "thread", "reply", "mention", "composer", "discussion", "feedback", "rich text", "blocknote", "cmd enter"],
|
|
7
|
+
"exports": ["CommentBox", "CommentComposer", "CommentBody", "CommentTime"],
|
|
8
|
+
"files": ["index.js", "comment-box.jsx", "comment-body.jsx", "comment-time.jsx"],
|
|
9
|
+
"requires": ["doc-editor"]
|
|
10
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// CommentBody — a posted doc, drawn read-only as plain React.
|
|
2
|
+
//
|
|
3
|
+
// Why not a read-only DocEditor: a thread is many small docs, and one
|
|
4
|
+
// BlockNote editor per comment is heavy and paints only after mount. This
|
|
5
|
+
// walks the same JSON (the shapes doc-editor's README lists) and renders
|
|
6
|
+
// on the server too. Mentions and fields look like the editor's chips.
|
|
7
|
+
// A block type it does not know shows its text, never nothing.
|
|
8
|
+
import { Fragment } from "react";
|
|
9
|
+
import { Icon, Separator, cx } from "../../ui";
|
|
10
|
+
|
|
11
|
+
const noText = (content) => inlineOf(content).every((c) => c?.type === "text" && !(c.text ?? "").trim());
|
|
12
|
+
|
|
13
|
+
const CHIP = "inline-flex items-baseline rounded-sm px-1 font-medium whitespace-nowrap";
|
|
14
|
+
|
|
15
|
+
/** The inline pieces of a block's content, whatever shape it came in. */
|
|
16
|
+
function inlineOf(content) {
|
|
17
|
+
if (typeof content === "string") return [{ type: "text", text: content, styles: {} }];
|
|
18
|
+
return Array.isArray(content) ? content : [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function styled(text, styles, key) {
|
|
22
|
+
let node = text;
|
|
23
|
+
const s = styles ?? {};
|
|
24
|
+
if (s.code) node = <code className="rounded-sm bg-muted px-1 font-mono text-[0.9em]">{node}</code>;
|
|
25
|
+
if (s.bold) node = <strong className="font-semibold">{node}</strong>;
|
|
26
|
+
if (s.italic) node = <em>{node}</em>;
|
|
27
|
+
if (s.underline) node = <u>{node}</u>;
|
|
28
|
+
if (s.strike) node = <s>{node}</s>;
|
|
29
|
+
return <Fragment key={key}>{node}</Fragment>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const safeHref = (href) => (typeof href === "string" && /^(https?:|mailto:|tel:|\/|#)/i.test(href.trim()) ? href.trim() : undefined);
|
|
33
|
+
|
|
34
|
+
function Inline({ content }) {
|
|
35
|
+
return inlineOf(content).map((c, i) => {
|
|
36
|
+
if (!c || typeof c !== "object") return null;
|
|
37
|
+
if (c.type === "text") return styled(c.text ?? "", c.styles, i);
|
|
38
|
+
if (c.type === "link")
|
|
39
|
+
return (
|
|
40
|
+
<a key={i} href={safeHref(c.href)} target="_blank" rel="noreferrer noopener" className="text-primary underline underline-offset-2">
|
|
41
|
+
<Inline content={c.content} />
|
|
42
|
+
</a>
|
|
43
|
+
);
|
|
44
|
+
if (c.type === "mention")
|
|
45
|
+
return (
|
|
46
|
+
<span key={i} className={cx(CHIP, "bg-primary/10 text-primary")} data-mention={c.props?.id}>
|
|
47
|
+
@{c.props?.label || c.props?.id}
|
|
48
|
+
</span>
|
|
49
|
+
);
|
|
50
|
+
if (c.type === "field")
|
|
51
|
+
return (
|
|
52
|
+
<span key={i} className={cx(CHIP, "border border-dashed border-border bg-muted text-muted-foreground")} title={`{${c.props?.key ?? ""}}`}>
|
|
53
|
+
{c.props?.label || c.props?.key}
|
|
54
|
+
</span>
|
|
55
|
+
);
|
|
56
|
+
return Array.isArray(c.content) ? <Inline key={i} content={c.content} /> : null;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const LISTS = { bulletListItem: "ul", numberedListItem: "ol", checkListItem: "ul", toggleListItem: "ul" };
|
|
61
|
+
const LIST_CLASS = {
|
|
62
|
+
bulletListItem: "list-disc ps-5",
|
|
63
|
+
numberedListItem: "list-decimal ps-5",
|
|
64
|
+
checkListItem: "",
|
|
65
|
+
toggleListItem: "list-disc ps-5",
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
function Children({ blocks }) {
|
|
69
|
+
return Array.isArray(blocks) && blocks.length ? (
|
|
70
|
+
<div className="mt-1 grid gap-1 ps-4">
|
|
71
|
+
<Blocks blocks={blocks} />
|
|
72
|
+
</div>
|
|
73
|
+
) : null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function ListItem({ block }) {
|
|
77
|
+
if (block.type === "checkListItem") {
|
|
78
|
+
const done = !!block.props?.checked;
|
|
79
|
+
return (
|
|
80
|
+
<li className="flex items-start gap-2">
|
|
81
|
+
<Icon name={done ? "check-circle" : "circle"} size={16} className={cx("mt-0.5 shrink-0", done ? "text-primary" : "text-muted-foreground")} />
|
|
82
|
+
<span className="sr-only">{done ? "Done: " : "To do: "}</span>
|
|
83
|
+
<div className={cx("min-w-0", done && "text-muted-foreground line-through")}>
|
|
84
|
+
<Inline content={block.content} />
|
|
85
|
+
<Children blocks={block.children} />
|
|
86
|
+
</div>
|
|
87
|
+
</li>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
return (
|
|
91
|
+
<li>
|
|
92
|
+
<Inline content={block.content} />
|
|
93
|
+
<Children blocks={block.children} />
|
|
94
|
+
</li>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function tableRows(content) {
|
|
99
|
+
return (content?.rows ?? []).map((r) => (r?.cells ?? []).map((cell) => cell?.content ?? cell));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function Block({ block }) {
|
|
103
|
+
const { type, props } = block;
|
|
104
|
+
switch (type) {
|
|
105
|
+
case "heading":
|
|
106
|
+
return (
|
|
107
|
+
<p className={cx("font-semibold", props?.level === 1 ? "text-base" : "text-sm")}>
|
|
108
|
+
<Inline content={block.content} />
|
|
109
|
+
</p>
|
|
110
|
+
);
|
|
111
|
+
case "quote":
|
|
112
|
+
return (
|
|
113
|
+
<blockquote className="border-s-2 border-border ps-3 text-muted-foreground">
|
|
114
|
+
<Inline content={block.content} />
|
|
115
|
+
</blockquote>
|
|
116
|
+
);
|
|
117
|
+
case "codeBlock":
|
|
118
|
+
return (
|
|
119
|
+
<pre className="overflow-x-auto rounded-md bg-muted p-2 font-mono text-xs">
|
|
120
|
+
<code>
|
|
121
|
+
<Inline content={block.content} />
|
|
122
|
+
</code>
|
|
123
|
+
</pre>
|
|
124
|
+
);
|
|
125
|
+
case "divider":
|
|
126
|
+
return <Separator className="my-1" />;
|
|
127
|
+
case "image": {
|
|
128
|
+
const src = safeHref(props?.url);
|
|
129
|
+
return src ? (
|
|
130
|
+
<a href={src} target="_blank" rel="noreferrer noopener" className="inline-flex items-center gap-1.5 text-primary underline underline-offset-2">
|
|
131
|
+
<Icon name="image" size={14} />
|
|
132
|
+
{props?.caption || props?.name || "Image"}
|
|
133
|
+
</a>
|
|
134
|
+
) : null;
|
|
135
|
+
}
|
|
136
|
+
case "table": {
|
|
137
|
+
const rows = tableRows(block.content);
|
|
138
|
+
if (!rows.length) return null;
|
|
139
|
+
return (
|
|
140
|
+
<div className="overflow-x-auto">
|
|
141
|
+
{/* raw: a doc's table is data drawn as it was typed, not a kit Table of records */}
|
|
142
|
+
<table className="text-xs">
|
|
143
|
+
<tbody>
|
|
144
|
+
{rows.map((r, i) => (
|
|
145
|
+
<tr key={i} className="border-b border-border last:border-0">
|
|
146
|
+
{r.map((cell, j) => (
|
|
147
|
+
<td key={j} className={cx("px-2 py-1 align-top", i === 0 && "font-medium")}>
|
|
148
|
+
<Inline content={cell} />
|
|
149
|
+
</td>
|
|
150
|
+
))}
|
|
151
|
+
</tr>
|
|
152
|
+
))}
|
|
153
|
+
</tbody>
|
|
154
|
+
</table>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
default: {
|
|
159
|
+
const empty = noText(block.content);
|
|
160
|
+
return (
|
|
161
|
+
<>
|
|
162
|
+
<p className={empty ? "min-h-5" : undefined}>
|
|
163
|
+
<Inline content={block.content} />
|
|
164
|
+
</p>
|
|
165
|
+
<Children blocks={block.children} />
|
|
166
|
+
</>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Consecutive list items of one kind become one list. */
|
|
173
|
+
function Blocks({ blocks }) {
|
|
174
|
+
const out = [];
|
|
175
|
+
let run = null;
|
|
176
|
+
(Array.isArray(blocks) ? blocks : []).forEach((b, i) => {
|
|
177
|
+
if (!b || typeof b !== "object") return;
|
|
178
|
+
const tag = LISTS[b.type];
|
|
179
|
+
if (tag) {
|
|
180
|
+
if (!run || run.type !== b.type) {
|
|
181
|
+
run = { type: b.type, tag, items: [], key: b.id ?? `l${i}` };
|
|
182
|
+
out.push(run);
|
|
183
|
+
}
|
|
184
|
+
run.items.push(b);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
run = null;
|
|
188
|
+
out.push(b);
|
|
189
|
+
});
|
|
190
|
+
return out.map((x, i) => {
|
|
191
|
+
if (x.items) {
|
|
192
|
+
const Tag = x.tag;
|
|
193
|
+
return (
|
|
194
|
+
<Tag key={x.key} className={cx("grid gap-0.5", LIST_CLASS[x.type])}>
|
|
195
|
+
{x.items.map((b, j) => (
|
|
196
|
+
<ListItem key={b.id ?? j} block={b} />
|
|
197
|
+
))}
|
|
198
|
+
</Tag>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
return <Block key={x.id ?? `b${i}`} block={x} />;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** A doc to read: `doc` is BlockNote JSON, or a plain string (one
|
|
206
|
+
* paragraph per line). Trailing empty paragraphs are dropped. */
|
|
207
|
+
export function CommentBody({ doc, className }) {
|
|
208
|
+
let blocks = typeof doc === "string" ? doc.split("\n").map((line) => ({ type: "paragraph", content: line })) : Array.isArray(doc) ? doc : [];
|
|
209
|
+
let end = blocks.length;
|
|
210
|
+
while (end > 0 && blocks[end - 1]?.type === "paragraph" && noText(blocks[end - 1].content) && !blocks[end - 1].children?.length) end--;
|
|
211
|
+
blocks = blocks.slice(0, end);
|
|
212
|
+
return (
|
|
213
|
+
<div className={cx("grid gap-1 break-words text-sm", className)}>
|
|
214
|
+
<Blocks blocks={blocks} />
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|