@astryxdesign/core 0.4.4 → 0.4.5-canary.0472ec1
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 +40 -0
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -1
- package/dist/Blockquote/Blockquote.d.ts +4 -3
- package/dist/Blockquote/Blockquote.d.ts.map +1 -1
- package/dist/Blockquote/Blockquote.js +9 -10
- package/dist/BottomSheet/BottomSheet.d.ts +11 -2
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +4 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +77 -18
- package/dist/BottomSheet/index.d.ts +1 -1
- package/dist/BottomSheet/index.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.d.ts +57 -20
- package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.js +106 -30
- package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +160 -64
- package/dist/Breadcrumbs/BreadcrumbItem.js +6 -6
- package/dist/Button/Button.js +5 -5
- package/dist/Calendar/Calendar.d.ts +17 -0
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +55 -15
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
- package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarDays.js +14 -10
- package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
- package/dist/Calendar/styles.js +3 -3
- package/dist/Center/Center.d.ts +23 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +12 -6
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +2 -2
- package/dist/Chat/ChatToolCalls.js +1 -1
- package/dist/Chat/useChatDictation.d.ts +1 -1
- package/dist/Chat/useChatDictation.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.d.ts +1 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +4 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +9 -0
- package/dist/Citation/Citation.js +3 -3
- package/dist/ClickableCard/ClickableCard.js +2 -2
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +8 -3
- package/dist/DateInput/DateInput.d.ts +31 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +92 -19
- package/dist/DateInput/MonthScroller.d.ts +35 -0
- package/dist/DateInput/MonthScroller.d.ts.map +1 -0
- package/dist/DateInput/MonthScroller.js +573 -0
- package/dist/DateInput/MonthYearWheels.d.ts +24 -0
- package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
- package/dist/DateInput/MonthYearWheels.js +114 -0
- package/dist/DateInput/TouchDateField.d.ts +10 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -0
- package/dist/DateInput/TouchDateField.js +810 -0
- package/dist/DateInput/Wheel.d.ts +41 -0
- package/dist/DateInput/Wheel.d.ts.map +1 -0
- package/dist/DateInput/Wheel.js +315 -0
- package/dist/DateInput/monthGeometry.d.ts +65 -0
- package/dist/DateInput/monthGeometry.d.ts.map +1 -0
- package/dist/DateInput/monthGeometry.js +98 -0
- package/dist/DateInput/tokens.stylex.d.ts +63 -0
- package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
- package/dist/DateInput/tokens.stylex.js +74 -0
- package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
- package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
- package/dist/DateInput/useOwnScrollGesture.js +202 -0
- package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
- package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
- package/dist/DateInput/usePointerDragScroll.js +216 -0
- package/dist/DateInput/useScrollSettle.d.ts +26 -0
- package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
- package/dist/DateInput/useScrollSettle.js +149 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +47 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +18 -10
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +3 -3
- package/dist/Field/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +21 -3
- package/dist/Field/InputClearButton.d.ts +2 -1
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +12 -1
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +4 -4
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +2 -2
- package/dist/FormLayout/FormLayout.d.ts +24 -2
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +7 -2
- package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
- package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
- package/dist/FormLayout/FormLayoutContext.js +19 -4
- package/dist/FormLayout/index.d.ts +1 -1
- package/dist/FormLayout/index.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.d.ts +13 -3
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/index.d.ts +1 -1
- package/dist/HoverCard/index.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.d.ts +17 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +78 -9
- package/dist/Item/Item.d.ts +9 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +46 -8
- package/dist/Layer/index.d.ts +4 -2
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +2 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +3 -2
- package/dist/Layer/useTouchTrigger.d.ts +113 -0
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
- package/dist/Layer/useTouchTrigger.js +241 -0
- package/dist/Layout/container.stylex.d.ts +4 -2
- package/dist/Layout/container.stylex.d.ts.map +1 -1
- package/dist/Layout/container.stylex.js +19 -11
- package/dist/Layout/index.d.ts +1 -0
- package/dist/Layout/index.d.ts.map +1 -1
- package/dist/Layout/index.js +4 -0
- package/dist/Layout/padding.stylex.d.ts +315 -12
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +389 -12
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +2 -1
- package/dist/Link/Link.js +4 -4
- package/dist/Markdown/Markdown.d.ts +8 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +31 -3
- package/dist/Markdown/parser.d.ts +14 -2
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +50 -2
- package/dist/MobileNav/MobileNav.d.ts +1 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +24 -6
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +8 -3
- package/dist/NavItem/navItemStyles.stylex.d.ts +2 -2
- package/dist/NavItem/navItemStyles.stylex.js +2 -2
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +38 -5
- package/dist/Outline/Outline.js +2 -2
- package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +11 -12
- package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchToken.js +3 -1
- package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +23 -8
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +12 -1
- package/dist/RadioList/RadioListItem.d.ts +2 -2
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +68 -38
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -3
- package/dist/Section/Section.d.ts +36 -1
- package/dist/Section/Section.d.ts.map +1 -1
- package/dist/Section/Section.js +12 -2
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +6 -1
- package/dist/SelectableCard/SelectableCard.js +1 -1
- package/dist/Selector/Selector.d.ts +26 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +95 -17
- package/dist/Selector/SelectorOption.d.ts +14 -1
- package/dist/Selector/SelectorOption.d.ts.map +1 -1
- package/dist/Selector/SelectorOption.js +6 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
- package/dist/Selector/SelectorRowLayoutContext.js +27 -0
- package/dist/Selector/types.d.ts +1 -0
- package/dist/Selector/types.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -3
- package/dist/Stack/Stack.d.ts +23 -1
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +12 -6
- package/dist/StatusDot/StatusDot.d.ts +43 -3
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +42 -5
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +9 -0
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/TableRow.js +4 -4
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
- package/dist/Table/plugins/tree/useTableTreeData.js +2 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +6 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +6 -1
- package/dist/Thumbnail/Thumbnail.js +1 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +6 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +6 -4
- package/dist/Timestamp/formatInstant.d.ts +3 -2
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +8 -8
- package/dist/Timestamp/tooltipEntries.d.ts +2 -1
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.js +5 -3
- package/dist/Token/Token.js +1 -1
- package/dist/Tooltip/Tooltip.d.ts +16 -3
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.js +2 -0
- package/dist/Tooltip/index.d.ts +1 -1
- package/dist/Tooltip/index.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +21 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +71 -13
- package/dist/TopNav/TopNavHeading.js +2 -2
- package/dist/TopNav/TopNavItem.js +2 -2
- package/dist/TopNav/TopNavMegaMenu.js +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
- package/dist/TopNav/TopNavMenu.js +2 -2
- package/dist/TreeList/TreeListItem.js +1 -1
- package/dist/astryx.css +123 -60
- package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
- package/dist/hooks/containerReveal.stylex.js +18 -18
- package/dist/hooks/scrollbarGutter.d.ts +28 -0
- package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
- package/dist/hooks/scrollbarGutter.js +103 -0
- package/dist/hooks/useResolvedRequired.d.ts +19 -0
- package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
- package/dist/hooks/useResolvedRequired.js +40 -0
- package/dist/hooks/useScrollLock.d.ts +4 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.js +13 -1
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +2 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +6 -0
- package/dist/i18n/useCollator.d.ts +12 -0
- package/dist/i18n/useCollator.d.ts.map +1 -0
- package/dist/i18n/useCollator.js +40 -0
- package/dist/i18n/useLocale.d.ts +3 -0
- package/dist/i18n/useLocale.d.ts.map +1 -0
- package/dist/i18n/useLocale.js +31 -0
- package/dist/theme/defineTheme.d.ts +5 -0
- 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 +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +66 -5
- package/dist/theme/syntax/index.d.ts +6 -0
- package/dist/theme/syntax/index.d.ts.map +1 -1
- package/dist/theme/syntax/index.js +7 -2
- package/dist/utils/dateParser.d.ts +4 -3
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +8 -8
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/plainDate.d.ts +11 -2
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +32 -4
- package/locales/af-ZA.json +958 -0
- package/locales/ar-SA.json +998 -0
- package/locales/ca-ES.json +974 -0
- package/locales/cs-CZ.json +990 -0
- package/locales/da-DK.json +966 -0
- package/locales/de-DE.json +966 -0
- package/locales/el-GR.json +990 -0
- package/locales/en.json +32 -0
- package/locales/es-ES.json +978 -0
- package/locales/fi-FI.json +990 -0
- package/locales/fr-FR.json +928 -0
- package/locales/he-IL.json +990 -0
- package/locales/hu-HU.json +990 -0
- package/locales/it-IT.json +978 -0
- package/locales/ja-JP.json +998 -0
- package/locales/ko-KR.json +990 -0
- package/locales/nl-NL.json +954 -0
- package/locales/no-NO.json +978 -0
- package/locales/pl-PL.json +982 -0
- package/locales/pseudo.json +24 -0
- package/locales/pt-BR.json +982 -0
- package/locales/pt-PT.json +982 -0
- package/locales/ro-RO.json +982 -0
- package/locales/ru-RU.json +990 -0
- package/locales/sr-SP.json +990 -0
- package/locales/sv-SE.json +986 -0
- package/locales/tr-TR.json +990 -0
- package/locales/uk-UA.json +990 -0
- package/locales/vi-VN.json +986 -0
- package/locales/zh-CN.json +998 -0
- package/locales/zh-TW.json +998 -0
- package/package.json +3 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -1
- package/src/Banner/Banner.doc.mjs +2 -0
- package/src/Blockquote/Blockquote.doc.mjs +30 -7
- package/src/Blockquote/Blockquote.test.tsx +34 -3
- package/src/Blockquote/Blockquote.tsx +11 -9
- package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
- package/src/BottomSheet/BottomSheet.test.tsx +177 -2
- package/src/BottomSheet/BottomSheet.tsx +16 -2
- package/src/BottomSheet/BottomSheetPanel.test.tsx +91 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +121 -15
- package/src/BottomSheet/index.ts +5 -1
- package/src/BottomSheet/snapOffsets.test.ts +114 -47
- package/src/BottomSheet/snapOffsets.ts +119 -33
- package/src/BottomSheet/useSheetGestures.test.ts +113 -15
- package/src/BottomSheet/useSheetGestures.ts +196 -100
- package/src/Breadcrumbs/BreadcrumbItem.tsx +1 -1
- package/src/Button/Button.tsx +7 -7
- package/src/Calendar/Calendar.doc.mjs +16 -0
- package/src/Calendar/Calendar.test.tsx +137 -0
- package/src/Calendar/Calendar.tsx +80 -11
- package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
- package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
- package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
- package/src/Calendar/hooks/useCalendarDays.ts +13 -10
- package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
- package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
- package/src/Calendar/styles.ts +3 -3
- package/src/Center/Center.doc.mjs +48 -0
- package/src/Center/Center.test.tsx +158 -0
- package/src/Center/Center.tsx +50 -9
- package/src/Chat/ChatComposer.tsx +7 -4
- package/src/Chat/ChatToolCalls.tsx +1 -1
- package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
- package/src/Chat/useChatDictation.ts +1 -1
- package/src/Chat/useSpeechRecognition.ts +5 -3
- package/src/CheckboxInput/CheckboxInput.tsx +6 -0
- package/src/Citation/Citation.tsx +3 -3
- package/src/ClickableCard/ClickableCard.tsx +2 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
- package/src/ComplexSelector/ComplexSelector.tsx +8 -5
- package/src/DateInput/DateInput.test.tsx +17 -1
- package/src/DateInput/DateInput.tsx +90 -19
- package/src/DateInput/DateInputTouch.test.tsx +2393 -0
- package/src/DateInput/MonthScroller.tsx +784 -0
- package/src/DateInput/MonthYearWheels.tsx +147 -0
- package/src/DateInput/TouchDateField.tsx +1214 -0
- package/src/DateInput/Wheel.tsx +470 -0
- package/src/DateInput/monthGeometry.ts +118 -0
- package/src/DateInput/tokens.stylex.ts +99 -0
- package/src/DateInput/useOwnScrollGesture.ts +227 -0
- package/src/DateInput/usePointerDragScroll.ts +220 -0
- package/src/DateInput/useScrollSettle.ts +164 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
- package/src/DateRangeInput/DateRangeInput.tsx +88 -8
- package/src/DateTimeInput/DateTimeInput.tsx +23 -8
- package/src/Dialog/Dialog.test.tsx +24 -0
- package/src/Dialog/Dialog.tsx +3 -0
- package/src/Field/Field.doc.mjs +3 -0
- package/src/Field/FieldLabel.tsx +20 -4
- package/src/Field/InputClearButton.test.tsx +134 -2
- package/src/Field/InputClearButton.tsx +42 -1
- package/src/Field/inputStyles.stylex.ts +16 -12
- package/src/FileInput/FileInput.tsx +5 -4
- package/src/FormLayout/FormLayout.doc.mjs +13 -0
- package/src/FormLayout/FormLayout.test.tsx +181 -4
- package/src/FormLayout/FormLayout.tsx +33 -2
- package/src/FormLayout/FormLayoutContext.ts +22 -7
- package/src/FormLayout/index.ts +1 -1
- package/src/HoverCard/HoverCard.doc.mjs +18 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -0
- package/src/HoverCard/HoverCard.tsx +22 -2
- package/src/HoverCard/index.ts +1 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +103 -7
- package/src/Item/Item.doc.mjs +1 -0
- package/src/Item/Item.test.tsx +50 -0
- package/src/Item/Item.tsx +41 -2
- package/src/Layer/index.ts +10 -0
- package/src/Layer/useLayer.tsx +13 -2
- package/src/Layer/useTouchTrigger.test.ts +70 -0
- package/src/Layer/useTouchTrigger.ts +366 -0
- package/src/Layout/Layout.doc.mjs +18 -0
- package/src/Layout/container.stylex.ts +11 -3
- package/src/Layout/index.ts +4 -0
- package/src/Layout/overlayPaddingReset.test.tsx +222 -0
- package/src/Layout/padding.stylex.ts +192 -12
- package/src/Lightbox/Lightbox.tsx +2 -1
- package/src/Link/Link.tsx +4 -4
- package/src/Markdown/Markdown.doc.mjs +3 -0
- package/src/Markdown/Markdown.test.tsx +78 -0
- package/src/Markdown/Markdown.tsx +41 -1
- package/src/Markdown/parser.ts +60 -2
- package/src/MobileNav/MobileNav.tsx +61 -5
- package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
- package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
- package/src/MultiSelector/MultiSelector.test.tsx +1 -1
- package/src/MultiSelector/MultiSelector.tsx +8 -5
- package/src/NavItem/navItemStyles.stylex.ts +2 -2
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +24 -0
- package/src/NumberInput/NumberInput.test.tsx +138 -0
- package/src/NumberInput/NumberInput.tsx +44 -6
- package/src/Outline/Outline.doc.mjs +2 -0
- package/src/Outline/Outline.tsx +1 -1
- package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
- package/src/PowerSearch/PowerSearch.tsx +17 -8
- package/src/PowerSearch/PowerSearchToken.tsx +3 -0
- package/src/PowerSearch/formatFilterValue.test.ts +22 -2
- package/src/PowerSearch/formatFilterValue.ts +31 -6
- package/src/RadioList/RadioList.doc.mjs +1 -1
- package/src/RadioList/RadioList.test.tsx +170 -2
- package/src/RadioList/RadioList.tsx +9 -1
- package/src/RadioList/RadioListItem.tsx +83 -51
- package/src/Resizable/ResizeHandle.test.tsx +22 -0
- package/src/Resizable/ResizeHandle.tsx +9 -3
- package/src/Section/Section.doc.mjs +55 -0
- package/src/Section/Section.test.tsx +201 -4
- package/src/Section/Section.tsx +69 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +11 -2
- package/src/SelectableCard/SelectableCard.tsx +1 -1
- package/src/Selector/Selector.doc.mjs +16 -2
- package/src/Selector/Selector.test.tsx +525 -1
- package/src/Selector/Selector.tsx +166 -21
- package/src/Selector/SelectorOption.doc.mjs +7 -0
- package/src/Selector/SelectorOption.tsx +21 -0
- package/src/Selector/SelectorRowLayoutContext.ts +32 -0
- package/src/Selector/types.ts +4 -4
- package/src/SideNav/SideNavHeading.tsx +2 -2
- package/src/SideNav/SideNavItem.tsx +1 -1
- package/src/Slider/Slider.tsx +11 -1
- package/src/Stack/Stack.doc.mjs +72 -0
- package/src/Stack/Stack.test.tsx +156 -0
- package/src/Stack/Stack.tsx +50 -8
- package/src/StatusDot/StatusDot.doc.mjs +13 -0
- package/src/StatusDot/StatusDot.test.tsx +115 -8
- package/src/StatusDot/StatusDot.tsx +74 -9
- package/src/Switch/Switch.tsx +6 -0
- package/src/TabList/TabMenu.tsx +1 -1
- package/src/Table/TableRow.tsx +4 -4
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +2 -1
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +2 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +22 -4
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
- package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
- package/src/Table/plugins/tree/useTableTreeData.tsx +2 -2
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.tsx +3 -1
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/Thumbnail/Thumbnail.tsx +1 -1
- package/src/TimeInput/TimeInput.tsx +3 -1
- package/src/Timestamp/Timestamp.test.tsx +27 -7
- package/src/Timestamp/Timestamp.tsx +8 -4
- package/src/Timestamp/formatInstant.ts +9 -7
- package/src/Timestamp/tooltipEntries.test.ts +11 -6
- package/src/Timestamp/tooltipEntries.ts +6 -2
- package/src/Token/Token.tsx +1 -1
- package/src/Tooltip/Tooltip.doc.mjs +18 -0
- package/src/Tooltip/Tooltip.test.tsx +254 -1
- package/src/Tooltip/Tooltip.tsx +22 -2
- package/src/Tooltip/index.ts +1 -0
- package/src/Tooltip/useTooltip.doc.mjs +2 -0
- package/src/Tooltip/useTooltip.tsx +99 -21
- package/src/TopNav/TopNavHeading.tsx +1 -1
- package/src/TopNav/TopNavItem.tsx +2 -2
- package/src/TopNav/TopNavMegaMenu.tsx +1 -1
- package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
- package/src/TopNav/TopNavMenu.tsx +2 -2
- package/src/TreeList/TreeListItem.tsx +1 -1
- package/src/hooks/containerReveal.stylex.ts +54 -18
- package/src/hooks/scrollbarGutter.test.ts +167 -0
- package/src/hooks/scrollbarGutter.ts +121 -0
- package/src/hooks/useResolvedRequired.ts +42 -0
- package/src/hooks/useScrollLock.doc.mjs +4 -4
- package/src/hooks/useScrollLock.test.ts +73 -0
- package/src/hooks/useScrollLock.ts +14 -0
- package/src/i18n/InternationalizationContext.ts +2 -0
- package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
- package/src/i18n/__tests__/useCollator.test.tsx +115 -0
- package/src/i18n/__tests__/useLocale.test.tsx +52 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/useCollator.doc.mjs +84 -0
- package/src/i18n/useCollator.ts +44 -0
- package/src/i18n/useLocale.doc.mjs +70 -0
- package/src/i18n/useLocale.ts +34 -0
- package/src/i18n/useTranslator.doc.mjs +1 -1
- package/src/theme/defineTheme.test.ts +9 -3
- package/src/theme/defineTheme.ts +5 -0
- package/src/theme/derivedVarRegistry.test.ts +19 -5
- package/src/theme/derivedVarRegistry.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +118 -0
- package/src/theme/generateThemeRules.ts +83 -5
- package/src/theme/syntax/index.ts +6 -2
- package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
- package/src/utils/dateParser.test.ts +20 -0
- package/src/utils/dateParser.ts +14 -7
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +56 -0
- package/src/utils/plainDate.ts +33 -4
|
@@ -237,4 +237,95 @@ describe('BottomSheetPanel', () => {
|
|
|
237
237
|
expect(panelRef).toHaveBeenLastCalledWith(null);
|
|
238
238
|
expect(panelRef).toHaveBeenCalledTimes(2);
|
|
239
239
|
});
|
|
240
|
+
|
|
241
|
+
it('floats the handle bar over content that starts at the sheet top edge', () => {
|
|
242
|
+
renderPanel({kind: 'open', entering: false});
|
|
243
|
+
|
|
244
|
+
const bar = getPanel().querySelector<HTMLElement>(
|
|
245
|
+
'div[aria-hidden="true"]',
|
|
246
|
+
);
|
|
247
|
+
if (bar == null) {
|
|
248
|
+
throw new Error('handle bar not found');
|
|
249
|
+
}
|
|
250
|
+
const body = bar.nextElementSibling as HTMLElement;
|
|
251
|
+
|
|
252
|
+
// Out of flow: the bar costs the content no layout space. That is the
|
|
253
|
+
// point of it -- the content sits closer to the sheet's top edge, and
|
|
254
|
+
// scrolled content passes beneath the pill rather than stopping at a
|
|
255
|
+
// hard edge.
|
|
256
|
+
expect(getComputedStyle(bar).position).toBe('absolute');
|
|
257
|
+
|
|
258
|
+
// So the body must not reserve room for it. A top padding here would
|
|
259
|
+
// push the content back down and undo the change.
|
|
260
|
+
expect(getComputedStyle(body).paddingTop).toBe('');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// The pill is only legible over the content riding up beneath it because
|
|
264
|
+
// the bar carries a backdrop; without it, text runs straight through the
|
|
265
|
+
// pill. jsdom's StyleX runtime does not inject the rule, so assert on the
|
|
266
|
+
// style definition itself (same approach as AspectRatio's reset.css tests).
|
|
267
|
+
it('backs the floating handle bar with a surface gradient', async () => {
|
|
268
|
+
const fs = await import('fs');
|
|
269
|
+
const path = await import('path');
|
|
270
|
+
const source = fs.readFileSync(
|
|
271
|
+
path.resolve(__dirname, './BottomSheetPanel.tsx'),
|
|
272
|
+
'utf-8',
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
const handleBar = source.match(/handleBar: \{([\s\S]*?)\n {2}\},/);
|
|
276
|
+
expect(handleBar).not.toBeNull();
|
|
277
|
+
expect(handleBar![1]).toContain("position: 'absolute'");
|
|
278
|
+
expect(handleBar![1]).toContain('linear-gradient(to bottom');
|
|
279
|
+
expect(handleBar![1]).toContain("colorVars['--color-background-surface']");
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// In dark mode the surface fill and the scrim sit a few RGB steps apart and
|
|
283
|
+
// the drop shadow is black on near-black, so the fill alone leaves the
|
|
284
|
+
// sheet's left and right edges invisible against the scrim. A hairline on
|
|
285
|
+
// the scrim-facing edges is what draws them. Asserted on the style
|
|
286
|
+
// definition for the same reason as the test above.
|
|
287
|
+
it('draws a hairline on the three edges that face the scrim', async () => {
|
|
288
|
+
const fs = await import('fs');
|
|
289
|
+
const path = await import('path');
|
|
290
|
+
const source = fs.readFileSync(
|
|
291
|
+
path.resolve(__dirname, './BottomSheetPanel.tsx'),
|
|
292
|
+
'utf-8',
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const sheet = source.match(/\n {2}sheet: \{([\s\S]*?)\n {2}\},/);
|
|
296
|
+
expect(sheet).not.toBeNull();
|
|
297
|
+
for (const edge of [
|
|
298
|
+
'borderBlockStart',
|
|
299
|
+
'borderInlineStart',
|
|
300
|
+
'borderInlineEnd',
|
|
301
|
+
]) {
|
|
302
|
+
expect(sheet![1]).toContain(`${edge}Width: borderVars['--border-width']`);
|
|
303
|
+
expect(sheet![1]).toContain(`${edge}Style: 'solid'`);
|
|
304
|
+
expect(sheet![1]).toContain(`${edge}Color: colorVars['--color-border']`);
|
|
305
|
+
}
|
|
306
|
+
// The block-end edge sits below the viewport, under the overscroll
|
|
307
|
+
// padding, so it carries no hairline to draw.
|
|
308
|
+
expect(sheet![1]).not.toContain('borderBlockEndWidth');
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// A theme that packs an inset ring into --shadow-high (the bundled themes all
|
|
312
|
+
// add one in dark mode) draws it just inside the sheet, where an opaque
|
|
313
|
+
// content wrapper such as Section paints over it -- so it showed only in the
|
|
314
|
+
// gap below the content and the side edges appeared to change width partway
|
|
315
|
+
// down. The scrolling body paints the surface across the whole inner box to
|
|
316
|
+
// hide the ring evenly.
|
|
317
|
+
it('paints the surface across the scrolling body so the edge stays uniform', async () => {
|
|
318
|
+
const fs = await import('fs');
|
|
319
|
+
const path = await import('path');
|
|
320
|
+
const source = fs.readFileSync(
|
|
321
|
+
path.resolve(__dirname, './BottomSheetPanel.tsx'),
|
|
322
|
+
'utf-8',
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
const body = source.match(/\n {2}body: \{([\s\S]*?)\n {2}\},/);
|
|
326
|
+
expect(body).not.toBeNull();
|
|
327
|
+
expect(body![1]).toContain(
|
|
328
|
+
"backgroundColor: colorVars['--color-background-surface']",
|
|
329
|
+
);
|
|
330
|
+
});
|
|
240
331
|
});
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* SYNC: When modified, update these files to stay in sync:
|
|
17
17
|
* - /packages/core/src/BottomSheet/BottomSheet.tsx
|
|
18
18
|
* - /packages/core/src/BottomSheet/BottomSheetPanel.test.tsx
|
|
19
|
+
* - /packages/core/src/BottomSheet/snapOffsets.ts
|
|
19
20
|
* - /packages/core/src/BottomSheet/useMobileKeyboard.ts
|
|
20
21
|
* - /packages/core/src/BottomSheet/useSheetGestures.ts
|
|
21
22
|
*/
|
|
@@ -25,12 +26,15 @@ import {
|
|
|
25
26
|
useEffect,
|
|
26
27
|
useImperativeHandle,
|
|
27
28
|
useLayoutEffect,
|
|
29
|
+
useMemo,
|
|
28
30
|
useRef,
|
|
29
31
|
type ReactNode,
|
|
30
32
|
} from 'react';
|
|
31
33
|
import * as stylex from '@stylexjs/stylex';
|
|
32
34
|
import type {BaseProps} from '../BaseProps';
|
|
35
|
+
import {useDevWarning} from '../hooks';
|
|
33
36
|
import {
|
|
37
|
+
borderVars,
|
|
34
38
|
colorVars,
|
|
35
39
|
durationVars,
|
|
36
40
|
easeVars,
|
|
@@ -40,11 +44,15 @@ import {
|
|
|
40
44
|
spacingVars,
|
|
41
45
|
} from '../theme/tokens.stylex';
|
|
42
46
|
import {mergeProps, themeProps} from '../utils';
|
|
47
|
+
import {overlayPaddingReset} from '../Layout/padding.stylex';
|
|
48
|
+
import {
|
|
49
|
+
isValidSnapPoint,
|
|
50
|
+
resolveSnapPoints,
|
|
51
|
+
type BottomSheetSnapPoint,
|
|
52
|
+
} from './snapOffsets';
|
|
43
53
|
import {useMobileKeyboard} from './useMobileKeyboard';
|
|
44
54
|
import {useSheetGestures} from './useSheetGestures';
|
|
45
55
|
|
|
46
|
-
const SNAP_FRACTIONS = [0.14, 0.5, 0.92];
|
|
47
|
-
|
|
48
56
|
const HEIGHT_BUDGETS = {
|
|
49
57
|
hug: '92dvh',
|
|
50
58
|
capped: '62dvh',
|
|
@@ -52,35 +60,75 @@ const HEIGHT_BUDGETS = {
|
|
|
52
60
|
} as const;
|
|
53
61
|
|
|
54
62
|
export type BottomSheetHeight = keyof typeof HEIGHT_BUDGETS;
|
|
63
|
+
export type {BottomSheetSnapPoint};
|
|
55
64
|
|
|
56
65
|
// SYNC: must match OVERSCROLL_MAX in useSheetGestures.ts.
|
|
57
66
|
const OVERSCROLL_PADDING = 48;
|
|
58
67
|
const MOBILE_KEYBOARD_BOTTOM_CLEARANCE = 48;
|
|
59
68
|
const TRANSITION_BACKSTOP_BUFFER_MS = 50;
|
|
69
|
+
// The floating handle bar's height. The bar is out of flow, so this is not
|
|
70
|
+
// layout space the content pays for -- the pill (4px, centered) lands 10-14px
|
|
71
|
+
// from the sheet's top edge, inside the space a content wrapper's own top
|
|
72
|
+
// padding already provides.
|
|
73
|
+
const HANDLE_BAR_HEIGHT = spacingVars['--spacing-6'];
|
|
74
|
+
|
|
75
|
+
// Measure the same viewport the height budgets are written against. Those are
|
|
76
|
+
// `dvh`, which the virtual keyboard does not shrink, so reading
|
|
77
|
+
// `visualViewport` here would make the two disagree by exactly the keyboard's
|
|
78
|
+
// height: every detent would move while the sheet it measures did not. A
|
|
79
|
+
// keyboard is `useMobileKeyboard`'s business — it holds the sheet still and
|
|
80
|
+
// scrolls the body — and it does not redefine the sheet's detents.
|
|
81
|
+
function layoutViewportHeight(): number {
|
|
82
|
+
return typeof window === 'undefined' ? 0 : window.innerHeight;
|
|
83
|
+
}
|
|
60
84
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
85
|
+
/**
|
|
86
|
+
* A stable identity for a set of snap points. Type-tagged, so the fraction
|
|
87
|
+
* `0.5` and the (invalid) string `'0.5'` cannot collide on one key.
|
|
88
|
+
*
|
|
89
|
+
* Recomputed every render — the panel re-renders on every frame of a drag — so
|
|
90
|
+
* it stays a single pass over a handful of values, and everything derived from
|
|
91
|
+
* the points hangs off it instead of being rebuilt per frame.
|
|
92
|
+
*/
|
|
93
|
+
function snapPointsKeyFor(
|
|
94
|
+
points: ReadonlyArray<BottomSheetSnapPoint> | undefined,
|
|
95
|
+
): string {
|
|
96
|
+
let key = '';
|
|
97
|
+
for (const point of points ?? []) {
|
|
98
|
+
key += `${typeof point}:${point}|`;
|
|
64
99
|
}
|
|
65
|
-
|
|
66
|
-
// are `dvh`, which the virtual keyboard does not shrink, so reading
|
|
67
|
-
// `visualViewport` here made the two disagree by exactly the keyboard's
|
|
68
|
-
// height: every detent moved while the sheet it was measuring did not. A
|
|
69
|
-
// keyboard is `useMobileKeyboard`'s business — it holds the sheet still and
|
|
70
|
-
// scrolls the body — and it does not redefine the sheet's detents.
|
|
71
|
-
return SNAP_FRACTIONS.map(fraction => fraction * window.innerHeight);
|
|
100
|
+
return key;
|
|
72
101
|
}
|
|
73
102
|
|
|
74
103
|
const styles = stylex.create({
|
|
75
104
|
sheet: {
|
|
76
105
|
pointerEvents: 'auto',
|
|
77
106
|
boxSizing: 'border-box',
|
|
107
|
+
// Containing block for the floating handle bar, which is lifted out of
|
|
108
|
+
// flow so the scrolling body reaches the sheet's top edge.
|
|
109
|
+
position: 'relative',
|
|
78
110
|
display: 'flex',
|
|
79
111
|
flexDirection: 'column',
|
|
80
112
|
minHeight: 0,
|
|
81
113
|
width: '100%',
|
|
82
114
|
maxWidth: 640,
|
|
83
115
|
backgroundColor: colorVars['--color-background-surface'],
|
|
116
|
+
// Hairline on the three edges that face the scrim. The surface fill alone
|
|
117
|
+
// separates sheet from scrim in light mode, but not in dark: there the two
|
|
118
|
+
// sit within a few RGB steps of each other and the drop shadow is black on
|
|
119
|
+
// near-black, so the sheet's left and right edges disappear. Same
|
|
120
|
+
// treatment MobileNav gives its scrim-facing edge. The block-end edge is
|
|
121
|
+
// deliberately left bare; it sits below the viewport, under the overscroll
|
|
122
|
+
// padding.
|
|
123
|
+
borderBlockStartWidth: borderVars['--border-width'],
|
|
124
|
+
borderBlockStartStyle: 'solid',
|
|
125
|
+
borderBlockStartColor: colorVars['--color-border'],
|
|
126
|
+
borderInlineStartWidth: borderVars['--border-width'],
|
|
127
|
+
borderInlineStartStyle: 'solid',
|
|
128
|
+
borderInlineStartColor: colorVars['--color-border'],
|
|
129
|
+
borderInlineEndWidth: borderVars['--border-width'],
|
|
130
|
+
borderInlineEndStyle: 'solid',
|
|
131
|
+
borderInlineEndColor: colorVars['--color-border'],
|
|
84
132
|
borderStartStartRadius: radiusVars['--radius-container'],
|
|
85
133
|
borderStartEndRadius: radiusVars['--radius-container'],
|
|
86
134
|
boxShadow: shadowVars['--shadow-high'],
|
|
@@ -111,11 +159,23 @@ const styles = stylex.create({
|
|
|
111
159
|
pointerEvents: 'none',
|
|
112
160
|
},
|
|
113
161
|
handleBar: {
|
|
114
|
-
|
|
162
|
+
// Floats over the body rather than taking a row in the flex column. The
|
|
163
|
+
// content starts at the sheet's top edge and rides up under the pill --
|
|
164
|
+
// both moving it closer to the top and letting scrolled content pass
|
|
165
|
+
// beneath instead of stopping at a hard edge.
|
|
166
|
+
position: 'absolute',
|
|
167
|
+
insetBlockStart: 0,
|
|
168
|
+
insetInlineStart: 0,
|
|
169
|
+
insetInlineEnd: 0,
|
|
170
|
+
zIndex: 1,
|
|
115
171
|
display: 'flex',
|
|
116
172
|
alignItems: 'center',
|
|
117
173
|
justifyContent: 'center',
|
|
118
|
-
height:
|
|
174
|
+
height: HANDLE_BAR_HEIGHT,
|
|
175
|
+
// Keeps the pill legible over whatever sits or scrolls under it: opaque
|
|
176
|
+
// surface behind the pill itself, fading out across the lower half so the
|
|
177
|
+
// content emerging below has no visible cut line.
|
|
178
|
+
backgroundImage: `linear-gradient(to bottom, ${colorVars['--color-background-surface']} 60%, transparent)`,
|
|
119
179
|
touchAction: 'none',
|
|
120
180
|
cursor: 'grab',
|
|
121
181
|
},
|
|
@@ -132,6 +192,19 @@ const styles = stylex.create({
|
|
|
132
192
|
overflowY: 'auto',
|
|
133
193
|
overscrollBehavior: 'none',
|
|
134
194
|
touchAction: 'pan-y',
|
|
195
|
+
// The scrolling area paints the surface itself, covering the sheet's whole
|
|
196
|
+
// inner box. Without it the sheet's edge is not uniform: a theme that packs
|
|
197
|
+
// an inset ring into --shadow-high (the bundled themes all add one in dark
|
|
198
|
+
// mode) draws that ring just inside the sheet, where an opaque content
|
|
199
|
+
// wrapper such as Section paints over it -- so the ring shows only in the
|
|
200
|
+
// gap below where the content ends, and the sheet's side edges appear to
|
|
201
|
+
// change width partway down. Painting the surface here hides the ring
|
|
202
|
+
// evenly, leaving the border below as the sheet's one edge.
|
|
203
|
+
backgroundColor: colorVars['--color-background-surface'],
|
|
204
|
+
// No reserve for the handle bar: it floats, so the content starts at the
|
|
205
|
+
// sheet's top edge and rides up under the pill. The pill is 4px centered
|
|
206
|
+
// in a 24px band, so it occupies only 10-14px from the edge -- inside the
|
|
207
|
+
// space a content wrapper's own top padding already provides.
|
|
135
208
|
paddingBlockEnd: 0,
|
|
136
209
|
},
|
|
137
210
|
tallKeyboardBody: {
|
|
@@ -171,6 +244,7 @@ interface BottomSheetPanelProps extends BaseProps<HTMLDivElement> {
|
|
|
171
244
|
state: BottomSheetPanelState;
|
|
172
245
|
height: BottomSheetHeight | number | string;
|
|
173
246
|
children: ReactNode;
|
|
247
|
+
snapPoints?: ReadonlyArray<BottomSheetSnapPoint>;
|
|
174
248
|
isSwipeDismissAllowed?: boolean;
|
|
175
249
|
/** Whether the host has locked page scrolling (a modal, scrim-backed sheet). */
|
|
176
250
|
isPageScrollLocked?: boolean;
|
|
@@ -296,6 +370,7 @@ export function BottomSheetPanel({
|
|
|
296
370
|
state,
|
|
297
371
|
height,
|
|
298
372
|
children,
|
|
373
|
+
snapPoints,
|
|
299
374
|
className,
|
|
300
375
|
style,
|
|
301
376
|
tabIndex,
|
|
@@ -340,6 +415,36 @@ export function BottomSheetPanel({
|
|
|
340
415
|
const isFading = isRetained && state.motion === 'fading';
|
|
341
416
|
const alignmentOffset = isRetained ? state.alignmentOffset : 0;
|
|
342
417
|
|
|
418
|
+
// Everything derived from the snap points keys off their identity, not the
|
|
419
|
+
// array's: the resolver's identity is the hook's signal that the stops
|
|
420
|
+
// changed, so it must not churn on a re-render the drag caused. The memo
|
|
421
|
+
// reads the points through a ref, so the resolver resolves them at call time
|
|
422
|
+
// — against whatever the viewport is then, not what it was at memo time.
|
|
423
|
+
const snapPointsKey = snapPointsKeyFor(snapPoints);
|
|
424
|
+
const snapPointsRef = useRef(snapPoints);
|
|
425
|
+
snapPointsRef.current = snapPoints;
|
|
426
|
+
const {snapHeights, ignoredSnapPointsMessage} = useMemo(() => {
|
|
427
|
+
if (snapPointsKey === '') {
|
|
428
|
+
return {snapHeights: undefined, ignoredSnapPointsMessage: ''};
|
|
429
|
+
}
|
|
430
|
+
const ignored = (snapPointsRef.current ?? []).filter(
|
|
431
|
+
point => !isValidSnapPoint(point),
|
|
432
|
+
);
|
|
433
|
+
return {
|
|
434
|
+
snapHeights: () =>
|
|
435
|
+
resolveSnapPoints(snapPointsRef.current ?? [], layoutViewportHeight()),
|
|
436
|
+
ignoredSnapPointsMessage:
|
|
437
|
+
ignored.length === 0
|
|
438
|
+
? ''
|
|
439
|
+
: `snapPoints ignored ${JSON.stringify(ignored)}. A snap point is a viewport fraction above 0 and up to 1 (0.5 is half the screen), a px length ('320px'), or a percentage ('50%').`,
|
|
440
|
+
};
|
|
441
|
+
}, [snapPointsKey]);
|
|
442
|
+
useDevWarning(
|
|
443
|
+
'BottomSheet',
|
|
444
|
+
ignoredSnapPointsMessage,
|
|
445
|
+
ignoredSnapPointsMessage !== '',
|
|
446
|
+
);
|
|
447
|
+
|
|
343
448
|
const {
|
|
344
449
|
contentProps,
|
|
345
450
|
handleProps,
|
|
@@ -359,7 +464,7 @@ export function BottomSheetPanel({
|
|
|
359
464
|
canDismiss: isSwipeDismissAllowed,
|
|
360
465
|
offscreenBlockEndInset: OVERSCROLL_PADDING,
|
|
361
466
|
onDismiss,
|
|
362
|
-
snapHeights
|
|
467
|
+
snapHeights,
|
|
363
468
|
onScrimOpacity,
|
|
364
469
|
});
|
|
365
470
|
|
|
@@ -502,6 +607,7 @@ export function BottomSheetPanel({
|
|
|
502
607
|
themeProps('bottom-sheet'),
|
|
503
608
|
stylex.props(
|
|
504
609
|
styles.sheet,
|
|
610
|
+
overlayPaddingReset.reset,
|
|
505
611
|
height === 'hug' ? styles.hugHeight : styles.budget,
|
|
506
612
|
isClosing && styles.sheetClosing,
|
|
507
613
|
isFading && styles.sheetFading,
|
package/src/BottomSheet/index.ts
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
export {BottomSheet} from './BottomSheet';
|
|
13
|
-
export type {
|
|
13
|
+
export type {
|
|
14
|
+
BottomSheetHeight,
|
|
15
|
+
BottomSheetProps,
|
|
16
|
+
BottomSheetSnapPoint,
|
|
17
|
+
} from './BottomSheet';
|
|
14
18
|
export {BottomSheetSwitcher} from './BottomSheetSwitcher';
|
|
15
19
|
export type {BottomSheetSwitcherProps} from './BottomSheetSwitcher';
|
|
@@ -11,24 +11,73 @@
|
|
|
11
11
|
|
|
12
12
|
import {describe, it, expect} from 'vitest';
|
|
13
13
|
import {
|
|
14
|
-
snapFractionsToHeights,
|
|
15
14
|
computeDetentOffsets,
|
|
15
|
+
isValidSnapPoint,
|
|
16
16
|
nearestOffset,
|
|
17
|
+
peekOffsetFor,
|
|
17
18
|
resolveSettleOffset,
|
|
19
|
+
resolveSnapPoints,
|
|
18
20
|
scrimOpacityForOffset,
|
|
19
|
-
isPeekOffset,
|
|
20
21
|
DETENT_DEDUP_PX,
|
|
21
22
|
} from './snapOffsets';
|
|
22
23
|
|
|
23
|
-
describe('
|
|
24
|
-
it('
|
|
25
|
-
expect(
|
|
24
|
+
describe('resolveSnapPoints', () => {
|
|
25
|
+
it('reads a bare number as a fraction of the viewport', () => {
|
|
26
|
+
expect(resolveSnapPoints([0.5, 0.92], 800)).toEqual([400, 736]);
|
|
26
27
|
});
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
it('reads a percentage as the same fraction', () => {
|
|
30
|
+
expect(resolveSnapPoints(['50%', '92%'], 800)).toEqual([400, 736]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('reads a px length as an absolute height', () => {
|
|
34
|
+
expect(resolveSnapPoints(['320px'], 800)).toEqual([320]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('keeps the caller order, mixing forms', () => {
|
|
38
|
+
expect(resolveSnapPoints(['120px', 0.5, '90%'], 800)).toEqual([
|
|
39
|
+
120, 400, 720,
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('accepts fractional and unit-cased lengths, and surrounding space', () => {
|
|
44
|
+
expect(resolveSnapPoints(['12.5%', '0.5PX', ' 80px '], 800)).toEqual([
|
|
45
|
+
100, 0.5, 80,
|
|
46
|
+
]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('drops numbers outside the (0, 1] fraction range', () => {
|
|
50
|
+
// 200 is the px mistake — a bare number is never a length.
|
|
51
|
+
expect(resolveSnapPoints([0, 0.5, 1, 1.2, -0.3, 200], 1000)).toEqual([
|
|
29
52
|
500, 1000,
|
|
30
53
|
]);
|
|
31
54
|
});
|
|
55
|
+
|
|
56
|
+
it('drops lengths it cannot resolve by arithmetic on the viewport', () => {
|
|
57
|
+
expect(
|
|
58
|
+
resolveSnapPoints(
|
|
59
|
+
['50', '30rem', '50vh', 'calc(50% - 20px)', '-10px', '', '0px'],
|
|
60
|
+
800,
|
|
61
|
+
),
|
|
62
|
+
).toEqual([]);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('isValidSnapPoint', () => {
|
|
67
|
+
it('accepts the three supported forms', () => {
|
|
68
|
+
expect(isValidSnapPoint(0.5)).toBe(true);
|
|
69
|
+
expect(isValidSnapPoint(1)).toBe(true);
|
|
70
|
+
expect(isValidSnapPoint('50%')).toBe(true);
|
|
71
|
+
expect(isValidSnapPoint('320px')).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('rejects what resolveSnapPoints would silently drop', () => {
|
|
75
|
+
expect(isValidSnapPoint(200)).toBe(false);
|
|
76
|
+
expect(isValidSnapPoint(0)).toBe(false);
|
|
77
|
+
expect(isValidSnapPoint('50')).toBe(false);
|
|
78
|
+
expect(isValidSnapPoint('50vh')).toBe(false);
|
|
79
|
+
expect(isValidSnapPoint('calc(50% - 20px)')).toBe(false);
|
|
80
|
+
});
|
|
32
81
|
});
|
|
33
82
|
|
|
34
83
|
describe('computeDetentOffsets', () => {
|
|
@@ -100,66 +149,84 @@ describe('resolveSettleOffset', () => {
|
|
|
100
149
|
});
|
|
101
150
|
});
|
|
102
151
|
|
|
103
|
-
describe('
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
expect(
|
|
108
|
-
expect(isPeekOffset(100, offsets)).toBe(false);
|
|
109
|
-
expect(isPeekOffset(0, offsets)).toBe(false);
|
|
152
|
+
describe('peekOffsetFor', () => {
|
|
153
|
+
it('is the shortest stop when that stop is a sliver', () => {
|
|
154
|
+
// sheet 800; stops at 800, 400 and 100 visible px. The 100px stop is an
|
|
155
|
+
// eighth of the sheet, well inside the quarter that makes a peek.
|
|
156
|
+
expect(peekOffsetFor([0, 400, 700], 800)).toBe(700);
|
|
110
157
|
});
|
|
111
158
|
|
|
112
|
-
it('
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
expect(
|
|
159
|
+
it('has no peek when the shortest stop is a working height', () => {
|
|
160
|
+
// A half-height stop lays its content out and keeps a full scrim; it is
|
|
161
|
+
// the sheet the caller asked for, not a glance at one.
|
|
162
|
+
expect(peekOffsetFor([0, 400], 800)).toBeNull();
|
|
116
163
|
});
|
|
117
164
|
|
|
118
165
|
it('has no peek when the sheet has no collapsed stop', () => {
|
|
119
|
-
expect(
|
|
120
|
-
expect(isPeekOffset(0, [0])).toBe(false);
|
|
166
|
+
expect(peekOffsetFor([0], 800)).toBeNull();
|
|
121
167
|
});
|
|
122
168
|
|
|
123
|
-
it('
|
|
124
|
-
expect(
|
|
169
|
+
it('takes the quarter mark itself as a peek', () => {
|
|
170
|
+
expect(peekOffsetFor([0, 600], 800)).toBe(600);
|
|
125
171
|
});
|
|
126
172
|
|
|
127
|
-
it('
|
|
128
|
-
|
|
129
|
-
const peek = offsets[offsets.length - 1];
|
|
130
|
-
expect(isPeekOffset(peek, offsets)).toBe(true);
|
|
131
|
-
expect(scrimOpacityForOffset(peek, offsets, dismissOffset)).toBeCloseTo(
|
|
132
|
-
0.3,
|
|
133
|
-
);
|
|
173
|
+
it('has no peek without a measured sheet', () => {
|
|
174
|
+
expect(peekOffsetFor([0, 600], 0)).toBeNull();
|
|
134
175
|
});
|
|
135
176
|
});
|
|
136
177
|
|
|
137
178
|
describe('scrimOpacityForOffset', () => {
|
|
138
|
-
describe('with a peek detent
|
|
179
|
+
describe('with a peek detent', () => {
|
|
139
180
|
const offsets = [0, 100, 200]; // full, mid, peek
|
|
181
|
+
const peekOffset = 200;
|
|
140
182
|
const dismissOffset = 280;
|
|
141
183
|
|
|
142
184
|
it('is full at or above the mid detent', () => {
|
|
143
|
-
expect(scrimOpacityForOffset(0, offsets, dismissOffset)).toBe(
|
|
144
|
-
|
|
145
|
-
|
|
185
|
+
expect(scrimOpacityForOffset(0, offsets, dismissOffset, peekOffset)).toBe(
|
|
186
|
+
1,
|
|
187
|
+
);
|
|
188
|
+
expect(
|
|
189
|
+
scrimOpacityForOffset(100, offsets, dismissOffset, peekOffset),
|
|
190
|
+
).toBe(1);
|
|
191
|
+
expect(
|
|
192
|
+
scrimOpacityForOffset(60, offsets, dismissOffset, peekOffset),
|
|
193
|
+
).toBe(1);
|
|
146
194
|
});
|
|
147
195
|
|
|
148
196
|
it('fades linearly from the mid detent toward the peek floor', () => {
|
|
149
197
|
// Halfway from mid (100) to peek (200), opacity is halfway from 1 to the
|
|
150
198
|
// 0.3 floor => 0.65.
|
|
151
|
-
expect(
|
|
152
|
-
|
|
153
|
-
);
|
|
199
|
+
expect(
|
|
200
|
+
scrimOpacityForOffset(150, offsets, dismissOffset, peekOffset),
|
|
201
|
+
).toBeCloseTo(0.65);
|
|
154
202
|
});
|
|
155
203
|
|
|
156
204
|
it('thins to the peek floor at or below the peek detent (still modal)', () => {
|
|
157
|
-
expect(
|
|
158
|
-
|
|
159
|
-
);
|
|
160
|
-
expect(
|
|
161
|
-
|
|
162
|
-
);
|
|
205
|
+
expect(
|
|
206
|
+
scrimOpacityForOffset(200, offsets, dismissOffset, peekOffset),
|
|
207
|
+
).toBeCloseTo(0.3);
|
|
208
|
+
expect(
|
|
209
|
+
scrimOpacityForOffset(240, offsets, dismissOffset, peekOffset),
|
|
210
|
+
).toBeCloseTo(0.3);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('with collapsed stops but no peek among them', () => {
|
|
215
|
+
// The shortest stop is a working height, so the scrim is full there and
|
|
216
|
+
// only fades once the sheet is being dragged out below it.
|
|
217
|
+
const offsets = [0, 100];
|
|
218
|
+
const dismissOffset = 160;
|
|
219
|
+
|
|
220
|
+
it('stays full at every stop, including the shortest', () => {
|
|
221
|
+
expect(scrimOpacityForOffset(0, offsets, dismissOffset, null)).toBe(1);
|
|
222
|
+
expect(scrimOpacityForOffset(100, offsets, dismissOffset, null)).toBe(1);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('fades only across the dismiss overshoot below the shortest stop', () => {
|
|
226
|
+
expect(
|
|
227
|
+
scrimOpacityForOffset(130, offsets, dismissOffset, null),
|
|
228
|
+
).toBeCloseTo(0.5);
|
|
229
|
+
expect(scrimOpacityForOffset(160, offsets, dismissOffset, null)).toBe(0);
|
|
163
230
|
});
|
|
164
231
|
});
|
|
165
232
|
|
|
@@ -168,14 +235,14 @@ describe('scrimOpacityForOffset', () => {
|
|
|
168
235
|
const dismissOffset = 160;
|
|
169
236
|
|
|
170
237
|
it('stays full until the drag begins collapsing', () => {
|
|
171
|
-
expect(scrimOpacityForOffset(0, offsets, dismissOffset)).toBe(1);
|
|
238
|
+
expect(scrimOpacityForOffset(0, offsets, dismissOffset, null)).toBe(1);
|
|
172
239
|
});
|
|
173
240
|
|
|
174
241
|
it('fades across the dismiss overshoot toward the threshold', () => {
|
|
175
|
-
expect(
|
|
176
|
-
|
|
177
|
-
);
|
|
178
|
-
expect(scrimOpacityForOffset(160, offsets, dismissOffset)).toBe(0);
|
|
242
|
+
expect(
|
|
243
|
+
scrimOpacityForOffset(80, offsets, dismissOffset, null),
|
|
244
|
+
).toBeCloseTo(0.5);
|
|
245
|
+
expect(scrimOpacityForOffset(160, offsets, dismissOffset, null)).toBe(0);
|
|
179
246
|
});
|
|
180
247
|
});
|
|
181
248
|
});
|