makersclaw 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +180 -0
- package/package.json +3 -2
- package/r/annotate.json +62 -0
- package/r/approval-request.json +52 -0
- package/r/audio-player.json +74 -0
- package/r/auth-form.json +55 -0
- package/r/board.json +10 -6
- package/r/calendar-view.json +105 -0
- package/r/cart.json +62 -0
- package/r/chart.json +83 -0
- package/r/chat.json +95 -0
- package/r/code-editor.json +94 -0
- package/r/comment-box.json +64 -0
- package/r/contact-section.json +53 -0
- package/r/core.json +205 -8
- package/r/csv-import.json +63 -0
- package/r/data-table.json +69 -0
- package/r/diagram.json +74 -0
- package/r/doc-editor.json +82 -0
- package/r/doc-page.json +61 -0
- package/r/email-render.json +73 -0
- package/r/faq.json +50 -0
- package/r/file-upload.json +54 -0
- package/r/flow-canvas.json +93 -0
- package/r/footer.json +52 -0
- package/r/gantt.json +70 -0
- package/r/job-panel.json +12 -7
- package/r/json-editor.json +66 -0
- package/r/map.json +89 -0
- package/r/menubar.json +52 -0
- package/r/mind-map.json +67 -0
- package/r/navigation-menu.json +52 -0
- package/r/order-detail.json +54 -0
- package/r/org-chart.json +66 -0
- package/r/page-builder.json +105 -0
- package/r/payment-methods.json +51 -0
- package/r/pdf-document.json +79 -0
- package/r/pdf-viewer.json +88 -0
- package/r/product-detail.json +76 -0
- package/r/product-grid.json +65 -0
- package/r/record-form.json +67 -0
- package/r/record-notes.json +55 -0
- package/r/registry.json +3411 -29
- package/r/search-dialog.json +51 -0
- package/r/settings-list.json +66 -0
- package/r/setup-checklist.json +51 -0
- package/r/share-dialog.json +52 -0
- package/r/sidebar.json +69 -0
- package/r/signature-pad.json +72 -0
- package/r/sketch-canvas.json +99 -0
- package/r/spreadsheet.json +90 -0
- package/r/stat-cards.json +66 -0
- package/r/task-list.json +63 -0
- package/r/task-model.json +98 -0
- package/r/testimonials.json +52 -0
- package/r/transaction-list.json +53 -0
- package/r/whiteboard.json +66 -0
- package/registry/blocks/annotate/README.md +179 -0
- package/registry/blocks/annotate/annotate-data.js +250 -0
- package/registry/blocks/annotate/annotate.jsx +646 -0
- package/registry/blocks/annotate/block.json +10 -0
- package/registry/blocks/annotate/demo.jsx +135 -0
- package/registry/blocks/annotate/index.js +15 -0
- package/registry/blocks/approval-request/README.md +116 -0
- package/registry/blocks/approval-request/approval-request.jsx +386 -0
- package/registry/blocks/approval-request/block.json +10 -0
- package/registry/blocks/approval-request/demo.jsx +127 -0
- package/registry/blocks/approval-request/index.js +4 -0
- package/registry/blocks/audio-player/README.md +167 -0
- package/registry/blocks/audio-player/audio-player.jsx +623 -0
- package/registry/blocks/audio-player/block.json +14 -0
- package/registry/blocks/audio-player/colors.js +109 -0
- package/registry/blocks/audio-player/demo.jsx +209 -0
- package/registry/blocks/audio-player/index.js +6 -0
- package/registry/blocks/audio-player/time.js +67 -0
- package/registry/blocks/audio-player/wavesurfer.js +9 -0
- package/registry/blocks/auth-form/README.md +126 -0
- package/registry/blocks/auth-form/auth-form.jsx +568 -0
- package/registry/blocks/auth-form/block.json +10 -0
- package/registry/blocks/auth-form/demo.jsx +131 -0
- package/registry/blocks/auth-form/index.js +3 -0
- package/registry/blocks/board/README.md +55 -5
- package/registry/blocks/board/block.json +2 -2
- package/registry/blocks/board/board.jsx +230 -86
- package/registry/blocks/board/demo.jsx +103 -24
- package/registry/blocks/calendar-view/README.md +180 -0
- package/registry/blocks/calendar-view/agenda.jsx +147 -0
- package/registry/blocks/calendar-view/block.json +76 -0
- package/registry/blocks/calendar-view/calendar-model.js +442 -0
- package/registry/blocks/calendar-view/calendar.jsx +627 -0
- package/registry/blocks/calendar-view/demo.jsx +195 -0
- package/registry/blocks/calendar-view/draft.jsx +49 -0
- package/registry/blocks/calendar-view/index.js +39 -0
- package/registry/blocks/calendar-view/month.jsx +346 -0
- package/registry/blocks/calendar-view/paint.js +69 -0
- package/registry/blocks/calendar-view/time-grid.jsx +527 -0
- package/registry/blocks/calendar-view/tray.jsx +87 -0
- package/registry/blocks/cart/README.md +146 -0
- package/registry/blocks/cart/block.json +10 -0
- package/registry/blocks/cart/cart.jsx +597 -0
- package/registry/blocks/cart/demo.jsx +98 -0
- package/registry/blocks/cart/index.js +4 -0
- package/registry/blocks/cart/money.js +28 -0
- package/registry/blocks/chart/README.md +316 -0
- package/registry/blocks/chart/block.json +10 -0
- package/registry/blocks/chart/cartesian.jsx +642 -0
- package/registry/blocks/chart/core.jsx +262 -0
- package/registry/blocks/chart/demo.jsx +357 -0
- package/registry/blocks/chart/heatmap.jsx +336 -0
- package/registry/blocks/chart/index.js +8 -0
- package/registry/blocks/chart/pie.jsx +245 -0
- package/registry/blocks/chart/sparkline.jsx +88 -0
- package/registry/blocks/chat/README.md +273 -0
- package/registry/blocks/chat/attachment.jsx +95 -0
- package/registry/blocks/chat/block.json +10 -0
- package/registry/blocks/chat/chat.jsx +132 -0
- package/registry/blocks/chat/composer.jsx +364 -0
- package/registry/blocks/chat/demo.jsx +578 -0
- package/registry/blocks/chat/header.jsx +34 -0
- package/registry/blocks/chat/index.js +9 -0
- package/registry/blocks/chat/message.jsx +450 -0
- package/registry/blocks/chat/scroller.jsx +247 -0
- package/registry/blocks/chat/text.jsx +104 -0
- package/registry/blocks/code-editor/README.md +210 -0
- package/registry/blocks/code-editor/block.json +22 -0
- package/registry/blocks/code-editor/code-editor.jsx +534 -0
- package/registry/blocks/code-editor/codemirror.js +38 -0
- package/registry/blocks/code-editor/demo.jsx +205 -0
- package/registry/blocks/code-editor/index.js +8 -0
- package/registry/blocks/code-editor/json.js +317 -0
- package/registry/blocks/code-editor/sql.js +136 -0
- package/registry/blocks/code-editor/text.js +101 -0
- package/registry/blocks/code-editor/theme.js +186 -0
- package/registry/blocks/comment-box/README.md +123 -0
- package/registry/blocks/comment-box/block.json +10 -0
- package/registry/blocks/comment-box/comment-body.jsx +217 -0
- package/registry/blocks/comment-box/comment-box.jsx +198 -0
- package/registry/blocks/comment-box/comment-time.jsx +77 -0
- package/registry/blocks/comment-box/demo.jsx +141 -0
- package/registry/blocks/comment-box/index.js +8 -0
- package/registry/blocks/contact-section/README.md +152 -0
- package/registry/blocks/contact-section/block.json +11 -0
- package/registry/blocks/contact-section/contact-section.jsx +509 -0
- package/registry/blocks/contact-section/demo.jsx +93 -0
- package/registry/blocks/contact-section/index.js +4 -0
- package/registry/blocks/csv-import/README.md +133 -0
- package/registry/blocks/csv-import/block.json +13 -0
- package/registry/blocks/csv-import/csv-import.jsx +479 -0
- package/registry/blocks/csv-import/demo.jsx +106 -0
- package/registry/blocks/csv-import/import.js +200 -0
- package/registry/blocks/csv-import/index.js +7 -0
- package/registry/blocks/data-table/README.md +386 -0
- package/registry/blocks/data-table/block.json +10 -0
- package/registry/blocks/data-table/data-table.jsx +1164 -0
- package/registry/blocks/data-table/demo.jsx +588 -0
- package/registry/blocks/data-table/index.js +5 -0
- package/registry/blocks/data-table/model.js +169 -0
- package/registry/blocks/diagram/README.md +108 -0
- package/registry/blocks/diagram/block.json +13 -0
- package/registry/blocks/diagram/demo.jsx +113 -0
- package/registry/blocks/diagram/diagram.jsx +481 -0
- package/registry/blocks/diagram/index.js +7 -0
- package/registry/blocks/diagram/mermaid.js +52 -0
- package/registry/blocks/diagram/palette.js +313 -0
- package/registry/blocks/diagram/source.js +98 -0
- package/registry/blocks/doc-editor/README.md +215 -0
- package/registry/blocks/doc-editor/block.json +15 -0
- package/registry/blocks/doc-editor/demo.jsx +225 -0
- package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
- package/registry/blocks/doc-editor/doc.js +309 -0
- package/registry/blocks/doc-editor/index.js +7 -0
- package/registry/blocks/doc-editor/schema.jsx +56 -0
- package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
- package/registry/blocks/doc-editor/theme.js +82 -0
- package/registry/blocks/doc-page/README.md +119 -0
- package/registry/blocks/doc-page/autosave.js +104 -0
- package/registry/blocks/doc-page/block.json +10 -0
- package/registry/blocks/doc-page/demo.jsx +137 -0
- package/registry/blocks/doc-page/doc-page.jsx +276 -0
- package/registry/blocks/doc-page/index.js +4 -0
- package/registry/blocks/email-render/README.md +151 -0
- package/registry/blocks/email-render/block.json +14 -0
- package/registry/blocks/email-render/demo.jsx +153 -0
- package/registry/blocks/email-render/doc-email.jsx +210 -0
- package/registry/blocks/email-render/email.jsx +221 -0
- package/registry/blocks/email-render/index.js +10 -0
- package/registry/blocks/email-render/render.js +50 -0
- package/registry/blocks/email-render/theme.js +215 -0
- package/registry/blocks/faq/README.md +101 -0
- package/registry/blocks/faq/block.json +11 -0
- package/registry/blocks/faq/demo.jsx +89 -0
- package/registry/blocks/faq/faq.jsx +220 -0
- package/registry/blocks/faq/index.js +4 -0
- package/registry/blocks/file-upload/README.md +138 -0
- package/registry/blocks/file-upload/block.json +10 -0
- package/registry/blocks/file-upload/demo.jsx +204 -0
- package/registry/blocks/file-upload/file-upload.jsx +635 -0
- package/registry/blocks/file-upload/index.js +4 -0
- package/registry/blocks/flow-canvas/README.md +420 -0
- package/registry/blocks/flow-canvas/block.json +13 -0
- package/registry/blocks/flow-canvas/board.js +819 -0
- package/registry/blocks/flow-canvas/chrome.jsx +649 -0
- package/registry/blocks/flow-canvas/context.jsx +35 -0
- package/registry/blocks/flow-canvas/demo.jsx +249 -0
- package/registry/blocks/flow-canvas/edges.jsx +107 -0
- package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
- package/registry/blocks/flow-canvas/index.js +41 -0
- package/registry/blocks/flow-canvas/nodes.jsx +392 -0
- package/registry/blocks/flow-canvas/theme.js +174 -0
- package/registry/blocks/footer/README.md +133 -0
- package/registry/blocks/footer/block.json +11 -0
- package/registry/blocks/footer/demo.jsx +119 -0
- package/registry/blocks/footer/footer.jsx +406 -0
- package/registry/blocks/footer/index.js +4 -0
- package/registry/blocks/gantt/README.md +220 -0
- package/registry/blocks/gantt/block.json +10 -0
- package/registry/blocks/gantt/demo.jsx +148 -0
- package/registry/blocks/gantt/gantt.jsx +923 -0
- package/registry/blocks/gantt/index.js +7 -0
- package/registry/blocks/gantt/rows.jsx +468 -0
- package/registry/blocks/gantt/schedule.js +278 -0
- package/registry/blocks/job-panel/README.md +80 -0
- package/registry/blocks/job-panel/block.json +3 -3
- package/registry/blocks/job-panel/demo.jsx +230 -3
- package/registry/blocks/job-panel/job-panel.jsx +169 -3
- package/registry/blocks/json-editor/README.md +133 -0
- package/registry/blocks/json-editor/block.json +10 -0
- package/registry/blocks/json-editor/demo.jsx +92 -0
- package/registry/blocks/json-editor/index.js +7 -0
- package/registry/blocks/json-editor/json-editor.jsx +305 -0
- package/registry/blocks/json-editor/json-tree.jsx +393 -0
- package/registry/blocks/json-editor/tree.js +225 -0
- package/registry/blocks/map/README.md +221 -0
- package/registry/blocks/map/block.json +14 -0
- package/registry/blocks/map/demo.jsx +201 -0
- package/registry/blocks/map/geo.js +198 -0
- package/registry/blocks/map/index.js +8 -0
- package/registry/blocks/map/list.jsx +128 -0
- package/registry/blocks/map/map-view.jsx +715 -0
- package/registry/blocks/map/maplibre.js +30 -0
- package/registry/blocks/map/marks.jsx +146 -0
- package/registry/blocks/map/theme.js +142 -0
- package/registry/blocks/menubar/README.md +109 -0
- package/registry/blocks/menubar/block.json +10 -0
- package/registry/blocks/menubar/demo.jsx +128 -0
- package/registry/blocks/menubar/index.js +4 -0
- package/registry/blocks/menubar/menubar.jsx +199 -0
- package/registry/blocks/mind-map/README.md +206 -0
- package/registry/blocks/mind-map/block.json +10 -0
- package/registry/blocks/mind-map/demo.jsx +103 -0
- package/registry/blocks/mind-map/index.js +31 -0
- package/registry/blocks/mind-map/mind-map.jsx +1125 -0
- package/registry/blocks/mind-map/topic.jsx +143 -0
- package/registry/blocks/mind-map/tree.js +645 -0
- package/registry/blocks/navigation-menu/README.md +124 -0
- package/registry/blocks/navigation-menu/block.json +10 -0
- package/registry/blocks/navigation-menu/demo.jsx +84 -0
- package/registry/blocks/navigation-menu/index.js +4 -0
- package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
- package/registry/blocks/order-detail/README.md +109 -0
- package/registry/blocks/order-detail/block.json +10 -0
- package/registry/blocks/order-detail/demo.jsx +88 -0
- package/registry/blocks/order-detail/index.js +4 -0
- package/registry/blocks/order-detail/order-detail.jsx +354 -0
- package/registry/blocks/org-chart/README.md +145 -0
- package/registry/blocks/org-chart/block.json +10 -0
- package/registry/blocks/org-chart/demo.jsx +94 -0
- package/registry/blocks/org-chart/index.js +7 -0
- package/registry/blocks/org-chart/org-chart.jsx +631 -0
- package/registry/blocks/org-chart/org.js +245 -0
- package/registry/blocks/org-chart/person.jsx +96 -0
- package/registry/blocks/page-builder/README.md +257 -0
- package/registry/blocks/page-builder/block.json +14 -0
- package/registry/blocks/page-builder/demo.jsx +145 -0
- package/registry/blocks/page-builder/grapes.js +18 -0
- package/registry/blocks/page-builder/index.js +11 -0
- package/registry/blocks/page-builder/page-builder.jsx +704 -0
- package/registry/blocks/page-builder/page-view.jsx +33 -0
- package/registry/blocks/page-builder/page.js +118 -0
- package/registry/blocks/page-builder/panels.jsx +588 -0
- package/registry/blocks/page-builder/sections.js +209 -0
- package/registry/blocks/page-builder/theme.js +87 -0
- package/registry/blocks/page-builder/thumbs.jsx +189 -0
- package/registry/blocks/page-builder/tokens.js +329 -0
- package/registry/blocks/payment-methods/README.md +104 -0
- package/registry/blocks/payment-methods/block.json +10 -0
- package/registry/blocks/payment-methods/demo.jsx +71 -0
- package/registry/blocks/payment-methods/index.js +4 -0
- package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
- package/registry/blocks/pdf-document/README.md +213 -0
- package/registry/blocks/pdf-document/block.json +13 -0
- package/registry/blocks/pdf-document/demo.jsx +136 -0
- package/registry/blocks/pdf-document/index.js +33 -0
- package/registry/blocks/pdf-document/money.js +83 -0
- package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
- package/registry/blocks/pdf-document/primitives.jsx +271 -0
- package/registry/blocks/pdf-document/quote.jsx +179 -0
- package/registry/blocks/pdf-document/theme.js +193 -0
- package/registry/blocks/pdf-viewer/README.md +191 -0
- package/registry/blocks/pdf-viewer/block.json +14 -0
- package/registry/blocks/pdf-viewer/demo.jsx +252 -0
- package/registry/blocks/pdf-viewer/helpers.js +270 -0
- package/registry/blocks/pdf-viewer/index.js +8 -0
- package/registry/blocks/pdf-viewer/notes.jsx +195 -0
- package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
- package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
- package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
- package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
- package/registry/blocks/product-detail/README.md +217 -0
- package/registry/blocks/product-detail/block.json +10 -0
- package/registry/blocks/product-detail/demo.jsx +233 -0
- package/registry/blocks/product-detail/index.js +7 -0
- package/registry/blocks/product-detail/price.jsx +115 -0
- package/registry/blocks/product-detail/product-detail.jsx +348 -0
- package/registry/blocks/product-detail/product-media.jsx +102 -0
- package/registry/blocks/product-detail/product-options.jsx +144 -0
- package/registry/blocks/product-grid/README.md +162 -0
- package/registry/blocks/product-grid/block.json +10 -0
- package/registry/blocks/product-grid/demo.jsx +255 -0
- package/registry/blocks/product-grid/index.js +5 -0
- package/registry/blocks/product-grid/product-card.jsx +232 -0
- package/registry/blocks/product-grid/product-grid.jsx +235 -0
- package/registry/blocks/record-form/README.md +196 -0
- package/registry/blocks/record-form/block.json +10 -0
- package/registry/blocks/record-form/demo.jsx +525 -0
- package/registry/blocks/record-form/index.js +4 -0
- package/registry/blocks/record-form/record-fields.jsx +457 -0
- package/registry/blocks/record-form/record-form.jsx +415 -0
- package/registry/blocks/record-form/rules.js +81 -0
- package/registry/blocks/record-notes/README.md +139 -0
- package/registry/blocks/record-notes/block.json +10 -0
- package/registry/blocks/record-notes/demo.jsx +179 -0
- package/registry/blocks/record-notes/index.js +4 -0
- package/registry/blocks/record-notes/record-notes.jsx +266 -0
- package/registry/blocks/search-dialog/README.md +108 -0
- package/registry/blocks/search-dialog/block.json +10 -0
- package/registry/blocks/search-dialog/demo.jsx +116 -0
- package/registry/blocks/search-dialog/index.js +3 -0
- package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
- package/registry/blocks/settings-list/README.md +171 -0
- package/registry/blocks/settings-list/block.json +10 -0
- package/registry/blocks/settings-list/demo.jsx +333 -0
- package/registry/blocks/settings-list/index.js +4 -0
- package/registry/blocks/settings-list/row-state.jsx +93 -0
- package/registry/blocks/settings-list/settings-list.jsx +349 -0
- package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
- package/registry/blocks/setup-checklist/README.md +142 -0
- package/registry/blocks/setup-checklist/block.json +10 -0
- package/registry/blocks/setup-checklist/demo.jsx +159 -0
- package/registry/blocks/setup-checklist/index.js +4 -0
- package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
- package/registry/blocks/share-dialog/README.md +113 -0
- package/registry/blocks/share-dialog/block.json +10 -0
- package/registry/blocks/share-dialog/demo.jsx +140 -0
- package/registry/blocks/share-dialog/index.js +3 -0
- package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
- package/registry/blocks/sidebar/README.md +190 -0
- package/registry/blocks/sidebar/block.json +43 -0
- package/registry/blocks/sidebar/demo.jsx +577 -0
- package/registry/blocks/sidebar/index.js +4 -0
- package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
- package/registry/blocks/sidebar/sidebar.jsx +864 -0
- package/registry/blocks/signature-pad/README.md +137 -0
- package/registry/blocks/signature-pad/block.json +13 -0
- package/registry/blocks/signature-pad/colors.js +115 -0
- package/registry/blocks/signature-pad/demo.jsx +94 -0
- package/registry/blocks/signature-pad/index.js +6 -0
- package/registry/blocks/signature-pad/pad.js +7 -0
- package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
- package/registry/blocks/signature-pad/signature.js +68 -0
- package/registry/blocks/sketch-canvas/README.md +280 -0
- package/registry/blocks/sketch-canvas/block.json +13 -0
- package/registry/blocks/sketch-canvas/demo.jsx +159 -0
- package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
- package/registry/blocks/sketch-canvas/index.js +9 -0
- package/registry/blocks/sketch-canvas/palette.js +226 -0
- package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
- package/registry/blocks/sketch-canvas/sketch.js +179 -0
- package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
- package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
- package/registry/blocks/sketch-canvas/stamps.js +104 -0
- package/registry/blocks/sketch-canvas/theme.js +131 -0
- package/registry/blocks/spreadsheet/README.md +307 -0
- package/registry/blocks/spreadsheet/block.json +13 -0
- package/registry/blocks/spreadsheet/cells.jsx +455 -0
- package/registry/blocks/spreadsheet/chrome.jsx +325 -0
- package/registry/blocks/spreadsheet/demo.jsx +177 -0
- package/registry/blocks/spreadsheet/grid.js +387 -0
- package/registry/blocks/spreadsheet/index.js +34 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
- package/registry/blocks/spreadsheet/types.js +473 -0
- package/registry/blocks/stat-cards/README.md +173 -0
- package/registry/blocks/stat-cards/block.json +10 -0
- package/registry/blocks/stat-cards/demo.jsx +257 -0
- package/registry/blocks/stat-cards/index.js +4 -0
- package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
- package/registry/blocks/stat-cards/usage.jsx +243 -0
- package/registry/blocks/task-list/README.md +176 -0
- package/registry/blocks/task-list/block.json +10 -0
- package/registry/blocks/task-list/demo.jsx +134 -0
- package/registry/blocks/task-list/index.js +5 -0
- package/registry/blocks/task-list/task-list.jsx +907 -0
- package/registry/blocks/task-model/README.md +455 -0
- package/registry/blocks/task-model/block.json +167 -0
- package/registry/blocks/task-model/changes.js +89 -0
- package/registry/blocks/task-model/dates.js +371 -0
- package/registry/blocks/task-model/demo.jsx +215 -0
- package/registry/blocks/task-model/dnd.jsx +240 -0
- package/registry/blocks/task-model/index.js +97 -0
- package/registry/blocks/task-model/model.js +919 -0
- package/registry/blocks/task-model/parts.jsx +449 -0
- package/registry/blocks/task-model/toolbar.jsx +271 -0
- package/registry/blocks/testimonials/README.md +139 -0
- package/registry/blocks/testimonials/block.json +11 -0
- package/registry/blocks/testimonials/demo.jsx +137 -0
- package/registry/blocks/testimonials/index.js +4 -0
- package/registry/blocks/testimonials/testimonials.jsx +430 -0
- package/registry/blocks/transaction-list/README.md +126 -0
- package/registry/blocks/transaction-list/block.json +10 -0
- package/registry/blocks/transaction-list/demo.jsx +79 -0
- package/registry/blocks/transaction-list/index.js +4 -0
- package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
- package/registry/blocks/whiteboard/README.md +179 -0
- package/registry/blocks/whiteboard/block.json +10 -0
- package/registry/blocks/whiteboard/demo.jsx +169 -0
- package/registry/blocks/whiteboard/index.js +6 -0
- package/registry/blocks/whiteboard/templates.js +150 -0
- package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
- package/src/cli.mjs +19 -6
- package/src/install.mjs +18 -0
- package/src/registry.mjs +38 -4
- package/src/shadcn.mjs +14 -1
- package/templates/next/files/README.md +145 -11
- package/templates/next/files/app/globals.css +55 -4
- package/templates/next/files/check/run.mjs +3 -3
- package/templates/next/files/components/ui/avatar.jsx +141 -0
- package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
- package/templates/next/files/components/ui/button-group.jsx +70 -0
- package/templates/next/files/components/ui/button.jsx +132 -12
- package/templates/next/files/components/ui/calendar.jsx +609 -0
- package/templates/next/files/components/ui/carousel.jsx +281 -0
- package/templates/next/files/components/ui/collapsible.jsx +208 -0
- package/templates/next/files/components/ui/combobox.jsx +608 -0
- package/templates/next/files/components/ui/command.jsx +577 -0
- package/templates/next/files/components/ui/context-menu.jsx +191 -0
- package/templates/next/files/components/ui/date-picker.jsx +360 -0
- package/templates/next/files/components/ui/distribution.jsx +117 -0
- package/templates/next/files/components/ui/feedback.jsx +143 -0
- package/templates/next/files/components/ui/field.jsx +115 -3
- package/templates/next/files/components/ui/file-input.jsx +234 -0
- package/templates/next/files/components/ui/icon.jsx +130 -8
- package/templates/next/files/components/ui/image.jsx +143 -0
- package/templates/next/files/components/ui/index.js +47 -2
- package/templates/next/files/components/ui/input-group.jsx +213 -0
- package/templates/next/files/components/ui/input-otp.jsx +170 -0
- package/templates/next/files/components/ui/item.jsx +206 -0
- package/templates/next/files/components/ui/menu.jsx +454 -82
- package/templates/next/files/components/ui/notice.jsx +126 -14
- package/templates/next/files/components/ui/pagination.jsx +156 -0
- package/templates/next/files/components/ui/popover.jsx +284 -0
- package/templates/next/files/components/ui/radio.jsx +193 -0
- package/templates/next/files/components/ui/rating.jsx +131 -0
- package/templates/next/files/components/ui/resizable.jsx +338 -0
- package/templates/next/files/components/ui/scroll-area.jsx +123 -0
- package/templates/next/files/components/ui/separator.jsx +119 -0
- package/templates/next/files/components/ui/sheet.jsx +96 -11
- package/templates/next/files/components/ui/slider.jsx +174 -0
- package/templates/next/files/components/ui/stat.jsx +574 -0
- package/templates/next/files/components/ui/steps.jsx +338 -0
- package/templates/next/files/components/ui/swatch.jsx +33 -0
- package/templates/next/files/components/ui/table.jsx +130 -0
- package/templates/next/files/components/ui/toast.jsx +440 -0
- package/templates/next/files/components/ui/toggle.jsx +195 -0
- package/templates/next/files/components/ui/tooltip.jsx +270 -0
- package/templates/next/template.json +264 -8
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// The email parts: react-email's components with the workspace theme laid
|
|
2
|
+
// on as concrete values. Server-safe (no hooks, no context): the same tree
|
|
3
|
+
// renders in the browser for a preview and on the server for a send.
|
|
4
|
+
//
|
|
5
|
+
// Every part takes `theme` (resolveEmailTheme(root) in the browser, or
|
|
6
|
+
// EMAIL_FALLBACK) and reads its colours from it. Styles are inline, which
|
|
7
|
+
// is what email clients keep; widths are a 600px column, the size every
|
|
8
|
+
// client draws well.
|
|
9
|
+
import { Body, Button, Column, Container, Head, Heading, Hr, Html, Img, Link, Preview, Row, Section, Text } from "@react-email/components";
|
|
10
|
+
import { EMAIL_FALLBACK, emailColor } from "./theme";
|
|
11
|
+
|
|
12
|
+
/** The width of an email's column, in px. */
|
|
13
|
+
export const EMAIL_WIDTH = 600;
|
|
14
|
+
|
|
15
|
+
const themeOf = (theme) => theme ?? EMAIL_FALLBACK;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The whole email: <html>, the preview line inboxes show after the
|
|
19
|
+
* subject, the page background and a centred 600px column.
|
|
20
|
+
*
|
|
21
|
+
* preview the preheader: up to ~110 characters shown in the inbox list
|
|
22
|
+
* lang the document's language ("en")
|
|
23
|
+
* title the <title> (some clients show it in a browser view)
|
|
24
|
+
*/
|
|
25
|
+
export function EmailLayout({ theme, preview, title, lang = "en", children }) {
|
|
26
|
+
const t = themeOf(theme);
|
|
27
|
+
return (
|
|
28
|
+
<Html lang={lang} dir="ltr">
|
|
29
|
+
<Head>
|
|
30
|
+
<meta name="color-scheme" content={t.scheme === "dark" ? "dark" : "light"} />
|
|
31
|
+
<meta name="supported-color-schemes" content={t.scheme === "dark" ? "dark" : "light"} />
|
|
32
|
+
{title ? <title>{title}</title> : null}
|
|
33
|
+
</Head>
|
|
34
|
+
{preview ? <Preview>{preview}</Preview> : null}
|
|
35
|
+
<Body
|
|
36
|
+
style={{
|
|
37
|
+
margin: 0,
|
|
38
|
+
padding: "32px 12px",
|
|
39
|
+
backgroundColor: emailColor(t, "background"),
|
|
40
|
+
color: emailColor(t, "foreground"),
|
|
41
|
+
fontFamily: t.font,
|
|
42
|
+
WebkitFontSmoothing: "antialiased",
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<Container style={{ width: "100%", maxWidth: `${EMAIL_WIDTH}px`, margin: "0 auto" }}>{children}</Container>
|
|
46
|
+
</Body>
|
|
47
|
+
</Html>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** A raised panel inside the column: the card colour, a hairline, the
|
|
52
|
+
* theme's corner. `padding` in px. */
|
|
53
|
+
export function EmailCard({ theme, padding = 32, children }) {
|
|
54
|
+
const t = themeOf(theme);
|
|
55
|
+
return (
|
|
56
|
+
<Section
|
|
57
|
+
style={{
|
|
58
|
+
backgroundColor: emailColor(t, "card"),
|
|
59
|
+
color: emailColor(t, "card-foreground"),
|
|
60
|
+
border: `1px solid ${emailColor(t, "border")}`,
|
|
61
|
+
borderRadius: t.radius,
|
|
62
|
+
padding: `${padding}px`,
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</Section>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The brand line at the top: a logo or the name, linked to the site.
|
|
72
|
+
* band "none" (default: on the page background) · "primary" · "muted"
|
|
73
|
+
* · "card" — a filled strip; the words take the matching
|
|
74
|
+
* foreground
|
|
75
|
+
* align "left" (default) · "center"
|
|
76
|
+
*/
|
|
77
|
+
export function EmailHeader({ theme, name, logoUrl, logoAlt, logoHeight = 28, href, band = "none", align = "left", tagline }) {
|
|
78
|
+
const t = themeOf(theme);
|
|
79
|
+
const filled = band && band !== "none";
|
|
80
|
+
const fill = filled ? emailColor(t, band) : undefined;
|
|
81
|
+
const ink = filled ? emailColor(t, band === "card" ? "card-foreground" : `${band}-foreground`) : emailColor(t, "foreground");
|
|
82
|
+
const mark = logoUrl ? (
|
|
83
|
+
<Img src={logoUrl} alt={logoAlt || name || ""} height={logoHeight} style={{ display: align === "center" ? "inline-block" : "block", height: `${logoHeight}px`, width: "auto", border: 0 }} />
|
|
84
|
+
) : (
|
|
85
|
+
<Text style={{ margin: 0, fontFamily: t.fontDisplay, fontSize: "18px", lineHeight: "24px", fontWeight: 700, letterSpacing: "-0.01em", color: ink }}>{name}</Text>
|
|
86
|
+
);
|
|
87
|
+
return (
|
|
88
|
+
<Section
|
|
89
|
+
style={{
|
|
90
|
+
padding: filled ? "18px 24px" : "0 4px 20px",
|
|
91
|
+
backgroundColor: fill,
|
|
92
|
+
borderRadius: filled ? t.radius : undefined,
|
|
93
|
+
marginBottom: filled ? "16px" : undefined,
|
|
94
|
+
textAlign: align,
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
<Row>
|
|
98
|
+
<Column style={{ textAlign: align }}>
|
|
99
|
+
{href ? (
|
|
100
|
+
<Link href={href} style={{ color: ink, textDecoration: "none" }}>
|
|
101
|
+
{mark}
|
|
102
|
+
</Link>
|
|
103
|
+
) : (
|
|
104
|
+
mark
|
|
105
|
+
)}
|
|
106
|
+
{tagline ? (
|
|
107
|
+
<Text style={{ margin: "4px 0 0", fontSize: "13px", lineHeight: "18px", color: filled ? ink : emailColor(t, "muted-foreground"), opacity: filled ? 0.8 : 1 }}>{tagline}</Text>
|
|
108
|
+
) : null}
|
|
109
|
+
</Column>
|
|
110
|
+
</Row>
|
|
111
|
+
</Section>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The small print at the bottom: a line or two about why the reader gets
|
|
117
|
+
* this, the sender's postal address (the law in most places wants it) and
|
|
118
|
+
* the unsubscribe link.
|
|
119
|
+
* note "You get this because you signed up at acme.com."
|
|
120
|
+
* address "Acme, 12 Market St, Leeds LS1 4AB"
|
|
121
|
+
* unsubscribeUrl the address your sender fills in ("{{unsubscribe_url}}")
|
|
122
|
+
* links [{ label, href }] — a row above the small print
|
|
123
|
+
*/
|
|
124
|
+
export function EmailFooter({ theme, note, address, unsubscribeUrl, unsubscribeLabel = "Unsubscribe", links = [], align = "center" }) {
|
|
125
|
+
const t = themeOf(theme);
|
|
126
|
+
const muted = emailColor(t, "muted-foreground");
|
|
127
|
+
const small = { margin: "0 0 6px", fontSize: "12px", lineHeight: "18px", color: muted };
|
|
128
|
+
return (
|
|
129
|
+
<Section style={{ padding: "24px 16px 8px", textAlign: align }}>
|
|
130
|
+
{links.length ? (
|
|
131
|
+
<Text style={{ ...small, marginBottom: "12px", fontSize: "13px" }}>
|
|
132
|
+
{links.map((l, i) => (
|
|
133
|
+
<span key={`${l.href}-${i}`}>
|
|
134
|
+
{i ? <span style={{ padding: "0 8px" }}>·</span> : null}
|
|
135
|
+
<Link href={l.href} style={{ color: muted, textDecoration: "underline" }}>
|
|
136
|
+
{l.label}
|
|
137
|
+
</Link>
|
|
138
|
+
</span>
|
|
139
|
+
))}
|
|
140
|
+
</Text>
|
|
141
|
+
) : null}
|
|
142
|
+
{note ? <Text style={small}>{note}</Text> : null}
|
|
143
|
+
{address ? <Text style={small}>{address}</Text> : null}
|
|
144
|
+
{unsubscribeUrl ? (
|
|
145
|
+
<Text style={small}>
|
|
146
|
+
<Link href={unsubscribeUrl} style={{ color: muted, textDecoration: "underline" }}>
|
|
147
|
+
{unsubscribeLabel}
|
|
148
|
+
</Link>
|
|
149
|
+
</Text>
|
|
150
|
+
) : null}
|
|
151
|
+
</Section>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** A button that works in every client (a padded link, no images).
|
|
156
|
+
* tone "primary" (default) · "secondary" · "foreground". */
|
|
157
|
+
export function EmailButton({ theme, href, tone = "primary", align = "left", children }) {
|
|
158
|
+
const t = themeOf(theme);
|
|
159
|
+
const fill = emailColor(t, tone === "foreground" ? "foreground" : tone);
|
|
160
|
+
const ink = emailColor(t, tone === "foreground" ? "background" : `${tone}-foreground`);
|
|
161
|
+
return (
|
|
162
|
+
<Section style={{ textAlign: align, margin: "8px 0 24px" }}>
|
|
163
|
+
<Button
|
|
164
|
+
href={href || "#"}
|
|
165
|
+
style={{
|
|
166
|
+
display: "inline-block",
|
|
167
|
+
backgroundColor: fill,
|
|
168
|
+
color: ink,
|
|
169
|
+
borderRadius: t.radius,
|
|
170
|
+
padding: "12px 22px",
|
|
171
|
+
fontSize: "15px",
|
|
172
|
+
lineHeight: "20px",
|
|
173
|
+
fontWeight: 600,
|
|
174
|
+
textDecoration: "none",
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
{children}
|
|
178
|
+
</Button>
|
|
179
|
+
</Section>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const HEADING_SIZES = { 1: ["28px", "34px"], 2: ["22px", "28px"], 3: ["18px", "24px"] };
|
|
184
|
+
|
|
185
|
+
/** A heading in the display face. level 1 · 2 · 3. */
|
|
186
|
+
export function EmailHeading({ theme, level = 2, align, children }) {
|
|
187
|
+
const t = themeOf(theme);
|
|
188
|
+
const [size, line] = HEADING_SIZES[level] ?? HEADING_SIZES[2];
|
|
189
|
+
return (
|
|
190
|
+
<Heading
|
|
191
|
+
as={`h${Math.min(3, Math.max(1, level))}`}
|
|
192
|
+
style={{ margin: level === 1 ? "0 0 16px" : "24px 0 12px", fontFamily: t.fontDisplay, fontSize: size, lineHeight: line, fontWeight: 700, letterSpacing: "-0.015em", color: emailColor(t, "card-foreground"), textAlign: align }}
|
|
193
|
+
>
|
|
194
|
+
{children}
|
|
195
|
+
</Heading>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** A paragraph. `muted` for secondary words, `size` "md" (16px) · "sm". */
|
|
200
|
+
export function EmailText({ theme, muted = false, size = "md", align, children }) {
|
|
201
|
+
const t = themeOf(theme);
|
|
202
|
+
return (
|
|
203
|
+
<Text
|
|
204
|
+
style={{
|
|
205
|
+
margin: "0 0 16px",
|
|
206
|
+
fontSize: size === "sm" ? "14px" : "16px",
|
|
207
|
+
lineHeight: size === "sm" ? "22px" : "26px",
|
|
208
|
+
color: emailColor(t, muted ? "muted-foreground" : "card-foreground"),
|
|
209
|
+
textAlign: align,
|
|
210
|
+
}}
|
|
211
|
+
>
|
|
212
|
+
{children}
|
|
213
|
+
</Text>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** A hairline. */
|
|
218
|
+
export function EmailDivider({ theme }) {
|
|
219
|
+
const t = themeOf(theme);
|
|
220
|
+
return <Hr style={{ border: 0, borderTop: `1px solid ${emailColor(t, "border")}`, margin: "24px 0" }} />;
|
|
221
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// The EmailRender block — `makersclaw add email-render`. Fixed: compose it
|
|
2
|
+
// through its exports (README.md beside this file). The door to
|
|
3
|
+
// react-email: themed email parts, a doc-editor document as email markup,
|
|
4
|
+
// and renderEmail() → { html, text }. Server-safe: the same tree renders
|
|
5
|
+
// in a browser preview and in a server send. Blocks built on this one
|
|
6
|
+
// (newsletter-builder…) import it, never @react-email/* directly.
|
|
7
|
+
export { EmailLayout, EmailCard, EmailHeader, EmailFooter, EmailButton, EmailHeading, EmailText, EmailDivider, EMAIL_WIDTH } from "./email";
|
|
8
|
+
export { DocEmail, fieldText } from "./doc-email";
|
|
9
|
+
export { renderEmail, emailPlainText } from "./render";
|
|
10
|
+
export { EMAIL_TOKENS, EMAIL_FALLBACK, resolveEmailTheme, emailColor, emailFontStack, emailThemeKey, luminance, toHex } from "./theme";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// renderEmail — a react-email tree → the HTML and the plain text a sender
|
|
2
|
+
// needs. The one door to @react-email/render; blocks built on this one
|
|
3
|
+
// never import it.
|
|
4
|
+
//
|
|
5
|
+
// Works in the browser (a live preview) and on the server (a send). It is
|
|
6
|
+
// async: react-email renders through React's streaming renderer, so an
|
|
7
|
+
// image or a font can load before the HTML is final.
|
|
8
|
+
import { render, toPlainText } from "@react-email/render";
|
|
9
|
+
|
|
10
|
+
// The plain-text part reads like the email: headings in their own case
|
|
11
|
+
// (html-to-text shouts them by default) and tables as rows and columns.
|
|
12
|
+
const TEXT_OPTIONS = {
|
|
13
|
+
selectors: [
|
|
14
|
+
{ selector: "h1", options: { uppercase: false } },
|
|
15
|
+
{ selector: "h2", options: { uppercase: false } },
|
|
16
|
+
{ selector: "h3", options: { uppercase: false } },
|
|
17
|
+
{ selector: "table", format: "dataTable" },
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* `await renderEmail(<EmailLayout …/>)` →
|
|
23
|
+
* { ok: true, html, text } html: a full <!DOCTYPE html> document
|
|
24
|
+
* { ok: false, error } a render that threw, in words
|
|
25
|
+
*
|
|
26
|
+
* `pretty: true` indents the HTML (slower; for reading, not for sending).
|
|
27
|
+
*/
|
|
28
|
+
export async function renderEmail(element, { pretty = false } = {}) {
|
|
29
|
+
try {
|
|
30
|
+
const html = await render(element, { pretty });
|
|
31
|
+
let text = "";
|
|
32
|
+
try {
|
|
33
|
+
text = toPlainText(html, TEXT_OPTIONS);
|
|
34
|
+
} catch {
|
|
35
|
+
text = "";
|
|
36
|
+
}
|
|
37
|
+
return { ok: true, html, text };
|
|
38
|
+
} catch (e) {
|
|
39
|
+
return { ok: false, error: e?.message ? `The email could not be drawn: ${e.message}` : "The email could not be drawn." };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The plain-text part for HTML you already have. */
|
|
44
|
+
export function emailPlainText(html) {
|
|
45
|
+
try {
|
|
46
|
+
return toPlainText(String(html ?? ""), TEXT_OPTIONS);
|
|
47
|
+
} catch {
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// The email's theme: the workspace tokens, resolved to concrete values.
|
|
2
|
+
//
|
|
3
|
+
// Why: an email is read in Gmail, Outlook and Apple Mail, which never see
|
|
4
|
+
// the app's stylesheet and mostly ignore CSS variables. So an email cannot
|
|
5
|
+
// say var(--color-primary) the way a page does. At render time we read
|
|
6
|
+
// what each token IS where the editor sits (its light or dark scheme, any
|
|
7
|
+
// [data-theme] scope) and hand the email plain hex values. The source of
|
|
8
|
+
// truth stays the theme; the email carries a copy made when it is rendered.
|
|
9
|
+
//
|
|
10
|
+
// resolveEmailTheme(root) browser: read the tokens at `root`
|
|
11
|
+
// EMAIL_FALLBACK a neutral light theme, for the server or a
|
|
12
|
+
// test, when there is no page to read
|
|
13
|
+
// emailColor(theme, name) a token name ("primary") → its hex
|
|
14
|
+
//
|
|
15
|
+
// A theme is plain data, so it can travel to the server with a send:
|
|
16
|
+
// { colors: { background, foreground, primary, … }, font, fontDisplay,
|
|
17
|
+
// fontMono, radius, scheme }
|
|
18
|
+
|
|
19
|
+
/** The tokens an email may name, in the order a picker would show them. */
|
|
20
|
+
export const EMAIL_TOKENS = [
|
|
21
|
+
"background",
|
|
22
|
+
"foreground",
|
|
23
|
+
"card",
|
|
24
|
+
"card-foreground",
|
|
25
|
+
"primary",
|
|
26
|
+
"primary-foreground",
|
|
27
|
+
"secondary",
|
|
28
|
+
"secondary-foreground",
|
|
29
|
+
"muted",
|
|
30
|
+
"muted-foreground",
|
|
31
|
+
"accent",
|
|
32
|
+
"accent-foreground",
|
|
33
|
+
"border",
|
|
34
|
+
"destructive",
|
|
35
|
+
"success",
|
|
36
|
+
"warning",
|
|
37
|
+
"info",
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// Web-safe tails for each face: most clients only have these installed.
|
|
41
|
+
const SANS_TAIL = ["-apple-system", "BlinkMacSystemFont", "Segoe UI", "Helvetica", "Arial", "sans-serif"];
|
|
42
|
+
const MONO_TAIL = ["SFMono-Regular", "Menlo", "Consolas", "monospace"];
|
|
43
|
+
|
|
44
|
+
const byte = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0");
|
|
45
|
+
|
|
46
|
+
/** [r, g, b] → "#rrggbb". */
|
|
47
|
+
export function toHex([r, g, b]) {
|
|
48
|
+
return "#" + byte(r) + byte(g) + byte(b);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const grey = (v) => toHex([v, v, v]);
|
|
52
|
+
|
|
53
|
+
/** A neutral light theme: what an email wears when no page can be read
|
|
54
|
+
* (the server, a test). Greys only, so it never claims a brand. */
|
|
55
|
+
export const EMAIL_FALLBACK = Object.freeze({
|
|
56
|
+
colors: Object.freeze({
|
|
57
|
+
background: grey(244),
|
|
58
|
+
foreground: grey(23),
|
|
59
|
+
card: grey(255),
|
|
60
|
+
"card-foreground": grey(23),
|
|
61
|
+
primary: grey(23),
|
|
62
|
+
"primary-foreground": grey(250),
|
|
63
|
+
secondary: grey(240),
|
|
64
|
+
"secondary-foreground": grey(23),
|
|
65
|
+
muted: grey(245),
|
|
66
|
+
"muted-foreground": grey(107),
|
|
67
|
+
accent: grey(240),
|
|
68
|
+
"accent-foreground": grey(23),
|
|
69
|
+
border: grey(226),
|
|
70
|
+
destructive: toHex([185, 28, 28]),
|
|
71
|
+
success: toHex([21, 112, 58]),
|
|
72
|
+
warning: toHex([154, 74, 6]),
|
|
73
|
+
info: toHex([29, 78, 216]),
|
|
74
|
+
}),
|
|
75
|
+
font: SANS_TAIL.map(quoteFamily).join(", "),
|
|
76
|
+
fontDisplay: SANS_TAIL.map(quoteFamily).join(", "),
|
|
77
|
+
fontMono: MONO_TAIL.map(quoteFamily).join(", "),
|
|
78
|
+
radius: "8px",
|
|
79
|
+
scheme: "light",
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/** A token name → its hex in `theme`, else the fallback's. A value that is
|
|
83
|
+
* not a token name ("" or unknown) gives `fallback`. */
|
|
84
|
+
export function emailColor(theme, name, fallback = "") {
|
|
85
|
+
const colors = theme?.colors ?? EMAIL_FALLBACK.colors;
|
|
86
|
+
return colors[name] ?? EMAIL_FALLBACK.colors[name] ?? fallback;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Quote a family name that needs it ("Segoe UI" → '"Segoe UI"'). */
|
|
90
|
+
function quoteFamily(name) {
|
|
91
|
+
const n = String(name).trim().replace(/^["']|["']$/g, "");
|
|
92
|
+
return /^[a-z-]+$/i.test(n) ? n : `"${n}"`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** A computed font-family → an email-safe stack: the theme's own families
|
|
96
|
+
* first (a reader who has them sees them), next/font's hashed aliases
|
|
97
|
+
* ("__Inter_a1b2") dropped, a web-safe tail added. */
|
|
98
|
+
export function emailFontStack(computed, tail = SANS_TAIL) {
|
|
99
|
+
const seen = new Set();
|
|
100
|
+
const out = [];
|
|
101
|
+
for (const raw of String(computed ?? "").split(",")) {
|
|
102
|
+
const name = raw.trim().replace(/^["']|["']$/g, "");
|
|
103
|
+
if (!name || name.startsWith("__") || /^var\(/.test(name)) continue;
|
|
104
|
+
if (["system-ui", "ui-sans-serif", "ui-monospace"].includes(name)) continue;
|
|
105
|
+
const key = name.toLowerCase();
|
|
106
|
+
if (seen.has(key)) continue;
|
|
107
|
+
seen.add(key);
|
|
108
|
+
out.push(quoteFamily(name));
|
|
109
|
+
}
|
|
110
|
+
for (const name of tail) {
|
|
111
|
+
const key = name.toLowerCase();
|
|
112
|
+
if (seen.has(key)) continue;
|
|
113
|
+
seen.add(key);
|
|
114
|
+
out.push(quoteFamily(name));
|
|
115
|
+
}
|
|
116
|
+
return out.join(", ");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Relative luminance of "#rrggbb" (0 black … 1 white). */
|
|
120
|
+
export function luminance(hex) {
|
|
121
|
+
const m = /^#?([0-9a-f]{6})$/i.exec(String(hex ?? ""));
|
|
122
|
+
if (!m) return 1;
|
|
123
|
+
const n = parseInt(m[1], 16);
|
|
124
|
+
const lin = (c) => {
|
|
125
|
+
const s = c / 255;
|
|
126
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
127
|
+
};
|
|
128
|
+
return 0.2126 * lin((n >> 16) & 255) + 0.7152 * lin((n >> 8) & 255) + 0.0722 * lin(n & 255);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Browser only: the theme as it is painted at `root` (default: the body).
|
|
133
|
+
*
|
|
134
|
+
* Each colour goes through a hidden probe (`color: var(--color-x)`), so
|
|
135
|
+
* light-dark(), color-mix() and a [data-theme] scope resolve exactly as
|
|
136
|
+
* the app paints them. A 1×1 canvas then turns the computed colour into
|
|
137
|
+
* bytes whatever syntax the browser wrote it in; a colour with alpha is
|
|
138
|
+
* laid over the background first, because email has no transparency to
|
|
139
|
+
* rely on. Faces and the corner radius are read the same way.
|
|
140
|
+
*/
|
|
141
|
+
export function resolveEmailTheme(root) {
|
|
142
|
+
if (typeof document === "undefined") return EMAIL_FALLBACK;
|
|
143
|
+
const host = root ?? document.body;
|
|
144
|
+
if (!host) return EMAIL_FALLBACK;
|
|
145
|
+
const probe = document.createElement("span");
|
|
146
|
+
probe.setAttribute("aria-hidden", "true");
|
|
147
|
+
probe.style.position = "absolute";
|
|
148
|
+
probe.style.visibility = "hidden";
|
|
149
|
+
probe.style.pointerEvents = "none";
|
|
150
|
+
host.appendChild(probe);
|
|
151
|
+
const canvas = document.createElement("canvas");
|
|
152
|
+
canvas.width = 1;
|
|
153
|
+
canvas.height = 1;
|
|
154
|
+
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
155
|
+
const colors = {};
|
|
156
|
+
const read = (token, under) => {
|
|
157
|
+
probe.style.color = "";
|
|
158
|
+
probe.style.color = `var(--color-${token})`;
|
|
159
|
+
const computed = getComputedStyle(probe).color;
|
|
160
|
+
if (!computed || !ctx) return null;
|
|
161
|
+
ctx.clearRect(0, 0, 1, 1);
|
|
162
|
+
if (under) {
|
|
163
|
+
ctx.fillStyle = under;
|
|
164
|
+
ctx.fillRect(0, 0, 1, 1);
|
|
165
|
+
}
|
|
166
|
+
ctx.fillStyle = "transparent";
|
|
167
|
+
ctx.fillStyle = computed;
|
|
168
|
+
ctx.fillRect(0, 0, 1, 1);
|
|
169
|
+
const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
|
|
170
|
+
if (a === 0) return null;
|
|
171
|
+
return toHex([r, g, b]);
|
|
172
|
+
};
|
|
173
|
+
let theme = EMAIL_FALLBACK;
|
|
174
|
+
try {
|
|
175
|
+
const bg = read("background", null) ?? EMAIL_FALLBACK.colors.background;
|
|
176
|
+
colors.background = bg;
|
|
177
|
+
for (const token of EMAIL_TOKENS) {
|
|
178
|
+
if (token === "background") continue;
|
|
179
|
+
colors[token] = read(token, bg) ?? EMAIL_FALLBACK.colors[token];
|
|
180
|
+
}
|
|
181
|
+
probe.style.fontFamily = "var(--theme-font-sans)";
|
|
182
|
+
const sans = getComputedStyle(probe).fontFamily;
|
|
183
|
+
probe.style.fontFamily = "var(--theme-font-display)";
|
|
184
|
+
const display = getComputedStyle(probe).fontFamily;
|
|
185
|
+
probe.style.fontFamily = "var(--theme-font-mono)";
|
|
186
|
+
const mono = getComputedStyle(probe).fontFamily;
|
|
187
|
+
probe.style.borderRadius = "var(--theme-radius)";
|
|
188
|
+
const radius = getComputedStyle(probe).borderTopLeftRadius;
|
|
189
|
+
const px = Number.parseFloat(radius);
|
|
190
|
+
theme = {
|
|
191
|
+
colors,
|
|
192
|
+
font: emailFontStack(sans),
|
|
193
|
+
fontDisplay: emailFontStack(display || sans),
|
|
194
|
+
fontMono: emailFontStack(mono, MONO_TAIL),
|
|
195
|
+
radius: Number.isFinite(px) ? `${Math.min(24, Math.round(px))}px` : EMAIL_FALLBACK.radius,
|
|
196
|
+
scheme: luminance(bg) < 0.35 ? "dark" : "light",
|
|
197
|
+
};
|
|
198
|
+
} finally {
|
|
199
|
+
probe.remove();
|
|
200
|
+
}
|
|
201
|
+
return theme;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** A stable fingerprint of a theme: equal strings, nothing to re-render. */
|
|
205
|
+
export function emailThemeKey(theme) {
|
|
206
|
+
const t = theme ?? EMAIL_FALLBACK;
|
|
207
|
+
return [
|
|
208
|
+
...Object.keys(t.colors ?? {})
|
|
209
|
+
.sort()
|
|
210
|
+
.map((k) => `${k}=${t.colors[k]}`),
|
|
211
|
+
t.font,
|
|
212
|
+
t.fontDisplay,
|
|
213
|
+
t.radius,
|
|
214
|
+
].join(";");
|
|
215
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# FAQ
|
|
2
|
+
|
|
3
|
+
A marketing section of questions and answers. Three layouts over the
|
|
4
|
+
same rows: an **accordion** built on the kit's `Accordion` (one open at a
|
|
5
|
+
time, or several; arrow keys move between questions, and find-in-page
|
|
6
|
+
opens a closed one), a **grid** of cards with an optional icon each, and
|
|
7
|
+
a plain **list** with every answer shown. The title sits above the
|
|
8
|
+
questions or beside them, and an optional "need more help?" call to
|
|
9
|
+
action closes the section. It is a full-width section: it pads itself
|
|
10
|
+
and centres its content.
|
|
11
|
+
|
|
12
|
+
```jsx
|
|
13
|
+
import { Faq } from "../components/blocks/faq"; // a Makersclaw app ("./blocks/faq" from components/)
|
|
14
|
+
import { Faq } from "@/components/makersclaw/blocks/faq"; // a shadcn project
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
It is a client component: render it from a `"use client"` component.
|
|
18
|
+
|
|
19
|
+
## The data
|
|
20
|
+
|
|
21
|
+
`items` is the questions, in order:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
{
|
|
25
|
+
question: "How long is the free trial?", // required; a row without one is skipped
|
|
26
|
+
answer: "Fourteen days, with every feature on.", // a string, or a node (paragraphs, a link)
|
|
27
|
+
id?: "trial", // a stable key; the accordion's open value
|
|
28
|
+
icon?: "clock", // a name from the kit's Icon: a badge in the grid, a glyph otherwise
|
|
29
|
+
anchor?: "trial", // grid and list: the element id, for /pricing#trial
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
- `items` — the questions, as above. Required.
|
|
36
|
+
- `layout` — `accordion` (default) · `grid` · `list`.
|
|
37
|
+
- `kicker`, `title`, `description` — the header. `title` defaults to
|
|
38
|
+
"Frequently asked questions".
|
|
39
|
+
- `titlePosition` — `top` (default, centred) · `start` (the header and
|
|
40
|
+
the call to action in a column beside the questions from `lg` up).
|
|
41
|
+
- `columns` — the grid: `1` · `2` · `3`. Default `3`, or `2` when the
|
|
42
|
+
title is beside it. One column on a phone.
|
|
43
|
+
- `look` — the grid's cards: `card` (default) · `plain` (no box, a rule
|
|
44
|
+
under each question).
|
|
45
|
+
- `type` — the accordion: `single` (default: opening one closes the
|
|
46
|
+
rest) · `multiple`.
|
|
47
|
+
- `defaultOpen` — the accordion's open question at first: an `id` (or
|
|
48
|
+
the index as a string) when single, an array of them when multiple.
|
|
49
|
+
- `open`, `onOpenChange(next)` — control the accordion yourself: `next`
|
|
50
|
+
is an id or `null` when single, an array when multiple.
|
|
51
|
+
- `cta` — `{ title?, body?, label?, href?, onClick?, icon? }`: "Still
|
|
52
|
+
have a question?" and one primary button. Under the questions, or under
|
|
53
|
+
the title when it is beside them.
|
|
54
|
+
- `loading` — `true` draws placeholder rows or cards (`aria-busy`).
|
|
55
|
+
- `empty` — `{ title?, body? }` when there are no `items`. Default "No
|
|
56
|
+
questions yet".
|
|
57
|
+
- `label` — what a screen reader calls the section. Default the title.
|
|
58
|
+
- `className` — the section's spacing and width. Never colour.
|
|
59
|
+
|
|
60
|
+
## Example
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
// components/PricingFaq.jsx
|
|
64
|
+
"use client";
|
|
65
|
+
import { Faq } from "./blocks/faq";
|
|
66
|
+
|
|
67
|
+
const FAQS = [
|
|
68
|
+
{ id: "trial", question: "How long is the free trial?", answer: "Fourteen days, with every feature on." },
|
|
69
|
+
{ id: "seats", question: "Do I pay per person?", answer: "Plans include five seats; each extra seat is $8 a month." },
|
|
70
|
+
{ id: "cancel", question: "What happens if I cancel?", answer: "Your workspace stays readable for 90 days." },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
export default function PricingFaq() {
|
|
74
|
+
return (
|
|
75
|
+
<Faq
|
|
76
|
+
items={FAQS}
|
|
77
|
+
defaultOpen="trial"
|
|
78
|
+
description="The things people ask before they sign up."
|
|
79
|
+
cta={{ title: "Still have a question?", label: "Send us a note", href: "/contact", icon: "mail" }}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## What it will not do
|
|
86
|
+
|
|
87
|
+
- Search or filter questions, or group them under categories: a help
|
|
88
|
+
centre is a page of its own.
|
|
89
|
+
- Render Markdown: pass a node for rich answers.
|
|
90
|
+
- Add FAQ structured data (JSON-LD) to the page: that belongs in your
|
|
91
|
+
page's metadata.
|
|
92
|
+
|
|
93
|
+
A section it cannot be is your own component in `components/`, built
|
|
94
|
+
from the kit — not an edit to this block. Its files are fixed: `npm run
|
|
95
|
+
check` refuses a change, and `makersclaw add faq` restores them.
|
|
96
|
+
|
|
97
|
+
## Credits
|
|
98
|
+
|
|
99
|
+
Layouts ported from Creative Tim UI's FAQ blocks
|
|
100
|
+
(https://github.com/creativetimofficial/ui, MIT), rewritten on the
|
|
101
|
+
Makersclaw kit.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "faq",
|
|
3
|
+
"title": "FAQ",
|
|
4
|
+
"description": "A marketing section of questions and answers: an accordion (one open at a time, or several), a grid of cards with optional icons, or a plain list with every answer shown; the title above or beside them, and an optional \"need more help?\" call to action. Loading and empty states.",
|
|
5
|
+
"useWhen": "The questions section of a public page: a landing page, pricing, a help centre's front page, a product page. Not for a searchable help centre with articles and categories, or collapsible settings inside an app (use the kit's Accordion).",
|
|
6
|
+
"tags": ["faq", "questions", "answers", "accordion", "help", "support", "marketing", "landing page", "pricing", "q&a"],
|
|
7
|
+
"exports": ["Faq"],
|
|
8
|
+
"files": ["index.js", "faq.jsx"],
|
|
9
|
+
"requires": [],
|
|
10
|
+
"frame": "bleed"
|
|
11
|
+
}
|