@seekalfred/primitives 0.5.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +682 -19
- package/dist/accordion/accordion.js +10 -4
- package/dist/accordion/accordion.js.map +1 -1
- package/dist/action-button/action-button.d.ts +50 -0
- package/dist/action-button/action-button.js +159 -0
- package/dist/action-button/action-button.js.map +1 -0
- package/dist/action-button/index.d.ts +2 -0
- package/dist/action-button/index.js +2 -0
- package/dist/activity-heatmap/activity-heatmap.d.ts +92 -0
- package/dist/activity-heatmap/activity-heatmap.js +699 -0
- package/dist/activity-heatmap/activity-heatmap.js.map +1 -0
- package/dist/activity-heatmap/index.d.ts +2 -0
- package/dist/activity-heatmap/index.js +2 -0
- package/dist/alert/alert.d.ts +19 -1
- package/dist/alert/alert.js +180 -23
- package/dist/alert/alert.js.map +1 -1
- package/dist/alert-dialog/alert-dialog.d.ts +45 -18
- package/dist/alert-dialog/alert-dialog.js +128 -9
- package/dist/alert-dialog/alert-dialog.js.map +1 -1
- package/dist/alert-dialog/index.d.ts +2 -2
- package/dist/alert-dialog/index.js +2 -2
- package/dist/animated-counter/animated-counter.d.ts +38 -0
- package/dist/animated-counter/animated-counter.js +230 -0
- package/dist/animated-counter/animated-counter.js.map +1 -0
- package/dist/animated-counter/index.d.ts +2 -0
- package/dist/animated-counter/index.js +2 -0
- package/dist/announcement-bar/announcement-bar.d.ts +67 -0
- package/dist/announcement-bar/announcement-bar.js +364 -0
- package/dist/announcement-bar/announcement-bar.js.map +1 -0
- package/dist/announcement-bar/index.d.ts +2 -0
- package/dist/announcement-bar/index.js +2 -0
- package/dist/avatar/avatar.d.ts +6 -0
- package/dist/avatar/avatar.js +47 -16
- package/dist/avatar/avatar.js.map +1 -1
- package/dist/badge/badge.d.ts +10 -3
- package/dist/badge/badge.js +35 -5
- package/dist/badge/badge.js.map +1 -1
- package/dist/bar-chart/bar-chart.d.ts +51 -0
- package/dist/bar-chart/bar-chart.js +565 -0
- package/dist/bar-chart/bar-chart.js.map +1 -0
- package/dist/bar-chart/index.d.ts +2 -0
- package/dist/bar-chart/index.js +2 -0
- package/dist/breadcrumb/breadcrumb.d.ts +2 -29
- package/dist/breadcrumb/breadcrumb.js +32 -9
- package/dist/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/brush-chart/brush-chart.d.ts +64 -0
- package/dist/brush-chart/brush-chart.js +1056 -0
- package/dist/brush-chart/brush-chart.js.map +1 -0
- package/dist/brush-chart/index.d.ts +2 -0
- package/dist/brush-chart/index.js +2 -0
- package/dist/button/button.d.ts +36 -23
- package/dist/button/button.js +198 -45
- package/dist/button/button.js.map +1 -1
- package/dist/button-group/button-group.d.ts +76 -0
- package/dist/button-group/button-group.js +402 -0
- package/dist/button-group/button-group.js.map +1 -0
- package/dist/button-group/index.d.ts +2 -0
- package/dist/button-group/index.js +2 -0
- package/dist/calendar/calendar.d.ts +1 -1
- package/dist/calendar/calendar.js +257 -30
- package/dist/calendar/calendar.js.map +1 -1
- package/dist/card/card.d.ts +9 -2
- package/dist/card/card.js +16 -5
- package/dist/card/card.js.map +1 -1
- package/dist/card-stack/card-stack.d.ts +54 -0
- package/dist/card-stack/card-stack.js +492 -0
- package/dist/card-stack/card-stack.js.map +1 -0
- package/dist/card-stack/index.d.ts +2 -0
- package/dist/card-stack/index.js +2 -0
- package/dist/carousel/carousel.d.ts +56 -0
- package/dist/carousel/carousel.js +389 -0
- package/dist/carousel/carousel.js.map +1 -0
- package/dist/carousel/index.d.ts +2 -0
- package/dist/carousel/index.js +2 -0
- package/dist/checkbox/checkbox.d.ts +0 -7
- package/dist/checkbox/checkbox.js +26 -29
- package/dist/checkbox/checkbox.js.map +1 -1
- package/dist/chip-group/chip-group.d.ts +37 -0
- package/dist/chip-group/chip-group.js +148 -0
- package/dist/chip-group/chip-group.js.map +1 -0
- package/dist/chip-group/index.d.ts +2 -0
- package/dist/chip-group/index.js +2 -0
- package/dist/confirm-morph/confirm-morph.d.ts +85 -0
- package/dist/confirm-morph/confirm-morph.js +652 -0
- package/dist/confirm-morph/confirm-morph.js.map +1 -0
- package/dist/confirm-morph/index.d.ts +2 -0
- package/dist/confirm-morph/index.js +2 -0
- package/dist/copy-button/copy-button.d.ts +32 -0
- package/dist/copy-button/copy-button.js +134 -0
- package/dist/copy-button/copy-button.js.map +1 -0
- package/dist/copy-button/index.d.ts +2 -0
- package/dist/copy-button/index.js +2 -0
- package/dist/countdown/countdown.d.ts +45 -0
- package/dist/countdown/countdown.js +298 -0
- package/dist/countdown/countdown.js.map +1 -0
- package/dist/countdown/index.d.ts +2 -0
- package/dist/countdown/index.js +2 -0
- package/dist/date-picker/date-picker.d.ts +51 -0
- package/dist/date-picker/date-picker.js +241 -0
- package/dist/date-picker/date-picker.js.map +1 -0
- package/dist/date-picker/date-range-picker.d.ts +78 -0
- package/dist/date-picker/date-range-picker.js +1015 -0
- package/dist/date-picker/date-range-picker.js.map +1 -0
- package/dist/date-picker/index.d.ts +4 -0
- package/dist/date-picker/index.js +4 -0
- package/dist/date-picker/picker-parts.d.ts +46 -0
- package/dist/date-picker/picker-parts.js +135 -0
- package/dist/date-picker/picker-parts.js.map +1 -0
- package/dist/dialog/dialog.d.ts +10 -14
- package/dist/dialog/dialog.js +40 -12
- package/dist/dialog/dialog.js.map +1 -1
- package/dist/donut-chart/donut-chart.d.ts +64 -0
- package/dist/donut-chart/donut-chart.js +576 -0
- package/dist/donut-chart/donut-chart.js.map +1 -0
- package/dist/donut-chart/index.d.ts +2 -0
- package/dist/donut-chart/index.js +2 -0
- package/dist/empty-state/empty-state.d.ts +55 -0
- package/dist/empty-state/empty-state.js +89 -0
- package/dist/empty-state/empty-state.js.map +1 -0
- package/dist/empty-state/index.d.ts +2 -0
- package/dist/empty-state/index.js +2 -0
- package/dist/expanding-button-group/expanding-button-group.d.ts +54 -0
- package/dist/expanding-button-group/expanding-button-group.js +350 -0
- package/dist/expanding-button-group/expanding-button-group.js.map +1 -0
- package/dist/expanding-button-group/index.d.ts +2 -0
- package/dist/expanding-button-group/index.js +2 -0
- package/dist/file-drop-zone/file-drop-zone.d.ts +71 -0
- package/dist/file-drop-zone/file-drop-zone.js +116 -0
- package/dist/file-drop-zone/file-drop-zone.js.map +1 -0
- package/dist/file-drop-zone/index.d.ts +2 -0
- package/dist/file-drop-zone/index.js +2 -0
- package/dist/filter-bar/filter-bar.d.ts +142 -0
- package/dist/filter-bar/filter-bar.js +416 -0
- package/dist/filter-bar/filter-bar.js.map +1 -0
- package/dist/filter-bar/index.d.ts +2 -0
- package/dist/filter-bar/index.js +2 -0
- package/dist/floating-button-group/floating-button-group.d.ts +61 -0
- package/dist/floating-button-group/floating-button-group.js +340 -0
- package/dist/floating-button-group/floating-button-group.js.map +1 -0
- package/dist/floating-button-group/index.d.ts +2 -0
- package/dist/floating-button-group/index.js +2 -0
- package/dist/gauge/gauge.d.ts +45 -0
- package/dist/gauge/gauge.js +219 -0
- package/dist/gauge/gauge.js.map +1 -0
- package/dist/gauge/index.d.ts +2 -0
- package/dist/gauge/index.js +2 -0
- package/dist/icon-morph/icon-morph.d.ts +55 -0
- package/dist/icon-morph/icon-morph.js +331 -0
- package/dist/icon-morph/icon-morph.js.map +1 -0
- package/dist/icon-morph/index.d.ts +2 -0
- package/dist/icon-morph/index.js +2 -0
- package/dist/in-view-title/in-view-title.d.ts +33 -0
- package/dist/in-view-title/in-view-title.js +119 -0
- package/dist/in-view-title/in-view-title.js.map +1 -0
- package/dist/in-view-title/index.d.ts +2 -0
- package/dist/in-view-title/index.js +2 -0
- package/dist/index.d.ts +71 -6
- package/dist/index.js +73 -11
- package/dist/input/input.d.ts +22 -0
- package/dist/input/input.js +36 -12
- package/dist/input/input.js.map +1 -1
- package/dist/lib/cn.js +11 -1
- package/dist/lib/cn.js.map +1 -1
- package/dist/lib/count-to.js +113 -0
- package/dist/lib/count-to.js.map +1 -0
- package/dist/lib/eye-morph.js +62 -0
- package/dist/lib/eye-morph.js.map +1 -0
- package/dist/lib/field-message.js +354 -0
- package/dist/lib/field-message.js.map +1 -0
- package/dist/lib/field-shell.js +81 -0
- package/dist/lib/field-shell.js.map +1 -0
- package/dist/lib/field-surface.js +11 -8
- package/dist/lib/field-surface.js.map +1 -1
- package/dist/lib/flag-emoji.js +50 -0
- package/dist/lib/flag-emoji.js.map +1 -0
- package/dist/lib/flip.js +88 -0
- package/dist/lib/flip.js.map +1 -0
- package/dist/lib/height-follow.js +59 -0
- package/dist/lib/height-follow.js.map +1 -0
- package/dist/lib/icon-swap.js +47 -0
- package/dist/lib/icon-swap.js.map +1 -0
- package/dist/lib/leaving-list.js +57 -0
- package/dist/lib/leaving-list.js.map +1 -0
- package/dist/lib/menu-highlight.js +64 -0
- package/dist/lib/menu-highlight.js.map +1 -0
- package/dist/lib/merge-refs.js +3 -3
- package/dist/lib/merge-refs.js.map +1 -1
- package/dist/lib/morph-text.js +128 -0
- package/dist/lib/morph-text.js.map +1 -0
- package/dist/lib/motion.js +169 -0
- package/dist/lib/motion.js.map +1 -0
- package/dist/lib/pausable-timeout.js +67 -0
- package/dist/lib/pausable-timeout.js.map +1 -0
- package/dist/lib/rolling-value.js +31 -0
- package/dist/lib/rolling-value.js.map +1 -0
- package/dist/lib/spring-progress.js +114 -0
- package/dist/lib/spring-progress.js.map +1 -0
- package/dist/lib/spring-tween.js +500 -0
- package/dist/lib/spring-tween.js.map +1 -0
- package/dist/lib/svg-id.js +10 -0
- package/dist/lib/svg-id.js.map +1 -0
- package/dist/lib/swap-text.js +79 -0
- package/dist/lib/swap-text.js.map +1 -0
- package/dist/lib/use-copy-feedback.js +36 -0
- package/dist/lib/use-copy-feedback.js.map +1 -0
- package/dist/line-chart/index.d.ts +2 -0
- package/dist/line-chart/index.js +2 -0
- package/dist/line-chart/line-chart.d.ts +76 -0
- package/dist/line-chart/line-chart.js +611 -0
- package/dist/line-chart/line-chart.js.map +1 -0
- package/dist/mention-input/index.d.ts +2 -0
- package/dist/mention-input/index.js +2 -0
- package/dist/mention-input/mention-input.d.ts +98 -0
- package/dist/mention-input/mention-input.js +576 -0
- package/dist/mention-input/mention-input.js.map +1 -0
- package/dist/menu/menu.d.ts +2 -0
- package/dist/menu/menu.js +23 -12
- package/dist/menu/menu.js.map +1 -1
- package/dist/money-input/index.d.ts +2 -0
- package/dist/money-input/index.js +2 -0
- package/dist/money-input/money-input.d.ts +65 -0
- package/dist/money-input/money-input.js +607 -0
- package/dist/money-input/money-input.js.map +1 -0
- package/dist/morph-select/index.d.ts +2 -0
- package/dist/morph-select/index.js +2 -0
- package/dist/morph-select/morph-select.d.ts +71 -0
- package/dist/morph-select/morph-select.js +693 -0
- package/dist/morph-select/morph-select.js.map +1 -0
- package/dist/multi-select/index.d.ts +2 -0
- package/dist/multi-select/index.js +2 -0
- package/dist/multi-select/multi-select.d.ts +36 -0
- package/dist/multi-select/multi-select.js +152 -0
- package/dist/multi-select/multi-select.js.map +1 -0
- package/dist/number-field/index.d.ts +2 -0
- package/dist/number-field/index.js +2 -0
- package/dist/number-field/number-field.d.ts +42 -0
- package/dist/number-field/number-field.js +199 -0
- package/dist/number-field/number-field.js.map +1 -0
- package/dist/onboarding-checklist/index.d.ts +2 -0
- package/dist/onboarding-checklist/index.js +2 -0
- package/dist/onboarding-checklist/onboarding-checklist.d.ts +55 -0
- package/dist/onboarding-checklist/onboarding-checklist.js +577 -0
- package/dist/onboarding-checklist/onboarding-checklist.js.map +1 -0
- package/dist/page-header/index.d.ts +2 -0
- package/dist/page-header/index.js +2 -0
- package/dist/page-header/page-header.d.ts +75 -0
- package/dist/page-header/page-header.js +83 -0
- package/dist/page-header/page-header.js.map +1 -0
- package/dist/password-field/index.d.ts +2 -0
- package/dist/password-field/index.js +2 -0
- package/dist/password-field/password-field.d.ts +37 -0
- package/dist/password-field/password-field.js +101 -0
- package/dist/password-field/password-field.js.map +1 -0
- package/dist/password-strength/index.d.ts +2 -0
- package/dist/password-strength/index.js +2 -0
- package/dist/password-strength/password-strength.d.ts +127 -0
- package/dist/password-strength/password-strength.js +455 -0
- package/dist/password-strength/password-strength.js.map +1 -0
- package/dist/phone-input/index.d.ts +3 -0
- package/dist/phone-input/index.js +3 -0
- package/dist/phone-input/phone-countries.d.ts +29 -0
- package/dist/phone-input/phone-countries.js +170 -0
- package/dist/phone-input/phone-countries.js.map +1 -0
- package/dist/phone-input/phone-input.d.ts +66 -0
- package/dist/phone-input/phone-input.js +440 -0
- package/dist/phone-input/phone-input.js.map +1 -0
- package/dist/popover/popover.d.ts +20 -0
- package/dist/popover/popover.js +33 -9
- package/dist/popover/popover.js.map +1 -1
- package/dist/progress/progress.js +46 -5
- package/dist/progress/progress.js.map +1 -1
- package/dist/radio-group/radio-group.js +8 -7
- package/dist/radio-group/radio-group.js.map +1 -1
- package/dist/reactions/index.d.ts +2 -0
- package/dist/reactions/index.js +2 -0
- package/dist/reactions/reactions.d.ts +50 -0
- package/dist/reactions/reactions.js +315 -0
- package/dist/reactions/reactions.js.map +1 -0
- package/dist/rich-text-editor/index.d.ts +3 -0
- package/dist/rich-text-editor/index.js +2 -0
- package/dist/rich-text-editor/rich-text-editor.d.ts +70 -0
- package/dist/rich-text-editor/rich-text-editor.js +909 -0
- package/dist/rich-text-editor/rich-text-editor.js.map +1 -0
- package/dist/rich-text-editor/rich-text-engine.d.ts +16 -0
- package/dist/rich-text-editor/rich-text-engine.js +366 -0
- package/dist/rich-text-editor/rich-text-engine.js.map +1 -0
- package/dist/rich-text-editor/rich-text-html.js +174 -0
- package/dist/rich-text-editor/rich-text-html.js.map +1 -0
- package/dist/rich-text-editor/rich-text-icons.js +43 -0
- package/dist/rich-text-editor/rich-text-icons.js.map +1 -0
- package/dist/ridgeline/index.d.ts +2 -0
- package/dist/ridgeline/index.js +2 -0
- package/dist/ridgeline/ridgeline.d.ts +55 -0
- package/dist/ridgeline/ridgeline.js +701 -0
- package/dist/ridgeline/ridgeline.js.map +1 -0
- package/dist/scroll-area/index.d.ts +2 -2
- package/dist/scroll-area/index.js +2 -2
- package/dist/scroll-area/scroll-area.d.ts +75 -28
- package/dist/scroll-area/scroll-area.js +212 -41
- package/dist/scroll-area/scroll-area.js.map +1 -1
- package/dist/scrub-input/evaluate.d.ts +14 -0
- package/dist/scrub-input/evaluate.js +72 -0
- package/dist/scrub-input/evaluate.js.map +1 -0
- package/dist/scrub-input/index.d.ts +3 -0
- package/dist/scrub-input/index.js +3 -0
- package/dist/scrub-input/scrub-input.d.ts +74 -0
- package/dist/scrub-input/scrub-input.js +486 -0
- package/dist/scrub-input/scrub-input.js.map +1 -0
- package/dist/search-field/index.d.ts +2 -0
- package/dist/search-field/index.js +2 -0
- package/dist/search-field/search-field.d.ts +27 -0
- package/dist/search-field/search-field.js +155 -0
- package/dist/search-field/search-field.js.map +1 -0
- package/dist/select/select.d.ts +3 -1
- package/dist/select/select.js +95 -25
- package/dist/select/select.js.map +1 -1
- package/dist/separator/separator.d.ts +1 -1
- package/dist/sheet/sheet.js +4 -2
- package/dist/sheet/sheet.js.map +1 -1
- package/dist/shortcut-recorder/index.d.ts +3 -0
- package/dist/shortcut-recorder/index.js +3 -0
- package/dist/shortcut-recorder/shortcut-model.d.ts +27 -0
- package/dist/shortcut-recorder/shortcut-model.js +206 -0
- package/dist/shortcut-recorder/shortcut-model.js.map +1 -0
- package/dist/shortcut-recorder/shortcut-recorder.d.ts +93 -0
- package/dist/shortcut-recorder/shortcut-recorder.js +489 -0
- package/dist/shortcut-recorder/shortcut-recorder.js.map +1 -0
- package/dist/side-nav/index.d.ts +2 -0
- package/dist/side-nav/index.js +2 -0
- package/dist/side-nav/side-nav.d.ts +72 -0
- package/dist/side-nav/side-nav.js +142 -0
- package/dist/side-nav/side-nav.js.map +1 -0
- package/dist/skeleton/skeleton.d.ts +8 -2
- package/dist/skeleton/skeleton.js +6 -2
- package/dist/skeleton/skeleton.js.map +1 -1
- package/dist/slider/index.d.ts +2 -2
- package/dist/slider/slider.d.ts +46 -14
- package/dist/slider/slider.js +188 -50
- package/dist/slider/slider.js.map +1 -1
- package/dist/slope-chart/index.d.ts +2 -0
- package/dist/slope-chart/index.js +2 -0
- package/dist/slope-chart/slope-chart.d.ts +54 -0
- package/dist/slope-chart/slope-chart.js +568 -0
- package/dist/slope-chart/slope-chart.js.map +1 -0
- package/dist/sparkline/index.d.ts +2 -0
- package/dist/sparkline/index.js +2 -0
- package/dist/sparkline/sparkline.d.ts +46 -0
- package/dist/sparkline/sparkline.js +390 -0
- package/dist/sparkline/sparkline.js.map +1 -0
- package/dist/split-bar/index.d.ts +2 -0
- package/dist/split-bar/index.js +2 -0
- package/dist/split-bar/split-bar.d.ts +62 -0
- package/dist/split-bar/split-bar.js +513 -0
- package/dist/split-bar/split-bar.js.map +1 -0
- package/dist/split-button/index.d.ts +2 -0
- package/dist/split-button/index.js +2 -0
- package/dist/split-button/split-button.d.ts +46 -0
- package/dist/split-button/split-button.js +123 -0
- package/dist/split-button/split-button.js.map +1 -0
- package/dist/stat-card/index.d.ts +2 -0
- package/dist/stat-card/index.js +2 -0
- package/dist/stat-card/stat-card.d.ts +101 -0
- package/dist/stat-card/stat-card.js +249 -0
- package/dist/stat-card/stat-card.js.map +1 -0
- package/dist/stepper/index.d.ts +2 -0
- package/dist/stepper/index.js +2 -0
- package/dist/stepper/stepper.d.ts +51 -0
- package/dist/stepper/stepper.js +215 -0
- package/dist/stepper/stepper.js.map +1 -0
- package/dist/streamgraph/index.d.ts +2 -0
- package/dist/streamgraph/index.js +2 -0
- package/dist/streamgraph/streamgraph.d.ts +70 -0
- package/dist/streamgraph/streamgraph.js +613 -0
- package/dist/streamgraph/streamgraph.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/swipe-actions/index.d.ts +2 -0
- package/dist/swipe-actions/index.js +2 -0
- package/dist/swipe-actions/swipe-actions.d.ts +67 -0
- package/dist/swipe-actions/swipe-actions.js +552 -0
- package/dist/swipe-actions/swipe-actions.js.map +1 -0
- package/dist/switch/switch.js +10 -9
- package/dist/switch/switch.js.map +1 -1
- package/dist/table/index.d.ts +2 -2
- package/dist/table/index.js +2 -2
- package/dist/table/table.d.ts +87 -4
- package/dist/table/table.js +441 -165
- package/dist/table/table.js.map +1 -1
- package/dist/tabs/tabs.js +143 -7
- package/dist/tabs/tabs.js.map +1 -1
- package/dist/tag-input/index.d.ts +2 -0
- package/dist/tag-input/index.js +2 -0
- package/dist/tag-input/tag-input.d.ts +40 -0
- package/dist/tag-input/tag-input.js +269 -0
- package/dist/tag-input/tag-input.js.map +1 -0
- package/dist/text-morph/index.d.ts +2 -0
- package/dist/text-morph/index.js +2 -0
- package/dist/text-morph/text-morph.d.ts +23 -0
- package/dist/text-morph/text-morph.js +21 -0
- package/dist/text-morph/text-morph.js.map +1 -0
- package/dist/text-reveal/index.d.ts +2 -0
- package/dist/text-reveal/index.js +2 -0
- package/dist/text-reveal/text-reveal.d.ts +27 -0
- package/dist/text-reveal/text-reveal.js +51 -0
- package/dist/text-reveal/text-reveal.js.map +1 -0
- package/dist/text-shimmer/index.d.ts +2 -0
- package/dist/text-shimmer/index.js +2 -0
- package/dist/text-shimmer/text-shimmer.d.ts +29 -0
- package/dist/text-shimmer/text-shimmer.js +29 -0
- package/dist/text-shimmer/text-shimmer.js.map +1 -0
- package/dist/textarea/textarea.d.ts +23 -0
- package/dist/textarea/textarea.js +24 -2
- package/dist/textarea/textarea.js.map +1 -1
- package/dist/theme-switch/index.d.ts +2 -0
- package/dist/theme-switch/index.js +2 -0
- package/dist/theme-switch/theme-switch.d.ts +37 -0
- package/dist/theme-switch/theme-switch.js +123 -0
- package/dist/theme-switch/theme-switch.js.map +1 -0
- package/dist/time-picker/index.d.ts +2 -0
- package/dist/time-picker/index.js +2 -0
- package/dist/time-picker/time-picker.d.ts +54 -0
- package/dist/time-picker/time-picker.js +201 -0
- package/dist/time-picker/time-picker.js.map +1 -0
- package/dist/toast/index.d.ts +2 -2
- package/dist/toast/index.js +2 -2
- package/dist/toast/toast.d.ts +6 -0
- package/dist/toast/toast.js +98 -36
- package/dist/toast/toast.js.map +1 -1
- package/dist/tooltip/tooltip.d.ts +10 -3
- package/dist/tooltip/tooltip.js +67 -18
- package/dist/tooltip/tooltip.js.map +1 -1
- package/dist/treemap/index.d.ts +2 -0
- package/dist/treemap/index.js +2 -0
- package/dist/treemap/treemap.d.ts +53 -0
- package/dist/treemap/treemap.js +699 -0
- package/dist/treemap/treemap.js.map +1 -0
- package/dist/usage-meter/index.d.ts +2 -0
- package/dist/usage-meter/index.js +2 -0
- package/dist/usage-meter/usage-meter.d.ts +50 -0
- package/dist/usage-meter/usage-meter.js +440 -0
- package/dist/usage-meter/usage-meter.js.map +1 -0
- package/dist/waffle-chart/index.d.ts +2 -0
- package/dist/waffle-chart/index.js +2 -0
- package/dist/waffle-chart/waffle-chart.d.ts +57 -0
- package/dist/waffle-chart/waffle-chart.js +426 -0
- package/dist/waffle-chart/waffle-chart.js.map +1 -0
- package/package.json +245 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"donut-chart.js","names":[],"sources":["../../src/donut-chart/donut-chart.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n type PointerEvent,\n} from \"react\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { useCountTo } from \"../lib/count-to.js\";\nimport { mergeRefs } from \"../lib/merge-refs.js\";\nimport { prefersReducedMotion, useIsomorphicLayoutEffect } from \"../lib/motion.js\";\nimport { live, retarget, REVEAL, SETTLE, SNAPPY, type Live } from \"../lib/spring-tween.js\";\n\n/**\n * DonutChart: a few parts of one whole, when the share of each part matters\n * more than a precise comparison.\n *\n * The ring sweeps open the first time it is seen: every segment leaves the top\n * together and each trailing edge follows a beat behind the one before. New\n * data, or a segment shown or hidden, moves every arc from where it is on\n * screen; a leaving segment closes where it sits. The active segment (hover,\n * focus, selection) slides out along its middle and thickens; the rest dim.\n * The centre rolls like a drum between the total and each segment, and every\n * number counts to its new value. Small parts fold into one \"Other\" segment.\n *\n * Plain SVG and CSS; one small spring tween moves the arcs. The legend is the\n * keyboard path (or the ring itself, without a legend), and a visually hidden\n * table carries every value.\n */\nexport interface DonutChartDatum {\n /** Stable identity. A segment whose key survives a data change keeps its place and colour. */\n key: string;\n label: string;\n value: number;\n /** Any CSS colour. Segments default to chart-1 to chart-4 in data order, then neutral steps. */\n color?: string;\n}\n\nexport interface DonutChartProps {\n data: DonutChartDatum[];\n /** What the whole is, such as \"Visits by source\". Names the chart for assistive technology. */\n label: string;\n /** Unit after values, such as \"visits\". */\n unit?: string;\n formatValue?: (value: number) => string;\n /** Centre label at rest, above the total. @default \"Total\" */\n totalLabel?: string;\n /** Diameter in pixels. The chart scales down to fit narrower containers. @default 208 */\n size?: number;\n /** Ring thickness in pixels. @default 24 */\n thickness?: number;\n /** Segments below this share of the total join \"Other\". @default 0.04 */\n groupBelow?: number;\n /** The most segments drawn, counting \"Other\". @default 6 */\n maxSegments?: number;\n /** @default \"Other\" */\n otherLabel?: string;\n /** Controlled selected segment key. Hover and focus preview other segments without changing it. */\n activeKey?: string | null;\n defaultActiveKey?: string | null;\n onActiveChange?: (key: string | null) => void;\n /** Controlled hidden segment keys. A hidden segment closes and the rest of the ring redistributes. */\n hiddenKeys?: string[];\n defaultHiddenKeys?: string[];\n onHiddenKeysChange?: (keys: string[]) => void;\n /** What clicking a legend row does: show or hide its segment, or pin it as selected. @default \"toggle\" */\n legendAction?: \"toggle\" | \"select\";\n /** The synced legend beside or below the ring. @default true */\n legend?: boolean;\n /** @default \"No data yet\" */\n emptyLabel?: string;\n /** Extra classes for the root. Merged last. */\n className?: string;\n}\n\ntype Slice = { key: string; label: string; value: number; color?: string; members?: DonutChartDatum[] };\ntype Arc = { start: number; end: number };\ntype Segment = { start: Live; end: Live; lift: Live };\n\nconst OTHER = \"__other\";\nconst TAU = Math.PI * 2;\n/** Neutral steps after the four series colours, and the quietest step for Other. */\nconst NEUTRAL = [56, 42, 32];\nconst seriesColor = (index: number) =>\n index < 4\n ? `var(--color-chart-${index + 1})`\n : `color-mix(in oklab, var(--color-foreground) ${NEUTRAL[(index - 4) % NEUTRAL.length]}%, var(--color-surface))`;\nconst OTHER_COLOR = \"color-mix(in oklab, var(--color-foreground) 26%, var(--color-surface))\";\n/** Room outside the ring for the lift; growth, margin, the gap between segments and their corner radius, in pixels. */\nconst LIFT = 4;\nconst GROW = 2;\nconst MARGIN = 7;\nconst GAP = 3;\nconst CORNER = 4;\n/** Stagger of the trailing edges on the first sweep. */\nconst STAGGER_MS = 35;\nconst GROUPED = new Intl.NumberFormat(\"en-US\", { maximumFractionDigits: 1 });\nconst PERCENT = new Intl.NumberFormat(\"en-US\", { style: \"percent\", maximumFractionDigits: 0 });\nconst shareText = (share: number) => (share > 0 && share < 0.01 ? \"<1%\" : PERCENT.format(share));\nconst n2 = (value: number) => (Math.round(value * 100) / 100).toString();\n\n/** Small parts join one \"Other\" segment, but only when at least two would; grouping a single part hides it for nothing. */\nfunction sliceData(data: DonutChartDatum[], groupBelow: number, maxSegments: number, otherLabel: string): Slice[] {\n const parts = data.filter((item) => item.value > 0);\n const total = parts.reduce((sum, item) => sum + item.value, 0);\n if (!total) return [];\n const ranked = [...parts].sort((a, b) => b.value - a.value);\n const keep = new Set(\n ranked.filter((item, rank) => item.value / total >= groupBelow && rank < maxSegments - 1).map((item) => item.key),\n );\n const rest = parts.filter((item) => !keep.has(item.key));\n if (rest.length < 2) return parts.map((item) => ({ ...item }));\n return [\n ...parts.filter((item) => keep.has(item.key)).map((item) => ({ ...item })),\n { key: OTHER, label: otherLabel, value: rest.reduce((sum, item) => sum + item.value, 0), members: rest },\n ];\n}\n\n/** Turns of the ring for each slice in data order; a hidden slice closes to a point where it sits. */\nfunction layout(slices: Slice[], hidden: Set<string>) {\n const total = slices.reduce((sum, item) => sum + (hidden.has(item.key) ? 0 : item.value), 0) || 1;\n let at = 0;\n return new Map(\n slices.map((item) => {\n const arc = { start: at, end: at + (hidden.has(item.key) ? 0 : item.value / total) };\n at = arc.end;\n return [item.key, arc] as const;\n }),\n );\n}\n\n/** Half the width, in pixels, of a sector's outer edge once the gap is cut; below a couple of pixels a segment fades rather than drawing a hairline. */\nfunction breadth(R: number, t0: number, t1: number, gap: number) {\n const turns = t1 - t0;\n if (turns >= 1 - 1e-6) return Infinity;\n return Math.sin(Math.min(turns * Math.PI, Math.PI / 2)) * R - Math.min(gap / 2, ((1 - turns) * TAU * R) / 2);\n}\n\n/**\n * An annular sector between two turns of the ring, clockwise from the top, with\n * rounded corners. Its sides run parallel to the radius at a fixed distance, so\n * the gap between neighbours is the same width from the inner edge to the outer.\n * A thin sector narrows to a wedge and then to nothing, so a closing one never pops.\n */\nfunction sector(c: number, R: number, r: number, t0: number, t1: number, gap: number, corner: number) {\n const turns = t1 - t0;\n if (turns <= 1e-6) return \"\";\n const at = (radius: number, angle: number) => `${n2(c + radius * Math.cos(angle))} ${n2(c + radius * Math.sin(angle))}`;\n if (turns >= 1 - 1e-6) {\n return `M${at(R, -Math.PI / 2)}A${n2(R)} ${n2(R)} 0 1 1 ${at(R, Math.PI / 2)}A${n2(R)} ${n2(R)} 0 1 1 ${at(R, -Math.PI / 2)}ZM${at(r, -Math.PI / 2)}A${n2(r)} ${n2(r)} 0 1 0 ${at(r, Math.PI / 2)}A${n2(r)} ${n2(r)} 0 1 0 ${at(r, -Math.PI / 2)}Z`;\n }\n // Half the gap on each side; a lone segment closes its gap as the rest of the ring empties, so it becomes a whole ring without a jump.\n const p = Math.min(gap / 2, ((1 - turns) * TAU * R) / 2);\n const a0 = t0 * TAU - Math.PI / 2;\n const a1 = t1 * TAU - Math.PI / 2;\n const half = (a1 - a0) / 2;\n const s = Math.sin(Math.min(half, Math.PI / 2));\n if (s * R <= p + 1e-6) return \"\";\n const side = (t: number, angle: number, sign: number) =>\n `${n2(c + t * Math.cos(angle) - sign * p * Math.sin(angle))} ${n2(c + t * Math.sin(angle) + sign * p * Math.cos(angle))}`;\n const band = (R - r) / 2;\n const ro = Math.max(0, Math.min(corner, band, s >= 0.9999 ? Infinity : (s * R - p) / (1 + s)));\n const dO = Math.asin(Math.min(1, (p + ro) / (R - ro)));\n const tO = Math.sqrt(Math.max(0, (R - ro) ** 2 - (p + ro) ** 2));\n const bigO = a1 - a0 - 2 * dO > Math.PI ? 1 : 0;\n let d = `M${side(tO, a0, 1)}`;\n if (ro > 0.01) d += `A${n2(ro)} ${n2(ro)} 0 0 1 ${at(R, a0 + dO)}`;\n d += `A${n2(R)} ${n2(R)} 0 ${bigO} 1 ${at(R, a1 - dO)}`;\n if (ro > 0.01) d += `A${n2(ro)} ${n2(ro)} 0 0 1 ${side(tO, a1, -1)}`;\n if (s * r > p + 1e-6 || s >= 0.9999) {\n const ri = Math.max(0, Math.min(corner, band, s >= 0.9999 ? Infinity : (s * r - p) / (1 - s)));\n const dI = Math.asin(Math.min(1, (p + ri) / (r + ri)));\n const tI = Math.sqrt(Math.max(0, (r + ri) ** 2 - (p + ri) ** 2));\n const bigI = a1 - a0 - 2 * dI > Math.PI ? 1 : 0;\n d += `L${side(tI, a1, -1)}`;\n if (ri > 0.01) d += `A${n2(ri)} ${n2(ri)} 0 0 1 ${at(r, a1 - dI)}`;\n d += `A${n2(r)} ${n2(r)} 0 ${bigI} 0 ${at(r, a0 + dI)}`;\n if (ri > 0.01) d += `A${n2(ri)} ${n2(ri)} 0 0 1 ${side(tI, a0, 1)}`;\n } else d += `L${at(p / s, (a0 + a1) / 2)}`;\n return `${d}Z`;\n}\n\n/**\n * A number that counts to each new value on the smooth spring. useCountTo counts\n * in whole steps, so a fraction (a share) is counted in ten-thousandths.\n */\nfunction Count({ value, format }: { value: number; format: (value: number) => string }) {\n const fine = !Number.isInteger(value);\n const shown = useCountTo(fine ? value * 10000 : value);\n return <>{format(fine ? shown / 10000 : shown)}</>;\n}\n\nexport const DonutChart = forwardRef<HTMLElement, DonutChartProps>(function DonutChart(\n {\n data,\n label,\n unit = \"\",\n formatValue = (value) => GROUPED.format(value),\n totalLabel = \"Total\",\n size = 208,\n thickness = 24,\n groupBelow = 0.04,\n maxSegments = 6,\n otherLabel = \"Other\",\n activeKey,\n defaultActiveKey = null,\n onActiveChange,\n hiddenKeys,\n defaultHiddenKeys,\n onHiddenKeysChange,\n legendAction = \"toggle\",\n legend = true,\n emptyLabel = \"No data yet\",\n className,\n },\n ref,\n) {\n const figure = useRef<HTMLElement | null>(null);\n const refs = useMemo(() => mergeRefs(ref, figure), [ref]);\n const legendId = useId();\n const slices = sliceData(data, groupBelow, maxSegments, otherLabel);\n\n const [ownHidden, setOwnHidden] = useState<string[]>(defaultHiddenKeys ?? []);\n const hiddenList = hiddenKeys ?? ownHidden;\n const hidden = new Set(hiddenList.filter((key) => slices.some((item) => item.key === key)));\n const visible = slices.filter((item) => !hidden.has(item.key));\n const total = visible.reduce((sum, item) => sum + item.value, 0);\n const signature = slices.map((item) => `${item.key}:${item.value}${hidden.has(item.key) ? \"h\" : \"\"}`).join(\"|\");\n const suffix = unit ? ` ${unit}` : \"\";\n\n // Colours follow a key from the first time it is seen, so a segment keeps its colour through every dataset.\n const [palette, setPalette] = useState(() => new Map(data.map((item, index) => [item.key, index])));\n if (data.some((item) => !palette.has(item.key))) {\n const next = new Map(palette);\n for (const item of data) if (!next.has(item.key)) next.set(item.key, next.size);\n setPalette(next);\n }\n const colorFor = (item: Slice) =>\n item.color ?? (item.key === OTHER ? OTHER_COLOR : seriesColor(palette.get(item.key) ?? 0));\n\n // Leaving segments stay drawn in their old place while they close, then drop out.\n const [drawn, setDrawn] = useState<Slice[]>(slices);\n const [seen, setSeen] = useState(signature);\n if (seen !== signature) {\n setSeen(signature);\n const next = [...slices];\n drawn.forEach((item, index) => {\n if (next.some((slice) => slice.key === item.key)) return;\n const before = drawn\n .slice(0, index)\n .reverse()\n .find((prior) => next.some((slice) => slice.key === prior.key));\n next.splice(before ? next.findIndex((slice) => slice.key === before.key) + 1 : 0, 0, { ...item, value: 0 });\n });\n setDrawn(next);\n }\n\n // Selection is controlled or not; hover and focus preview on top of it.\n const [ownActive, setOwnActive] = useState<string | null>(defaultActiveKey);\n const selected = activeKey !== undefined ? activeKey : ownActive;\n const [preview, setPreview] = useState<string | null>(null);\n const select = (key: string | null) => {\n if (activeKey === undefined) setOwnActive(key);\n onActiveChange?.(key);\n };\n const current = [preview, selected].find((key) => key && visible.some((item) => item.key === key)) ?? null;\n const activeSlice = visible.find((item) => item.key === current) ?? null;\n\n const [announcement, setAnnouncement] = useState(\"\");\n const setHidden = (key: string) => {\n const isHidden = hidden.has(key);\n if (!isHidden && visible.length <= 1) return;\n const next = isHidden ? hiddenList.filter((item) => item !== key) : [...hiddenList, key];\n if (hiddenKeys === undefined) setOwnHidden(next);\n onHiddenKeysChange?.(next);\n const item = slices.find((slice) => slice.key === key);\n const nextTotal = slices.reduce((sum, slice) => sum + (next.includes(slice.key) ? 0 : slice.value), 0);\n if (item) setAnnouncement(`${item.label} ${isHidden ? \"shown\" : \"hidden\"}. ${totalLabel} ${formatValue(nextTotal)}${suffix}.`);\n };\n\n // Geometry in the chart's own units; the SVG scales with its container.\n const c = size / 2;\n const outer = c - MARGIN;\n const inner = Math.max(8, outer - thickness);\n const corner = Math.min(CORNER, thickness / 4);\n const geometry = useRef({ c, outer, inner, corner });\n const segments = useRef(new Map<string, Segment>());\n const svg = useRef<SVGSVGElement>(null);\n\n /** One writer: every path's shape, opacity and lift, straight onto the elements. */\n const paint = useCallback(() => {\n const root = svg.current;\n if (!root) return;\n const { c, outer, inner, corner } = geometry.current;\n for (const node of root.querySelectorAll<SVGPathElement>(\"[data-key]\")) {\n const segment = segments.current.get(node.dataset.key!);\n if (!segment) {\n node.setAttribute(\"d\", \"\");\n continue;\n }\n const start = segment.start.value;\n const end = segment.end.value;\n const lift = Math.max(0, segment.lift.value);\n const R = outer + lift * GROW;\n node.setAttribute(\"d\", sector(c, R, inner - lift * GROW * 0.5, start, end, GAP, corner));\n node.setAttribute(\"fill-opacity\", n2(Math.min(1, Math.max(0, (breadth(R, start, end, GAP) - 1) / 3))));\n const middle = ((start + end) / 2) * TAU - Math.PI / 2;\n node.setAttribute(\"transform\", `translate(${n2(Math.cos(middle) * lift * LIFT)} ${n2(Math.sin(middle) * lift * LIFT)})`);\n }\n }, []);\n useIsomorphicLayoutEffect(() => {\n geometry.current = { c, outer, inner, corner };\n paint();\n });\n useEffect(\n () => () => {\n for (const segment of segments.current.values()) {\n segment.start.stop();\n segment.end.stop();\n segment.lift.stop();\n }\n },\n [],\n );\n\n // The ring sweeps once a third of it is in view.\n const [shown, setShown] = useState(false);\n useEffect(() => {\n const node = figure.current;\n if (!node || prefersReducedMotion() || typeof IntersectionObserver === \"undefined\") {\n setShown(true);\n return;\n }\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return;\n observer.disconnect();\n setShown(true);\n },\n { threshold: 0.35 },\n );\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n\n const targets = useRef(new Map<string, Arc>());\n const latest = useRef({ drawn, slices });\n useIsomorphicLayoutEffect(() => {\n latest.current = { drawn, slices };\n });\n\n // New data, or a segment shown or hidden, moves every arc from wherever it is on screen.\n useEffect(() => {\n if (!shown) return;\n const { drawn: order, slices: now } = latest.current;\n const goal = layout(now, hidden);\n targets.current = goal;\n const first = segments.current.size === 0;\n const place = (index: number) => {\n const before = order\n .slice(0, index)\n .reverse()\n .find((item) => goal.has(item.key));\n return before ? goal.get(before.key)!.end : 0;\n };\n const drop = (key: string) => {\n if (latest.current.slices.some((item) => item.key === key)) return;\n segments.current.delete(key);\n setDrawn((list) => list.filter((item) => item.key !== key));\n };\n order.forEach((item, index) => {\n const leaving = !goal.has(item.key);\n const to = goal.get(item.key) ?? { start: place(index), end: place(index) };\n let segment = segments.current.get(item.key);\n if (!segment) {\n // A new segment opens from the edge of the one before it, as it is right now.\n const prior = order\n .slice(0, index)\n .reverse()\n .map((entry) => segments.current.get(entry.key))\n .find(Boolean);\n const from = first ? 0 : prior ? prior.end.value : 0;\n segment = { start: live(from), end: live(from), lift: live(0) };\n segments.current.set(item.key, segment);\n }\n if (first) {\n // One sweep: every segment leaves the top together, and each trailing edge follows a beat behind the one before.\n retarget(segment.start, to.start, REVEAL, paint);\n retarget(segment.end, to.end, REVEAL, paint, 40 + index * STAGGER_MS);\n return;\n }\n retarget(segment.start, to.start, SETTLE, paint);\n retarget(segment.end, to.end, SETTLE, paint, 0, leaving ? () => drop(item.key) : undefined);\n });\n paint();\n // The signature stands for the slices and the hidden set.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [shown, signature, paint]);\n\n // The active segment slides out along its middle and thickens; the one it replaces settles back.\n useEffect(() => {\n for (const [key, segment] of segments.current) retarget(segment.lift, key === current ? 1 : 0, SNAPPY, paint);\n }, [current, drawn, shown, paint]);\n\n // One pointer handler for the whole ring: the angle picks the segment, so crossing a gap never drops the hover.\n const hit = (event: { clientX: number; clientY: number }) => {\n const box = svg.current?.getBoundingClientRect();\n if (!box?.width) return undefined;\n const scale = size / box.width;\n const x = (event.clientX - box.left) * scale - c;\n const y = (event.clientY - box.top) * scale - c;\n const radius = Math.hypot(x, y);\n if (radius < inner - 6 || radius > c) return null;\n let turn = (Math.atan2(y, x) + Math.PI / 2) / TAU;\n if (turn < 0) turn += 1;\n for (const [key, arc] of targets.current) {\n if (arc.end > arc.start && turn >= arc.start && turn < arc.end && visible.some((item) => item.key === key)) return key;\n }\n return undefined;\n };\n const onRingMove = (event: PointerEvent<SVGSVGElement>) => {\n if (event.pointerType !== \"mouse\") return;\n const key = hit(event);\n if (key !== undefined && key !== preview) setPreview(key);\n };\n const onRingClick = (event: MouseEvent<SVGSVGElement>) => {\n const key = hit(event);\n if (key) select(selected === key ? null : key);\n };\n\n const format = (value: number) => `${formatValue(value)}${suffix}`;\n const describe = (item: Slice) =>\n `${item.label}, ${format(item.value)}, ${shareText(item.value / (total || 1))}${\n item.members ? `. Includes ${item.members.map((member) => member.label).join(\", \")}` : \"\"\n }`;\n\n // Arrow keys walk the segments, in the legend or on the ring itself when there is no legend.\n const rows = useRef<(HTMLButtonElement | null)[]>([]);\n const step = (key: string, index: number, count: number) => {\n const moves: Record<string, number> = {\n ArrowDown: index + 1,\n ArrowRight: index + 1,\n ArrowUp: index - 1,\n ArrowLeft: index - 1,\n Home: 0,\n End: count - 1,\n };\n return moves[key];\n };\n const onLegendKey = (event: KeyboardEvent<HTMLButtonElement>, index: number) => {\n if (event.key === \"Escape\" && selected) {\n event.preventDefault();\n select(null);\n return;\n }\n const next = step(event.key, index, slices.length);\n if (next === undefined) return;\n event.preventDefault();\n rows.current[(next + slices.length) % slices.length]?.focus();\n };\n const onRingKey = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!visible.length) return;\n if (event.key === \"Escape\") {\n event.preventDefault();\n setPreview(null);\n if (selected) select(null);\n return;\n }\n if ((event.key === \"Enter\" || event.key === \" \") && current) {\n event.preventDefault();\n select(selected === current ? null : current);\n return;\n }\n const index = visible.findIndex((item) => item.key === current);\n const next = step(\n event.key,\n index < 0 ? (event.key.endsWith(\"Up\") || event.key.endsWith(\"Left\") ? 0 : -1) : index,\n visible.length,\n );\n if (next === undefined) return;\n event.preventDefault();\n const item = visible[(next + visible.length) % visible.length]!;\n setPreview(item.key);\n setAnnouncement(describe(item));\n };\n const onLegendBlur = (event: FocusEvent<HTMLButtonElement>) => {\n if (!(event.relatedTarget instanceof Node && event.currentTarget.closest(\"ul\")?.contains(event.relatedTarget))) {\n setPreview(null);\n }\n };\n\n // One readout per segment plus the total; the active one rolls in from the side it sits on.\n const identity = activeSlice ? activeSlice.key : \"__total\";\n const readouts = [\n { key: \"__total\", label: total ? totalLabel : emptyLabel, value: total, meta: null as Slice | null },\n ...slices.map((item) => ({ key: item.key, label: item.label, value: item.value, meta: item })),\n ];\n const activeIndex = Math.max(0, readouts.findIndex((item) => item.key === identity));\n const summary = total ? `${label}. ${totalLabel} ${format(total)}. ${visible.map(describe).join(\". \")}.` : `${label}. ${emptyLabel}.`;\n const members = (item: Slice) =>\n item.members\n ? item.members.length > 2\n ? `${item.members\n .slice(0, 2)\n .map((member) => member.label)\n .join(\", \")} and ${item.members.length - 2} more`\n : item.members.map((member) => member.label).join(\" and \")\n : null;\n\n return (\n <figure\n ref={refs}\n data-slot=\"donut-chart\"\n aria-label={label}\n data-legend={legend || undefined}\n className={cn(\"donut-chart box-border font-sans text-foreground\", className)}\n >\n <div\n data-slot=\"donut-chart-ring\"\n className=\"donut-chart-ring\"\n style={{ width: size, \"--inner\": `${((inner * 2) / size) * 100}%` } as CSSProperties}\n tabIndex={legend ? undefined : 0}\n role={legend ? undefined : \"application\"}\n aria-label={legend ? undefined : `${label}. Use the arrow keys to read each segment.`}\n onKeyDown={legend ? undefined : onRingKey}\n onBlur={legend ? undefined : () => setPreview(null)}\n >\n <svg\n ref={svg}\n viewBox={`0 0 ${size} ${size}`}\n aria-hidden=\"true\"\n focusable=\"false\"\n onPointerMove={onRingMove}\n onPointerLeave={() => setPreview(null)}\n onClick={onRingClick}\n data-hovering={current !== null || undefined}\n className=\"block size-full overflow-visible data-[hovering]:cursor-pointer\"\n >\n <circle\n className=\"donut-chart-track\"\n cx={c}\n cy={c}\n r={(outer + inner) / 2}\n strokeWidth={outer - inner}\n data-idle={!shown || !total || undefined}\n />\n {drawn.map((item) => (\n <path\n key={item.key}\n data-key={item.key}\n data-active={item.key === current || undefined}\n data-dim={(current !== null && item.key !== current) || undefined}\n className=\"donut-chart-segment\"\n style={{ \"--slice\": colorFor(item) } as CSSProperties}\n />\n ))}\n </svg>\n <div aria-hidden=\"true\" className=\"donut-chart-center\">\n {readouts.map((item, index) => (\n <span\n key={item.key}\n data-place={Math.sign(index - activeIndex)}\n className=\"donut-chart-readout\"\n >\n <span className=\"block w-full min-h-5 truncate text-xs text-text-secondary\">{item.label}</span>\n <span className=\"block max-w-full min-h-8 truncate text-h3 font-medium tabular-nums\">\n {item.value || item.meta ? <Count value={item.value} format={formatValue} /> : \" \"}\n </span>\n <span className=\"block w-full min-h-5 truncate text-xs tabular-nums text-muted-foreground\">\n {item.meta ? (\n <>\n <Count value={total && !hidden.has(item.key) ? item.value / total : 0} format={shareText} /> of{\" \"}\n {totalLabel.toLowerCase()}\n </>\n ) : (\n unit || \" \"\n )}\n </span>\n </span>\n ))}\n </div>\n </div>\n {legend && slices.length > 0 ? (\n <ul\n id={legendId}\n aria-label={`${label}, segments${legendAction === \"toggle\" ? \". Press a segment to show or hide it\" : \"\"}`}\n onPointerLeave={() => setPreview(null)}\n className=\"m-0 -mb-0.5 grid list-none p-0\"\n >\n {slices.map((item, index) => {\n const off = hidden.has(item.key);\n return (\n <li key={item.key} className=\"overflow-hidden motion-safe:animate-fade-in\">\n <button\n ref={(node) => {\n rows.current[index] = node;\n }}\n type=\"button\"\n data-slot=\"donut-chart-row\"\n aria-pressed={legendAction === \"toggle\" ? !off : selected === item.key}\n aria-label={off ? `${item.label}, hidden` : describe(item)}\n data-active={item.key === current || undefined}\n data-pinned={selected === item.key || undefined}\n data-hidden={off || undefined}\n style={{ \"--slice\": colorFor(item) } as CSSProperties}\n onClick={() => (legendAction === \"toggle\" ? setHidden(item.key) : select(selected === item.key ? null : item.key))}\n onPointerEnter={(event) => {\n if (event.pointerType === \"mouse\") setPreview(off ? null : item.key);\n }}\n onFocus={(event) => {\n if (event.currentTarget.matches(\":focus-visible\")) setPreview(off ? null : item.key);\n }}\n onBlur={onLegendBlur}\n onKeyDown={(event) => onLegendKey(event, index)}\n className=\"donut-chart-row\"\n >\n <span aria-hidden=\"true\" className=\"donut-chart-dot\" />\n <span className=\"grid min-w-0\">\n <span className=\"donut-chart-row-label truncate\">{item.label}</span>\n {item.members ? <span className=\"truncate text-xs text-muted-foreground\">{members(item)}</span> : null}\n </span>\n <span aria-hidden=\"true\" className=\"donut-chart-row-value justify-self-end tabular-nums text-text-secondary\">\n <Count value={item.value} format={formatValue} />\n </span>\n <span aria-hidden=\"true\" className=\"donut-chart-row-value justify-self-end font-medium tabular-nums\">\n <Count value={off || !total ? 0 : item.value / total} format={shareText} />\n </span>\n </button>\n </li>\n );\n })}\n </ul>\n ) : null}\n <p className=\"sr-only\">{summary}</p>\n <p className=\"sr-only\" aria-live=\"polite\">\n {announcement}\n </p>\n {total > 0 ? (\n <div className=\"sr-only\">\n <table>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Segment</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {visible\n .flatMap((item) =>\n item.members\n ? item.members.map((member) => ({ key: member.key, label: `${member.label} (${otherLabel})`, value: member.value }))\n : [item],\n )\n .map((item) => (\n <tr key={item.key}>\n <th scope=\"row\">{item.label}</th>\n <td>{format(item.value)}</td>\n <td>{shareText(item.value / total)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : null}\n </figure>\n );\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
|
+
//#region src/empty-state/empty-state.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* EmptyState: what a list shows when it has nothing to show. An icon in a
|
|
5
|
+
* circle, a short title, a one- or two-line description and an optional next
|
|
6
|
+
* step, centred on the page surface with room to breathe.
|
|
7
|
+
*
|
|
8
|
+
* Presentational, so there is no React Aria base. It exists because every
|
|
9
|
+
* list has an empty case, and without a shared component each screen picks its
|
|
10
|
+
* own padding, border and alignment, so "nothing here" looks different on
|
|
11
|
+
* every page.
|
|
12
|
+
*
|
|
13
|
+
* Every string in the cva blocks below is a STATIC literal. Tailwind scans
|
|
14
|
+
* source text, so a class assembled at runtime is invisible to it and would
|
|
15
|
+
* simply never be emitted.
|
|
16
|
+
*/
|
|
17
|
+
export declare const emptyStateVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
18
|
+
export declare const emptyStateTitleVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
19
|
+
export declare const emptyStateTextVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
20
|
+
export declare const emptyStateActionVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
21
|
+
/**
|
|
22
|
+
* An empty list's message.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* <EmptyState
|
|
26
|
+
* icon={<Folder aria-hidden="true" />}
|
|
27
|
+
* title="No saved views"
|
|
28
|
+
* description="Save a set of filters as a view to come back to it later."
|
|
29
|
+
* action={<Button>Create view</Button>}
|
|
30
|
+
* />
|
|
31
|
+
*/
|
|
32
|
+
export interface EmptyStateProps extends Omit<ComponentPropsWithoutRef<"div">, "title"> {
|
|
33
|
+
/**
|
|
34
|
+
* A short heading above the description. When it is set, `description` (or
|
|
35
|
+
* `children`) is the supporting text under it.
|
|
36
|
+
*/
|
|
37
|
+
title?: ReactNode;
|
|
38
|
+
/** One or two lines of supporting text. `children` is the same slot and works the same way. */
|
|
39
|
+
description?: ReactNode;
|
|
40
|
+
/** Why the list is empty, in one short statement. The message when there is no `description`. */
|
|
41
|
+
children?: ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* A glyph above the message, inside a circle. It settles in once when the state first appears
|
|
44
|
+
* (small and transparent to rest over 480ms); a different icon component later
|
|
45
|
+
* swaps in place, and the same one re-rendering stays still. Mark it `aria-hidden`.
|
|
46
|
+
*/
|
|
47
|
+
icon?: ReactNode;
|
|
48
|
+
/** A next step under the text: a button or a link. Omitted from the DOM when absent. */
|
|
49
|
+
action?: ReactNode;
|
|
50
|
+
/** Extra classes for the box. Merged last, so they win conflicts with ours. */
|
|
51
|
+
className?: string;
|
|
52
|
+
}
|
|
53
|
+
export declare const EmptyState: import("react").ForwardRefExoticComponent<EmptyStateProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
54
|
+
//#endregion
|
|
55
|
+
//# sourceMappingURL=empty-state.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn, cnAll } from "../lib/cn.js";
|
|
3
|
+
import { SwapText } from "../lib/swap-text.js";
|
|
4
|
+
import { useHeightFollow } from "../lib/height-follow.js";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { forwardRef, isValidElement, useRef } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/empty-state/empty-state.tsx
|
|
9
|
+
/**
|
|
10
|
+
* EmptyState: what a list shows when it has nothing to show. An icon in a
|
|
11
|
+
* circle, a short title, a one- or two-line description and an optional next
|
|
12
|
+
* step, centred on the page surface with room to breathe.
|
|
13
|
+
*
|
|
14
|
+
* Presentational, so there is no React Aria base. It exists because every
|
|
15
|
+
* list has an empty case, and without a shared component each screen picks its
|
|
16
|
+
* own padding, border and alignment, so "nothing here" looks different on
|
|
17
|
+
* every page.
|
|
18
|
+
*
|
|
19
|
+
* Every string in the cva blocks below is a STATIC literal. Tailwind scans
|
|
20
|
+
* source text, so a class assembled at runtime is invisible to it and would
|
|
21
|
+
* simply never be emitted.
|
|
22
|
+
*/
|
|
23
|
+
const emptyStateVariants = cva(["flex flex-col items-center px-5 py-12 text-center", "box-border font-sans text-foreground"]);
|
|
24
|
+
const emptyStateTitleVariants = cva("m-0 mt-5 text-base leading-(--leading-normal) font-medium text-foreground");
|
|
25
|
+
const emptyStateTextVariants = cva("mx-auto mt-0 mb-0 max-w-72 text-sm leading-(--leading-normal) text-pretty text-text-secondary");
|
|
26
|
+
const emptyStateActionVariants = cva("mt-5 flex flex-wrap justify-center gap-3");
|
|
27
|
+
/** The name an icon swaps under: a different component swaps; the same one re-rendering does not. */
|
|
28
|
+
function iconKey(icon) {
|
|
29
|
+
if (!isValidElement(icon)) return "icon";
|
|
30
|
+
const type = icon.type;
|
|
31
|
+
return typeof type === "string" ? type : type.displayName ?? type.name ?? "icon";
|
|
32
|
+
}
|
|
33
|
+
const EmptyState = forwardRef(function EmptyState({ title, description, children, icon, action, className, ...props }, ref) {
|
|
34
|
+
const frame = useRef(null);
|
|
35
|
+
const copy = useRef(null);
|
|
36
|
+
const message = description ?? children;
|
|
37
|
+
const text = (value) => typeof value === "string" ? /* @__PURE__ */ jsx(SwapText, {
|
|
38
|
+
swapKey: value,
|
|
39
|
+
className: "block",
|
|
40
|
+
children: value
|
|
41
|
+
}) : value;
|
|
42
|
+
useHeightFollow(frame, copy, `${typeof title === "string" ? title : ""}\n${typeof message === "string" ? message : ""}`);
|
|
43
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
44
|
+
ref,
|
|
45
|
+
...props,
|
|
46
|
+
"data-slot": "empty-state",
|
|
47
|
+
className: cn(emptyStateVariants(), className),
|
|
48
|
+
children: [
|
|
49
|
+
icon === void 0 || icon === null ? null : /* @__PURE__ */ jsx("div", {
|
|
50
|
+
"data-slot": "empty-state-icon",
|
|
51
|
+
"aria-hidden": "true",
|
|
52
|
+
className: "grid size-12 place-items-center rounded-circle border-(length:--border-width) border-border bg-muted text-text-secondary motion-safe:animate-empty-state-icon [&_svg]:size-6",
|
|
53
|
+
children: /* @__PURE__ */ jsx(SwapText, {
|
|
54
|
+
swapKey: iconKey(icon),
|
|
55
|
+
motion: "glyph",
|
|
56
|
+
className: "grid place-items-center",
|
|
57
|
+
children: icon
|
|
58
|
+
})
|
|
59
|
+
}),
|
|
60
|
+
/* @__PURE__ */ jsx("div", {
|
|
61
|
+
ref: frame,
|
|
62
|
+
"data-slot": "empty-state-copy",
|
|
63
|
+
className: "height-follow w-full",
|
|
64
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
65
|
+
ref: copy,
|
|
66
|
+
className: "flow-root",
|
|
67
|
+
children: [title == null ? null : /* @__PURE__ */ jsx("h3", {
|
|
68
|
+
"data-slot": "empty-state-title",
|
|
69
|
+
className: emptyStateTitleVariants(),
|
|
70
|
+
children: text(title)
|
|
71
|
+
}), message == null ? null : /* @__PURE__ */ jsx("p", {
|
|
72
|
+
"data-slot": "empty-state-text",
|
|
73
|
+
className: cnAll(emptyStateTextVariants(), title != null ? "mt-2" : icon != null && "mt-5"),
|
|
74
|
+
children: text(message)
|
|
75
|
+
})]
|
|
76
|
+
})
|
|
77
|
+
}),
|
|
78
|
+
action == null ? null : /* @__PURE__ */ jsx("div", {
|
|
79
|
+
"data-slot": "empty-state-action",
|
|
80
|
+
className: emptyStateActionVariants(),
|
|
81
|
+
children: action
|
|
82
|
+
})
|
|
83
|
+
]
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//#endregion
|
|
87
|
+
export { EmptyState, emptyStateActionVariants, emptyStateTextVariants, emptyStateTitleVariants, emptyStateVariants };
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=empty-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-state.js","names":[],"sources":["../../src/empty-state/empty-state.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport {\n forwardRef,\n isValidElement,\n useRef,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from \"react\";\n\nimport { cn, cnAll } from \"../lib/cn.js\";\nimport { useHeightFollow } from \"../lib/height-follow.js\";\nimport { SwapText } from \"../lib/swap-text.js\";\n\n/**\n * EmptyState: what a list shows when it has nothing to show. An icon in a\n * circle, a short title, a one- or two-line description and an optional next\n * step, centred on the page surface with room to breathe.\n *\n * Presentational, so there is no React Aria base. It exists because every\n * list has an empty case, and without a shared component each screen picks its\n * own padding, border and alignment, so \"nothing here\" looks different on\n * every page.\n *\n * Every string in the cva blocks below is a STATIC literal. Tailwind scans\n * source text, so a class assembled at runtime is invisible to it and would\n * simply never be emitted.\n */\nexport const emptyStateVariants = cva([\n \"flex flex-col items-center px-5 py-12 text-center\",\n // The reset in @seekalfred/styles is opt-in, so a consumer may load none.\n // Its own text colour too, so it reads the same on any page background.\n \"box-border font-sans text-foreground\",\n]);\n\nexport const emptyStateTitleVariants = cva(\n \"m-0 mt-5 text-base leading-(--leading-normal) font-medium text-foreground\",\n);\n\nexport const emptyStateTextVariants = cva(\n \"mx-auto mt-0 mb-0 max-w-72 text-sm leading-(--leading-normal) text-pretty text-text-secondary\",\n);\n\nexport const emptyStateActionVariants = cva(\"mt-5 flex flex-wrap justify-center gap-3\");\n\n/**\n * An empty list's message.\n *\n * @example\n * <EmptyState\n * icon={<Folder aria-hidden=\"true\" />}\n * title=\"No saved views\"\n * description=\"Save a set of filters as a view to come back to it later.\"\n * action={<Button>Create view</Button>}\n * />\n */\nexport interface EmptyStateProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"title\"> {\n /**\n * A short heading above the description. When it is set, `description` (or\n * `children`) is the supporting text under it.\n */\n title?: ReactNode;\n /** One or two lines of supporting text. `children` is the same slot and works the same way. */\n description?: ReactNode;\n /** Why the list is empty, in one short statement. The message when there is no `description`. */\n children?: ReactNode;\n /**\n * A glyph above the message, inside a circle. It settles in once when the state first appears\n * (small and transparent to rest over 480ms); a different icon component later\n * swaps in place, and the same one re-rendering stays still. Mark it `aria-hidden`.\n */\n icon?: ReactNode;\n /** A next step under the text: a button or a link. Omitted from the DOM when absent. */\n action?: ReactNode;\n /** Extra classes for the box. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\n/** The name an icon swaps under: a different component swaps; the same one re-rendering does not. */\nfunction iconKey(icon: ReactNode) {\n if (!isValidElement(icon)) return \"icon\";\n const type = icon.type as string | { displayName?: string; name?: string };\n return typeof type === \"string\" ? type : (type.displayName ?? type.name ?? \"icon\");\n}\n\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(function EmptyState(\n { title, description, children, icon, action, className, ...props },\n ref,\n) {\n const frame = useRef<HTMLDivElement>(null);\n const copy = useRef<HTMLDivElement>(null);\n const message = description ?? children;\n const text = (value: ReactNode) =>\n typeof value === \"string\" ? (\n <SwapText swapKey={value} className=\"block\">\n {value}\n </SwapText>\n ) : (\n value\n );\n // The copy column follows its height when the title or the message changes.\n useHeightFollow(\n frame,\n copy,\n `${typeof title === \"string\" ? title : \"\"}\\n${typeof message === \"string\" ? message : \"\"}`,\n );\n return (\n <div\n ref={ref}\n {...props}\n data-slot=\"empty-state\"\n className={cn(emptyStateVariants(), className)}\n >\n {icon === undefined || icon === null ? null : (\n <div\n data-slot=\"empty-state-icon\"\n aria-hidden=\"true\"\n className=\"grid size-12 place-items-center rounded-circle border-(length:--border-width) border-border bg-muted text-text-secondary motion-safe:animate-empty-state-icon [&_svg]:size-6\"\n >\n <SwapText swapKey={iconKey(icon)} motion=\"glyph\" className=\"grid place-items-center\">\n {icon}\n </SwapText>\n </div>\n )}\n <div ref={frame} data-slot=\"empty-state-copy\" className=\"height-follow w-full\">\n <div ref={copy} className=\"flow-root\">\n {title == null ? null : (\n <h3 data-slot=\"empty-state-title\" className={emptyStateTitleVariants()}>\n {text(title)}\n </h3>\n )}\n {message == null ? null : (\n <p\n data-slot=\"empty-state-text\"\n className={cnAll(\n emptyStateTextVariants(),\n // Under the title it sits close; straight under the icon it clears it.\n title != null ? \"mt-2\" : icon != null && \"mt-5\",\n )}\n >\n {text(message)}\n </p>\n )}\n </div>\n </div>\n {action == null ? null : (\n <div data-slot=\"empty-state-action\" className={emptyStateActionVariants()}>\n {action}\n </div>\n )}\n </div>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,qBAAqB,IAAI,CACpC,qDAGA,sCACF,CAAC;AAED,MAAa,0BAA0B,IACrC,2EACF;AAEA,MAAa,yBAAyB,IACpC,+FACF;AAEA,MAAa,2BAA2B,IAAI,0CAA0C;;AAoCtF,SAAS,QAAQ,MAAiB;CAChC,IAAI,CAAC,eAAe,IAAI,GAAG,OAAO;CAClC,MAAM,OAAO,KAAK;CAClB,OAAO,OAAO,SAAS,WAAW,OAAQ,KAAK,eAAe,KAAK,QAAQ;AAC7E;AAEA,MAAa,aAAa,WAA4C,SAAS,WAC7E,EAAE,OAAO,aAAa,UAAU,MAAM,QAAQ,WAAW,GAAG,SAC5D,KACA;CACA,MAAM,QAAQ,OAAuB,IAAI;CACzC,MAAM,OAAO,OAAuB,IAAI;CACxC,MAAM,UAAU,eAAe;CAC/B,MAAM,QAAQ,UACZ,OAAO,UAAU,WACf,oBAAC,UAAD;EAAU,SAAS;EAAO,WAAU;EACjC,UAAA;CACO,CAAA,IAEV;CAGJ,gBACE,OACA,MACA,GAAG,OAAO,UAAU,WAAW,QAAQ,GAAG,IAAI,OAAO,YAAY,WAAW,UAAU,IACxF;CACA,OACE,qBAAC,OAAD;EACO;EACL,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,mBAAmB,GAAG,SAAS;EAJ/C,UAAA;GAMG,SAAS,KAAA,KAAa,SAAS,OAAO,OACrC,oBAAC,OAAD;IACE,aAAU;IACV,eAAY;IACZ,WAAU;IAEV,UAAA,oBAAC,UAAD;KAAU,SAAS,QAAQ,IAAI;KAAG,QAAO;KAAQ,WAAU;KACxD,UAAA;IACO,CAAA;GACP,CAAA;GAEP,oBAAC,OAAD;IAAK,KAAK;IAAO,aAAU;IAAmB,WAAU;IACtD,UAAA,qBAAC,OAAD;KAAK,KAAK;KAAM,WAAU;KAA1B,UAAA,CACG,SAAS,OAAO,OACf,oBAAC,MAAD;MAAI,aAAU;MAAoB,WAAW,wBAAwB;MAClE,UAAA,KAAK,KAAK;KACT,CAAA,GAEL,WAAW,OAAO,OACjB,oBAAC,KAAD;MACE,aAAU;MACV,WAAW,MACT,uBAAuB,GAEvB,SAAS,OAAO,SAAS,QAAQ,QAAQ,MAC3C;MAEC,UAAA,KAAK,OAAO;KACZ,CAAA,CAEF;;GACF,CAAA;GACJ,UAAU,OAAO,OAChB,oBAAC,OAAD;IAAK,aAAU;IAAqB,WAAW,yBAAyB;IACrE,UAAA;GACE,CAAA;EAEJ;;AAET,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { EmptyState, EmptyStateProps, emptyStateActionVariants, emptyStateTextVariants, emptyStateTitleVariants, emptyStateVariants } from "./empty-state.js";
|
|
2
|
+
export { EmptyState, type EmptyStateProps, emptyStateActionVariants, emptyStateTextVariants, emptyStateTitleVariants, emptyStateVariants };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/expanding-button-group/expanding-button-group.d.ts
|
|
3
|
+
export type ExpandingButtonGroupSize = "sm" | "md";
|
|
4
|
+
export type ExpandingButtonGroupTone = "neutral" | "danger";
|
|
5
|
+
export interface ExpandingButtonGroupItem {
|
|
6
|
+
/** Stable key for the action. Also the value passed to onAction. */
|
|
7
|
+
id: string;
|
|
8
|
+
/** Visible label once the button expands, and its accessible name at all times. Use a short verb, such as "Archive". */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Icon shown while collapsed. A 16px icon fits; it is sized by the group. Mark it `aria-hidden`. */
|
|
11
|
+
icon: ReactNode;
|
|
12
|
+
/** Runs the action. Return false, or reject, to skip the confirmation. A promise keeps the button busy until it settles. */
|
|
13
|
+
onSelect?: () => void | boolean | Promise<void | boolean>;
|
|
14
|
+
/** Past tense word shown in place after the action, such as "Archived". The icon becomes a check for confirmDuration. Omit for actions that open something. */
|
|
15
|
+
doneLabel?: string;
|
|
16
|
+
/** `danger` colours the expanded state with the destructive token, for destructive actions such as Delete. */
|
|
17
|
+
tone?: ExpandingButtonGroupTone;
|
|
18
|
+
/** Dimmed and inert. Stays focusable and still reveals its label, so people can learn what it would do. */
|
|
19
|
+
isDisabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface ExpandingButtonGroupProps {
|
|
22
|
+
items: readonly ExpandingButtonGroupItem[];
|
|
23
|
+
/** Accessible name of the toolbar, such as "Message actions". */
|
|
24
|
+
label: string;
|
|
25
|
+
/** @default "md" */
|
|
26
|
+
size?: ExpandingButtonGroupSize;
|
|
27
|
+
/**
|
|
28
|
+
* Id of the action whose label shows at rest, usually the primary one. Defaults to the first enabled action: one action is always
|
|
29
|
+
* expanded. Pointing at or focusing another moves the expansion there, and it returns here when the pointer and focus leave.
|
|
30
|
+
*/
|
|
31
|
+
defaultExpanded?: string | null;
|
|
32
|
+
/** Called with the item id whenever an action runs, before its own onSelect. */
|
|
33
|
+
onAction?: (id: string) => void;
|
|
34
|
+
/** How long the confirmation stays, in milliseconds. @default 1400 */
|
|
35
|
+
confirmDuration?: number;
|
|
36
|
+
/** Extra classes. Merged last, so they win conflicts with ours. */
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A compact pill of icon buttons for actions. One action always shows its label;
|
|
41
|
+
* the one you point at or focus takes over the label while its neighbours slide
|
|
42
|
+
* aside, and an action can confirm in place: the icon draws a check and the label
|
|
43
|
+
* becomes a past tense word. On touch, the first tap reveals the label and a
|
|
44
|
+
* second tap runs the action.
|
|
45
|
+
*
|
|
46
|
+
* Arrow keys move focus, Home and End jump to the ends. A disabled action stays
|
|
47
|
+
* focusable and still reveals its label, so people can learn what it would do.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* <ExpandingButtonGroup label="Message actions" items={[{ id: "archive", label: "Archive", doneLabel: "Archived", icon: <ArchiveIcon aria-hidden /> }]} />
|
|
51
|
+
*/
|
|
52
|
+
export declare function ExpandingButtonGroup({ items, label, size, defaultExpanded, onAction, confirmDuration, className }: ExpandingButtonGroupProps): import("react").JSX.Element;
|
|
53
|
+
//#endregion
|
|
54
|
+
//# sourceMappingURL=expanding-button-group.d.ts.map
|