@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
|
@@ -44,9 +44,10 @@ const accordionTriggerVariants = cva([
|
|
|
44
44
|
"[&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
45
45
|
"[&_svg:not([class*='size-'])]:size-(--icon-sm)",
|
|
46
46
|
"[&_svg]:text-muted-foreground",
|
|
47
|
-
"[&_svg]:motion-safe:transition-transform [&_svg]:motion-safe:duration-(--duration-
|
|
47
|
+
"[&_svg]:motion-safe:transition-transform [&_svg]:motion-safe:duration-(--duration-snappy) [&_svg]:motion-safe:ease-snappy",
|
|
48
|
+
"[&_svg]:motion-safe:transition-[transform,color]"
|
|
48
49
|
]);
|
|
49
|
-
const accordionPanelVariants = cva(["pb-(--density-control-pad-md) font-sans text-sm leading-(--leading-normal) text-foreground"]);
|
|
50
|
+
const accordionPanelVariants = cva(["pb-(--density-control-pad-md) font-sans text-sm leading-(--leading-normal) text-foreground", "accordion-panel"]);
|
|
50
51
|
const Accordion = forwardRef(function Accordion({ className, ...props }, ref) {
|
|
51
52
|
return /* @__PURE__ */ jsx(DisclosureGroup, {
|
|
52
53
|
ref,
|
|
@@ -75,12 +76,17 @@ const AccordionTrigger = forwardRef(function AccordionTrigger({ children, icon,
|
|
|
75
76
|
})
|
|
76
77
|
});
|
|
77
78
|
});
|
|
78
|
-
const AccordionPanel = forwardRef(function AccordionPanel({ className, ...props }, ref) {
|
|
79
|
+
const AccordionPanel = forwardRef(function AccordionPanel({ className, children, ...props }, ref) {
|
|
79
80
|
return /* @__PURE__ */ jsx(DisclosurePanel, {
|
|
80
81
|
ref,
|
|
81
82
|
...props,
|
|
82
83
|
"data-slot": "accordion-panel",
|
|
83
|
-
className: cn(accordionPanelVariants(), className)
|
|
84
|
+
className: cn(accordionPanelVariants(), className),
|
|
85
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
86
|
+
"data-slot": "accordion-panel-content",
|
|
87
|
+
className: "accordion-panel-content",
|
|
88
|
+
children
|
|
89
|
+
})
|
|
84
90
|
});
|
|
85
91
|
});
|
|
86
92
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accordion.js","names":["AriaDisclosureGroup","AriaDisclosure","AriaButton","AriaDisclosurePanel"],"sources":["../../src/accordion/accordion.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n Button as AriaButton,\n Disclosure as AriaDisclosure,\n DisclosureGroup as AriaDisclosureGroup,\n DisclosurePanel as AriaDisclosurePanel,\n Heading,\n type DisclosureGroupProps as AriaDisclosureGroupProps,\n type DisclosurePanelProps as AriaDisclosurePanelProps,\n type DisclosureProps as AriaDisclosureProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\n\n/**\n * Accordion, ported from the legacy shadcn/Radix component onto React Aria's\n * Disclosure primitives.\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 -- the component would render unstyled with no\n * error anywhere.\n *\n * State comes from React Aria data attributes (`data-expanded`,\n * `data-focus-visible`, `data-disabled`), never from pseudo-classes.\n *\n * ONE BEHAVIOUR IS DELIBERATELY DROPPED. Radix moved focus between headers\n * with Home/End and the arrow keys; React Aria's useDisclosure has no key\n * handling, so each trigger is a button in the tab order and arrows do\n * nothing. The ARIA APG lists arrow navigation for accordions as optional,\n * and hand-rolling roving focus would mean owning focus management that the\n * headless base deliberately does not. The TabReachesEveryTrigger story pins\n * this so it stays a decision rather than becoming a surprise.\n */\nexport const accordionVariants = cva(\"w-full\");\n\nexport const accordionItemVariants = cva([\n // The divider between items. border-b-0 on the last child rather than\n // border-t on siblings: it survives a single-item accordion, which the\n // sibling form does not.\n \"border-b-(length:--border-width) border-b-border last:border-b-0\",\n // The chevron rotation is authored HERE, not on the trigger: React Aria\n // puts data-expanded on the Disclosure, and CSS cannot look upward from\n // the button to its expanded ancestor.\n \"data-[expanded]:[&_[data-slot=accordion-trigger]_svg]:rotate-180\",\n]);\n\nexport const accordionTriggerVariants = cva([\n \"flex w-full items-center justify-between gap-(--density-control-gap)\",\n // text-start, never text-left. Logical properties are what make RTL work\n // without a second stylesheet (ARCHITECTURE section 5 rule 4).\n \"text-start text-sm leading-(--leading-normal) font-sans font-medium text-foreground\",\n \"rounded-md py-(--density-control-pad-md)\",\n \"cursor-pointer select-none\",\n\n // The reset in @seekalfred/styles is opt-in, so a consumer may load none.\n // A bare <button> then keeps the user-agent border, ButtonFace grey and\n // Arial -- the same defence the Button base carries, for the same reason.\n \"border-(length:--border-width) border-transparent bg-transparent\",\n\n // A real outline, not a ring. The legacy component focused with\n // ring-[3px], a box-shadow, which forced-colors discards entirely -- and\n // axe has no focus-indicator rule, so nothing would have caught it.\n // outline-solid is load-bearing: outline-none sets --tw-outline-style:none\n // and the width utility resolves its style from that same variable, so\n // without it the ring gets a width and a colour and paints nothing.\n \"outline-none\",\n \"data-[focus-visible]:outline-solid\",\n \"data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset)\",\n \"data-[focus-visible]:outline-(--color-ring)\",\n\n \"motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n \"data-[hovered]:underline\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-(--opacity-disabled)\",\n\n // The chevron. Sized from the icon scale unless the caller sized it, and\n // never a press target of its own.\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"[&_svg:not([class*='size-'])]:size-(--icon-sm)\",\n \"[&_svg]:text-muted-foreground\",\n // Rotation is the whole motion story for this component -- see the panel\n // note below for why the panel itself does not animate.\n \"[&_svg]:motion-safe:transition-transform [&_svg]:motion-safe:duration-(--duration-fast)\",\n]);\n\nexport const accordionPanelVariants = cva([\n // font-sans is not decoration. The panel is a plain <div> inheriting from\n // the consumer's body, and the library deliberately does not style the\n // page -- so without this the copy renders in the browser's default serif\n // while the trigger above it renders in the brand face. Caught by eye in\n // the browser, not by any assertion, which is why NoUaLeak now covers the\n // panel too.\n \"pb-(--density-control-pad-md) font-sans text-sm leading-(--leading-normal) text-foreground\",\n // No expand/collapse animation, deliberately. React Aria hides a collapsed\n // panel with the `hidden` attribute, which is display:none, and CSS cannot\n // transition out of display:none. Overriding [hidden] would restore the\n // animation by breaking the accessibility semantics that make hidden\n // correct -- the panel would stay in the accessibility tree while\n // collapsed. @starting-style with transition-behavior:allow-discrete could\n // do this properly once the browser floor allows it.\n]);\n\n/**\n * A grouping of collapsible sections.\n *\n * Expansion is KEYED, which is the sharpest break from the legacy component:\n * `type=\"single\" | \"multiple\"` becomes {@link AccordionProps.allowsMultipleExpanded},\n * and `value` / `defaultValue` strings become `expandedKeys` /\n * `defaultExpandedKeys` holding item ids. The change handler receives a\n * `Set`, not a string.\n *\n * The legacy `collapsible` prop has no equivalent and needs none: React\n * Aria's single-expand mode always allows collapsing the open item.\n *\n * @example\n * <Accordion defaultExpandedKeys={[\"billing\"]}>\n * <AccordionItem id=\"billing\">\n * <AccordionTrigger icon={<ChevronDown aria-hidden />}>Billing</AccordionTrigger>\n * <AccordionPanel>Invoices and payment methods.</AccordionPanel>\n * </AccordionItem>\n * </Accordion>\n */\nexport interface AccordionProps\n extends\n Omit<AriaDisclosureGroupProps, \"className\" | \"style\">,\n VariantProps<typeof accordionVariants> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(\n { className, ...props },\n ref,\n) {\n return (\n <AriaDisclosureGroup\n ref={ref}\n {...props}\n data-slot=\"accordion\"\n className={cn(accordionVariants(), className)}\n />\n );\n});\n\n/**\n * One collapsible section.\n *\n * `id` replaces the legacy `value`, and is what `expandedKeys` refers to.\n */\nexport interface AccordionItemProps\n extends\n Omit<AriaDisclosureProps, \"className\" | \"style\">,\n VariantProps<typeof accordionItemVariants> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\nexport const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(function AccordionItem(\n { className, ...props },\n ref,\n) {\n return (\n <AriaDisclosure\n ref={ref}\n {...props}\n data-slot=\"accordion-item\"\n className={cn(accordionItemVariants(), className)}\n />\n );\n});\n\n/**\n * The header button that expands its item.\n *\n * Rendered inside a {@link Heading} because screen-reader users navigate an\n * accordion by heading; that wrapper is what makes it usable rather than\n * merely operable.\n */\nexport interface AccordionTriggerProps extends VariantProps<typeof accordionTriggerVariants> {\n /** The header label. */\n children?: ReactNode;\n /**\n * The expand/collapse glyph, rendered after the label.\n *\n * Required, and supplied by the caller: this library ships no icon set, so\n * it stays icon-library agnostic. Mark the glyph `aria-hidden` -- the label\n * is the accessible name, and a second name source makes the trigger\n * announce twice. It is sized at `--icon-sm` unless it carries a `size-*`\n * class of its own, and rotates on expand.\n */\n icon: ReactNode;\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n /**\n * Heading level for the wrapper. Accordions appear at different depths, and\n * a fixed level would break the document outline wherever it is wrong.\n *\n * @default 3\n */\n headingLevel?: number;\n}\n\nexport const AccordionTrigger = forwardRef<HTMLButtonElement, AccordionTriggerProps>(\n function AccordionTrigger({ children, icon, className, headingLevel = 3 }, ref) {\n return (\n <Heading level={headingLevel}>\n <AriaButton\n // The ref goes on the button, not the Heading wrapping it: Heading has\n // no interactive behaviour, while the button is what expands/collapses\n // and carries the press/focus data attributes.\n ref={ref}\n slot=\"trigger\"\n data-slot=\"accordion-trigger\"\n className={cn(accordionTriggerVariants(), className)}\n >\n {children}\n {icon}\n </AriaButton>\n </Heading>\n );\n },\n);\n\n/**\n * The content revealed when its item expands.\n *\n * Named Panel rather than the legacy Content, matching React Aria and the\n * ARIA pattern.\n */\nexport interface AccordionPanelProps\n extends\n Omit<AriaDisclosurePanelProps, \"className\" | \"style\">,\n VariantProps<typeof accordionPanelVariants> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\nexport const AccordionPanel = forwardRef<HTMLDivElement, AccordionPanelProps>(\n function AccordionPanel({ className, ...props }, ref) {\n return (\n <AriaDisclosurePanel\n ref={ref}\n {...props}\n data-slot=\"accordion-panel\"\n className={cn(accordionPanelVariants(), className)}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,oBAAoB,IAAI,QAAQ;AAE7C,MAAa,wBAAwB,IAAI,CAIvC,oEAIA,kEACF,CAAC;AAED,MAAa,2BAA2B,IAAI;CAC1C;CAGA;CACA;CACA;CAKA;CAQA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CAIA;CACA;CACA;CAGA;AACF,CAAC;AAED,MAAa,yBAAyB,IAAI,CAOxC,4FAQF,CAAC;AA8BD,MAAa,YAAY,WAA2C,SAAS,UAC3E,EAAE,WAAW,GAAG,SAChB,KACA;CACA,OACE,oBAACA,iBAAD;EACO;EACL,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,kBAAkB,GAAG,SAAS;CAC7C,CAAA;AAEL,CAAC;AAeD,MAAa,gBAAgB,WAA+C,SAAS,cACnF,EAAE,WAAW,GAAG,SAChB,KACA;CACA,OACE,oBAACC,YAAD;EACO;EACL,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,sBAAsB,GAAG,SAAS;CACjD,CAAA;AAEL,CAAC;AAiCD,MAAa,mBAAmB,WAC9B,SAAS,iBAAiB,EAAE,UAAU,MAAM,WAAW,eAAe,KAAK,KAAK;CAC9E,OACE,oBAAC,SAAD;EAAS,OAAO;EACd,UAAA,qBAACC,QAAD;GAIO;GACL,MAAK;GACL,aAAU;GACV,WAAW,GAAG,yBAAyB,GAAG,SAAS;GAPrD,UAAA,CASG,UACA,IACS;;CACL,CAAA;AAEb,CACF;AAgBA,MAAa,iBAAiB,WAC5B,SAAS,eAAe,EAAE,WAAW,GAAG,SAAS,KAAK;CACpD,OACE,oBAACC,iBAAD;EACO;EACL,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,uBAAuB,GAAG,SAAS;CAClD,CAAA;AAEL,CACF"}
|
|
1
|
+
{"version":3,"file":"accordion.js","names":["AriaDisclosureGroup","AriaDisclosure","AriaButton","AriaDisclosurePanel"],"sources":["../../src/accordion/accordion.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n Button as AriaButton,\n Disclosure as AriaDisclosure,\n DisclosureGroup as AriaDisclosureGroup,\n DisclosurePanel as AriaDisclosurePanel,\n Heading,\n type DisclosureGroupProps as AriaDisclosureGroupProps,\n type DisclosurePanelProps as AriaDisclosurePanelProps,\n type DisclosureProps as AriaDisclosureProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\n\n/**\n * Accordion, ported from the legacy shadcn/Radix component onto React Aria's\n * Disclosure primitives.\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 -- the component would render unstyled with no\n * error anywhere.\n *\n * State comes from React Aria data attributes (`data-expanded`,\n * `data-focus-visible`, `data-disabled`), never from pseudo-classes.\n *\n * ONE BEHAVIOUR IS DELIBERATELY DROPPED. Radix moved focus between headers\n * with Home/End and the arrow keys; React Aria's useDisclosure has no key\n * handling, so each trigger is a button in the tab order and arrows do\n * nothing. The ARIA APG lists arrow navigation for accordions as optional,\n * and hand-rolling roving focus would mean owning focus management that the\n * headless base deliberately does not. The TabReachesEveryTrigger story pins\n * this so it stays a decision rather than becoming a surprise.\n */\nexport const accordionVariants = cva(\"w-full\");\n\nexport const accordionItemVariants = cva([\n // The divider between items. border-b-0 on the last child rather than\n // border-t on siblings: it survives a single-item accordion, which the\n // sibling form does not.\n \"border-b-(length:--border-width) border-b-border last:border-b-0\",\n // The chevron rotation is authored HERE, not on the trigger: React Aria\n // puts data-expanded on the Disclosure, and CSS cannot look upward from\n // the button to its expanded ancestor.\n \"data-[expanded]:[&_[data-slot=accordion-trigger]_svg]:rotate-180\",\n]);\n\nexport const accordionTriggerVariants = cva([\n \"flex w-full items-center justify-between gap-(--density-control-gap)\",\n // text-start, never text-left. Logical properties are what make RTL work\n // without a second stylesheet (ARCHITECTURE section 5 rule 4).\n \"text-start text-sm leading-(--leading-normal) font-sans font-medium text-foreground\",\n \"rounded-md py-(--density-control-pad-md)\",\n \"cursor-pointer select-none\",\n\n // The reset in @seekalfred/styles is opt-in, so a consumer may load none.\n // A bare <button> then keeps the user-agent border, ButtonFace grey and\n // Arial -- the same defence the Button base carries, for the same reason.\n \"border-(length:--border-width) border-transparent bg-transparent\",\n\n // A real outline, not a ring. The legacy component focused with\n // ring-[3px], a box-shadow, which forced-colors discards entirely -- and\n // axe has no focus-indicator rule, so nothing would have caught it.\n // outline-solid is load-bearing: outline-none sets --tw-outline-style:none\n // and the width utility resolves its style from that same variable, so\n // without it the ring gets a width and a colour and paints nothing.\n \"outline-none\",\n \"data-[focus-visible]:outline-solid\",\n \"data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset)\",\n \"data-[focus-visible]:outline-(--color-ring)\",\n\n \"motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n \"data-[hovered]:underline\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-(--opacity-disabled)\",\n\n // The chevron. Sized from the icon scale unless the caller sized it, and\n // never a press target of its own.\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"[&_svg:not([class*='size-'])]:size-(--icon-sm)\",\n \"[&_svg]:text-muted-foreground\",\n // Rotation is the whole motion story for this component -- see the panel\n // note below for why the panel itself does not animate.\n \"[&_svg]:motion-safe:transition-transform [&_svg]:motion-safe:duration-(--duration-snappy) [&_svg]:motion-safe:ease-snappy\",\n // The icon takes its full colour once its panel is open.\n \"[&_svg]:motion-safe:transition-[transform,color]\",\n]);\n\nexport const accordionPanelVariants = cva([\n // font-sans is not decoration. The panel is a plain <div> inheriting from\n // the consumer's body, and the library deliberately does not style the\n // page -- so without this the copy renders in the browser's default serif\n // while the trigger above it renders in the brand face. Caught by eye in\n // the browser, not by any assertion, which is why NoUaLeak now covers the\n // panel too.\n \"pb-(--density-control-pad-md) font-sans text-sm leading-(--leading-normal) text-foreground\",\n // Opens and closes in place (see the accordion-panel utility): the collapsed\n // panel is kept as a box of no height, out of the accessibility tree.\n \"accordion-panel\",\n]);\n\n/**\n * A grouping of collapsible sections.\n *\n * Expansion is KEYED, which is the sharpest break from the legacy component:\n * `type=\"single\" | \"multiple\"` becomes {@link AccordionProps.allowsMultipleExpanded},\n * and `value` / `defaultValue` strings become `expandedKeys` /\n * `defaultExpandedKeys` holding item ids. The change handler receives a\n * `Set`, not a string.\n *\n * The legacy `collapsible` prop has no equivalent and needs none: React\n * Aria's single-expand mode always allows collapsing the open item.\n *\n * @example\n * <Accordion defaultExpandedKeys={[\"billing\"]}>\n * <AccordionItem id=\"billing\">\n * <AccordionTrigger icon={<ChevronDown aria-hidden />}>Billing</AccordionTrigger>\n * <AccordionPanel>Invoices and payment methods.</AccordionPanel>\n * </AccordionItem>\n * </Accordion>\n */\nexport interface AccordionProps\n extends\n Omit<AriaDisclosureGroupProps, \"className\" | \"style\">,\n VariantProps<typeof accordionVariants> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(\n { className, ...props },\n ref,\n) {\n return (\n <AriaDisclosureGroup\n ref={ref}\n {...props}\n data-slot=\"accordion\"\n className={cn(accordionVariants(), className)}\n />\n );\n});\n\n/**\n * One collapsible section.\n *\n * `id` replaces the legacy `value`, and is what `expandedKeys` refers to.\n */\nexport interface AccordionItemProps\n extends\n Omit<AriaDisclosureProps, \"className\" | \"style\">,\n VariantProps<typeof accordionItemVariants> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\nexport const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(function AccordionItem(\n { className, ...props },\n ref,\n) {\n return (\n <AriaDisclosure\n ref={ref}\n {...props}\n data-slot=\"accordion-item\"\n className={cn(accordionItemVariants(), className)}\n />\n );\n});\n\n/**\n * The header button that expands its item.\n *\n * Rendered inside a {@link Heading} because screen-reader users navigate an\n * accordion by heading; that wrapper is what makes it usable rather than\n * merely operable.\n */\nexport interface AccordionTriggerProps extends VariantProps<typeof accordionTriggerVariants> {\n /** The header label. */\n children?: ReactNode;\n /**\n * The expand/collapse glyph, rendered after the label.\n *\n * Required, and supplied by the caller: this library ships no icon set, so\n * it stays icon-library agnostic. Mark the glyph `aria-hidden` -- the label\n * is the accessible name, and a second name source makes the trigger\n * announce twice. It is sized at `--icon-sm` unless it carries a `size-*`\n * class of its own, and rotates on expand.\n */\n icon: ReactNode;\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n /**\n * Heading level for the wrapper. Accordions appear at different depths, and\n * a fixed level would break the document outline wherever it is wrong.\n *\n * @default 3\n */\n headingLevel?: number;\n}\n\nexport const AccordionTrigger = forwardRef<HTMLButtonElement, AccordionTriggerProps>(\n function AccordionTrigger({ children, icon, className, headingLevel = 3 }, ref) {\n return (\n <Heading level={headingLevel}>\n <AriaButton\n // The ref goes on the button, not the Heading wrapping it: Heading has\n // no interactive behaviour, while the button is what expands/collapses\n // and carries the press/focus data attributes.\n ref={ref}\n slot=\"trigger\"\n data-slot=\"accordion-trigger\"\n className={cn(accordionTriggerVariants(), className)}\n >\n {children}\n {icon}\n </AriaButton>\n </Heading>\n );\n },\n);\n\n/**\n * The content revealed when its item expands.\n *\n * Named Panel rather than the legacy Content, matching React Aria and the\n * ARIA pattern.\n */\nexport interface AccordionPanelProps\n extends\n Omit<AriaDisclosurePanelProps, \"className\" | \"style\">,\n VariantProps<typeof accordionPanelVariants> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\nexport const AccordionPanel = forwardRef<HTMLDivElement, AccordionPanelProps>(\n function AccordionPanel({ className, children, ...props }, ref) {\n return (\n <AriaDisclosurePanel\n ref={ref}\n {...props}\n data-slot=\"accordion-panel\"\n className={cn(accordionPanelVariants(), className)}\n >\n {/* A wrapper, so the answer can settle down into place while the panel opens. */}\n <div data-slot=\"accordion-panel-content\" className=\"accordion-panel-content\">\n {children}\n </div>\n </AriaDisclosurePanel>\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,oBAAoB,IAAI,QAAQ;AAE7C,MAAa,wBAAwB,IAAI,CAIvC,oEAIA,kEACF,CAAC;AAED,MAAa,2BAA2B,IAAI;CAC1C;CAGA;CACA;CACA;CAKA;CAQA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CAIA;CACA;CACA;CAGA;CAEA;AACF,CAAC;AAED,MAAa,yBAAyB,IAAI,CAOxC,8FAGA,iBACF,CAAC;AA8BD,MAAa,YAAY,WAA2C,SAAS,UAC3E,EAAE,WAAW,GAAG,SAChB,KACA;CACA,OACE,oBAACA,iBAAD;EACO;EACL,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,kBAAkB,GAAG,SAAS;CAC7C,CAAA;AAEL,CAAC;AAeD,MAAa,gBAAgB,WAA+C,SAAS,cACnF,EAAE,WAAW,GAAG,SAChB,KACA;CACA,OACE,oBAACC,YAAD;EACO;EACL,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,sBAAsB,GAAG,SAAS;CACjD,CAAA;AAEL,CAAC;AAiCD,MAAa,mBAAmB,WAC9B,SAAS,iBAAiB,EAAE,UAAU,MAAM,WAAW,eAAe,KAAK,KAAK;CAC9E,OACE,oBAAC,SAAD;EAAS,OAAO;EACd,UAAA,qBAACC,QAAD;GAIO;GACL,MAAK;GACL,aAAU;GACV,WAAW,GAAG,yBAAyB,GAAG,SAAS;GAPrD,UAAA,CASG,UACA,IACS;;CACL,CAAA;AAEb,CACF;AAgBA,MAAa,iBAAiB,WAC5B,SAAS,eAAe,EAAE,WAAW,UAAU,GAAG,SAAS,KAAK;CAC9D,OACE,oBAACC,iBAAD;EACO;EACL,GAAI;EACJ,aAAU;EACV,WAAW,GAAG,uBAAuB,GAAG,SAAS;EAGjD,UAAA,oBAAC,OAAD;GAAK,aAAU;GAA0B,WAAU;GAChD;EACE,CAAA;CACc,CAAA;AAEzB,CACF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { buttonVariants } from "../button/button.js";
|
|
2
|
+
import { VariantProps } from "class-variance-authority";
|
|
3
|
+
import { ButtonProps } from "react-aria-components";
|
|
4
|
+
//#region src/action-button/action-button.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Props.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately NOT Button's props: an action button owns its own content (the
|
|
9
|
+
* morphing label and the arrow, spinner or tick beside it), so `children` is the
|
|
10
|
+
* resting label as a plain string rather than arbitrary content, and `onAction`
|
|
11
|
+
* replaces `onPress` because it is awaited. It does take Button's `variant` and
|
|
12
|
+
* `size`, so it looks like the Button next to it.
|
|
13
|
+
*/
|
|
14
|
+
export interface ActionButtonProps extends Omit<ButtonProps, "className" | "style" | "onPress" | "children" | "isPending">, VariantProps<typeof buttonVariants> {
|
|
15
|
+
/** The label at rest. A plain string: it is split into letters to morph. */
|
|
16
|
+
children: string;
|
|
17
|
+
/** The label once the action succeeds. */
|
|
18
|
+
successLabel?: string;
|
|
19
|
+
/** The label while the action runs. */
|
|
20
|
+
pendingLabel?: string;
|
|
21
|
+
/**
|
|
22
|
+
* What the button does. If it returns a promise the button stays pending
|
|
23
|
+
* until it settles; a rejection returns the button to rest and goes to
|
|
24
|
+
* `onActionError`. A press while pending is ignored.
|
|
25
|
+
*/
|
|
26
|
+
onAction: () => void | Promise<void>;
|
|
27
|
+
/** How long the success state shows before the button returns to rest, in ms. `0` keeps it. */
|
|
28
|
+
resetAfterMs?: number;
|
|
29
|
+
/** Called when `onAction` throws or rejects. Without it the error is dropped, because the button has already returned to rest. */
|
|
30
|
+
onActionError?: (error: unknown) => void;
|
|
31
|
+
/** Extra classes. Merged last, so they win conflicts with ours. */
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A button that runs an action and shows it through: its label morphs from the
|
|
36
|
+
* resting text to a pending one and then a success one, the arrow becomes a
|
|
37
|
+
* spinner and then a tick that draws itself, and the button's width follows the
|
|
38
|
+
* text on a spring.
|
|
39
|
+
*
|
|
40
|
+
* Use it for one async commit ("Save", "Send"). It stays focusable while
|
|
41
|
+
* pending (`aria-disabled`, not disabled), so a keyboard user keeps focus
|
|
42
|
+
* through the whole action, and a live region announces the pending and success
|
|
43
|
+
* labels. The accessible name is always the resting label.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* <ActionButton onAction={save} pendingLabel="Saving" successLabel="Saved">Save changes</ActionButton>
|
|
47
|
+
*/
|
|
48
|
+
export declare const ActionButton: import("react").ForwardRefExoticComponent<ActionButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
49
|
+
//#endregion
|
|
50
|
+
//# sourceMappingURL=action-button.d.ts.map
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { mergeRefs } from "../lib/merge-refs.js";
|
|
4
|
+
import { anchorsLayer, pressScaleFor, useAriaBusy, useExitBackstop, useLeavingItems } from "../lib/motion.js";
|
|
5
|
+
import { buttonVariants } from "../button/button.js";
|
|
6
|
+
import { MorphText } from "../lib/morph-text.js";
|
|
7
|
+
import "class-variance-authority";
|
|
8
|
+
import { forwardRef, useCallback, useEffect, useRef, useState } from "react";
|
|
9
|
+
import { Button } from "react-aria-components";
|
|
10
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
//#region src/action-button/action-button.tsx
|
|
12
|
+
const ICON = "size-(--icon-sm)";
|
|
13
|
+
/** The tick draws itself from its short stroke, the way a hand would write it. */
|
|
14
|
+
function DrawnCheck() {
|
|
15
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
16
|
+
className: ICON,
|
|
17
|
+
viewBox: "0 0 24 24",
|
|
18
|
+
fill: "none",
|
|
19
|
+
stroke: "currentColor",
|
|
20
|
+
strokeWidth: 2,
|
|
21
|
+
strokeLinecap: "round",
|
|
22
|
+
strokeLinejoin: "round",
|
|
23
|
+
"aria-hidden": "true",
|
|
24
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
25
|
+
d: "M4 12l5 5L20 6",
|
|
26
|
+
pathLength: 1,
|
|
27
|
+
className: "[stroke-dasharray:1] motion-safe:animate-check-draw"
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function Arrow() {
|
|
32
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
33
|
+
className: ICON,
|
|
34
|
+
viewBox: "0 0 24 24",
|
|
35
|
+
fill: "none",
|
|
36
|
+
stroke: "currentColor",
|
|
37
|
+
strokeWidth: 2,
|
|
38
|
+
strokeLinecap: "round",
|
|
39
|
+
strokeLinejoin: "round",
|
|
40
|
+
"aria-hidden": "true",
|
|
41
|
+
children: /* @__PURE__ */ jsx("path", { d: "M5 12h14M12 5l7 7-7 7" })
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function Spinner() {
|
|
45
|
+
return /* @__PURE__ */ jsx("span", { className: "size-4 rounded-circle border-(length:--border-width-spinner) border-current border-r-transparent motion-safe:animate-spin-fast" });
|
|
46
|
+
}
|
|
47
|
+
function PhaseIcon({ state }) {
|
|
48
|
+
if (state === "pending") return /* @__PURE__ */ jsx(Spinner, {});
|
|
49
|
+
if (state === "success") return /* @__PURE__ */ jsx(DrawnCheck, {});
|
|
50
|
+
return /* @__PURE__ */ jsx(Arrow, {});
|
|
51
|
+
}
|
|
52
|
+
/** Classes for one phase of the icon slot. The arrow moves; the spinner and tick scale. */
|
|
53
|
+
function phaseClasses(state, leaving, animated) {
|
|
54
|
+
const arrow = state === "idle";
|
|
55
|
+
if (leaving) return arrow ? "motion-safe:animate-arrow-out motion-reduce:animate-fade-out" : "motion-safe:animate-glyph-out motion-reduce:animate-fade-out";
|
|
56
|
+
if (!animated) return "";
|
|
57
|
+
return arrow ? "motion-safe:animate-arrow-in motion-reduce:animate-fade-in" : "motion-safe:animate-glyph-in motion-reduce:animate-fade-in";
|
|
58
|
+
}
|
|
59
|
+
function IconSlot({ state }) {
|
|
60
|
+
const phaseRef = useRef(null);
|
|
61
|
+
const { leaving, changed, remove } = useLeavingItems(state, state, () => phaseRef.current);
|
|
62
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
63
|
+
className: cn("grid shrink-0 place-items-center", ICON),
|
|
64
|
+
children: [leaving.map((item) => /* @__PURE__ */ jsx(LeavingIcon, {
|
|
65
|
+
id: item.id,
|
|
66
|
+
state: item.value,
|
|
67
|
+
onDone: remove
|
|
68
|
+
}, item.id)), /* @__PURE__ */ jsx("span", {
|
|
69
|
+
ref: phaseRef,
|
|
70
|
+
className: cn(`col-start-1 row-start-1 grid place-items-center ${ICON} ${phaseClasses(state, false, changed)}`),
|
|
71
|
+
children: /* @__PURE__ */ jsx(PhaseIcon, { state })
|
|
72
|
+
}, state)]
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function LeavingIcon({ id, state, onDone }) {
|
|
76
|
+
const remove = useCallback(() => onDone(id), [onDone, id]);
|
|
77
|
+
useExitBackstop(true, remove);
|
|
78
|
+
return /* @__PURE__ */ jsx("span", {
|
|
79
|
+
"aria-hidden": "true",
|
|
80
|
+
onAnimationEnd: (event) => {
|
|
81
|
+
if (event.target === event.currentTarget) remove();
|
|
82
|
+
},
|
|
83
|
+
className: cn(`col-start-1 row-start-1 grid place-items-center ${ICON} ${phaseClasses(state, true, true)}`),
|
|
84
|
+
children: /* @__PURE__ */ jsx(PhaseIcon, { state })
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A button that runs an action and shows it through: its label morphs from the
|
|
89
|
+
* resting text to a pending one and then a success one, the arrow becomes a
|
|
90
|
+
* spinner and then a tick that draws itself, and the button's width follows the
|
|
91
|
+
* text on a spring.
|
|
92
|
+
*
|
|
93
|
+
* Use it for one async commit ("Save", "Send"). It stays focusable while
|
|
94
|
+
* pending (`aria-disabled`, not disabled), so a keyboard user keeps focus
|
|
95
|
+
* through the whole action, and a live region announces the pending and success
|
|
96
|
+
* labels. The accessible name is always the resting label.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* <ActionButton onAction={save} pendingLabel="Saving" successLabel="Saved">Save changes</ActionButton>
|
|
100
|
+
*/
|
|
101
|
+
const ActionButton = forwardRef(function ActionButton({ children: label, successLabel = "Saved", pendingLabel = "Saving", onAction, resetAfterMs = 2400, onActionError, className, variant, size, onPressStart, ...props }, ref) {
|
|
102
|
+
const [state, setState] = useState("idle");
|
|
103
|
+
const resetTimer = useRef(null);
|
|
104
|
+
const busy = useAriaBusy(state === "pending");
|
|
105
|
+
useEffect(() => () => {
|
|
106
|
+
if (resetTimer.current) clearTimeout(resetTimer.current);
|
|
107
|
+
}, []);
|
|
108
|
+
async function run() {
|
|
109
|
+
if (state === "pending") return;
|
|
110
|
+
if (resetTimer.current) clearTimeout(resetTimer.current);
|
|
111
|
+
setState("pending");
|
|
112
|
+
try {
|
|
113
|
+
await onAction();
|
|
114
|
+
setState("success");
|
|
115
|
+
if (resetAfterMs > 0) resetTimer.current = setTimeout(() => setState("idle"), resetAfterMs);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
setState("idle");
|
|
118
|
+
onActionError?.(error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const pressStart = (event) => {
|
|
122
|
+
const target = event.target;
|
|
123
|
+
if (state === "pending" || anchorsLayer(props)) target.style.removeProperty("--press-scale");
|
|
124
|
+
else target.style.setProperty("--press-scale", pressScaleFor(target.offsetWidth));
|
|
125
|
+
onPressStart?.(event);
|
|
126
|
+
};
|
|
127
|
+
const text = state === "pending" ? pendingLabel : state === "success" ? successLabel : label;
|
|
128
|
+
const status = state === "pending" ? pendingLabel : state === "success" ? successLabel : "";
|
|
129
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Button, {
|
|
130
|
+
...props,
|
|
131
|
+
ref: mergeRefs(ref, busy),
|
|
132
|
+
"aria-disabled": state === "pending" ? true : props["aria-disabled"],
|
|
133
|
+
"data-pending": state === "pending" || void 0,
|
|
134
|
+
onPress: () => void run(),
|
|
135
|
+
onPressStart: pressStart,
|
|
136
|
+
"data-slot": "button",
|
|
137
|
+
"data-status": state,
|
|
138
|
+
className: cn(`${buttonVariants({
|
|
139
|
+
variant,
|
|
140
|
+
size
|
|
141
|
+
})} relative overflow-hidden`, className),
|
|
142
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
143
|
+
className: "inline-flex min-h-5 items-center justify-center gap-2 whitespace-nowrap",
|
|
144
|
+
"aria-hidden": "true",
|
|
145
|
+
children: [/* @__PURE__ */ jsx(MorphText, { text }), /* @__PURE__ */ jsx(IconSlot, { state })]
|
|
146
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
147
|
+
className: "sr-only",
|
|
148
|
+
children: label
|
|
149
|
+
})]
|
|
150
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
151
|
+
className: "sr-only",
|
|
152
|
+
role: "status",
|
|
153
|
+
children: status
|
|
154
|
+
})] });
|
|
155
|
+
});
|
|
156
|
+
//#endregion
|
|
157
|
+
export { ActionButton };
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=action-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-button.js","names":["AriaButton"],"sources":["../../src/action-button/action-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, useCallback, useEffect, useRef, useState, type RefObject } from \"react\";\nimport {\n Button as AriaButton,\n type ButtonProps as AriaButtonProps,\n type PressEvent,\n} from \"react-aria-components\";\n\nimport { buttonVariants } from \"../button/button.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { mergeRefs } from \"../lib/merge-refs.js\";\nimport { MorphText } from \"../lib/morph-text.js\";\nimport {\n anchorsLayer,\n pressScaleFor,\n useAriaBusy,\n useExitBackstop,\n useLeavingItems,\n} from \"../lib/motion.js\";\n\ntype ActionState = \"idle\" | \"pending\" | \"success\";\n\n/**\n * Props.\n *\n * Deliberately NOT Button's props: an action button owns its own content (the\n * morphing label and the arrow, spinner or tick beside it), so `children` is the\n * resting label as a plain string rather than arbitrary content, and `onAction`\n * replaces `onPress` because it is awaited. It does take Button's `variant` and\n * `size`, so it looks like the Button next to it.\n */\nexport interface ActionButtonProps\n extends\n Omit<AriaButtonProps, \"className\" | \"style\" | \"onPress\" | \"children\" | \"isPending\">,\n VariantProps<typeof buttonVariants> {\n /** The label at rest. A plain string: it is split into letters to morph. */\n children: string;\n /** The label once the action succeeds. */\n successLabel?: string;\n /** The label while the action runs. */\n pendingLabel?: string;\n /**\n * What the button does. If it returns a promise the button stays pending\n * until it settles; a rejection returns the button to rest and goes to\n * `onActionError`. A press while pending is ignored.\n */\n onAction: () => void | Promise<void>;\n /** How long the success state shows before the button returns to rest, in ms. `0` keeps it. */\n resetAfterMs?: number;\n /** Called when `onAction` throws or rejects. Without it the error is dropped, because the button has already returned to rest. */\n onActionError?: (error: unknown) => void;\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\nconst ICON = \"size-(--icon-sm)\";\n\n/** The tick draws itself from its short stroke, the way a hand would write it. */\nfunction DrawnCheck() {\n return (\n <svg\n className={ICON}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4 12l5 5L20 6\"\n pathLength={1}\n className=\"[stroke-dasharray:1] motion-safe:animate-check-draw\"\n />\n </svg>\n );\n}\n\nfunction Arrow() {\n return (\n <svg\n className={ICON}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14M12 5l7 7-7 7\" />\n </svg>\n );\n}\n\nfunction Spinner() {\n return (\n <span className=\"size-4 rounded-circle border-(length:--border-width-spinner) border-current border-r-transparent motion-safe:animate-spin-fast\" />\n );\n}\n\nfunction PhaseIcon({ state }: { state: ActionState }) {\n if (state === \"pending\") return <Spinner />;\n if (state === \"success\") return <DrawnCheck />;\n return <Arrow />;\n}\n\n/** Classes for one phase of the icon slot. The arrow moves; the spinner and tick scale. */\nfunction phaseClasses(state: ActionState, leaving: boolean, animated: boolean) {\n const arrow = state === \"idle\";\n if (leaving) {\n return arrow\n ? \"motion-safe:animate-arrow-out motion-reduce:animate-fade-out\"\n : \"motion-safe:animate-glyph-out motion-reduce:animate-fade-out\";\n }\n if (!animated) return \"\";\n return arrow\n ? \"motion-safe:animate-arrow-in motion-reduce:animate-fade-in\"\n : \"motion-safe:animate-glyph-in motion-reduce:animate-fade-in\";\n}\n\nfunction IconSlot({ state }: { state: ActionState }) {\n const phaseRef = useRef<HTMLSpanElement>(null);\n // The phases share one grid cell, so a leaving one needs no rect: it simply stays under the new one.\n const { leaving, changed, remove } = useLeavingItems<ActionState>(\n state,\n state,\n () => phaseRef.current,\n );\n return (\n <span className={cn(\"grid shrink-0 place-items-center\", ICON)}>\n {leaving.map((item) => (\n <LeavingIcon key={item.id} id={item.id} state={item.value} onDone={remove} />\n ))}\n <span\n key={state}\n ref={phaseRef}\n className={cn(\n `col-start-1 row-start-1 grid place-items-center ${ICON} ${phaseClasses(state, false, changed)}`,\n )}\n >\n <PhaseIcon state={state} />\n </span>\n </span>\n );\n}\n\nfunction LeavingIcon({\n id,\n state,\n onDone,\n}: {\n id: number;\n state: ActionState;\n onDone: (id: number) => void;\n}) {\n const remove = useCallback(() => onDone(id), [onDone, id]);\n useExitBackstop(true, remove);\n return (\n <span\n aria-hidden=\"true\"\n onAnimationEnd={(event) => {\n if (event.target === event.currentTarget) remove();\n }}\n className={cn(\n `col-start-1 row-start-1 grid place-items-center ${ICON} ${phaseClasses(state, true, true)}`,\n )}\n >\n <PhaseIcon state={state} />\n </span>\n );\n}\n\n/**\n * A button that runs an action and shows it through: its label morphs from the\n * resting text to a pending one and then a success one, the arrow becomes a\n * spinner and then a tick that draws itself, and the button's width follows the\n * text on a spring.\n *\n * Use it for one async commit (\"Save\", \"Send\"). It stays focusable while\n * pending (`aria-disabled`, not disabled), so a keyboard user keeps focus\n * through the whole action, and a live region announces the pending and success\n * labels. The accessible name is always the resting label.\n *\n * @example\n * <ActionButton onAction={save} pendingLabel=\"Saving\" successLabel=\"Saved\">Save changes</ActionButton>\n */\nexport const ActionButton = forwardRef<HTMLButtonElement, ActionButtonProps>(function ActionButton(\n {\n children: label,\n successLabel = \"Saved\",\n pendingLabel = \"Saving\",\n onAction,\n resetAfterMs = 2400,\n onActionError,\n className,\n variant,\n size,\n onPressStart,\n ...props\n },\n ref,\n) {\n const [state, setState] = useState<ActionState>(\"idle\");\n const resetTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const busy = useAriaBusy(state === \"pending\");\n\n useEffect(\n () => () => {\n if (resetTimer.current) clearTimeout(resetTimer.current);\n },\n [],\n );\n\n async function run() {\n if (state === \"pending\") return;\n if (resetTimer.current) clearTimeout(resetTimer.current);\n setState(\"pending\");\n try {\n await onAction();\n setState(\"success\");\n if (resetAfterMs > 0) resetTimer.current = setTimeout(() => setState(\"idle\"), resetAfterMs);\n } catch (error) {\n setState(\"idle\");\n onActionError?.(error);\n }\n }\n\n const pressStart = (event: PressEvent) => {\n const target = event.target as HTMLElement;\n // A pending button does not scale: drop the depth a previous press left behind.\n if (state === \"pending\" || anchorsLayer(props)) target.style.removeProperty(\"--press-scale\");\n else target.style.setProperty(\"--press-scale\", pressScaleFor(target.offsetWidth));\n onPressStart?.(event);\n };\n\n const text = state === \"pending\" ? pendingLabel : state === \"success\" ? successLabel : label;\n const status = state === \"pending\" ? pendingLabel : state === \"success\" ? successLabel : \"\";\n\n return (\n <>\n <AriaButton\n {...props}\n ref={mergeRefs(ref, busy as RefObject<HTMLButtonElement | null>)}\n // Not React Aria's isPending: it announces through a transient role=\"img\" node\n // whose label id does not resolve, which axe rejects, and this button has its\n // own live region. aria-disabled and aria-busy keep it focusable and announced.\n aria-disabled={state === \"pending\" ? true : props[\"aria-disabled\"]}\n data-pending={state === \"pending\" || undefined}\n onPress={() => void run()}\n onPressStart={pressStart}\n data-slot=\"button\"\n data-status={state}\n className={cn(`${buttonVariants({ variant, size })} relative overflow-hidden`, className)}\n >\n <span\n className=\"inline-flex min-h-5 items-center justify-center gap-2 whitespace-nowrap\"\n aria-hidden=\"true\"\n >\n <MorphText text={text} />\n <IconSlot state={state} />\n </span>\n <span className=\"sr-only\">{label}</span>\n </AriaButton>\n {/* Beside the button, not inside it: inside, its text would join the button's accessible name. */}\n <span className=\"sr-only\" role=\"status\">\n {status}\n </span>\n </>\n );\n});\n"],"mappings":";;;;;;;;;;;AAyDA,MAAM,OAAO;;AAGb,SAAS,aAAa;CACpB,OACE,oBAAC,OAAD;EACE,WAAW;EACX,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;EAEZ,UAAA,oBAAC,QAAD;GACE,GAAE;GACF,YAAY;GACZ,WAAU;EACX,CAAA;CACE,CAAA;AAET;AAEA,SAAS,QAAQ;CACf,OACE,oBAAC,OAAD;EACE,WAAW;EACX,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;EAEZ,UAAA,oBAAC,QAAD,EAAM,GAAE,wBAAyB,CAAA;CAC9B,CAAA;AAET;AAEA,SAAS,UAAU;CACjB,OACE,oBAAC,QAAD,EAAM,WAAU,iIAAkI,CAAA;AAEtJ;AAEA,SAAS,UAAU,EAAE,SAAiC;CACpD,IAAI,UAAU,WAAW,OAAO,oBAAC,SAAD,CAAU,CAAA;CAC1C,IAAI,UAAU,WAAW,OAAO,oBAAC,YAAD,CAAa,CAAA;CAC7C,OAAO,oBAAC,OAAD,CAAQ,CAAA;AACjB;;AAGA,SAAS,aAAa,OAAoB,SAAkB,UAAmB;CAC7E,MAAM,QAAQ,UAAU;CACxB,IAAI,SACF,OAAO,QACH,iEACA;CAEN,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,QACH,+DACA;AACN;AAEA,SAAS,SAAS,EAAE,SAAiC;CACnD,MAAM,WAAW,OAAwB,IAAI;CAE7C,MAAM,EAAE,SAAS,SAAS,WAAW,gBACnC,OACA,aACM,SAAS,OACjB;CACA,OACE,qBAAC,QAAD;EAAM,WAAW,GAAG,oCAAoC,IAAI;EAA5D,UAAA,CACG,QAAQ,KAAK,SACZ,oBAAC,aAAD;GAA2B,IAAI,KAAK;GAAI,OAAO,KAAK;GAAO,QAAQ;EAAS,GAA1D,KAAK,EAAqD,CAC7E,GACD,oBAAC,QAAD;GAEE,KAAK;GACL,WAAW,GACT,mDAAmD,KAAK,GAAG,aAAa,OAAO,OAAO,OAAO,GAC/F;GAEA,UAAA,oBAAC,WAAD,EAAkB,MAAQ,CAAA;EACtB,GAPC,KAOD,CACF;;AAEV;AAEA,SAAS,YAAY,EACnB,IACA,OACA,UAKC;CACD,MAAM,SAAS,kBAAkB,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;CACzD,gBAAgB,MAAM,MAAM;CAC5B,OACE,oBAAC,QAAD;EACE,eAAY;EACZ,iBAAiB,UAAU;GACzB,IAAI,MAAM,WAAW,MAAM,eAAe,OAAO;EACnD;EACA,WAAW,GACT,mDAAmD,KAAK,GAAG,aAAa,OAAO,MAAM,IAAI,GAC3F;EAEA,UAAA,oBAAC,WAAD,EAAkB,MAAQ,CAAA;CACtB,CAAA;AAEV;;;;;;;;;;;;;;;AAgBA,MAAa,eAAe,WAAiD,SAAS,aACpF,EACE,UAAU,OACV,eAAe,SACf,eAAe,UACf,UACA,eAAe,MACf,eACA,WACA,SACA,MACA,cACA,GAAG,SAEL,KACA;CACA,MAAM,CAAC,OAAO,YAAY,SAAsB,MAAM;CACtD,MAAM,aAAa,OAA6C,IAAI;CACpE,MAAM,OAAO,YAAY,UAAU,SAAS;CAE5C,sBACc;EACV,IAAI,WAAW,SAAS,aAAa,WAAW,OAAO;CACzD,GACA,CAAC,CACH;CAEA,eAAe,MAAM;EACnB,IAAI,UAAU,WAAW;EACzB,IAAI,WAAW,SAAS,aAAa,WAAW,OAAO;EACvD,SAAS,SAAS;EAClB,IAAI;GACF,MAAM,SAAS;GACf,SAAS,SAAS;GAClB,IAAI,eAAe,GAAG,WAAW,UAAU,iBAAiB,SAAS,MAAM,GAAG,YAAY;EAC5F,SAAS,OAAO;GACd,SAAS,MAAM;GACf,gBAAgB,KAAK;EACvB;CACF;CAEA,MAAM,cAAc,UAAsB;EACxC,MAAM,SAAS,MAAM;EAErB,IAAI,UAAU,aAAa,aAAa,KAAK,GAAG,OAAO,MAAM,eAAe,eAAe;OACtF,OAAO,MAAM,YAAY,iBAAiB,cAAc,OAAO,WAAW,CAAC;EAChF,eAAe,KAAK;CACtB;CAEA,MAAM,OAAO,UAAU,YAAY,eAAe,UAAU,YAAY,eAAe;CACvF,MAAM,SAAS,UAAU,YAAY,eAAe,UAAU,YAAY,eAAe;CAEzF,OACE,qBAAA,YAAA,EAAA,UAAA,CACE,qBAACA,QAAD;EACE,GAAI;EACJ,KAAK,UAAU,KAAK,IAA2C;EAI/D,iBAAe,UAAU,YAAY,OAAO,MAAM;EAClD,gBAAc,UAAU,aAAa,KAAA;EACrC,eAAe,KAAK,IAAI;EACxB,cAAc;EACd,aAAU;EACV,eAAa;EACb,WAAW,GAAG,GAAG,eAAe;GAAE;GAAS;EAAK,CAAC,EAAE,4BAA4B,SAAS;EAZ1F,UAAA,CAcE,qBAAC,QAAD;GACE,WAAU;GACV,eAAY;GAFd,UAAA,CAIE,oBAAC,WAAD,EAAiB,KAAO,CAAA,GACxB,oBAAC,UAAD,EAAiB,MAAQ,CAAA,CACrB;EACN,CAAA,GAAA,oBAAC,QAAD;GAAM,WAAU;GAAW,UAAA;EAAY,CAAA,CAC7B;CAEZ,CAAA,GAAA,oBAAC,QAAD;EAAM,WAAU;EAAU,MAAK;EAC5B,UAAA;CACG,CAAA,CACN,EAAA,CAAA;AAEN,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/activity-heatmap/activity-heatmap.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* ActivityHeatmap: one square per day, weeks as columns, four tints of the
|
|
5
|
+
* primary chart colour for how busy a day was. Use it when rhythm, streaks and
|
|
6
|
+
* quiet weeks matter more than exact comparisons; use a bar chart when the
|
|
7
|
+
* exact comparison is the point.
|
|
8
|
+
*
|
|
9
|
+
* The squares wave in once, diagonally, when the grid is seen. A tooltip
|
|
10
|
+
* glides between squares on hover or keyboard focus and its words rise in. A
|
|
11
|
+
* new range recolours the grid in a sweep instead of redrawing it, and the
|
|
12
|
+
* total rolls to its new number. The legend's squares preview a level on the
|
|
13
|
+
* grid (the others step back) and pin it on press.
|
|
14
|
+
*
|
|
15
|
+
* It sits in a card (`framed`, on by default). A year switch (`periods`) sits
|
|
16
|
+
* beside the total, and a detail line under the legend says what the hovered,
|
|
17
|
+
* focused or selected day holds (`describeDay`).
|
|
18
|
+
*
|
|
19
|
+
* The grid is a `grid` of `gridcell`s with one tab stop: arrow keys move by
|
|
20
|
+
* day (up and down) and by week (left and right), Home and End jump to the
|
|
21
|
+
* ends, Enter selects. A visually hidden table carries every day.
|
|
22
|
+
*/
|
|
23
|
+
export interface ActivityDay {
|
|
24
|
+
/** Calendar day as YYYY-MM-DD. */
|
|
25
|
+
date: string;
|
|
26
|
+
count: number;
|
|
27
|
+
}
|
|
28
|
+
/** What `describeDay` is given for one day. */
|
|
29
|
+
export interface ActivityDayDetail {
|
|
30
|
+
/** The day as YYYY-MM-DD. */
|
|
31
|
+
date: string;
|
|
32
|
+
count: number;
|
|
33
|
+
/** The day spelled out, such as "Tuesday, March 18". The year is added when the range spans more than one. */
|
|
34
|
+
label: string;
|
|
35
|
+
/** The nouns for the count, as passed in `unit`. */
|
|
36
|
+
unit: {
|
|
37
|
+
one: string;
|
|
38
|
+
other: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface ActivityHeatmapProps {
|
|
42
|
+
/** One entry per day, oldest first. Days missing inside the range count as zero. */
|
|
43
|
+
days: ActivityDay[];
|
|
44
|
+
/** Accessible name for the grid, such as "Contributions in 2025". */
|
|
45
|
+
label: string;
|
|
46
|
+
/** Finishes the summary line: "1,284 contributions in {period}". */
|
|
47
|
+
period: string;
|
|
48
|
+
/** Nouns for the count. @default { one: "contribution", other: "contributions" } */
|
|
49
|
+
unit?: {
|
|
50
|
+
one: string;
|
|
51
|
+
other: string;
|
|
52
|
+
};
|
|
53
|
+
/** Upper bounds for levels one to three; anything above the last is level four. Defaults to quarters of the busiest day. */
|
|
54
|
+
thresholds?: [number, number, number];
|
|
55
|
+
/** @default 0 (Sunday) */
|
|
56
|
+
weekStartsOn?: 0 | 1;
|
|
57
|
+
/** Controlled selected day, as YYYY-MM-DD. */
|
|
58
|
+
selectedDate?: string | null;
|
|
59
|
+
defaultSelectedDate?: string | null;
|
|
60
|
+
/** Called with the day's YYYY-MM-DD when a day is pressed or chosen with Enter. */
|
|
61
|
+
onSelectDate?: (date: string) => void;
|
|
62
|
+
/** Controls beside the summary. */
|
|
63
|
+
actions?: ReactNode;
|
|
64
|
+
/**
|
|
65
|
+
* The ranges to switch between, such as ["2025", "2024", "2023"], shown as a segmented switch beside the summary with the one
|
|
66
|
+
* equal to `period` selected. You own the data: when `onPeriodChange` fires, pass the new `days`, `period` and `label`.
|
|
67
|
+
*/
|
|
68
|
+
periods?: string[];
|
|
69
|
+
/** Called with the chosen entry of `periods`. */
|
|
70
|
+
onPeriodChange?: (period: string) => void;
|
|
71
|
+
/** Accessible name for the switch. @default "Period" */
|
|
72
|
+
periodsLabel?: string;
|
|
73
|
+
/**
|
|
74
|
+
* The sentence under the legend about the hovered, focused or selected day. Return the whole sentence, so it can carry data
|
|
75
|
+
* the heatmap does not hold. Pass `null` to remove the line. The default is date and count only:
|
|
76
|
+
* "Tuesday, March 18: 4 contributions."
|
|
77
|
+
*/
|
|
78
|
+
describeDay?: ((day: ActivityDayDetail) => string) | null;
|
|
79
|
+
/** The detail line when no day is hovered, focused or selected. @default "Hover or select a day for details." */
|
|
80
|
+
detailHint?: string;
|
|
81
|
+
/** Draws the card around it: border, panel radius, surface and padding. Turn it off to place the heatmap inside a card of your own. @default true */
|
|
82
|
+
framed?: boolean;
|
|
83
|
+
/** Shown instead of the grid when there are no days. @default "No activity yet" */
|
|
84
|
+
emptyLabel?: string;
|
|
85
|
+
/** Formatting locale. Fixed by default so server and client render the same labels. @default "en-US" */
|
|
86
|
+
locale?: string;
|
|
87
|
+
/** Extra classes for the root. Merged last. */
|
|
88
|
+
className?: string;
|
|
89
|
+
}
|
|
90
|
+
export declare const ActivityHeatmap: import("react").ForwardRefExoticComponent<ActivityHeatmapProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
91
|
+
//#endregion
|
|
92
|
+
//# sourceMappingURL=activity-heatmap.d.ts.map
|