@astryxdesign/core 0.5.0 → 0.5.1-canary.046f6ea
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/CHANGELOG.md +222 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +45 -20
- package/dist/AspectRatio/AspectRatio.d.ts +6 -6
- package/dist/Avatar/Avatar.d.ts +25 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +43 -9
- package/dist/Avatar/index.d.ts +2 -2
- package/dist/Avatar/index.d.ts.map +1 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +5 -2
- package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
- package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +11 -7
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +26 -2
- package/dist/Banner/Banner.d.ts +10 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +11 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +8 -7
- package/dist/Calendar/Calendar.d.ts +4 -2
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +15 -21
- package/dist/Calendar/hooks/useCalendarDays.js +4 -6
- package/dist/Calendar/hooks/useCalendarNavigation.js +4 -6
- package/dist/Calendar/styles.d.ts +5 -20
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +15 -17
- package/dist/Card/Card.d.ts +12 -12
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +17 -9
- package/dist/Card/index.d.ts +35 -1
- package/dist/Card/index.d.ts.map +1 -1
- package/dist/Card/index.js +21 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +108 -7
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +7 -1
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +15 -4
- package/dist/CodeBlock/highlightRanges.js +1 -1
- package/dist/CodeBlock/highlightStyles.js +13 -13
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +2 -7
- package/dist/ComplexSelector/ComplexSelector.d.ts +10 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +14 -7
- package/dist/DateInput/DateInput.d.ts +43 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +22 -5
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +5 -3
- package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
- package/dist/DateInput/MonthYearWheels.js +6 -4
- package/dist/DateInput/NativeDateField.d.ts +10 -0
- package/dist/DateInput/NativeDateField.d.ts.map +1 -0
- package/dist/DateInput/NativeDateField.js +494 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +52 -25
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +1 -0
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateInput/nativeDateSegments.d.ts +22 -0
- package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
- package/dist/DateInput/nativeDateSegments.js +111 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +3 -5
- package/dist/DateTimeInput/DateTimeInput.d.ts +23 -24
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +35 -10
- package/dist/DateTimeInput/TouchDateTimeField.d.ts +6 -0
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -0
- package/dist/DateTimeInput/TouchDateTimeField.js +1021 -0
- package/dist/Dialog/Dialog.d.ts +16 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +28 -7
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -13
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -1
- package/dist/Field/InputClearButton.d.ts +9 -3
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +14 -3
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +0 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +104 -3
- package/dist/HoverCard/useHoverCard.d.ts +14 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -1
- package/dist/Icon/Icon.d.ts +4 -2
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/defaultIcons.d.ts +3 -2
- package/dist/Icon/defaultIcons.d.ts.map +1 -1
- package/dist/Icon/defaultIcons.js +7 -0
- package/dist/Icon/globalIconRegistry.d.ts +13 -0
- package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
- package/dist/Icon/globalIconRegistry.js +34 -6
- package/dist/Icon/index.d.ts +1 -1
- package/dist/Icon/index.d.ts.map +1 -1
- package/dist/Icon/useIcon.d.ts +5 -2
- package/dist/Icon/useIcon.d.ts.map +1 -1
- package/dist/Icon/useIcon.js +3 -0
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +6 -2
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +2 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +2 -26
- package/dist/Layer/gestureCounter.d.ts +8 -0
- package/dist/Layer/gestureCounter.d.ts.map +1 -0
- package/dist/Layer/gestureCounter.js +53 -0
- package/dist/Layer/useLayer.d.ts +23 -13
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +146 -24
- package/dist/List/List.d.ts +1 -1
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +15 -4
- package/dist/Markdown/Markdown.d.ts +1 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +20 -7
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +5 -3
- package/dist/MetadataList/MetadataListItem.d.ts +1 -1
- package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
- package/dist/MetadataList/MetadataListItem.js +4 -1
- package/dist/MultiSelector/MultiSelector.d.ts +18 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +58 -11
- package/dist/MultiSelector/hooks.d.ts +7 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +3 -2
- package/dist/NavIcon/NavIcon.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.js +5 -1
- package/dist/NavItem/navItemStyles.stylex.d.ts +0 -8
- package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
- package/dist/NavItem/navItemStyles.stylex.js +0 -2
- package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +7 -4
- package/dist/NumberInput/NumberInput.d.ts +6 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +95 -126
- package/dist/NumberInput/numberInputCommit.d.ts +34 -0
- package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
- package/dist/NumberInput/numberInputCommit.js +71 -0
- package/dist/NumberInput/numberParser.d.ts +64 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -0
- package/dist/NumberInput/numberParser.js +350 -0
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +2 -3
- package/dist/OverflowList/OverflowList.d.ts +41 -1
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +43 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +8 -14
- package/dist/Popover/usePopover.d.ts +15 -41
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +26 -7
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +91 -18
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +4 -2
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +18 -5
- package/dist/Resizable/useResizable.d.ts +19 -1
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +104 -38
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +9 -0
- package/dist/Selector/Selector.d.ts +18 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +92 -21
- package/dist/Selector/hooks.d.ts +7 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +3 -2
- package/dist/SideNav/SideNav.d.ts +6 -1
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +57 -27
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +5 -4
- package/dist/SideNav/SideNavItem.d.ts +29 -4
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +75 -20
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +34 -2
- package/dist/Spinner/Spinner.d.ts +3 -1
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +199 -20
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +6 -1
- package/dist/Stepper/Step.d.ts.map +1 -1
- package/dist/Stepper/Step.js +7 -6
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +5 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +6 -1
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +3 -6
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +34 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +25 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +0 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +13 -8
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +10 -18
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +10 -5
- package/dist/Toast/Toast.d.ts +17 -2
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +77 -11
- package/dist/Toast/ToastViewport.d.ts +1 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +76 -21
- package/dist/Toast/index.d.ts +1 -1
- package/dist/Toast/index.d.ts.map +1 -1
- package/dist/Toast/types.d.ts +38 -0
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Toast/useToastGesture.d.ts +26 -0
- package/dist/Toast/useToastGesture.d.ts.map +1 -0
- package/dist/Toast/useToastGesture.js +223 -0
- package/dist/Token/Token.d.ts +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +23 -12
- package/dist/Token/TokenLink.d.ts +1 -1
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +5 -2
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +31 -21
- package/dist/TopNav/TopNavHeading.js +2 -2
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +3 -3
- package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +30 -9
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +3 -3
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +21 -6
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +7 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +2 -2
- package/dist/Typeahead/BaseTypeahead.d.ts +33 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +51 -8
- package/dist/Typeahead/Typeahead.d.ts +8 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +2 -0
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +7 -2
- package/dist/astryx.css +87 -22
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +3 -25
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +14 -4
- package/dist/i18n/InternationalizationContext.d.ts +2 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +3 -1
- package/dist/i18n/resolve.d.ts +1 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +37 -38
- package/dist/i18n/useTranslator.d.ts.map +1 -1
- package/dist/i18n/useTranslator.js +2 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +46 -10
- package/dist/theme/defineTheme.d.ts +9 -3
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +5 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +24 -4
- package/dist/theme/generateThemeRules.d.ts +21 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +26 -0
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.js +5 -2
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +6 -7
- package/dist/utils/dateParser.d.ts +5 -8
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +10 -11
- package/dist/utils/focusOutline.stylex.d.ts +25 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
- package/dist/utils/focusOutline.stylex.js +15 -0
- package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
- package/dist/utils/interactionOverlay.stylex.js +42 -0
- package/dist/utils/isApplePlatform.d.ts +18 -0
- package/dist/utils/isApplePlatform.d.ts.map +1 -0
- package/dist/utils/isApplePlatform.js +37 -0
- package/dist/utils/plainDate.d.ts +11 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +20 -4
- package/locales/af-ZA.json +7 -7
- package/locales/ar-SA.json +7 -7
- package/locales/ca-ES.json +6 -6
- package/locales/cs-CZ.json +7 -7
- package/locales/da-DK.json +7 -7
- package/locales/de-DE.json +7 -7
- package/locales/el-GR.json +7 -7
- package/locales/en.json +178 -6
- package/locales/es-ES.json +6 -6
- package/locales/fi-FI.json +7 -7
- package/locales/fr-FR.json +7 -7
- package/locales/he-IL.json +7 -7
- package/locales/hu-HU.json +7 -7
- package/locales/it-IT.json +7 -7
- package/locales/ja-JP.json +7 -7
- package/locales/ko-KR.json +7 -7
- package/locales/nl-NL.json +7 -7
- package/locales/no-NO.json +7 -7
- package/locales/pl-PL.json +7 -7
- package/locales/pseudo.json +130 -1
- package/locales/pt-BR.json +7 -7
- package/locales/pt-PT.json +7 -7
- package/locales/ro-RO.json +7 -7
- package/locales/ru-RU.json +7 -7
- package/locales/sr-SP.json +7 -7
- package/locales/sv-SE.json +7 -7
- package/locales/tr-TR.json +7 -7
- package/locales/uk-UA.json +7 -7
- package/locales/vi-VN.json +7 -7
- package/locales/zh-CN.json +7 -7
- package/locales/zh-TW.json +7 -7
- package/package.json +4 -5
- package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
- package/src/AlertDialog/AlertDialog.test.tsx +211 -2
- package/src/AlertDialog/AlertDialog.tsx +62 -20
- package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
- package/src/AspectRatio/AspectRatio.tsx +6 -6
- package/src/Avatar/Avatar.doc.mjs +12 -2
- package/src/Avatar/Avatar.test.tsx +80 -0
- package/src/Avatar/Avatar.tsx +64 -14
- package/src/Avatar/index.ts +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
- package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
- package/src/AvatarGroup/AvatarGroup.tsx +12 -4
- package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
- package/src/Badge/Badge.doc.mjs +3 -2
- package/src/Badge/Badge.test.tsx +32 -3
- package/src/Badge/Badge.tsx +42 -1
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +76 -11
- package/src/Banner/Banner.tsx +21 -2
- package/src/Button/Button.doc.mjs +2 -1
- package/src/Button/Button.test.tsx +19 -4
- package/src/Button/Button.tsx +9 -29
- package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
- package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +112 -0
- package/src/Calendar/Calendar.tsx +18 -16
- package/src/Calendar/hooks/useCalendarDays.ts +4 -4
- package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
- package/src/Calendar/styles.ts +48 -42
- package/src/Card/Card.doc.mjs +10 -7
- package/src/Card/Card.test.tsx +113 -19
- package/src/Card/Card.tsx +67 -89
- package/src/Card/index.ts +36 -1
- package/src/Carousel/Carousel.doc.mjs +3 -0
- package/src/Carousel/Carousel.test.tsx +360 -0
- package/src/Carousel/Carousel.tsx +116 -15
- package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
- package/src/CheckboxInput/CheckboxInput.tsx +5 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
- package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
- package/src/CodeBlock/CodeBlock.test.tsx +37 -0
- package/src/CodeBlock/CodeBlock.tsx +20 -4
- package/src/CodeBlock/highlightRanges.ts +1 -1
- package/src/CodeBlock/highlightStyles.ts +13 -13
- package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
- package/src/ComplexSelector/ComplexSelector.doc.mjs +9 -2
- package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
- package/src/ComplexSelector/ComplexSelector.tsx +22 -12
- package/src/DateInput/DateInput.doc.mjs +17 -1
- package/src/DateInput/DateInput.test.tsx +9 -4
- package/src/DateInput/DateInput.tsx +54 -3
- package/src/DateInput/DateInputTouch.test.tsx +146 -32
- package/src/DateInput/MonthScroller.tsx +5 -1
- package/src/DateInput/MonthYearWheels.tsx +7 -4
- package/src/DateInput/NativeDateField.test.tsx +635 -0
- package/src/DateInput/NativeDateField.tsx +641 -0
- package/src/DateInput/TouchDateField.tsx +83 -33
- package/src/DateInput/Wheel.tsx +1 -0
- package/src/DateInput/index.ts +1 -0
- package/src/DateInput/nativeDateSegments.ts +127 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +3 -3
- package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
- package/src/DateRangeInput/DateRangeInput.tsx +8 -13
- package/src/DateTimeInput/DateTimeInput.doc.mjs +39 -22
- package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
- package/src/DateTimeInput/DateTimeInput.tsx +54 -20
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
- package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
- package/src/Dialog/Dialog.test.tsx +185 -18
- package/src/Dialog/Dialog.tsx +35 -11
- package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
- package/src/DropdownMenu/DropdownMenu.tsx +4 -13
- package/src/Field/Field.doc.mjs +1 -1
- package/src/Field/FieldLabel.test.tsx +29 -0
- package/src/Field/FieldLabel.tsx +7 -0
- package/src/Field/InputClearButton.test.tsx +15 -1
- package/src/Field/InputClearButton.tsx +28 -4
- package/src/FieldStatus/FieldStatus.doc.mjs +1 -1
- package/src/FileInput/FileInput.doc.mjs +1 -1
- package/src/Heading/Heading.tsx +0 -1
- package/src/HoverCard/HoverCard.doc.mjs +8 -2
- package/src/HoverCard/HoverCard.test.tsx +154 -4
- package/src/HoverCard/HoverCard.tsx +137 -3
- package/src/HoverCard/useHoverCard.tsx +23 -3
- package/src/Icon/Icon.test.tsx +55 -1
- package/src/Icon/Icon.tsx +5 -3
- package/src/Icon/defaultIcons.tsx +11 -2
- package/src/Icon/globalIconRegistry.test.tsx +16 -3
- package/src/Icon/globalIconRegistry.tsx +37 -6
- package/src/Icon/index.ts +1 -0
- package/src/Icon/useIcon.ts +9 -2
- package/src/Indicator/CheckboxIndicator.tsx +14 -8
- package/src/Indicator/Indicator.doc.mjs +3 -1
- package/src/InputGroup/InputGroup.doc.mjs +1 -1
- package/src/Item/Item.tsx +2 -7
- package/src/Kbd/Kbd.test.tsx +0 -17
- package/src/Kbd/Kbd.tsx +2 -26
- package/src/Layer/gestureCounter.ts +57 -0
- package/src/Layer/useLayer.test.tsx +368 -16
- package/src/Layer/useLayer.tsx +208 -35
- package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
- package/src/List/List.test.tsx +38 -0
- package/src/List/List.tsx +8 -1
- package/src/Markdown/Markdown.test.tsx +37 -0
- package/src/Markdown/Markdown.tsx +16 -5
- package/src/Markdown/parser.test.ts +33 -0
- package/src/Markdown/parser.ts +9 -3
- package/src/MetadataList/MetadataList.test.tsx +75 -2
- package/src/MetadataList/MetadataListItem.tsx +5 -2
- package/src/MultiSelector/MultiSelector.doc.mjs +23 -2
- package/src/MultiSelector/MultiSelector.test.tsx +205 -0
- package/src/MultiSelector/MultiSelector.tsx +103 -16
- package/src/MultiSelector/hooks.ts +9 -2
- package/src/NavIcon/NavIcon.doc.mjs +8 -2
- package/src/NavIcon/NavIcon.test.tsx +9 -0
- package/src/NavIcon/NavIcon.tsx +5 -1
- package/src/NavItem/navItemStyles.stylex.ts +0 -8
- package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
- package/src/NavMenu/NavHeadingMenu.tsx +7 -4
- package/src/NumberInput/NumberInput.doc.mjs +27 -8
- package/src/NumberInput/NumberInput.test.tsx +563 -8
- package/src/NumberInput/NumberInput.tsx +77 -131
- package/src/NumberInput/numberInputCommit.test.ts +72 -0
- package/src/NumberInput/numberInputCommit.ts +103 -0
- package/src/NumberInput/numberParser.docblock.test.ts +234 -0
- package/src/NumberInput/numberParser.test.ts +222 -0
- package/src/NumberInput/numberParser.ts +403 -0
- package/src/Outline/Outline.tsx +2 -4
- package/src/OverflowList/OverflowList.doc.mjs +102 -21
- package/src/OverflowList/OverflowList.test.tsx +550 -4
- package/src/OverflowList/OverflowList.tsx +100 -2
- package/src/Pagination/Pagination.test.tsx +3 -2
- package/src/Popover/Popover.doc.mjs +2 -2
- package/src/Popover/Popover.test.tsx +38 -0
- package/src/Popover/Popover.tsx +28 -66
- package/src/Popover/usePopover.tsx +44 -5
- package/src/PowerSearch/PowerSearch.doc.mjs +1 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
- package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
- package/src/PowerSearch/formatFilterValue.test.ts +16 -1
- package/src/PowerSearch/formatFilterValue.ts +2 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
- package/src/ProgressBar/ProgressBar.test.tsx +24 -0
- package/src/ProgressBar/ProgressBar.tsx +28 -8
- package/src/RadioList/RadioList.doc.mjs +1 -1
- package/src/Resizable/Resizable.doc.mjs +2 -2
- package/src/Resizable/useResizable.doc.mjs +21 -2
- package/src/Resizable/useResizable.test.ts +421 -0
- package/src/Resizable/useResizable.ts +133 -48
- package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
- package/src/SelectableCard/SelectableCard.tsx +16 -0
- package/src/Selector/Selector.doc.mjs +15 -1
- package/src/Selector/Selector.source-build.test.mjs +65 -0
- package/src/Selector/Selector.test.tsx +301 -0
- package/src/Selector/Selector.tsx +145 -32
- package/src/Selector/hooks.ts +17 -2
- package/src/SideNav/SideNav.doc.mjs +2 -2
- package/src/SideNav/SideNav.test.tsx +1069 -6
- package/src/SideNav/SideNav.tsx +109 -38
- package/src/SideNav/SideNavHeading.tsx +5 -2
- package/src/SideNav/SideNavItem.doc.mjs +24 -3
- package/src/SideNav/SideNavItem.tsx +134 -44
- package/src/Slider/Slider.doc.mjs +2 -2
- package/src/Slider/Slider.test.tsx +106 -1
- package/src/Slider/Slider.tsx +52 -1
- package/src/Spinner/Spinner.doc.mjs +17 -5
- package/src/Spinner/Spinner.test.tsx +164 -0
- package/src/Spinner/Spinner.tsx +252 -22
- package/src/StatusDot/StatusDot.doc.mjs +8 -2
- package/src/StatusDot/StatusDot.test.tsx +9 -0
- package/src/StatusDot/StatusDot.tsx +7 -1
- package/src/Stepper/Step.doc.mjs +1 -1
- package/src/Stepper/Step.tsx +7 -14
- package/src/Switch/Switch.doc.mjs +3 -1
- package/src/Switch/Switch.test.tsx +10 -0
- package/src/Switch/Switch.tsx +3 -0
- package/src/Table/BaseTable.tsx +6 -1
- package/src/Table/Table.doc.mjs +5 -3
- package/src/Table/Table.tsx +3 -8
- package/src/Table/TableBody.doc.mjs +2 -2
- package/src/Table/TableFooter.doc.mjs +1 -1
- package/src/Table/TableHeader.doc.mjs +1 -1
- package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
- package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
- package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
- package/src/Table/useTableGroupedRows.doc.mjs +3 -3
- package/src/Table/useTablePagination.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +1 -1
- package/src/Text/Text.test.tsx +44 -0
- package/src/Text/Text.tsx +0 -1
- package/src/TextArea/TextArea.doc.mjs +13 -3
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +34 -22
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.doc.mjs +1 -1
- package/src/Timestamp/Timestamp.test.tsx +89 -0
- package/src/Timestamp/Timestamp.tsx +8 -8
- package/src/Timestamp/formatInstant.ts +5 -0
- package/src/Toast/Toast.doc.mjs +213 -44
- package/src/Toast/Toast.tsx +118 -23
- package/src/Toast/ToastViewport.test.tsx +1434 -8
- package/src/Toast/ToastViewport.tsx +85 -14
- package/src/Toast/index.ts +2 -0
- package/src/Toast/types.ts +43 -5
- package/src/Toast/useToastGesture.ts +361 -0
- package/src/Token/Token.test.tsx +95 -0
- package/src/Token/Token.tsx +19 -17
- package/src/Token/TokenLink.tsx +12 -3
- package/src/Tokenizer/Tokenizer.doc.mjs +17 -4
- package/src/Tokenizer/Tokenizer.test.tsx +161 -0
- package/src/Tokenizer/Tokenizer.tsx +49 -24
- package/src/TopNav/TopNavHeading.tsx +2 -2
- package/src/TopNav/TopNavItem.tsx +3 -7
- package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
- package/src/TopNav/TopNavMegaMenu.tsx +47 -4
- package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
- package/src/TopNav/TopNavMenu.test.tsx +133 -1
- package/src/TopNav/TopNavMenu.tsx +38 -5
- package/src/TreeList/TreeList.test.tsx +49 -0
- package/src/TreeList/TreeList.tsx +7 -2
- package/src/TreeList/TreeListItem.tsx +2 -7
- package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
- package/src/Typeahead/BaseTypeahead.tsx +96 -6
- package/src/Typeahead/Typeahead.doc.mjs +7 -1
- package/src/Typeahead/Typeahead.test.tsx +154 -0
- package/src/Typeahead/Typeahead.tsx +9 -0
- package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
- package/src/Typeahead/TypeaheadItem.tsx +8 -1
- package/src/hooks/useAnnounce.doc.mjs +96 -0
- package/src/hooks/useDevWarning.doc.mjs +96 -0
- package/src/hooks/useHotkeys.test.ts +0 -18
- package/src/hooks/useHotkeys.ts +3 -25
- package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
- package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
- package/src/hooks/useInteractiveRole.doc.mjs +119 -0
- package/src/hooks/useLongPress.doc.mjs +123 -0
- package/src/hooks/useOverflow.doc.mjs +58 -17
- package/src/hooks/useOverflow.ts +16 -4
- package/src/hooks/useTypeahead.doc.mjs +153 -0
- package/src/i18n/InternationalizationContext.ts +3 -0
- package/src/i18n/InternationalizationProvider.tsx +8 -1
- package/src/i18n/__tests__/resolve.test.ts +23 -1
- package/src/i18n/resolve.ts +46 -49
- package/src/i18n/useTranslator.ts +2 -7
- package/src/index.ts +2 -0
- package/src/raw-import.d.ts +14 -0
- package/src/theme/Theme.test.tsx +104 -2
- package/src/theme/Theme.tsx +49 -14
- package/src/theme/defineTheme.test.ts +23 -0
- package/src/theme/defineTheme.ts +12 -3
- package/src/theme/derivedVarRegistry.test.ts +87 -3
- package/src/theme/derivedVarRegistry.ts +23 -4
- package/src/theme/generateThemeRules.test.ts +99 -1
- package/src/theme/generateThemeRules.ts +28 -0
- package/src/theme/syntax/tokens.ts +5 -2
- package/src/theme/useTheme.test.tsx +10 -0
- package/src/theme/useTheme.ts +16 -10
- package/src/utils/dateParser.test.ts +34 -2
- package/src/utils/dateParser.ts +11 -14
- package/src/utils/focusOutline.stylex.ts +50 -0
- package/src/utils/interactionOverlay.stylex.ts +74 -0
- package/src/utils/isApplePlatform.test.ts +61 -0
- package/src/utils/isApplePlatform.ts +37 -0
- package/src/utils/plainDate.test.ts +46 -0
- package/src/utils/plainDate.ts +18 -3
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file useResizable.test.ts
|
|
5
|
+
* @input Uses vitest, @testing-library/react renderHook, useResizable
|
|
6
|
+
* @output Unit tests for useResizable persistence and collapse state
|
|
7
|
+
* @position Testing; validates useResizable implementation
|
|
8
|
+
*
|
|
9
|
+
* Persistence coverage originated in #4824 by @AKnassa.
|
|
10
|
+
*
|
|
11
|
+
* SYNC: When useResizable changes, update tests to match new behavior
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {useLayoutEffect} from 'react';
|
|
15
|
+
import {describe, it, expect, beforeEach, vi} from 'vitest';
|
|
16
|
+
import {renderHook, act} from '@testing-library/react';
|
|
17
|
+
import {useResizable} from './useResizable';
|
|
18
|
+
|
|
19
|
+
const AUTO_SAVE_ID = 'test-panel';
|
|
20
|
+
const KEY = `astryx-resizable:${AUTO_SAVE_ID}`;
|
|
21
|
+
|
|
22
|
+
const BASE_CONFIG = {
|
|
23
|
+
defaultSize: 260,
|
|
24
|
+
minSizePx: 180,
|
|
25
|
+
maxSizePx: 480,
|
|
26
|
+
autoSaveId: AUTO_SAVE_ID,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type StoredEntry = {size: number; isCollapsed: boolean} | number | null;
|
|
30
|
+
|
|
31
|
+
function readStored(): StoredEntry {
|
|
32
|
+
return JSON.parse(localStorage.getItem(KEY) ?? 'null') as StoredEntry;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
localStorage.clear();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('useResizable persistence', () => {
|
|
40
|
+
it('restores a persisted width (legacy plain-number format)', () => {
|
|
41
|
+
localStorage.setItem(KEY, '320');
|
|
42
|
+
const {result} = renderHook(() =>
|
|
43
|
+
useResizable({...BASE_CONFIG, collapsible: true}),
|
|
44
|
+
);
|
|
45
|
+
expect(result.current.size).toBe(320);
|
|
46
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('clamps a persisted width below the minimum', () => {
|
|
50
|
+
localStorage.setItem(KEY, '20');
|
|
51
|
+
const {result} = renderHook(() => useResizable(BASE_CONFIG));
|
|
52
|
+
expect(result.current.size).toBe(180);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('ignores a non-finite persisted value', () => {
|
|
56
|
+
// JSON.parse('1e999') yields Infinity, which passes a typeof check.
|
|
57
|
+
localStorage.setItem(KEY, '1e999');
|
|
58
|
+
const {result} = renderHook(() => useResizable(BASE_CONFIG));
|
|
59
|
+
expect(result.current.size).toBe(260);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('ignores corrupt storage content', () => {
|
|
63
|
+
localStorage.setItem(KEY, 'not json');
|
|
64
|
+
const {result} = renderHook(() => useResizable(BASE_CONFIG));
|
|
65
|
+
expect(result.current.size).toBe(260);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('persists the expanded size together with the collapse flag', () => {
|
|
69
|
+
const {result} = renderHook(() =>
|
|
70
|
+
useResizable({...BASE_CONFIG, collapsible: true}),
|
|
71
|
+
);
|
|
72
|
+
act(() => result.current.resize(340));
|
|
73
|
+
expect(readStored()).toEqual({size: 340, isCollapsed: false});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('keeps the expanded width in storage when collapsing', () => {
|
|
77
|
+
const {result} = renderHook(() =>
|
|
78
|
+
useResizable({...BASE_CONFIG, collapsible: true}),
|
|
79
|
+
);
|
|
80
|
+
act(() => result.current.resize(300));
|
|
81
|
+
act(() => result.current.collapse());
|
|
82
|
+
|
|
83
|
+
expect(result.current.size).toBe(0);
|
|
84
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
85
|
+
expect(readStored()).toEqual({size: 300, isCollapsed: true});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('restores the collapsed state and the pre-collapse width on remount', () => {
|
|
89
|
+
localStorage.setItem(KEY, JSON.stringify({size: 300, isCollapsed: true}));
|
|
90
|
+
const {result} = renderHook(() =>
|
|
91
|
+
useResizable({...BASE_CONFIG, collapsible: true}),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
95
|
+
expect(result.current.size).toBe(0);
|
|
96
|
+
|
|
97
|
+
act(() => result.current.expand());
|
|
98
|
+
expect(result.current.size).toBe(300);
|
|
99
|
+
expect(readStored()).toEqual({size: 300, isCollapsed: false});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('treats a legacy persisted 0 as collapsed when collapsible', () => {
|
|
103
|
+
localStorage.setItem(KEY, '0');
|
|
104
|
+
const {result} = renderHook(() =>
|
|
105
|
+
useResizable({...BASE_CONFIG, collapsible: true}),
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
109
|
+
expect(result.current.size).toBe(0);
|
|
110
|
+
|
|
111
|
+
// The legacy entry lost the real width, so expanding falls back to the
|
|
112
|
+
// default rather than to the minimum.
|
|
113
|
+
act(() => result.current.expand());
|
|
114
|
+
expect(result.current.size).toBe(260);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('treats a legacy persisted 0 as the default width when not collapsible', () => {
|
|
118
|
+
localStorage.setItem(KEY, '0');
|
|
119
|
+
const {result} = renderHook(() => useResizable(BASE_CONFIG));
|
|
120
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
121
|
+
expect(result.current.size).toBe(260);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('ignores a persisted collapse flag when not collapsible', () => {
|
|
125
|
+
localStorage.setItem(KEY, JSON.stringify({size: 300, isCollapsed: true}));
|
|
126
|
+
const {result} = renderHook(() => useResizable(BASE_CONFIG));
|
|
127
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
128
|
+
expect(result.current.size).toBe(300);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('keeps the saved width across repeated collapse calls', () => {
|
|
132
|
+
const {result} = renderHook(() =>
|
|
133
|
+
useResizable({...BASE_CONFIG, collapsible: true}),
|
|
134
|
+
);
|
|
135
|
+
act(() => result.current.resize(300));
|
|
136
|
+
act(() => result.current.collapse());
|
|
137
|
+
act(() => result.current.collapse());
|
|
138
|
+
|
|
139
|
+
expect(readStored()).toEqual({size: 300, isCollapsed: true});
|
|
140
|
+
act(() => result.current.expand());
|
|
141
|
+
expect(result.current.size).toBe(300);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('persists the pre-drag width when dragging to collapse', () => {
|
|
145
|
+
const {result} = renderHook(() =>
|
|
146
|
+
useResizable({...BASE_CONFIG, collapsible: true}),
|
|
147
|
+
);
|
|
148
|
+
act(() => result.current.resize(300));
|
|
149
|
+
act(() => result.current.props._onResizeStart());
|
|
150
|
+
act(() => result.current.props._onResizeMove(-270));
|
|
151
|
+
|
|
152
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
153
|
+
expect(readStored()).toEqual({size: 300, isCollapsed: true});
|
|
154
|
+
|
|
155
|
+
// A continued drag below the threshold must not clobber the saved width.
|
|
156
|
+
act(() => result.current.props._onResizeMove(-275));
|
|
157
|
+
act(() => result.current.expand());
|
|
158
|
+
expect(result.current.size).toBe(300);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('does not touch storage without an autoSaveId', () => {
|
|
162
|
+
const {result} = renderHook(() =>
|
|
163
|
+
useResizable({defaultSize: 260, collapsible: true}),
|
|
164
|
+
);
|
|
165
|
+
act(() => result.current.collapse());
|
|
166
|
+
expect(localStorage.length).toBe(0);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('useResizable uncontrolled collapse', () => {
|
|
171
|
+
it('starts collapsed from defaultIsCollapsed', () => {
|
|
172
|
+
const {result} = renderHook(() =>
|
|
173
|
+
useResizable({
|
|
174
|
+
defaultSize: 260,
|
|
175
|
+
collapsible: true,
|
|
176
|
+
defaultIsCollapsed: true,
|
|
177
|
+
}),
|
|
178
|
+
);
|
|
179
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
180
|
+
expect(result.current.size).toBe(0);
|
|
181
|
+
|
|
182
|
+
act(() => result.current.expand());
|
|
183
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
184
|
+
expect(result.current.size).toBe(260);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('ignores defaultIsCollapsed when not collapsible', () => {
|
|
188
|
+
const {result} = renderHook(() =>
|
|
189
|
+
useResizable({defaultSize: 260, defaultIsCollapsed: true}),
|
|
190
|
+
);
|
|
191
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
192
|
+
expect(result.current.size).toBe(260);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('lets a persisted collapse flag win over defaultIsCollapsed', () => {
|
|
196
|
+
localStorage.setItem(KEY, JSON.stringify({size: 300, isCollapsed: false}));
|
|
197
|
+
const {result} = renderHook(() =>
|
|
198
|
+
useResizable({
|
|
199
|
+
...BASE_CONFIG,
|
|
200
|
+
collapsible: true,
|
|
201
|
+
defaultIsCollapsed: true,
|
|
202
|
+
}),
|
|
203
|
+
);
|
|
204
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
205
|
+
expect(result.current.size).toBe(300);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('keeps defaultIsCollapsed when a legacy width entry says nothing about collapse', () => {
|
|
209
|
+
localStorage.setItem(KEY, '300');
|
|
210
|
+
const {result} = renderHook(() =>
|
|
211
|
+
useResizable({
|
|
212
|
+
...BASE_CONFIG,
|
|
213
|
+
collapsible: true,
|
|
214
|
+
defaultIsCollapsed: true,
|
|
215
|
+
}),
|
|
216
|
+
);
|
|
217
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
218
|
+
// The width is still restored — it is only collapse that is unknown.
|
|
219
|
+
act(() => result.current.expand());
|
|
220
|
+
expect(result.current.size).toBe(300);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('notifies onCollapseChange once per collapse and expand', () => {
|
|
224
|
+
const onCollapseChange = vi.fn();
|
|
225
|
+
const {result} = renderHook(() =>
|
|
226
|
+
useResizable({defaultSize: 260, collapsible: true, onCollapseChange}),
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
act(() => result.current.collapse());
|
|
230
|
+
expect(onCollapseChange).toHaveBeenCalledExactlyOnceWith(true);
|
|
231
|
+
|
|
232
|
+
onCollapseChange.mockClear();
|
|
233
|
+
act(() => result.current.expand());
|
|
234
|
+
expect(onCollapseChange).toHaveBeenCalledExactlyOnceWith(false);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('collapses on a drag past the threshold', () => {
|
|
238
|
+
const onCollapseChange = vi.fn();
|
|
239
|
+
const {result} = renderHook(() =>
|
|
240
|
+
useResizable({...BASE_CONFIG, collapsible: true, onCollapseChange}),
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
act(() => result.current.props._onResizeStart());
|
|
244
|
+
act(() => result.current.props._onResizeMove(-240));
|
|
245
|
+
|
|
246
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
247
|
+
expect(onCollapseChange).toHaveBeenCalledWith(true);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
describe('useResizable controlled collapse', () => {
|
|
252
|
+
it('renders the controlled value rather than its own state', () => {
|
|
253
|
+
const {result, rerender} = renderHook(
|
|
254
|
+
({isCollapsed}: {isCollapsed: boolean}) =>
|
|
255
|
+
useResizable({defaultSize: 260, collapsible: true, isCollapsed}),
|
|
256
|
+
{initialProps: {isCollapsed: true}},
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
260
|
+
expect(result.current.size).toBe(0);
|
|
261
|
+
|
|
262
|
+
rerender({isCollapsed: false});
|
|
263
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
264
|
+
expect(result.current.size).toBe(260);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('makes collapse() and expand() intents that change nothing locally', () => {
|
|
268
|
+
const onCollapseChange = vi.fn();
|
|
269
|
+
const {result} = renderHook(() =>
|
|
270
|
+
useResizable({
|
|
271
|
+
defaultSize: 260,
|
|
272
|
+
collapsible: true,
|
|
273
|
+
isCollapsed: false,
|
|
274
|
+
onCollapseChange,
|
|
275
|
+
}),
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
act(() => result.current.collapse());
|
|
279
|
+
expect(onCollapseChange).toHaveBeenCalledExactlyOnceWith(true);
|
|
280
|
+
// The owner said expanded and never changed its mind.
|
|
281
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
282
|
+
expect(result.current.size).toBe(260);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('reports a drag past the threshold instead of collapsing itself', () => {
|
|
286
|
+
const onCollapseChange = vi.fn();
|
|
287
|
+
const {result} = renderHook(() =>
|
|
288
|
+
useResizable({
|
|
289
|
+
...BASE_CONFIG,
|
|
290
|
+
collapsible: true,
|
|
291
|
+
isCollapsed: false,
|
|
292
|
+
onCollapseChange,
|
|
293
|
+
}),
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
act(() => result.current.props._onResizeStart());
|
|
297
|
+
act(() => result.current.props._onResizeMove(-240));
|
|
298
|
+
|
|
299
|
+
expect(onCollapseChange).toHaveBeenCalledWith(true);
|
|
300
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('persists the collapse state the owner holds', () => {
|
|
304
|
+
const {result} = renderHook(() =>
|
|
305
|
+
useResizable({...BASE_CONFIG, collapsible: true, isCollapsed: true}),
|
|
306
|
+
);
|
|
307
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
308
|
+
expect(readStored()).toEqual({size: 260, isCollapsed: true});
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// The fix under test is @AKnassa's, from #5118.
|
|
313
|
+
describe('useResizable live collapse state', () => {
|
|
314
|
+
it('reads the current controlled value before consumer layout effects', () => {
|
|
315
|
+
const onCollapseChange = vi.fn();
|
|
316
|
+
const {rerender} = renderHook(
|
|
317
|
+
({isCollapsed, shouldCollapse}) => {
|
|
318
|
+
const {collapse} = useResizable({
|
|
319
|
+
defaultSize: 260,
|
|
320
|
+
collapsible: true,
|
|
321
|
+
isCollapsed,
|
|
322
|
+
onCollapseChange,
|
|
323
|
+
});
|
|
324
|
+
useLayoutEffect(() => {
|
|
325
|
+
if (shouldCollapse) {
|
|
326
|
+
collapse();
|
|
327
|
+
}
|
|
328
|
+
}, [collapse, shouldCollapse]);
|
|
329
|
+
return collapse;
|
|
330
|
+
},
|
|
331
|
+
{initialProps: {isCollapsed: true, shouldCollapse: false}},
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
rerender({isCollapsed: false, shouldCollapse: true});
|
|
335
|
+
expect(onCollapseChange).toHaveBeenCalledExactlyOnceWith(true);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// ResizeHandle registers its pointermove listener once at pointer down, so
|
|
339
|
+
// a whole gesture runs against the props object captured there. These tests
|
|
340
|
+
// hold that snapshot instead of re-reading result.current between moves —
|
|
341
|
+
// re-reading hands the callbacks a fresh render and hides the bug.
|
|
342
|
+
it('reports one collapse for a drag that stays below the threshold', () => {
|
|
343
|
+
const onCollapseChange = vi.fn();
|
|
344
|
+
const {result} = renderHook(() =>
|
|
345
|
+
useResizable({...BASE_CONFIG, collapsible: true, onCollapseChange}),
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
act(() => result.current.props._onResizeStart());
|
|
349
|
+
const gesture = result.current.props;
|
|
350
|
+
for (const delta of [-240, -245, -250, -255, -260]) {
|
|
351
|
+
act(() => gesture._onResizeMove(delta));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
expect(onCollapseChange).toHaveBeenCalledExactlyOnceWith(true);
|
|
355
|
+
expect(result.current.isCollapsed).toBe(true);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('re-expands mid-gesture when the drag crosses back above the threshold', () => {
|
|
359
|
+
const onCollapseChange = vi.fn();
|
|
360
|
+
const {result} = renderHook(() =>
|
|
361
|
+
useResizable({...BASE_CONFIG, collapsible: true, onCollapseChange}),
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
act(() => result.current.props._onResizeStart());
|
|
365
|
+
const gesture = result.current.props;
|
|
366
|
+
act(() => gesture._onResizeMove(-240));
|
|
367
|
+
act(() => gesture._onResizeMove(-20));
|
|
368
|
+
|
|
369
|
+
expect(onCollapseChange.mock.calls).toEqual([[true], [false]]);
|
|
370
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
371
|
+
expect(result.current.size).toBe(240);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('notifies when resize() lifts the panel out of collapse', () => {
|
|
375
|
+
const onCollapseChange = vi.fn();
|
|
376
|
+
const {result} = renderHook(() =>
|
|
377
|
+
useResizable({...BASE_CONFIG, collapsible: true, onCollapseChange}),
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
act(() => result.current.collapse());
|
|
381
|
+
onCollapseChange.mockClear();
|
|
382
|
+
act(() => result.current.resize(300));
|
|
383
|
+
|
|
384
|
+
expect(onCollapseChange).toHaveBeenCalledExactlyOnceWith(false);
|
|
385
|
+
expect(result.current.isCollapsed).toBe(false);
|
|
386
|
+
expect(result.current.size).toBe(300);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('reports one collapse when collapse() runs twice in a tick', () => {
|
|
390
|
+
const onCollapseChange = vi.fn();
|
|
391
|
+
const {result} = renderHook(() =>
|
|
392
|
+
useResizable({...BASE_CONFIG, collapsible: true, onCollapseChange}),
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
act(() => {
|
|
396
|
+
result.current.collapse();
|
|
397
|
+
result.current.collapse();
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
expect(onCollapseChange).toHaveBeenCalledExactlyOnceWith(true);
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
describe('useResizable identity', () => {
|
|
405
|
+
it('keeps callbacks stable when optional snaps are omitted', () => {
|
|
406
|
+
const {result, rerender} = renderHook(() =>
|
|
407
|
+
useResizable({defaultSize: 200, minSizePx: 100, maxSizePx: 400}),
|
|
408
|
+
);
|
|
409
|
+
const first = {
|
|
410
|
+
expand: result.current.expand,
|
|
411
|
+
resize: result.current.resize,
|
|
412
|
+
snaps: result.current.props._snaps,
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
rerender();
|
|
416
|
+
|
|
417
|
+
expect(result.current.expand).toBe(first.expand);
|
|
418
|
+
expect(result.current.resize).toBe(first.resize);
|
|
419
|
+
expect(result.current.props._snaps).toBe(first.snaps);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useResizable.ts
|
|
7
|
-
* @input Resize configuration (defaultSize, minSizePx, maxSizePx,
|
|
7
|
+
* @input Resize configuration (defaultSize, minSizePx, maxSizePx, snaps) and
|
|
8
|
+
* collapse configuration (collapsible, defaultIsCollapsed, isCollapsed)
|
|
8
9
|
* @output Hook return: size, isCollapsed, collapse/expand/resize methods, props for handle
|
|
9
10
|
* @position Public hook; consumed by layout components via `resizable` prop
|
|
10
11
|
*/
|
|
@@ -44,15 +45,33 @@ export interface ResizableConfig {
|
|
|
44
45
|
minWidth?: number;
|
|
45
46
|
/** Maximum width in pixels. @default 480 */
|
|
46
47
|
maxWidth?: number;
|
|
47
|
-
/** localStorage key for persisting width. */
|
|
48
|
+
/** localStorage key for persisting width and collapse state. */
|
|
48
49
|
autoSaveId?: string;
|
|
49
50
|
/** Called when the width changes (on drag end). */
|
|
50
51
|
onWidthChange?: (width: number) => void;
|
|
52
|
+
/** Start collapsed (uncontrolled). A persisted entry wins over this. */
|
|
53
|
+
defaultIsCollapsed?: boolean;
|
|
54
|
+
/** Controlled collapse state. Pair with `onCollapseChange`. */
|
|
55
|
+
isCollapsed?: boolean;
|
|
56
|
+
/** Called when collapse state changes (via drag or programmatic). */
|
|
57
|
+
onCollapseChange?: (isCollapsed: boolean) => void;
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
export interface UseResizableSingleConfig extends ResizableRegionConfig {
|
|
54
61
|
/** Unique key for localStorage persistence. */
|
|
55
62
|
autoSaveId?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Initial collapse state (uncontrolled). A persisted entry wins over it,
|
|
65
|
+
* so a restored session keeps the state the user left behind.
|
|
66
|
+
* Only honored when `collapsible` is true.
|
|
67
|
+
*/
|
|
68
|
+
defaultIsCollapsed?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Controlled collapse state. When set, the caller owns collapse:
|
|
71
|
+
* `collapse()`, `expand()` and a drag past the collapse threshold report
|
|
72
|
+
* through `onCollapseChange` instead of changing state here.
|
|
73
|
+
*/
|
|
74
|
+
isCollapsed?: boolean;
|
|
56
75
|
/** Called when size changes during drag. */
|
|
57
76
|
onSizeChange?: (size: number) => void;
|
|
58
77
|
/** Called when collapse state changes (via drag or programmatic). */
|
|
@@ -138,16 +157,55 @@ function clampSize(
|
|
|
138
157
|
return clamped;
|
|
139
158
|
}
|
|
140
159
|
|
|
141
|
-
|
|
160
|
+
interface PersistedResizableState {
|
|
161
|
+
/** Expanded size in px, or null when the entry carries no usable size. */
|
|
162
|
+
size: number | null;
|
|
163
|
+
/**
|
|
164
|
+
* Collapse state when the entry was written, or null when the entry
|
|
165
|
+
* predates collapse persistence and says nothing about it.
|
|
166
|
+
*/
|
|
167
|
+
isCollapsed: boolean | null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Reads a persisted entry. Three formats exist in storage:
|
|
172
|
+
* - `{size, isCollapsed}` — the current format; `size` is the expanded size,
|
|
173
|
+
* so the pre-collapse width survives a collapsed session
|
|
174
|
+
* - a plain non-zero number — a legacy width-only entry that never recorded
|
|
175
|
+
* collapse, so `isCollapsed` is null (unknown)
|
|
176
|
+
* - a plain `0` — written by legacy collapse, which restored the region as a
|
|
177
|
+
* zero-width expanded panel (#4790); read as "collapsed, no saved size"
|
|
178
|
+
*/
|
|
179
|
+
function loadPersistedState(key: string): PersistedResizableState | null {
|
|
142
180
|
if (typeof window === 'undefined') {
|
|
143
181
|
return null;
|
|
144
182
|
}
|
|
145
183
|
try {
|
|
146
184
|
const raw = localStorage.getItem(STORAGE_PREFIX + key);
|
|
147
|
-
if (raw
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
185
|
+
if (raw == null) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const parsed: unknown = JSON.parse(raw);
|
|
189
|
+
if (typeof parsed === 'number') {
|
|
190
|
+
if (!Number.isFinite(parsed)) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
return parsed === 0
|
|
194
|
+
? {size: null, isCollapsed: true}
|
|
195
|
+
: {size: parsed, isCollapsed: null};
|
|
196
|
+
}
|
|
197
|
+
if (typeof parsed === 'object' && parsed != null) {
|
|
198
|
+
const {size, isCollapsed} = parsed as {
|
|
199
|
+
size?: unknown;
|
|
200
|
+
isCollapsed?: unknown;
|
|
201
|
+
};
|
|
202
|
+
const hasSize =
|
|
203
|
+
typeof size === 'number' && Number.isFinite(size) && size > 0;
|
|
204
|
+
if (hasSize || isCollapsed === true) {
|
|
205
|
+
return {
|
|
206
|
+
size: hasSize ? size : null,
|
|
207
|
+
isCollapsed: isCollapsed === true,
|
|
208
|
+
};
|
|
151
209
|
}
|
|
152
210
|
}
|
|
153
211
|
} catch {
|
|
@@ -156,12 +214,12 @@ function loadPersistedSize(key: string): number | null {
|
|
|
156
214
|
return null;
|
|
157
215
|
}
|
|
158
216
|
|
|
159
|
-
function
|
|
217
|
+
function persistState(key: string, state: PersistedResizableState): void {
|
|
160
218
|
if (typeof window === 'undefined') {
|
|
161
219
|
return;
|
|
162
220
|
}
|
|
163
221
|
try {
|
|
164
|
-
localStorage.setItem(STORAGE_PREFIX + key, JSON.stringify(
|
|
222
|
+
localStorage.setItem(STORAGE_PREFIX + key, JSON.stringify(state));
|
|
165
223
|
} catch {
|
|
166
224
|
/* ignore */
|
|
167
225
|
}
|
|
@@ -195,87 +253,115 @@ function useSingleResizable(config: UseResizableSingleConfig): ResizableRegion {
|
|
|
195
253
|
maxSizePx = Infinity,
|
|
196
254
|
collapsible = false,
|
|
197
255
|
collapsedSize = DEFAULT_COLLAPSED_SIZE,
|
|
198
|
-
snaps
|
|
256
|
+
snaps: configuredSnaps,
|
|
199
257
|
autoSaveId,
|
|
258
|
+
defaultIsCollapsed,
|
|
259
|
+
isCollapsed: controlledIsCollapsed,
|
|
200
260
|
onSizeChange,
|
|
201
261
|
onCollapseChange,
|
|
202
262
|
} = config;
|
|
263
|
+
const emptySnapsRef = useRef<number[]>([]);
|
|
264
|
+
const snaps = configuredSnaps ?? emptySnapsRef.current;
|
|
203
265
|
|
|
204
266
|
const resolvedDefault = resolveDefaultSize(defaultSize);
|
|
205
|
-
const persisted = autoSaveId ?
|
|
206
|
-
const initial = persisted ?? resolvedDefault;
|
|
267
|
+
const persisted = autoSaveId ? loadPersistedState(autoSaveId) : null;
|
|
268
|
+
const initial = persisted?.size ?? resolvedDefault;
|
|
207
269
|
|
|
270
|
+
// `size` is always the *expanded* size: collapse hides it behind the
|
|
271
|
+
// isCollapsed gate below rather than zeroing it, so the width the user had
|
|
272
|
+
// survives a collapse, a persist round-trip, and an expand.
|
|
208
273
|
const [size, setSize] = useState(() =>
|
|
209
274
|
clampSize(initial, minSizePx, maxSizePx, snaps),
|
|
210
275
|
);
|
|
211
|
-
const [
|
|
212
|
-
() => persisted
|
|
276
|
+
const [uncontrolledIsCollapsed, setUncontrolledIsCollapsed] = useState(
|
|
277
|
+
() => persisted?.isCollapsed ?? defaultIsCollapsed ?? false,
|
|
213
278
|
);
|
|
214
|
-
|
|
279
|
+
|
|
280
|
+
const isControlled = controlledIsCollapsed !== undefined;
|
|
281
|
+
const isCollapsed =
|
|
282
|
+
collapsible &&
|
|
283
|
+
(isControlled ? controlledIsCollapsed : uncontrolledIsCollapsed);
|
|
215
284
|
const dragStartSizeRef = useRef(size);
|
|
216
285
|
|
|
286
|
+
// Mirrors isCollapsed so the callbacks below read the live value instead of
|
|
287
|
+
// the one their last render captured. Two cases reach them from a stale
|
|
288
|
+
// closure: two imperative calls in one tick, and a drag — ResizeHandle
|
|
289
|
+
// registers its pointermove listener once at pointer down, so a whole
|
|
290
|
+
// gesture runs against one props snapshot.
|
|
291
|
+
const isCollapsedRef = useRef(isCollapsed);
|
|
292
|
+
isCollapsedRef.current = isCollapsed;
|
|
293
|
+
|
|
294
|
+
// Controlled callers own the state; collapse() and a drag past the
|
|
295
|
+
// threshold report through onCollapseChange and change nothing here.
|
|
296
|
+
const setCollapsed = useCallback(
|
|
297
|
+
(value: boolean) => {
|
|
298
|
+
if (!isControlled) {
|
|
299
|
+
isCollapsedRef.current = value;
|
|
300
|
+
setUncontrolledIsCollapsed(value);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
[isControlled],
|
|
304
|
+
);
|
|
305
|
+
|
|
217
306
|
useEffect(() => {
|
|
218
307
|
if (autoSaveId) {
|
|
219
|
-
|
|
308
|
+
persistState(autoSaveId, {size, isCollapsed});
|
|
220
309
|
}
|
|
221
310
|
}, [size, isCollapsed, autoSaveId]);
|
|
222
311
|
|
|
223
312
|
const collapse = useCallback(() => {
|
|
224
|
-
|
|
313
|
+
// The already-collapsed guard keeps a repeated call from re-notifying a
|
|
314
|
+
// transition that already happened.
|
|
315
|
+
if (!collapsible || isCollapsedRef.current) {
|
|
225
316
|
return;
|
|
226
317
|
}
|
|
227
|
-
|
|
228
|
-
setIsCollapsed(true);
|
|
229
|
-
setSize(0);
|
|
318
|
+
setCollapsed(true);
|
|
230
319
|
onCollapseChange?.(true);
|
|
231
320
|
onSizeChange?.(0);
|
|
232
|
-
}, [collapsible,
|
|
321
|
+
}, [collapsible, setCollapsed, onCollapseChange, onSizeChange]);
|
|
233
322
|
|
|
234
323
|
const expand = useCallback(() => {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
onSizeChange?.(
|
|
241
|
-
}, [
|
|
242
|
-
resolvedDefault,
|
|
243
|
-
minSizePx,
|
|
244
|
-
maxSizePx,
|
|
245
|
-
snaps,
|
|
246
|
-
onCollapseChange,
|
|
247
|
-
onSizeChange,
|
|
248
|
-
]);
|
|
324
|
+
const wasCollapsed = isCollapsedRef.current;
|
|
325
|
+
setCollapsed(false);
|
|
326
|
+
if (wasCollapsed) {
|
|
327
|
+
onCollapseChange?.(false);
|
|
328
|
+
}
|
|
329
|
+
onSizeChange?.(size);
|
|
330
|
+
}, [setCollapsed, size, onCollapseChange, onSizeChange]);
|
|
249
331
|
|
|
250
332
|
const resize = useCallback(
|
|
251
333
|
(newSize: number) => {
|
|
252
334
|
const clamped = clampSize(newSize, minSizePx, maxSizePx, snaps);
|
|
335
|
+
const wasCollapsed = isCollapsedRef.current;
|
|
253
336
|
setSize(clamped);
|
|
254
|
-
|
|
337
|
+
setCollapsed(false);
|
|
338
|
+
// Resizing out of the collapsed state is an implicit expand — notify
|
|
339
|
+
// like the drag path does when it crosses back over the threshold.
|
|
340
|
+
if (wasCollapsed) {
|
|
341
|
+
onCollapseChange?.(false);
|
|
342
|
+
}
|
|
255
343
|
onSizeChange?.(clamped);
|
|
256
344
|
},
|
|
257
|
-
[minSizePx, maxSizePx, snaps, onSizeChange],
|
|
345
|
+
[minSizePx, maxSizePx, snaps, setCollapsed, onCollapseChange, onSizeChange],
|
|
258
346
|
);
|
|
259
347
|
|
|
260
348
|
const onResizeStart = useCallback(() => {
|
|
261
|
-
dragStartSizeRef.current =
|
|
262
|
-
}, [size
|
|
349
|
+
dragStartSizeRef.current = isCollapsedRef.current ? 0 : size;
|
|
350
|
+
}, [size]);
|
|
263
351
|
|
|
264
352
|
const onResizeMove = useCallback(
|
|
265
353
|
(delta: number) => {
|
|
266
354
|
const raw = dragStartSizeRef.current + delta;
|
|
267
355
|
if (collapsible && raw < collapsedSize) {
|
|
268
|
-
if (!
|
|
269
|
-
|
|
356
|
+
if (!isCollapsedRef.current) {
|
|
357
|
+
setCollapsed(true);
|
|
270
358
|
onCollapseChange?.(true);
|
|
359
|
+
onSizeChange?.(0);
|
|
271
360
|
}
|
|
272
|
-
setIsCollapsed(true);
|
|
273
|
-
setSize(0);
|
|
274
|
-
onSizeChange?.(0);
|
|
275
361
|
return;
|
|
276
362
|
}
|
|
277
|
-
if (
|
|
278
|
-
|
|
363
|
+
if (isCollapsedRef.current && raw >= collapsedSize) {
|
|
364
|
+
setCollapsed(false);
|
|
279
365
|
onCollapseChange?.(false);
|
|
280
366
|
}
|
|
281
367
|
const clamped = clampSize(raw, minSizePx, maxSizePx, snaps);
|
|
@@ -285,8 +371,7 @@ function useSingleResizable(config: UseResizableSingleConfig): ResizableRegion {
|
|
|
285
371
|
[
|
|
286
372
|
collapsible,
|
|
287
373
|
collapsedSize,
|
|
288
|
-
|
|
289
|
-
size,
|
|
374
|
+
setCollapsed,
|
|
290
375
|
minSizePx,
|
|
291
376
|
maxSizePx,
|
|
292
377
|
snaps,
|