@react-md/core 1.0.0-next.8 → 1.0.0-next.9
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/.stylelintrc.json +14 -0
- package/.turbo/turbo-build.log +5 -5
- package/.turbo/turbo-lint.log +13 -0
- package/CHANGELOG.md +9 -0
- package/README.md +39 -24
- package/coverage/clover.xml +1013 -404
- package/coverage/coverage-final.json +9 -2
- package/coverage/lcov-report/AutoComplete.tsx.html +283 -0
- package/coverage/lcov-report/RootHtml.tsx.html +370 -0
- package/coverage/lcov-report/Select.tsx.html +1411 -0
- package/coverage/lcov-report/autocomplete/AutoComplete.tsx.html +283 -0
- package/coverage/lcov-report/autocomplete/Autocomplete.tsx.html +283 -0
- package/coverage/lcov-report/autocomplete/index.html +161 -0
- package/coverage/lcov-report/autocomplete/useAutoComplete.ts.html +775 -0
- package/coverage/lcov-report/autocomplete/useAutocomplete.ts.html +775 -0
- package/coverage/lcov-report/autocomplete/useInlineAutoComplete.ts.html +340 -0
- package/coverage/lcov-report/autocomplete/useInlineAutocomplete.ts.html +346 -0
- package/coverage/lcov-report/autocomplete/utils.ts.html +106 -0
- package/coverage/lcov-report/avatar/Avatar.tsx.html +162 -99
- package/coverage/lcov-report/avatar/index.html +19 -34
- package/coverage/lcov-report/avatar/styles.ts.html +1 -1
- package/coverage/lcov-report/button/Button.tsx.html +85 -85
- package/coverage/lcov-report/button/index.html +12 -12
- package/coverage/lcov-report/dialog/DialogFooter.tsx.html +36 -36
- package/coverage/lcov-report/dialog/DialogHeader.tsx.html +26 -26
- package/coverage/lcov-report/dialog/index.html +34 -19
- package/coverage/lcov-report/form/AutoComplete.tsx.html +283 -0
- package/coverage/lcov-report/form/Form.tsx.html +22 -22
- package/coverage/lcov-report/form/OptGroup.tsx.html +169 -166
- package/coverage/lcov-report/form/Option.tsx.html +727 -0
- package/coverage/lcov-report/form/Select.tsx.html +962 -1112
- package/coverage/lcov-report/form/SelectOriginal.tsx.html +1630 -0
- package/coverage/lcov-report/form/SelectV2.tsx.html +1024 -0
- package/coverage/lcov-report/form/SelectedOption.tsx.html +250 -0
- package/coverage/lcov-report/form/index.html +57 -12
- package/coverage/lcov-report/form/selectUtils.ts.html +188 -221
- package/coverage/lcov-report/form/useAutoComplete.ts.html +787 -0
- package/coverage/lcov-report/form/useCombobox.ts.html +454 -460
- package/coverage/lcov-report/form/useComboboxList.ts.html +108 -93
- package/coverage/lcov-report/form/useFormReset.ts.html +229 -0
- package/coverage/lcov-report/form/useInlineAutoComplete.ts.html +379 -0
- package/coverage/lcov-report/form/useSelectCombobox.ts.html +499 -0
- package/coverage/lcov-report/form/utils.ts.html +209 -170
- package/coverage/lcov-report/icon/FontIcon.tsx.html +28 -28
- package/coverage/lcov-report/icon/MaterialIcon.tsx.html +235 -0
- package/coverage/lcov-report/icon/index.html +1 -1
- package/coverage/lcov-report/index.html +36 -21
- package/coverage/lcov-report/media-queries/appSize.ts.html +1 -1
- package/coverage/lcov-report/media-queries/index.html +1 -1
- package/coverage/lcov-report/menu/DropdownMenu.tsx.html +188 -188
- package/coverage/lcov-report/menu/Menu.tsx.html +271 -265
- package/coverage/lcov-report/menu/MenuItem.tsx.html +292 -0
- package/coverage/lcov-report/menu/MenuVisibilityProvider.tsx.html +48 -33
- package/coverage/lcov-report/menu/index.html +45 -15
- package/coverage/lcov-report/menu/useContextMenu.ts.html +490 -0
- package/coverage/lcov-report/movement/index.html +19 -19
- package/coverage/lcov-report/movement/useKeyboardMovementProvider.ts.html +422 -383
- package/coverage/lcov-report/positioning/constants.ts.html +463 -0
- package/coverage/lcov-report/positioning/index.html +30 -30
- package/coverage/lcov-report/positioning/useFixedPositioning.ts.html +1321 -0
- package/coverage/lcov-report/progress/CircularProgress.tsx.html +184 -184
- package/coverage/lcov-report/progress/index.html +19 -34
- package/coverage/lcov-report/searching/caseInsensitive.ts.html +685 -0
- package/coverage/lcov-report/searching/fuzzy.ts.html +610 -0
- package/coverage/lcov-report/searching/index.html +161 -0
- package/coverage/lcov-report/searching/toSearchQuery.ts.html +139 -0
- package/coverage/lcov-report/searching/utils.ts.html +247 -0
- package/coverage/lcov-report/src/CoreProviders.tsx.html +20 -20
- package/coverage/lcov-report/src/NoSsr.tsx.html +1 -1
- package/coverage/lcov-report/src/RootHtml.tsx.html +370 -0
- package/coverage/lcov-report/src/SsrProvider.tsx.html +10 -10
- package/coverage/lcov-report/src/app-bar/AppBar.tsx.html +1 -1
- package/coverage/lcov-report/src/app-bar/AppBarTitle.tsx.html +1 -1
- package/coverage/lcov-report/src/app-bar/index.html +1 -1
- package/coverage/lcov-report/src/avatar/Avatar.tsx.html +1 -1
- package/coverage/lcov-report/src/avatar/index.html +1 -1
- package/coverage/lcov-report/src/avatar/styles.ts.html +1 -1
- package/coverage/lcov-report/src/badge/Badge.tsx.html +1 -1
- package/coverage/lcov-report/src/badge/index.html +1 -1
- package/coverage/lcov-report/src/box/Box.tsx.html +1 -1
- package/coverage/lcov-report/src/box/index.html +1 -1
- package/coverage/lcov-report/src/box/styles.ts.html +1 -1
- package/coverage/lcov-report/src/button/AsyncButton.tsx.html +1 -1
- package/coverage/lcov-report/src/button/Button.tsx.html +1 -1
- package/coverage/lcov-report/src/button/ButtonUnstyled.tsx.html +1 -1
- package/coverage/lcov-report/src/button/FloatingActionButton.tsx.html +1 -1
- package/coverage/lcov-report/src/button/TooltippedButton.tsx.html +1 -1
- package/coverage/lcov-report/src/button/buttonStyles.ts.html +1 -1
- package/coverage/lcov-report/src/button/buttonUnstyledStyles.ts.html +1 -1
- package/coverage/lcov-report/src/button/index.html +1 -1
- package/coverage/lcov-report/src/card/Card.tsx.html +1 -1
- package/coverage/lcov-report/src/card/CardContent.tsx.html +1 -1
- package/coverage/lcov-report/src/card/CardFooter.tsx.html +1 -1
- package/coverage/lcov-report/src/card/CardHeader.tsx.html +1 -1
- package/coverage/lcov-report/src/card/CardSubtitle.tsx.html +1 -1
- package/coverage/lcov-report/src/card/CardTitle.tsx.html +1 -1
- package/coverage/lcov-report/src/card/ClickableCard.tsx.html +1 -1
- package/coverage/lcov-report/src/card/index.html +1 -1
- package/coverage/lcov-report/src/card/styles.ts.html +1 -1
- package/coverage/lcov-report/src/chip/Chip.tsx.html +1 -1
- package/coverage/lcov-report/src/chip/index.html +1 -1
- package/coverage/lcov-report/src/chip/styles.ts.html +1 -1
- package/coverage/lcov-report/src/cssUtils.ts.html +53 -53
- package/coverage/lcov-report/src/delegateEvent.ts.html +1 -1
- package/coverage/lcov-report/src/dialog/Dialog.tsx.html +1 -1
- package/coverage/lcov-report/src/dialog/DialogContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/dialog/DialogContent.tsx.html +1 -1
- package/coverage/lcov-report/src/dialog/DialogFooter.tsx.html +1 -1
- package/coverage/lcov-report/src/dialog/DialogHeader.tsx.html +1 -1
- package/coverage/lcov-report/src/dialog/DialogTitle.tsx.html +1 -1
- package/coverage/lcov-report/src/dialog/FixedDialog.tsx.html +1 -1
- package/coverage/lcov-report/src/dialog/NestedDialogProvider.ts.html +1 -1
- package/coverage/lcov-report/src/dialog/index.html +1 -1
- package/coverage/lcov-report/src/dialog/styles.ts.html +1 -1
- package/coverage/lcov-report/src/divider/Divider.tsx.html +1 -1
- package/coverage/lcov-report/src/divider/index.html +1 -1
- package/coverage/lcov-report/src/divider/styles.ts.html +1 -1
- package/coverage/lcov-report/src/draggable/index.html +1 -1
- package/coverage/lcov-report/src/draggable/useDraggable.ts.html +1 -1
- package/coverage/lcov-report/src/draggable/utils.ts.html +1 -1
- package/coverage/lcov-report/src/expansion-panel/ExpansionList.tsx.html +1 -1
- package/coverage/lcov-report/src/expansion-panel/ExpansionPanel.tsx.html +1 -1
- package/coverage/lcov-report/src/expansion-panel/ExpansionPanelHeader.tsx.html +1 -1
- package/coverage/lcov-report/src/expansion-panel/index.html +1 -1
- package/coverage/lcov-report/src/expansion-panel/useExpansionList.ts.html +1 -1
- package/coverage/lcov-report/src/expansion-panel/useExpansionPanels.ts.html +1 -1
- package/coverage/lcov-report/src/focus/index.html +1 -1
- package/coverage/lcov-report/src/focus/useFocusContainer.ts.html +1 -1
- package/coverage/lcov-report/src/focus/utils.ts.html +1 -1
- package/coverage/lcov-report/src/form/AutoComplete.tsx.html +283 -0
- package/coverage/lcov-report/src/form/Checkbox.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Fieldset.tsx.html +1 -1
- package/coverage/lcov-report/src/form/FileInput.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Form.tsx.html +11 -8
- package/coverage/lcov-report/src/form/FormMessage.tsx.html +1 -1
- package/coverage/lcov-report/src/form/FormMessageContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/form/FormMessageCounter.tsx.html +1 -1
- package/coverage/lcov-report/src/form/InputToggle.tsx.html +1 -1
- package/coverage/lcov-report/src/form/InputToggleIcon.tsx.html +56 -56
- package/coverage/lcov-report/src/form/Label.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Legend.tsx.html +1 -1
- package/coverage/lcov-report/src/form/MenuItemCheckbox.tsx.html +3 -3
- package/coverage/lcov-report/src/form/MenuItemFileInput.tsx.html +1 -1
- package/coverage/lcov-report/src/form/MenuItemInputToggle.tsx.html +178 -232
- package/coverage/lcov-report/src/form/MenuItemRadio.tsx.html +3 -3
- package/coverage/lcov-report/src/form/MenuItemSwitch.tsx.html +1 -1
- package/coverage/lcov-report/src/form/MenuItemTextField.tsx.html +1 -1
- package/coverage/lcov-report/src/form/NativeSelect.tsx.html +1 -1
- package/coverage/lcov-report/src/form/OptGroup.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Option.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Password.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Radio.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Select.tsx.html +894 -1146
- package/coverage/lcov-report/src/form/SelectValue.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Slider.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SliderContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SliderMark.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SliderMarkLabel.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SliderThumb.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SliderTrack.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SliderValueMarks.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SliderValueTooltip.tsx.html +1 -1
- package/coverage/lcov-report/src/form/Switch.tsx.html +1 -1
- package/coverage/lcov-report/src/form/SwitchTrack.tsx.html +1 -1
- package/coverage/lcov-report/src/form/TextArea.tsx.html +1 -1
- package/coverage/lcov-report/src/form/TextField.tsx.html +1 -1
- package/coverage/lcov-report/src/form/TextFieldAddon.tsx.html +1 -1
- package/coverage/lcov-report/src/form/TextFieldContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/form/TextFieldContainerStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/fileUtils.ts.html +1 -1
- package/coverage/lcov-report/src/form/formConfig.ts.html +1 -1
- package/coverage/lcov-report/src/form/formMessageStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/index.html +30 -900
- package/coverage/lcov-report/src/form/inputToggleStyles.ts.html +30 -30
- package/coverage/lcov-report/src/form/menuItemInputToggleStyles.ts.html +319 -0
- package/coverage/lcov-report/src/form/nativeSelectStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/optionStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/passwordStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/selectStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/selectUtils.ts.html +1 -1
- package/coverage/lcov-report/src/form/sliderUtils.ts.html +1 -1
- package/coverage/lcov-report/src/form/switchStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/textAreaStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/textFieldStyles.ts.html +1 -1
- package/coverage/lcov-report/src/form/useAutoComplete.ts.html +787 -0
- package/coverage/lcov-report/src/form/useCheckboxGroup.ts.html +1 -1
- package/coverage/lcov-report/src/form/useCombobox.ts.html +943 -457
- package/coverage/lcov-report/src/form/useEditableCombobox.ts.html +502 -0
- package/coverage/lcov-report/src/form/useFileUpload.ts.html +1 -1
- package/coverage/lcov-report/src/form/useInlineAutoComplete.ts.html +109 -0
- package/coverage/lcov-report/src/form/useListboxProvider.ts.html +1 -1
- package/coverage/lcov-report/src/form/useNumberField.ts.html +1 -1
- package/coverage/lcov-report/src/form/useRadioGroup.ts.html +1 -1
- package/coverage/lcov-report/src/form/useRangeSlider.ts.html +1 -1
- package/coverage/lcov-report/src/form/useResizingTextArea.ts.html +1 -1
- package/coverage/lcov-report/src/form/useSelectCombobox.ts.html +295 -0
- package/coverage/lcov-report/src/form/useSlider.ts.html +1 -1
- package/coverage/lcov-report/src/form/useTextField.ts.html +1 -1
- package/coverage/lcov-report/src/form/utils.ts.html +200 -170
- package/coverage/lcov-report/src/form/validation.ts.html +1 -1
- package/coverage/lcov-report/src/hoverMode/index.html +1 -1
- package/coverage/lcov-report/src/hoverMode/useHoverMode.ts.html +1 -1
- package/coverage/lcov-report/src/hoverMode/useHoverModeProvider.ts.html +1 -1
- package/coverage/lcov-report/src/icon/FontIcon.tsx.html +28 -28
- package/coverage/lcov-report/src/icon/IconRotator.tsx.html +1 -1
- package/coverage/lcov-report/src/icon/MaterialIcon.tsx.html +1 -1
- package/coverage/lcov-report/src/icon/MaterialSymbol.tsx.html +1 -1
- package/coverage/lcov-report/src/icon/SVGIcon.tsx.html +1 -1
- package/coverage/lcov-report/src/icon/TextIconSpacing.tsx.html +51 -51
- package/coverage/lcov-report/src/icon/iconConfig.tsx.html +10 -10
- package/coverage/lcov-report/src/icon/index.html +1 -1
- package/coverage/lcov-report/src/icon/material.ts.html +1 -1
- package/coverage/lcov-report/src/icon/materialConfig.ts.html +1 -1
- package/coverage/lcov-report/src/icon/styles.ts.html +38 -38
- package/coverage/lcov-report/src/index.html +9 -354
- package/coverage/lcov-report/src/interaction/Ripple.tsx.html +1 -1
- package/coverage/lcov-report/src/interaction/RippleContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/interaction/UserInteractionModeProvider.tsx.html +87 -87
- package/coverage/lcov-report/src/interaction/config.ts.html +7 -7
- package/coverage/lcov-report/src/interaction/index.html +1 -1
- package/coverage/lcov-report/src/interaction/useElementInteraction.tsx.html +83 -83
- package/coverage/lcov-report/src/interaction/useHigherContrastChildren.tsx.html +7 -7
- package/coverage/lcov-report/src/interaction/utils.ts.html +1 -1
- package/coverage/lcov-report/src/layout/LayoutAppBar.tsx.html +1 -1
- package/coverage/lcov-report/src/layout/LayoutNav.tsx.html +1 -1
- package/coverage/lcov-report/src/layout/LayoutWindowSplitter.tsx.html +1 -1
- package/coverage/lcov-report/src/layout/Main.tsx.html +1 -1
- package/coverage/lcov-report/src/layout/index.html +1 -1
- package/coverage/lcov-report/src/layout/layoutNavStyles.ts.html +1 -1
- package/coverage/lcov-report/src/layout/layoutWindowSplitterStyles.ts.html +1 -1
- package/coverage/lcov-report/src/layout/mainStyles.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useExpandableLayout.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useHorizontalLayoutTransition.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useLayoutAppBarHeight.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useLayoutTree.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useLayoutWindowSplitter.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useMainTabIndex.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useResizableLayout.ts.html +1 -1
- package/coverage/lcov-report/src/layout/useTemporaryLayout.ts.html +1 -1
- package/coverage/lcov-report/src/link/Link.tsx.html +1 -1
- package/coverage/lcov-report/src/link/SkipToMainContent.tsx.html +1 -1
- package/coverage/lcov-report/src/link/index.html +1 -1
- package/coverage/lcov-report/src/link/styles.ts.html +1 -1
- package/coverage/lcov-report/src/list/List.tsx.html +30 -30
- package/coverage/lcov-report/src/list/ListItem.tsx.html +124 -124
- package/coverage/lcov-report/src/list/ListItemAddon.tsx.html +35 -35
- package/coverage/lcov-report/src/list/ListItemChildren.tsx.html +79 -79
- package/coverage/lcov-report/src/list/ListItemLink.tsx.html +2 -2
- package/coverage/lcov-report/src/list/ListItemText.tsx.html +35 -35
- package/coverage/lcov-report/src/list/ListSubheader.tsx.html +1 -1
- package/coverage/lcov-report/src/list/getListItemHeight.ts.html +44 -47
- package/coverage/lcov-report/src/list/index.html +5 -5
- package/coverage/lcov-report/src/list/listItemStyles.ts.html +65 -65
- package/coverage/lcov-report/src/media-queries/AppSizeProvider.tsx.html +49 -49
- package/coverage/lcov-report/src/media-queries/appSize.ts.html +1 -1
- package/coverage/lcov-report/src/media-queries/index.html +1 -1
- package/coverage/lcov-report/src/media-queries/useMediaQuery.ts.html +24 -24
- package/coverage/lcov-report/src/menu/DropdownMenu.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/Menu.tsx.html +3 -3
- package/coverage/lcov-report/src/menu/MenuBar.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuButton.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuConfigurationProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuItem.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuItemButton.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuItemGroup.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuItemSeparator.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuSheet.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuVisibilityProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuWidget.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/MenuWidgetKeyboardProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/menu/index.html +1 -1
- package/coverage/lcov-report/src/menu/useContextMenu.ts.html +1 -1
- package/coverage/lcov-report/src/menu/useMenuBarProvider.ts.html +1 -1
- package/coverage/lcov-report/src/menu/utils.ts.html +1 -1
- package/coverage/lcov-report/src/movement/constants.ts.html +1 -1
- package/coverage/lcov-report/src/movement/findMatchIndex.ts.html +1 -1
- package/coverage/lcov-report/src/movement/index.html +17 -62
- package/coverage/lcov-report/src/movement/useKeyboardMovementProvider.ts.html +1 -1
- package/coverage/lcov-report/src/movement/utils.ts.html +143 -119
- package/coverage/lcov-report/src/overlay/Overlay.tsx.html +1 -1
- package/coverage/lcov-report/src/overlay/index.html +1 -1
- package/coverage/lcov-report/src/overlay/overlayStyles.ts.html +1 -1
- package/coverage/lcov-report/src/portal/Portal.tsx.html +1 -1
- package/coverage/lcov-report/src/portal/PortalContainerProvider.tsx.html +36 -36
- package/coverage/lcov-report/src/portal/index.html +1 -1
- package/coverage/lcov-report/src/positioning/constants.ts.html +1 -1
- package/coverage/lcov-report/src/positioning/createHorizontalPosition.ts.html +1 -1
- package/coverage/lcov-report/src/positioning/createVerticalPosition.ts.html +1 -1
- package/coverage/lcov-report/src/positioning/getFixedPosition.ts.html +1 -1
- package/coverage/lcov-report/src/positioning/index.html +1 -1
- package/coverage/lcov-report/src/positioning/useFixedPositioning.ts.html +1 -1
- package/coverage/lcov-report/src/positioning/utils.ts.html +1 -1
- package/coverage/lcov-report/src/progress/CircularProgress.tsx.html +81 -81
- package/coverage/lcov-report/src/progress/LinearProgress.tsx.html +1 -1
- package/coverage/lcov-report/src/progress/getProgressA11y.ts.html +1 -1
- package/coverage/lcov-report/src/progress/index.html +1 -1
- package/coverage/lcov-report/src/responsive-item/ResponsiveItemContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/responsive-item/ResponsiveItemOverlay.tsx.html +1 -1
- package/coverage/lcov-report/src/responsive-item/index.html +1 -1
- package/coverage/lcov-report/src/responsive-item/styles.ts.html +1 -1
- package/coverage/lcov-report/src/scroll/ScrollLock.tsx.html +1 -1
- package/coverage/lcov-report/src/scroll/getScrollbarWidth.ts.html +1 -1
- package/coverage/lcov-report/src/scroll/index.html +1 -1
- package/coverage/lcov-report/src/scroll/useScrollLock.ts.html +1 -1
- package/coverage/lcov-report/src/segmented-button/SegmentedButton.tsx.html +1 -1
- package/coverage/lcov-report/src/segmented-button/SegmentedButtonContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/segmented-button/index.html +1 -1
- package/coverage/lcov-report/src/segmented-button/segmentedButtonContainerStyles.ts.html +1 -1
- package/coverage/lcov-report/src/segmented-button/segmentedButtonStyles.ts.html +1 -1
- package/coverage/lcov-report/src/sheet/Sheet.tsx.html +1 -1
- package/coverage/lcov-report/src/sheet/index.html +1 -1
- package/coverage/lcov-report/src/sheet/styles.ts.html +1 -1
- package/coverage/lcov-report/src/snackbar/DefaultToastRenderer.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/Snackbar.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/Toast.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/ToastActionButton.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/ToastCloseButton.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/ToastContent.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/ToastManager.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/ToastManagerProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/snackbar/index.html +1 -1
- package/coverage/lcov-report/src/snackbar/snackbarStyles.ts.html +1 -1
- package/coverage/lcov-report/src/snackbar/toastContentStyles.ts.html +1 -1
- package/coverage/lcov-report/src/snackbar/toastStyles.ts.html +1 -1
- package/coverage/lcov-report/src/snackbar/useCurrentToastActions.ts.html +1 -1
- package/coverage/lcov-report/src/suspense/CircularProgressSuspense.tsx.html +142 -142
- package/coverage/lcov-report/src/suspense/NullSuspense.tsx.html +88 -88
- package/coverage/lcov-report/src/suspense/index.html +32 -32
- package/coverage/lcov-report/src/table/Table.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableBody.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableCell.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableCellContent.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableCheckbox.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableConfigurationProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableContainerProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableFooter.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableHeader.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableRadio.tsx.html +1 -1
- package/coverage/lcov-report/src/table/TableRow.tsx.html +1 -1
- package/coverage/lcov-report/src/table/index.html +1 -1
- package/coverage/lcov-report/src/table/tableCellStyles.ts.html +1 -1
- package/coverage/lcov-report/src/table/tableContainerStyles.ts.html +1 -1
- package/coverage/lcov-report/src/table/tableFooterStyles.ts.html +1 -1
- package/coverage/lcov-report/src/table/tableHeaderStyles.ts.html +1 -1
- package/coverage/lcov-report/src/table/tableRowStyles.ts.html +1 -1
- package/coverage/lcov-report/src/table/tableStyles.ts.html +1 -1
- package/coverage/lcov-report/src/tabs/Tab.tsx.html +1 -1
- package/coverage/lcov-report/src/tabs/TabList.tsx.html +1 -1
- package/coverage/lcov-report/src/tabs/TabListScrollButton.tsx.html +1 -1
- package/coverage/lcov-report/src/tabs/index.html +1 -1
- package/coverage/lcov-report/src/tabs/tabIndicatorStyles.ts.html +1 -1
- package/coverage/lcov-report/src/tabs/tabListScrollButtonStyles.ts.html +1 -1
- package/coverage/lcov-report/src/tabs/tabListStyles.ts.html +1 -1
- package/coverage/lcov-report/src/tabs/tabStyles.ts.html +1 -1
- package/coverage/lcov-report/src/tabs/useTabList.ts.html +1 -1
- package/coverage/lcov-report/src/tabs/useTabs.ts.html +1 -1
- package/coverage/lcov-report/src/tabs/utils.ts.html +1 -1
- package/coverage/lcov-report/src/test-utils/IntersectionObserver.ts.html +1 -1
- package/coverage/lcov-report/src/test-utils/ResizeObserver.ts.html +1 -1
- package/coverage/lcov-report/src/test-utils/data-testid.ts.html +18 -6
- package/coverage/lcov-report/src/test-utils/drag.ts.html +1 -1
- package/coverage/lcov-report/src/test-utils/index.html +7 -7
- package/coverage/lcov-report/src/test-utils/jest-setup.ts.html +9 -9
- package/coverage/lcov-report/src/test-utils/matchMedia.ts.html +4 -4
- package/coverage/lcov-report/src/test-utils/polyfills/IntersectionObserver.ts.html +4 -4
- package/coverage/lcov-report/src/test-utils/polyfills/ResizeObserver.ts.html +3 -3
- package/coverage/lcov-report/src/test-utils/polyfills/TextDecoder.ts.html +106 -0
- package/coverage/lcov-report/src/test-utils/polyfills/TextEncoder.ts.html +100 -0
- package/coverage/lcov-report/src/test-utils/polyfills/index.html +1 -1
- package/coverage/lcov-report/src/test-utils/polyfills/matchMedia.ts.html +6 -6
- package/coverage/lcov-report/src/test-utils/polyfills/offsetParent.ts.html +14 -14
- package/coverage/lcov-report/src/test-utils/polyfills/scrollIntoView.ts.html +5 -5
- package/coverage/lcov-report/src/test-utils/render.tsx.html +21 -21
- package/coverage/lcov-report/src/test-utils/root-html-environment.ts.html +85 -0
- package/coverage/lcov-report/src/test-utils/timers.ts.html +1 -1
- package/coverage/lcov-report/src/theme/LocalStorageColorSchemeProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/theme/ThemeProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/theme/colors.ts.html +1 -1
- package/coverage/lcov-report/src/theme/cssVars.ts.html +1 -1
- package/coverage/lcov-report/src/theme/index.html +1 -1
- package/coverage/lcov-report/src/theme/useCSSVariables.ts.html +1 -1
- package/coverage/lcov-report/src/theme/useColorScheme.ts.html +1 -1
- package/coverage/lcov-report/src/theme/useColorSchemeMetaTag.ts.html +1 -1
- package/coverage/lcov-report/src/theme/useColorSchemeProvider.ts.html +1 -1
- package/coverage/lcov-report/src/theme/usePrefersColorScheme.ts.html +1 -1
- package/coverage/lcov-report/src/theme/utils.ts.html +1 -1
- package/coverage/lcov-report/src/tooltip/Tooltip.tsx.html +1 -1
- package/coverage/lcov-report/src/tooltip/TooltipHoverModeProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/tooltip/constants.ts.html +1 -1
- package/coverage/lcov-report/src/tooltip/index.html +1 -1
- package/coverage/lcov-report/src/tooltip/tooltipStyles.ts.html +1 -1
- package/coverage/lcov-report/src/tooltip/useTooltip.ts.html +1 -1
- package/coverage/lcov-report/src/tooltip/useTooltipPosition.ts.html +1 -1
- package/coverage/lcov-report/src/tooltip/utils.ts.html +1 -1
- package/coverage/lcov-report/src/transition/CSSTransition.tsx.html +1 -1
- package/coverage/lcov-report/src/transition/Collapse.tsx.html +1 -1
- package/coverage/lcov-report/src/transition/CrossFade.tsx.html +1 -1
- package/coverage/lcov-report/src/transition/ScaleTransition.tsx.html +1 -1
- package/coverage/lcov-report/src/transition/SkeletonPlaceholder.tsx.html +1 -1
- package/coverage/lcov-report/src/transition/Slide.tsx.html +1 -1
- package/coverage/lcov-report/src/transition/SlideContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/transition/collapseStyles.ts.html +13 -13
- package/coverage/lcov-report/src/transition/config.ts.html +3 -3
- package/coverage/lcov-report/src/transition/index.html +7 -7
- package/coverage/lcov-report/src/transition/maxWidthTransition.ts.html +1 -1
- package/coverage/lcov-report/src/transition/skeletonPlaceholderUtils.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useCSSTransition.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useCarousel.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useCollapseTransition.ts.html +96 -150
- package/coverage/lcov-report/src/transition/useCrossFadeTransition.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useMaxWidthTransition.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useScaleTransition.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useSkeletonPlaceholder.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useSlideTransition.ts.html +1 -1
- package/coverage/lcov-report/src/transition/useTransition.ts.html +152 -152
- package/coverage/lcov-report/src/transition/utils.ts.html +14 -14
- package/coverage/lcov-report/src/tree/DefaultTreeItemRenderer.tsx.html +1 -1
- package/coverage/lcov-report/src/tree/Tree.tsx.html +1 -1
- package/coverage/lcov-report/src/tree/TreeGroup.tsx.html +45 -45
- package/coverage/lcov-report/src/tree/TreeItem.tsx.html +1 -1
- package/coverage/lcov-report/src/tree/TreeItemExpander.tsx.html +1 -1
- package/coverage/lcov-report/src/tree/TreeProvider.tsx.html +8 -8
- package/coverage/lcov-report/src/tree/index.html +1 -1
- package/coverage/lcov-report/src/tree/styles.ts.html +5 -5
- package/coverage/lcov-report/src/tree/useTree.ts.html +1 -1
- package/coverage/lcov-report/src/tree/useTreeExpansion.ts.html +1 -1
- package/coverage/lcov-report/src/tree/useTreeItems.ts.html +1 -1
- package/coverage/lcov-report/src/tree/useTreeMovement.ts.html +1 -1
- package/coverage/lcov-report/src/tree/useTreeSelection.ts.html +1 -1
- package/coverage/lcov-report/src/tree/utils.ts.html +1 -1
- package/coverage/lcov-report/src/typography/SrOnly.tsx.html +12 -12
- package/coverage/lcov-report/src/typography/TextContainer.tsx.html +1 -1
- package/coverage/lcov-report/src/typography/Typography.tsx.html +94 -94
- package/coverage/lcov-report/src/typography/WritingDirectionProvider.tsx.html +1 -1
- package/coverage/lcov-report/src/typography/index.html +1 -1
- package/coverage/lcov-report/src/useAsyncAction.ts.html +1 -1
- package/coverage/lcov-report/src/useDebouncedFunction.ts.html +1 -1
- package/coverage/lcov-report/src/useDropzone.ts.html +1 -1
- package/coverage/lcov-report/src/useElementSize.ts.html +1 -1
- package/coverage/lcov-report/src/useEnsuredId.ts.html +8 -8
- package/coverage/lcov-report/src/useEnsuredRef.ts.html +11 -11
- package/coverage/lcov-report/src/useEnsuredState.ts.html +16 -16
- package/coverage/lcov-report/src/useHtmlClassName.ts.html +1 -1
- package/coverage/lcov-report/src/useIntersectionObserver.ts.html +1 -1
- package/coverage/lcov-report/src/useIsomorphicLayoutEffect.ts.html +1 -1
- package/coverage/lcov-report/src/useLocalStorage.ts.html +1 -1
- package/coverage/lcov-report/src/useOrientation.ts.html +32 -32
- package/coverage/lcov-report/src/usePageInactive.ts.html +1 -1
- package/coverage/lcov-report/src/useResizeListener.ts.html +1 -1
- package/coverage/lcov-report/src/useResizeObserver.ts.html +23 -23
- package/coverage/lcov-report/src/useThrottledFunction.ts.html +1 -1
- package/coverage/lcov-report/src/useToggle.ts.html +1 -1
- package/coverage/lcov-report/src/useUnmounted.ts.html +1 -1
- package/coverage/lcov-report/src/useWindowSize.ts.html +1 -1
- package/coverage/lcov-report/src/utils/RenderRecursively.tsx.html +1 -1
- package/coverage/lcov-report/src/utils/alphaNumericSort.ts.html +1 -1
- package/coverage/lcov-report/src/utils/applyRef.ts.html +1 -1
- package/coverage/lcov-report/src/utils/bem.ts.html +50 -50
- package/coverage/lcov-report/src/utils/filters.ts.html +357 -84
- package/coverage/lcov-report/src/utils/getClientPosition.ts.html +1 -1
- package/coverage/lcov-report/src/utils/getMiddleOfRange.ts.html +1 -1
- package/coverage/lcov-report/src/utils/getPercentage.ts.html +1 -1
- package/coverage/lcov-report/src/utils/getRangeDefaultValue.ts.html +1 -1
- package/coverage/lcov-report/src/utils/getRangeSteps.ts.html +1 -1
- package/coverage/lcov-report/src/utils/identity.ts.html +1 -1
- package/coverage/lcov-report/src/utils/index.html +13 -268
- package/coverage/lcov-report/src/utils/isElementVisible.ts.html +1 -1
- package/coverage/lcov-report/src/utils/loop.ts.html +1 -1
- package/coverage/lcov-report/src/utils/nearest.ts.html +1 -1
- package/coverage/lcov-report/src/utils/parseCssLengthUnit.ts.html +1 -1
- package/coverage/lcov-report/src/utils/randomInt.ts.html +1 -1
- package/coverage/lcov-report/src/utils/wait.ts.html +1 -1
- package/coverage/lcov-report/src/utils/withinRange.ts.html +1 -1
- package/coverage/lcov-report/src/window-splitter/WindowSplitter.tsx.html +1 -1
- package/coverage/lcov-report/src/window-splitter/index.html +1 -1
- package/coverage/lcov-report/src/window-splitter/useWindowSplitter.ts.html +1 -1
- package/coverage/lcov-report/transition/config.ts.html +5 -5
- package/coverage/lcov-report/transition/index.html +1 -1
- package/coverage/lcov-report/transition/useScaleTransition.ts.html +535 -0
- package/coverage/lcov-report/useAutoComplete.ts.html +787 -0
- package/coverage/lcov-report/useCollapseTransition.ts.html +166 -211
- package/coverage/lcov-report/useCombobox.ts.html +1513 -0
- package/coverage/lcov-report/useInlineAutoComplete.ts.html +379 -0
- package/coverage/lcov-report/useSelectCombobox.ts.html +295 -0
- package/coverage/lcov-report/utils/alphaNumericSort.ts.html +11 -50
- package/coverage/lcov-report/utils/filters.ts.html +1056 -201
- package/coverage/lcov-report/utils/index.html +10 -10
- package/coverage/lcov-report/utils/searching.ts.html +85 -0
- package/coverage/lcov-report/utils.ts.html +109 -277
- package/coverage/lcov.info +928 -259
- package/dist/RootHtml.d.ts +62 -0
- package/dist/RootHtml.js +49 -0
- package/dist/RootHtml.js.map +1 -0
- package/dist/avatar/Avatar.d.ts +14 -0
- package/dist/avatar/Avatar.js +5 -2
- package/dist/avatar/Avatar.js.map +1 -1
- package/dist/dialog/FixedDialog.d.ts +5 -4
- package/dist/dialog/FixedDialog.js +5 -4
- package/dist/dialog/FixedDialog.js.map +1 -1
- package/dist/form/NativeSelect.d.ts +5 -2
- package/dist/form/NativeSelect.js.map +1 -1
- package/dist/form/Option.js +3 -2
- package/dist/form/Option.js.map +1 -1
- package/dist/form/Select.d.ts +105 -15
- package/dist/form/Select.js +160 -249
- package/dist/form/Select.js.map +1 -1
- package/dist/form/SelectedOption.d.ts +21 -0
- package/dist/form/SelectedOption.js +37 -0
- package/dist/form/SelectedOption.js.map +1 -0
- package/dist/form/TextField.d.ts +2 -2
- package/dist/form/TextField.js.map +1 -1
- package/dist/form/_form.scss +8 -13
- package/dist/form/selectUtils.d.ts +1 -3
- package/dist/form/selectUtils.js +2 -10
- package/dist/form/selectUtils.js.map +1 -1
- package/dist/form/types.d.ts +6 -6
- package/dist/form/types.js.map +1 -1
- package/dist/form/useCombobox.d.ts +157 -0
- package/dist/form/useCombobox.js +206 -0
- package/dist/form/useCombobox.js.map +1 -0
- package/dist/form/useEditableCombobox.d.ts +15 -0
- package/dist/form/useEditableCombobox.js +101 -0
- package/dist/form/useEditableCombobox.js.map +1 -0
- package/dist/form/useFormReset.d.ts +16 -0
- package/dist/form/useFormReset.js +32 -0
- package/dist/form/useFormReset.js.map +1 -0
- package/dist/form/useListboxProvider.d.ts +1 -0
- package/dist/form/useListboxProvider.js +1 -0
- package/dist/form/useListboxProvider.js.map +1 -1
- package/dist/form/useSelectCombobox.d.ts +17 -0
- package/dist/form/useSelectCombobox.js +36 -0
- package/dist/form/useSelectCombobox.js.map +1 -0
- package/dist/form/utils.d.ts +11 -1
- package/dist/form/utils.js +6 -0
- package/dist/form/utils.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/menu/Menu.js +12 -1
- package/dist/menu/Menu.js.map +1 -1
- package/dist/menu/useContextMenu.d.ts +3 -3
- package/dist/menu/useContextMenu.js +3 -3
- package/dist/menu/useContextMenu.js.map +1 -1
- package/dist/movement/types.d.ts +40 -21
- package/dist/movement/types.js.map +1 -1
- package/dist/movement/useKeyboardMovementProvider.js +15 -4
- package/dist/movement/useKeyboardMovementProvider.js.map +1 -1
- package/dist/movement/utils.d.ts +7 -2
- package/dist/movement/utils.js +10 -0
- package/dist/movement/utils.js.map +1 -1
- package/dist/positioning/useFixedPositioning.js +0 -8
- package/dist/positioning/useFixedPositioning.js.map +1 -1
- package/dist/searching/caseInsensitive.d.ts +150 -0
- package/dist/searching/caseInsensitive.js +30 -0
- package/dist/searching/caseInsensitive.js.map +1 -0
- package/dist/searching/fuzzy.d.ts +128 -0
- package/dist/searching/fuzzy.js +54 -0
- package/dist/searching/fuzzy.js.map +1 -0
- package/dist/searching/toSearchQuery.d.ts +5 -0
- package/dist/searching/toSearchQuery.js +13 -0
- package/dist/searching/toSearchQuery.js.map +1 -0
- package/dist/searching/types.d.ts +28 -0
- package/dist/searching/types.js +5 -0
- package/dist/searching/types.js.map +1 -0
- package/dist/searching/utils.d.ts +21 -0
- package/dist/searching/utils.js +28 -0
- package/dist/searching/utils.js.map +1 -0
- package/dist/test-utils/IntersectionObserver.d.ts +12 -0
- package/dist/test-utils/ResizeObserver.d.ts +172 -0
- package/dist/test-utils/data-testid.d.ts +7 -0
- package/dist/test-utils/data-testid.js +1 -0
- package/dist/test-utils/data-testid.js.map +1 -1
- package/dist/test-utils/drag.d.ts +26 -0
- package/dist/test-utils/index.d.ts +7 -0
- package/dist/test-utils/jest-setup.d.ts +1 -0
- package/dist/test-utils/matchMedia.d.ts +101 -0
- package/dist/test-utils/polyfills/IntersectionObserver.d.ts +1 -0
- package/dist/test-utils/polyfills/ResizeObserver.d.ts +1 -0
- package/dist/test-utils/polyfills/TextDecoder.d.ts +1 -0
- package/dist/test-utils/polyfills/TextDecoder.js +8 -0
- package/dist/test-utils/polyfills/TextDecoder.js.map +1 -0
- package/dist/test-utils/polyfills/TextEncoder.d.ts +1 -0
- package/dist/test-utils/polyfills/TextEncoder.js +6 -0
- package/dist/test-utils/polyfills/TextEncoder.js.map +1 -0
- package/dist/test-utils/polyfills/index.d.ts +7 -0
- package/dist/test-utils/polyfills/index.js +2 -0
- package/dist/test-utils/polyfills/index.js.map +1 -1
- package/dist/test-utils/polyfills/matchMedia.d.ts +1 -0
- package/dist/test-utils/polyfills/offsetParent.d.ts +1 -0
- package/dist/test-utils/polyfills/scrollIntoView.d.ts +1 -0
- package/dist/test-utils/render.d.ts +13 -0
- package/dist/test-utils/timers.d.ts +39 -0
- package/dist/transition/useCollapseTransition.d.ts +3 -18
- package/dist/transition/useCollapseTransition.js +1 -10
- package/dist/transition/useCollapseTransition.js.map +1 -1
- package/dist/transition/utils.js +7 -2
- package/dist/transition/utils.js.map +1 -1
- package/dist/useEnsuredState.d.ts +1 -1
- package/dist/useEnsuredState.js.map +1 -1
- package/dist/utils/alphaNumericSort.d.ts +1 -1
- package/dist/utils/alphaNumericSort.js +2 -10
- package/dist/utils/alphaNumericSort.js.map +1 -1
- package/jest.config.ts +4 -0
- package/package.json +14 -13
- package/src/RootHtml.tsx +95 -0
- package/src/__tests__/RootHtml.node.tsx +46 -0
- package/src/__tests__/__snapshots__/RootHtml.node.tsx.snap +19 -0
- package/src/avatar/Avatar.tsx +24 -3
- package/src/avatar/__tests__/Avatar.tsx +1 -1
- package/src/avatar/__tests__/__snapshots__/Avatar.tsx.snap +6 -6
- package/src/dialog/FixedDialog.tsx +5 -4
- package/src/form/NativeSelect.tsx +6 -3
- package/src/form/Option.tsx +8 -2
- package/src/form/Select.tsx +251 -335
- package/src/form/SelectedOption.tsx +55 -0
- package/src/form/TextField.tsx +2 -2
- package/src/form/__tests__/Select.tsx +439 -0
- package/src/form/__tests__/__snapshots__/Select.tsx.snap +492 -0
- package/src/form/__tests__/useFormReset.tsx +195 -0
- package/src/form/_form.scss +8 -13
- package/src/form/selectUtils.ts +3 -14
- package/src/form/types.ts +6 -6
- package/src/form/useCombobox.ts +523 -0
- package/src/form/useEditableCombobox.ts +139 -0
- package/src/form/useFormReset.ts +48 -0
- package/src/form/useListboxProvider.ts +2 -0
- package/src/form/useSelectCombobox.ts +70 -0
- package/src/form/utils.ts +17 -4
- package/src/index.ts +14 -1
- package/src/menu/Menu.tsx +9 -1
- package/src/menu/__tests__/__snapshots__/useContextMenu.tsx.snap +54 -0
- package/src/menu/__tests__/useContextMenu.tsx +41 -0
- package/src/menu/useContextMenu.ts +3 -3
- package/src/movement/types.ts +50 -25
- package/src/movement/useKeyboardMovementProvider.ts +21 -8
- package/src/movement/utils.ts +12 -2
- package/src/positioning/__tests__/__snapshots__/useFixedPositioning.tsx.snap +0 -32
- package/src/positioning/__tests__/useFixedPositioning.tsx +0 -14
- package/src/positioning/useFixedPositioning.ts +0 -6
- package/src/searching/__tests__/caseInsensitive.ts +165 -0
- package/src/searching/__tests__/fuzzy.ts +169 -0
- package/src/searching/__tests__/toSearchQuery.ts +21 -0
- package/src/searching/caseInsensitive.ts +200 -0
- package/src/searching/fuzzy.ts +175 -0
- package/src/searching/toSearchQuery.ts +18 -0
- package/src/searching/types.ts +34 -0
- package/src/searching/utils.ts +54 -0
- package/src/test-utils/data-testid.ts +5 -1
- package/src/test-utils/polyfills/TextDecoder.ts +7 -0
- package/src/test-utils/polyfills/TextEncoder.ts +5 -0
- package/src/test-utils/polyfills/index.ts +2 -0
- package/src/transition/__tests__/utils.ts +25 -0
- package/src/transition/useCollapseTransition.ts +6 -24
- package/src/transition/utils.ts +10 -5
- package/src/useEnsuredState.ts +1 -1
- package/src/utils/alphaNumericSort.ts +3 -16
- package/tsconfig.json +2 -2
- package/tsconfig.types.json +1 -1
- package/dist/form/SelectValue.d.ts +0 -17
- package/dist/form/SelectValue.js +0 -32
- package/dist/form/SelectValue.js.map +0 -1
- package/dist/utils/filters.d.ts +0 -196
- package/dist/utils/filters.js +0 -67
- package/dist/utils/filters.js.map +0 -1
- package/src/form/SelectValue.tsx +0 -39
- package/src/utils/filters.ts +0 -320
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/movement/types.ts"],"sourcesContent":["import type {\n FocusEvent,\n FocusEventHandler,\n KeyboardEvent,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n} from \"react\";\nimport type {\n NonNullMutableRef,\n NonNullRef,\n UseStateSetter,\n} from \"../types.js\";\n\n/**\n * Set this to `\"roving\"` when:\n * - there are a group of focusable elements that have a `tabIndex={-1}`\n * - the container element defaults to having a `tabIndex={0}`\n * - if the container is focused, it should no longer be included in the normal\n * tab flow. Instead, the current focused element should be included instead\n * by changing its `tabIndex` from `-1` to `0`\n *\n * Set this to `\"virtual\"` when:\n * - the container element should never lose focus\n * - the \"focused\" element only gains focus styles instead of being focused\n * - the container element specifies an `aria-activedescendant` pointing to one\n * of the ids for the child \"focusable\" elements\n *\n * @remarks \\@since 6.0.0\n */\nexport type TabIndexBehavior = \"roving\" | \"virtual\";\n\n/**\n * @remarks \\@since 5.0.0\n */\nexport interface KeyboardMovementConfiguration {\n /**\n * A list of keys that will attempt to increment the focus index by 1.\n *\n * @defaultValue `[\"ArrowDown\"]`\n */\n incrementKeys?: readonly string[];\n\n /**\n * A list of keys that will attempt to decrement the focus index by 1.\n *\n * @defaultValue `[\"ArrowUp\"]`\n */\n decrementKeys?: readonly string[];\n\n /**\n * A list of keys that will set the focus index to `0`.\n *\n * @defaultValue `[\"Home\"]`\n */\n jumpToFirstKeys?: readonly string[];\n\n /**\n * A list of keys that will set the focus index to the last focusable index.\n *\n * @defaultValue `[\"End\"]`\n */\n jumpToLastKeys?: readonly string[];\n}\n\n/**\n * The defined {@link KeyboardMovementConfiguration} that should be used for\n * custom keyboard focus behavior.\n *\n * @remarks \\@since 5.0.0\n */\nexport type KeyboardMovementConfig = Required<KeyboardMovementConfiguration>;\n\n/**\n * @remarks \\@since 5.0.0\n */\nexport interface KeyboardMovementBehavior {\n /**\n * Boolean if pressing a letter will focus the next item in the\n * {@link KeyboardMovementProvider} that starts with the same letter.\n *\n * @defaultValue `false`\n */\n searchable?: boolean;\n\n /**\n * Boolean if the {@link KeyboardMovementProvider} should allow the focus behavior\n * to loop from the first to last or last to first item instead of preventing\n * any new focus behavior. In other words... if the last item is focused and\n * the user presses a key that should advance the focus to the next focusable\n * element, should the focus stay on the current element or loop back and\n * focus the first focusable item.\n *\n * @defaultValue `false`\n */\n loopable?: boolean;\n\n /**\n * Boolean if elements that are `aria-disabled` or `disabled` should still be\n * able to gain focus.\n *\n * @defaultValue `false`\n */\n includeDisabled?: boolean;\n\n /**\n * Boolean if the keyboard movement is horizontal instead of vertical. This\n * updates the default keyboard config to use `ArrowRight` and `ArrowLeft`\n * instead of `ArrowDown` and `ArrowUp`,\n *\n * @remarks \\@since 5.1.2\n * @defaultValue `false`\n */\n horizontal?: boolean;\n}\n\n/**\n * @remarks\n * \\@since 5.0.0\n * \\@since 6.0.0 Removed `attach`, `detach` and `watching`\n * @internal\n */\nexport interface KeyboardMovementContext\n extends Required<KeyboardMovementBehavior> {\n /** {@inheritDoc KeyboardMovementConfig} */\n config: NonNullRef<KeyboardMovementConfig>;\n\n /** @see {@link TabIndexBehavior} */\n tabIndexBehavior: TabIndexBehavior | undefined;\n\n /**\n * Note: This will only update if the {@link KeyboardMovementProviderOptions.tabIndexBehavior}\n * has been set to `\"roving\"` or `\"virtual\"`.\n */\n activeDescendantId: string;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface FocusableIndexOptions {\n focusables: readonly HTMLElement[];\n includeDisabled: boolean;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport type GetDefaultFocusedIndex = (options: FocusableIndexOptions) => number;\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface
|
|
1
|
+
{"version":3,"sources":["../../src/movement/types.ts"],"sourcesContent":["import type {\n FocusEvent,\n FocusEventHandler,\n KeyboardEvent,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n} from \"react\";\nimport type {\n NonNullMutableRef,\n NonNullRef,\n UseStateSetter,\n} from \"../types.js\";\n\n/**\n * Set this to `\"roving\"` when:\n * - there are a group of focusable elements that have a `tabIndex={-1}`\n * - the container element defaults to having a `tabIndex={0}`\n * - if the container is focused, it should no longer be included in the normal\n * tab flow. Instead, the current focused element should be included instead\n * by changing its `tabIndex` from `-1` to `0`\n *\n * Set this to `\"virtual\"` when:\n * - the container element should never lose focus\n * - the \"focused\" element only gains focus styles instead of being focused\n * - the container element specifies an `aria-activedescendant` pointing to one\n * of the ids for the child \"focusable\" elements\n *\n * @remarks \\@since 6.0.0\n */\nexport type TabIndexBehavior = \"roving\" | \"virtual\";\n\n/**\n * This should be used for specific widgets that should not include all\n * focusable elements and instead only specific elements.\n *\n * @example\n * ```ts\n * const getExpansionPanelsOnly: GetFocusableElements = (container) =>\n * [...container.querySelectorAll(\".rmd-expansion-panel__button\")];\n *\n * const getTreeItemsOnly: GetFocusableElements = (container) =>\n * [...container.querySelectorAll(\"[role='treeitem']\")];\n * ```\n *\n * @defaultValue `getFocusableElements`\n * @see the default `getFocusableElements` function.\n */\nexport type GetFocusableElements = (\n container: HTMLElement,\n programmatic: boolean\n) => readonly HTMLElement[];\n\n/**\n * @remarks \\@since 5.0.0\n */\nexport interface KeyboardMovementConfiguration {\n /**\n * A list of keys that will attempt to increment the focus index by 1.\n *\n * @defaultValue `[\"ArrowDown\"]`\n */\n incrementKeys?: readonly string[];\n\n /**\n * A list of keys that will attempt to decrement the focus index by 1.\n *\n * @defaultValue `[\"ArrowUp\"]`\n */\n decrementKeys?: readonly string[];\n\n /**\n * A list of keys that will set the focus index to `0`.\n *\n * @defaultValue `[\"Home\"]`\n */\n jumpToFirstKeys?: readonly string[];\n\n /**\n * A list of keys that will set the focus index to the last focusable index.\n *\n * @defaultValue `[\"End\"]`\n */\n jumpToLastKeys?: readonly string[];\n}\n\n/**\n * The defined {@link KeyboardMovementConfiguration} that should be used for\n * custom keyboard focus behavior.\n *\n * @remarks \\@since 5.0.0\n */\nexport type KeyboardMovementConfig = Required<KeyboardMovementConfiguration>;\n\n/**\n * @remarks \\@since 5.0.0\n */\nexport interface KeyboardMovementBehavior {\n /**\n * Boolean if pressing a letter will focus the next item in the\n * {@link KeyboardMovementProvider} that starts with the same letter.\n *\n * @defaultValue `false`\n */\n searchable?: boolean;\n\n /**\n * Boolean if the {@link KeyboardMovementProvider} should allow the focus behavior\n * to loop from the first to last or last to first item instead of preventing\n * any new focus behavior. In other words... if the last item is focused and\n * the user presses a key that should advance the focus to the next focusable\n * element, should the focus stay on the current element or loop back and\n * focus the first focusable item.\n *\n * @defaultValue `false`\n */\n loopable?: boolean;\n\n /**\n * Boolean if elements that are `aria-disabled` or `disabled` should still be\n * able to gain focus.\n *\n * @defaultValue `false`\n */\n includeDisabled?: boolean;\n\n /**\n * Boolean if the keyboard movement is horizontal instead of vertical. This\n * updates the default keyboard config to use `ArrowRight` and `ArrowLeft`\n * instead of `ArrowDown` and `ArrowUp`,\n *\n * @remarks \\@since 5.1.2\n * @defaultValue `false`\n */\n horizontal?: boolean;\n}\n\n/**\n * @remarks\n * \\@since 5.0.0\n * \\@since 6.0.0 Removed `attach`, `detach` and `watching`\n * @internal\n */\nexport interface KeyboardMovementContext\n extends Required<KeyboardMovementBehavior> {\n /** {@inheritDoc KeyboardMovementConfig} */\n config: NonNullRef<KeyboardMovementConfig>;\n\n /** @see {@link TabIndexBehavior} */\n tabIndexBehavior: TabIndexBehavior | undefined;\n\n /**\n * Note: This will only update if the {@link KeyboardMovementProviderOptions.tabIndexBehavior}\n * has been set to `\"roving\"` or `\"virtual\"`.\n */\n activeDescendantId: string;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface FocusableIndexOptions {\n focusables: readonly HTMLElement[];\n includeDisabled: boolean;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport type GetDefaultFocusedIndex = (options: FocusableIndexOptions) => number;\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport type ExtendKeyDown<E extends HTMLElement> = (\n movementData: KeyboardMovementExtensionData<E>\n) => void;\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface KeyboardMovementFocusChangeEvent {\n index: number;\n element: HTMLElement;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport type KeyboardMovementFocusChangeEventHandler = (\n event: KeyboardMovementFocusChangeEvent\n) => void;\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface KeyboardMovementExtensionData<E extends HTMLElement>\n extends KeyboardMovementContext {\n event: KeyboardEvent<E>;\n currentFocusIndex: NonNullMutableRef<number>;\n setFocusIndex(index: number, focusables: readonly HTMLElement[]): void;\n setActiveDescendantId(id: string): void;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface KeyboardMovementProviderOptions<E extends HTMLElement>\n extends KeyboardMovementBehavior,\n KeyboardMovementConfiguration {\n /** @see {@link TabIndexBehavior} */\n tabIndexBehavior?: TabIndexBehavior;\n\n onClick?(event: MouseEvent<E>): void;\n onFocus?(event: FocusEvent<E>): void;\n onKeyDown?(event: KeyboardEvent<E>): void;\n\n /** @defaultValue `false` */\n disabled?: boolean;\n\n /**\n * This is used to implement custom keyboard movement for the `keydown` event.\n */\n extendKeyDown?: ExtendKeyDown<E>;\n\n /**\n * Triggered whenever the focus changes.\n */\n onFocusChange?: KeyboardMovementFocusChangeEventHandler;\n\n /**\n * From what I've understood so far, programmatically focusable elements\n * should only be included when disabled elements via `aria-disabled` are\n * allowed.\n *\n * @defaultValue `includeDisabled`\n */\n programmatic?: boolean;\n\n /** @see {@link GetFocusableElements} */\n getFocusableElements?: GetFocusableElements;\n\n /**\n * This can be used to set the initial focus index whenever the container\n * element is first focused or the focus index is `-1` on other focus events.\n */\n getDefaultFocusedIndex?: GetDefaultFocusedIndex;\n\n /**\n * This was added to support editable combobox behavior. As the user types or\n * uses native input keyboard behavior, the focus index should be reset to\n * `-1` so that the next \"ArrowDown\" event focuses the first option again\n * instead of the last selected one.\n *\n * @defaultValue `false`\n */\n isNegativeOneAllowed?: boolean;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface KeyboardMovementProps<E extends HTMLElement> {\n /**\n * This will only be provided if the {@link KeyboardMovementContext.tabIndexBehavior}\n * is set to `\"virtual\"`.\n */\n \"aria-activedescendant\"?: string;\n\n /**\n * This will not be provided if the {@link KeyboardMovementContext.tabIndexBehavior}\n * is `undefined`. Otherwise:\n * - `0` when `\"virtual\"`\n * - `0` when `\"roving\"` and the container element has not been focused at\n * least once\n * - `-1` when `\"roving\"` and the container has been focused at least once\n * - a child element **should** have a `tabIndex={0}` instead\n */\n tabIndex?: number;\n onClick: MouseEventHandler<E>;\n onFocus: FocusEventHandler<E>;\n onKeyDown: KeyboardEventHandler<E>;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface KeyboardMovementProviderImplementation<E extends HTMLElement> {\n movementProps: Readonly<KeyboardMovementProps<E>>;\n movementContext: Readonly<KeyboardMovementContext>;\n currentFocusIndex: NonNullMutableRef<number>;\n activeDescendantId: string;\n setActiveDescendantId: UseStateSetter<string>;\n}\n"],"names":[],"mappings":"AAoSA;;;CAGC,GACD,WAMC"}
|
|
@@ -157,7 +157,7 @@ const returnNegative1 = ()=>-1;
|
|
|
157
157
|
* @remarks \@since 6.0.0
|
|
158
158
|
* @internal
|
|
159
159
|
*/ export function useKeyboardMovementProvider(options = {}) {
|
|
160
|
-
const { onClick = noop, onFocus = noop, onKeyDown = noop, loopable = false, searchable = false, horizontal = false, includeDisabled = false, tabIndexBehavior, extendKeyDown = noop, onFocusChange = noop, programmatic = includeDisabled, incrementKeys: propIncrementKeys, decrementKeys: propDecrementKeys, jumpToFirstKeys: propJumpToFirstKeys, jumpToLastKeys: propJumpToLastKeys, getFocusableElements = defaultGetFocusableElements, getDefaultFocusedIndex = returnNegative1 } = options;
|
|
160
|
+
const { onClick = noop, onFocus = noop, onKeyDown = noop, loopable = false, disabled, searchable = false, horizontal = false, includeDisabled = false, tabIndexBehavior, extendKeyDown = noop, onFocusChange = noop, programmatic = includeDisabled, incrementKeys: propIncrementKeys, decrementKeys: propDecrementKeys, jumpToFirstKeys: propJumpToFirstKeys, jumpToLastKeys: propJumpToLastKeys, getFocusableElements = defaultGetFocusableElements, getDefaultFocusedIndex = returnNegative1, isNegativeOneAllowed = false } = options;
|
|
161
161
|
const isRTL = useDir().dir === "rtl";
|
|
162
162
|
let defaults;
|
|
163
163
|
if (horizontal) {
|
|
@@ -208,14 +208,21 @@ const returnNegative1 = ()=>-1;
|
|
|
208
208
|
};
|
|
209
209
|
}, []);
|
|
210
210
|
}
|
|
211
|
+
let tabIndex;
|
|
212
|
+
if (tabIndexBehavior) {
|
|
213
|
+
tabIndex = disabled || tabIndexBehavior === "roving" && activeDescendantId ? -1 : 0;
|
|
214
|
+
}
|
|
211
215
|
return {
|
|
212
216
|
movementProps: {
|
|
213
217
|
"aria-activedescendant": tabIndexBehavior === "virtual" ? activeDescendantId : undefined,
|
|
214
|
-
tabIndex
|
|
218
|
+
tabIndex,
|
|
215
219
|
// Note: This used to be on the `onFocus` event, but this causes issues in
|
|
216
220
|
// Chromium browsers for drag and drop behavior
|
|
217
221
|
onClick (event) {
|
|
218
222
|
onClick(event);
|
|
223
|
+
if (disabled) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
219
226
|
// This makes it so you can click an element with a mouse and then
|
|
220
227
|
// keyboard navigate from that element instead of the last keyboard focus
|
|
221
228
|
// element
|
|
@@ -264,7 +271,7 @@ const returnNegative1 = ()=>-1;
|
|
|
264
271
|
// This allows my custom `getDefaultFocusedIndex` implementations to
|
|
265
272
|
// have a nice fallback without having to re-implement the "focus
|
|
266
273
|
// first" behavior
|
|
267
|
-
if (defaultFocusIndex === -1) {
|
|
274
|
+
if (!isNegativeOneAllowed && defaultFocusIndex === -1) {
|
|
268
275
|
if (tabIndexBehavior === "virtual") {
|
|
269
276
|
// virtual keyboard navigation **must** always focus at least one element
|
|
270
277
|
defaultFocusIndex = getVirtualFocusDefaultIndex({
|
|
@@ -301,6 +308,9 @@ const returnNegative1 = ()=>-1;
|
|
|
301
308
|
},
|
|
302
309
|
onKeyDown (event) {
|
|
303
310
|
onKeyDown(event);
|
|
311
|
+
if (disabled) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
304
314
|
const { currentTarget } = event;
|
|
305
315
|
const setFocusIndex = (index, focusables)=>{
|
|
306
316
|
event.preventDefault();
|
|
@@ -338,7 +348,7 @@ const returnNegative1 = ()=>-1;
|
|
|
338
348
|
// TODO: Figure this part out. This is currently required for the tree
|
|
339
349
|
// movement when the asterisk key is pressed. There might be other cases
|
|
340
350
|
// as well.
|
|
341
|
-
if (currentFocusIndex.current === -1) {
|
|
351
|
+
if (!isNegativeOneAllowed && currentFocusIndex.current === -1) {
|
|
342
352
|
currentFocusIndex.current = recalculateFocusIndex({
|
|
343
353
|
focusables: getFocusableElements(currentTarget, programmatic),
|
|
344
354
|
includeDisabled,
|
|
@@ -403,6 +413,7 @@ const returnNegative1 = ()=>-1;
|
|
|
403
413
|
},
|
|
404
414
|
movementContext,
|
|
405
415
|
currentFocusIndex,
|
|
416
|
+
activeDescendantId,
|
|
406
417
|
setActiveDescendantId
|
|
407
418
|
};
|
|
408
419
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/movement/useKeyboardMovementProvider.ts"],"sourcesContent":["\"use client\";\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { getFocusableElements as defaultGetFocusableElements } from \"../focus/utils.js\";\nimport { useUserInteractionMode } from \"../interaction/UserInteractionModeProvider.js\";\nimport { useDir } from \"../typography/WritingDirectionProvider.js\";\nimport { useIsomorphicLayoutEffect } from \"../useIsomorphicLayoutEffect.js\";\nimport {\n DEFAULT_KEYBOARD_MOVEMENT,\n DEFAULT_LTR_KEYBOARD_MOVEMENT,\n DEFAULT_RTL_KEYBOARD_MOVEMENT,\n} from \"./constants.js\";\nimport { findMatchIndex } from \"./findMatchIndex.js\";\nimport type {\n KeyboardMovementConfig,\n KeyboardMovementConfiguration,\n KeyboardMovementContext,\n KeyboardMovementProviderImplementation,\n KeyboardMovementProviderOptions,\n} from \"./types.js\";\nimport {\n getFirstFocusableIndex,\n getLastFocusableIndex,\n getNextFocusableIndex,\n getSearchText,\n getVirtualFocusDefaultIndex,\n isElementDisabled,\n isNotFocusable,\n isSearchableEvent,\n recalculateFocusIndex,\n} from \"./utils.js\";\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nconst context = createContext<KeyboardMovementContext>({\n config: { current: DEFAULT_KEYBOARD_MOVEMENT },\n loopable: false,\n searchable: false,\n horizontal: false,\n includeDisabled: false,\n tabIndexBehavior: undefined,\n activeDescendantId: \"\",\n});\ncontext.displayName = \"KeyboardMovement\";\nexport const { Provider: KeyboardMovementProvider } = context;\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport function useKeyboardMovementContext(): Readonly<KeyboardMovementContext> {\n return useContext(context);\n}\n\nconst noop = (): void => {\n // do nothing\n};\n\nconst returnNegative1 = (): number => -1;\n\n/**\n * Implements the custom keyboard movement behavior throughout react-md. Using\n * the \"Find References\" will be the best way to see example usage.\n *\n * @example\n * Default Keyboard Movement for any Focusable Element\n * ```tsx\n * import {\n * KeyboardMovementProvider,\n * useKeyboardMovementProvider,\n * } from \"@react-md/core\";\n * import type { ReactElement, ReactNode } from \"react\";\n *\n * function Example({ children }: { children: ReactNode }): ReactElement {\n * const { movementContext, movementProps } = useKeyboardMovementProvider();\n *\n * // any focusable element child can be focused with the arrow , home, and\n * // end keys\n * return (\n * <KeyboardMovementProvider value={movementContext}>\n * <div {...movementProps}>\n * {children}\n * </div>\n * </KeyboardMovementProvider>\n * );\n * }\n * ```\n *\n * @example\n * Active Descendant Movement\n * ```tsx\n * import {\n * KeyboardMovementProvider,\n * useKeyboardMovementContext,\n * useKeyboardMovementProvider,\n * } from \"@react-md/core\";\n * import type { ReactElement, ReactNode } from \"react\";\n * import { useId } from \"react\";\n *\n * function Child(): ReactElement {\n * const id = useId()\n * const { activeDescendantId } = useKeyboardMovementContext();\n *\n * return (\n * <div\n * {...props}\n * id={id}\n * className={cnb(id === activeDescendantId && \"focused-class-name\")}\n * >\n * Some Content\n * </div>\n * );\n * }\n *\n * function Example({ children }: { children: ReactNode }): ReactElement {\n * const { movementContext, movementProps } = useKeyboardMovementProvider({\n * loopable: true,\n * searchable: true,\n * tabIndexBehavior: \"virtual\",\n * });\n *\n * // any focusable element child can be focused with the arrow , home, and\n * // end keys\n * return (\n * <KeyboardMovementProvider value={movementContext}>\n * <div {...movementProps}>\n * <Child />\n * <Child />\n * <Child />\n * </div>\n * </KeyboardMovementProvider>\n * );\n * }\n * ```\n *\n * @example\n * Roving Tab Index\n * ```tsx\n * import {\n * KeyboardMovementProvider,\n * useKeyboardMovementContext,\n * useKeyboardMovementProvider,\n * } from \"@react-md/core\";\n * import type { ReactElement, ReactNode } from \"react\";\n * import { useId } from \"react\";\n *\n * function Child(): ReactElement {\n * const id = useId()\n * const { activeDescendantId } = useKeyboardMovementContext();\n *\n * return (\n * <div\n * {...props}\n * id={id}\n * tabIndex={id === activeDescendantId ? 0 : -1}\n * >\n * Some Content\n * </div>\n * );\n * }\n *\n * function Example({ children }: { children: ReactNode }): ReactElement {\n * const { movementContext, movementProps } = useKeyboardMovementProvider({\n * loopable: true,\n * searchable: true,\n * tabIndexBehavior: \"roving\",\n * });\n *\n * // any focusable element child can be focused with the arrow , home, and\n * // end keys\n * return (\n * <KeyboardMovementProvider value={movementContext}>\n * <div {...movementProps}>\n * <Child />\n * <Child />\n * <Child />\n * </div>\n * </KeyboardMovementProvider>\n * );\n * }\n * ```\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport function useKeyboardMovementProvider<E extends HTMLElement>(\n options: KeyboardMovementProviderOptions<E> = {}\n): KeyboardMovementProviderImplementation<E> {\n const {\n onClick = noop,\n onFocus = noop,\n onKeyDown = noop,\n loopable = false,\n searchable = false,\n horizontal = false,\n includeDisabled = false,\n tabIndexBehavior,\n extendKeyDown = noop,\n onFocusChange = noop,\n programmatic = includeDisabled,\n incrementKeys: propIncrementKeys,\n decrementKeys: propDecrementKeys,\n jumpToFirstKeys: propJumpToFirstKeys,\n jumpToLastKeys: propJumpToLastKeys,\n getFocusableElements = defaultGetFocusableElements,\n getDefaultFocusedIndex = returnNegative1,\n } = options;\n\n const isRTL = useDir().dir === \"rtl\";\n let defaults: Readonly<Required<KeyboardMovementConfiguration>>;\n if (horizontal) {\n defaults = isRTL\n ? DEFAULT_RTL_KEYBOARD_MOVEMENT\n : DEFAULT_LTR_KEYBOARD_MOVEMENT;\n } else {\n defaults = DEFAULT_KEYBOARD_MOVEMENT;\n }\n\n const incrementKeys = propIncrementKeys || defaults.incrementKeys;\n const decrementKeys = propDecrementKeys || defaults.decrementKeys;\n const jumpToFirstKeys = propJumpToFirstKeys || defaults.jumpToFirstKeys;\n const jumpToLastKeys = propJumpToLastKeys || defaults.jumpToLastKeys;\n\n const configuration: KeyboardMovementConfig = {\n incrementKeys,\n decrementKeys,\n jumpToFirstKeys,\n jumpToLastKeys,\n };\n const config = useRef(configuration);\n useIsomorphicLayoutEffect(() => {\n config.current = configuration;\n });\n\n const [activeDescendantId, setActiveDescendantId] = useState(\"\");\n const movementContext = useMemo<KeyboardMovementContext>(\n () => ({\n config,\n loopable,\n searchable,\n horizontal,\n includeDisabled,\n tabIndexBehavior,\n activeDescendantId,\n }),\n [\n activeDescendantId,\n horizontal,\n includeDisabled,\n loopable,\n searchable,\n tabIndexBehavior,\n ]\n );\n const currentFocusIndex = useRef(-1);\n const mode = useUserInteractionMode();\n const refocus = useRef(false);\n\n if (process.env.NODE_ENV !== \"production\") {\n // this fixes issues during hot reloading and using the `useId()` hook\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n return () => {\n setActiveDescendantId(\"\");\n };\n }, []);\n }\n\n return {\n movementProps: {\n \"aria-activedescendant\":\n tabIndexBehavior === \"virtual\" ? activeDescendantId : undefined,\n tabIndex:\n tabIndexBehavior === \"roving\"\n ? activeDescendantId\n ? -1\n : 0\n : undefined,\n\n // Note: This used to be on the `onFocus` event, but this causes issues in\n // Chromium browsers for drag and drop behavior\n onClick(event) {\n onClick(event);\n\n // This makes it so you can click an element with a mouse and then\n // keyboard navigate from that element instead of the last keyboard focus\n // element\n const { currentTarget, target } = event;\n if (target === currentTarget || !(target instanceof HTMLElement)) {\n return;\n }\n\n const focusables = getFocusableElements(currentTarget, programmatic);\n const focusedIndex = focusables.findIndex(\n (element) => element === target || element.contains(target)\n );\n if (focusedIndex === -1 || !focusables.length) {\n return;\n }\n\n currentFocusIndex.current = focusedIndex;\n const focused = focusables[focusedIndex];\n if (tabIndexBehavior) {\n setActiveDescendantId(focused.id);\n }\n\n // need to force focus back to the container element when using\n // aria activedescendant\n if (tabIndexBehavior === \"virtual\") {\n refocus.current = true;\n currentTarget.focus();\n }\n\n onFocusChange({\n index: focusedIndex,\n element: focused,\n });\n },\n onFocus(event) {\n onFocus(event);\n if (event.isPropagationStopped() || refocus.current) {\n refocus.current = false;\n return;\n }\n\n if (\n (mode !== \"keyboard\" && tabIndexBehavior !== \"virtual\") ||\n event.target !== event.currentTarget\n ) {\n return;\n }\n\n const focusables = getFocusableElements(\n event.currentTarget,\n programmatic\n );\n if (!focusables.length) {\n return;\n }\n\n let defaultFocusIndex = getDefaultFocusedIndex({\n focusables,\n includeDisabled,\n });\n\n // This allows my custom `getDefaultFocusedIndex` implementations to\n // have a nice fallback without having to re-implement the \"focus\n // first\" behavior\n if (defaultFocusIndex === -1) {\n if (tabIndexBehavior === \"virtual\") {\n // virtual keyboard navigation **must** always focus at least one element\n defaultFocusIndex = getVirtualFocusDefaultIndex({\n focusables,\n includeDisabled,\n activeDescendantId,\n });\n } else {\n defaultFocusIndex = getFirstFocusableIndex({\n focusables,\n includeDisabled,\n });\n }\n }\n\n if (defaultFocusIndex === -1) {\n return;\n }\n\n currentFocusIndex.current = defaultFocusIndex;\n const focused = focusables[defaultFocusIndex];\n if (tabIndexBehavior) {\n setActiveDescendantId(focused.id);\n }\n\n if (tabIndexBehavior !== \"virtual\") {\n focused.focus();\n } else {\n focused.scrollIntoView({ block: \"nearest\" });\n }\n\n onFocusChange({\n index: defaultFocusIndex,\n element: focused,\n });\n },\n onKeyDown(event) {\n onKeyDown(event);\n const { currentTarget } = event;\n\n const setFocusIndex = (\n index: number,\n focusables: readonly HTMLElement[]\n ): void => {\n event.preventDefault();\n event.stopPropagation();\n if (currentFocusIndex.current === index || index === -1) {\n return;\n }\n\n currentFocusIndex.current = index;\n const focused = focusables[index];\n if (tabIndexBehavior) {\n focused.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n setActiveDescendantId(focused.id);\n }\n\n if (tabIndexBehavior !== \"virtual\") {\n focused.focus();\n }\n\n onFocusChange({\n index,\n element: focused,\n });\n };\n\n extendKeyDown({\n event,\n setFocusIndex,\n currentFocusIndex,\n setActiveDescendantId,\n ...movementContext,\n });\n\n if (event.isPropagationStopped()) {\n return;\n }\n\n // TODO: Figure this part out. This is currently required for the tree\n // movement when the asterisk key is pressed. There might be other cases\n // as well.\n if (currentFocusIndex.current === -1) {\n currentFocusIndex.current = recalculateFocusIndex({\n focusables: getFocusableElements(currentTarget, programmatic),\n includeDisabled,\n tabIndexBehavior,\n activeDescendantId,\n });\n }\n\n const { key, shiftKey } = event;\n if (\n tabIndexBehavior === \"virtual\" &&\n activeDescendantId &&\n (key === \" \" || key === \"Enter\")\n ) {\n if (key === \" \") {\n event.preventDefault();\n }\n\n const focusables = getFocusableElements(currentTarget, programmatic);\n const activeElement = focusables[currentFocusIndex.current];\n if (!activeElement || isElementDisabled(activeElement)) {\n return;\n }\n\n activeElement.click();\n return;\n }\n\n const {\n incrementKeys,\n decrementKeys,\n jumpToFirstKeys,\n jumpToLastKeys,\n } = config.current;\n\n if (searchable && isSearchableEvent(event)) {\n const focusables = getFocusableElements(currentTarget, programmatic);\n const index = findMatchIndex({\n value: key,\n values: focusables.map((element) =>\n getSearchText(element, !isNotFocusable(element, includeDisabled))\n ),\n startIndex: shiftKey ? -1 : currentFocusIndex.current,\n });\n setFocusIndex(index, focusables);\n return;\n }\n\n const jumpToFirst = jumpToFirstKeys.includes(key);\n const jumpToLast = !jumpToFirst && jumpToLastKeys.includes(key);\n const increment =\n !jumpToFirst && !jumpToLast && incrementKeys.includes(key);\n const decrement =\n !jumpToFirst &&\n !jumpToLast &&\n !increment &&\n decrementKeys.includes(key);\n\n if (!jumpToFirst && !jumpToLast && !increment && !decrement) {\n return;\n }\n const focusables = getFocusableElements(currentTarget, programmatic);\n\n let index: number;\n if (jumpToFirst) {\n index = getFirstFocusableIndex({\n focusables,\n includeDisabled,\n });\n } else if (jumpToLast) {\n index = getLastFocusableIndex({\n focusables,\n includeDisabled,\n });\n } else {\n index = getNextFocusableIndex({\n loopable,\n increment,\n focusables,\n includeDisabled,\n currentFocusIndex: currentFocusIndex.current,\n });\n }\n\n setFocusIndex(index, focusables);\n },\n },\n movementContext,\n currentFocusIndex,\n setActiveDescendantId,\n };\n}\n"],"names":["createContext","useContext","useEffect","useMemo","useRef","useState","getFocusableElements","defaultGetFocusableElements","useUserInteractionMode","useDir","useIsomorphicLayoutEffect","DEFAULT_KEYBOARD_MOVEMENT","DEFAULT_LTR_KEYBOARD_MOVEMENT","DEFAULT_RTL_KEYBOARD_MOVEMENT","findMatchIndex","getFirstFocusableIndex","getLastFocusableIndex","getNextFocusableIndex","getSearchText","getVirtualFocusDefaultIndex","isElementDisabled","isNotFocusable","isSearchableEvent","recalculateFocusIndex","context","config","current","loopable","searchable","horizontal","includeDisabled","tabIndexBehavior","undefined","activeDescendantId","displayName","Provider","KeyboardMovementProvider","useKeyboardMovementContext","noop","returnNegative1","useKeyboardMovementProvider","options","onClick","onFocus","onKeyDown","extendKeyDown","onFocusChange","programmatic","incrementKeys","propIncrementKeys","decrementKeys","propDecrementKeys","jumpToFirstKeys","propJumpToFirstKeys","jumpToLastKeys","propJumpToLastKeys","getDefaultFocusedIndex","isRTL","dir","defaults","configuration","setActiveDescendantId","movementContext","currentFocusIndex","mode","refocus","process","env","NODE_ENV","movementProps","tabIndex","event","currentTarget","target","HTMLElement","focusables","focusedIndex","findIndex","element","contains","length","focused","id","focus","index","isPropagationStopped","defaultFocusIndex","scrollIntoView","block","setFocusIndex","preventDefault","stopPropagation","inline","key","shiftKey","activeElement","click","value","values","map","startIndex","jumpToFirst","includes","jumpToLast","increment","decrement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/movement/useKeyboardMovementProvider.ts"],"sourcesContent":["\"use client\";\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { getFocusableElements as defaultGetFocusableElements } from \"../focus/utils.js\";\nimport { useUserInteractionMode } from \"../interaction/UserInteractionModeProvider.js\";\nimport { useDir } from \"../typography/WritingDirectionProvider.js\";\nimport { useIsomorphicLayoutEffect } from \"../useIsomorphicLayoutEffect.js\";\nimport {\n DEFAULT_KEYBOARD_MOVEMENT,\n DEFAULT_LTR_KEYBOARD_MOVEMENT,\n DEFAULT_RTL_KEYBOARD_MOVEMENT,\n} from \"./constants.js\";\nimport { findMatchIndex } from \"./findMatchIndex.js\";\nimport type {\n KeyboardMovementConfig,\n KeyboardMovementConfiguration,\n KeyboardMovementContext,\n KeyboardMovementProviderImplementation,\n KeyboardMovementProviderOptions,\n} from \"./types.js\";\nimport {\n getFirstFocusableIndex,\n getLastFocusableIndex,\n getNextFocusableIndex,\n getSearchText,\n getVirtualFocusDefaultIndex,\n isElementDisabled,\n isNotFocusable,\n isSearchableEvent,\n recalculateFocusIndex,\n} from \"./utils.js\";\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nconst context = createContext<KeyboardMovementContext>({\n config: { current: DEFAULT_KEYBOARD_MOVEMENT },\n loopable: false,\n searchable: false,\n horizontal: false,\n includeDisabled: false,\n tabIndexBehavior: undefined,\n activeDescendantId: \"\",\n});\ncontext.displayName = \"KeyboardMovement\";\nexport const { Provider: KeyboardMovementProvider } = context;\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport function useKeyboardMovementContext(): Readonly<KeyboardMovementContext> {\n return useContext(context);\n}\n\nconst noop = (): void => {\n // do nothing\n};\n\nconst returnNegative1 = (): number => -1;\n\n/**\n * Implements the custom keyboard movement behavior throughout react-md. Using\n * the \"Find References\" will be the best way to see example usage.\n *\n * @example\n * Default Keyboard Movement for any Focusable Element\n * ```tsx\n * import {\n * KeyboardMovementProvider,\n * useKeyboardMovementProvider,\n * } from \"@react-md/core\";\n * import type { ReactElement, ReactNode } from \"react\";\n *\n * function Example({ children }: { children: ReactNode }): ReactElement {\n * const { movementContext, movementProps } = useKeyboardMovementProvider();\n *\n * // any focusable element child can be focused with the arrow , home, and\n * // end keys\n * return (\n * <KeyboardMovementProvider value={movementContext}>\n * <div {...movementProps}>\n * {children}\n * </div>\n * </KeyboardMovementProvider>\n * );\n * }\n * ```\n *\n * @example\n * Active Descendant Movement\n * ```tsx\n * import {\n * KeyboardMovementProvider,\n * useKeyboardMovementContext,\n * useKeyboardMovementProvider,\n * } from \"@react-md/core\";\n * import type { ReactElement, ReactNode } from \"react\";\n * import { useId } from \"react\";\n *\n * function Child(): ReactElement {\n * const id = useId()\n * const { activeDescendantId } = useKeyboardMovementContext();\n *\n * return (\n * <div\n * {...props}\n * id={id}\n * className={cnb(id === activeDescendantId && \"focused-class-name\")}\n * >\n * Some Content\n * </div>\n * );\n * }\n *\n * function Example({ children }: { children: ReactNode }): ReactElement {\n * const { movementContext, movementProps } = useKeyboardMovementProvider({\n * loopable: true,\n * searchable: true,\n * tabIndexBehavior: \"virtual\",\n * });\n *\n * // any focusable element child can be focused with the arrow , home, and\n * // end keys\n * return (\n * <KeyboardMovementProvider value={movementContext}>\n * <div {...movementProps}>\n * <Child />\n * <Child />\n * <Child />\n * </div>\n * </KeyboardMovementProvider>\n * );\n * }\n * ```\n *\n * @example\n * Roving Tab Index\n * ```tsx\n * import {\n * KeyboardMovementProvider,\n * useKeyboardMovementContext,\n * useKeyboardMovementProvider,\n * } from \"@react-md/core\";\n * import type { ReactElement, ReactNode } from \"react\";\n * import { useId } from \"react\";\n *\n * function Child(): ReactElement {\n * const id = useId()\n * const { activeDescendantId } = useKeyboardMovementContext();\n *\n * return (\n * <div\n * {...props}\n * id={id}\n * tabIndex={id === activeDescendantId ? 0 : -1}\n * >\n * Some Content\n * </div>\n * );\n * }\n *\n * function Example({ children }: { children: ReactNode }): ReactElement {\n * const { movementContext, movementProps } = useKeyboardMovementProvider({\n * loopable: true,\n * searchable: true,\n * tabIndexBehavior: \"roving\",\n * });\n *\n * // any focusable element child can be focused with the arrow , home, and\n * // end keys\n * return (\n * <KeyboardMovementProvider value={movementContext}>\n * <div {...movementProps}>\n * <Child />\n * <Child />\n * <Child />\n * </div>\n * </KeyboardMovementProvider>\n * );\n * }\n * ```\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport function useKeyboardMovementProvider<E extends HTMLElement>(\n options: KeyboardMovementProviderOptions<E> = {}\n): KeyboardMovementProviderImplementation<E> {\n const {\n onClick = noop,\n onFocus = noop,\n onKeyDown = noop,\n loopable = false,\n disabled,\n searchable = false,\n horizontal = false,\n includeDisabled = false,\n tabIndexBehavior,\n extendKeyDown = noop,\n onFocusChange = noop,\n programmatic = includeDisabled,\n incrementKeys: propIncrementKeys,\n decrementKeys: propDecrementKeys,\n jumpToFirstKeys: propJumpToFirstKeys,\n jumpToLastKeys: propJumpToLastKeys,\n getFocusableElements = defaultGetFocusableElements,\n getDefaultFocusedIndex = returnNegative1,\n isNegativeOneAllowed = false,\n } = options;\n\n const isRTL = useDir().dir === \"rtl\";\n let defaults: Readonly<Required<KeyboardMovementConfiguration>>;\n if (horizontal) {\n defaults = isRTL\n ? DEFAULT_RTL_KEYBOARD_MOVEMENT\n : DEFAULT_LTR_KEYBOARD_MOVEMENT;\n } else {\n defaults = DEFAULT_KEYBOARD_MOVEMENT;\n }\n\n const incrementKeys = propIncrementKeys || defaults.incrementKeys;\n const decrementKeys = propDecrementKeys || defaults.decrementKeys;\n const jumpToFirstKeys = propJumpToFirstKeys || defaults.jumpToFirstKeys;\n const jumpToLastKeys = propJumpToLastKeys || defaults.jumpToLastKeys;\n\n const configuration: KeyboardMovementConfig = {\n incrementKeys,\n decrementKeys,\n jumpToFirstKeys,\n jumpToLastKeys,\n };\n const config = useRef(configuration);\n useIsomorphicLayoutEffect(() => {\n config.current = configuration;\n });\n\n const [activeDescendantId, setActiveDescendantId] = useState(\"\");\n const movementContext = useMemo<KeyboardMovementContext>(\n () => ({\n config,\n loopable,\n searchable,\n horizontal,\n includeDisabled,\n tabIndexBehavior,\n activeDescendantId,\n }),\n [\n activeDescendantId,\n horizontal,\n includeDisabled,\n loopable,\n searchable,\n tabIndexBehavior,\n ]\n );\n const currentFocusIndex = useRef(-1);\n const mode = useUserInteractionMode();\n const refocus = useRef(false);\n\n if (process.env.NODE_ENV !== \"production\") {\n // this fixes issues during hot reloading and using the `useId()` hook\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n return () => {\n setActiveDescendantId(\"\");\n };\n }, []);\n }\n\n let tabIndex: number | undefined;\n if (tabIndexBehavior) {\n tabIndex =\n disabled || (tabIndexBehavior === \"roving\" && activeDescendantId)\n ? -1\n : 0;\n }\n\n return {\n movementProps: {\n \"aria-activedescendant\":\n tabIndexBehavior === \"virtual\" ? activeDescendantId : undefined,\n tabIndex,\n\n // Note: This used to be on the `onFocus` event, but this causes issues in\n // Chromium browsers for drag and drop behavior\n onClick(event) {\n onClick(event);\n if (disabled) {\n return;\n }\n\n // This makes it so you can click an element with a mouse and then\n // keyboard navigate from that element instead of the last keyboard focus\n // element\n const { currentTarget, target } = event;\n if (target === currentTarget || !(target instanceof HTMLElement)) {\n return;\n }\n\n const focusables = getFocusableElements(currentTarget, programmatic);\n const focusedIndex = focusables.findIndex(\n (element) => element === target || element.contains(target)\n );\n if (focusedIndex === -1 || !focusables.length) {\n return;\n }\n\n currentFocusIndex.current = focusedIndex;\n const focused = focusables[focusedIndex];\n if (tabIndexBehavior) {\n setActiveDescendantId(focused.id);\n }\n\n // need to force focus back to the container element when using\n // aria activedescendant\n if (tabIndexBehavior === \"virtual\") {\n refocus.current = true;\n currentTarget.focus();\n }\n\n onFocusChange({\n index: focusedIndex,\n element: focused,\n });\n },\n onFocus(event) {\n onFocus(event);\n if (event.isPropagationStopped() || refocus.current) {\n refocus.current = false;\n return;\n }\n\n if (\n (mode !== \"keyboard\" && tabIndexBehavior !== \"virtual\") ||\n event.target !== event.currentTarget\n ) {\n return;\n }\n\n const focusables = getFocusableElements(\n event.currentTarget,\n programmatic\n );\n if (!focusables.length) {\n return;\n }\n\n let defaultFocusIndex = getDefaultFocusedIndex({\n focusables,\n includeDisabled,\n });\n\n // This allows my custom `getDefaultFocusedIndex` implementations to\n // have a nice fallback without having to re-implement the \"focus\n // first\" behavior\n if (!isNegativeOneAllowed && defaultFocusIndex === -1) {\n if (tabIndexBehavior === \"virtual\") {\n // virtual keyboard navigation **must** always focus at least one element\n defaultFocusIndex = getVirtualFocusDefaultIndex({\n focusables,\n includeDisabled,\n activeDescendantId,\n });\n } else {\n defaultFocusIndex = getFirstFocusableIndex({\n focusables,\n includeDisabled,\n });\n }\n }\n\n if (defaultFocusIndex === -1) {\n return;\n }\n\n currentFocusIndex.current = defaultFocusIndex;\n const focused = focusables[defaultFocusIndex];\n if (tabIndexBehavior) {\n setActiveDescendantId(focused.id);\n }\n\n if (tabIndexBehavior !== \"virtual\") {\n focused.focus();\n } else {\n focused.scrollIntoView({ block: \"nearest\" });\n }\n\n onFocusChange({\n index: defaultFocusIndex,\n element: focused,\n });\n },\n onKeyDown(event) {\n onKeyDown(event);\n if (disabled) {\n return;\n }\n\n const { currentTarget } = event;\n\n const setFocusIndex = (\n index: number,\n focusables: readonly HTMLElement[]\n ): void => {\n event.preventDefault();\n event.stopPropagation();\n if (currentFocusIndex.current === index || index === -1) {\n return;\n }\n\n currentFocusIndex.current = index;\n const focused = focusables[index];\n if (tabIndexBehavior) {\n focused.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n setActiveDescendantId(focused.id);\n }\n\n if (tabIndexBehavior !== \"virtual\") {\n focused.focus();\n }\n\n onFocusChange({\n index,\n element: focused,\n });\n };\n\n extendKeyDown({\n event,\n setFocusIndex,\n currentFocusIndex,\n setActiveDescendantId,\n ...movementContext,\n });\n\n if (event.isPropagationStopped()) {\n return;\n }\n\n // TODO: Figure this part out. This is currently required for the tree\n // movement when the asterisk key is pressed. There might be other cases\n // as well.\n if (!isNegativeOneAllowed && currentFocusIndex.current === -1) {\n currentFocusIndex.current = recalculateFocusIndex({\n focusables: getFocusableElements(currentTarget, programmatic),\n includeDisabled,\n tabIndexBehavior,\n activeDescendantId,\n });\n }\n\n const { key, shiftKey } = event;\n if (\n tabIndexBehavior === \"virtual\" &&\n activeDescendantId &&\n (key === \" \" || key === \"Enter\")\n ) {\n if (key === \" \") {\n event.preventDefault();\n }\n\n const focusables = getFocusableElements(currentTarget, programmatic);\n const activeElement = focusables[currentFocusIndex.current];\n if (!activeElement || isElementDisabled(activeElement)) {\n return;\n }\n\n activeElement.click();\n return;\n }\n\n const {\n incrementKeys,\n decrementKeys,\n jumpToFirstKeys,\n jumpToLastKeys,\n } = config.current;\n\n if (searchable && isSearchableEvent(event)) {\n const focusables = getFocusableElements(currentTarget, programmatic);\n const index = findMatchIndex({\n value: key,\n values: focusables.map((element) =>\n getSearchText(element, !isNotFocusable(element, includeDisabled))\n ),\n startIndex: shiftKey ? -1 : currentFocusIndex.current,\n });\n setFocusIndex(index, focusables);\n return;\n }\n\n const jumpToFirst = jumpToFirstKeys.includes(key);\n const jumpToLast = !jumpToFirst && jumpToLastKeys.includes(key);\n const increment =\n !jumpToFirst && !jumpToLast && incrementKeys.includes(key);\n const decrement =\n !jumpToFirst &&\n !jumpToLast &&\n !increment &&\n decrementKeys.includes(key);\n\n if (!jumpToFirst && !jumpToLast && !increment && !decrement) {\n return;\n }\n const focusables = getFocusableElements(currentTarget, programmatic);\n\n let index: number;\n if (jumpToFirst) {\n index = getFirstFocusableIndex({\n focusables,\n includeDisabled,\n });\n } else if (jumpToLast) {\n index = getLastFocusableIndex({\n focusables,\n includeDisabled,\n });\n } else {\n index = getNextFocusableIndex({\n loopable,\n increment,\n focusables,\n includeDisabled,\n currentFocusIndex: currentFocusIndex.current,\n });\n }\n\n setFocusIndex(index, focusables);\n },\n },\n movementContext,\n currentFocusIndex,\n activeDescendantId,\n setActiveDescendantId,\n };\n}\n"],"names":["createContext","useContext","useEffect","useMemo","useRef","useState","getFocusableElements","defaultGetFocusableElements","useUserInteractionMode","useDir","useIsomorphicLayoutEffect","DEFAULT_KEYBOARD_MOVEMENT","DEFAULT_LTR_KEYBOARD_MOVEMENT","DEFAULT_RTL_KEYBOARD_MOVEMENT","findMatchIndex","getFirstFocusableIndex","getLastFocusableIndex","getNextFocusableIndex","getSearchText","getVirtualFocusDefaultIndex","isElementDisabled","isNotFocusable","isSearchableEvent","recalculateFocusIndex","context","config","current","loopable","searchable","horizontal","includeDisabled","tabIndexBehavior","undefined","activeDescendantId","displayName","Provider","KeyboardMovementProvider","useKeyboardMovementContext","noop","returnNegative1","useKeyboardMovementProvider","options","onClick","onFocus","onKeyDown","disabled","extendKeyDown","onFocusChange","programmatic","incrementKeys","propIncrementKeys","decrementKeys","propDecrementKeys","jumpToFirstKeys","propJumpToFirstKeys","jumpToLastKeys","propJumpToLastKeys","getDefaultFocusedIndex","isNegativeOneAllowed","isRTL","dir","defaults","configuration","setActiveDescendantId","movementContext","currentFocusIndex","mode","refocus","process","env","NODE_ENV","tabIndex","movementProps","event","currentTarget","target","HTMLElement","focusables","focusedIndex","findIndex","element","contains","length","focused","id","focus","index","isPropagationStopped","defaultFocusIndex","scrollIntoView","block","setFocusIndex","preventDefault","stopPropagation","inline","key","shiftKey","activeElement","click","value","values","map","startIndex","jumpToFirst","includes","jumpToLast","increment","decrement"],"mappings":"AAAA;AACA,SACEA,aAAa,EACbC,UAAU,EACVC,SAAS,EACTC,OAAO,EACPC,MAAM,EACNC,QAAQ,QACH,QAAQ;AACf,SAASC,wBAAwBC,2BAA2B,QAAQ,oBAAoB;AACxF,SAASC,sBAAsB,QAAQ,gDAAgD;AACvF,SAASC,MAAM,QAAQ,4CAA4C;AACnE,SAASC,yBAAyB,QAAQ,kCAAkC;AAC5E,SACEC,yBAAyB,EACzBC,6BAA6B,EAC7BC,6BAA6B,QACxB,iBAAiB;AACxB,SAASC,cAAc,QAAQ,sBAAsB;AAQrD,SACEC,sBAAsB,EACtBC,qBAAqB,EACrBC,qBAAqB,EACrBC,aAAa,EACbC,2BAA2B,EAC3BC,iBAAiB,EACjBC,cAAc,EACdC,iBAAiB,EACjBC,qBAAqB,QAChB,aAAa;AAEpB;;;CAGC,GACD,MAAMC,UAAUxB,cAAuC;IACrDyB,QAAQ;QAAEC,SAASf;IAA0B;IAC7CgB,UAAU;IACVC,YAAY;IACZC,YAAY;IACZC,iBAAiB;IACjBC,kBAAkBC;IAClBC,oBAAoB;AACtB;AACAT,QAAQU,WAAW,GAAG;AACtB,OAAO,MAAM,EAAEC,UAAUC,wBAAwB,EAAE,GAAGZ,QAAQ;AAE9D;;;CAGC,GACD,OAAO,SAASa;IACd,OAAOpC,WAAWuB;AACpB;AAEA,MAAMc,OAAO;AACX,aAAa;AACf;AAEA,MAAMC,kBAAkB,IAAc,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2HC,GACD,OAAO,SAASC,4BACdC,UAA8C,CAAC,CAAC;IAEhD,MAAM,EACJC,UAAUJ,IAAI,EACdK,UAAUL,IAAI,EACdM,YAAYN,IAAI,EAChBX,WAAW,KAAK,EAChBkB,QAAQ,EACRjB,aAAa,KAAK,EAClBC,aAAa,KAAK,EAClBC,kBAAkB,KAAK,EACvBC,gBAAgB,EAChBe,gBAAgBR,IAAI,EACpBS,gBAAgBT,IAAI,EACpBU,eAAelB,eAAe,EAC9BmB,eAAeC,iBAAiB,EAChCC,eAAeC,iBAAiB,EAChCC,iBAAiBC,mBAAmB,EACpCC,gBAAgBC,kBAAkB,EAClClD,uBAAuBC,2BAA2B,EAClDkD,yBAAyBlB,eAAe,EACxCmB,uBAAuB,KAAK,EAC7B,GAAGjB;IAEJ,MAAMkB,QAAQlD,SAASmD,GAAG,KAAK;IAC/B,IAAIC;IACJ,IAAIhC,YAAY;QACdgC,WAAWF,QACP9C,gCACAD;IACN,OAAO;QACLiD,WAAWlD;IACb;IAEA,MAAMsC,gBAAgBC,qBAAqBW,SAASZ,aAAa;IACjE,MAAME,gBAAgBC,qBAAqBS,SAASV,aAAa;IACjE,MAAME,kBAAkBC,uBAAuBO,SAASR,eAAe;IACvE,MAAME,iBAAiBC,sBAAsBK,SAASN,cAAc;IAEpE,MAAMO,gBAAwC;QAC5Cb;QACAE;QACAE;QACAE;IACF;IACA,MAAM9B,SAASrB,OAAO0D;IACtBpD,0BAA0B;QACxBe,OAAOC,OAAO,GAAGoC;IACnB;IAEA,MAAM,CAAC7B,oBAAoB8B,sBAAsB,GAAG1D,SAAS;IAC7D,MAAM2D,kBAAkB7D,QACtB,IAAO,CAAA;YACLsB;YACAE;YACAC;YACAC;YACAC;YACAC;YACAE;QACF,CAAA,GACA;QACEA;QACAJ;QACAC;QACAH;QACAC;QACAG;KACD;IAEH,MAAMkC,oBAAoB7D,OAAO,CAAC;IAClC,MAAM8D,OAAO1D;IACb,MAAM2D,UAAU/D,OAAO;IAEvB,IAAIgE,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,sEAAsE;QACtE,sDAAsD;QACtDpE,UAAU;YACR,OAAO;gBACL6D,sBAAsB;YACxB;QACF,GAAG,EAAE;IACP;IAEA,IAAIQ;IACJ,IAAIxC,kBAAkB;QACpBwC,WACE1B,YAAad,qBAAqB,YAAYE,qBAC1C,CAAC,IACD;IACR;IAEA,OAAO;QACLuC,eAAe;YACb,yBACEzC,qBAAqB,YAAYE,qBAAqBD;YACxDuC;YAEA,0EAA0E;YAC1E,+CAA+C;YAC/C7B,SAAQ+B,KAAK;gBACX/B,QAAQ+B;gBACR,IAAI5B,UAAU;oBACZ;gBACF;gBAEA,kEAAkE;gBAClE,yEAAyE;gBACzE,UAAU;gBACV,MAAM,EAAE6B,aAAa,EAAEC,MAAM,EAAE,GAAGF;gBAClC,IAAIE,WAAWD,iBAAiB,CAAEC,CAAAA,kBAAkBC,WAAU,GAAI;oBAChE;gBACF;gBAEA,MAAMC,aAAavE,qBAAqBoE,eAAe1B;gBACvD,MAAM8B,eAAeD,WAAWE,SAAS,CACvC,CAACC,UAAYA,YAAYL,UAAUK,QAAQC,QAAQ,CAACN;gBAEtD,IAAIG,iBAAiB,CAAC,KAAK,CAACD,WAAWK,MAAM,EAAE;oBAC7C;gBACF;gBAEAjB,kBAAkBvC,OAAO,GAAGoD;gBAC5B,MAAMK,UAAUN,UAAU,CAACC,aAAa;gBACxC,IAAI/C,kBAAkB;oBACpBgC,sBAAsBoB,QAAQC,EAAE;gBAClC;gBAEA,+DAA+D;gBAC/D,wBAAwB;gBACxB,IAAIrD,qBAAqB,WAAW;oBAClCoC,QAAQzC,OAAO,GAAG;oBAClBgD,cAAcW,KAAK;gBACrB;gBAEAtC,cAAc;oBACZuC,OAAOR;oBACPE,SAASG;gBACX;YACF;YACAxC,SAAQ8B,KAAK;gBACX9B,QAAQ8B;gBACR,IAAIA,MAAMc,oBAAoB,MAAMpB,QAAQzC,OAAO,EAAE;oBACnDyC,QAAQzC,OAAO,GAAG;oBAClB;gBACF;gBAEA,IACE,AAACwC,SAAS,cAAcnC,qBAAqB,aAC7C0C,MAAME,MAAM,KAAKF,MAAMC,aAAa,EACpC;oBACA;gBACF;gBAEA,MAAMG,aAAavE,qBACjBmE,MAAMC,aAAa,EACnB1B;gBAEF,IAAI,CAAC6B,WAAWK,MAAM,EAAE;oBACtB;gBACF;gBAEA,IAAIM,oBAAoB/B,uBAAuB;oBAC7CoB;oBACA/C;gBACF;gBAEA,oEAAoE;gBACpE,iEAAiE;gBACjE,kBAAkB;gBAClB,IAAI,CAAC4B,wBAAwB8B,sBAAsB,CAAC,GAAG;oBACrD,IAAIzD,qBAAqB,WAAW;wBAClC,yEAAyE;wBACzEyD,oBAAoBrE,4BAA4B;4BAC9C0D;4BACA/C;4BACAG;wBACF;oBACF,OAAO;wBACLuD,oBAAoBzE,uBAAuB;4BACzC8D;4BACA/C;wBACF;oBACF;gBACF;gBAEA,IAAI0D,sBAAsB,CAAC,GAAG;oBAC5B;gBACF;gBAEAvB,kBAAkBvC,OAAO,GAAG8D;gBAC5B,MAAML,UAAUN,UAAU,CAACW,kBAAkB;gBAC7C,IAAIzD,kBAAkB;oBACpBgC,sBAAsBoB,QAAQC,EAAE;gBAClC;gBAEA,IAAIrD,qBAAqB,WAAW;oBAClCoD,QAAQE,KAAK;gBACf,OAAO;oBACLF,QAAQM,cAAc,CAAC;wBAAEC,OAAO;oBAAU;gBAC5C;gBAEA3C,cAAc;oBACZuC,OAAOE;oBACPR,SAASG;gBACX;YACF;YACAvC,WAAU6B,KAAK;gBACb7B,UAAU6B;gBACV,IAAI5B,UAAU;oBACZ;gBACF;gBAEA,MAAM,EAAE6B,aAAa,EAAE,GAAGD;gBAE1B,MAAMkB,gBAAgB,CACpBL,OACAT;oBAEAJ,MAAMmB,cAAc;oBACpBnB,MAAMoB,eAAe;oBACrB,IAAI5B,kBAAkBvC,OAAO,KAAK4D,SAASA,UAAU,CAAC,GAAG;wBACvD;oBACF;oBAEArB,kBAAkBvC,OAAO,GAAG4D;oBAC5B,MAAMH,UAAUN,UAAU,CAACS,MAAM;oBACjC,IAAIvD,kBAAkB;wBACpBoD,QAAQM,cAAc,CAAC;4BACrBC,OAAO;4BACPI,QAAQ;wBACV;wBACA/B,sBAAsBoB,QAAQC,EAAE;oBAClC;oBAEA,IAAIrD,qBAAqB,WAAW;wBAClCoD,QAAQE,KAAK;oBACf;oBAEAtC,cAAc;wBACZuC;wBACAN,SAASG;oBACX;gBACF;gBAEArC,cAAc;oBACZ2B;oBACAkB;oBACA1B;oBACAF;oBACA,GAAGC,eAAe;gBACpB;gBAEA,IAAIS,MAAMc,oBAAoB,IAAI;oBAChC;gBACF;gBAEA,sEAAsE;gBACtE,wEAAwE;gBACxE,WAAW;gBACX,IAAI,CAAC7B,wBAAwBO,kBAAkBvC,OAAO,KAAK,CAAC,GAAG;oBAC7DuC,kBAAkBvC,OAAO,GAAGH,sBAAsB;wBAChDsD,YAAYvE,qBAAqBoE,eAAe1B;wBAChDlB;wBACAC;wBACAE;oBACF;gBACF;gBAEA,MAAM,EAAE8D,GAAG,EAAEC,QAAQ,EAAE,GAAGvB;gBAC1B,IACE1C,qBAAqB,aACrBE,sBACC8D,CAAAA,QAAQ,OAAOA,QAAQ,OAAM,GAC9B;oBACA,IAAIA,QAAQ,KAAK;wBACftB,MAAMmB,cAAc;oBACtB;oBAEA,MAAMf,aAAavE,qBAAqBoE,eAAe1B;oBACvD,MAAMiD,gBAAgBpB,UAAU,CAACZ,kBAAkBvC,OAAO,CAAC;oBAC3D,IAAI,CAACuE,iBAAiB7E,kBAAkB6E,gBAAgB;wBACtD;oBACF;oBAEAA,cAAcC,KAAK;oBACnB;gBACF;gBAEA,MAAM,EACJjD,aAAa,EACbE,aAAa,EACbE,eAAe,EACfE,cAAc,EACf,GAAG9B,OAAOC,OAAO;gBAElB,IAAIE,cAAcN,kBAAkBmD,QAAQ;oBAC1C,MAAMI,aAAavE,qBAAqBoE,eAAe1B;oBACvD,MAAMsC,QAAQxE,eAAe;wBAC3BqF,OAAOJ;wBACPK,QAAQvB,WAAWwB,GAAG,CAAC,CAACrB,UACtB9D,cAAc8D,SAAS,CAAC3D,eAAe2D,SAASlD;wBAElDwE,YAAYN,WAAW,CAAC,IAAI/B,kBAAkBvC,OAAO;oBACvD;oBACAiE,cAAcL,OAAOT;oBACrB;gBACF;gBAEA,MAAM0B,cAAclD,gBAAgBmD,QAAQ,CAACT;gBAC7C,MAAMU,aAAa,CAACF,eAAehD,eAAeiD,QAAQ,CAACT;gBAC3D,MAAMW,YACJ,CAACH,eAAe,CAACE,cAAcxD,cAAcuD,QAAQ,CAACT;gBACxD,MAAMY,YACJ,CAACJ,eACD,CAACE,cACD,CAACC,aACDvD,cAAcqD,QAAQ,CAACT;gBAEzB,IAAI,CAACQ,eAAe,CAACE,cAAc,CAACC,aAAa,CAACC,WAAW;oBAC3D;gBACF;gBACA,MAAM9B,aAAavE,qBAAqBoE,eAAe1B;gBAEvD,IAAIsC;gBACJ,IAAIiB,aAAa;oBACfjB,QAAQvE,uBAAuB;wBAC7B8D;wBACA/C;oBACF;gBACF,OAAO,IAAI2E,YAAY;oBACrBnB,QAAQtE,sBAAsB;wBAC5B6D;wBACA/C;oBACF;gBACF,OAAO;oBACLwD,QAAQrE,sBAAsB;wBAC5BU;wBACA+E;wBACA7B;wBACA/C;wBACAmC,mBAAmBA,kBAAkBvC,OAAO;oBAC9C;gBACF;gBAEAiE,cAAcL,OAAOT;YACvB;QACF;QACAb;QACAC;QACAhC;QACA8B;IACF;AACF"}
|
package/dist/movement/utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
1
|
+
import { type KeyboardEvent } from "react";
|
|
2
|
+
import { type FocusableIndexOptions, type TabIndexBehavior } from "./types.js";
|
|
3
3
|
/**
|
|
4
4
|
* @remarks \@since 6.0.0
|
|
5
5
|
* @internal
|
|
@@ -86,4 +86,9 @@ export declare function recalculateFocusIndex(options: RecalculateOptions): numb
|
|
|
86
86
|
* @internal
|
|
87
87
|
*/
|
|
88
88
|
export declare function isSearchableEvent(event: KeyboardEvent): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* @remarks \@since 6.0.0
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
export declare function isTypeEvent(event: KeyboardEvent): boolean;
|
|
89
94
|
export {};
|
package/dist/movement/utils.js
CHANGED
|
@@ -155,5 +155,15 @@ import { loop } from "../utils/loop.js";
|
|
|
155
155
|
return key.length === 1 && // can't search with space since it is generally a click event
|
|
156
156
|
key !== " " && !altKey && !ctrlKey && !metaKey;
|
|
157
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* @remarks \@since 6.0.0
|
|
160
|
+
* @internal
|
|
161
|
+
*/ export function isTypeEvent(event) {
|
|
162
|
+
return isSearchableEvent(event) || [
|
|
163
|
+
"Backspace",
|
|
164
|
+
"Delete",
|
|
165
|
+
" "
|
|
166
|
+
].includes(event.key);
|
|
167
|
+
}
|
|
158
168
|
|
|
159
169
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/movement/utils.ts"],"sourcesContent":["import type { KeyboardEvent } from \"react\";\nimport { loop } from \"../utils/loop.js\";\nimport type { FocusableIndexOptions, TabIndexBehavior } from \"./types.js\";\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport const isElementDisabled = (element: HTMLElement): boolean =>\n element.getAttribute(\"disabled\") !== null ||\n element.getAttribute(\"aria-disabled\") === \"true\";\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const isNotFocusable = (\n element: HTMLElement | undefined,\n includeDisabled: boolean\n): boolean => {\n if (!element) {\n return true;\n }\n\n if (includeDisabled) {\n return false;\n }\n\n return isElementDisabled(element);\n};\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface VirtualFocusableIndexOptions {\n focusables: readonly HTMLElement[];\n includeDisabled: boolean;\n activeDescendantId: string;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport const getVirtualFocusDefaultIndex = (\n options: VirtualFocusableIndexOptions\n): number => {\n const { focusables, includeDisabled, activeDescendantId } = options;\n if (!focusables.length || (!activeDescendantId && includeDisabled)) {\n return 0;\n }\n\n const activeIndex = focusables.findIndex((element) => {\n if (activeDescendantId) {\n return element.id === activeDescendantId;\n }\n\n return !isElementDisabled(element);\n });\n return Math.max(0, activeIndex);\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const getFirstFocusableIndex = (\n options: FocusableIndexOptions\n): number => {\n const { focusables, includeDisabled } = options;\n\n if (!focusables.length) {\n return -1;\n }\n\n let firstIndex = 0;\n while (\n firstIndex < focusables.length - 1 &&\n isNotFocusable(focusables[firstIndex], includeDisabled)\n ) {\n firstIndex += 1;\n }\n\n if (isNotFocusable(focusables[firstIndex], includeDisabled)) {\n return -1;\n }\n\n return firstIndex;\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const getLastFocusableIndex = (\n options: FocusableIndexOptions\n): number => {\n const { focusables, includeDisabled } = options;\n\n if (!focusables.length) {\n return -1;\n }\n\n let lastIndex = focusables.length - 1;\n while (\n lastIndex > 0 &&\n isNotFocusable(focusables[lastIndex], includeDisabled)\n ) {\n lastIndex -= 1;\n }\n\n if (isNotFocusable(focusables[lastIndex], includeDisabled)) {\n return -1;\n }\n\n return lastIndex;\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\ninterface NextFocusableIndexOptions extends FocusableIndexOptions {\n loopable: boolean;\n increment: boolean;\n currentFocusIndex: number;\n}\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const getNextFocusableIndex = (\n options: NextFocusableIndexOptions\n): number => {\n const {\n loopable,\n increment,\n focusables,\n includeDisabled,\n currentFocusIndex,\n } = options;\n if (!focusables.length) {\n return currentFocusIndex;\n }\n\n const min = getFirstFocusableIndex({ focusables, includeDisabled });\n const max = getLastFocusableIndex({ focusables, includeDisabled });\n let nextIndex = loop({\n min,\n max,\n value: currentFocusIndex,\n minmax: !loopable,\n increment,\n });\n while (\n isNotFocusable(focusables[nextIndex], includeDisabled) &&\n (loopable || nextIndex !== (increment ? max : min))\n ) {\n nextIndex = loop({\n min,\n max,\n value: nextIndex,\n minmax: !loopable,\n increment,\n });\n }\n\n // Since the `min` and `max` values are \"safely\" set, I don't need to verify\n // the nextIndex is still focusable\n return nextIndex;\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport function getSearchText(\n element: HTMLElement,\n searchable: boolean\n): string {\n if (!searchable) {\n return \"\";\n }\n\n const cloned = element.cloneNode(true) as HTMLElement;\n cloned\n .querySelectorAll(\n // Note: do not include DISPLAY_NONE_CLASS since it is presentational only\n \".rmd-icon--font,[aria-hidden=true],[hidden],[role=presentation]\"\n )\n .forEach((element) => {\n element.parentNode?.removeChild(element);\n });\n\n // Note: It would be good to use `cloned.innerText` (maybe?) at some point,\n // but it returns `undefined` in jsdom. It also does cause a reflow, so maybe\n // this is fine?\n // https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#differences_from_innertext\n return (cloned.textContent || \"\")[0].toUpperCase();\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface RecalculateOptions {\n focusables: readonly HTMLElement[];\n includeDisabled: boolean;\n tabIndexBehavior: TabIndexBehavior | undefined;\n activeDescendantId: string;\n}\n\n/**\n * This was added to help with specific widgets that cause focus index to change\n * between renders (i.e. expanding all tree items on the same level with `*`).\n * There might be a better way to handle this in the future.\n *\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport function recalculateFocusIndex(options: RecalculateOptions): number {\n const { focusables, includeDisabled, tabIndexBehavior, activeDescendantId } =\n options;\n if (tabIndexBehavior === \"virtual\") {\n return getVirtualFocusDefaultIndex({\n focusables,\n includeDisabled,\n activeDescendantId,\n });\n }\n\n const { activeElement } = document;\n return focusables.findIndex((element) => element === activeElement);\n}\n\n/**\n * Checks if a keyboard event can trigger a search through focusable elements\n * by:\n *\n * - checking if the key is a single letter that is not the space key\n * - checking that the alt, ctrl, and meta keys are not being held\n *\n * The shift key **is allowed** because holding shift means \"search from the\n * beginning\" instead of \"search from current location\".\n *\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport function isSearchableEvent(event: KeyboardEvent): boolean {\n const { key, altKey, ctrlKey, metaKey } = event;\n\n return (\n key.length === 1 &&\n // can't search with space since it is generally a click event\n key !== \" \" &&\n !altKey &&\n !ctrlKey &&\n !metaKey\n );\n}\n"],"names":["loop","isElementDisabled","element","getAttribute","isNotFocusable","includeDisabled","getVirtualFocusDefaultIndex","options","focusables","activeDescendantId","length","activeIndex","findIndex","id","Math","max","getFirstFocusableIndex","firstIndex","getLastFocusableIndex","lastIndex","getNextFocusableIndex","loopable","increment","currentFocusIndex","min","nextIndex","value","minmax","getSearchText","searchable","cloned","cloneNode","querySelectorAll","forEach","parentNode","removeChild","textContent","toUpperCase","recalculateFocusIndex","tabIndexBehavior","activeElement","document","isSearchableEvent","event","key","altKey","ctrlKey","metaKey"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/movement/utils.ts"],"sourcesContent":["import { type KeyboardEvent } from \"react\";\nimport { loop } from \"../utils/loop.js\";\nimport { type FocusableIndexOptions, type TabIndexBehavior } from \"./types.js\";\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport const isElementDisabled = (element: HTMLElement): boolean =>\n element.getAttribute(\"disabled\") !== null ||\n element.getAttribute(\"aria-disabled\") === \"true\";\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const isNotFocusable = (\n element: HTMLElement | undefined,\n includeDisabled: boolean\n): boolean => {\n if (!element) {\n return true;\n }\n\n if (includeDisabled) {\n return false;\n }\n\n return isElementDisabled(element);\n};\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface VirtualFocusableIndexOptions {\n focusables: readonly HTMLElement[];\n includeDisabled: boolean;\n activeDescendantId: string;\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport const getVirtualFocusDefaultIndex = (\n options: VirtualFocusableIndexOptions\n): number => {\n const { focusables, includeDisabled, activeDescendantId } = options;\n if (!focusables.length || (!activeDescendantId && includeDisabled)) {\n return 0;\n }\n\n const activeIndex = focusables.findIndex((element) => {\n if (activeDescendantId) {\n return element.id === activeDescendantId;\n }\n\n return !isElementDisabled(element);\n });\n return Math.max(0, activeIndex);\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const getFirstFocusableIndex = (\n options: FocusableIndexOptions\n): number => {\n const { focusables, includeDisabled } = options;\n\n if (!focusables.length) {\n return -1;\n }\n\n let firstIndex = 0;\n while (\n firstIndex < focusables.length - 1 &&\n isNotFocusable(focusables[firstIndex], includeDisabled)\n ) {\n firstIndex += 1;\n }\n\n if (isNotFocusable(focusables[firstIndex], includeDisabled)) {\n return -1;\n }\n\n return firstIndex;\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const getLastFocusableIndex = (\n options: FocusableIndexOptions\n): number => {\n const { focusables, includeDisabled } = options;\n\n if (!focusables.length) {\n return -1;\n }\n\n let lastIndex = focusables.length - 1;\n while (\n lastIndex > 0 &&\n isNotFocusable(focusables[lastIndex], includeDisabled)\n ) {\n lastIndex -= 1;\n }\n\n if (isNotFocusable(focusables[lastIndex], includeDisabled)) {\n return -1;\n }\n\n return lastIndex;\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\ninterface NextFocusableIndexOptions extends FocusableIndexOptions {\n loopable: boolean;\n increment: boolean;\n currentFocusIndex: number;\n}\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport const getNextFocusableIndex = (\n options: NextFocusableIndexOptions\n): number => {\n const {\n loopable,\n increment,\n focusables,\n includeDisabled,\n currentFocusIndex,\n } = options;\n if (!focusables.length) {\n return currentFocusIndex;\n }\n\n const min = getFirstFocusableIndex({ focusables, includeDisabled });\n const max = getLastFocusableIndex({ focusables, includeDisabled });\n let nextIndex = loop({\n min,\n max,\n value: currentFocusIndex,\n minmax: !loopable,\n increment,\n });\n while (\n isNotFocusable(focusables[nextIndex], includeDisabled) &&\n (loopable || nextIndex !== (increment ? max : min))\n ) {\n nextIndex = loop({\n min,\n max,\n value: nextIndex,\n minmax: !loopable,\n increment,\n });\n }\n\n // Since the `min` and `max` values are \"safely\" set, I don't need to verify\n // the nextIndex is still focusable\n return nextIndex;\n};\n\n/**\n * @remarks \\@since 5.0.0\n * @internal\n */\nexport function getSearchText(\n element: HTMLElement,\n searchable: boolean\n): string {\n if (!searchable) {\n return \"\";\n }\n\n const cloned = element.cloneNode(true) as HTMLElement;\n cloned\n .querySelectorAll(\n // Note: do not include DISPLAY_NONE_CLASS since it is presentational only\n \".rmd-icon--font,[aria-hidden=true],[hidden],[role=presentation]\"\n )\n .forEach((element) => {\n element.parentNode?.removeChild(element);\n });\n\n // Note: It would be good to use `cloned.innerText` (maybe?) at some point,\n // but it returns `undefined` in jsdom. It also does cause a reflow, so maybe\n // this is fine?\n // https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#differences_from_innertext\n return (cloned.textContent || \"\")[0].toUpperCase();\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport interface RecalculateOptions {\n focusables: readonly HTMLElement[];\n includeDisabled: boolean;\n tabIndexBehavior: TabIndexBehavior | undefined;\n activeDescendantId: string;\n}\n\n/**\n * This was added to help with specific widgets that cause focus index to change\n * between renders (i.e. expanding all tree items on the same level with `*`).\n * There might be a better way to handle this in the future.\n *\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport function recalculateFocusIndex(options: RecalculateOptions): number {\n const { focusables, includeDisabled, tabIndexBehavior, activeDescendantId } =\n options;\n if (tabIndexBehavior === \"virtual\") {\n return getVirtualFocusDefaultIndex({\n focusables,\n includeDisabled,\n activeDescendantId,\n });\n }\n\n const { activeElement } = document;\n return focusables.findIndex((element) => element === activeElement);\n}\n\n/**\n * Checks if a keyboard event can trigger a search through focusable elements\n * by:\n *\n * - checking if the key is a single letter that is not the space key\n * - checking that the alt, ctrl, and meta keys are not being held\n *\n * The shift key **is allowed** because holding shift means \"search from the\n * beginning\" instead of \"search from current location\".\n *\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport function isSearchableEvent(event: KeyboardEvent): boolean {\n const { key, altKey, ctrlKey, metaKey } = event;\n\n return (\n key.length === 1 &&\n // can't search with space since it is generally a click event\n key !== \" \" &&\n !altKey &&\n !ctrlKey &&\n !metaKey\n );\n}\n\n/**\n * @remarks \\@since 6.0.0\n * @internal\n */\nexport function isTypeEvent(event: KeyboardEvent): boolean {\n return (\n isSearchableEvent(event) || [\"Backspace\", \"Delete\", \" \"].includes(event.key)\n );\n}\n"],"names":["loop","isElementDisabled","element","getAttribute","isNotFocusable","includeDisabled","getVirtualFocusDefaultIndex","options","focusables","activeDescendantId","length","activeIndex","findIndex","id","Math","max","getFirstFocusableIndex","firstIndex","getLastFocusableIndex","lastIndex","getNextFocusableIndex","loopable","increment","currentFocusIndex","min","nextIndex","value","minmax","getSearchText","searchable","cloned","cloneNode","querySelectorAll","forEach","parentNode","removeChild","textContent","toUpperCase","recalculateFocusIndex","tabIndexBehavior","activeElement","document","isSearchableEvent","event","key","altKey","ctrlKey","metaKey","isTypeEvent","includes"],"mappings":"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"}
|
|
@@ -199,14 +199,6 @@ const noop = ()=>undefined;
|
|
|
199
199
|
ref,
|
|
200
200
|
updateStyle
|
|
201
201
|
]);
|
|
202
|
-
useEffect(()=>{
|
|
203
|
-
if (!ref.current || !ref.current.hidden) {
|
|
204
|
-
updateStyle();
|
|
205
|
-
}
|
|
206
|
-
}, [
|
|
207
|
-
ref,
|
|
208
|
-
updateStyle
|
|
209
|
-
]);
|
|
210
202
|
const callbacks = {
|
|
211
203
|
onEnter (appearing) {
|
|
212
204
|
onEnter(appearing);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/positioning/useFixedPositioning.ts"],"sourcesContent":["\"use client\";\nimport type { CSSProperties, Ref, RefCallback, RefObject } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { delegateEvent } from \"../delegateEvent.js\";\nimport type { TransitionCallbacks } from \"../transition/types.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { useIsomorphicLayoutEffect } from \"../useIsomorphicLayoutEffect.js\";\nimport { BELOW_CENTER_ANCHOR } from \"./constants.js\";\nimport { getFixedPosition } from \"./getFixedPosition.js\";\nimport type { CalculateFixedPositionOptions } from \"./types.js\";\nimport { isWithinViewport } from \"./utils.js\";\n\nconst noop = (): undefined => undefined;\n\n/**\n * @remarks \\@since 4.0.0\n */\nexport type FixedPositioningTransitionCallbacks = Pick<\n TransitionCallbacks,\n \"onEnter\" | \"onEntering\" | \"onEntered\" | \"onExited\"\n>;\n\n/**\n * This options should be passed to the {@link useCSSTransition} for the styling\n * and positioning to work correctly.\n *\n * @typeParam E - An HTMLElement type used for the ref required for the\n * transition.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningTransitionOptions<E extends HTMLElement>\n extends FixedPositioningTransitionCallbacks {\n /** {@inheritDoc TransitionOptions.nodeRef} */\n nodeRef?: Ref<E>;\n}\n\n/**\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningScrollData<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n> {\n fixedElement: FixedElement;\n fixedToElement: FixedToElement;\n\n /**\n * Boolean if the {@link fixedToElement} is visible within the viewport.\n */\n visible: boolean;\n}\n\n/**\n * This function is called when the page is scrolled while the fixed element is\n * visible. This is generally used to reposition the fixed element or hide it if\n * it is no longer visible within the viewport.\n *\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @param event - The scroll event\n * @param data - The {@link FixedPositioningScrollData} that can be used for\n * custom scroll behavior.\n * @remarks \\@since 4.0.0\n */\nexport type TransitionScrollCallback<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n> = (\n event: Event,\n data: Readonly<FixedPositioningScrollData<FixedToElement, FixedElement>>\n) => void;\n\n/**\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningOptions<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n> extends FixedPositioningTransitionOptions<FixedElement>,\n CalculateFixedPositionOptions {\n /**\n * An optional style that will be merged with the fixed positioning required\n * styles.\n *\n * @see {@link FixedPositionStyle}\n */\n style?: CSSProperties;\n\n /**\n * A ref pointing to an element that another element should be fixed to. This\n * **must** be provided for the positioning to work.\n */\n fixedTo: RefObject<FixedToElement>;\n\n /**\n * An optional function that can be used to override positioning options if\n * some options require the element to be in the DOM for specific\n * calculations.\n */\n getFixedPositionOptions?(): CalculateFixedPositionOptions;\n\n /**\n * An optional function to call if the page resizes while the `FixedElement`\n * is visible.\n */\n onResize?: EventListener;\n /** @see {@link TransitionScrollCallback} */\n onScroll?: TransitionScrollCallback<FixedToElement, FixedElement>;\n}\n\n/**\n * @typeParam E - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningHookReturnValue<E extends HTMLElement> {\n /**\n * A ref that should be passed to a component for the fixed positioning\n * behavior to work correctly.\n *\n * This should really only be used if the {@link TransitionOptions} is not\n * being used.\n */\n ref: RefCallback<E>;\n\n /**\n * @see {@link FixedPositionStyle}\n */\n style: CSSProperties;\n\n /**\n * This should really only be used if the {@link transitionOptions} is not\n * being used.\n */\n callbacks: Readonly<Required<FixedPositioningTransitionCallbacks>>;\n\n /**\n * A function that can be called to update the style for the fixed element.\n */\n updateStyle(): void;\n\n /** {@inheritDoc FixedPositioningTransitionOptions} */\n transitionOptions: Readonly<Required<FixedPositioningTransitionOptions<E>>>;\n}\n\n/**\n * This hook is used to attach a temporary (fixed) element to another element\n * within the page. In other words, this is a way to have an element with\n * `position: fixed` as if it were `position: absolute` to a parent element that\n * had `position: relative`.\n *\n * @example\n * Simple Example\n * ```tsx\n * import { ReactElement, useRef, useState } from \"react\";\n * import { Button, useCSSTransition, useFixedPositioning } from \"@react-md/core\";\n *\n * function Example(): ReactElement {\n * const fixedTo = useRef<HTMLButtonElement>(null);\n * const [transitionIn, setTransitionIn] = useState(false);\n * const { style, transitionOptions } = useFixedPositioning({\n * fixedTo,\n * });\n * const { elementProps, rendered } = useCSSTransition({\n * ...transitionOptions,\n * transitionIn,\n * temporary: true,\n * timeout: {\n * enter: 200,\n * exit: 150,\n * },\n * classNames: {\n * enter: \"enter\",\n * enterActive: \"enter--active\",\n * exit: \"exit\",\n * exitActive: \"exit--active\",\n * },\n * });\n *\n * return (\n * <>\n * <Button\n * ref={fixedTo}\n * onClick={() => setTransitionIn(!transitionIn)}\n * >\n * Toggle\n * </Button>\n * {rendered && (\n * <div {...elementProps} style={style}>\n * Fixed Temporary Element\n * </div>\n * )}\n * </>\n * );\n * }\n * ```\n *\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport function useFixedPositioning<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n>(\n options: FixedPositioningOptions<FixedToElement, FixedElement>\n): FixedPositioningHookReturnValue<FixedElement> {\n const {\n style: propStyle,\n nodeRef,\n fixedTo,\n onEnter = noop,\n onEntering = noop,\n onEntered = noop,\n onExited = noop,\n anchor = BELOW_CENTER_ANCHOR,\n disableSwapping,\n disableVHBounds,\n initialX,\n initialY,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions = noop,\n onScroll,\n onResize = noop,\n } = options;\n\n const [active, setActive] = useState(false);\n const [ref, refHandler] = useEnsuredRef(nodeRef);\n const optionsRef = useRef({\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n } as const);\n useIsomorphicLayoutEffect(() => {\n optionsRef.current = {\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n };\n }, [\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n ]);\n const [style, setStyle] = useState<CSSProperties | undefined>(\n () =>\n getFixedPosition({\n container: ref.current,\n element: fixedTo.current,\n anchor,\n disableSwapping,\n disableVHBounds,\n initialX,\n initialY,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n ...getFixedPositionOptions(),\n }).style\n );\n\n const updateStyle = useCallback(() => {\n const {\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n } = optionsRef.current;\n const element = ref.current;\n const container = fixedTo.current;\n const { style } = getFixedPosition({\n container,\n element,\n anchor,\n disableSwapping,\n disableVHBounds,\n initialX,\n initialY,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n ...getFixedPositionOptions(),\n });\n\n setStyle(style);\n setActive(!!element && !element.hidden);\n\n // Only changing the initialX and initialY should cause the useEffect below\n // to trigger, which is why everything else is set in a ref.\n }, [initialX, initialY]);\n\n useEffect(() => {\n if (!active) {\n return;\n }\n\n const resizeCallback = (event: Event): void => {\n onResize(event);\n updateStyle();\n };\n const scrollCallback = (event: Event): void => {\n const fixedElement = ref.current;\n const fixedToElement = fixedTo.current;\n if (onScroll && fixedElement && fixedToElement) {\n onScroll(event, {\n visible: isWithinViewport({ fixedElement, fixedToElement }),\n fixedElement,\n fixedToElement,\n });\n }\n\n updateStyle();\n };\n\n const resizeHandler = delegateEvent(\"resize\", window, true);\n const scrollHandler = delegateEvent(\"scroll\", window, true, {\n passive: true,\n });\n resizeHandler.add(resizeCallback);\n scrollHandler.add(scrollCallback);\n return () => {\n resizeHandler.remove(resizeCallback);\n scrollHandler.remove(scrollCallback);\n };\n }, [active, fixedTo, onResize, onScroll, ref, updateStyle]);\n\n useEffect(() => {\n if (!ref.current || !ref.current.hidden) {\n updateStyle();\n }\n }, [ref, updateStyle]);\n\n const callbacks: Required<FixedPositioningTransitionCallbacks> = {\n onEnter(appearing) {\n onEnter(appearing);\n updateStyle();\n },\n onEntering(appearing) {\n onEntering(appearing);\n updateStyle();\n },\n onEntered(appearing) {\n onEntered(appearing);\n updateStyle();\n },\n onExited() {\n onExited();\n setActive(false);\n },\n };\n\n return {\n ref: refHandler,\n style: { ...style, ...propStyle },\n callbacks,\n updateStyle,\n transitionOptions: {\n ...callbacks,\n nodeRef: refHandler,\n },\n };\n}\n"],"names":["useCallback","useEffect","useRef","useState","delegateEvent","useEnsuredRef","useIsomorphicLayoutEffect","BELOW_CENTER_ANCHOR","getFixedPosition","isWithinViewport","noop","undefined","useFixedPositioning","options","style","propStyle","nodeRef","fixedTo","onEnter","onEntering","onEntered","onExited","anchor","disableSwapping","disableVHBounds","initialX","initialY","preventOverlap","transformOrigin","vhMargin","vwMargin","width","xMargin","yMargin","getFixedPositionOptions","onScroll","onResize","active","setActive","ref","refHandler","optionsRef","current","setStyle","container","element","updateStyle","hidden","resizeCallback","event","scrollCallback","fixedElement","fixedToElement","visible","resizeHandler","window","scrollHandler","passive","add","remove","callbacks","appearing","transitionOptions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/positioning/useFixedPositioning.ts"],"sourcesContent":["\"use client\";\nimport type { CSSProperties, Ref, RefCallback, RefObject } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { delegateEvent } from \"../delegateEvent.js\";\nimport type { TransitionCallbacks } from \"../transition/types.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { useIsomorphicLayoutEffect } from \"../useIsomorphicLayoutEffect.js\";\nimport { BELOW_CENTER_ANCHOR } from \"./constants.js\";\nimport { getFixedPosition } from \"./getFixedPosition.js\";\nimport type { CalculateFixedPositionOptions } from \"./types.js\";\nimport { isWithinViewport } from \"./utils.js\";\n\nconst noop = (): undefined => undefined;\n\n/**\n * @remarks \\@since 4.0.0\n */\nexport type FixedPositioningTransitionCallbacks = Pick<\n TransitionCallbacks,\n \"onEnter\" | \"onEntering\" | \"onEntered\" | \"onExited\"\n>;\n\n/**\n * This options should be passed to the {@link useCSSTransition} for the styling\n * and positioning to work correctly.\n *\n * @typeParam E - An HTMLElement type used for the ref required for the\n * transition.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningTransitionOptions<E extends HTMLElement>\n extends FixedPositioningTransitionCallbacks {\n /** {@inheritDoc TransitionOptions.nodeRef} */\n nodeRef?: Ref<E>;\n}\n\n/**\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningScrollData<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n> {\n fixedElement: FixedElement;\n fixedToElement: FixedToElement;\n\n /**\n * Boolean if the {@link fixedToElement} is visible within the viewport.\n */\n visible: boolean;\n}\n\n/**\n * This function is called when the page is scrolled while the fixed element is\n * visible. This is generally used to reposition the fixed element or hide it if\n * it is no longer visible within the viewport.\n *\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @param event - The scroll event\n * @param data - The {@link FixedPositioningScrollData} that can be used for\n * custom scroll behavior.\n * @remarks \\@since 4.0.0\n */\nexport type TransitionScrollCallback<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n> = (\n event: Event,\n data: Readonly<FixedPositioningScrollData<FixedToElement, FixedElement>>\n) => void;\n\n/**\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningOptions<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n> extends FixedPositioningTransitionOptions<FixedElement>,\n CalculateFixedPositionOptions {\n /**\n * An optional style that will be merged with the fixed positioning required\n * styles.\n *\n * @see {@link FixedPositionStyle}\n */\n style?: CSSProperties;\n\n /**\n * A ref pointing to an element that another element should be fixed to. This\n * **must** be provided for the positioning to work.\n */\n fixedTo: RefObject<FixedToElement>;\n\n /**\n * An optional function that can be used to override positioning options if\n * some options require the element to be in the DOM for specific\n * calculations.\n */\n getFixedPositionOptions?(): CalculateFixedPositionOptions;\n\n /**\n * An optional function to call if the page resizes while the `FixedElement`\n * is visible.\n */\n onResize?: EventListener;\n /** @see {@link TransitionScrollCallback} */\n onScroll?: TransitionScrollCallback<FixedToElement, FixedElement>;\n}\n\n/**\n * @typeParam E - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport interface FixedPositioningHookReturnValue<E extends HTMLElement> {\n /**\n * A ref that should be passed to a component for the fixed positioning\n * behavior to work correctly.\n *\n * This should really only be used if the {@link TransitionOptions} is not\n * being used.\n */\n ref: RefCallback<E>;\n\n /**\n * @see {@link FixedPositionStyle}\n */\n style: CSSProperties;\n\n /**\n * This should really only be used if the {@link transitionOptions} is not\n * being used.\n */\n callbacks: Readonly<Required<FixedPositioningTransitionCallbacks>>;\n\n /**\n * A function that can be called to update the style for the fixed element.\n */\n updateStyle(): void;\n\n /** {@inheritDoc FixedPositioningTransitionOptions} */\n transitionOptions: Readonly<Required<FixedPositioningTransitionOptions<E>>>;\n}\n\n/**\n * This hook is used to attach a temporary (fixed) element to another element\n * within the page. In other words, this is a way to have an element with\n * `position: fixed` as if it were `position: absolute` to a parent element that\n * had `position: relative`.\n *\n * @example\n * Simple Example\n * ```tsx\n * import { ReactElement, useRef, useState } from \"react\";\n * import { Button, useCSSTransition, useFixedPositioning } from \"@react-md/core\";\n *\n * function Example(): ReactElement {\n * const fixedTo = useRef<HTMLButtonElement>(null);\n * const [transitionIn, setTransitionIn] = useState(false);\n * const { style, transitionOptions } = useFixedPositioning({\n * fixedTo,\n * });\n * const { elementProps, rendered } = useCSSTransition({\n * ...transitionOptions,\n * transitionIn,\n * temporary: true,\n * timeout: {\n * enter: 200,\n * exit: 150,\n * },\n * classNames: {\n * enter: \"enter\",\n * enterActive: \"enter--active\",\n * exit: \"exit\",\n * exitActive: \"exit--active\",\n * },\n * });\n *\n * return (\n * <>\n * <Button\n * ref={fixedTo}\n * onClick={() => setTransitionIn(!transitionIn)}\n * >\n * Toggle\n * </Button>\n * {rendered && (\n * <div {...elementProps} style={style}>\n * Fixed Temporary Element\n * </div>\n * )}\n * </>\n * );\n * }\n * ```\n *\n * @typeParam FixedToElement - An HTMLElement type for the static element.\n * @typeParam FixedElement - An HTMLElement type for the fixed element.\n * @remarks \\@since 4.0.0\n */\nexport function useFixedPositioning<\n FixedToElement extends HTMLElement,\n FixedElement extends HTMLElement,\n>(\n options: FixedPositioningOptions<FixedToElement, FixedElement>\n): FixedPositioningHookReturnValue<FixedElement> {\n const {\n style: propStyle,\n nodeRef,\n fixedTo,\n onEnter = noop,\n onEntering = noop,\n onEntered = noop,\n onExited = noop,\n anchor = BELOW_CENTER_ANCHOR,\n disableSwapping,\n disableVHBounds,\n initialX,\n initialY,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions = noop,\n onScroll,\n onResize = noop,\n } = options;\n\n const [active, setActive] = useState(false);\n const [ref, refHandler] = useEnsuredRef(nodeRef);\n const optionsRef = useRef({\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n } as const);\n useIsomorphicLayoutEffect(() => {\n optionsRef.current = {\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n };\n }, [\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n ]);\n const [style, setStyle] = useState<CSSProperties | undefined>(\n () =>\n getFixedPosition({\n container: ref.current,\n element: fixedTo.current,\n anchor,\n disableSwapping,\n disableVHBounds,\n initialX,\n initialY,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n ...getFixedPositionOptions(),\n }).style\n );\n\n const updateStyle = useCallback(() => {\n const {\n ref,\n fixedTo,\n anchor,\n disableSwapping,\n disableVHBounds,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n getFixedPositionOptions,\n } = optionsRef.current;\n const element = ref.current;\n const container = fixedTo.current;\n const { style } = getFixedPosition({\n container,\n element,\n anchor,\n disableSwapping,\n disableVHBounds,\n initialX,\n initialY,\n preventOverlap,\n transformOrigin,\n vhMargin,\n vwMargin,\n width,\n xMargin,\n yMargin,\n ...getFixedPositionOptions(),\n });\n\n setStyle(style);\n setActive(!!element && !element.hidden);\n\n // Only changing the initialX and initialY should cause the useEffect below\n // to trigger, which is why everything else is set in a ref.\n }, [initialX, initialY]);\n\n useEffect(() => {\n if (!active) {\n return;\n }\n\n const resizeCallback = (event: Event): void => {\n onResize(event);\n updateStyle();\n };\n const scrollCallback = (event: Event): void => {\n const fixedElement = ref.current;\n const fixedToElement = fixedTo.current;\n if (onScroll && fixedElement && fixedToElement) {\n onScroll(event, {\n visible: isWithinViewport({ fixedElement, fixedToElement }),\n fixedElement,\n fixedToElement,\n });\n }\n\n updateStyle();\n };\n\n const resizeHandler = delegateEvent(\"resize\", window, true);\n const scrollHandler = delegateEvent(\"scroll\", window, true, {\n passive: true,\n });\n resizeHandler.add(resizeCallback);\n scrollHandler.add(scrollCallback);\n return () => {\n resizeHandler.remove(resizeCallback);\n scrollHandler.remove(scrollCallback);\n };\n }, [active, fixedTo, onResize, onScroll, ref, updateStyle]);\n\n const callbacks: Required<FixedPositioningTransitionCallbacks> = {\n onEnter(appearing) {\n onEnter(appearing);\n updateStyle();\n },\n onEntering(appearing) {\n onEntering(appearing);\n updateStyle();\n },\n onEntered(appearing) {\n onEntered(appearing);\n updateStyle();\n },\n onExited() {\n onExited();\n setActive(false);\n },\n };\n\n return {\n ref: refHandler,\n style: { ...style, ...propStyle },\n callbacks,\n updateStyle,\n transitionOptions: {\n ...callbacks,\n nodeRef: refHandler,\n },\n };\n}\n"],"names":["useCallback","useEffect","useRef","useState","delegateEvent","useEnsuredRef","useIsomorphicLayoutEffect","BELOW_CENTER_ANCHOR","getFixedPosition","isWithinViewport","noop","undefined","useFixedPositioning","options","style","propStyle","nodeRef","fixedTo","onEnter","onEntering","onEntered","onExited","anchor","disableSwapping","disableVHBounds","initialX","initialY","preventOverlap","transformOrigin","vhMargin","vwMargin","width","xMargin","yMargin","getFixedPositionOptions","onScroll","onResize","active","setActive","ref","refHandler","optionsRef","current","setStyle","container","element","updateStyle","hidden","resizeCallback","event","scrollCallback","fixedElement","fixedToElement","visible","resizeHandler","window","scrollHandler","passive","add","remove","callbacks","appearing","transitionOptions"],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { type TextExtractor } from "../types.js";
|
|
2
|
+
import { type BaseSearchOptions } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* @remarks \@since 6.0.0
|
|
5
|
+
*/
|
|
6
|
+
export interface CaseInsensitiveStartsWithOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Set this to `true` if the item in the list must start with the query
|
|
9
|
+
* instead of only including it.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* Search Example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const fruits = ["Banana", "Grape", "Apple", "Orange"];
|
|
15
|
+
*
|
|
16
|
+
* caseInsensitiveSearch({
|
|
17
|
+
* list: fruits,
|
|
18
|
+
* query: "ap",
|
|
19
|
+
* type: "search",
|
|
20
|
+
* });
|
|
21
|
+
* // "Grape"
|
|
22
|
+
*
|
|
23
|
+
* caseInsensitiveSearch({
|
|
24
|
+
* list: fruits,
|
|
25
|
+
* query: "ap",
|
|
26
|
+
* type: "search",
|
|
27
|
+
* startsWith: true,
|
|
28
|
+
* });
|
|
29
|
+
* // "Apple"
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* Filter Example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const fruits = ["Apple", "Banana", "Grape", "Orange"];
|
|
36
|
+
*
|
|
37
|
+
* caseInsensitiveSearch({
|
|
38
|
+
* list: fruits,
|
|
39
|
+
* query: "ap",
|
|
40
|
+
* });
|
|
41
|
+
* // ["Apple", "Grape"]
|
|
42
|
+
*
|
|
43
|
+
* caseInsensitiveSearch({
|
|
44
|
+
* list: fruits,
|
|
45
|
+
* query: "ap",
|
|
46
|
+
* startsWith: true,
|
|
47
|
+
* });
|
|
48
|
+
* // ["Apple"]
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @defaultValue `false`
|
|
52
|
+
*/
|
|
53
|
+
startsWith?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @remarks \@since 6.0.0
|
|
57
|
+
*/
|
|
58
|
+
export interface IsCaseInsensitiveMatchOptions extends CaseInsensitiveStartsWithOptions {
|
|
59
|
+
/**
|
|
60
|
+
* The current search query.
|
|
61
|
+
*/
|
|
62
|
+
query: string;
|
|
63
|
+
/**
|
|
64
|
+
* The current value to compare against.
|
|
65
|
+
*/
|
|
66
|
+
value: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @remarks \@since 6.0.0
|
|
70
|
+
*/
|
|
71
|
+
export declare function isCaseInsensitiveMatch(options: IsCaseInsensitiveMatchOptions): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* @remarks \@since 6.0.0
|
|
74
|
+
*/
|
|
75
|
+
export interface CaseInsensitiveOptions<T> extends BaseSearchOptions<T>, CaseInsensitiveStartsWithOptions {
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @example
|
|
79
|
+
* String list
|
|
80
|
+
* ```ts
|
|
81
|
+
* const fruits = ["Apple", "Banana", "Grape", "Orange"];
|
|
82
|
+
*
|
|
83
|
+
* caseInsensitiveSearch({
|
|
84
|
+
* list: fruits,
|
|
85
|
+
* query: "ap",
|
|
86
|
+
* });
|
|
87
|
+
* // ["Apple", "Grape"]
|
|
88
|
+
*
|
|
89
|
+
* caseInsensitiveSearch({
|
|
90
|
+
* list: fruits,
|
|
91
|
+
* query: "ap",
|
|
92
|
+
* startsWith: true,
|
|
93
|
+
* });
|
|
94
|
+
* // ["Apple"]
|
|
95
|
+
*
|
|
96
|
+
* caseInsensitiveSearch({
|
|
97
|
+
* list: fruits,
|
|
98
|
+
* query: " a p",
|
|
99
|
+
* });
|
|
100
|
+
* // []
|
|
101
|
+
*
|
|
102
|
+
* caseInsensitiveSearch({
|
|
103
|
+
* list: fruits,
|
|
104
|
+
* query: " a p",
|
|
105
|
+
* whitespace: "ignore",
|
|
106
|
+
* });
|
|
107
|
+
* // ["Apple", "Grape"]
|
|
108
|
+
*
|
|
109
|
+
* caseInsensitiveSearch({
|
|
110
|
+
* list: fruits,
|
|
111
|
+
* query: " ap ",
|
|
112
|
+
* whitespace: "trim",
|
|
113
|
+
* });
|
|
114
|
+
* // ["Apple", "Grape"]
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* Objects
|
|
119
|
+
* ```ts
|
|
120
|
+
* const fruits = [
|
|
121
|
+
* { name: "Apple", value: 0 },
|
|
122
|
+
* { name: "Banana", value: 1 },
|
|
123
|
+
* { name: "Grape", value: 2 },
|
|
124
|
+
* { name: "Orange", value: 3 },
|
|
125
|
+
* ];
|
|
126
|
+
*
|
|
127
|
+
* caseInsensitiveSearch({
|
|
128
|
+
* list: fruits,
|
|
129
|
+
* query: "ap",
|
|
130
|
+
* extractor: (item) => item.name,
|
|
131
|
+
* });
|
|
132
|
+
* // [{ name: "Apple", value: 0 }, { name: "Grape", value: 2 }]
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @remarks \@since 6.0.0
|
|
136
|
+
*/
|
|
137
|
+
export declare function caseInsensitiveSearch<T extends string>(options: Omit<CaseInsensitiveOptions<T>, "extractor"> & {
|
|
138
|
+
type?: "filter";
|
|
139
|
+
}): readonly T[];
|
|
140
|
+
export declare function caseInsensitiveSearch<T extends string>(options: Omit<CaseInsensitiveOptions<T>, "extractor"> & {
|
|
141
|
+
type: "search";
|
|
142
|
+
}): T | undefined;
|
|
143
|
+
export declare function caseInsensitiveSearch<T>(options: CaseInsensitiveOptions<T> & {
|
|
144
|
+
extractor: TextExtractor<T>;
|
|
145
|
+
type?: "filter";
|
|
146
|
+
}): readonly T[];
|
|
147
|
+
export declare function caseInsensitiveSearch<T>(options: CaseInsensitiveOptions<T> & {
|
|
148
|
+
extractor: TextExtractor<T>;
|
|
149
|
+
type: "search";
|
|
150
|
+
}): T | undefined;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defaultExtractor, search } from "./utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* @remarks \@since 6.0.0
|
|
4
|
+
*/ export function isCaseInsensitiveMatch(options) {
|
|
5
|
+
const { query, value, startsWith } = options;
|
|
6
|
+
const matchIndex = value.indexOf(query);
|
|
7
|
+
if (startsWith) {
|
|
8
|
+
return matchIndex === 0;
|
|
9
|
+
}
|
|
10
|
+
return matchIndex !== -1;
|
|
11
|
+
}
|
|
12
|
+
export function caseInsensitiveSearch(options) {
|
|
13
|
+
const { list, type = "filter", query, extractor = defaultExtractor("caseInsensitiveSearch"), startsWith, whitespace } = options;
|
|
14
|
+
return search({
|
|
15
|
+
type,
|
|
16
|
+
list,
|
|
17
|
+
query,
|
|
18
|
+
extractor,
|
|
19
|
+
whitespace,
|
|
20
|
+
filter (q, value) {
|
|
21
|
+
return isCaseInsensitiveMatch({
|
|
22
|
+
query: q,
|
|
23
|
+
value,
|
|
24
|
+
startsWith
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=caseInsensitive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/searching/caseInsensitive.ts"],"sourcesContent":["import { type TextExtractor } from \"../types.js\";\nimport { type BaseSearchOptions } from \"./types.js\";\nimport { defaultExtractor, search } from \"./utils.js\";\n\n/**\n * @remarks \\@since 6.0.0\n */\nexport interface CaseInsensitiveStartsWithOptions {\n /**\n * Set this to `true` if the item in the list must start with the query\n * instead of only including it.\n *\n * @example\n * Search Example\n * ```ts\n * const fruits = [\"Banana\", \"Grape\", \"Apple\", \"Orange\"];\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \"ap\",\n * type: \"search\",\n * });\n * // \"Grape\"\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \"ap\",\n * type: \"search\",\n * startsWith: true,\n * });\n * // \"Apple\"\n * ```\n *\n * @example\n * Filter Example\n * ```ts\n * const fruits = [\"Apple\", \"Banana\", \"Grape\", \"Orange\"];\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \"ap\",\n * });\n * // [\"Apple\", \"Grape\"]\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \"ap\",\n * startsWith: true,\n * });\n * // [\"Apple\"]\n * ```\n *\n * @defaultValue `false`\n */\n startsWith?: boolean;\n}\n\n/**\n * @remarks \\@since 6.0.0\n */\nexport interface IsCaseInsensitiveMatchOptions\n extends CaseInsensitiveStartsWithOptions {\n /**\n * The current search query.\n */\n query: string;\n\n /**\n * The current value to compare against.\n */\n value: string;\n}\n\n/**\n * @remarks \\@since 6.0.0\n */\nexport function isCaseInsensitiveMatch(\n options: IsCaseInsensitiveMatchOptions\n): boolean {\n const { query, value, startsWith } = options;\n const matchIndex = value.indexOf(query);\n if (startsWith) {\n return matchIndex === 0;\n }\n\n return matchIndex !== -1;\n}\n\n/**\n * @remarks \\@since 6.0.0\n */\nexport interface CaseInsensitiveOptions<T>\n extends BaseSearchOptions<T>,\n CaseInsensitiveStartsWithOptions {}\n\n/**\n * @example\n * String list\n * ```ts\n * const fruits = [\"Apple\", \"Banana\", \"Grape\", \"Orange\"];\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \"ap\",\n * });\n * // [\"Apple\", \"Grape\"]\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \"ap\",\n * startsWith: true,\n * });\n * // [\"Apple\"]\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \" a p\",\n * });\n * // []\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \" a p\",\n * whitespace: \"ignore\",\n * });\n * // [\"Apple\", \"Grape\"]\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \" ap \",\n * whitespace: \"trim\",\n * });\n * // [\"Apple\", \"Grape\"]\n * ```\n *\n * @example\n * Objects\n * ```ts\n * const fruits = [\n * { name: \"Apple\", value: 0 },\n * { name: \"Banana\", value: 1 },\n * { name: \"Grape\", value: 2 },\n * { name: \"Orange\", value: 3 },\n * ];\n *\n * caseInsensitiveSearch({\n * list: fruits,\n * query: \"ap\",\n * extractor: (item) => item.name,\n * });\n * // [{ name: \"Apple\", value: 0 }, { name: \"Grape\", value: 2 }]\n * ```\n *\n * @remarks \\@since 6.0.0\n */\nexport function caseInsensitiveSearch<T extends string>(\n options: Omit<CaseInsensitiveOptions<T>, \"extractor\"> & { type?: \"filter\" }\n): readonly T[];\nexport function caseInsensitiveSearch<T extends string>(\n options: Omit<CaseInsensitiveOptions<T>, \"extractor\"> & { type: \"search\" }\n): T | undefined;\nexport function caseInsensitiveSearch<T>(\n options: CaseInsensitiveOptions<T> & {\n extractor: TextExtractor<T>;\n type?: \"filter\";\n }\n): readonly T[];\nexport function caseInsensitiveSearch<T>(\n options: CaseInsensitiveOptions<T> & {\n extractor: TextExtractor<T>;\n type: \"search\";\n }\n): T | undefined;\nexport function caseInsensitiveSearch<T>(\n options: CaseInsensitiveOptions<T>\n): readonly T[] | T | undefined {\n const {\n list,\n type = \"filter\",\n query,\n extractor = defaultExtractor(\"caseInsensitiveSearch\"),\n startsWith,\n whitespace,\n } = options;\n\n return search({\n type,\n list,\n query,\n extractor,\n whitespace,\n filter(q, value) {\n return isCaseInsensitiveMatch({\n query: q,\n value,\n startsWith,\n });\n },\n });\n}\n"],"names":["defaultExtractor","search","isCaseInsensitiveMatch","options","query","value","startsWith","matchIndex","indexOf","caseInsensitiveSearch","list","type","extractor","whitespace","filter","q"],"mappings":"AAEA,SAASA,gBAAgB,EAAEC,MAAM,QAAQ,aAAa;AAuEtD;;CAEC,GACD,OAAO,SAASC,uBACdC,OAAsC;IAEtC,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAEC,UAAU,EAAE,GAAGH;IACrC,MAAMI,aAAaF,MAAMG,OAAO,CAACJ;IACjC,IAAIE,YAAY;QACd,OAAOC,eAAe;IACxB;IAEA,OAAOA,eAAe,CAAC;AACzB;AAuFA,OAAO,SAASE,sBACdN,OAAkC;IAElC,MAAM,EACJO,IAAI,EACJC,OAAO,QAAQ,EACfP,KAAK,EACLQ,YAAYZ,iBAAiB,wBAAwB,EACrDM,UAAU,EACVO,UAAU,EACX,GAAGV;IAEJ,OAAOF,OAAO;QACZU;QACAD;QACAN;QACAQ;QACAC;QACAC,QAAOC,CAAC,EAAEV,KAAK;YACb,OAAOH,uBAAuB;gBAC5BE,OAAOW;gBACPV;gBACAC;YACF;QACF;IACF;AACF"}
|