@gnome-ui/react 1.45.1 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AboutDialog/AboutDialog.cjs +1 -1
- package/dist/components/AboutDialog/AboutDialog.cjs.map +1 -1
- package/dist/components/AboutDialog/AboutDialog.d.ts +1 -1
- package/dist/components/AboutDialog/AboutDialog.js +106 -108
- package/dist/components/AboutDialog/AboutDialog.js.map +1 -1
- package/dist/components/AboutDialog/AboutDialog.module.css.cjs +1 -1
- package/dist/components/AboutDialog/AboutDialog.module.css.js +28 -29
- package/dist/components/AboutDialog.cjs +1 -1
- package/dist/components/ActionRow/ActionRow.cjs +1 -1
- package/dist/components/ActionRow/ActionRow.cjs.map +1 -1
- package/dist/components/ActionRow/ActionRow.d.ts +1 -1
- package/dist/components/ActionRow/ActionRow.js +2 -2
- package/dist/components/ActionRow/ActionRow.js.map +1 -1
- package/dist/components/ActionRow.cjs +1 -1
- package/dist/components/Avatar/Avatar.cjs +1 -1
- package/dist/components/Avatar/Avatar.cjs.map +1 -1
- package/dist/components/Avatar/Avatar.d.ts +1 -1
- package/dist/components/Avatar/Avatar.js +2 -2
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar.cjs +1 -1
- package/dist/components/AvatarRotator/AvatarRotator.cjs +1 -1
- package/dist/components/AvatarRotator/AvatarRotator.cjs.map +1 -1
- package/dist/components/AvatarRotator/AvatarRotator.d.ts +1 -1
- package/dist/components/AvatarRotator/AvatarRotator.js +2 -2
- package/dist/components/AvatarRotator/AvatarRotator.js.map +1 -1
- package/dist/components/AvatarRotator.cjs +1 -1
- package/dist/components/Badge/Badge.cjs +1 -1
- package/dist/components/Badge/Badge.cjs.map +1 -1
- package/dist/components/Badge/Badge.d.ts +1 -1
- package/dist/components/Badge/Badge.js +2 -2
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Badge.cjs +1 -1
- package/dist/components/Banner/Banner.cjs +1 -1
- package/dist/components/Banner/Banner.cjs.map +1 -1
- package/dist/components/Banner/Banner.d.ts +1 -1
- package/dist/components/Banner/Banner.js +34 -36
- package/dist/components/Banner/Banner.js.map +1 -1
- package/dist/components/Banner/Banner.module.css.cjs +1 -1
- package/dist/components/Banner/Banner.module.css.js +11 -12
- package/dist/components/Banner.cjs +1 -1
- package/dist/components/Bin/Bin.cjs +1 -1
- package/dist/components/Bin/Bin.cjs.map +1 -1
- package/dist/components/Bin/Bin.d.ts +1 -1
- package/dist/components/Bin/Bin.js +4 -6
- package/dist/components/Bin/Bin.js.map +1 -1
- package/dist/components/Bin.cjs +1 -1
- package/dist/components/Blockquote/Blockquote.cjs +1 -1
- package/dist/components/Blockquote/Blockquote.cjs.map +1 -1
- package/dist/components/Blockquote/Blockquote.d.ts +1 -1
- package/dist/components/Blockquote/Blockquote.js +24 -26
- package/dist/components/Blockquote/Blockquote.js.map +1 -1
- package/dist/components/Blockquote.cjs +1 -1
- package/dist/components/BottomSheet/BottomSheet.cjs +1 -1
- package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.d.ts +1 -1
- package/dist/components/BottomSheet/BottomSheet.js +37 -38
- package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.module.css.cjs +1 -1
- package/dist/components/BottomSheet/BottomSheet.module.css.js +8 -9
- package/dist/components/BottomSheet.cjs +1 -1
- package/dist/components/Box/Box.cjs +1 -1
- package/dist/components/Box/Box.cjs.map +1 -1
- package/dist/components/Box/Box.d.ts +1 -1
- package/dist/components/Box/Box.js +2 -2
- package/dist/components/Box/Box.js.map +1 -1
- package/dist/components/Box.cjs +1 -1
- package/dist/components/BoxedList/BoxedList.cjs +1 -1
- package/dist/components/BoxedList/BoxedList.cjs.map +1 -1
- package/dist/components/BoxedList/BoxedList.d.ts +1 -1
- package/dist/components/BoxedList/BoxedList.js +2 -2
- package/dist/components/BoxedList/BoxedList.js.map +1 -1
- package/dist/components/BoxedList.cjs +1 -1
- package/dist/components/BreakpointBin/BreakpointBin.cjs +1 -1
- package/dist/components/BreakpointBin/BreakpointBin.cjs.map +1 -1
- package/dist/components/BreakpointBin/BreakpointBin.d.ts +1 -1
- package/dist/components/BreakpointBin/BreakpointBin.js +2 -2
- package/dist/components/BreakpointBin/BreakpointBin.js.map +1 -1
- package/dist/components/BreakpointBin.cjs +1 -1
- package/dist/components/Button/Button.cjs +1 -1
- package/dist/components/Button/Button.cjs.map +1 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button.cjs +1 -1
- package/dist/components/ButtonContent/ButtonContent.cjs +1 -1
- package/dist/components/ButtonContent/ButtonContent.cjs.map +1 -1
- package/dist/components/ButtonContent/ButtonContent.d.ts +1 -1
- package/dist/components/ButtonContent/ButtonContent.js +24 -26
- package/dist/components/ButtonContent/ButtonContent.js.map +1 -1
- package/dist/components/ButtonContent.cjs +1 -1
- package/dist/components/ButtonRow/ButtonRow.cjs +1 -1
- package/dist/components/ButtonRow/ButtonRow.cjs.map +1 -1
- package/dist/components/ButtonRow/ButtonRow.d.ts +1 -1
- package/dist/components/ButtonRow/ButtonRow.js +22 -24
- package/dist/components/ButtonRow/ButtonRow.js.map +1 -1
- package/dist/components/ButtonRow.cjs +1 -1
- package/dist/components/Card/Card.cjs +1 -1
- package/dist/components/Card/Card.cjs.map +1 -1
- package/dist/components/Card/Card.d.ts +1 -1
- package/dist/components/Card/Card.js +10 -12
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Card/Card.module.css.cjs +1 -1
- package/dist/components/Card/Card.module.css.js +4 -5
- package/dist/components/Card.cjs +1 -1
- package/dist/components/Carousel/Carousel.cjs +1 -1
- package/dist/components/Carousel/Carousel.cjs.map +1 -1
- package/dist/components/Carousel/Carousel.d.ts +3 -3
- package/dist/components/Carousel/Carousel.js +28 -34
- package/dist/components/Carousel/Carousel.js.map +1 -1
- package/dist/components/Carousel.cjs +1 -1
- package/dist/components/CheckRow/CheckRow.cjs +1 -1
- package/dist/components/CheckRow/CheckRow.cjs.map +1 -1
- package/dist/components/CheckRow/CheckRow.d.ts +1 -1
- package/dist/components/CheckRow/CheckRow.js +7 -7
- package/dist/components/CheckRow/CheckRow.js.map +1 -1
- package/dist/components/CheckRow.cjs +1 -1
- package/dist/components/Checkbox/Checkbox.cjs +1 -1
- package/dist/components/Checkbox/Checkbox.cjs.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.js +2 -2
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Checkbox.cjs +1 -1
- package/dist/components/Chip/Chip.cjs +1 -1
- package/dist/components/Chip/Chip.cjs.map +1 -1
- package/dist/components/Chip/Chip.d.ts +1 -1
- package/dist/components/Chip/Chip.js +2 -2
- package/dist/components/Chip/Chip.js.map +1 -1
- package/dist/components/Chip.cjs +1 -1
- package/dist/components/Clamp/Clamp.cjs +1 -1
- package/dist/components/Clamp/Clamp.cjs.map +1 -1
- package/dist/components/Clamp/Clamp.d.ts +1 -1
- package/dist/components/Clamp/Clamp.js +9 -11
- package/dist/components/Clamp/Clamp.js.map +1 -1
- package/dist/components/Clamp.cjs +1 -1
- package/dist/components/ColorPicker/ColorPicker.cjs +1 -1
- package/dist/components/ColorPicker/ColorPicker.cjs.map +1 -1
- package/dist/components/ColorPicker/ColorPicker.d.ts +2 -2
- package/dist/components/ColorPicker/ColorPicker.js +33 -37
- package/dist/components/ColorPicker/ColorPicker.js.map +1 -1
- package/dist/components/ColorPicker/ColorPicker.module.css.cjs +1 -1
- package/dist/components/ColorPicker/ColorPicker.module.css.js +9 -10
- package/dist/components/ColorPicker.cjs +1 -1
- package/dist/components/ColumnView/ColumnView.cjs +1 -1
- package/dist/components/ColumnView/ColumnView.cjs.map +1 -1
- package/dist/components/ColumnView/ColumnView.d.ts +1 -1
- package/dist/components/ColumnView/ColumnView.js +24 -28
- package/dist/components/ColumnView/ColumnView.js.map +1 -1
- package/dist/components/ColumnView.cjs +1 -1
- package/dist/components/ComboRow/ComboRow.cjs +1 -1
- package/dist/components/ComboRow/ComboRow.cjs.map +1 -1
- package/dist/components/ComboRow/ComboRow.d.ts +1 -1
- package/dist/components/ComboRow/ComboRow.js +2 -2
- package/dist/components/ComboRow/ComboRow.js.map +1 -1
- package/dist/components/ComboRow/ComboRow.module.css.cjs +1 -1
- package/dist/components/ComboRow/ComboRow.module.css.js +24 -25
- package/dist/components/ComboRow.cjs +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.cjs +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.cjs.map +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.d.ts +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.js +2 -2
- package/dist/components/ContributionGraph/ContributionGraph.js.map +1 -1
- package/dist/components/ContributionGraph.cjs +1 -1
- package/dist/components/CountDownTimer/CountDownTimer.cjs +1 -1
- package/dist/components/CountDownTimer/CountDownTimer.cjs.map +1 -1
- package/dist/components/CountDownTimer/CountDownTimer.d.ts +1 -1
- package/dist/components/CountDownTimer/CountDownTimer.js +2 -2
- package/dist/components/CountDownTimer/CountDownTimer.js.map +1 -1
- package/dist/components/CountDownTimer.cjs +1 -1
- package/dist/components/Dialog/Dialog.cjs +1 -1
- package/dist/components/Dialog/Dialog.cjs.map +1 -1
- package/dist/components/Dialog/Dialog.d.ts +1 -1
- package/dist/components/Dialog/Dialog.js +51 -52
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/Dialog/Dialog.module.css.cjs +1 -1
- package/dist/components/Dialog/Dialog.module.css.js +8 -9
- package/dist/components/Dialog/dialogUtils.cjs +1 -1
- package/dist/components/Dialog/dialogUtils.cjs.map +1 -1
- package/dist/components/Dialog/dialogUtils.d.ts +6 -0
- package/dist/components/Dialog/dialogUtils.js +11 -2
- package/dist/components/Dialog/dialogUtils.js.map +1 -1
- package/dist/components/Dialog.cjs +1 -1
- package/dist/components/Drawer/Drawer.cjs +1 -1
- package/dist/components/Drawer/Drawer.cjs.map +1 -1
- package/dist/components/Drawer/Drawer.d.ts +1 -1
- package/dist/components/Drawer/Drawer.js +2 -2
- package/dist/components/Drawer/Drawer.js.map +1 -1
- package/dist/components/Drawer/Drawer.module.css.cjs +1 -1
- package/dist/components/Drawer/Drawer.module.css.js +11 -12
- package/dist/components/Drawer.cjs +1 -1
- package/dist/components/Dropdown/Dropdown.cjs +1 -1
- package/dist/components/Dropdown/Dropdown.cjs.map +1 -1
- package/dist/components/Dropdown/Dropdown.d.ts +1 -1
- package/dist/components/Dropdown/Dropdown.js +89 -85
- package/dist/components/Dropdown/Dropdown.js.map +1 -1
- package/dist/components/Dropdown/Dropdown.module.css.cjs +1 -1
- package/dist/components/Dropdown/Dropdown.module.css.js +20 -21
- package/dist/components/Dropdown.cjs +1 -1
- package/dist/components/EntryRow/EntryRow.cjs +1 -1
- package/dist/components/EntryRow/EntryRow.cjs.map +1 -1
- package/dist/components/EntryRow/EntryRow.d.ts +1 -1
- package/dist/components/EntryRow/EntryRow.js +2 -2
- package/dist/components/EntryRow/EntryRow.js.map +1 -1
- package/dist/components/EntryRow.cjs +1 -1
- package/dist/components/ExpanderRow/ExpanderRow.cjs +1 -1
- package/dist/components/ExpanderRow/ExpanderRow.cjs.map +1 -1
- package/dist/components/ExpanderRow/ExpanderRow.d.ts +1 -1
- package/dist/components/ExpanderRow/ExpanderRow.js +2 -2
- package/dist/components/ExpanderRow/ExpanderRow.js.map +1 -1
- package/dist/components/ExpanderRow.cjs +1 -1
- package/dist/components/Footer/Footer.cjs +1 -1
- package/dist/components/Footer/Footer.cjs.map +1 -1
- package/dist/components/Footer/Footer.d.ts +1 -1
- package/dist/components/Footer/Footer.js +22 -24
- package/dist/components/Footer/Footer.js.map +1 -1
- package/dist/components/Footer.cjs +1 -1
- package/dist/components/Frame/Frame.cjs +1 -1
- package/dist/components/Frame/Frame.cjs.map +1 -1
- package/dist/components/Frame/Frame.d.ts +1 -1
- package/dist/components/Frame/Frame.js +5 -7
- package/dist/components/Frame/Frame.js.map +1 -1
- package/dist/components/Frame.cjs +1 -1
- package/dist/components/GnomeProvider/GnomeContext.cjs +1 -1
- package/dist/components/GnomeProvider/GnomeContext.cjs.map +1 -1
- package/dist/components/GnomeProvider/GnomeContext.js.map +1 -1
- package/dist/components/GnomeProvider/GnomeProvider.cjs +1 -1
- package/dist/components/GnomeProvider/GnomeProvider.cjs.map +1 -1
- package/dist/components/GnomeProvider/GnomeProvider.d.ts +1 -1
- package/dist/components/GnomeProvider/GnomeProvider.js +2 -2
- package/dist/components/GnomeProvider/GnomeProvider.js.map +1 -1
- package/dist/components/HeaderBar/HeaderBar.cjs +1 -1
- package/dist/components/HeaderBar/HeaderBar.cjs.map +1 -1
- package/dist/components/HeaderBar/HeaderBar.d.ts +1 -1
- package/dist/components/HeaderBar/HeaderBar.js +26 -28
- package/dist/components/HeaderBar/HeaderBar.js.map +1 -1
- package/dist/components/HeaderBar.cjs +1 -1
- package/dist/components/Icon/Icon.cjs +1 -1
- package/dist/components/Icon/Icon.cjs.map +1 -1
- package/dist/components/Icon/Icon.d.ts +1 -1
- package/dist/components/Icon/Icon.js +2 -2
- package/dist/components/Icon/Icon.js.map +1 -1
- package/dist/components/Icon.cjs +1 -1
- package/dist/components/IconButton/IconButton.cjs +1 -1
- package/dist/components/IconButton/IconButton.cjs.map +1 -1
- package/dist/components/IconButton/IconButton.js +4 -4
- package/dist/components/IconButton/IconButton.js.map +1 -1
- package/dist/components/IconButton.cjs +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcher.cjs +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcher.cjs.map +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcher.d.ts +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcher.js +2 -2
- package/dist/components/InlineViewSwitcher/InlineViewSwitcher.js.map +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcherItem.cjs +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcherItem.cjs.map +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcherItem.d.ts +1 -1
- package/dist/components/InlineViewSwitcher/InlineViewSwitcherItem.js +2 -2
- package/dist/components/InlineViewSwitcher/InlineViewSwitcherItem.js.map +1 -1
- package/dist/components/InlineViewSwitcher.cjs +1 -1
- package/dist/components/Link/Link.cjs +1 -1
- package/dist/components/Link/Link.cjs.map +1 -1
- package/dist/components/Link/Link.d.ts +1 -1
- package/dist/components/Link/Link.js +2 -2
- package/dist/components/Link/Link.js.map +1 -1
- package/dist/components/Link.cjs +1 -1
- package/dist/components/LinkedGroup/LinkedGroup.cjs +1 -1
- package/dist/components/LinkedGroup/LinkedGroup.cjs.map +1 -1
- package/dist/components/LinkedGroup/LinkedGroup.d.ts +1 -1
- package/dist/components/LinkedGroup/LinkedGroup.js +9 -11
- package/dist/components/LinkedGroup/LinkedGroup.js.map +1 -1
- package/dist/components/LinkedGroup.cjs +1 -1
- package/dist/components/NavigationSplitView/NavigationSplitView.cjs +1 -1
- package/dist/components/NavigationSplitView/NavigationSplitView.cjs.map +1 -1
- package/dist/components/NavigationSplitView/NavigationSplitView.d.ts +1 -1
- package/dist/components/NavigationSplitView/NavigationSplitView.js +2 -2
- package/dist/components/NavigationSplitView/NavigationSplitView.js.map +1 -1
- package/dist/components/NavigationSplitView.cjs +1 -1
- package/dist/components/NavigationView/NavigationView.cjs +1 -1
- package/dist/components/NavigationView/NavigationView.cjs.map +1 -1
- package/dist/components/NavigationView/NavigationView.d.ts +2 -2
- package/dist/components/NavigationView/NavigationView.js +3 -4
- package/dist/components/NavigationView/NavigationView.js.map +1 -1
- package/dist/components/NavigationView/NavigationView.module.css.cjs +1 -1
- package/dist/components/NavigationView/NavigationView.module.css.js +9 -10
- package/dist/components/NavigationView.cjs +1 -1
- package/dist/components/OverlaySplitView/OverlaySplitView.cjs +1 -1
- package/dist/components/OverlaySplitView/OverlaySplitView.cjs.map +1 -1
- package/dist/components/OverlaySplitView/OverlaySplitView.d.ts +1 -1
- package/dist/components/OverlaySplitView/OverlaySplitView.js +2 -2
- package/dist/components/OverlaySplitView/OverlaySplitView.js.map +1 -1
- package/dist/components/OverlaySplitView.cjs +1 -1
- package/dist/components/PasswordEntryRow/PasswordEntryRow.cjs +1 -1
- package/dist/components/PasswordEntryRow/PasswordEntryRow.cjs.map +1 -1
- package/dist/components/PasswordEntryRow/PasswordEntryRow.d.ts +1 -1
- package/dist/components/PasswordEntryRow/PasswordEntryRow.js +11 -10
- package/dist/components/PasswordEntryRow/PasswordEntryRow.js.map +1 -1
- package/dist/components/PasswordEntryRow.cjs +1 -1
- package/dist/components/PathBar/PathBar.cjs +1 -1
- package/dist/components/PathBar/PathBar.cjs.map +1 -1
- package/dist/components/PathBar/PathBar.d.ts +1 -1
- package/dist/components/PathBar/PathBar.js +48 -50
- package/dist/components/PathBar/PathBar.js.map +1 -1
- package/dist/components/PathBar.cjs +1 -1
- package/dist/components/Popover/Popover.cjs +1 -1
- package/dist/components/Popover/Popover.cjs.map +1 -1
- package/dist/components/Popover/Popover.d.ts +1 -1
- package/dist/components/Popover/Popover.js +5 -5
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover.cjs +1 -1
- package/dist/components/PreferencesDialog/PreferencesDialog.cjs +1 -1
- package/dist/components/PreferencesDialog/PreferencesDialog.cjs.map +1 -1
- package/dist/components/PreferencesDialog/PreferencesDialog.d.ts +1 -1
- package/dist/components/PreferencesDialog/PreferencesDialog.js +2 -2
- package/dist/components/PreferencesDialog/PreferencesDialog.js.map +1 -1
- package/dist/components/PreferencesDialog/PreferencesDialog.module.css.cjs +1 -1
- package/dist/components/PreferencesDialog/PreferencesDialog.module.css.js +18 -19
- package/dist/components/PreferencesDialog.cjs +1 -1
- package/dist/components/PreferencesGroup/PreferencesGroup.cjs +1 -1
- package/dist/components/PreferencesGroup/PreferencesGroup.cjs.map +1 -1
- package/dist/components/PreferencesGroup/PreferencesGroup.d.ts +1 -1
- package/dist/components/PreferencesGroup/PreferencesGroup.js +2 -2
- package/dist/components/PreferencesGroup/PreferencesGroup.js.map +1 -1
- package/dist/components/PreferencesGroup.cjs +1 -1
- package/dist/components/PreferencesPage/PreferencesPage.cjs +1 -1
- package/dist/components/PreferencesPage/PreferencesPage.cjs.map +1 -1
- package/dist/components/PreferencesPage/PreferencesPage.d.ts +1 -1
- package/dist/components/PreferencesPage/PreferencesPage.js +9 -11
- package/dist/components/PreferencesPage/PreferencesPage.js.map +1 -1
- package/dist/components/PreferencesPage.cjs +1 -1
- package/dist/components/ProgressBar/ProgressBar.cjs +1 -1
- package/dist/components/ProgressBar/ProgressBar.cjs.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts +1 -1
- package/dist/components/ProgressBar/ProgressBar.js +2 -2
- package/dist/components/ProgressBar/ProgressBar.js.map +1 -1
- package/dist/components/ProgressBar.cjs +1 -1
- package/dist/components/RadioButton/RadioButton.cjs +1 -1
- package/dist/components/RadioButton/RadioButton.cjs.map +1 -1
- package/dist/components/RadioButton/RadioButton.d.ts +1 -1
- package/dist/components/RadioButton/RadioButton.js +5 -7
- package/dist/components/RadioButton/RadioButton.js.map +1 -1
- package/dist/components/RadioButton.cjs +1 -1
- package/dist/components/SearchBar/SearchBar.cjs +1 -1
- package/dist/components/SearchBar/SearchBar.cjs.map +1 -1
- package/dist/components/SearchBar/SearchBar.d.ts +1 -1
- package/dist/components/SearchBar/SearchBar.js +2 -2
- package/dist/components/SearchBar/SearchBar.js.map +1 -1
- package/dist/components/SearchBar.cjs +1 -1
- package/dist/components/SegmentedBar/SegmentedBar.cjs +1 -1
- package/dist/components/SegmentedBar/SegmentedBar.cjs.map +1 -1
- package/dist/components/SegmentedBar/SegmentedBar.js.map +1 -1
- package/dist/components/SegmentedBar.cjs +1 -1
- package/dist/components/Separator/Separator.cjs +1 -1
- package/dist/components/Separator/Separator.cjs.map +1 -1
- package/dist/components/Separator/Separator.d.ts +1 -1
- package/dist/components/Separator/Separator.js +2 -2
- package/dist/components/Separator/Separator.js.map +1 -1
- package/dist/components/Separator.cjs +1 -1
- package/dist/components/ShortcutLabel/ShortcutLabel.cjs +1 -1
- package/dist/components/ShortcutLabel/ShortcutLabel.cjs.map +1 -1
- package/dist/components/ShortcutLabel/ShortcutLabel.d.ts +1 -1
- package/dist/components/ShortcutLabel/ShortcutLabel.js +2 -3
- package/dist/components/ShortcutLabel/ShortcutLabel.js.map +1 -1
- package/dist/components/ShortcutLabel.cjs +1 -1
- package/dist/components/ShortcutsDialog/ShortcutsDialog.cjs +1 -1
- package/dist/components/ShortcutsDialog/ShortcutsDialog.cjs.map +1 -1
- package/dist/components/ShortcutsDialog/ShortcutsDialog.d.ts +1 -1
- package/dist/components/ShortcutsDialog/ShortcutsDialog.js +75 -76
- package/dist/components/ShortcutsDialog/ShortcutsDialog.js.map +1 -1
- package/dist/components/ShortcutsDialog/ShortcutsDialog.module.css.cjs +1 -1
- package/dist/components/ShortcutsDialog/ShortcutsDialog.module.css.js +21 -22
- package/dist/components/ShortcutsDialog.cjs +1 -1
- package/dist/components/Sidebar/Sidebar.cjs +1 -1
- package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
- package/dist/components/Sidebar/Sidebar.d.ts +1 -1
- package/dist/components/Sidebar/Sidebar.js +2 -3
- package/dist/components/Sidebar/Sidebar.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.module.css.cjs +1 -1
- package/dist/components/Sidebar/Sidebar.module.css.js +33 -34
- package/dist/components/Sidebar/SidebarItem.cjs +1 -1
- package/dist/components/Sidebar/SidebarItem.cjs.map +1 -1
- package/dist/components/Sidebar/SidebarItem.d.ts +1 -1
- package/dist/components/Sidebar/SidebarItem.js +16 -16
- package/dist/components/Sidebar/SidebarItem.js.map +1 -1
- package/dist/components/Sidebar/SidebarSection.cjs +1 -1
- package/dist/components/Sidebar/SidebarSection.cjs.map +1 -1
- package/dist/components/Sidebar/SidebarSection.js.map +1 -1
- package/dist/components/Sidebar.cjs +1 -1
- package/dist/components/Skeleton/Skeleton.cjs +1 -1
- package/dist/components/Skeleton/Skeleton.cjs.map +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +1 -1
- package/dist/components/Skeleton/Skeleton.js +9 -10
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Skeleton.cjs +1 -1
- package/dist/components/Slider/Slider.cjs +1 -1
- package/dist/components/Slider/Slider.cjs.map +1 -1
- package/dist/components/Slider/Slider.d.ts +1 -1
- package/dist/components/Slider/Slider.js +2 -2
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Slider.cjs +1 -1
- package/dist/components/SpinButton/SpinButton.cjs +1 -1
- package/dist/components/SpinButton/SpinButton.cjs.map +1 -1
- package/dist/components/SpinButton/SpinButton.d.ts +1 -1
- package/dist/components/SpinButton/SpinButton.js +2 -2
- package/dist/components/SpinButton/SpinButton.js.map +1 -1
- package/dist/components/SpinButton.cjs +1 -1
- package/dist/components/SpinRow/SpinRow.cjs +1 -1
- package/dist/components/SpinRow/SpinRow.cjs.map +1 -1
- package/dist/components/SpinRow/SpinRow.d.ts +1 -1
- package/dist/components/SpinRow/SpinRow.js +2 -2
- package/dist/components/SpinRow/SpinRow.js.map +1 -1
- package/dist/components/SpinRow.cjs +1 -1
- package/dist/components/Spinner/Spinner.cjs +1 -1
- package/dist/components/Spinner/Spinner.cjs.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +1 -1
- package/dist/components/Spinner/Spinner.js +2 -2
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/Spinner.cjs +1 -1
- package/dist/components/SplitButton/SplitButton.cjs +1 -1
- package/dist/components/SplitButton/SplitButton.cjs.map +1 -1
- package/dist/components/SplitButton/SplitButton.d.ts +1 -1
- package/dist/components/SplitButton/SplitButton.js +2 -2
- package/dist/components/SplitButton/SplitButton.js.map +1 -1
- package/dist/components/SplitButton.cjs +1 -1
- package/dist/components/StatusBadge/StatusBadge.cjs +1 -1
- package/dist/components/StatusBadge/StatusBadge.cjs.map +1 -1
- package/dist/components/StatusBadge/StatusBadge.d.ts +1 -1
- package/dist/components/StatusBadge/StatusBadge.js +9 -11
- package/dist/components/StatusBadge/StatusBadge.js.map +1 -1
- package/dist/components/StatusBadge.cjs +1 -1
- package/dist/components/StatusPage/StatusPage.cjs +1 -1
- package/dist/components/StatusPage/StatusPage.cjs.map +1 -1
- package/dist/components/StatusPage/StatusPage.d.ts +1 -1
- package/dist/components/StatusPage/StatusPage.js +2 -2
- package/dist/components/StatusPage/StatusPage.js.map +1 -1
- package/dist/components/StatusPage.cjs +1 -1
- package/dist/components/Switch/Switch.cjs +1 -1
- package/dist/components/Switch/Switch.cjs.map +1 -1
- package/dist/components/Switch/Switch.d.ts +1 -1
- package/dist/components/Switch/Switch.js +6 -8
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Switch.cjs +1 -1
- package/dist/components/SwitchRow/SwitchRow.cjs +1 -1
- package/dist/components/SwitchRow/SwitchRow.cjs.map +1 -1
- package/dist/components/SwitchRow/SwitchRow.d.ts +1 -1
- package/dist/components/SwitchRow/SwitchRow.js +7 -7
- package/dist/components/SwitchRow/SwitchRow.js.map +1 -1
- package/dist/components/SwitchRow.cjs +1 -1
- package/dist/components/Tabs/TabBar.cjs +1 -1
- package/dist/components/Tabs/TabBar.cjs.map +1 -1
- package/dist/components/Tabs/TabBar.d.ts +1 -1
- package/dist/components/Tabs/TabBar.js +2 -2
- package/dist/components/Tabs/TabBar.js.map +1 -1
- package/dist/components/Tabs/TabItem.cjs +1 -1
- package/dist/components/Tabs/TabItem.cjs.map +1 -1
- package/dist/components/Tabs/TabItem.js.map +1 -1
- package/dist/components/Tabs/TabPanel.cjs +1 -1
- package/dist/components/Tabs/TabPanel.cjs.map +1 -1
- package/dist/components/Tabs/TabPanel.d.ts +1 -1
- package/dist/components/Tabs/TabPanel.js +8 -10
- package/dist/components/Tabs/TabPanel.js.map +1 -1
- package/dist/components/Tabs.cjs +1 -1
- package/dist/components/TerminalView/TerminalView.cjs +1 -1
- package/dist/components/TerminalView/TerminalView.cjs.map +1 -1
- package/dist/components/TerminalView/TerminalView.d.ts +1 -1
- package/dist/components/TerminalView/TerminalView.js +2 -2
- package/dist/components/TerminalView/TerminalView.js.map +1 -1
- package/dist/components/TerminalView.cjs +1 -1
- package/dist/components/Text/Text.cjs +1 -1
- package/dist/components/Text/Text.cjs.map +1 -1
- package/dist/components/Text/Text.d.ts +1 -1
- package/dist/components/Text/Text.js +10 -13
- package/dist/components/Text/Text.js.map +1 -1
- package/dist/components/Text/Text.module.css.cjs +1 -1
- package/dist/components/Text/Text.module.css.js +9 -10
- package/dist/components/Text.cjs +1 -1
- package/dist/components/TextField/TextField.cjs +1 -1
- package/dist/components/TextField/TextField.cjs.map +1 -1
- package/dist/components/TextField/TextField.d.ts +1 -1
- package/dist/components/TextField/TextField.js +2 -2
- package/dist/components/TextField/TextField.js.map +1 -1
- package/dist/components/TextField.cjs +1 -1
- package/dist/components/Timeline/Timeline.cjs +1 -1
- package/dist/components/Timeline/Timeline.cjs.map +1 -1
- package/dist/components/Timeline/Timeline.d.ts +1 -1
- package/dist/components/Timeline/Timeline.js +2 -2
- package/dist/components/Timeline/Timeline.js.map +1 -1
- package/dist/components/Timeline.cjs +1 -1
- package/dist/components/Toast/Toast.cjs +1 -1
- package/dist/components/Toast/Toast.cjs.map +1 -1
- package/dist/components/Toast/Toast.d.ts +1 -1
- package/dist/components/Toast/Toast.js +2 -2
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/Toast/Toast.module.css.cjs +1 -1
- package/dist/components/Toast/Toast.module.css.js +10 -11
- package/dist/components/Toast/Toaster.cjs +1 -1
- package/dist/components/Toast/Toaster.cjs.map +1 -1
- package/dist/components/Toast/Toaster.d.ts +1 -1
- package/dist/components/Toast/Toaster.js +2 -2
- package/dist/components/Toast/Toaster.js.map +1 -1
- package/dist/components/Toast.cjs +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.cjs +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.js +2 -2
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupItem.cjs +1 -1
- package/dist/components/ToggleGroup/ToggleGroupItem.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupItem.d.ts +1 -1
- package/dist/components/ToggleGroup/ToggleGroupItem.js +2 -2
- package/dist/components/ToggleGroup/ToggleGroupItem.js.map +1 -1
- package/dist/components/ToggleGroup.cjs +1 -1
- package/dist/components/Toolbar/Spacer.cjs +1 -1
- package/dist/components/Toolbar/Spacer.cjs.map +1 -1
- package/dist/components/Toolbar/Spacer.d.ts +1 -1
- package/dist/components/Toolbar/Spacer.js +5 -7
- package/dist/components/Toolbar/Spacer.js.map +1 -1
- package/dist/components/Toolbar/Toolbar.cjs +1 -1
- package/dist/components/Toolbar/Toolbar.cjs.map +1 -1
- package/dist/components/Toolbar/Toolbar.d.ts +1 -1
- package/dist/components/Toolbar/Toolbar.js +5 -7
- package/dist/components/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/Toolbar.cjs +1 -1
- package/dist/components/ToolbarView/ToolbarView.cjs +1 -1
- package/dist/components/ToolbarView/ToolbarView.cjs.map +1 -1
- package/dist/components/ToolbarView/ToolbarView.d.ts +1 -1
- package/dist/components/ToolbarView/ToolbarView.js +18 -20
- package/dist/components/ToolbarView/ToolbarView.js.map +1 -1
- package/dist/components/ToolbarView.cjs +1 -1
- package/dist/components/Tooltip/Tooltip.cjs +1 -1
- package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.js +2 -2
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tooltip.cjs +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcher.cjs +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcher.cjs.map +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcher.d.ts +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcher.js +2 -2
- package/dist/components/ViewSwitcher/ViewSwitcher.js.map +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcherItem.cjs +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcherItem.cjs.map +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcherItem.d.ts +1 -1
- package/dist/components/ViewSwitcher/ViewSwitcherItem.js +24 -26
- package/dist/components/ViewSwitcher/ViewSwitcherItem.js.map +1 -1
- package/dist/components/ViewSwitcher.cjs +1 -1
- package/dist/components/ViewSwitcherBar/ViewSwitcherBar.cjs +1 -1
- package/dist/components/ViewSwitcherBar/ViewSwitcherBar.cjs.map +1 -1
- package/dist/components/ViewSwitcherBar/ViewSwitcherBar.d.ts +1 -1
- package/dist/components/ViewSwitcherBar/ViewSwitcherBar.js +7 -9
- package/dist/components/ViewSwitcherBar/ViewSwitcherBar.js.map +1 -1
- package/dist/components/ViewSwitcherBar.cjs +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebar.cjs +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebar.cjs.map +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebar.d.ts +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebar.js +2 -2
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebar.js.map +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebarItem.cjs +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebarItem.cjs.map +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebarItem.d.ts +1 -1
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebarItem.js +2 -2
- package/dist/components/ViewSwitcherSidebar/ViewSwitcherSidebarItem.js.map +1 -1
- package/dist/components/ViewSwitcherSidebar.cjs +1 -1
- package/dist/components/WindowTitle/WindowTitle.cjs +1 -1
- package/dist/components/WindowTitle/WindowTitle.cjs.map +1 -1
- package/dist/components/WindowTitle/WindowTitle.d.ts +1 -1
- package/dist/components/WindowTitle/WindowTitle.js +11 -13
- package/dist/components/WindowTitle/WindowTitle.js.map +1 -1
- package/dist/components/WindowTitle.cjs +1 -1
- package/dist/components/WrapBox/WrapBox.cjs +1 -1
- package/dist/components/WrapBox/WrapBox.cjs.map +1 -1
- package/dist/components/WrapBox/WrapBox.d.ts +1 -1
- package/dist/components/WrapBox/WrapBox.js +5 -5
- package/dist/components/WrapBox/WrapBox.js.map +1 -1
- package/dist/components/WrapBox.cjs +1 -1
- package/dist/hooks/useBreakpoint.cjs +1 -1
- package/dist/hooks/useBreakpoint.cjs.map +1 -1
- package/dist/hooks/useBreakpoint.js.map +1 -1
- package/dist/hooks.cjs +1 -1
- package/dist/index.cjs +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContributionGraph.cjs","names":[],"sources":["../../../src/components/ContributionGraph/ContributionGraph.tsx"],"sourcesContent":["import type { KeyboardEvent, MouseEvent } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { createPortal } from 'react-dom';\n\nimport {\n GnomeContext,\n type GnomeNamedAccentColor,\n useDateTimeFormatter,\n} from '../GnomeProvider/GnomeContext';\n\nimport styles from './ContributionGraph.module.css';\n\nexport interface ContributionDay {\n /** ISO 8601 date — \"YYYY-MM-DD\". */\n date: string;\n /** Non-negative activity count. */\n count: number;\n}\n\nexport interface ContributionGraphProps {\n /** Activity data. Days absent from the array are treated as count = 0. */\n data: ContributionDay[];\n /**\n * Number of intensity levels (excluding 0).\n * @default 4\n */\n maxLevel?: number;\n /** Cell side length in pixels. @default 12 */\n cellSize?: number;\n /** Gap between cells in pixels. @default 3 */\n cellGap?: number;\n /**\n * Fit the graph to its container by resizing cells and reducing visible\n * weeks when the configured range cannot stay legible.\n * @default true\n */\n responsive?: boolean;\n /** Smallest responsive cell side length in pixels. @default 8 */\n minCellSize?: number;\n /** Largest responsive cell side length in pixels. @default 24 */\n maxCellSize?: number;\n /** 0 = Sunday · 1 = Monday (GNOME locale default). @default 1 */\n weekStartDay?: 0 | 1;\n /** @default true */\n showMonthLabels?: boolean;\n /** @default true */\n showDayLabels?: boolean;\n /** @default true */\n showLegend?: boolean;\n /** Number of week columns to display. @default 52 */\n weeks?: number;\n /** @default \"Contribution graph\" */\n ariaLabel?: string;\n onDayClick?: (day: ContributionDay) => void;\n /** Returns a plain-text tooltip string for a day. */\n tooltipContent?: (day: ContributionDay) => string;\n className?: string;\n}\n\n// Reference Sunday: 2000-01-02 is a Sunday (day index 0)\nconst REF_SUNDAY = new Date(2000, 0, 2);\n\nfunction getShortMonth(monthIndex: number, formatter: Intl.DateTimeFormat): string {\n return formatter.format(new Date(2000, monthIndex));\n}\n\nfunction getShortDay(dayIndex: number, formatter: Intl.DateTimeFormat): string {\n const date = new Date(REF_SUNDAY);\n\n date.setDate(REF_SUNDAY.getDate() + dayIndex);\n\n return formatter.format(date);\n}\n\nconst DAY_LABEL_WIDTH = 28;\nconst MONTH_LABEL_HEIGHT = 20;\n\nconst NAMED_ACCENTS = new Set<GnomeNamedAccentColor>([\n 'blue',\n 'green',\n 'yellow',\n 'orange',\n 'red',\n 'purple',\n 'brown',\n]);\n\nfunction accentScale(accentColor: GnomeNamedAccentColor): string[] {\n return [\n 'var(--gnome-card-shade-color)',\n `var(--gnome-${accentColor}-1)`,\n `var(--gnome-${accentColor}-2)`,\n `var(--gnome-${accentColor}-4)`,\n `var(--gnome-${accentColor}-5)`,\n ];\n}\n\nfunction dateToIso(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n\n return `${y}-${m}-${d}`;\n}\n\nfunction isoToLocal(iso: string): Date {\n const [y, m, d] = iso.split('-').map(Number);\n\n return new Date(y, m - 1, d);\n}\n\nfunction fullDateLabel(iso: string, formatter: Intl.DateTimeFormat): string {\n return formatter.format(isoToLocal(iso));\n}\n\ninterface GridCell {\n iso: string;\n count: number;\n level: number;\n future: boolean;\n}\n\nexport function ContributionGraph({\n data,\n maxLevel = 4,\n cellSize = 12,\n cellGap = 3,\n responsive = true,\n minCellSize = 8,\n maxCellSize = 24,\n weekStartDay = 1,\n showMonthLabels = true,\n showDayLabels = true,\n showLegend = true,\n weeks = 52,\n ariaLabel = 'Contribution graph',\n onDayClick,\n tooltipContent,\n className,\n}: ContributionGraphProps) {\n const monthFormatter = useDateTimeFormatter({ month: 'short' });\n const weekdayFormatter = useDateTimeFormatter({ weekday: 'short' });\n const fullDateFormatter = useDateTimeFormatter({\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n const { accentColor } = useContext(GnomeContext);\n const graphAccent = NAMED_ACCENTS.has(accentColor as GnomeNamedAccentColor)\n ? (accentColor as GnomeNamedAccentColor)\n : 'green';\n const svgRef = useRef<SVGSVGElement>(null);\n const graphViewportRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const colors = useMemo(() => accentScale(graphAccent), [graphAccent]);\n\n const [availableWidth, setAvailableWidth] = useState<number | null>(null);\n const [focusedCell, setFocusedCell] = useState({ col: 0, row: 0 });\n const [tooltip, setTooltip] = useState<{\n target: SVGRectElement;\n text: string;\n } | null>(null);\n const [tooltipPosition, setTooltipPosition] = useState<{\n left: number;\n top: number;\n } | null>(null);\n\n useEffect(() => {\n if (!responsive) {\n return;\n }\n\n const viewport = graphViewportRef.current;\n\n if (!viewport) {\n return;\n }\n\n const updateWidth = () => {\n const width = viewport.clientWidth || viewport.getBoundingClientRect().width;\n\n if (width > 0) {\n setAvailableWidth(width);\n }\n };\n\n updateWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateWidth);\n\n return () => window.removeEventListener('resize', updateWidth);\n }\n\n const observer = new ResizeObserver(updateWidth);\n\n observer.observe(viewport);\n\n return () => observer.disconnect();\n }, [responsive]);\n\n useEffect(() => {\n if (!tooltip) {\n return;\n }\n\n const placeTooltip = () => {\n const tooltipNode = tooltipRef.current;\n\n if (!tooltipNode) {\n return;\n }\n\n const cellRect = tooltip.target.getBoundingClientRect();\n const tipRect = tooltipNode.getBoundingClientRect();\n const margin = 8;\n const gap = 6;\n const viewportWidth = document.documentElement.clientWidth || window.innerWidth;\n const viewportHeight = document.documentElement.clientHeight || window.innerHeight;\n const maxLeft = Math.max(margin, viewportWidth - tipRect.width - margin);\n const maxTop = Math.max(margin, viewportHeight - tipRect.height - margin);\n const centeredLeft = cellRect.left + cellRect.width / 2 - tipRect.width / 2;\n const aboveTop = cellRect.top - tipRect.height - gap;\n const preferredTop = aboveTop >= margin ? aboveTop : cellRect.bottom + gap;\n\n setTooltipPosition({\n left: Math.max(margin, Math.min(centeredLeft, maxLeft)),\n top: Math.max(margin, Math.min(preferredTop, maxTop)),\n });\n };\n\n placeTooltip();\n window.addEventListener('resize', placeTooltip);\n window.addEventListener('scroll', placeTooltip, { passive: true, capture: true });\n\n return () => {\n window.removeEventListener('resize', placeTooltip);\n window.removeEventListener('scroll', placeTooltip, { capture: true });\n };\n }, [tooltip]);\n\n const countMap = useMemo(() => {\n const map = new Map<string, number>();\n\n for (const d of data) {\n map.set(d.date, d.count);\n }\n\n return map;\n }, [data]);\n\n const maxCount = useMemo(() => Math.max(1, ...data.map((d) => d.count)), [data]);\n\n const dayLabelW = showDayLabels ? DAY_LABEL_WIDTH : 0;\n const monthLabelH = showMonthLabels ? MONTH_LABEL_HEIGHT : 0;\n const configuredWeeks = Math.max(1, Math.floor(weeks));\n const normalizedMinCellSize = Math.max(1, minCellSize);\n const normalizedMaxCellSize = Math.max(normalizedMinCellSize, maxCellSize);\n const fit = useMemo(() => {\n if (!responsive || availableWidth === null) {\n return { cellSize, weeks: configuredWeeks };\n }\n\n const gridWidth = Math.max(0, availableWidth - dayLabelW);\n const fittedCellSize = (gridWidth + cellGap) / configuredWeeks - cellGap;\n\n if (fittedCellSize >= normalizedMinCellSize) {\n return {\n cellSize: Math.min(normalizedMaxCellSize, fittedCellSize),\n weeks: configuredWeeks,\n };\n }\n\n const fittedWeeks = Math.floor((gridWidth + cellGap) / (normalizedMinCellSize + cellGap));\n\n return {\n cellSize: normalizedMinCellSize,\n weeks: Math.max(1, Math.min(configuredWeeks, fittedWeeks)),\n };\n }, [\n availableWidth,\n cellGap,\n cellSize,\n configuredWeeks,\n dayLabelW,\n normalizedMaxCellSize,\n normalizedMinCellSize,\n responsive,\n ]);\n const visibleWeeks = fit.weeks;\n const resolvedCellSize = fit.cellSize;\n const stride = resolvedCellSize + cellGap;\n\n const { grid, monthLabels } = useMemo(() => {\n const today = new Date();\n\n today.setHours(0, 0, 0, 0);\n\n // Align to start of current week\n const daysFromWeekStart = (today.getDay() - weekStartDay + 7) % 7;\n const lastWeekStart = new Date(today);\n\n lastWeekStart.setDate(today.getDate() - daysFromWeekStart);\n\n const firstDay = new Date(lastWeekStart);\n\n firstDay.setDate(lastWeekStart.getDate() - (visibleWeeks - 1) * 7);\n\n const gridResult: GridCell[][] = [];\n const labels: { col: number; month: string }[] = [];\n\n let lastMonth = -1;\n\n for (let col = 0; col < visibleWeeks; col++) {\n const colStart = new Date(firstDay);\n\n colStart.setDate(firstDay.getDate() + col * 7);\n\n // Month label when the column starts a new month\n if (colStart.getMonth() !== lastMonth) {\n labels.push({\n col,\n month: getShortMonth(colStart.getMonth(), monthFormatter),\n });\n lastMonth = colStart.getMonth();\n }\n\n const column: GridCell[] = [];\n\n for (let row = 0; row < 7; row++) {\n const date = new Date(firstDay);\n\n date.setDate(firstDay.getDate() + col * 7 + row);\n const future = date > today;\n const iso = dateToIso(date);\n const count = future ? 0 : (countMap.get(iso) ?? 0);\n const level =\n count === 0 ? 0 : Math.min(maxLevel, Math.ceil((count / maxCount) * maxLevel));\n\n column.push({ iso, count, level, future });\n }\n\n gridResult.push(column);\n }\n\n return { grid: gridResult, monthLabels: labels };\n }, [countMap, maxCount, maxLevel, visibleWeeks, weekStartDay, monthFormatter]);\n\n // Always label Mon(1), Wed(3), Fri(5) — rows shift with weekStartDay\n const labelRows = useMemo(\n () =>\n [1, 3, 5].map((dayIndex) => ({\n row: (dayIndex - weekStartDay + 7) % 7,\n label: getShortDay(dayIndex, weekdayFormatter),\n })),\n [weekStartDay, weekdayFormatter],\n );\n\n const svgWidth = dayLabelW + visibleWeeks * stride - cellGap;\n const svgHeight = monthLabelH + 7 * stride - cellGap;\n const cellRx = Math.min(4, Math.floor(resolvedCellSize / 3));\n\n useEffect(() => {\n setFocusedCell((current) => ({\n col: Math.min(visibleWeeks - 1, current.col),\n row: current.row,\n }));\n }, [visibleWeeks]);\n\n function focusCell(col: number, row: number) {\n const c = Math.max(0, Math.min(visibleWeeks - 1, col));\n const r = Math.max(0, Math.min(6, row));\n\n setFocusedCell({ col: c, row: r });\n svgRef.current?.querySelector<SVGRectElement>(`[data-col=\"${c}\"][data-row=\"${r}\"]`)?.focus();\n }\n\n function handleCellKey(e: KeyboardEvent, col: number, row: number) {\n const moves: Record<string, [number, number]> = {\n ArrowRight: [col + 1, row],\n ArrowLeft: [col - 1, row],\n ArrowDown: [col, row + 1],\n ArrowUp: [col, row - 1],\n };\n\n if (moves[e.key]) {\n e.preventDefault();\n focusCell(...moves[e.key]);\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const cell = grid[col]?.[row];\n\n if (cell && !cell.future) {\n onDayClick?.({ date: cell.iso, count: cell.count });\n }\n }\n }\n\n function handleMouseEnter(e: MouseEvent<SVGRectElement>, text: string) {\n setTooltipPosition(null);\n setTooltip({\n target: e.currentTarget,\n text,\n });\n }\n\n function hideTooltip() {\n setTooltip(null);\n setTooltipPosition(null);\n }\n\n function cellColor(cell: GridCell): string {\n if (cell.future) {\n return colors[0];\n }\n\n return colors[Math.min(cell.level, colors.length - 1)] ?? colors[colors.length - 1];\n }\n\n function cellTooltip(cell: GridCell): string {\n if (cell.future) {\n return fullDateLabel(cell.iso, fullDateFormatter);\n }\n\n const formattedDate = fullDateLabel(cell.iso, fullDateFormatter);\n\n return (\n tooltipContent?.({ date: cell.iso, count: cell.count }) ??\n `${cell.count} contribution${cell.count !== 1 ? 's' : ''} on ${formattedDate}`\n );\n }\n\n return (\n <div className={[styles.wrapper, className].filter(Boolean).join(' ')}>\n <div ref={graphViewportRef} className={styles.graphViewport}>\n <svg\n ref={svgRef}\n width={svgWidth}\n height={svgHeight}\n className={styles.svg}\n aria-label={ariaLabel}\n role=\"img\"\n data-cell-size={resolvedCellSize}\n data-visible-weeks={visibleWeeks}\n >\n {/* Month labels */}\n {showMonthLabels &&\n monthLabels.map(({ col, month }) => (\n <text key={`m-${col}`} x={dayLabelW + col * stride} y={12} className={styles.label}>\n {month}\n </text>\n ))}\n\n {/* Day-of-week labels: Mon, Wed, Fri */}\n {showDayLabels &&\n labelRows.map(({ row, label }) => (\n <text\n key={`d-${row}`}\n x={0}\n y={monthLabelH + row * stride + resolvedCellSize - 1}\n className={styles.label}\n >\n {label}\n </text>\n ))}\n\n {/* Activity grid */}\n <g role=\"grid\" aria-label={ariaLabel}>\n {grid.map((column, col) => (\n <g key={col} role=\"row\">\n {column.map((cell, row) => {\n const tipText = cellTooltip(cell);\n const isFocused = focusedCell.col === col && focusedCell.row === row;\n\n return (\n <rect\n key={`${col}-${row}`}\n data-col={col}\n data-row={row}\n x={dayLabelW + col * stride}\n y={monthLabelH + row * stride}\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={cellColor(cell)}\n opacity={cell.future ? 0.35 : 1}\n className={styles.cell}\n role=\"gridcell\"\n aria-label={tipText}\n aria-disabled={cell.future || undefined}\n tabIndex={isFocused ? 0 : -1}\n onClick={() =>\n !cell.future && onDayClick?.({ date: cell.iso, count: cell.count })\n }\n onKeyDown={(e) => handleCellKey(e, col, row)}\n onFocus={() => setFocusedCell({ col, row })}\n onMouseEnter={(e) => handleMouseEnter(e, tipText)}\n onMouseLeave={hideTooltip}\n />\n );\n })}\n </g>\n ))}\n </g>\n </svg>\n </div>\n\n {tooltip &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={tooltipRef}\n className={styles.tooltip}\n style={\n tooltipPosition\n ? { left: tooltipPosition.left, top: tooltipPosition.top }\n : { visibility: 'hidden', left: 0, top: 0 }\n }\n role=\"tooltip\"\n >\n {tooltip.text}\n </div>,\n document.body,\n )}\n\n {showLegend && (\n <div className={styles.legend}>\n <span className={styles.legendLabel}>Less</span>\n {Array.from({ length: maxLevel + 1 }, (_, i) => (\n <svg\n key={i}\n width={resolvedCellSize}\n height={resolvedCellSize}\n aria-hidden=\"true\"\n className={styles.legendCell}\n >\n <rect\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={colors[Math.min(i, colors.length - 1)]}\n />\n </svg>\n ))}\n <span className={styles.legendLabel}>More</span>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ContributionGraph.cjs","names":[],"sources":["../../../src/components/ContributionGraph/ContributionGraph.tsx"],"sourcesContent":["import type { KeyboardEvent, MouseEvent } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { createPortal } from 'react-dom';\n\nimport {\n GnomeContext,\n type GnomeNamedAccentColor,\n useDateTimeFormatter,\n} from '../GnomeProvider/GnomeContext';\n\nimport styles from './ContributionGraph.module.css';\n\nexport interface ContributionDay {\n /** ISO 8601 date — \"YYYY-MM-DD\". */\n date: string;\n /** Non-negative activity count. */\n count: number;\n}\n\nexport interface ContributionGraphProps {\n /** Activity data. Days absent from the array are treated as count = 0. */\n data: ContributionDay[];\n /**\n * Number of intensity levels (excluding 0).\n * @default 4\n */\n maxLevel?: number;\n /** Cell side length in pixels. @default 12 */\n cellSize?: number;\n /** Gap between cells in pixels. @default 3 */\n cellGap?: number;\n /**\n * Fit the graph to its container by resizing cells and reducing visible\n * weeks when the configured range cannot stay legible.\n * @default true\n */\n responsive?: boolean;\n /** Smallest responsive cell side length in pixels. @default 8 */\n minCellSize?: number;\n /** Largest responsive cell side length in pixels. @default 24 */\n maxCellSize?: number;\n /** 0 = Sunday · 1 = Monday (GNOME locale default). @default 1 */\n weekStartDay?: 0 | 1;\n /** @default true */\n showMonthLabels?: boolean;\n /** @default true */\n showDayLabels?: boolean;\n /** @default true */\n showLegend?: boolean;\n /** Number of week columns to display. @default 52 */\n weeks?: number;\n /** @default \"Contribution graph\" */\n ariaLabel?: string;\n onDayClick?: (day: ContributionDay) => void;\n /** Returns a plain-text tooltip string for a day. */\n tooltipContent?: (day: ContributionDay) => string;\n className?: string;\n}\n\n// Reference Sunday: 2000-01-02 is a Sunday (day index 0)\nconst REF_SUNDAY = new Date(2000, 0, 2);\n\nfunction getShortMonth(monthIndex: number, formatter: Intl.DateTimeFormat): string {\n return formatter.format(new Date(2000, monthIndex));\n}\n\nfunction getShortDay(dayIndex: number, formatter: Intl.DateTimeFormat): string {\n const date = new Date(REF_SUNDAY);\n\n date.setDate(REF_SUNDAY.getDate() + dayIndex);\n\n return formatter.format(date);\n}\n\nconst DAY_LABEL_WIDTH = 28;\nconst MONTH_LABEL_HEIGHT = 20;\n\nconst NAMED_ACCENTS = new Set<GnomeNamedAccentColor>([\n 'blue',\n 'green',\n 'yellow',\n 'orange',\n 'red',\n 'purple',\n 'brown',\n]);\n\nfunction accentScale(accentColor: GnomeNamedAccentColor): string[] {\n return [\n 'var(--gnome-card-shade-color)',\n `var(--gnome-${accentColor}-1)`,\n `var(--gnome-${accentColor}-2)`,\n `var(--gnome-${accentColor}-4)`,\n `var(--gnome-${accentColor}-5)`,\n ];\n}\n\nfunction dateToIso(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n\n return `${y}-${m}-${d}`;\n}\n\nfunction isoToLocal(iso: string): Date {\n const [y, m, d] = iso.split('-').map(Number);\n\n return new Date(y, m - 1, d);\n}\n\nfunction fullDateLabel(iso: string, formatter: Intl.DateTimeFormat): string {\n return formatter.format(isoToLocal(iso));\n}\n\ninterface GridCell {\n iso: string;\n count: number;\n level: number;\n future: boolean;\n}\n\nexport const ContributionGraph = ({\n data,\n maxLevel = 4,\n cellSize = 12,\n cellGap = 3,\n responsive = true,\n minCellSize = 8,\n maxCellSize = 24,\n weekStartDay = 1,\n showMonthLabels = true,\n showDayLabels = true,\n showLegend = true,\n weeks = 52,\n ariaLabel = 'Contribution graph',\n onDayClick,\n tooltipContent,\n className,\n}: ContributionGraphProps) => {\n const monthFormatter = useDateTimeFormatter({ month: 'short' });\n const weekdayFormatter = useDateTimeFormatter({ weekday: 'short' });\n const fullDateFormatter = useDateTimeFormatter({\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n const { accentColor } = useContext(GnomeContext);\n const graphAccent = NAMED_ACCENTS.has(accentColor as GnomeNamedAccentColor)\n ? (accentColor as GnomeNamedAccentColor)\n : 'green';\n const svgRef = useRef<SVGSVGElement>(null);\n const graphViewportRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const colors = useMemo(() => accentScale(graphAccent), [graphAccent]);\n\n const [availableWidth, setAvailableWidth] = useState<number | null>(null);\n const [focusedCell, setFocusedCell] = useState({ col: 0, row: 0 });\n const [tooltip, setTooltip] = useState<{\n target: SVGRectElement;\n text: string;\n } | null>(null);\n const [tooltipPosition, setTooltipPosition] = useState<{\n left: number;\n top: number;\n } | null>(null);\n\n useEffect(() => {\n if (!responsive) {\n return;\n }\n\n const viewport = graphViewportRef.current;\n\n if (!viewport) {\n return;\n }\n\n const updateWidth = () => {\n const width = viewport.clientWidth || viewport.getBoundingClientRect().width;\n\n if (width > 0) {\n setAvailableWidth(width);\n }\n };\n\n updateWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateWidth);\n\n return () => window.removeEventListener('resize', updateWidth);\n }\n\n const observer = new ResizeObserver(updateWidth);\n\n observer.observe(viewport);\n\n return () => observer.disconnect();\n }, [responsive]);\n\n useEffect(() => {\n if (!tooltip) {\n return;\n }\n\n const placeTooltip = () => {\n const tooltipNode = tooltipRef.current;\n\n if (!tooltipNode) {\n return;\n }\n\n const cellRect = tooltip.target.getBoundingClientRect();\n const tipRect = tooltipNode.getBoundingClientRect();\n const margin = 8;\n const gap = 6;\n const viewportWidth = document.documentElement.clientWidth || window.innerWidth;\n const viewportHeight = document.documentElement.clientHeight || window.innerHeight;\n const maxLeft = Math.max(margin, viewportWidth - tipRect.width - margin);\n const maxTop = Math.max(margin, viewportHeight - tipRect.height - margin);\n const centeredLeft = cellRect.left + cellRect.width / 2 - tipRect.width / 2;\n const aboveTop = cellRect.top - tipRect.height - gap;\n const preferredTop = aboveTop >= margin ? aboveTop : cellRect.bottom + gap;\n\n setTooltipPosition({\n left: Math.max(margin, Math.min(centeredLeft, maxLeft)),\n top: Math.max(margin, Math.min(preferredTop, maxTop)),\n });\n };\n\n placeTooltip();\n window.addEventListener('resize', placeTooltip);\n window.addEventListener('scroll', placeTooltip, { passive: true, capture: true });\n\n return () => {\n window.removeEventListener('resize', placeTooltip);\n window.removeEventListener('scroll', placeTooltip, { capture: true });\n };\n }, [tooltip]);\n\n const countMap = useMemo(() => {\n const map = new Map<string, number>();\n\n for (const d of data) {\n map.set(d.date, d.count);\n }\n\n return map;\n }, [data]);\n\n const maxCount = useMemo(() => Math.max(1, ...data.map((d) => d.count)), [data]);\n\n const dayLabelW = showDayLabels ? DAY_LABEL_WIDTH : 0;\n const monthLabelH = showMonthLabels ? MONTH_LABEL_HEIGHT : 0;\n const configuredWeeks = Math.max(1, Math.floor(weeks));\n const normalizedMinCellSize = Math.max(1, minCellSize);\n const normalizedMaxCellSize = Math.max(normalizedMinCellSize, maxCellSize);\n const fit = useMemo(() => {\n if (!responsive || availableWidth === null) {\n return { cellSize, weeks: configuredWeeks };\n }\n\n const gridWidth = Math.max(0, availableWidth - dayLabelW);\n const fittedCellSize = (gridWidth + cellGap) / configuredWeeks - cellGap;\n\n if (fittedCellSize >= normalizedMinCellSize) {\n return {\n cellSize: Math.min(normalizedMaxCellSize, fittedCellSize),\n weeks: configuredWeeks,\n };\n }\n\n const fittedWeeks = Math.floor((gridWidth + cellGap) / (normalizedMinCellSize + cellGap));\n\n return {\n cellSize: normalizedMinCellSize,\n weeks: Math.max(1, Math.min(configuredWeeks, fittedWeeks)),\n };\n }, [\n availableWidth,\n cellGap,\n cellSize,\n configuredWeeks,\n dayLabelW,\n normalizedMaxCellSize,\n normalizedMinCellSize,\n responsive,\n ]);\n const visibleWeeks = fit.weeks;\n const resolvedCellSize = fit.cellSize;\n const stride = resolvedCellSize + cellGap;\n\n const { grid, monthLabels } = useMemo(() => {\n const today = new Date();\n\n today.setHours(0, 0, 0, 0);\n\n // Align to start of current week\n const daysFromWeekStart = (today.getDay() - weekStartDay + 7) % 7;\n const lastWeekStart = new Date(today);\n\n lastWeekStart.setDate(today.getDate() - daysFromWeekStart);\n\n const firstDay = new Date(lastWeekStart);\n\n firstDay.setDate(lastWeekStart.getDate() - (visibleWeeks - 1) * 7);\n\n const gridResult: GridCell[][] = [];\n const labels: { col: number; month: string }[] = [];\n\n let lastMonth = -1;\n\n for (let col = 0; col < visibleWeeks; col++) {\n const colStart = new Date(firstDay);\n\n colStart.setDate(firstDay.getDate() + col * 7);\n\n // Month label when the column starts a new month\n if (colStart.getMonth() !== lastMonth) {\n labels.push({\n col,\n month: getShortMonth(colStart.getMonth(), monthFormatter),\n });\n lastMonth = colStart.getMonth();\n }\n\n const column: GridCell[] = [];\n\n for (let row = 0; row < 7; row++) {\n const date = new Date(firstDay);\n\n date.setDate(firstDay.getDate() + col * 7 + row);\n const future = date > today;\n const iso = dateToIso(date);\n const count = future ? 0 : (countMap.get(iso) ?? 0);\n const level =\n count === 0 ? 0 : Math.min(maxLevel, Math.ceil((count / maxCount) * maxLevel));\n\n column.push({ iso, count, level, future });\n }\n\n gridResult.push(column);\n }\n\n return { grid: gridResult, monthLabels: labels };\n }, [countMap, maxCount, maxLevel, visibleWeeks, weekStartDay, monthFormatter]);\n\n // Always label Mon(1), Wed(3), Fri(5) — rows shift with weekStartDay\n const labelRows = useMemo(\n () =>\n [1, 3, 5].map((dayIndex) => ({\n row: (dayIndex - weekStartDay + 7) % 7,\n label: getShortDay(dayIndex, weekdayFormatter),\n })),\n [weekStartDay, weekdayFormatter],\n );\n\n const svgWidth = dayLabelW + visibleWeeks * stride - cellGap;\n const svgHeight = monthLabelH + 7 * stride - cellGap;\n const cellRx = Math.min(4, Math.floor(resolvedCellSize / 3));\n\n useEffect(() => {\n setFocusedCell((current) => ({\n col: Math.min(visibleWeeks - 1, current.col),\n row: current.row,\n }));\n }, [visibleWeeks]);\n\n function focusCell(col: number, row: number) {\n const c = Math.max(0, Math.min(visibleWeeks - 1, col));\n const r = Math.max(0, Math.min(6, row));\n\n setFocusedCell({ col: c, row: r });\n svgRef.current?.querySelector<SVGRectElement>(`[data-col=\"${c}\"][data-row=\"${r}\"]`)?.focus();\n }\n\n function handleCellKey(e: KeyboardEvent, col: number, row: number) {\n const moves: Record<string, [number, number]> = {\n ArrowRight: [col + 1, row],\n ArrowLeft: [col - 1, row],\n ArrowDown: [col, row + 1],\n ArrowUp: [col, row - 1],\n };\n\n if (moves[e.key]) {\n e.preventDefault();\n focusCell(...moves[e.key]);\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const cell = grid[col]?.[row];\n\n if (cell && !cell.future) {\n onDayClick?.({ date: cell.iso, count: cell.count });\n }\n }\n }\n\n function handleMouseEnter(e: MouseEvent<SVGRectElement>, text: string) {\n setTooltipPosition(null);\n setTooltip({\n target: e.currentTarget,\n text,\n });\n }\n\n function hideTooltip() {\n setTooltip(null);\n setTooltipPosition(null);\n }\n\n function cellColor(cell: GridCell): string {\n if (cell.future) {\n return colors[0];\n }\n\n return colors[Math.min(cell.level, colors.length - 1)] ?? colors[colors.length - 1];\n }\n\n function cellTooltip(cell: GridCell): string {\n if (cell.future) {\n return fullDateLabel(cell.iso, fullDateFormatter);\n }\n\n const formattedDate = fullDateLabel(cell.iso, fullDateFormatter);\n\n return (\n tooltipContent?.({ date: cell.iso, count: cell.count }) ??\n `${cell.count} contribution${cell.count !== 1 ? 's' : ''} on ${formattedDate}`\n );\n }\n\n return (\n <div className={[styles.wrapper, className].filter(Boolean).join(' ')}>\n <div ref={graphViewportRef} className={styles.graphViewport}>\n <svg\n ref={svgRef}\n width={svgWidth}\n height={svgHeight}\n className={styles.svg}\n aria-label={ariaLabel}\n role=\"img\"\n data-cell-size={resolvedCellSize}\n data-visible-weeks={visibleWeeks}\n >\n {/* Month labels */}\n {showMonthLabels &&\n monthLabels.map(({ col, month }) => (\n <text key={`m-${col}`} x={dayLabelW + col * stride} y={12} className={styles.label}>\n {month}\n </text>\n ))}\n\n {/* Day-of-week labels: Mon, Wed, Fri */}\n {showDayLabels &&\n labelRows.map(({ row, label }) => (\n <text\n key={`d-${row}`}\n x={0}\n y={monthLabelH + row * stride + resolvedCellSize - 1}\n className={styles.label}\n >\n {label}\n </text>\n ))}\n\n {/* Activity grid */}\n <g role=\"grid\" aria-label={ariaLabel}>\n {grid.map((column, col) => (\n <g key={col} role=\"row\">\n {column.map((cell, row) => {\n const tipText = cellTooltip(cell);\n const isFocused = focusedCell.col === col && focusedCell.row === row;\n\n return (\n <rect\n key={`${col}-${row}`}\n data-col={col}\n data-row={row}\n x={dayLabelW + col * stride}\n y={monthLabelH + row * stride}\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={cellColor(cell)}\n opacity={cell.future ? 0.35 : 1}\n className={styles.cell}\n role=\"gridcell\"\n aria-label={tipText}\n aria-disabled={cell.future || undefined}\n tabIndex={isFocused ? 0 : -1}\n onClick={() =>\n !cell.future && onDayClick?.({ date: cell.iso, count: cell.count })\n }\n onKeyDown={(e) => handleCellKey(e, col, row)}\n onFocus={() => setFocusedCell({ col, row })}\n onMouseEnter={(e) => handleMouseEnter(e, tipText)}\n onMouseLeave={hideTooltip}\n />\n );\n })}\n </g>\n ))}\n </g>\n </svg>\n </div>\n\n {tooltip &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={tooltipRef}\n className={styles.tooltip}\n style={\n tooltipPosition\n ? { left: tooltipPosition.left, top: tooltipPosition.top }\n : { visibility: 'hidden', left: 0, top: 0 }\n }\n role=\"tooltip\"\n >\n {tooltip.text}\n </div>,\n document.body,\n )}\n\n {showLegend && (\n <div className={styles.legend}>\n <span className={styles.legendLabel}>Less</span>\n {Array.from({ length: maxLevel + 1 }, (_, i) => (\n <svg\n key={i}\n width={resolvedCellSize}\n height={resolvedCellSize}\n aria-hidden=\"true\"\n className={styles.legendCell}\n >\n <rect\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={colors[Math.min(i, colors.length - 1)]}\n />\n </svg>\n ))}\n <span className={styles.legendLabel}>More</span>\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -43,4 +43,4 @@ export interface ContributionGraphProps {
|
|
|
43
43
|
tooltipContent?: (day: ContributionDay) => string;
|
|
44
44
|
className?: string;
|
|
45
45
|
}
|
|
46
|
-
export declare
|
|
46
|
+
export declare const ContributionGraph: ({ data, maxLevel, cellSize, cellGap, responsive, minCellSize, maxCellSize, weekStartDay, showMonthLabels, showDayLabels, showLegend, weeks, ariaLabel, onDayClick, tooltipContent, className, }: ContributionGraphProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -40,7 +40,7 @@ function m(e) {
|
|
|
40
40
|
function h(e, t) {
|
|
41
41
|
return t.format(m(e));
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
var g = ({ data: d, maxLevel: m = 4, cellSize: g = 12, cellGap: _ = 3, responsive: v = !0, minCellSize: ae = 8, maxCellSize: oe = 24, weekStartDay: y = 1, showMonthLabels: b = !0, showDayLabels: x = !0, showLegend: se = !0, weeks: ce = 52, ariaLabel: S = "Contribution graph", onDayClick: C, tooltipContent: le, className: ue }) => {
|
|
44
44
|
let w = t({ month: "short" }), T = t({ weekday: "short" }), E = t({
|
|
45
45
|
weekday: "long",
|
|
46
46
|
year: "numeric",
|
|
@@ -313,7 +313,7 @@ function g({ data: d, maxLevel: m = 4, cellSize: g = 12, cellGap: _ = 3, respons
|
|
|
313
313
|
})
|
|
314
314
|
]
|
|
315
315
|
});
|
|
316
|
-
}
|
|
316
|
+
};
|
|
317
317
|
//#endregion
|
|
318
318
|
export { g as ContributionGraph };
|
|
319
319
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContributionGraph.js","names":[],"sources":["../../../src/components/ContributionGraph/ContributionGraph.tsx"],"sourcesContent":["import type { KeyboardEvent, MouseEvent } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { createPortal } from 'react-dom';\n\nimport {\n GnomeContext,\n type GnomeNamedAccentColor,\n useDateTimeFormatter,\n} from '../GnomeProvider/GnomeContext';\n\nimport styles from './ContributionGraph.module.css';\n\nexport interface ContributionDay {\n /** ISO 8601 date — \"YYYY-MM-DD\". */\n date: string;\n /** Non-negative activity count. */\n count: number;\n}\n\nexport interface ContributionGraphProps {\n /** Activity data. Days absent from the array are treated as count = 0. */\n data: ContributionDay[];\n /**\n * Number of intensity levels (excluding 0).\n * @default 4\n */\n maxLevel?: number;\n /** Cell side length in pixels. @default 12 */\n cellSize?: number;\n /** Gap between cells in pixels. @default 3 */\n cellGap?: number;\n /**\n * Fit the graph to its container by resizing cells and reducing visible\n * weeks when the configured range cannot stay legible.\n * @default true\n */\n responsive?: boolean;\n /** Smallest responsive cell side length in pixels. @default 8 */\n minCellSize?: number;\n /** Largest responsive cell side length in pixels. @default 24 */\n maxCellSize?: number;\n /** 0 = Sunday · 1 = Monday (GNOME locale default). @default 1 */\n weekStartDay?: 0 | 1;\n /** @default true */\n showMonthLabels?: boolean;\n /** @default true */\n showDayLabels?: boolean;\n /** @default true */\n showLegend?: boolean;\n /** Number of week columns to display. @default 52 */\n weeks?: number;\n /** @default \"Contribution graph\" */\n ariaLabel?: string;\n onDayClick?: (day: ContributionDay) => void;\n /** Returns a plain-text tooltip string for a day. */\n tooltipContent?: (day: ContributionDay) => string;\n className?: string;\n}\n\n// Reference Sunday: 2000-01-02 is a Sunday (day index 0)\nconst REF_SUNDAY = new Date(2000, 0, 2);\n\nfunction getShortMonth(monthIndex: number, formatter: Intl.DateTimeFormat): string {\n return formatter.format(new Date(2000, monthIndex));\n}\n\nfunction getShortDay(dayIndex: number, formatter: Intl.DateTimeFormat): string {\n const date = new Date(REF_SUNDAY);\n\n date.setDate(REF_SUNDAY.getDate() + dayIndex);\n\n return formatter.format(date);\n}\n\nconst DAY_LABEL_WIDTH = 28;\nconst MONTH_LABEL_HEIGHT = 20;\n\nconst NAMED_ACCENTS = new Set<GnomeNamedAccentColor>([\n 'blue',\n 'green',\n 'yellow',\n 'orange',\n 'red',\n 'purple',\n 'brown',\n]);\n\nfunction accentScale(accentColor: GnomeNamedAccentColor): string[] {\n return [\n 'var(--gnome-card-shade-color)',\n `var(--gnome-${accentColor}-1)`,\n `var(--gnome-${accentColor}-2)`,\n `var(--gnome-${accentColor}-4)`,\n `var(--gnome-${accentColor}-5)`,\n ];\n}\n\nfunction dateToIso(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n\n return `${y}-${m}-${d}`;\n}\n\nfunction isoToLocal(iso: string): Date {\n const [y, m, d] = iso.split('-').map(Number);\n\n return new Date(y, m - 1, d);\n}\n\nfunction fullDateLabel(iso: string, formatter: Intl.DateTimeFormat): string {\n return formatter.format(isoToLocal(iso));\n}\n\ninterface GridCell {\n iso: string;\n count: number;\n level: number;\n future: boolean;\n}\n\nexport function ContributionGraph({\n data,\n maxLevel = 4,\n cellSize = 12,\n cellGap = 3,\n responsive = true,\n minCellSize = 8,\n maxCellSize = 24,\n weekStartDay = 1,\n showMonthLabels = true,\n showDayLabels = true,\n showLegend = true,\n weeks = 52,\n ariaLabel = 'Contribution graph',\n onDayClick,\n tooltipContent,\n className,\n}: ContributionGraphProps) {\n const monthFormatter = useDateTimeFormatter({ month: 'short' });\n const weekdayFormatter = useDateTimeFormatter({ weekday: 'short' });\n const fullDateFormatter = useDateTimeFormatter({\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n const { accentColor } = useContext(GnomeContext);\n const graphAccent = NAMED_ACCENTS.has(accentColor as GnomeNamedAccentColor)\n ? (accentColor as GnomeNamedAccentColor)\n : 'green';\n const svgRef = useRef<SVGSVGElement>(null);\n const graphViewportRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const colors = useMemo(() => accentScale(graphAccent), [graphAccent]);\n\n const [availableWidth, setAvailableWidth] = useState<number | null>(null);\n const [focusedCell, setFocusedCell] = useState({ col: 0, row: 0 });\n const [tooltip, setTooltip] = useState<{\n target: SVGRectElement;\n text: string;\n } | null>(null);\n const [tooltipPosition, setTooltipPosition] = useState<{\n left: number;\n top: number;\n } | null>(null);\n\n useEffect(() => {\n if (!responsive) {\n return;\n }\n\n const viewport = graphViewportRef.current;\n\n if (!viewport) {\n return;\n }\n\n const updateWidth = () => {\n const width = viewport.clientWidth || viewport.getBoundingClientRect().width;\n\n if (width > 0) {\n setAvailableWidth(width);\n }\n };\n\n updateWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateWidth);\n\n return () => window.removeEventListener('resize', updateWidth);\n }\n\n const observer = new ResizeObserver(updateWidth);\n\n observer.observe(viewport);\n\n return () => observer.disconnect();\n }, [responsive]);\n\n useEffect(() => {\n if (!tooltip) {\n return;\n }\n\n const placeTooltip = () => {\n const tooltipNode = tooltipRef.current;\n\n if (!tooltipNode) {\n return;\n }\n\n const cellRect = tooltip.target.getBoundingClientRect();\n const tipRect = tooltipNode.getBoundingClientRect();\n const margin = 8;\n const gap = 6;\n const viewportWidth = document.documentElement.clientWidth || window.innerWidth;\n const viewportHeight = document.documentElement.clientHeight || window.innerHeight;\n const maxLeft = Math.max(margin, viewportWidth - tipRect.width - margin);\n const maxTop = Math.max(margin, viewportHeight - tipRect.height - margin);\n const centeredLeft = cellRect.left + cellRect.width / 2 - tipRect.width / 2;\n const aboveTop = cellRect.top - tipRect.height - gap;\n const preferredTop = aboveTop >= margin ? aboveTop : cellRect.bottom + gap;\n\n setTooltipPosition({\n left: Math.max(margin, Math.min(centeredLeft, maxLeft)),\n top: Math.max(margin, Math.min(preferredTop, maxTop)),\n });\n };\n\n placeTooltip();\n window.addEventListener('resize', placeTooltip);\n window.addEventListener('scroll', placeTooltip, { passive: true, capture: true });\n\n return () => {\n window.removeEventListener('resize', placeTooltip);\n window.removeEventListener('scroll', placeTooltip, { capture: true });\n };\n }, [tooltip]);\n\n const countMap = useMemo(() => {\n const map = new Map<string, number>();\n\n for (const d of data) {\n map.set(d.date, d.count);\n }\n\n return map;\n }, [data]);\n\n const maxCount = useMemo(() => Math.max(1, ...data.map((d) => d.count)), [data]);\n\n const dayLabelW = showDayLabels ? DAY_LABEL_WIDTH : 0;\n const monthLabelH = showMonthLabels ? MONTH_LABEL_HEIGHT : 0;\n const configuredWeeks = Math.max(1, Math.floor(weeks));\n const normalizedMinCellSize = Math.max(1, minCellSize);\n const normalizedMaxCellSize = Math.max(normalizedMinCellSize, maxCellSize);\n const fit = useMemo(() => {\n if (!responsive || availableWidth === null) {\n return { cellSize, weeks: configuredWeeks };\n }\n\n const gridWidth = Math.max(0, availableWidth - dayLabelW);\n const fittedCellSize = (gridWidth + cellGap) / configuredWeeks - cellGap;\n\n if (fittedCellSize >= normalizedMinCellSize) {\n return {\n cellSize: Math.min(normalizedMaxCellSize, fittedCellSize),\n weeks: configuredWeeks,\n };\n }\n\n const fittedWeeks = Math.floor((gridWidth + cellGap) / (normalizedMinCellSize + cellGap));\n\n return {\n cellSize: normalizedMinCellSize,\n weeks: Math.max(1, Math.min(configuredWeeks, fittedWeeks)),\n };\n }, [\n availableWidth,\n cellGap,\n cellSize,\n configuredWeeks,\n dayLabelW,\n normalizedMaxCellSize,\n normalizedMinCellSize,\n responsive,\n ]);\n const visibleWeeks = fit.weeks;\n const resolvedCellSize = fit.cellSize;\n const stride = resolvedCellSize + cellGap;\n\n const { grid, monthLabels } = useMemo(() => {\n const today = new Date();\n\n today.setHours(0, 0, 0, 0);\n\n // Align to start of current week\n const daysFromWeekStart = (today.getDay() - weekStartDay + 7) % 7;\n const lastWeekStart = new Date(today);\n\n lastWeekStart.setDate(today.getDate() - daysFromWeekStart);\n\n const firstDay = new Date(lastWeekStart);\n\n firstDay.setDate(lastWeekStart.getDate() - (visibleWeeks - 1) * 7);\n\n const gridResult: GridCell[][] = [];\n const labels: { col: number; month: string }[] = [];\n\n let lastMonth = -1;\n\n for (let col = 0; col < visibleWeeks; col++) {\n const colStart = new Date(firstDay);\n\n colStart.setDate(firstDay.getDate() + col * 7);\n\n // Month label when the column starts a new month\n if (colStart.getMonth() !== lastMonth) {\n labels.push({\n col,\n month: getShortMonth(colStart.getMonth(), monthFormatter),\n });\n lastMonth = colStart.getMonth();\n }\n\n const column: GridCell[] = [];\n\n for (let row = 0; row < 7; row++) {\n const date = new Date(firstDay);\n\n date.setDate(firstDay.getDate() + col * 7 + row);\n const future = date > today;\n const iso = dateToIso(date);\n const count = future ? 0 : (countMap.get(iso) ?? 0);\n const level =\n count === 0 ? 0 : Math.min(maxLevel, Math.ceil((count / maxCount) * maxLevel));\n\n column.push({ iso, count, level, future });\n }\n\n gridResult.push(column);\n }\n\n return { grid: gridResult, monthLabels: labels };\n }, [countMap, maxCount, maxLevel, visibleWeeks, weekStartDay, monthFormatter]);\n\n // Always label Mon(1), Wed(3), Fri(5) — rows shift with weekStartDay\n const labelRows = useMemo(\n () =>\n [1, 3, 5].map((dayIndex) => ({\n row: (dayIndex - weekStartDay + 7) % 7,\n label: getShortDay(dayIndex, weekdayFormatter),\n })),\n [weekStartDay, weekdayFormatter],\n );\n\n const svgWidth = dayLabelW + visibleWeeks * stride - cellGap;\n const svgHeight = monthLabelH + 7 * stride - cellGap;\n const cellRx = Math.min(4, Math.floor(resolvedCellSize / 3));\n\n useEffect(() => {\n setFocusedCell((current) => ({\n col: Math.min(visibleWeeks - 1, current.col),\n row: current.row,\n }));\n }, [visibleWeeks]);\n\n function focusCell(col: number, row: number) {\n const c = Math.max(0, Math.min(visibleWeeks - 1, col));\n const r = Math.max(0, Math.min(6, row));\n\n setFocusedCell({ col: c, row: r });\n svgRef.current?.querySelector<SVGRectElement>(`[data-col=\"${c}\"][data-row=\"${r}\"]`)?.focus();\n }\n\n function handleCellKey(e: KeyboardEvent, col: number, row: number) {\n const moves: Record<string, [number, number]> = {\n ArrowRight: [col + 1, row],\n ArrowLeft: [col - 1, row],\n ArrowDown: [col, row + 1],\n ArrowUp: [col, row - 1],\n };\n\n if (moves[e.key]) {\n e.preventDefault();\n focusCell(...moves[e.key]);\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const cell = grid[col]?.[row];\n\n if (cell && !cell.future) {\n onDayClick?.({ date: cell.iso, count: cell.count });\n }\n }\n }\n\n function handleMouseEnter(e: MouseEvent<SVGRectElement>, text: string) {\n setTooltipPosition(null);\n setTooltip({\n target: e.currentTarget,\n text,\n });\n }\n\n function hideTooltip() {\n setTooltip(null);\n setTooltipPosition(null);\n }\n\n function cellColor(cell: GridCell): string {\n if (cell.future) {\n return colors[0];\n }\n\n return colors[Math.min(cell.level, colors.length - 1)] ?? colors[colors.length - 1];\n }\n\n function cellTooltip(cell: GridCell): string {\n if (cell.future) {\n return fullDateLabel(cell.iso, fullDateFormatter);\n }\n\n const formattedDate = fullDateLabel(cell.iso, fullDateFormatter);\n\n return (\n tooltipContent?.({ date: cell.iso, count: cell.count }) ??\n `${cell.count} contribution${cell.count !== 1 ? 's' : ''} on ${formattedDate}`\n );\n }\n\n return (\n <div className={[styles.wrapper, className].filter(Boolean).join(' ')}>\n <div ref={graphViewportRef} className={styles.graphViewport}>\n <svg\n ref={svgRef}\n width={svgWidth}\n height={svgHeight}\n className={styles.svg}\n aria-label={ariaLabel}\n role=\"img\"\n data-cell-size={resolvedCellSize}\n data-visible-weeks={visibleWeeks}\n >\n {/* Month labels */}\n {showMonthLabels &&\n monthLabels.map(({ col, month }) => (\n <text key={`m-${col}`} x={dayLabelW + col * stride} y={12} className={styles.label}>\n {month}\n </text>\n ))}\n\n {/* Day-of-week labels: Mon, Wed, Fri */}\n {showDayLabels &&\n labelRows.map(({ row, label }) => (\n <text\n key={`d-${row}`}\n x={0}\n y={monthLabelH + row * stride + resolvedCellSize - 1}\n className={styles.label}\n >\n {label}\n </text>\n ))}\n\n {/* Activity grid */}\n <g role=\"grid\" aria-label={ariaLabel}>\n {grid.map((column, col) => (\n <g key={col} role=\"row\">\n {column.map((cell, row) => {\n const tipText = cellTooltip(cell);\n const isFocused = focusedCell.col === col && focusedCell.row === row;\n\n return (\n <rect\n key={`${col}-${row}`}\n data-col={col}\n data-row={row}\n x={dayLabelW + col * stride}\n y={monthLabelH + row * stride}\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={cellColor(cell)}\n opacity={cell.future ? 0.35 : 1}\n className={styles.cell}\n role=\"gridcell\"\n aria-label={tipText}\n aria-disabled={cell.future || undefined}\n tabIndex={isFocused ? 0 : -1}\n onClick={() =>\n !cell.future && onDayClick?.({ date: cell.iso, count: cell.count })\n }\n onKeyDown={(e) => handleCellKey(e, col, row)}\n onFocus={() => setFocusedCell({ col, row })}\n onMouseEnter={(e) => handleMouseEnter(e, tipText)}\n onMouseLeave={hideTooltip}\n />\n );\n })}\n </g>\n ))}\n </g>\n </svg>\n </div>\n\n {tooltip &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={tooltipRef}\n className={styles.tooltip}\n style={\n tooltipPosition\n ? { left: tooltipPosition.left, top: tooltipPosition.top }\n : { visibility: 'hidden', left: 0, top: 0 }\n }\n role=\"tooltip\"\n >\n {tooltip.text}\n </div>,\n document.body,\n )}\n\n {showLegend && (\n <div className={styles.legend}>\n <span className={styles.legendLabel}>Less</span>\n {Array.from({ length: maxLevel + 1 }, (_, i) => (\n <svg\n key={i}\n width={resolvedCellSize}\n height={resolvedCellSize}\n aria-hidden=\"true\"\n className={styles.legendCell}\n >\n <rect\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={colors[Math.min(i, colors.length - 1)]}\n />\n </svg>\n ))}\n <span className={styles.legendLabel}>More</span>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ContributionGraph.js","names":[],"sources":["../../../src/components/ContributionGraph/ContributionGraph.tsx"],"sourcesContent":["import type { KeyboardEvent, MouseEvent } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { createPortal } from 'react-dom';\n\nimport {\n GnomeContext,\n type GnomeNamedAccentColor,\n useDateTimeFormatter,\n} from '../GnomeProvider/GnomeContext';\n\nimport styles from './ContributionGraph.module.css';\n\nexport interface ContributionDay {\n /** ISO 8601 date — \"YYYY-MM-DD\". */\n date: string;\n /** Non-negative activity count. */\n count: number;\n}\n\nexport interface ContributionGraphProps {\n /** Activity data. Days absent from the array are treated as count = 0. */\n data: ContributionDay[];\n /**\n * Number of intensity levels (excluding 0).\n * @default 4\n */\n maxLevel?: number;\n /** Cell side length in pixels. @default 12 */\n cellSize?: number;\n /** Gap between cells in pixels. @default 3 */\n cellGap?: number;\n /**\n * Fit the graph to its container by resizing cells and reducing visible\n * weeks when the configured range cannot stay legible.\n * @default true\n */\n responsive?: boolean;\n /** Smallest responsive cell side length in pixels. @default 8 */\n minCellSize?: number;\n /** Largest responsive cell side length in pixels. @default 24 */\n maxCellSize?: number;\n /** 0 = Sunday · 1 = Monday (GNOME locale default). @default 1 */\n weekStartDay?: 0 | 1;\n /** @default true */\n showMonthLabels?: boolean;\n /** @default true */\n showDayLabels?: boolean;\n /** @default true */\n showLegend?: boolean;\n /** Number of week columns to display. @default 52 */\n weeks?: number;\n /** @default \"Contribution graph\" */\n ariaLabel?: string;\n onDayClick?: (day: ContributionDay) => void;\n /** Returns a plain-text tooltip string for a day. */\n tooltipContent?: (day: ContributionDay) => string;\n className?: string;\n}\n\n// Reference Sunday: 2000-01-02 is a Sunday (day index 0)\nconst REF_SUNDAY = new Date(2000, 0, 2);\n\nfunction getShortMonth(monthIndex: number, formatter: Intl.DateTimeFormat): string {\n return formatter.format(new Date(2000, monthIndex));\n}\n\nfunction getShortDay(dayIndex: number, formatter: Intl.DateTimeFormat): string {\n const date = new Date(REF_SUNDAY);\n\n date.setDate(REF_SUNDAY.getDate() + dayIndex);\n\n return formatter.format(date);\n}\n\nconst DAY_LABEL_WIDTH = 28;\nconst MONTH_LABEL_HEIGHT = 20;\n\nconst NAMED_ACCENTS = new Set<GnomeNamedAccentColor>([\n 'blue',\n 'green',\n 'yellow',\n 'orange',\n 'red',\n 'purple',\n 'brown',\n]);\n\nfunction accentScale(accentColor: GnomeNamedAccentColor): string[] {\n return [\n 'var(--gnome-card-shade-color)',\n `var(--gnome-${accentColor}-1)`,\n `var(--gnome-${accentColor}-2)`,\n `var(--gnome-${accentColor}-4)`,\n `var(--gnome-${accentColor}-5)`,\n ];\n}\n\nfunction dateToIso(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n\n return `${y}-${m}-${d}`;\n}\n\nfunction isoToLocal(iso: string): Date {\n const [y, m, d] = iso.split('-').map(Number);\n\n return new Date(y, m - 1, d);\n}\n\nfunction fullDateLabel(iso: string, formatter: Intl.DateTimeFormat): string {\n return formatter.format(isoToLocal(iso));\n}\n\ninterface GridCell {\n iso: string;\n count: number;\n level: number;\n future: boolean;\n}\n\nexport const ContributionGraph = ({\n data,\n maxLevel = 4,\n cellSize = 12,\n cellGap = 3,\n responsive = true,\n minCellSize = 8,\n maxCellSize = 24,\n weekStartDay = 1,\n showMonthLabels = true,\n showDayLabels = true,\n showLegend = true,\n weeks = 52,\n ariaLabel = 'Contribution graph',\n onDayClick,\n tooltipContent,\n className,\n}: ContributionGraphProps) => {\n const monthFormatter = useDateTimeFormatter({ month: 'short' });\n const weekdayFormatter = useDateTimeFormatter({ weekday: 'short' });\n const fullDateFormatter = useDateTimeFormatter({\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n const { accentColor } = useContext(GnomeContext);\n const graphAccent = NAMED_ACCENTS.has(accentColor as GnomeNamedAccentColor)\n ? (accentColor as GnomeNamedAccentColor)\n : 'green';\n const svgRef = useRef<SVGSVGElement>(null);\n const graphViewportRef = useRef<HTMLDivElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const colors = useMemo(() => accentScale(graphAccent), [graphAccent]);\n\n const [availableWidth, setAvailableWidth] = useState<number | null>(null);\n const [focusedCell, setFocusedCell] = useState({ col: 0, row: 0 });\n const [tooltip, setTooltip] = useState<{\n target: SVGRectElement;\n text: string;\n } | null>(null);\n const [tooltipPosition, setTooltipPosition] = useState<{\n left: number;\n top: number;\n } | null>(null);\n\n useEffect(() => {\n if (!responsive) {\n return;\n }\n\n const viewport = graphViewportRef.current;\n\n if (!viewport) {\n return;\n }\n\n const updateWidth = () => {\n const width = viewport.clientWidth || viewport.getBoundingClientRect().width;\n\n if (width > 0) {\n setAvailableWidth(width);\n }\n };\n\n updateWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateWidth);\n\n return () => window.removeEventListener('resize', updateWidth);\n }\n\n const observer = new ResizeObserver(updateWidth);\n\n observer.observe(viewport);\n\n return () => observer.disconnect();\n }, [responsive]);\n\n useEffect(() => {\n if (!tooltip) {\n return;\n }\n\n const placeTooltip = () => {\n const tooltipNode = tooltipRef.current;\n\n if (!tooltipNode) {\n return;\n }\n\n const cellRect = tooltip.target.getBoundingClientRect();\n const tipRect = tooltipNode.getBoundingClientRect();\n const margin = 8;\n const gap = 6;\n const viewportWidth = document.documentElement.clientWidth || window.innerWidth;\n const viewportHeight = document.documentElement.clientHeight || window.innerHeight;\n const maxLeft = Math.max(margin, viewportWidth - tipRect.width - margin);\n const maxTop = Math.max(margin, viewportHeight - tipRect.height - margin);\n const centeredLeft = cellRect.left + cellRect.width / 2 - tipRect.width / 2;\n const aboveTop = cellRect.top - tipRect.height - gap;\n const preferredTop = aboveTop >= margin ? aboveTop : cellRect.bottom + gap;\n\n setTooltipPosition({\n left: Math.max(margin, Math.min(centeredLeft, maxLeft)),\n top: Math.max(margin, Math.min(preferredTop, maxTop)),\n });\n };\n\n placeTooltip();\n window.addEventListener('resize', placeTooltip);\n window.addEventListener('scroll', placeTooltip, { passive: true, capture: true });\n\n return () => {\n window.removeEventListener('resize', placeTooltip);\n window.removeEventListener('scroll', placeTooltip, { capture: true });\n };\n }, [tooltip]);\n\n const countMap = useMemo(() => {\n const map = new Map<string, number>();\n\n for (const d of data) {\n map.set(d.date, d.count);\n }\n\n return map;\n }, [data]);\n\n const maxCount = useMemo(() => Math.max(1, ...data.map((d) => d.count)), [data]);\n\n const dayLabelW = showDayLabels ? DAY_LABEL_WIDTH : 0;\n const monthLabelH = showMonthLabels ? MONTH_LABEL_HEIGHT : 0;\n const configuredWeeks = Math.max(1, Math.floor(weeks));\n const normalizedMinCellSize = Math.max(1, minCellSize);\n const normalizedMaxCellSize = Math.max(normalizedMinCellSize, maxCellSize);\n const fit = useMemo(() => {\n if (!responsive || availableWidth === null) {\n return { cellSize, weeks: configuredWeeks };\n }\n\n const gridWidth = Math.max(0, availableWidth - dayLabelW);\n const fittedCellSize = (gridWidth + cellGap) / configuredWeeks - cellGap;\n\n if (fittedCellSize >= normalizedMinCellSize) {\n return {\n cellSize: Math.min(normalizedMaxCellSize, fittedCellSize),\n weeks: configuredWeeks,\n };\n }\n\n const fittedWeeks = Math.floor((gridWidth + cellGap) / (normalizedMinCellSize + cellGap));\n\n return {\n cellSize: normalizedMinCellSize,\n weeks: Math.max(1, Math.min(configuredWeeks, fittedWeeks)),\n };\n }, [\n availableWidth,\n cellGap,\n cellSize,\n configuredWeeks,\n dayLabelW,\n normalizedMaxCellSize,\n normalizedMinCellSize,\n responsive,\n ]);\n const visibleWeeks = fit.weeks;\n const resolvedCellSize = fit.cellSize;\n const stride = resolvedCellSize + cellGap;\n\n const { grid, monthLabels } = useMemo(() => {\n const today = new Date();\n\n today.setHours(0, 0, 0, 0);\n\n // Align to start of current week\n const daysFromWeekStart = (today.getDay() - weekStartDay + 7) % 7;\n const lastWeekStart = new Date(today);\n\n lastWeekStart.setDate(today.getDate() - daysFromWeekStart);\n\n const firstDay = new Date(lastWeekStart);\n\n firstDay.setDate(lastWeekStart.getDate() - (visibleWeeks - 1) * 7);\n\n const gridResult: GridCell[][] = [];\n const labels: { col: number; month: string }[] = [];\n\n let lastMonth = -1;\n\n for (let col = 0; col < visibleWeeks; col++) {\n const colStart = new Date(firstDay);\n\n colStart.setDate(firstDay.getDate() + col * 7);\n\n // Month label when the column starts a new month\n if (colStart.getMonth() !== lastMonth) {\n labels.push({\n col,\n month: getShortMonth(colStart.getMonth(), monthFormatter),\n });\n lastMonth = colStart.getMonth();\n }\n\n const column: GridCell[] = [];\n\n for (let row = 0; row < 7; row++) {\n const date = new Date(firstDay);\n\n date.setDate(firstDay.getDate() + col * 7 + row);\n const future = date > today;\n const iso = dateToIso(date);\n const count = future ? 0 : (countMap.get(iso) ?? 0);\n const level =\n count === 0 ? 0 : Math.min(maxLevel, Math.ceil((count / maxCount) * maxLevel));\n\n column.push({ iso, count, level, future });\n }\n\n gridResult.push(column);\n }\n\n return { grid: gridResult, monthLabels: labels };\n }, [countMap, maxCount, maxLevel, visibleWeeks, weekStartDay, monthFormatter]);\n\n // Always label Mon(1), Wed(3), Fri(5) — rows shift with weekStartDay\n const labelRows = useMemo(\n () =>\n [1, 3, 5].map((dayIndex) => ({\n row: (dayIndex - weekStartDay + 7) % 7,\n label: getShortDay(dayIndex, weekdayFormatter),\n })),\n [weekStartDay, weekdayFormatter],\n );\n\n const svgWidth = dayLabelW + visibleWeeks * stride - cellGap;\n const svgHeight = monthLabelH + 7 * stride - cellGap;\n const cellRx = Math.min(4, Math.floor(resolvedCellSize / 3));\n\n useEffect(() => {\n setFocusedCell((current) => ({\n col: Math.min(visibleWeeks - 1, current.col),\n row: current.row,\n }));\n }, [visibleWeeks]);\n\n function focusCell(col: number, row: number) {\n const c = Math.max(0, Math.min(visibleWeeks - 1, col));\n const r = Math.max(0, Math.min(6, row));\n\n setFocusedCell({ col: c, row: r });\n svgRef.current?.querySelector<SVGRectElement>(`[data-col=\"${c}\"][data-row=\"${r}\"]`)?.focus();\n }\n\n function handleCellKey(e: KeyboardEvent, col: number, row: number) {\n const moves: Record<string, [number, number]> = {\n ArrowRight: [col + 1, row],\n ArrowLeft: [col - 1, row],\n ArrowDown: [col, row + 1],\n ArrowUp: [col, row - 1],\n };\n\n if (moves[e.key]) {\n e.preventDefault();\n focusCell(...moves[e.key]);\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const cell = grid[col]?.[row];\n\n if (cell && !cell.future) {\n onDayClick?.({ date: cell.iso, count: cell.count });\n }\n }\n }\n\n function handleMouseEnter(e: MouseEvent<SVGRectElement>, text: string) {\n setTooltipPosition(null);\n setTooltip({\n target: e.currentTarget,\n text,\n });\n }\n\n function hideTooltip() {\n setTooltip(null);\n setTooltipPosition(null);\n }\n\n function cellColor(cell: GridCell): string {\n if (cell.future) {\n return colors[0];\n }\n\n return colors[Math.min(cell.level, colors.length - 1)] ?? colors[colors.length - 1];\n }\n\n function cellTooltip(cell: GridCell): string {\n if (cell.future) {\n return fullDateLabel(cell.iso, fullDateFormatter);\n }\n\n const formattedDate = fullDateLabel(cell.iso, fullDateFormatter);\n\n return (\n tooltipContent?.({ date: cell.iso, count: cell.count }) ??\n `${cell.count} contribution${cell.count !== 1 ? 's' : ''} on ${formattedDate}`\n );\n }\n\n return (\n <div className={[styles.wrapper, className].filter(Boolean).join(' ')}>\n <div ref={graphViewportRef} className={styles.graphViewport}>\n <svg\n ref={svgRef}\n width={svgWidth}\n height={svgHeight}\n className={styles.svg}\n aria-label={ariaLabel}\n role=\"img\"\n data-cell-size={resolvedCellSize}\n data-visible-weeks={visibleWeeks}\n >\n {/* Month labels */}\n {showMonthLabels &&\n monthLabels.map(({ col, month }) => (\n <text key={`m-${col}`} x={dayLabelW + col * stride} y={12} className={styles.label}>\n {month}\n </text>\n ))}\n\n {/* Day-of-week labels: Mon, Wed, Fri */}\n {showDayLabels &&\n labelRows.map(({ row, label }) => (\n <text\n key={`d-${row}`}\n x={0}\n y={monthLabelH + row * stride + resolvedCellSize - 1}\n className={styles.label}\n >\n {label}\n </text>\n ))}\n\n {/* Activity grid */}\n <g role=\"grid\" aria-label={ariaLabel}>\n {grid.map((column, col) => (\n <g key={col} role=\"row\">\n {column.map((cell, row) => {\n const tipText = cellTooltip(cell);\n const isFocused = focusedCell.col === col && focusedCell.row === row;\n\n return (\n <rect\n key={`${col}-${row}`}\n data-col={col}\n data-row={row}\n x={dayLabelW + col * stride}\n y={monthLabelH + row * stride}\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={cellColor(cell)}\n opacity={cell.future ? 0.35 : 1}\n className={styles.cell}\n role=\"gridcell\"\n aria-label={tipText}\n aria-disabled={cell.future || undefined}\n tabIndex={isFocused ? 0 : -1}\n onClick={() =>\n !cell.future && onDayClick?.({ date: cell.iso, count: cell.count })\n }\n onKeyDown={(e) => handleCellKey(e, col, row)}\n onFocus={() => setFocusedCell({ col, row })}\n onMouseEnter={(e) => handleMouseEnter(e, tipText)}\n onMouseLeave={hideTooltip}\n />\n );\n })}\n </g>\n ))}\n </g>\n </svg>\n </div>\n\n {tooltip &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={tooltipRef}\n className={styles.tooltip}\n style={\n tooltipPosition\n ? { left: tooltipPosition.left, top: tooltipPosition.top }\n : { visibility: 'hidden', left: 0, top: 0 }\n }\n role=\"tooltip\"\n >\n {tooltip.text}\n </div>,\n document.body,\n )}\n\n {showLegend && (\n <div className={styles.legend}>\n <span className={styles.legendLabel}>Less</span>\n {Array.from({ length: maxLevel + 1 }, (_, i) => (\n <svg\n key={i}\n width={resolvedCellSize}\n height={resolvedCellSize}\n aria-hidden=\"true\"\n className={styles.legendCell}\n >\n <rect\n width={resolvedCellSize}\n height={resolvedCellSize}\n rx={cellRx}\n fill={colors[Math.min(i, colors.length - 1)]}\n />\n </svg>\n ))}\n <span className={styles.legendLabel}>More</span>\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./ContributionGraph/ContributionGraph.cjs");exports.ContributionGraph=e.ContributionGraph;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require("../GnomeProvider/GnomeContext.cjs"),t=require("./CountDownTimer.module.css.cjs");let n=require("react"),r=require("react/jsx-runtime");var i=({start:i,end:a,format:o=`time`,variant:s=`accent`,action:c,className:l,...u})=>{let d=e.useDateTimeFormatter(),[f,p]=(0,n.useState)(null),[m,h]=(0,n.useState)(!1);if((0,n.useEffect)(()=>{let e=()=>{let e=new Date,t=new Date(a).getTime()-e.getTime();return t<=0?{days:0,hours:0,minutes:0,seconds:0,isFinished:!0}:{days:Math.floor(t/(1e3*60*60*24)),hours:Math.floor(t/(1e3*60*60)%24),minutes:Math.floor(t/1e3/60%60),seconds:Math.floor(t/1e3%60),isFinished:!1}};p(e());let t=setInterval(()=>{let t=e();p(t),t.isFinished&&!m&&(c?.(),h(!0))},1e3);return()=>clearInterval(t)},[a,c,m]),!f)return null;let g=()=>{if(o===`date`){let e=new Date(a);return d.format(e)}let{days:e,hours:t,minutes:n,seconds:r,isFinished:i}=f;if(i)return`00:00:00`;if(o===`datetime`){let e=new Date(a);return`${d.format(e)} ${`${String(t).padStart(2,`0`)}:${String(n).padStart(2,`0`)}:${String(r).padStart(2,`0`)}`}`}return e>0?`${e}d ${String(t).padStart(2,`0`)}h ${String(n).padStart(2,`0`)}m`:`${String(t).padStart(2,`0`)}:${String(n).padStart(2,`0`)}:${String(r).padStart(2,`0`)}`},_=f.isFinished?`destructive`:s;return(0,r.jsx)(`div`,{className:[t.default.countdownTimer,t.default[_],f.isFinished?t.default.finished:null,l].filter(Boolean).join(` `),...u,children:(0,r.jsx)(`span`,{className:t.default.value,children:g()})})};exports.CountDownTimer=i;
|
|
2
2
|
//# sourceMappingURL=CountDownTimer.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CountDownTimer.cjs","names":[],"sources":["../../../src/components/CountDownTimer/CountDownTimer.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { useEffect, useState } from 'react';\n\nimport { useDateTimeFormatter } from '../GnomeProvider/GnomeContext';\n\nimport styles from './CountDownTimer.module.css';\n\nexport type CountDownVariant = 'accent' | 'destructive' | 'success' | 'warning';\n\nexport interface CountDownTimerProps extends HTMLAttributes<HTMLDivElement> {\n /** Start date for the countdown */\n start: Date;\n /** End date for the countdown */\n end: Date;\n /** Format to display: \"date\", \"time\", or \"datetime\" */\n format?: 'date' | 'time' | 'datetime';\n /** Visual style variant. Defaults to `\"accent\"`. */\n variant?: CountDownVariant;\n /** Callback action to execute when countdown reaches zero */\n action?: () => void;\n}\n\ninterface TimeRemaining {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n isFinished: boolean;\n}\n\n/**\n * CountDown timer component that displays remaining time and executes an action when time runs out.\n *\n * @see https://developer.gnome.org/hig/patterns/\n */\nexport
|
|
1
|
+
{"version":3,"file":"CountDownTimer.cjs","names":[],"sources":["../../../src/components/CountDownTimer/CountDownTimer.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { useEffect, useState } from 'react';\n\nimport { useDateTimeFormatter } from '../GnomeProvider/GnomeContext';\n\nimport styles from './CountDownTimer.module.css';\n\nexport type CountDownVariant = 'accent' | 'destructive' | 'success' | 'warning';\n\nexport interface CountDownTimerProps extends HTMLAttributes<HTMLDivElement> {\n /** Start date for the countdown */\n start: Date;\n /** End date for the countdown */\n end: Date;\n /** Format to display: \"date\", \"time\", or \"datetime\" */\n format?: 'date' | 'time' | 'datetime';\n /** Visual style variant. Defaults to `\"accent\"`. */\n variant?: CountDownVariant;\n /** Callback action to execute when countdown reaches zero */\n action?: () => void;\n}\n\ninterface TimeRemaining {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n isFinished: boolean;\n}\n\n/**\n * CountDown timer component that displays remaining time and executes an action when time runs out.\n *\n * @see https://developer.gnome.org/hig/patterns/\n */\nexport const CountDownTimer = ({\n start: _start,\n end,\n format = 'time',\n variant = 'accent',\n action,\n className,\n ...props\n}: CountDownTimerProps) => {\n const dateFormatter = useDateTimeFormatter();\n const [timeRemaining, setTimeRemaining] = useState<TimeRemaining | null>(null);\n const [hasExecutedAction, setHasExecutedAction] = useState(false);\n\n useEffect(() => {\n const calculateTimeRemaining = (): TimeRemaining => {\n const now = new Date();\n const endTime = new Date(end).getTime();\n const nowTime = now.getTime();\n const difference = endTime - nowTime;\n\n if (difference <= 0) {\n return {\n days: 0,\n hours: 0,\n minutes: 0,\n seconds: 0,\n isFinished: true,\n };\n }\n\n const days = Math.floor(difference / (1000 * 60 * 60 * 24));\n const hours = Math.floor((difference / (1000 * 60 * 60)) % 24);\n const minutes = Math.floor((difference / 1000 / 60) % 60);\n const seconds = Math.floor((difference / 1000) % 60);\n\n return {\n days,\n hours,\n minutes,\n seconds,\n isFinished: false,\n };\n };\n\n // Initial calculation\n setTimeRemaining(calculateTimeRemaining());\n\n // Update every second\n const interval = setInterval(() => {\n const remaining = calculateTimeRemaining();\n\n setTimeRemaining(remaining);\n\n // Execute action when countdown finishes\n if (remaining.isFinished && !hasExecutedAction) {\n action?.();\n setHasExecutedAction(true);\n }\n }, 1000);\n\n return () => clearInterval(interval);\n }, [end, action, hasExecutedAction]);\n\n if (!timeRemaining) {\n return null;\n }\n\n const formatTime = (): string => {\n if (format === 'date') {\n const endDate = new Date(end);\n\n return dateFormatter.format(endDate);\n }\n\n const { days, hours, minutes, seconds, isFinished } = timeRemaining;\n\n if (isFinished) {\n return '00:00:00';\n }\n\n if (format === 'datetime') {\n const endDate = new Date(end);\n const dateString = dateFormatter.format(endDate);\n const timeString = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n\n return `${dateString} ${timeString}`;\n }\n\n if (days > 0) {\n return `${days}d ${String(hours).padStart(2, '0')}h ${String(minutes).padStart(2, '0')}m`;\n }\n\n return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n };\n\n const displayVariant = timeRemaining.isFinished ? 'destructive' : variant;\n\n return (\n <div\n className={[\n styles.countdownTimer,\n styles[displayVariant],\n timeRemaining.isFinished ? styles.finished : null,\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n <span className={styles.value}>{formatTime()}</span>\n </div>\n );\n};\n"],"mappings":"wJAmCA,IAAa,GAAkB,CAC7B,MAAO,EACP,MACA,SAAS,OACT,UAAU,SACV,SACA,YACA,GAAG,KACsB,CACzB,IAAM,EAAgB,EAAA,qBAAqB,EACrC,CAAC,EAAe,IAAA,EAAA,EAAA,UAAmD,IAAI,EACvE,CAAC,EAAmB,IAAA,EAAA,EAAA,UAAiC,EAAK,EAoDhE,IAlDA,EAAA,EAAA,eAAgB,CACd,IAAM,MAA8C,CAClD,IAAM,EAAM,IAAI,KAGV,EAFU,IAAI,KAAK,CAAG,EAAE,QAEX,EADH,EAAI,QACS,EAiB7B,OAfI,GAAc,EACT,CACL,KAAM,EACN,MAAO,EACP,QAAS,EACT,QAAS,EACT,WAAY,EACd,EAQK,CACL,KANW,KAAK,MAAM,GAAc,IAAO,GAAK,GAAK,GAMrD,EACA,MANY,KAAK,MAAO,GAAc,IAAO,GAAK,IAAO,EAMzD,EACA,QANc,KAAK,MAAO,EAAa,IAAO,GAAM,EAMpD,EACA,QANc,KAAK,MAAO,EAAa,IAAQ,EAM/C,EACA,WAAY,EACd,CACF,EAGA,EAAiB,EAAuB,CAAC,EAGzC,IAAM,EAAW,gBAAkB,CACjC,IAAM,EAAY,EAAuB,EAEzC,EAAiB,CAAS,EAGtB,EAAU,YAAc,CAAC,IAC3B,IAAS,EACT,EAAqB,EAAI,EAE7B,EAAG,GAAI,EAEP,UAAa,cAAc,CAAQ,CACrC,EAAG,CAAC,EAAK,EAAQ,CAAiB,CAAC,EAE/B,CAAC,EACH,OAAO,KAGT,IAAM,MAA2B,CAC/B,GAAI,IAAW,OAAQ,CACrB,IAAM,EAAU,IAAI,KAAK,CAAG,EAE5B,OAAO,EAAc,OAAO,CAAO,CACrC,CAEA,GAAM,CAAE,OAAM,QAAO,UAAS,UAAS,cAAe,EAEtD,GAAI,EACF,MAAO,WAGT,GAAI,IAAW,WAAY,CACzB,IAAM,EAAU,IAAI,KAAK,CAAG,EAI5B,MAAO,GAHY,EAAc,OAAO,CAG9B,EAAW,GAAG,GAFF,OAAO,CAAK,EAAE,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,EAAG,GAAG,KAG7H,CAMA,OAJI,EAAO,EACF,GAAG,EAAK,IAAI,OAAO,CAAK,EAAE,SAAS,EAAG,GAAG,EAAE,IAAI,OAAO,CAAO,EAAE,SAAS,EAAG,GAAG,EAAE,GAGlF,GAAG,OAAO,CAAK,EAAE,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,EAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,EAAG,GAAG,GACjH,EAEM,EAAiB,EAAc,WAAa,cAAgB,EAElE,OACE,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,CACT,EAAA,QAAO,eACP,EAAA,QAAO,GACP,EAAc,WAAa,EAAA,QAAO,SAAW,KAC7C,CACF,EACG,OAAO,OAAO,EACd,KAAK,GAAG,EACX,GAAI,YAEJ,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,EAAW,CAAQ,CAAA,CAChD,CAAA,CAET"}
|
|
@@ -17,4 +17,4 @@ export interface CountDownTimerProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
17
17
|
*
|
|
18
18
|
* @see https://developer.gnome.org/hig/patterns/
|
|
19
19
|
*/
|
|
20
|
-
export declare
|
|
20
|
+
export declare const CountDownTimer: ({ start: _start, end, format, variant, action, className, ...props }: CountDownTimerProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -3,7 +3,7 @@ import t from "./CountDownTimer.module.css.js";
|
|
|
3
3
|
import { useEffect as n, useState as r } from "react";
|
|
4
4
|
import { jsx as i } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/CountDownTimer/CountDownTimer.tsx
|
|
6
|
-
|
|
6
|
+
var a = ({ start: a, end: o, format: s = "time", variant: c = "accent", action: l, className: u, ...d }) => {
|
|
7
7
|
let f = e(), [p, m] = r(null), [h, g] = r(!1);
|
|
8
8
|
if (n(() => {
|
|
9
9
|
let e = () => {
|
|
@@ -59,7 +59,7 @@ function a({ start: a, end: o, format: s = "time", variant: c = "accent", action
|
|
|
59
59
|
children: _()
|
|
60
60
|
})
|
|
61
61
|
});
|
|
62
|
-
}
|
|
62
|
+
};
|
|
63
63
|
//#endregion
|
|
64
64
|
export { a as CountDownTimer };
|
|
65
65
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CountDownTimer.js","names":[],"sources":["../../../src/components/CountDownTimer/CountDownTimer.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { useEffect, useState } from 'react';\n\nimport { useDateTimeFormatter } from '../GnomeProvider/GnomeContext';\n\nimport styles from './CountDownTimer.module.css';\n\nexport type CountDownVariant = 'accent' | 'destructive' | 'success' | 'warning';\n\nexport interface CountDownTimerProps extends HTMLAttributes<HTMLDivElement> {\n /** Start date for the countdown */\n start: Date;\n /** End date for the countdown */\n end: Date;\n /** Format to display: \"date\", \"time\", or \"datetime\" */\n format?: 'date' | 'time' | 'datetime';\n /** Visual style variant. Defaults to `\"accent\"`. */\n variant?: CountDownVariant;\n /** Callback action to execute when countdown reaches zero */\n action?: () => void;\n}\n\ninterface TimeRemaining {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n isFinished: boolean;\n}\n\n/**\n * CountDown timer component that displays remaining time and executes an action when time runs out.\n *\n * @see https://developer.gnome.org/hig/patterns/\n */\nexport
|
|
1
|
+
{"version":3,"file":"CountDownTimer.js","names":[],"sources":["../../../src/components/CountDownTimer/CountDownTimer.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { useEffect, useState } from 'react';\n\nimport { useDateTimeFormatter } from '../GnomeProvider/GnomeContext';\n\nimport styles from './CountDownTimer.module.css';\n\nexport type CountDownVariant = 'accent' | 'destructive' | 'success' | 'warning';\n\nexport interface CountDownTimerProps extends HTMLAttributes<HTMLDivElement> {\n /** Start date for the countdown */\n start: Date;\n /** End date for the countdown */\n end: Date;\n /** Format to display: \"date\", \"time\", or \"datetime\" */\n format?: 'date' | 'time' | 'datetime';\n /** Visual style variant. Defaults to `\"accent\"`. */\n variant?: CountDownVariant;\n /** Callback action to execute when countdown reaches zero */\n action?: () => void;\n}\n\ninterface TimeRemaining {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n isFinished: boolean;\n}\n\n/**\n * CountDown timer component that displays remaining time and executes an action when time runs out.\n *\n * @see https://developer.gnome.org/hig/patterns/\n */\nexport const CountDownTimer = ({\n start: _start,\n end,\n format = 'time',\n variant = 'accent',\n action,\n className,\n ...props\n}: CountDownTimerProps) => {\n const dateFormatter = useDateTimeFormatter();\n const [timeRemaining, setTimeRemaining] = useState<TimeRemaining | null>(null);\n const [hasExecutedAction, setHasExecutedAction] = useState(false);\n\n useEffect(() => {\n const calculateTimeRemaining = (): TimeRemaining => {\n const now = new Date();\n const endTime = new Date(end).getTime();\n const nowTime = now.getTime();\n const difference = endTime - nowTime;\n\n if (difference <= 0) {\n return {\n days: 0,\n hours: 0,\n minutes: 0,\n seconds: 0,\n isFinished: true,\n };\n }\n\n const days = Math.floor(difference / (1000 * 60 * 60 * 24));\n const hours = Math.floor((difference / (1000 * 60 * 60)) % 24);\n const minutes = Math.floor((difference / 1000 / 60) % 60);\n const seconds = Math.floor((difference / 1000) % 60);\n\n return {\n days,\n hours,\n minutes,\n seconds,\n isFinished: false,\n };\n };\n\n // Initial calculation\n setTimeRemaining(calculateTimeRemaining());\n\n // Update every second\n const interval = setInterval(() => {\n const remaining = calculateTimeRemaining();\n\n setTimeRemaining(remaining);\n\n // Execute action when countdown finishes\n if (remaining.isFinished && !hasExecutedAction) {\n action?.();\n setHasExecutedAction(true);\n }\n }, 1000);\n\n return () => clearInterval(interval);\n }, [end, action, hasExecutedAction]);\n\n if (!timeRemaining) {\n return null;\n }\n\n const formatTime = (): string => {\n if (format === 'date') {\n const endDate = new Date(end);\n\n return dateFormatter.format(endDate);\n }\n\n const { days, hours, minutes, seconds, isFinished } = timeRemaining;\n\n if (isFinished) {\n return '00:00:00';\n }\n\n if (format === 'datetime') {\n const endDate = new Date(end);\n const dateString = dateFormatter.format(endDate);\n const timeString = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n\n return `${dateString} ${timeString}`;\n }\n\n if (days > 0) {\n return `${days}d ${String(hours).padStart(2, '0')}h ${String(minutes).padStart(2, '0')}m`;\n }\n\n return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n };\n\n const displayVariant = timeRemaining.isFinished ? 'destructive' : variant;\n\n return (\n <div\n className={[\n styles.countdownTimer,\n styles[displayVariant],\n timeRemaining.isFinished ? styles.finished : null,\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...props}\n >\n <span className={styles.value}>{formatTime()}</span>\n </div>\n );\n};\n"],"mappings":";;;;;AAmCA,IAAa,KAAkB,EAC7B,OAAO,GACP,QACA,YAAS,QACT,aAAU,UACV,WACA,cACA,GAAG,QACsB;CACzB,IAAM,IAAgB,EAAqB,GACrC,CAAC,GAAe,KAAoB,EAA+B,IAAI,GACvE,CAAC,GAAmB,KAAwB,EAAS,EAAK;CAoDhE,IAlDA,QAAgB;EACd,IAAM,UAA8C;GAClD,IAAM,oBAAM,IAAI,KAAK,GAGf,IAFU,IAAI,KAAK,CAAG,EAAE,QAEX,IADH,EAAI,QACS;GAiB7B,OAfI,KAAc,IACT;IACL,MAAM;IACN,OAAO;IACP,SAAS;IACT,SAAS;IACT,YAAY;GACd,IAQK;IACL,MANW,KAAK,MAAM,KAAc,MAAO,KAAK,KAAK,GAMrD;IACA,OANY,KAAK,MAAO,KAAc,MAAO,KAAK,MAAO,EAMzD;IACA,SANc,KAAK,MAAO,IAAa,MAAO,KAAM,EAMpD;IACA,SANc,KAAK,MAAO,IAAa,MAAQ,EAM/C;IACA,YAAY;GACd;EACF;EAGA,EAAiB,EAAuB,CAAC;EAGzC,IAAM,IAAW,kBAAkB;GACjC,IAAM,IAAY,EAAuB;GAKzC,AAHA,EAAiB,CAAS,GAGtB,EAAU,cAAc,CAAC,MAC3B,IAAS,GACT,EAAqB,EAAI;EAE7B,GAAG,GAAI;EAEP,aAAa,cAAc,CAAQ;CACrC,GAAG;EAAC;EAAK;EAAQ;CAAiB,CAAC,GAE/B,CAAC,GACH,OAAO;CAGT,IAAM,UAA2B;EAC/B,IAAI,MAAW,QAAQ;GACrB,IAAM,IAAU,IAAI,KAAK,CAAG;GAE5B,OAAO,EAAc,OAAO,CAAO;EACrC;EAEA,IAAM,EAAE,SAAM,UAAO,YAAS,YAAS,kBAAe;EAEtD,IAAI,GACF,OAAO;EAGT,IAAI,MAAW,YAAY;GACzB,IAAM,IAAU,IAAI,KAAK,CAAG;GAI5B,OAAO,GAHY,EAAc,OAAO,CAG9B,EAAW,GAAG,GAFF,OAAO,CAAK,EAAE,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,GAAG,GAAG;EAG7H;EAMA,OAJI,IAAO,IACF,GAAG,EAAK,IAAI,OAAO,CAAK,EAAE,SAAS,GAAG,GAAG,EAAE,IAAI,OAAO,CAAO,EAAE,SAAS,GAAG,GAAG,EAAE,KAGlF,GAAG,OAAO,CAAK,EAAE,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,CAAO,EAAE,SAAS,GAAG,GAAG;CACjH,GAEM,IAAiB,EAAc,aAAa,gBAAgB;CAElE,OACE,kBAAC,OAAD;EACE,WAAW;GACT,EAAO;GACP,EAAO;GACP,EAAc,aAAa,EAAO,WAAW;GAC7C;EACF,EACG,OAAO,OAAO,EACd,KAAK,GAAG;EACX,GAAI;YAEJ,kBAAC,QAAD;GAAM,WAAW,EAAO;aAAQ,EAAW;EAAQ,CAAA;CAChD,CAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./CountDownTimer/CountDownTimer.cjs");exports.CountDownTimer=e.CountDownTimer;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require("./dialogUtils.cjs"),t=require("./Dialog.module.css.cjs");let n=require("react"),r=require("react-dom"),i=require("react/jsx-runtime");var a=({open:a,title:o,children:s,buttons:c=[],onClose:l,closeOnBackdrop:u=!0,role:d=`dialog`,responses:f,onResponse:p,className:m,...h})=>{let g=(0,n.useRef)(null),_=(0,n.useId)(),v=(0,n.useRef)(null),y=!!f,b=e.useVisualViewport();e.useBodyScrollLock(a),(0,n.useEffect)(()=>{a?(v.current=document.activeElement,(g.current?.querySelector(e.FOCUSABLE))?.focus()):v.current?.focus()},[a]);let x=(0,n.useCallback)(()=>{let e=f?.find(e=>e.variant!==`destructive`&&!e.disabled);e&&p?.(e.id)},[f,p]),S=y?x:u?l:void 0,C=(0,n.useCallback)(t=>{if(t.key===`Escape`){t.preventDefault(),y?x():l?.();return}e.trapFocus(t,g)},[y,x,l]);if(!a)return null;let w=()=>y&&f?(0,i.jsx)(`div`,{className:t.default.footer,children:f.map(e=>(0,i.jsx)(`button`,{type:`button`,disabled:e.disabled,className:[t.default.btn,t.default[`btn-${e.variant??`default`}`]].filter(Boolean).join(` `),onClick:()=>p?.(e.id),children:e.label},e.id))}):c.length>0?(0,i.jsx)(`div`,{className:t.default.footer,children:c.map(e=>(0,i.jsx)(`button`,{type:`button`,disabled:e.disabled,className:[t.default.btn,t.default[`btn-${e.variant??`default`}`]].filter(Boolean).join(` `),onClick:e.onClick,children:e.label},e.label))}):null,T=(0,i.jsx)(`div`,{className:t.default.backdrop,style:b,onClick:S,children:(0,i.jsxs)(`div`,{ref:g,role:d,"aria-modal":`true`,"aria-labelledby":o?_:void 0,className:[t.default.dialog,m].filter(Boolean).join(` `),onKeyDown:C,onClick:e=>e.stopPropagation(),...h,children:[o&&(0,i.jsx)(`div`,{id:_,className:t.default.title,children:o}),s&&(0,i.jsx)(`div`,{className:t.default.body,children:s}),w()]})});return typeof document>`u`?T:(0,r.createPortal)(T,document.body)};exports.Dialog=a;
|
|
2
2
|
//# sourceMappingURL=Dialog.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.cjs","names":[],"sources":["../../../src/components/Dialog/Dialog.tsx"],"sourcesContent":["import {\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\n\nimport styles from './Dialog.module.css';\nimport { FOCUSABLE, trapFocus, useVisualViewport } from './dialogUtils';\n\n// ─── AlertDialog types ────────────────────────────────────────────────────────\n\nexport type AlertDialogResponseVariant = 'default' | 'suggested' | 'destructive';\n\nexport interface AlertDialogResponse {\n /**\n * Unique identifier returned via `onResponse`.\n * Use `\"cancel\"` by convention for the dismissive action.\n */\n id: string;\n /** Button label. */\n label: string;\n /** Visual emphasis. Defaults to `\"default\"`. */\n variant?: AlertDialogResponseVariant;\n /** Disables the button. */\n disabled?: boolean;\n}\n\n// ─── Dialog ───────────────────────────────────────────────────────────────────\n\nexport interface DialogButton {\n /** Button label. */\n label: string;\n /** Visual variant. Defaults to `\"default\"`. */\n variant?: 'default' | 'suggested' | 'destructive';\n /** Called when the button is clicked. */\n onClick: () => void;\n /** Whether the button is disabled. */\n disabled?: boolean;\n}\n\nexport interface DialogProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Whether the dialog is visible. */\n open: boolean;\n\n // ── Standard dialog ──────────────────────────────────────────────────────\n\n /** Dialog heading. */\n title?: ReactNode;\n /** Body content. */\n children?: ReactNode;\n /** Action buttons (standard dialog API). */\n buttons?: DialogButton[];\n /** Called on Escape or backdrop click. */\n onClose?: () => void;\n /** Whether clicking the backdrop closes the dialog. Defaults to `true`. */\n closeOnBackdrop?: boolean;\n\n // ── AlertDialog extension ─────────────────────────────────────────────────\n\n /**\n * ARIA role. Use `\"alertdialog\"` for confirmations and destructive warnings —\n * screen readers announce it immediately. Defaults to `\"dialog\"`.\n *\n * When using `role=\"alertdialog\"`, prefer the `responses`/`onResponse` API\n * over `buttons`/`onClick` for semantic clarity.\n */\n role?: 'dialog' | 'alertdialog';\n\n /**\n * Response buttons (AlertDialog API). Alternative to `buttons` — each\n * response has a semantic `id` returned via `onResponse`.\n * Escape and backdrop click fire the first non-destructive response.\n */\n responses?: AlertDialogResponse[];\n\n /**\n * Called with the `id` of the response button clicked.\n * Required when `responses` is provided.\n */\n onResponse?: (id: string) => void;\n}\n\n/**\n * Blocking modal dialog following the Adwaita pattern.\n *\n * **Standard** — `title` + `children` + `buttons[]`.\n *\n * **Alert** — add `role=\"alertdialog\"` + `responses[]` + `onResponse`.\n * Uses a semantic response id instead of per-button `onClick`.\n * Escape / backdrop fire the first non-destructive response.\n * Mirrors `AdwAlertDialog`.\n *\n * For the app-info dialog, use `<AboutDialog />` instead.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Dialog.html\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.AlertDialog.html\n */\nexport
|
|
1
|
+
{"version":3,"file":"Dialog.cjs","names":[],"sources":["../../../src/components/Dialog/Dialog.tsx"],"sourcesContent":["import {\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\n\nimport styles from './Dialog.module.css';\nimport { FOCUSABLE, trapFocus, useBodyScrollLock, useVisualViewport } from './dialogUtils';\n\n// ─── AlertDialog types ────────────────────────────────────────────────────────\n\nexport type AlertDialogResponseVariant = 'default' | 'suggested' | 'destructive';\n\nexport interface AlertDialogResponse {\n /**\n * Unique identifier returned via `onResponse`.\n * Use `\"cancel\"` by convention for the dismissive action.\n */\n id: string;\n /** Button label. */\n label: string;\n /** Visual emphasis. Defaults to `\"default\"`. */\n variant?: AlertDialogResponseVariant;\n /** Disables the button. */\n disabled?: boolean;\n}\n\n// ─── Dialog ───────────────────────────────────────────────────────────────────\n\nexport interface DialogButton {\n /** Button label. */\n label: string;\n /** Visual variant. Defaults to `\"default\"`. */\n variant?: 'default' | 'suggested' | 'destructive';\n /** Called when the button is clicked. */\n onClick: () => void;\n /** Whether the button is disabled. */\n disabled?: boolean;\n}\n\nexport interface DialogProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Whether the dialog is visible. */\n open: boolean;\n\n // ── Standard dialog ──────────────────────────────────────────────────────\n\n /** Dialog heading. */\n title?: ReactNode;\n /** Body content. */\n children?: ReactNode;\n /** Action buttons (standard dialog API). */\n buttons?: DialogButton[];\n /** Called on Escape or backdrop click. */\n onClose?: () => void;\n /** Whether clicking the backdrop closes the dialog. Defaults to `true`. */\n closeOnBackdrop?: boolean;\n\n // ── AlertDialog extension ─────────────────────────────────────────────────\n\n /**\n * ARIA role. Use `\"alertdialog\"` for confirmations and destructive warnings —\n * screen readers announce it immediately. Defaults to `\"dialog\"`.\n *\n * When using `role=\"alertdialog\"`, prefer the `responses`/`onResponse` API\n * over `buttons`/`onClick` for semantic clarity.\n */\n role?: 'dialog' | 'alertdialog';\n\n /**\n * Response buttons (AlertDialog API). Alternative to `buttons` — each\n * response has a semantic `id` returned via `onResponse`.\n * Escape and backdrop click fire the first non-destructive response.\n */\n responses?: AlertDialogResponse[];\n\n /**\n * Called with the `id` of the response button clicked.\n * Required when `responses` is provided.\n */\n onResponse?: (id: string) => void;\n}\n\n/**\n * Blocking modal dialog following the Adwaita pattern.\n *\n * **Standard** — `title` + `children` + `buttons[]`.\n *\n * **Alert** — add `role=\"alertdialog\"` + `responses[]` + `onResponse`.\n * Uses a semantic response id instead of per-button `onClick`.\n * Escape / backdrop fire the first non-destructive response.\n * Mirrors `AdwAlertDialog`.\n *\n * For the app-info dialog, use `<AboutDialog />` instead.\n *\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Dialog.html\n * @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.AlertDialog.html\n */\nexport const Dialog = ({\n open,\n title,\n children,\n buttons = [],\n onClose,\n closeOnBackdrop = true,\n role = 'dialog',\n responses,\n onResponse,\n className,\n ...props\n}: DialogProps) => {\n const dialogRef = useRef<HTMLDivElement>(null);\n const titleId = useId();\n const previouslyFocused = useRef<Element | null>(null);\n\n const isAlert = !!responses;\n const viewportStyle = useVisualViewport();\n\n useBodyScrollLock(open);\n\n // ── Focus management ───────────────────────────────────────────────────────\n useEffect(() => {\n if (open) {\n previouslyFocused.current = document.activeElement;\n const el = dialogRef.current?.querySelector<HTMLElement>(FOCUSABLE);\n\n el?.focus();\n } else {\n (previouslyFocused.current as HTMLElement | null)?.focus();\n }\n }, [open]);\n\n // ── Dismiss helpers ────────────────────────────────────────────────────────\n const dismissAlert = useCallback(() => {\n const cancel = responses?.find((r) => r.variant !== 'destructive' && !r.disabled);\n\n if (cancel) {\n onResponse?.(cancel.id);\n }\n }, [responses, onResponse]);\n\n const handleBackdrop = isAlert ? dismissAlert : closeOnBackdrop ? onClose : undefined;\n\n // ── Keyboard ───────────────────────────────────────────────────────────────\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n if (isAlert) {\n dismissAlert();\n } else {\n onClose?.();\n }\n\n return;\n }\n\n trapFocus(e, dialogRef);\n },\n [isAlert, dismissAlert, onClose],\n );\n\n if (!open) {\n return null;\n }\n\n // ── Render buttons (standard or alert) ────────────────────────────────────\n const renderButtons = () => {\n if (isAlert && responses) {\n return (\n <div className={styles.footer}>\n {responses.map((r) => (\n <button\n key={r.id}\n type=\"button\"\n disabled={r.disabled}\n className={[styles.btn, styles[`btn-${r.variant ?? 'default'}`]]\n .filter(Boolean)\n .join(' ')}\n onClick={() => onResponse?.(r.id)}\n >\n {r.label}\n </button>\n ))}\n </div>\n );\n }\n\n if (buttons.length > 0) {\n return (\n <div className={styles.footer}>\n {buttons.map((btn) => (\n <button\n key={btn.label}\n type=\"button\"\n disabled={btn.disabled}\n className={[styles.btn, styles[`btn-${btn.variant ?? 'default'}`]]\n .filter(Boolean)\n .join(' ')}\n onClick={btn.onClick}\n >\n {btn.label}\n </button>\n ))}\n </div>\n );\n }\n\n return null;\n };\n\n const node = (\n <div className={styles.backdrop} style={viewportStyle} onClick={handleBackdrop}>\n <div\n ref={dialogRef}\n role={role}\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n className={[styles.dialog, className].filter(Boolean).join(' ')}\n onKeyDown={handleKeyDown}\n onClick={(e) => e.stopPropagation()}\n {...props}\n >\n {title && (\n <div id={titleId} className={styles.title}>\n {title}\n </div>\n )}\n {children && <div className={styles.body}>{children}</div>}\n {renderButtons()}\n </div>\n </div>\n );\n\n if (typeof document === 'undefined') {\n return node;\n }\n\n return createPortal(node, document.body);\n};\n"],"mappings":"uJAuGA,IAAa,GAAU,CACrB,OACA,QACA,WACA,UAAU,CAAC,EACX,UACA,kBAAkB,GAClB,OAAO,SACP,YACA,aACA,YACA,GAAG,KACc,CACjB,IAAM,GAAA,EAAA,EAAA,QAAmC,IAAI,EACvC,GAAA,EAAA,EAAA,OAAgB,EAChB,GAAA,EAAA,EAAA,QAA2C,IAAI,EAE/C,EAAU,CAAC,CAAC,EACZ,EAAgB,EAAA,kBAAkB,EAExC,EAAA,kBAAkB,CAAI,GAGtB,EAAA,EAAA,eAAgB,CACV,GACF,EAAkB,QAAU,SAAS,eAC1B,EAAU,SAAS,cAA2B,EAAA,SAAS,IAE9D,MAAM,GAEV,EAAmB,SAAgC,MAAM,CAE7D,EAAG,CAAC,CAAI,CAAC,EAGT,IAAM,GAAA,EAAA,EAAA,iBAAiC,CACrC,IAAM,EAAS,GAAW,KAAM,GAAM,EAAE,UAAY,eAAiB,CAAC,EAAE,QAAQ,EAE5E,GACF,IAAa,EAAO,EAAE,CAE1B,EAAG,CAAC,EAAW,CAAU,CAAC,EAEpB,EAAiB,EAAU,EAAe,EAAkB,EAAU,IAAA,GAGtE,GAAA,EAAA,EAAA,aACH,GAAqC,CACpC,GAAI,EAAE,MAAQ,SAAU,CACtB,EAAE,eAAe,EACb,EACF,EAAa,EAEb,IAAU,EAGZ,MACF,CAEA,EAAA,UAAU,EAAG,CAAS,CACxB,EACA,CAAC,EAAS,EAAc,CAAO,CACjC,EAEA,GAAI,CAAC,EACH,OAAO,KAIT,IAAM,MACA,GAAW,GAEX,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAA,QAAO,gBACpB,EAAU,IAAK,IACd,EAAA,EAAA,KAAC,SAAD,CAEE,KAAK,SACL,SAAU,EAAE,SACZ,UAAW,CAAC,EAAA,QAAO,IAAK,EAAA,QAAO,OAAO,EAAE,SAAW,YAAY,EAC5D,OAAO,OAAO,EACd,KAAK,GAAG,EACX,YAAe,IAAa,EAAE,EAAE,WAE/B,EAAE,KACG,EATD,EAAE,EASD,CACT,CACE,CAAA,EAIL,EAAQ,OAAS,GAEjB,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAA,QAAO,gBACpB,EAAQ,IAAK,IACZ,EAAA,EAAA,KAAC,SAAD,CAEE,KAAK,SACL,SAAU,EAAI,SACd,UAAW,CAAC,EAAA,QAAO,IAAK,EAAA,QAAO,OAAO,EAAI,SAAW,YAAY,EAC9D,OAAO,OAAO,EACd,KAAK,GAAG,EACX,QAAS,EAAI,iBAEZ,EAAI,KACC,EATD,EAAI,KASH,CACT,CACE,CAAA,EAIF,KAGH,GACJ,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAA,QAAO,SAAU,MAAO,EAAe,QAAS,YAC9D,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACC,OACN,aAAW,OACX,kBAAiB,EAAQ,EAAU,IAAA,GACnC,UAAW,CAAC,EAAA,QAAO,OAAQ,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAC9D,UAAW,EACX,QAAU,GAAM,EAAE,gBAAgB,EAClC,GAAI,WARN,CAUG,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,GAAI,EAAS,UAAW,EAAA,QAAO,eACjC,CACE,CAAA,EAEN,IAAY,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAO,UAAc,CAAA,EACxD,EAAc,CACZ,GACF,CAAA,EAOP,OAJI,OAAO,SAAa,IACf,GAGT,EAAA,EAAA,cAAoB,EAAM,SAAS,IAAI,CACzC"}
|
|
@@ -71,4 +71,4 @@ export interface DialogProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title
|
|
|
71
71
|
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Dialog.html
|
|
72
72
|
* @see https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.AlertDialog.html
|
|
73
73
|
*/
|
|
74
|
-
export declare
|
|
74
|
+
export declare const Dialog: ({ open, title, children, buttons, onClose, closeOnBackdrop, role, responses, onResponse, className, ...props }: DialogProps) => import("react/jsx-runtime").JSX.Element | null;
|