@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,218 @@
|
|
|
1
|
+
// src/components/area-chart/area-chart.meta.ts
|
|
2
|
+
var areaChartMeta = {
|
|
3
|
+
name: "AreaChart",
|
|
4
|
+
summary: "A trend over a sequence, filled to the baseline: overlapping translucent series, stacked, or stacked to 100%, with smooth, linear or step curves and optional gradient fills. The line draws on and the fill rises as it scrolls into view.",
|
|
5
|
+
keywords: [
|
|
6
|
+
"chart",
|
|
7
|
+
"area",
|
|
8
|
+
"trend",
|
|
9
|
+
"time series",
|
|
10
|
+
"stacked",
|
|
11
|
+
"graph",
|
|
12
|
+
"analytics",
|
|
13
|
+
"dashboard",
|
|
14
|
+
"visitors",
|
|
15
|
+
"revenue"
|
|
16
|
+
],
|
|
17
|
+
usage: {
|
|
18
|
+
description: 'Use AreaChart for volume over time \u2014 visitors, revenue, usage \u2014 where the filled shape helps the eye read the size of the total. Stack the series to show a total and its parts; `stacked="expand"` shows each category as 100%. For comparing how measures move relative to each other, LineChart is cleaner; for amounts per category, BarChart.',
|
|
19
|
+
bestPractices: [
|
|
20
|
+
{
|
|
21
|
+
guidance: "do",
|
|
22
|
+
description: "Keep to one to three series; past that the tints muddy \u2014 stack them or switch to LineChart."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
guidance: "do",
|
|
26
|
+
description: "Set a height on className (h-72, aspect-video h-auto); the chart fills the box it is given."
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
guidance: "dont",
|
|
30
|
+
description: "Overlap more than two unstacked series \u2014 the translucent tints blend into a colour no series has."
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
guidance: "dont",
|
|
34
|
+
description: "Use it for data-heavy views \u2014 streaming or real-time data, thousands of points, zoom and brushing, trading charts. Those belong on a charting library (Recharts, visx, ECharts); Sable's charts are for dashboards, landing pages and decks."
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
related: {
|
|
39
|
+
components: [
|
|
40
|
+
"LineChart",
|
|
41
|
+
"BarChart",
|
|
42
|
+
"Sparkline",
|
|
43
|
+
"Card"
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
status: "beta",
|
|
47
|
+
props: [
|
|
48
|
+
{
|
|
49
|
+
name: "data",
|
|
50
|
+
type: "Record<string, unknown>[]",
|
|
51
|
+
description: "The rows, in order along the category axis."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "index",
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "The datum field naming each row's category (a month, a day, a channel)."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "series",
|
|
60
|
+
type: "{ key: string; label: string; tone?: ChartTone; color?: string; icon?: string }[]",
|
|
61
|
+
description: "The measures to plot: the datum field, its name in the legend/tooltip/table, and its colour (a tone by role, or any CSS colour). Omitted, series take the chart palette in order: --chart-1 \u2026 --chart-8, validated for colour-blind separation in light and dark; a theme may override the set."
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "label",
|
|
65
|
+
type: "string",
|
|
66
|
+
description: "What the chart shows. Its accessible name and the caption of the data table assistive tech reads."
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "className",
|
|
70
|
+
type: "string",
|
|
71
|
+
default: '"h-60"',
|
|
72
|
+
description: "Sizes the chart (plot + legend). Set a height: `h-72`, `aspect-video h-auto`."
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "valueFormatter",
|
|
76
|
+
type: "(value: number) => string",
|
|
77
|
+
description: 'Format values everywhere (axis, labels, tooltip, table) \u2014 units like "$12,480". Default: compact on the axis, full elsewhere.'
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "indexFormatter",
|
|
81
|
+
type: "(value: string) => string",
|
|
82
|
+
description: 'Shorten category labels on the axis ("January" \u2192 "Jan"); the tooltip keeps the full value.'
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "locale",
|
|
86
|
+
type: "string",
|
|
87
|
+
default: "runtime locale",
|
|
88
|
+
description: "BCP 47 locale for default number and date formatting."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "tooltip",
|
|
92
|
+
type: 'boolean | { indicator?: "dot" | "line" | "dashed" | "none"; hideLabel?: boolean; labelFormatter?: (label, datum) => ReactNode; showTotal?: boolean }',
|
|
93
|
+
default: "true",
|
|
94
|
+
description: "Show a tooltip on hover and keyboard focus, or configure it: the row marker, hiding the heading, rewriting it, adding a Total row."
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "legend",
|
|
98
|
+
type: "boolean",
|
|
99
|
+
default: "true when there is more than one series",
|
|
100
|
+
description: "Show the legend under the chart."
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "grid",
|
|
104
|
+
type: "boolean",
|
|
105
|
+
default: "true (false for horizontal bars)",
|
|
106
|
+
description: "Hairline gridlines along the value axis."
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "xAxis",
|
|
110
|
+
type: "boolean",
|
|
111
|
+
default: "true for columns; false for horizontal bars",
|
|
112
|
+
description: "The horizontal axis."
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "yAxis",
|
|
116
|
+
type: "boolean",
|
|
117
|
+
default: "false for columns; true for horizontal bars",
|
|
118
|
+
description: "The vertical axis."
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "animate",
|
|
122
|
+
type: "boolean",
|
|
123
|
+
default: "true",
|
|
124
|
+
description: "Play the arrival once the chart scrolls into view. Reduced motion shows the finished chart."
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "activeIndex",
|
|
128
|
+
type: "number | null",
|
|
129
|
+
description: "The highlighted row (controlled); `null` for none."
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "defaultActiveIndex",
|
|
133
|
+
type: "number | null",
|
|
134
|
+
description: "The row highlighted at first \u2014 a tooltip already open before anyone hovers."
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "onActiveIndexChange",
|
|
138
|
+
type: "(index: number | null) => void",
|
|
139
|
+
description: "Called as the pointer or keyboard moves between rows."
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "curve",
|
|
143
|
+
type: '"smooth" | "linear" | "step"',
|
|
144
|
+
default: '"smooth"',
|
|
145
|
+
description: "How the line runs between points. `smooth` is monotone: it never overshoots a value the data does not contain."
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "stacked",
|
|
149
|
+
type: 'boolean | "expand"',
|
|
150
|
+
default: "false",
|
|
151
|
+
description: 'Stack the series, or `"expand"` to show each category as 100%.'
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "gradient",
|
|
155
|
+
type: "boolean",
|
|
156
|
+
default: "false",
|
|
157
|
+
description: "Fill each area with a fade from its colour to transparent instead of a flat tint."
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
tokensUsed: [
|
|
161
|
+
"tone-edition",
|
|
162
|
+
"tone-collectible",
|
|
163
|
+
"tone-standard",
|
|
164
|
+
"tone-info",
|
|
165
|
+
"tone-warning",
|
|
166
|
+
"primary",
|
|
167
|
+
"muted-foreground",
|
|
168
|
+
"border",
|
|
169
|
+
"popover",
|
|
170
|
+
"popover-foreground",
|
|
171
|
+
"foreground",
|
|
172
|
+
"background"
|
|
173
|
+
],
|
|
174
|
+
motion: [
|
|
175
|
+
{
|
|
176
|
+
slot: "arrival",
|
|
177
|
+
recipe: "custom",
|
|
178
|
+
part: "Area + line",
|
|
179
|
+
why: "Once on screen, each line draws on (stroke-dashoffset) and its fill rises from the baseline, series staggered \u2014 the trend is read as it is drawn. On the motion tokens; reduced motion shows the finished chart."
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
slot: "response",
|
|
183
|
+
recipe: "none",
|
|
184
|
+
part: "Cursor + tooltip",
|
|
185
|
+
why: "Hover and focus move the cursor and tooltip instantly \u2014 a lagging cursor reads as a slow chart."
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
slot: "transition",
|
|
189
|
+
recipe: "custom",
|
|
190
|
+
part: "Area + line",
|
|
191
|
+
why: "Geometry eases from the old shape to the new one through a CSS `d` transition on the motion tokens (no recipe animates path geometry); browsers without `d` transitions update in place."
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
slot: "activity",
|
|
195
|
+
recipe: "none",
|
|
196
|
+
part: "AreaChart",
|
|
197
|
+
why: "A chart has no indeterminate state; show a Skeleton while the data loads."
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
a11y: [
|
|
201
|
+
"The drawing is aria-hidden; the same numbers are in a visually hidden data table (captioned by `label`) that the chart is aria-describedby, so assistive tech reads values, not shapes.",
|
|
202
|
+
'With a tooltip, the chart is one tab stop (role=group, aria-roledescription="chart"): arrow keys, Home and End step through the data, Escape clears, and each step is announced in a polite live region.',
|
|
203
|
+
"Colour is never the only key: series are named in the legend, tooltip and table."
|
|
204
|
+
],
|
|
205
|
+
examples: [
|
|
206
|
+
{
|
|
207
|
+
label: "Two series with a legend",
|
|
208
|
+
code: 'const visitors = [\n { month: "January", desktop: 186, mobile: 80 },\n { month: "February", desktop: 305, mobile: 200 },\n { month: "March", desktop: 237, mobile: 120 },\n { month: "April", desktop: 73, mobile: 190 },\n { month: "May", desktop: 209, mobile: 130 },\n { month: "June", desktop: 214, mobile: 140 },\n]\n\n<AreaChart\n label="Visitors, January to June"\n data={visitors}\n index="month"\n series={[\n { key: "desktop", label: "Desktop" },\n { key: "mobile", label: "Mobile" },\n ]}\n indexFormatter={(m) => m.slice(0, 3)}\n gradient\n/>'
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
label: "Stacked to 100%",
|
|
212
|
+
code: '<AreaChart\n label="Share of visitors by device"\n data={visitors}\n index="month"\n series={[\n { key: "desktop", label: "Desktop" },\n { key: "mobile", label: "Mobile" },\n ]}\n stacked="expand"\n yAxis\n tooltip={{ indicator: "line", showTotal: true }}\n/>'
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
};
|
|
216
|
+
export {
|
|
217
|
+
areaChartMeta
|
|
218
|
+
};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// src/components/attachment/attachment.tsx
|
|
2
|
+
import { Icon } from "../../icon/index.js";
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
import { useTypeTier } from "../../lib/density.js";
|
|
5
|
+
import { Progress, ProgressTrack } from "../progress/index.js";
|
|
6
|
+
import {
|
|
7
|
+
attachmentMediaVariants,
|
|
8
|
+
attachmentVariants
|
|
9
|
+
} from "./attachment.variants.js";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
function Attachment({
|
|
12
|
+
name,
|
|
13
|
+
meta,
|
|
14
|
+
thumbnail,
|
|
15
|
+
icon,
|
|
16
|
+
variant = "card",
|
|
17
|
+
status = "idle",
|
|
18
|
+
progress,
|
|
19
|
+
actions,
|
|
20
|
+
onOpen,
|
|
21
|
+
openLabel,
|
|
22
|
+
className,
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}) {
|
|
26
|
+
const glyph = icon ?? (thumbnail ? "image-stack" : "file");
|
|
27
|
+
const dot = name.lastIndexOf(".");
|
|
28
|
+
const hasExtension = dot > 0 && name.length - dot <= 6;
|
|
29
|
+
const stem = hasExtension ? name.slice(0, dot) : name;
|
|
30
|
+
const extension = hasExtension ? name.slice(dot) : "";
|
|
31
|
+
const isMedia = variant === "media";
|
|
32
|
+
const tier = useTypeTier();
|
|
33
|
+
const textLayer = onOpen ? "pointer-events-none" : void 0;
|
|
34
|
+
return /* @__PURE__ */ jsxs(
|
|
35
|
+
"div",
|
|
36
|
+
{
|
|
37
|
+
"data-status": status,
|
|
38
|
+
className: cn(
|
|
39
|
+
attachmentVariants({ variant, status, interactive: Boolean(onOpen) }),
|
|
40
|
+
className
|
|
41
|
+
),
|
|
42
|
+
...props,
|
|
43
|
+
children: [
|
|
44
|
+
onOpen ? (
|
|
45
|
+
// z-0 keeps this a local stacking concern inside the card's own
|
|
46
|
+
// `isolate`, not a bid in the global layer order.
|
|
47
|
+
/* @__PURE__ */ jsx(
|
|
48
|
+
"button",
|
|
49
|
+
{
|
|
50
|
+
type: "button",
|
|
51
|
+
onClick: onOpen,
|
|
52
|
+
className: "absolute inset-0 z-0 cursor-pointer rounded-[var(--attachment-radius,var(--radius-md))] motion-interactive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
|
|
53
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: openLabel ?? `Open ${name}` })
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
) : null,
|
|
57
|
+
/* @__PURE__ */ jsx("div", { className: cn(attachmentMediaVariants({ variant })), children: thumbnail ? (
|
|
58
|
+
// On a media tile the picture IS the label — there is no adjacent
|
|
59
|
+
// filename to read. On a card it sits next to one, so describing it
|
|
60
|
+
// again would just make AT say the name twice.
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
"img",
|
|
63
|
+
{
|
|
64
|
+
src: thumbnail,
|
|
65
|
+
alt: isMedia ? name : "",
|
|
66
|
+
className: "size-full object-cover",
|
|
67
|
+
loading: "lazy"
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
) : /* @__PURE__ */ jsx(Icon, { name: glyph, className: isMedia ? "text-2xl" : "text-lg" }) }),
|
|
71
|
+
isMedia ? (
|
|
72
|
+
/* On a media tile the name would cover the picture, so it only appears
|
|
73
|
+
when there is something to say — a size, an upload state, an error.
|
|
74
|
+
`bg-overlay` rather than a themed surface: this ink sits on arbitrary
|
|
75
|
+
imagery, not on a theme surface, and has to stay legible over both. */
|
|
76
|
+
meta || status !== "idle" ? /* @__PURE__ */ jsx(
|
|
77
|
+
"div",
|
|
78
|
+
{
|
|
79
|
+
className: cn(
|
|
80
|
+
"absolute inset-x-0 z-10 bg-overlay px-2 py-1",
|
|
81
|
+
// Clear the progress bar (h-1) on the same edge rather than
|
|
82
|
+
// letting it paint over the bottom of the text.
|
|
83
|
+
status === "uploading" ? "bottom-1" : "bottom-0",
|
|
84
|
+
textLayer
|
|
85
|
+
),
|
|
86
|
+
children: /* @__PURE__ */ jsx(
|
|
87
|
+
"p",
|
|
88
|
+
{
|
|
89
|
+
className: cn(
|
|
90
|
+
"truncate text-overlay-foreground",
|
|
91
|
+
tier.secondary
|
|
92
|
+
),
|
|
93
|
+
children: meta ?? name
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
) : null
|
|
98
|
+
) : /* @__PURE__ */ jsxs("div", { className: cn("z-10 min-w-0 flex-1", textLayer), children: [
|
|
99
|
+
/* @__PURE__ */ jsxs(
|
|
100
|
+
"p",
|
|
101
|
+
{
|
|
102
|
+
"data-slot": "attachment-name",
|
|
103
|
+
title: name,
|
|
104
|
+
className: cn("flex min-w-0 text-foreground", tier.body),
|
|
105
|
+
children: [
|
|
106
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: stem }),
|
|
107
|
+
extension ? /* @__PURE__ */ jsx("span", { className: "shrink-0", children: extension }) : null
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
meta ? (
|
|
112
|
+
// Truncated normally — a size and a type are recognisable from
|
|
113
|
+
// their first few characters. NOT on error: the reason is the
|
|
114
|
+
// only thing telling the reader whether to retry or pick a
|
|
115
|
+
// different file, and "Upload failed — over the 50 MB l…" is
|
|
116
|
+
// exactly the half of the sentence that does not help.
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
"p",
|
|
119
|
+
{
|
|
120
|
+
className: cn(
|
|
121
|
+
tier.secondary,
|
|
122
|
+
status === "error" ? "text-destructive" : "truncate text-muted-foreground"
|
|
123
|
+
),
|
|
124
|
+
children: meta
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
) : null,
|
|
128
|
+
status === "uploading" ? (
|
|
129
|
+
// In the text column, under the meta it measures — not along
|
|
130
|
+
// the card's bottom edge. On the edge the corner curve clipped
|
|
131
|
+
// the bar at rounder settings, and the track, read against
|
|
132
|
+
// whatever the card sits on, made the card look cut off.
|
|
133
|
+
/* @__PURE__ */ jsx(
|
|
134
|
+
Progress,
|
|
135
|
+
{
|
|
136
|
+
value: progress ?? null,
|
|
137
|
+
"aria-label": `Uploading ${name}`,
|
|
138
|
+
className: "mt-1.5 w-full",
|
|
139
|
+
children: /* @__PURE__ */ jsx(ProgressTrack, { className: "h-1" })
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
) : null
|
|
143
|
+
] }),
|
|
144
|
+
actions ? (
|
|
145
|
+
// On a media tile the picture fills the box, so in-flow actions were
|
|
146
|
+
// pushed below it and clipped away. They float on the top-end corner
|
|
147
|
+
// instead — pass `variant="floating"` buttons so they read on any image.
|
|
148
|
+
/* @__PURE__ */ jsx(
|
|
149
|
+
"div",
|
|
150
|
+
{
|
|
151
|
+
className: cn(
|
|
152
|
+
"z-10 flex shrink-0 items-center gap-1",
|
|
153
|
+
isMedia ? "absolute end-1 top-1" : "relative"
|
|
154
|
+
),
|
|
155
|
+
children: actions
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
) : null,
|
|
159
|
+
isMedia && status === "uploading" ? /* @__PURE__ */ jsx(
|
|
160
|
+
Progress,
|
|
161
|
+
{
|
|
162
|
+
value: progress ?? null,
|
|
163
|
+
"aria-label": `Uploading ${name}`,
|
|
164
|
+
className: "pointer-events-none absolute inset-x-0 bottom-0 z-10 w-full",
|
|
165
|
+
children: /* @__PURE__ */ jsx(ProgressTrack, { className: "h-1 rounded-none bg-muted" })
|
|
166
|
+
}
|
|
167
|
+
) : null,
|
|
168
|
+
children
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
Attachment.displayName = "Attachment";
|
|
174
|
+
export {
|
|
175
|
+
Attachment
|
|
176
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// src/components/attachment/attachment.meta.ts
|
|
2
|
+
var attachmentMeta = {
|
|
3
|
+
name: "Attachment",
|
|
4
|
+
summary: "A file or image attached to a message: media or icon lead, name and metadata, upload and error states, an actions slot, and a full-card trigger that keeps those actions separately clickable.",
|
|
5
|
+
status: "stable",
|
|
6
|
+
keywords: [
|
|
7
|
+
"attachment",
|
|
8
|
+
"file",
|
|
9
|
+
"upload",
|
|
10
|
+
"image preview",
|
|
11
|
+
"chat file",
|
|
12
|
+
"document",
|
|
13
|
+
"drag and drop",
|
|
14
|
+
"file card"
|
|
15
|
+
],
|
|
16
|
+
usage: {
|
|
17
|
+
description: "The card a file takes in a conversation \u2014 in the composer while it uploads, and in the transcript once it has. It renders all four states an attachment actually moves through (queued, uploading, failed, delivered) rather than only the delivered one, because the other three are the states that are hard to get right and would otherwise fall back on every caller.",
|
|
18
|
+
bestPractices: [
|
|
19
|
+
{
|
|
20
|
+
guidance: "do",
|
|
21
|
+
description: 'Use `variant="media"` for images and `variant="card"` for documents. A filename tells you nothing about a photo, and a thumbnail tells you nothing about a contract.'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
guidance: "do",
|
|
25
|
+
description: 'Pass `onOpen` rather than wrapping the card in your own button. It renders a stretched trigger underneath the actions, so the card is one tab stop, each action is its own, and clicking "remove" never opens the file.'
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
guidance: "do",
|
|
29
|
+
description: 'Give `status="uploading"` a numeric `progress` when you have one and omit it when you do not \u2014 the bar goes indeterminate rather than lying about 0%.'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
guidance: "do",
|
|
33
|
+
description: 'Put the reason in `meta` when `status="error"`. The card re-colors but keeps its shape, so a failed upload stays recognisable as the file it was \u2014 the text is what says why.'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
guidance: "dont",
|
|
37
|
+
description: "Do not nest interactive controls inside a card you have wrapped in a link or button yourself. That is invalid HTML and unreachable in the order it looks like; `onOpen` exists to avoid it."
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
guidance: "dont",
|
|
41
|
+
description: "Do not use it as a generic file-list row. `Tree` is the file listing; this one is shaped for a conversation, where an attachment is a message payload."
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
guidance: "dont",
|
|
45
|
+
description: "Do not rely on the error colour alone to signal failure. Colour is not a status for anyone who cannot see it \u2014 say what happened in `meta`."
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
anatomy: [
|
|
49
|
+
{
|
|
50
|
+
name: "Media",
|
|
51
|
+
required: true,
|
|
52
|
+
description: "Thumbnail crop or file glyph. Fills the tile in `media`, a lead square in `card`."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "Label",
|
|
56
|
+
required: true,
|
|
57
|
+
description: "Name and metadata. A row beside the media in `card`; a scrim strip over the picture in `media`, shown only when there is something to say."
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "Actions",
|
|
61
|
+
required: false,
|
|
62
|
+
description: "Remove / retry / download controls, stacked above the stretched trigger so they stay separately clickable."
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "Progress",
|
|
66
|
+
required: false,
|
|
67
|
+
description: 'A hairline bar along the bottom edge while `status="uploading"`; determinate with `progress`, indeterminate without.'
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
related: {
|
|
72
|
+
components: ["Message", "Bubble", "MessageScroller", "Progress"]
|
|
73
|
+
},
|
|
74
|
+
props: [
|
|
75
|
+
{
|
|
76
|
+
name: "name",
|
|
77
|
+
type: "string",
|
|
78
|
+
description: "File name. Truncated rather than wrapped \u2014 the stem truncates and a short extension stays visible \u2014 and used as the default label for the stretched trigger and the media tile's alt text."
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "meta",
|
|
82
|
+
type: "ReactNode",
|
|
83
|
+
description: "Size, type, upload progress, or the failure reason \u2014 the quiet second line."
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "thumbnail",
|
|
87
|
+
type: "string",
|
|
88
|
+
description: "Image preview URL. Present means the card shows a crop of the file instead of a glyph."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "icon",
|
|
92
|
+
type: "string",
|
|
93
|
+
default: '"file"',
|
|
94
|
+
description: 'Semantic icon name for a non-image file (resolved through IconProvider). Defaults to "image-stack" when a thumbnail is set.'
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "variant",
|
|
98
|
+
type: '"card" | "media"',
|
|
99
|
+
default: '"card"',
|
|
100
|
+
description: "`card` is a name-led horizontal row for documents; `media` is a square tile that is mostly picture."
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "status",
|
|
104
|
+
type: '"idle" | "uploading" | "error"',
|
|
105
|
+
default: '"idle"',
|
|
106
|
+
description: "Transfer state. `uploading` adds a progress bar; `error` re-colors the card without changing its shape."
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "progress",
|
|
110
|
+
type: "number",
|
|
111
|
+
description: "Percentage 0\u2013100 while uploading. Omit for an indeterminate bar."
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "actions",
|
|
115
|
+
type: "ReactNode",
|
|
116
|
+
description: 'Remove / retry / download controls. Stay clickable when `onOpen` makes the card a trigger. On a `media` tile they float on the top-end corner over the picture, so pass `variant="floating"` buttons there.'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "onOpen",
|
|
120
|
+
type: "() => void",
|
|
121
|
+
description: "Makes the whole card activate, via a stretched button rendered beneath the actions rather than by wrapping the card."
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: "openLabel",
|
|
125
|
+
type: "string",
|
|
126
|
+
default: "`Open ${name}`",
|
|
127
|
+
description: "Accessible label for that stretched trigger."
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "...div props",
|
|
131
|
+
type: 'Omit<ComponentPropsWithRef<"div">, "onClick">',
|
|
132
|
+
description: "Spread onto the card. Use `onOpen` rather than `onClick` \u2014 a click handler on a div is not a control."
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
variants: {
|
|
136
|
+
variant: ["card", "media"],
|
|
137
|
+
status: ["idle", "uploading", "error"]
|
|
138
|
+
},
|
|
139
|
+
tokensUsed: [
|
|
140
|
+
"card",
|
|
141
|
+
"border",
|
|
142
|
+
"border-strong",
|
|
143
|
+
"muted",
|
|
144
|
+
"muted-foreground",
|
|
145
|
+
"foreground",
|
|
146
|
+
"destructive",
|
|
147
|
+
"overlay",
|
|
148
|
+
"overlay-foreground",
|
|
149
|
+
"ring"
|
|
150
|
+
],
|
|
151
|
+
a11y: [
|
|
152
|
+
"The full-card trigger is a real stretched `<button>` with an accessible label, not a click handler on a div \u2014 so it is one tab stop, keyboard-activatable, and focus-ringed.",
|
|
153
|
+
"Actions sit above that trigger in the stacking order, which keeps them individually focusable and stops a click on `remove` from also opening the file. Text is only made click-through when a trigger is present, so a filename stays selectable otherwise.",
|
|
154
|
+
"A thumbnail is described as the attachment in `media` (where the picture is the only label) and left decorative in `card` (where the filename is right beside it), so AT never reads the same name twice.",
|
|
155
|
+
"The upload bar carries an accessible name via Progress; the error state is carried by text in `meta` as well as colour.",
|
|
156
|
+
"Label text on a media tile sits on `overlay` / `overlay-foreground` \u2014 a fixed pairing that stays legible over arbitrary imagery, where a theme surface token would not."
|
|
157
|
+
],
|
|
158
|
+
examples: [
|
|
159
|
+
{
|
|
160
|
+
label: "Document with a remove action",
|
|
161
|
+
code: '<Attachment name="proposal.pdf" meta="2.4 MB \xB7 PDF" onOpen={() => open(file)} actions={<Button variant="ghost" size="icon-xs" aria-label="Remove"><Icon name="xmark" /></Button>} />'
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
label: "Image tile, uploading",
|
|
165
|
+
code: '<Attachment variant="media" name="cover.png" thumbnail={previewUrl} status="uploading" progress={62} meta="Uploading\u2026 62%" />'
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
label: "Failed upload with a retry",
|
|
169
|
+
code: '<Attachment name="recording.mov" meta="Upload failed \u2014 file is over the 50 MB limit" status="error" icon="warning" actions={<Button variant="ghost" size="xs" onClick={retry}>Retry</Button>} />'
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
label: "Attachments as a message payload",
|
|
173
|
+
code: '<Message messageId="m7" align="end" footer={<RelativeTime date={sentAt} />}>\n <div className="flex flex-wrap gap-2">\n {files.map((f) => (<Attachment key={f.id} variant="media" name={f.name} thumbnail={f.url} onOpen={() => open(f)} />))}\n </div>\n</Message>'
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
};
|
|
177
|
+
export {
|
|
178
|
+
attachmentMeta
|
|
179
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/components/attachment/attachment.variants.ts
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
var attachmentVariants = cva(
|
|
4
|
+
"group/attachment relative isolate overflow-hidden rounded-[var(--attachment-radius,var(--radius-md))] border text-start motion-interactive",
|
|
5
|
+
{
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
// The inset grows with the corner radius (half of it, never under 8px), so a
|
|
9
|
+
// rounder card does not crowd its tile and progress bar into the curve.
|
|
10
|
+
card: "flex w-full max-w-xs items-center gap-3 p-[max(--spacing(2),calc(var(--attachment-radius,var(--radius-md))/2))]",
|
|
11
|
+
media: "block size-28"
|
|
12
|
+
},
|
|
13
|
+
status: {
|
|
14
|
+
idle: "border-border bg-card",
|
|
15
|
+
uploading: "border-border bg-card",
|
|
16
|
+
error: "border-destructive/40 bg-destructive/5"
|
|
17
|
+
},
|
|
18
|
+
interactive: {
|
|
19
|
+
true: "hover:border-border-strong",
|
|
20
|
+
false: ""
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: "card",
|
|
25
|
+
status: "idle",
|
|
26
|
+
interactive: false
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
var attachmentMediaVariants = cva(
|
|
31
|
+
"flex shrink-0 items-center justify-center overflow-hidden bg-muted text-muted-foreground",
|
|
32
|
+
{
|
|
33
|
+
variants: {
|
|
34
|
+
variant: {
|
|
35
|
+
// Concentric with the card: its radius less the inset. The tile sits right
|
|
36
|
+
// at the edge, so it follows the curve rather than a floor (4px minimum).
|
|
37
|
+
card: "size-10 rounded-[max(--spacing(1),calc(var(--attachment-radius,var(--radius-md))-max(--spacing(2),calc(var(--attachment-radius,var(--radius-md))/2))))]",
|
|
38
|
+
media: "size-full rounded-none"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
defaultVariants: { variant: "card" }
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
export {
|
|
45
|
+
attachmentMediaVariants,
|
|
46
|
+
attachmentVariants
|
|
47
|
+
};
|