@sableui/react 0.6.1 → 0.7.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/AGENTS.md +2 -2
- package/CHANGELOG.md +285 -0
- package/CONTRIBUTING.md +16 -10
- package/DESIGN.md +3 -3
- package/README.md +3 -3
- package/bin/sable-lint.mjs +18 -0
- package/bin/sable.mjs +470 -62
- package/dist/blocks/api-keys-block.js +44 -0
- package/dist/blocks/api-keys-block.meta.js +21 -0
- package/dist/blocks/chat-thread-block.js +17 -0
- package/dist/blocks/chat-thread-block.meta.js +20 -0
- package/dist/blocks/command-palette-block.js +24 -0
- package/dist/blocks/command-palette-block.meta.js +21 -0
- package/dist/blocks/cta-band-block.js +27 -0
- package/dist/blocks/cta-band-block.meta.js +20 -0
- package/dist/blocks/danger-zone-block.js +39 -0
- package/dist/blocks/danger-zone-block.meta.js +21 -0
- package/dist/blocks/device-comparison-block.js +69 -0
- package/dist/blocks/device-comparison-block.meta.js +21 -0
- package/dist/blocks/event-card-block.js +40 -0
- package/dist/blocks/event-card-block.meta.js +21 -0
- package/dist/blocks/faq-block.js +38 -0
- package/dist/blocks/faq-block.meta.js +20 -0
- package/dist/blocks/feature-grid-block.js +38 -0
- package/dist/blocks/feature-grid-block.meta.js +21 -0
- package/dist/blocks/feedback-form-block.js +30 -0
- package/dist/blocks/feedback-form-block.meta.js +21 -0
- package/dist/blocks/goal-progress-block.js +24 -0
- package/dist/blocks/goal-progress-block.meta.js +21 -0
- package/dist/blocks/hero-block.js +33 -0
- package/dist/blocks/hero-block.meta.js +21 -0
- package/dist/blocks/index.js +162 -1964
- package/dist/blocks/invite-team-block.js +36 -0
- package/dist/blocks/invite-team-block.meta.js +20 -0
- package/dist/blocks/invoice-history-block.js +41 -0
- package/dist/blocks/invoice-history-block.meta.js +21 -0
- package/dist/blocks/kpi-sparkline-block.js +29 -0
- package/dist/blocks/kpi-sparkline-block.meta.js +20 -0
- package/dist/blocks/media-player-block.js +68 -0
- package/dist/blocks/media-player-block.meta.js +21 -0
- package/dist/blocks/newsletter-block.js +35 -0
- package/dist/blocks/newsletter-block.meta.js +21 -0
- package/dist/blocks/not-found-block.js +27 -0
- package/dist/blocks/not-found-block.meta.js +20 -0
- package/dist/blocks/notification-list-block.js +32 -0
- package/dist/blocks/notification-list-block.meta.js +21 -0
- package/dist/blocks/notification-settings-block.js +25 -0
- package/dist/blocks/notification-settings-block.meta.js +20 -0
- package/dist/blocks/order-tracking-block.js +26 -0
- package/dist/blocks/order-tracking-block.meta.js +20 -0
- package/dist/blocks/pricing-card-block.js +46 -0
- package/dist/blocks/pricing-card-block.meta.js +21 -0
- package/dist/blocks/pricing-table-block.js +88 -0
- package/dist/blocks/pricing-table-block.meta.js +20 -0
- package/dist/blocks/product-card-block.js +26 -0
- package/dist/blocks/product-card-block.meta.js +21 -0
- package/dist/blocks/profile-card-block.js +58 -0
- package/dist/blocks/profile-card-block.meta.js +21 -0
- package/dist/blocks/profile-form-block.js +70 -0
- package/dist/blocks/profile-form-block.meta.js +21 -0
- package/dist/blocks/revenue-breakdown-block.js +38 -0
- package/dist/blocks/revenue-breakdown-block.meta.js +21 -0
- package/dist/blocks/sign-in-block.js +38 -0
- package/dist/blocks/sign-in-block.meta.js +21 -0
- package/dist/blocks/sign-up-block.js +48 -0
- package/dist/blocks/sign-up-block.meta.js +21 -0
- package/dist/blocks/site-footer-block.js +54 -0
- package/dist/blocks/site-footer-block.meta.js +20 -0
- package/dist/blocks/stat-row-block.js +28 -0
- package/dist/blocks/stat-row-block.meta.js +21 -0
- package/dist/blocks/steps-block.js +37 -0
- package/dist/blocks/steps-block.meta.js +20 -0
- package/dist/blocks/task-list-block.js +52 -0
- package/dist/blocks/task-list-block.meta.js +21 -0
- package/dist/blocks/team-members-block.js +49 -0
- package/dist/blocks/team-members-block.meta.js +21 -0
- package/dist/blocks/testimonial-block.js +49 -0
- package/dist/blocks/testimonial-block.meta.js +20 -0
- package/dist/blocks/traffic-sources-block.js +39 -0
- package/dist/blocks/traffic-sources-block.meta.js +21 -0
- package/dist/blocks/traffic-trend-block.js +61 -0
- package/dist/blocks/traffic-trend-block.meta.js +21 -0
- package/dist/blocks/upload-list-block.js +39 -0
- package/dist/blocks/upload-list-block.meta.js +21 -0
- package/dist/blocks/verify-code-block.js +28 -0
- package/dist/blocks/verify-code-block.meta.js +21 -0
- package/dist/blocks/wallet-block.js +48 -0
- package/dist/blocks/wallet-block.meta.js +21 -0
- package/dist/components/accordion/accordion.js +63 -0
- package/dist/components/accordion/accordion.meta.js +155 -0
- package/dist/components/accordion/index.js +15 -0
- package/dist/components/app-header/app-header.js +30 -0
- package/dist/components/app-header/app-header.meta.js +88 -0
- package/dist/components/app-header/index.js +7 -0
- package/dist/components/app-shell/app-shell-dock.js +37 -0
- package/dist/components/app-shell/app-shell.js +67 -0
- package/dist/components/app-shell/app-shell.meta.js +176 -0
- package/dist/components/app-shell/index.js +7 -0
- package/dist/components/area-chart/area-chart.js +10 -0
- package/dist/components/area-chart/area-chart.meta.js +218 -0
- package/dist/components/area-chart/index.js +7 -0
- package/dist/components/attachment/attachment.js +176 -0
- package/dist/components/attachment/attachment.meta.js +179 -0
- package/dist/components/attachment/attachment.variants.js +47 -0
- package/dist/components/attachment/index.js +7 -0
- package/dist/components/avatar/avatar.js +192 -0
- package/dist/components/avatar/avatar.meta.js +233 -0
- package/dist/components/avatar/avatar.variants.js +44 -0
- package/dist/components/avatar/index.js +22 -0
- package/dist/components/badge/badge.js +26 -0
- package/dist/components/badge/badge.meta.js +171 -0
- package/dist/components/badge/badge.variants.js +103 -0
- package/dist/components/badge/index.js +11 -0
- package/dist/components/banner/banner.js +76 -0
- package/dist/components/banner/banner.meta.js +172 -0
- package/dist/components/banner/banner.variants.js +44 -0
- package/dist/components/banner/index.js +9 -0
- package/dist/components/bar-chart/bar-chart.js +10 -0
- package/dist/components/bar-chart/bar-chart.meta.js +245 -0
- package/dist/components/bar-chart/index.js +7 -0
- package/dist/components/bottom-nav/bottom-nav.js +63 -0
- package/dist/components/bottom-nav/bottom-nav.meta.js +95 -0
- package/dist/components/bottom-nav/index.js +11 -0
- package/dist/components/breadcrumbs/breadcrumbs.js +90 -0
- package/dist/components/breadcrumbs/breadcrumbs.meta.js +111 -0
- package/dist/components/breadcrumbs/index.js +17 -0
- package/dist/components/browser/browser.js +39 -0
- package/dist/components/browser/browser.meta.js +80 -0
- package/dist/components/browser/index.js +7 -0
- package/dist/components/bubble/bubble.js +110 -0
- package/dist/components/bubble/bubble.meta.js +158 -0
- package/dist/components/bubble/bubble.variants.js +90 -0
- package/dist/components/bubble/index.js +13 -0
- package/dist/components/button/button.js +87 -0
- package/dist/components/button/button.meta.js +302 -0
- package/dist/components/button/button.variants.js +137 -0
- package/dist/components/button/index.js +9 -0
- package/dist/components/calendar/calendar.js +89 -0
- package/dist/components/calendar/calendar.meta.js +136 -0
- package/dist/components/calendar/index.js +7 -0
- package/dist/components/card/card.js +200 -0
- package/dist/components/card/card.meta.js +212 -0
- package/dist/components/card/index.js +23 -0
- package/dist/components/carousel/carousel.js +428 -0
- package/dist/components/carousel/carousel.meta.js +100 -0
- package/dist/components/carousel/index.js +7 -0
- package/dist/components/chat-composer/chat-composer.js +174 -0
- package/dist/components/chat-composer/chat-composer.meta.js +241 -0
- package/dist/components/chat-composer/chat-composer.variants.js +17 -0
- package/dist/components/chat-composer/index.js +7 -0
- package/dist/components/checkbox/checkbox-mark.js +28 -0
- package/dist/components/checkbox/checkbox.js +30 -0
- package/dist/components/checkbox/checkbox.meta.js +127 -0
- package/dist/components/checkbox/index.js +7 -0
- package/dist/components/checkbox-card/checkbox-card.js +94 -0
- package/dist/components/checkbox-card/checkbox-card.meta.js +154 -0
- package/dist/components/checkbox-card/checkbox-card.variants.js +43 -0
- package/dist/components/checkbox-card/index.js +11 -0
- package/dist/components/code/code.js +19 -0
- package/dist/components/code/code.meta.js +71 -0
- package/dist/components/code/index.js +7 -0
- package/dist/components/code-block/code-block.js +84 -0
- package/dist/components/code-block/code-block.meta.js +103 -0
- package/dist/components/code-block/index.js +8 -0
- package/dist/components/collapsible/collapsible.js +38 -0
- package/dist/components/collapsible/collapsible.meta.js +117 -0
- package/dist/components/collapsible/index.js +15 -0
- package/dist/components/color-field/color-field.js +293 -0
- package/dist/components/color-field/color-field.meta.js +142 -0
- package/dist/components/color-field/color.js +69 -0
- package/dist/components/color-field/index.js +15 -0
- package/dist/components/combobox/combobox.js +486 -0
- package/dist/components/combobox/combobox.meta.js +217 -0
- package/dist/components/combobox/index.js +37 -0
- package/dist/components/command-menu/command-menu-trigger.js +122 -0
- package/dist/components/command-menu/command-menu.js +433 -0
- package/dist/components/command-menu/command-menu.meta.js +279 -0
- package/dist/components/command-menu/index.js +21 -0
- package/dist/components/context-card/context-card.js +62 -0
- package/dist/components/context-card/context-card.meta.js +106 -0
- package/dist/components/context-card/index.js +17 -0
- package/dist/components/context-menu/context-menu.js +92 -0
- package/dist/components/context-menu/context-menu.meta.js +138 -0
- package/dist/components/context-menu/index.js +23 -0
- package/dist/components/data-table/data-table.js +142 -0
- package/dist/components/data-table/data-table.meta.js +146 -0
- package/dist/components/data-table/index.js +9 -0
- package/dist/components/date-picker/date-picker.js +196 -0
- package/dist/components/date-picker/date-picker.meta.js +164 -0
- package/dist/components/date-picker/index.js +7 -0
- package/dist/components/date-tile/date-tile.js +29 -0
- package/dist/components/date-tile/date-tile.meta.js +72 -0
- package/dist/components/date-tile/index.js +7 -0
- package/dist/components/destructive-action-modal/destructive-action-modal.js +130 -0
- package/dist/components/destructive-action-modal/destructive-action-modal.meta.js +136 -0
- package/dist/components/destructive-action-modal/index.js +9 -0
- package/dist/components/dialog/dialog.js +207 -0
- package/dist/components/dialog/dialog.meta.js +239 -0
- package/dist/components/dialog/index.js +45 -0
- package/dist/components/disclosure-picker/disclosure-picker.js +417 -0
- package/dist/components/disclosure-picker/disclosure-picker.meta.js +213 -0
- package/dist/components/disclosure-picker/index.js +21 -0
- package/dist/components/empty-state/empty-state.js +52 -0
- package/dist/components/empty-state/empty-state.meta.js +158 -0
- package/dist/components/empty-state/index.js +7 -0
- package/dist/components/entity/entity.js +70 -0
- package/dist/components/entity/entity.meta.js +108 -0
- package/dist/components/entity/entity.variants.js +16 -0
- package/dist/components/entity/index.js +7 -0
- package/dist/components/feedback/feedback.js +93 -0
- package/dist/components/feedback/feedback.meta.js +109 -0
- package/dist/components/feedback/index.js +7 -0
- package/dist/components/fieldset/fieldset.js +80 -0
- package/dist/components/fieldset/fieldset.meta.js +160 -0
- package/dist/components/fieldset/index.js +17 -0
- package/dist/components/file-dropzone/file-dropzone.js +193 -0
- package/dist/components/file-dropzone/file-dropzone.meta.js +210 -0
- package/dist/components/file-dropzone/file-dropzone.variants.js +26 -0
- package/dist/components/file-dropzone/index.js +13 -0
- package/dist/components/font-picker/font-picker.js +77 -0
- package/dist/components/font-picker/font-picker.meta.js +119 -0
- package/dist/components/font-picker/index.js +7 -0
- package/dist/components/form/form.js +145 -0
- package/dist/components/form/form.meta.js +142 -0
- package/dist/components/form/index.js +11 -0
- package/dist/components/gliding-highlight/gliding-highlight.js +50 -0
- package/dist/components/gliding-highlight/gliding-highlight.meta.js +135 -0
- package/dist/components/gliding-highlight/index.js +9 -0
- package/dist/components/gradient-art/gradient-art.js +168 -0
- package/dist/components/gradient-art/gradient-art.meta.js +81 -0
- package/dist/components/gradient-art/index.js +7 -0
- package/dist/components/gradient-art/renderer.js +336 -0
- package/dist/components/inline-status/index.js +7 -0
- package/dist/components/inline-status/inline-status.js +33 -0
- package/dist/components/inline-status/inline-status.meta.js +83 -0
- package/dist/components/inline-status/inline-status.variants.js +18 -0
- package/dist/components/input/index.js +7 -0
- package/dist/components/input/input.js +33 -0
- package/dist/components/input/input.meta.js +155 -0
- package/dist/components/kbd/index.js +8 -0
- package/dist/components/kbd/kbd.js +54 -0
- package/dist/components/kbd/kbd.meta.js +95 -0
- package/dist/components/label/index.js +7 -0
- package/dist/components/label/label.js +51 -0
- package/dist/components/label/label.meta.js +98 -0
- package/dist/components/line-chart/index.js +7 -0
- package/dist/components/line-chart/line-chart.js +10 -0
- package/dist/components/line-chart/line-chart.meta.js +222 -0
- package/dist/components/marker/index.js +7 -0
- package/dist/components/marker/marker.js +39 -0
- package/dist/components/marker/marker.meta.js +132 -0
- package/dist/components/marker/marker.variants.js +25 -0
- package/dist/components/marquee/index.js +7 -0
- package/dist/components/marquee/marquee.js +146 -0
- package/dist/components/marquee/marquee.meta.js +106 -0
- package/dist/components/media-image/index.js +7 -0
- package/dist/components/media-image/media-image.js +56 -0
- package/dist/components/media-image/media-image.meta.js +92 -0
- package/dist/components/media-tile/index.js +7 -0
- package/dist/components/media-tile/media-tile.js +135 -0
- package/dist/components/media-tile/media-tile.meta.js +133 -0
- package/dist/components/media-tile/media-tile.variants.js +48 -0
- package/dist/components/menu/index.js +33 -0
- package/dist/components/menu/menu.js +168 -0
- package/dist/components/menu/menu.meta.js +176 -0
- package/dist/components/message/index.js +7 -0
- package/dist/components/message/message.js +83 -0
- package/dist/components/message/message.meta.js +150 -0
- package/dist/components/message/message.variants.js +41 -0
- package/dist/components/message-scroller/index.js +9 -0
- package/dist/components/message-scroller/message-scroller.js +300 -0
- package/dist/components/message-scroller/message-scroller.meta.js +172 -0
- package/dist/components/meter/index.js +20 -0
- package/dist/components/meter/meter.js +112 -0
- package/dist/components/meter/meter.meta.js +227 -0
- package/dist/components/meter/meter.variants.js +61 -0
- package/dist/components/middle-truncate/index.js +7 -0
- package/dist/components/middle-truncate/middle-truncate.js +28 -0
- package/dist/components/middle-truncate/middle-truncate.meta.js +77 -0
- package/dist/components/note/index.js +9 -0
- package/dist/components/note/note.js +73 -0
- package/dist/components/note/note.meta.js +112 -0
- package/dist/components/note/note.variants.js +22 -0
- package/dist/components/notification-badge/index.js +15 -0
- package/dist/components/notification-badge/notification-badge.js +48 -0
- package/dist/components/notification-badge/notification-badge.meta.js +107 -0
- package/dist/components/notification-badge/notification-badge.variants.js +57 -0
- package/dist/components/number-field/index.js +7 -0
- package/dist/components/number-field/number-field.js +70 -0
- package/dist/components/number-field/number-field.meta.js +109 -0
- package/dist/components/otp-field/index.js +7 -0
- package/dist/components/otp-field/otp-field.js +70 -0
- package/dist/components/otp-field/otp-field.meta.js +197 -0
- package/dist/components/overflow-menu/index.js +7 -0
- package/dist/components/overflow-menu/overflow-menu.js +26 -0
- package/dist/components/overflow-menu/overflow-menu.meta.js +100 -0
- package/dist/components/page-header/index.js +7 -0
- package/dist/components/page-header/page-header.js +34 -0
- package/dist/components/page-header/page-header.meta.js +104 -0
- package/dist/components/page-loader/index.js +7 -0
- package/dist/components/page-loader/page-loader.js +37 -0
- package/dist/components/page-loader/page-loader.meta.js +85 -0
- package/dist/components/pagination/index.js +7 -0
- package/dist/components/pagination/pagination.js +105 -0
- package/dist/components/pagination/pagination.meta.js +141 -0
- package/dist/components/panel-group/index.js +10 -0
- package/dist/components/panel-group/panel-group.js +168 -0
- package/dist/components/panel-group/panel-group.meta.js +153 -0
- package/dist/components/panel-section/index.js +9 -0
- package/dist/components/panel-section/panel-section.js +115 -0
- package/dist/components/panel-section/panel-section.meta.js +156 -0
- package/dist/components/phone/index.js +7 -0
- package/dist/components/phone/phone.js +50 -0
- package/dist/{chunk-KFZ43RKU.js → components/phone/phone.meta.js} +3 -50
- package/dist/{chunk-NEQNXI2G.js → components/phone/status-icons.js} +4 -4
- package/dist/components/pie-chart/index.js +7 -0
- package/dist/components/pie-chart/pie-chart.js +191 -0
- package/dist/components/pie-chart/pie-chart.meta.js +210 -0
- package/dist/components/pill/index.js +9 -0
- package/dist/components/pill/pill.js +24 -0
- package/dist/components/pill/pill.meta.js +108 -0
- package/dist/components/pill/pill.variants.js +65 -0
- package/dist/components/popover/index.js +23 -0
- package/dist/components/popover/popover.js +100 -0
- package/dist/components/popover/popover.meta.js +136 -0
- package/dist/components/progress/index.js +19 -0
- package/dist/components/progress/progress.js +70 -0
- package/dist/components/progress/progress.meta.js +171 -0
- package/dist/components/progress/progress.variants.js +17 -0
- package/dist/components/radar-chart/index.js +7 -0
- package/dist/components/radar-chart/radar-chart.js +161 -0
- package/dist/components/radar-chart/radar-chart.meta.js +204 -0
- package/dist/components/radial-chart/index.js +7 -0
- package/dist/components/radial-chart/radial-chart.js +175 -0
- package/dist/components/radial-chart/radial-chart.meta.js +216 -0
- package/dist/components/radio/index.js +8 -0
- package/dist/components/radio/radio.js +39 -0
- package/dist/components/radio/radio.meta.js +104 -0
- package/dist/components/radio-card/index.js +7 -0
- package/dist/components/radio-card/radio-card.js +81 -0
- package/dist/components/radio-card/radio-card.meta.js +144 -0
- package/dist/components/radio-card/radio-card.variants.js +43 -0
- package/dist/components/relative-time/index.js +7 -0
- package/dist/components/relative-time/relative-time.js +47 -0
- package/dist/components/relative-time/relative-time.meta.js +77 -0
- package/dist/components/scroller/index.js +7 -0
- package/dist/components/scroller/scroller.js +111 -0
- package/dist/components/scroller/scroller.meta.js +118 -0
- package/dist/components/scrub-field/index.js +7 -0
- package/dist/components/scrub-field/scrub-field.js +124 -0
- package/dist/components/scrub-field/scrub-field.meta.js +139 -0
- package/dist/components/search-input/index.js +7 -0
- package/dist/components/search-input/search-input.js +91 -0
- package/dist/components/search-input/search-input.meta.js +129 -0
- package/dist/components/section-header/index.js +7 -0
- package/dist/components/section-header/section-header.js +39 -0
- package/dist/components/section-header/section-header.meta.js +174 -0
- package/dist/components/segmented-bar/index.js +14 -0
- package/dist/components/segmented-bar/segmented-bar.js +26 -0
- package/dist/components/segmented-bar/segmented-bar.meta.js +108 -0
- package/dist/components/segmented-bar/segmented-bar.variants.js +39 -0
- package/dist/components/select/index.js +25 -0
- package/dist/components/select/select.js +191 -0
- package/dist/components/select/select.meta.js +189 -0
- package/dist/components/separator/index.js +7 -0
- package/dist/components/separator/separator.js +42 -0
- package/dist/components/separator/separator.meta.js +84 -0
- package/dist/components/settings-menu/index.js +11 -0
- package/dist/components/settings-menu/settings-menu.js +101 -0
- package/dist/components/settings-menu/settings-menu.meta.js +177 -0
- package/dist/components/settings-menu/settings-menu.variants.js +15 -0
- package/dist/components/sheet/index.js +29 -0
- package/dist/components/sheet/sheet.js +121 -0
- package/dist/components/sheet/sheet.meta.js +167 -0
- package/dist/components/sheet/sheet.variants.js +21 -0
- package/dist/components/show-more/index.js +7 -0
- package/dist/components/show-more/show-more.js +87 -0
- package/dist/components/show-more/show-more.meta.js +79 -0
- package/dist/components/side-nav/index.js +13 -0
- package/dist/components/side-nav/side-nav.js +75 -0
- package/dist/components/side-nav/side-nav.meta.js +139 -0
- package/dist/components/side-nav/side-nav.variants.js +33 -0
- package/dist/components/sidebar/index.js +21 -0
- package/dist/components/sidebar/sidebar.js +196 -0
- package/dist/components/sidebar/sidebar.meta.js +118 -0
- package/dist/components/skeleton/index.js +7 -0
- package/dist/components/skeleton/skeleton.js +16 -0
- package/dist/components/skeleton/skeleton.meta.js +90 -0
- package/dist/components/slider/index.js +21 -0
- package/dist/components/slider/slider.js +115 -0
- package/dist/components/slider/slider.meta.js +214 -0
- package/dist/components/sparkline/index.js +7 -0
- package/dist/components/sparkline/sparkline.js +84 -0
- package/dist/components/sparkline/sparkline.meta.js +147 -0
- package/dist/components/spinner/index.js +7 -0
- package/dist/components/spinner/spinner.js +59 -0
- package/dist/components/spinner/spinner.meta.js +118 -0
- package/dist/components/status-bar/index.js +9 -0
- package/dist/components/status-bar/status-bar.js +40 -0
- package/dist/components/status-bar/status-bar.meta.js +117 -0
- package/dist/components/status-dot/index.js +9 -0
- package/dist/components/status-dot/status-dot.js +40 -0
- package/dist/components/status-dot/status-dot.meta.js +113 -0
- package/dist/components/status-dot/status-dot.variants.js +28 -0
- package/dist/components/stepper/index.js +17 -0
- package/dist/components/stepper/stepper.js +161 -0
- package/dist/components/stepper/stepper.meta.js +190 -0
- package/dist/components/stepper/stepper.variants.js +72 -0
- package/dist/components/streaming-text/index.js +7 -0
- package/dist/components/streaming-text/streaming-text.js +55 -0
- package/dist/components/streaming-text/streaming-text.meta.js +147 -0
- package/dist/components/switch/index.js +7 -0
- package/dist/components/switch/switch.js +26 -0
- package/dist/components/switch/switch.meta.js +133 -0
- package/dist/components/table/index.js +23 -0
- package/dist/components/table/table.js +117 -0
- package/dist/components/table/table.meta.js +143 -0
- package/dist/components/tabs/index.js +17 -0
- package/dist/components/tabs/tabs.js +58 -0
- package/dist/components/tabs/tabs.meta.js +120 -0
- package/dist/components/textarea/index.js +7 -0
- package/dist/components/textarea/textarea.js +38 -0
- package/dist/components/textarea/textarea.meta.js +117 -0
- package/dist/components/theme-selector/index.js +11 -0
- package/dist/components/theme-selector/theme-selector.js +145 -0
- package/dist/components/theme-selector/theme-selector.meta.js +181 -0
- package/dist/components/theme-switcher/index.js +7 -0
- package/dist/components/theme-switcher/theme-switcher.js +106 -0
- package/dist/components/theme-switcher/theme-switcher.meta.js +99 -0
- package/dist/components/thinking-orb/index.js +9 -0
- package/dist/components/thinking-orb/thinking-orb.js +126 -0
- package/dist/components/thinking-orb/thinking-orb.meta.js +142 -0
- package/dist/components/thinking-orb/thinking-orb.render.js +252 -0
- package/dist/components/toast/index.js +29 -0
- package/dist/components/toast/toast.js +254 -0
- package/dist/components/toast/toast.meta.js +261 -0
- package/dist/components/toggle/index.js +13 -0
- package/dist/components/toggle/toggle.js +51 -0
- package/dist/components/toggle/toggle.meta.js +129 -0
- package/dist/components/toolbar/index.js +27 -0
- package/dist/components/toolbar/toolbar.js +80 -0
- package/dist/components/toolbar/toolbar.meta.js +272 -0
- package/dist/components/toolbar/toolbar.variants.js +16 -0
- package/dist/components/tooltip/index.js +21 -0
- package/dist/components/tooltip/tooltip.js +74 -0
- package/dist/components/tooltip/tooltip.meta.js +156 -0
- package/dist/components/tree/index.js +12 -0
- package/dist/components/tree/tree.js +364 -0
- package/dist/components/tree/tree.meta.js +334 -0
- package/dist/components/video/index.js +7 -0
- package/dist/components/video/video.js +59 -0
- package/dist/components/video/video.meta.js +81 -0
- package/dist/components/workspace/index.js +9 -0
- package/dist/components/workspace/workspace.js +79 -0
- package/dist/components/workspace/workspace.meta.js +183 -0
- package/dist/foundations/accessibility.js +107 -0
- package/dist/foundations/index.js +25 -792
- package/dist/foundations/motion.js +135 -0
- package/dist/foundations/scrolling.js +62 -0
- package/dist/foundations/shape.js +113 -0
- package/dist/foundations/spacing.js +121 -0
- package/dist/foundations/surfaces.js +107 -0
- package/dist/foundations/types.js +0 -0
- package/dist/foundations/typography.js +152 -0
- package/dist/icon/Icon.js +30 -0
- package/dist/icon/IconProvider.js +27 -0
- package/dist/icon/compose.js +13 -0
- package/dist/icon/index.d.ts +13 -5
- package/dist/icon/index.js +13 -2
- package/dist/icon/registry.js +0 -0
- package/dist/icon-sets/brands.generated.js +123 -0
- package/dist/icon-sets/brands.js +10 -123
- package/dist/icon-sets/reicon.d.ts +3 -1
- package/dist/icon-sets/reicon.js +209 -1
- package/dist/index.d.ts +611 -33
- package/dist/index.js +211 -11351
- package/dist/ios/chrome.js +36 -0
- package/dist/ios/index.js +19 -315
- package/dist/ios/liquid-glass.js +103 -0
- package/dist/ios/native-app.js +46 -0
- package/dist/ios/navigation.js +63 -0
- package/dist/ios/phone-frame.js +64 -0
- package/dist/ios/preview-theme.js +83 -0
- package/dist/ios/preview.js +10 -137
- package/dist/ios/sheet.js +85 -0
- package/dist/ios/theme.js +19 -0
- package/dist/layout/AspectBox.js +27 -0
- package/dist/layout/Bleed.js +15 -0
- package/dist/layout/Center.js +21 -0
- package/dist/layout/Columns.js +70 -0
- package/dist/layout/Grid.js +50 -0
- package/dist/layout/GridOverlay.js +41 -0
- package/dist/layout/Page.js +11 -0
- package/dist/layout/Region.js +39 -0
- package/dist/layout/Row.js +45 -0
- package/dist/layout/SafeArea.js +26 -0
- package/dist/layout/Spacer.js +9 -0
- package/dist/layout/SplitPane.js +55 -0
- package/dist/layout/Stack.js +42 -0
- package/dist/layout/_responsive.js +16 -0
- package/dist/layout/_safeArea.js +18 -0
- package/dist/layout/index.d.ts +25 -6
- package/dist/layout/index.js +14 -2
- package/dist/lib/anchored-scroll.js +7 -0
- package/dist/lib/bleed.js +7 -0
- package/dist/lib/chart/cartesian.js +365 -0
- package/dist/lib/chart/chart-frame.js +163 -0
- package/dist/lib/chart/chart-legend.js +13 -0
- package/dist/lib/chart/chart-tooltip.js +38 -0
- package/dist/lib/chart/format.js +19 -0
- package/dist/lib/chart/geometry.js +114 -0
- package/dist/lib/chart/motion.js +34 -0
- package/dist/lib/chart/scale.js +72 -0
- package/dist/lib/chart/types.js +45 -0
- package/dist/lib/chart/use-arrival.js +41 -0
- package/dist/{chunk-SRQWQUTW.js → lib/cn.js} +5 -5
- package/dist/lib/component-guidance.js +210 -0
- package/dist/lib/density.js +54 -0
- package/dist/lib/field-shell.js +11 -0
- package/dist/lib/glyphs.js +9 -0
- package/dist/lib/heading-row.js +36 -0
- package/dist/lib/highlight-glide.js +84 -0
- package/dist/lib/hit-target.js +5 -0
- package/dist/lib/meta.js +0 -0
- package/dist/lib/portal-theme-scope.js +74 -0
- package/dist/{chunk-FKZXAFIY.js → lib/presentation.js} +8 -3
- package/dist/lib/refs.js +14 -0
- package/dist/lib/scrub-gesture.js +50 -0
- package/dist/lib/segmented.js +13 -0
- package/dist/lib/selection-card.js +41 -0
- package/dist/lib/status-tone.js +13 -0
- package/dist/lib/taxonomy.js +214 -0
- package/dist/lib/trim-label.js +20 -0
- package/dist/lib/use-copy.js +27 -0
- package/dist/lib/use-edge-fade.js +32 -0
- package/dist/lib/use-isomorphic-layout-effect.js +8 -0
- package/dist/lib/use-resize-observer.js +18 -0
- package/dist/lib/use-scroll-activity.js +52 -0
- package/dist/lib/use-wheel-to-horizontal.js +65 -0
- package/dist/motion/MotionProvider.js +75 -0
- package/dist/motion/Presence.js +112 -0
- package/dist/motion/Reveal.js +42 -0
- package/dist/motion/TextReveal.js +61 -0
- package/dist/motion/index.js +24 -0
- package/dist/motion/useInView.js +36 -0
- package/dist/motion/useReducedMotion.js +25 -0
- package/dist/motion/viewTransition.js +47 -0
- package/dist/patterns/auth-page.js +90 -0
- package/dist/patterns/auth-page.meta.js +27 -0
- package/dist/patterns/brand-landing-page.js +341 -0
- package/dist/patterns/brand-landing-page.meta.js +28 -0
- package/dist/patterns/chat-panel.js +185 -0
- package/dist/patterns/chat-panel.meta.js +31 -0
- package/dist/patterns/dashboard-page.js +332 -0
- package/dist/patterns/dashboard-page.meta.js +29 -0
- package/dist/patterns/feed-page.js +205 -0
- package/dist/patterns/feed-page.meta.js +25 -0
- package/dist/patterns/index.js +34 -2140
- package/dist/patterns/landing-page.js +356 -0
- package/dist/patterns/landing-page.meta.js +26 -0
- package/dist/patterns/list-detail-page.js +373 -0
- package/dist/patterns/list-detail-page.meta.js +24 -0
- package/dist/patterns/settings-page.js +268 -0
- package/dist/patterns/settings-page.meta.js +27 -0
- package/dist/presets/index.js +43 -185
- package/dist/styles.css +118 -3
- package/dist/{theme-provider-kQszHYji.d.ts → theme-provider-S0NVJs2Y.d.ts} +6 -1
- package/dist/{chunk-NETUFI34.js → themes/_contract.js} +14 -2
- package/dist/themes/atelier/index.js +17 -1
- package/dist/themes/contrast.js +288 -0
- package/dist/themes/ember/ember.css +6 -6
- package/dist/themes/ember/index.js +16 -1
- package/dist/themes/index.d.ts +1 -1
- package/dist/themes/index.js +3 -8
- package/dist/themes/meridian/index.js +16 -1
- package/dist/themes/poppy/index.js +17 -1
- package/dist/themes/prism/index.js +17 -1
- package/dist/themes/prism/prism.css +2 -2
- package/dist/themes/registry.js +59 -0
- package/dist/themes/sable/index.js +16 -1
- package/dist/{chunk-EFLC4NA3.js → themes/theme-provider.js} +38 -54
- package/dist/themes/verdant/index.js +17 -1
- package/llms/blocks/media-player-block.md +20 -7
- package/llms/blocks/product-card-block.md +6 -4
- package/llms/blocks/task-list-block.md +1 -1
- package/llms/blocks/verify-code-block.md +1 -1
- package/llms/components/app-shell.md +5 -2
- package/llms/components/avatar.md +25 -3
- package/llms/components/button.md +20 -1
- package/llms/components/card.md +1 -1
- package/llms/components/disclosure-picker.md +168 -0
- package/llms/components/font-picker.md +104 -0
- package/llms/components/media-image.md +98 -0
- package/llms/components/media-tile.md +143 -0
- package/llms/components/page-header.md +6 -5
- package/llms/components/section-header.md +144 -0
- package/llms/components/sheet.md +10 -0
- package/llms/components/sidebar.md +4 -3
- package/llms/components/slider.md +14 -2
- package/llms/components/theme-selector.md +44 -4
- package/llms/components/tree.md +3 -3
- package/llms/layout/grid.md +24 -3
- package/llms/patterns/dashboard-page.md +3 -6
- package/llms/patterns/feed-page.md +4 -4
- package/llms/patterns/list-detail-page.md +1 -0
- package/llms/patterns/settings-page.md +2 -5
- package/llms/reference/utilities.md +84 -4
- package/llms/tasks/converting-an-app.md +14 -4
- package/llms/tasks/reviewing-a-design.md +15 -0
- package/llms-full.txt +981 -65
- package/llms.txt +27 -10
- package/package.json +1 -1
- package/registry.json +2324 -171
- package/scripts/agent-setup.mjs +90 -0
- package/scripts/design-presets.mjs +46 -4
- package/scripts/grade.mjs +195 -29
- package/scripts/lint-rules.mjs +486 -10
- package/scripts/review-evidence.mjs +28 -1
- package/skills/sable/SKILL.md +56 -22
- package/targets/ios.json +45 -0
- package/dist/chunk-3IWZYBGH.js +0 -398
- package/dist/chunk-7MG4SHYX.js +0 -15
- package/dist/chunk-7QSDYBXO.js +0 -7421
- package/dist/chunk-ADLLDWLW.js +0 -15
- package/dist/chunk-C4Z3CF54.js +0 -15
- package/dist/chunk-EDXLM7YL.js +0 -5078
- package/dist/chunk-EHH4MHO6.js +0 -14
- package/dist/chunk-K7RUHUGC.js +0 -14
- package/dist/chunk-KO3NAEBF.js +0 -15
- package/dist/chunk-L4IEIQQA.js +0 -14
- package/dist/chunk-QJ6FWTUG.js +0 -40
- package/dist/chunk-VVW4UCDI.js +0 -4908
- package/dist/chunk-XAZGMY73.js +0 -187
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/blocks/api-keys-block.tsx
|
|
2
|
+
import { Button } from "../components/button/index.js";
|
|
3
|
+
import { Card, CardAction, CardDescription, CardHeader, CardList, CardTitle } from "../components/card/index.js";
|
|
4
|
+
import { Code } from "../components/code/index.js";
|
|
5
|
+
import { OverflowMenu } from "../components/overflow-menu/index.js";
|
|
6
|
+
import { Entity } from "../components/entity/index.js";
|
|
7
|
+
import { MenuItem, MenuSeparator } from "../components/menu/index.js";
|
|
8
|
+
import { Icon } from "../icon/index.js";
|
|
9
|
+
import { cn } from "../lib/cn.js";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
var keys = [
|
|
12
|
+
{ id: "k1", name: "Production", hint: "sk_live_\u2022\u2022\u2022\u20224f2a", detail: "Created Mar 2 \xB7 used 4 minutes ago" },
|
|
13
|
+
{ id: "k2", name: "Staging", hint: "sk_test_\u2022\u2022\u2022\u202291cd", detail: "Created Feb 11 \xB7 used yesterday" },
|
|
14
|
+
{ id: "k3", name: "CI deploys", hint: "sk_live_\u2022\u2022\u2022\u20220b7e", detail: "Created Jan 5 \xB7 never used" }
|
|
15
|
+
];
|
|
16
|
+
function ApiKeysBlock({ className, framed = true, onCreate, onKeyAction }) {
|
|
17
|
+
return /* @__PURE__ */ jsxs(Card, { variant: framed ? "default" : "flat", className: cn("w-full max-w-2xl", className), children: [
|
|
18
|
+
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
19
|
+
/* @__PURE__ */ jsx(CardTitle, { render: /* @__PURE__ */ jsx("h2", {}), children: "API keys" }),
|
|
20
|
+
/* @__PURE__ */ jsx(CardDescription, { children: "A key is shown once, when you create it. Store it somewhere safe." }),
|
|
21
|
+
/* @__PURE__ */ jsx(CardAction, { children: /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", iconStart: /* @__PURE__ */ jsx(Icon, { name: "key" }), onClick: onCreate, children: "Create key" }) })
|
|
22
|
+
] }),
|
|
23
|
+
/* @__PURE__ */ jsx(CardList, { children: keys.map((k) => /* @__PURE__ */ jsx(
|
|
24
|
+
Entity,
|
|
25
|
+
{
|
|
26
|
+
title: /* @__PURE__ */ jsxs("span", { className: "flex flex-wrap items-center gap-x-2", children: [
|
|
27
|
+
k.name,
|
|
28
|
+
/* @__PURE__ */ jsx(Code, { children: k.hint })
|
|
29
|
+
] }),
|
|
30
|
+
subtitle: k.detail,
|
|
31
|
+
action: /* @__PURE__ */ jsxs(OverflowMenu, { label: `Manage the ${k.name} key`, size: "icon-sm", children: [
|
|
32
|
+
/* @__PURE__ */ jsx(MenuItem, { onClick: () => onKeyAction?.(k.id, "rename"), children: "Rename" }),
|
|
33
|
+
/* @__PURE__ */ jsx(MenuItem, { onClick: () => onKeyAction?.(k.id, "roll"), children: "Roll key" }),
|
|
34
|
+
/* @__PURE__ */ jsx(MenuSeparator, {}),
|
|
35
|
+
/* @__PURE__ */ jsx(MenuItem, { variant: "destructive", onClick: () => onKeyAction?.(k.id, "revoke"), children: "Revoke" })
|
|
36
|
+
] })
|
|
37
|
+
},
|
|
38
|
+
k.id
|
|
39
|
+
)) })
|
|
40
|
+
] });
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
ApiKeysBlock
|
|
44
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/blocks/api-keys-block.meta.ts
|
|
2
|
+
var apiKeysBlockMeta = {
|
|
3
|
+
name: "ApiKeysBlock",
|
|
4
|
+
family: "Settings & team",
|
|
5
|
+
kind: "card",
|
|
6
|
+
width: { min: "20rem", max: "42rem" },
|
|
7
|
+
summary: "An API keys card: each key's name with its masked hint in Code, when it was created and last used, and an OverflowMenu to rename, roll or revoke.",
|
|
8
|
+
intent: "Reach for this for developer settings \u2014 API keys, access tokens, webhook secrets. Show a newly created key once, in a Dialog with a copy button; this list only ever shows the masked hint.",
|
|
9
|
+
notes: [
|
|
10
|
+
"Only the last four characters are shown. A full key never appears in a list, so there is no copy action here.",
|
|
11
|
+
'"Last used" sits in the detail line: it is what tells someone a key is safe to revoke.',
|
|
12
|
+
"Revoke is the destructive item, last and after a separator; confirm it in your handler with DestructiveActionModal."
|
|
13
|
+
],
|
|
14
|
+
a11y: [
|
|
15
|
+
"Each OverflowMenu is labelled with the key's name, so the triggers are distinguishable.",
|
|
16
|
+
"The masked hint is a Code element inside the title, read after the key's name."
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
apiKeysBlockMeta
|
|
21
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/blocks/chat-thread-block.tsx
|
|
2
|
+
import { Bubble } from "../components/bubble/index.js";
|
|
3
|
+
import { Card, CardContent } from "../components/card/index.js";
|
|
4
|
+
import { Message } from "../components/message/index.js";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
var messages = [
|
|
8
|
+
{ id: "m1", text: "Is the new cover ready?", mine: false },
|
|
9
|
+
{ id: "m2", text: "Uploading it now \u{1F389}", mine: true },
|
|
10
|
+
{ id: "m3", text: "Perfect, thank you!", mine: false }
|
|
11
|
+
];
|
|
12
|
+
function ChatThreadBlock({ className, framed = true }) {
|
|
13
|
+
return /* @__PURE__ */ jsx(Card, { variant: framed ? "default" : "flat", className: cn("w-full max-w-xs", className), children: /* @__PURE__ */ jsx(CardContent, { className: "flex flex-col gap-2", children: messages.map((m) => /* @__PURE__ */ jsx(Message, { messageId: m.id, align: m.mine ? "end" : void 0, children: /* @__PURE__ */ jsx(Bubble, { variant: m.mine ? "primary" : void 0, align: m.mine ? "end" : void 0, children: m.text }) }, m.id)) }) });
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
ChatThreadBlock
|
|
17
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/blocks/chat-thread-block.meta.ts
|
|
2
|
+
var chatThreadBlockMeta = {
|
|
3
|
+
name: "ChatThreadBlock",
|
|
4
|
+
family: "Social & messaging",
|
|
5
|
+
kind: "card",
|
|
6
|
+
width: { min: "16rem", max: "20rem" },
|
|
7
|
+
summary: "A short message thread on a card: Message rows with incoming muted Bubbles on the start side and your own primary Bubbles on the end.",
|
|
8
|
+
intent: "Reach for this to show a conversation excerpt \u2014 a support preview, a comment thread on a dashboard, a recent-DM card. A working chat with a composer, streaming and history is the ChatPanel page shell.",
|
|
9
|
+
notes: [
|
|
10
|
+
"Sit it on a card, not straight on a muted page: incoming bubbles are the muted surface, and would vanish into it.",
|
|
11
|
+
"Your own messages align to the end with the primary Bubble; everyone else's align to the start."
|
|
12
|
+
],
|
|
13
|
+
a11y: [
|
|
14
|
+
"Each Message carries a messageId, so a thread can be addressed and announced item by item.",
|
|
15
|
+
"Direction is shown by alignment and colour; when senders matter, add the sender's name to each Message."
|
|
16
|
+
]
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
chatThreadBlockMeta
|
|
20
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/blocks/command-palette-block.tsx
|
|
2
|
+
import { CommandMenuPanel } from "../components/command-menu/index.js";
|
|
3
|
+
import { Kbd } from "../components/kbd/index.js";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var commands = [
|
|
7
|
+
{ id: "new-project", icon: "plus", label: "New project", key: "N" },
|
|
8
|
+
{ id: "invite", icon: "user", label: "Invite teammate", key: "I" },
|
|
9
|
+
{ id: "settings", icon: "gear", label: "Open settings", key: "," }
|
|
10
|
+
];
|
|
11
|
+
function CommandPaletteBlock({ className, onCommand }) {
|
|
12
|
+
const items = commands.map((c) => ({
|
|
13
|
+
id: c.id,
|
|
14
|
+
group: "Actions",
|
|
15
|
+
icon: c.icon,
|
|
16
|
+
label: c.label,
|
|
17
|
+
hint: /* @__PURE__ */ jsx(Kbd, { children: c.key }),
|
|
18
|
+
onSelect: () => onCommand?.(c.id)
|
|
19
|
+
}));
|
|
20
|
+
return /* @__PURE__ */ jsx(CommandMenuPanel, { className: cn("w-full max-w-xs shadow-sm", className), placeholder: "Type a command\u2026", items });
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
CommandPaletteBlock
|
|
24
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/blocks/command-palette-block.meta.ts
|
|
2
|
+
var commandPaletteBlockMeta = {
|
|
3
|
+
name: "CommandPaletteBlock",
|
|
4
|
+
family: "Navigation",
|
|
5
|
+
kind: "card",
|
|
6
|
+
width: { min: "18rem", max: "20rem" },
|
|
7
|
+
summary: "An inline command palette: CommandMenuPanel with a filter field and grouped actions, each with an icon and its keyboard shortcut.",
|
|
8
|
+
intent: "Reach for this to show a command list in place \u2014 an empty state that teaches shortcuts, an onboarding step, a quick-actions card. The \u2318K palette that opens over the app is CommandMenu; this is its panel without the dialog.",
|
|
9
|
+
notes: [
|
|
10
|
+
"Each command shows its shortcut as a Kbd hint, so the palette also teaches the keys.",
|
|
11
|
+
"`onCommand` receives the command's id; ids also key the rows, so two commands may share a label.",
|
|
12
|
+
"No card around it: the panel is its own surface, lifted with `shadow-sm` when it sits on a muted section."
|
|
13
|
+
],
|
|
14
|
+
a11y: [
|
|
15
|
+
"CommandMenuPanel wires the filter input to the list as a combobox, with arrow-key navigation and the active row announced.",
|
|
16
|
+
"Shortcut hints are Kbd elements, read as keys."
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
commandPaletteBlockMeta
|
|
21
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/blocks/cta-band-block.tsx
|
|
2
|
+
import { useId } from "react";
|
|
3
|
+
import { Button } from "../components/button/index.js";
|
|
4
|
+
import { Card, CardContent } from "../components/card/index.js";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { Region, Row, Stack } from "../layout/index.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var cta = {
|
|
9
|
+
title: "Build the product, not another component library",
|
|
10
|
+
lede: "Install Sable, pick a preset, and ship the first screen today.",
|
|
11
|
+
primary: { label: "Get started", href: "/docs/getting-started" },
|
|
12
|
+
secondary: { label: "Star on GitHub", href: "/github" }
|
|
13
|
+
};
|
|
14
|
+
function CtaBandBlock({ className }) {
|
|
15
|
+
const titleId = useId();
|
|
16
|
+
return /* @__PURE__ */ jsx(Region, { as: "section", "aria-labelledby": titleId, max: "wide", className: cn("w-full py-16", className), children: /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs(Stack, { gap: 4, align: "center", className: "py-8 text-center sm:py-12", children: [
|
|
17
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, className: "max-w-2xl text-balance text-heading-1", children: cta.title }),
|
|
18
|
+
/* @__PURE__ */ jsx("p", { className: "max-w-(--measure-prose) text-body-lg text-muted-foreground", children: cta.lede }),
|
|
19
|
+
/* @__PURE__ */ jsxs(Row, { gap: 2, justify: "center", wrap: true, className: "pt-2", children: [
|
|
20
|
+
/* @__PURE__ */ jsx(Button, { size: "cta", render: /* @__PURE__ */ jsx("a", { href: cta.primary.href }), children: cta.primary.label }),
|
|
21
|
+
/* @__PURE__ */ jsx(Button, { size: "cta", variant: "outline", render: /* @__PURE__ */ jsx("a", { href: cta.secondary.href }), children: cta.secondary.label })
|
|
22
|
+
] })
|
|
23
|
+
] }) }) }) });
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
CtaBandBlock
|
|
27
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/blocks/cta-band-block.meta.ts
|
|
2
|
+
var ctaBandBlockMeta = {
|
|
3
|
+
name: "CtaBandBlock",
|
|
4
|
+
family: "Marketing",
|
|
5
|
+
kind: "section",
|
|
6
|
+
summary: "A closing call to action: a centred h2 and one-line lede on a card, with a primary and an outline action.",
|
|
7
|
+
intent: "Reach for this as the last section before the footer, repeating the hero's primary action once the reader has seen the case. Mid-page prompts to sign up belong inline, not in a band.",
|
|
8
|
+
notes: [
|
|
9
|
+
"Copied from the LandingPage page shell's closing call to action.",
|
|
10
|
+
"The primary action matches the hero's, so the page asks for one thing twice rather than two things once.",
|
|
11
|
+
"Sitting on a Card lifts it from the page without a coloured band, so it follows any preset."
|
|
12
|
+
],
|
|
13
|
+
a11y: [
|
|
14
|
+
"The section is labelled by its h2.",
|
|
15
|
+
"Both actions are links styled as Buttons, because they navigate."
|
|
16
|
+
]
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
ctaBandBlockMeta
|
|
20
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/blocks/danger-zone-block.tsx
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Button } from "../components/button/index.js";
|
|
4
|
+
import { Card, CardDescription, CardFooter, CardHeader, CardTitle } from "../components/card/index.js";
|
|
5
|
+
import { DestructiveActionModal } from "../components/destructive-action-modal/index.js";
|
|
6
|
+
import { cn } from "../lib/cn.js";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var account = { handle: "ada", editions: 12 };
|
|
9
|
+
function DangerZoneBlock({ className, framed = true, onDelete }) {
|
|
10
|
+
const [open, setOpen] = useState(false);
|
|
11
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12
|
+
/* @__PURE__ */ jsxs(Card, { variant: framed ? "default" : "flat", className: cn("w-full max-w-2xl", className), children: [
|
|
13
|
+
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
14
|
+
/* @__PURE__ */ jsx(CardTitle, { render: /* @__PURE__ */ jsx("h2", {}), children: "Delete account" }),
|
|
15
|
+
/* @__PURE__ */ jsx(CardDescription, { children: "Permanently remove your profile, editions, and sales history. Collectors keep the editions they own." })
|
|
16
|
+
] }),
|
|
17
|
+
/* @__PURE__ */ jsx(CardFooter, { actions: true, className: "justify-end", children: /* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: () => setOpen(true), children: "Delete account" }) })
|
|
18
|
+
] }),
|
|
19
|
+
/* @__PURE__ */ jsx(
|
|
20
|
+
DestructiveActionModal,
|
|
21
|
+
{
|
|
22
|
+
open,
|
|
23
|
+
onOpenChange: setOpen,
|
|
24
|
+
title: "Delete your account?",
|
|
25
|
+
description: `This permanently removes your profile, ${account.editions} editions, and sales history. Pending payouts are still sent. This can't be undone.`,
|
|
26
|
+
confirmLabel: "Delete account",
|
|
27
|
+
confirmingLabel: "Deleting\u2026",
|
|
28
|
+
confirmText: account.handle,
|
|
29
|
+
onConfirm: () => {
|
|
30
|
+
setOpen(false);
|
|
31
|
+
onDelete?.();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
] });
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
DangerZoneBlock
|
|
39
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/blocks/danger-zone-block.meta.ts
|
|
2
|
+
var dangerZoneBlockMeta = {
|
|
3
|
+
name: "DangerZoneBlock",
|
|
4
|
+
family: "Settings & team",
|
|
5
|
+
kind: "card",
|
|
6
|
+
width: { min: "20rem", max: "42rem" },
|
|
7
|
+
summary: "A delete-account card: what deleting removes and what survives, one destructive Button, and a DestructiveActionModal that asks for the handle to be typed before it acts.",
|
|
8
|
+
intent: "Reach for this as the last section of account, workspace or project settings. Deleting a single record from a list is an OverflowMenu item that opens DestructiveActionModal directly, not a card.",
|
|
9
|
+
notes: [
|
|
10
|
+
"Copied from the SettingsPage page shell's Delete account section.",
|
|
11
|
+
"The button never acts directly: it opens the modal, whose confirm stays disabled until the handle is typed.",
|
|
12
|
+
'The description says what is lost AND what is kept ("Collectors keep the editions they own"), which is what people want to know before they decide.'
|
|
13
|
+
],
|
|
14
|
+
a11y: [
|
|
15
|
+
"DestructiveActionModal is an alertdialog: focus opens on Cancel and the backdrop does not dismiss it.",
|
|
16
|
+
"The CardTitle is an h2, so the section is reachable by heading."
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
dangerZoneBlockMeta
|
|
21
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// src/blocks/device-comparison-block.tsx
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { BarChart } from "../components/bar-chart/index.js";
|
|
4
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/card/index.js";
|
|
5
|
+
import { Toggle, ToggleGroup } from "../components/toggle/index.js";
|
|
6
|
+
import { cn } from "../lib/cn.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var days = Array.from({ length: 30 }, (_, i) => ({
|
|
9
|
+
date: new Date(2026, 8, 1 + i).toISOString().slice(0, 10),
|
|
10
|
+
desktop: Math.round(320 + Math.sin(i / 3) * 90 + i % 5 * 14),
|
|
11
|
+
mobile: Math.round(260 + Math.cos(i / 4) * 80 + i % 4 * 18)
|
|
12
|
+
}));
|
|
13
|
+
var series = [
|
|
14
|
+
{ key: "desktop", label: "Desktop" },
|
|
15
|
+
{ key: "mobile", label: "Mobile" }
|
|
16
|
+
];
|
|
17
|
+
var shortDate = (iso) => (/* @__PURE__ */ new Date(`${iso}T00:00:00`)).toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
18
|
+
function DeviceComparisonBlock({ className, framed = true }) {
|
|
19
|
+
const [active, setActive] = useState("desktop");
|
|
20
|
+
const totals = Object.fromEntries(series.map((s) => [s.key, days.reduce((sum, d) => sum + d[s.key], 0)]));
|
|
21
|
+
const current = series.find((s) => s.key === active) ?? series[0];
|
|
22
|
+
return (
|
|
23
|
+
// overflow-hidden: the square tiles meet the card's rounded corner.
|
|
24
|
+
/* @__PURE__ */ jsxs(Card, { variant: framed ? "default" : "flat", className: cn("w-full max-w-3xl overflow-hidden", className), children: [
|
|
25
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col border-b border-border sm:flex-row", children: [
|
|
26
|
+
/* @__PURE__ */ jsxs(CardHeader, { className: "flex-1 pb-[var(--card-p,--spacing(6))]", children: [
|
|
27
|
+
/* @__PURE__ */ jsx(CardTitle, { render: /* @__PURE__ */ jsx("h2", {}), children: "Visitors by device" }),
|
|
28
|
+
/* @__PURE__ */ jsx(CardDescription, { children: "The last 30 days. Pick a device to plot it." })
|
|
29
|
+
] }),
|
|
30
|
+
/* @__PURE__ */ jsx(
|
|
31
|
+
ToggleGroup,
|
|
32
|
+
{
|
|
33
|
+
value: [active],
|
|
34
|
+
onValueChange: (v) => v[0] && setActive(String(v[0])),
|
|
35
|
+
"aria-label": "Device",
|
|
36
|
+
className: "items-stretch gap-0",
|
|
37
|
+
children: series.map((s) => /* @__PURE__ */ jsxs(
|
|
38
|
+
Toggle,
|
|
39
|
+
{
|
|
40
|
+
value: s.key,
|
|
41
|
+
className: "h-auto flex-1 flex-col items-start justify-center gap-1 rounded-none border-border px-6 py-4 text-start text-foreground max-sm:border-t sm:border-s",
|
|
42
|
+
children: [
|
|
43
|
+
/* @__PURE__ */ jsx("span", { className: "text-caption text-muted-foreground", children: s.label }),
|
|
44
|
+
/* @__PURE__ */ jsx("span", { className: "text-mono-lg", children: totals[s.key].toLocaleString("en-US") })
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
s.key
|
|
48
|
+
))
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
] }),
|
|
52
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(
|
|
53
|
+
BarChart,
|
|
54
|
+
{
|
|
55
|
+
label: `${current.label} visitors per day, last 30 days`,
|
|
56
|
+
data: days,
|
|
57
|
+
index: "date",
|
|
58
|
+
series: [current],
|
|
59
|
+
indexFormatter: shortDate,
|
|
60
|
+
radius: 3,
|
|
61
|
+
className: "h-64"
|
|
62
|
+
}
|
|
63
|
+
) })
|
|
64
|
+
] })
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
DeviceComparisonBlock
|
|
69
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/blocks/device-comparison-block.meta.ts
|
|
2
|
+
var deviceComparisonBlockMeta = {
|
|
3
|
+
name: "DeviceComparisonBlock",
|
|
4
|
+
family: "Dashboard",
|
|
5
|
+
kind: "card",
|
|
6
|
+
width: { min: "20rem", max: "48rem" },
|
|
7
|
+
summary: "A comparison card: each series' total sits in the header as a pressable tile, and the one pressed is plotted below as a daily BarChart.",
|
|
8
|
+
intent: "Reach for this when two or three measures share a page and the reader looks at one at a time \u2014 devices, regions, plans. To see them together, plot both in one BarChart or LineChart instead.",
|
|
9
|
+
notes: [
|
|
10
|
+
"The totals are the switch: Toggles in a labelled ToggleGroup, so the number and the control are one thing, with the group's own pressed and hover states.",
|
|
11
|
+
"Switching eases every bar to its new height rather than redrawing.",
|
|
12
|
+
"Below sm the tiles stack under the title and divide with a top rule instead of a side rule."
|
|
13
|
+
],
|
|
14
|
+
a11y: [
|
|
15
|
+
'Each total is a Toggle (aria-pressed) named by its label and value, in a ToggleGroup labelled "Device" with arrow-key movement between tiles.',
|
|
16
|
+
"The chart's name says which series is plotted, so the data table is unambiguous."
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
deviceComparisonBlockMeta
|
|
21
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/blocks/event-card-block.tsx
|
|
2
|
+
import { Avatar, AvatarGroup } from "../components/avatar/index.js";
|
|
3
|
+
import { Badge } from "../components/badge/index.js";
|
|
4
|
+
import { Button } from "../components/button/index.js";
|
|
5
|
+
import { Card, CardContent, CardDescription, CardFooter, CardTitle } from "../components/card/index.js";
|
|
6
|
+
import { DateTile } from "../components/date-tile/index.js";
|
|
7
|
+
import { cn } from "../lib/cn.js";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var event = {
|
|
10
|
+
title: "Design review",
|
|
11
|
+
date: new Date(2026, 9, 14),
|
|
12
|
+
when: "Tuesday, 2:00 \u2013 2:45 PM",
|
|
13
|
+
starts: "In 10 min",
|
|
14
|
+
attendees: ["MO", "SR", "JL"],
|
|
15
|
+
total: 7
|
|
16
|
+
};
|
|
17
|
+
function EventCardBlock({ className, framed = true, onRespond }) {
|
|
18
|
+
return /* @__PURE__ */ jsxs(Card, { variant: framed ? "default" : "flat", className: cn("w-full max-w-xs", className), children: [
|
|
19
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "flex gap-4", children: [
|
|
20
|
+
/* @__PURE__ */ jsx(DateTile, { date: event.date }),
|
|
21
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-x-2 text-title-lg", children: [
|
|
23
|
+
/* @__PURE__ */ jsx(CardTitle, { children: event.title }),
|
|
24
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-[1lh] shrink-0 items-center", children: /* @__PURE__ */ jsx(Badge, { tone: "info", size: "sm", children: event.starts }) })
|
|
25
|
+
] }),
|
|
26
|
+
/* @__PURE__ */ jsx(CardDescription, { children: event.when })
|
|
27
|
+
] })
|
|
28
|
+
] }),
|
|
29
|
+
/* @__PURE__ */ jsxs(CardFooter, { className: "flex-wrap justify-between gap-3", children: [
|
|
30
|
+
/* @__PURE__ */ jsx(AvatarGroup, { "aria-label": `${event.total} attendees`, total: event.total, size: "sm", surface: framed ? "card" : void 0, fit: true, children: event.attendees.map((initials) => /* @__PURE__ */ jsx(Avatar, { variant: "art", fallback: initials, alt: initials }, initials)) }),
|
|
31
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
32
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: () => onRespond?.("decline"), children: "Decline" }),
|
|
33
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: () => onRespond?.("join"), children: "Join" })
|
|
34
|
+
] })
|
|
35
|
+
] })
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
EventCardBlock
|
|
40
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/blocks/event-card-block.meta.ts
|
|
2
|
+
var eventCardBlockMeta = {
|
|
3
|
+
name: "EventCardBlock",
|
|
4
|
+
family: "Dashboard",
|
|
5
|
+
kind: "card",
|
|
6
|
+
width: { min: "18rem", max: "20rem" },
|
|
7
|
+
summary: 'An upcoming-event card: a DateTile beside the title and time, a "starts in" Badge, attendees as an AvatarGroup, and Decline / Join.',
|
|
8
|
+
intent: "Reach for this for the next meeting, booking or live session on a dashboard or home screen. For a list of many upcoming events, use Entity rows with a DateTile as `leading`.",
|
|
9
|
+
notes: [
|
|
10
|
+
"The DateTile names the day; the full weekday and time range sit in text beside it.",
|
|
11
|
+
"The Badge is one title line tall and wraps under the title rather than squeezing it onto two lines.",
|
|
12
|
+
"AvatarGroup `fit` trades avatars for the +N count before it pushes the actions to their own line."
|
|
13
|
+
],
|
|
14
|
+
a11y: [
|
|
15
|
+
"DateTile is a <time> with a machine-readable date; the time range is plain text read in order after the title.",
|
|
16
|
+
"The AvatarGroup's aria-label states the total attendee count."
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
eventCardBlockMeta
|
|
21
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/blocks/faq-block.tsx
|
|
2
|
+
import { useId } from "react";
|
|
3
|
+
import { Accordion, AccordionItem, AccordionPanel, AccordionTrigger } from "../components/accordion/index.js";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { Region, Stack } from "../layout/index.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
var intro = {
|
|
8
|
+
title: "Questions, answered",
|
|
9
|
+
lede: "Can't find what you need?",
|
|
10
|
+
contact: { label: "Write to us", href: "/contact" }
|
|
11
|
+
};
|
|
12
|
+
var questions = [
|
|
13
|
+
{ q: "Is there a free plan?", a: "Yes. Starter is free forever for three live editions, with no fees on your first $1,000 in sales." },
|
|
14
|
+
{ q: "Can I change plans later?", a: "Any time. Upgrades apply immediately and are prorated; downgrades take effect at the end of the billing period." },
|
|
15
|
+
{ q: "Who owns the work I sell?", a: "You do. Collectors own the editions they buy, and you keep the rights to the work itself." },
|
|
16
|
+
{ q: "How do payouts work?", a: "Sales clear after seven days and are paid out every Friday to the account you connect in settings." }
|
|
17
|
+
];
|
|
18
|
+
function FaqBlock({ className }) {
|
|
19
|
+
const titleId = useId();
|
|
20
|
+
return /* @__PURE__ */ jsx(Region, { as: "section", "aria-labelledby": titleId, max: "content", className: cn("w-full py-16", className), children: /* @__PURE__ */ jsxs("div", { className: "grid gap-10 md:grid-cols-[1fr_2fr]", children: [
|
|
21
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
22
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, className: "text-balance text-heading-2", children: intro.title }),
|
|
23
|
+
/* @__PURE__ */ jsxs("p", { className: "text-body-md text-muted-foreground", children: [
|
|
24
|
+
intro.lede,
|
|
25
|
+
" ",
|
|
26
|
+
/* @__PURE__ */ jsx("a", { href: intro.contact.href, className: "text-foreground underline underline-offset-4 motion-interactive hover:text-muted-foreground", children: intro.contact.label }),
|
|
27
|
+
"."
|
|
28
|
+
] })
|
|
29
|
+
] }),
|
|
30
|
+
/* @__PURE__ */ jsx(Accordion, { children: questions.map((item) => /* @__PURE__ */ jsxs(AccordionItem, { value: item.q, children: [
|
|
31
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { children: item.q }),
|
|
32
|
+
/* @__PURE__ */ jsx(AccordionPanel, { children: item.a })
|
|
33
|
+
] }, item.q)) })
|
|
34
|
+
] }) });
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
FaqBlock
|
|
38
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/blocks/faq-block.meta.ts
|
|
2
|
+
var faqBlockMeta = {
|
|
3
|
+
name: "FaqBlock",
|
|
4
|
+
family: "Marketing",
|
|
5
|
+
kind: "section",
|
|
6
|
+
summary: "A FAQ section: the heading and a way to ask beside an Accordion of questions, each answer one or two sentences.",
|
|
7
|
+
intent: "Reach for this near pricing or at the end of a landing page, for the questions that block a decision. Long help content belongs in docs, not an accordion.",
|
|
8
|
+
notes: [
|
|
9
|
+
"Every question starts closed: the list of questions is itself the useful summary.",
|
|
10
|
+
"The way to ask a human sits beside the heading, so it is found before the reader scrolls the list.",
|
|
11
|
+
"Capped at the `content` region width; questions wider than that are hard to scan."
|
|
12
|
+
],
|
|
13
|
+
a11y: [
|
|
14
|
+
"Accordion triggers are buttons with aria-expanded, inside headings, so the questions are navigable by heading and operable by keyboard.",
|
|
15
|
+
"The contact link is a real <a> inside the lede sentence."
|
|
16
|
+
]
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
faqBlockMeta
|
|
20
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/blocks/feature-grid-block.tsx
|
|
2
|
+
import { useId } from "react";
|
|
3
|
+
import { Card, CardContent } from "../components/card/index.js";
|
|
4
|
+
import { Icon } from "../icon/index.js";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { Grid, Region, Stack } from "../layout/index.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var intro = {
|
|
9
|
+
eyebrow: "Why Sable",
|
|
10
|
+
title: "A design system with the rules written down",
|
|
11
|
+
lede: "The decisions a senior designer would make are encoded once, so every screen your team or your agent builds starts from them."
|
|
12
|
+
};
|
|
13
|
+
var features = [
|
|
14
|
+
{ icon: "component", title: "Behavior built in", body: "Focus management, keyboard navigation, and ARIA come from Base UI primitives under every control." },
|
|
15
|
+
{ icon: "eyedropper", title: "Semantic tokens end to end", body: "Re-theme the whole product, light and dark, from one preset without touching a component." },
|
|
16
|
+
{ icon: "layout", title: "Pages, not just parts", body: "Landing, dashboard, settings, auth, and list-detail shells to copy and adapt." },
|
|
17
|
+
{ icon: "book", title: "A contract agents can read", body: "registry.json, llms.txt, and a CLI hand agents the exact props, examples, and rules." },
|
|
18
|
+
{ icon: "circle-check", title: "Lint that knows the design", body: "sable-lint flags raw colors, hand-built controls, and motion that ignores reduced motion." },
|
|
19
|
+
{ icon: "play", title: "Motion with an off switch", body: "Named recipes run on one scale variable, so reduced motion stops every transition at once." }
|
|
20
|
+
];
|
|
21
|
+
function FeatureGridBlock({ className }) {
|
|
22
|
+
const titleId = useId();
|
|
23
|
+
return /* @__PURE__ */ jsx(Region, { as: "section", "aria-labelledby": titleId, max: "wide", className: cn("w-full py-16 sm:py-24", className), children: /* @__PURE__ */ jsxs(Stack, { gap: 10, children: [
|
|
24
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 3, className: "max-w-2xl", children: [
|
|
25
|
+
/* @__PURE__ */ jsx("p", { className: "text-overline text-muted-foreground", children: intro.eyebrow }),
|
|
26
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, className: "text-balance text-heading-1", children: intro.title }),
|
|
27
|
+
/* @__PURE__ */ jsx("p", { className: "text-body-lg text-muted-foreground", children: intro.lede })
|
|
28
|
+
] }),
|
|
29
|
+
/* @__PURE__ */ jsx(Grid, { cols: { base: 1, sm: 2, lg: 3 }, gap: 4, children: features.map((feature) => /* @__PURE__ */ jsx(Card, { render: /* @__PURE__ */ jsx("article", {}), className: "h-full", children: /* @__PURE__ */ jsxs(CardContent, { className: "flex flex-col gap-3", children: [
|
|
30
|
+
/* @__PURE__ */ jsx("span", { className: "grid size-10 place-items-center rounded-md sable-well", children: /* @__PURE__ */ jsx(Icon, { name: feature.icon, className: "text-xl" }) }),
|
|
31
|
+
/* @__PURE__ */ jsx("h3", { className: "pt-2 text-title-lg", children: feature.title }),
|
|
32
|
+
/* @__PURE__ */ jsx("p", { className: "text-body-sm text-muted-foreground", children: feature.body })
|
|
33
|
+
] }) }, feature.title)) })
|
|
34
|
+
] }) });
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
FeatureGridBlock
|
|
38
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/blocks/feature-grid-block.meta.ts
|
|
2
|
+
var featureGridBlockMeta = {
|
|
3
|
+
name: "FeatureGridBlock",
|
|
4
|
+
family: "Marketing",
|
|
5
|
+
kind: "section",
|
|
6
|
+
summary: "A feature section: an overline, an h2 and a lede over a grid of article cards, each with an icon in a well, a title and one sentence \u2014 1, 2 then 3 columns.",
|
|
7
|
+
intent: "Reach for this to explain what a product does in six or fewer points. For a sequence (first this, then that), use StepsBlock; for one proof point with numbers, TestimonialBlock.",
|
|
8
|
+
notes: [
|
|
9
|
+
"Copied from the LandingPage page shell's features section.",
|
|
10
|
+
"Six features fill 3 \xD7 2 evenly; keep the count a multiple of three, or drop to cols={{ lg: 2 }}.",
|
|
11
|
+
"Each body is one sentence. A feature that needs a paragraph needs its own section.",
|
|
12
|
+
"Icons sit in a `sable-well`, which derives its fill from the card surface it is on."
|
|
13
|
+
],
|
|
14
|
+
a11y: [
|
|
15
|
+
"Each feature is an <article> with an h3 under the section's h2.",
|
|
16
|
+
"The icons are decorative; each title says what the feature is."
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
featureGridBlockMeta
|
|
21
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/blocks/feedback-form-block.tsx
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Button } from "../components/button/index.js";
|
|
4
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../components/card/index.js";
|
|
5
|
+
import { Textarea } from "../components/textarea/index.js";
|
|
6
|
+
import { Toggle, ToggleGroup } from "../components/toggle/index.js";
|
|
7
|
+
import { cn } from "../lib/cn.js";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var scale = ["1", "2", "3", "4", "5"];
|
|
10
|
+
function FeedbackFormBlock({ className, framed = true, onDone }) {
|
|
11
|
+
const [score, setScore] = useState("4");
|
|
12
|
+
const [notes, setNotes] = useState("");
|
|
13
|
+
return /* @__PURE__ */ jsxs(Card, { variant: framed ? "default" : "flat", className: cn("w-full max-w-xs", className), children: [
|
|
14
|
+
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
15
|
+
/* @__PURE__ */ jsx(CardTitle, { children: "How was the session?" }),
|
|
16
|
+
/* @__PURE__ */ jsx(CardDescription, { children: "One tap is enough. Notes help us more." })
|
|
17
|
+
] }),
|
|
18
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "flex flex-col gap-4", children: [
|
|
19
|
+
/* @__PURE__ */ jsx(ToggleGroup, { value: [score], onValueChange: (v) => v[0] && setScore(String(v[0])), "aria-label": "Rating", className: "w-full", children: scale.map((n) => /* @__PURE__ */ jsx(Toggle, { value: n, className: "flex-1", children: n }, n)) }),
|
|
20
|
+
/* @__PURE__ */ jsx(Textarea, { placeholder: "What worked, what didn\u2019t\u2026", "aria-label": "Notes", rows: 3, value: notes, onChange: (e) => setNotes(e.target.value) })
|
|
21
|
+
] }),
|
|
22
|
+
/* @__PURE__ */ jsxs(CardFooter, { actions: true, className: "justify-end", children: [
|
|
23
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => onDone?.(false), children: "Skip" }),
|
|
24
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: () => onDone?.(true, { score: Number(score), notes }), children: "Send feedback" })
|
|
25
|
+
] })
|
|
26
|
+
] });
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
FeedbackFormBlock
|
|
30
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/blocks/feedback-form-block.meta.ts
|
|
2
|
+
var feedbackFormBlockMeta = {
|
|
3
|
+
name: "FeedbackFormBlock",
|
|
4
|
+
family: "Social & messaging",
|
|
5
|
+
kind: "card",
|
|
6
|
+
width: { min: "18rem", max: "20rem" },
|
|
7
|
+
summary: "A feedback card: a one-to-five rating as a full-width ToggleGroup, an optional notes field, and Skip / Send feedback.",
|
|
8
|
+
intent: "Reach for this for a post-session or post-purchase survey in a Sheet, Dialog or end-of-flow screen. For a feedback control anchored to a button in the app chrome, use the Feedback component (a popover).",
|
|
9
|
+
notes: [
|
|
10
|
+
"The rating is preselected, so one tap on Send is a complete answer; the notes are optional and say so.",
|
|
11
|
+
"Skip is a ghost Button before the primary, so dismissing is always available and never competes with sending.",
|
|
12
|
+
"`onDone` reports whether feedback was sent and, if so, the score and notes."
|
|
13
|
+
],
|
|
14
|
+
a11y: [
|
|
15
|
+
`The ToggleGroup carries aria-label="Rating"; each Toggle's number is its name.`,
|
|
16
|
+
'The Textarea carries aria-label="Notes"; its placeholder is a prompt, not the label.'
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
feedbackFormBlockMeta
|
|
21
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/blocks/goal-progress-block.tsx
|
|
2
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../components/card/index.js";
|
|
3
|
+
import { RadialChart } from "../components/radial-chart/index.js";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
var goals = [
|
|
7
|
+
{ goal: "Releases", progress: 82 },
|
|
8
|
+
{ goal: "Collectors", progress: 64 },
|
|
9
|
+
{ goal: "Revenue", progress: 91 }
|
|
10
|
+
];
|
|
11
|
+
function GoalProgressBlock({ className, framed = true }) {
|
|
12
|
+
const behind = goals.filter((g) => g.progress < 70);
|
|
13
|
+
return /* @__PURE__ */ jsxs(Card, { variant: framed ? "default" : "flat", className: cn("w-full max-w-sm", className), children: [
|
|
14
|
+
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
15
|
+
/* @__PURE__ */ jsx(CardTitle, { render: /* @__PURE__ */ jsx("h2", {}), children: "Quarter goals" }),
|
|
16
|
+
/* @__PURE__ */ jsx(CardDescription, { children: "Progress toward each target, in percent." })
|
|
17
|
+
] }),
|
|
18
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(RadialChart, { label: "Progress toward quarter goals", data: goals, index: "goal", valueKey: "progress", max: 100, className: "h-64", valueFormatter: (v) => `${v}%` }) }),
|
|
19
|
+
/* @__PURE__ */ jsx(CardFooter, { className: "text-body-sm text-muted-foreground", children: behind.length ? `${behind.map((g) => g.goal).join(" and ")} behind pace.` : "Every goal on pace." })
|
|
20
|
+
] });
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
GoalProgressBlock
|
|
24
|
+
};
|