@salt-ds/lab 1.0.0-alpha.73 → 1.0.0-alpha.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/css/salt-lab.css +332 -18
- package/dist-cjs/app-header/AppHeader.js +5 -1
- package/dist-cjs/app-header/AppHeader.js.map +1 -1
- package/dist-cjs/breadcrumbs/Breadcrumb.js.map +1 -1
- package/dist-cjs/breadcrumbs/Breadcrumbs.js +11 -2
- package/dist-cjs/breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist-cjs/breadcrumbs/internal/BreadcrumbsCollapsed.js +3 -6
- package/dist-cjs/breadcrumbs/internal/BreadcrumbsCollapsed.js.map +1 -1
- package/dist-cjs/button-bar/ButtonBar.js +1 -1
- package/dist-cjs/button-bar/ButtonBar.js.map +1 -1
- package/dist-cjs/button-bar/internal/DescendantContext.js.map +1 -1
- package/dist-cjs/calendar/useCalendarSelection.js +2 -2
- package/dist-cjs/calendar/useCalendarSelection.js.map +1 -1
- package/dist-cjs/cascading-menu/CascadingMenu.js +19 -13
- package/dist-cjs/cascading-menu/CascadingMenu.js.map +1 -1
- package/dist-cjs/cascading-menu/CascadingMenuItem.js +2 -4
- package/dist-cjs/cascading-menu/CascadingMenuItem.js.map +1 -1
- package/dist-cjs/cascading-menu/CascadingMenuList.js +1 -2
- package/dist-cjs/cascading-menu/CascadingMenuList.js.map +1 -1
- package/dist-cjs/cascading-menu/internal/useMenuTriggerHandlers.js +4 -1
- package/dist-cjs/cascading-menu/internal/useMenuTriggerHandlers.js.map +1 -1
- package/dist-cjs/cascading-menu/internal/useMouseHandlers.js +1 -1
- package/dist-cjs/cascading-menu/internal/useMouseHandlers.js.map +1 -1
- package/dist-cjs/cascading-menu/internal/useRefsManager.js +3 -1
- package/dist-cjs/cascading-menu/internal/useRefsManager.js.map +1 -1
- package/dist-cjs/collapsible/Collapsible.js +47 -0
- package/dist-cjs/collapsible/Collapsible.js.map +1 -0
- package/dist-cjs/collapsible/CollapsibleContext.js +23 -0
- package/dist-cjs/collapsible/CollapsibleContext.js.map +1 -0
- package/dist-cjs/collapsible/CollapsiblePanel.css.js +6 -0
- package/dist-cjs/collapsible/CollapsiblePanel.css.js.map +1 -0
- package/dist-cjs/collapsible/CollapsiblePanel.js +42 -0
- package/dist-cjs/collapsible/CollapsiblePanel.js.map +1 -0
- package/dist-cjs/collapsible/CollapsibleTrigger.js +35 -0
- package/dist-cjs/collapsible/CollapsibleTrigger.js.map +1 -0
- package/dist-cjs/color-chooser/AlphaInputField.js +1 -1
- package/dist-cjs/color-chooser/AlphaInputField.js.map +1 -1
- package/dist-cjs/color-chooser/ColorChooser.js.map +1 -1
- package/dist-cjs/color-chooser/DictTabs.js +1 -1
- package/dist-cjs/color-chooser/DictTabs.js.map +1 -1
- package/dist-cjs/color-chooser/RGBAInputField.js +2 -2
- package/dist-cjs/color-chooser/RGBAInputField.js.map +1 -1
- package/dist-cjs/combo-box/useCombobox.js.map +1 -1
- package/dist-cjs/combo-box-deprecated/ComboBoxDeprecated.js +1 -1
- package/dist-cjs/combo-box-deprecated/ComboBoxDeprecated.js.map +1 -1
- package/dist-cjs/combo-box-deprecated/internal/DefaultComboBox.js +1 -2
- package/dist-cjs/combo-box-deprecated/internal/DefaultComboBox.js.map +1 -1
- package/dist-cjs/combo-box-deprecated/internal/MultiSelectComboBox.js +0 -4
- package/dist-cjs/combo-box-deprecated/internal/MultiSelectComboBox.js.map +1 -1
- package/dist-cjs/combo-box-deprecated/internal/useComboBox.js +4 -1
- package/dist-cjs/combo-box-deprecated/internal/useComboBox.js.map +1 -1
- package/dist-cjs/combo-box-deprecated/internal/useMultiSelectComboBox.js +7 -2
- package/dist-cjs/combo-box-deprecated/internal/useMultiSelectComboBox.js.map +1 -1
- package/dist-cjs/common-hooks/useAutoSizer.js +0 -9
- package/dist-cjs/common-hooks/useAutoSizer.js.map +1 -1
- package/dist-cjs/common-hooks/useCollapsibleGroups.js +37 -49
- package/dist-cjs/common-hooks/useCollapsibleGroups.js.map +1 -1
- package/dist-cjs/common-hooks/useCollectionItems.js +6 -11
- package/dist-cjs/common-hooks/useCollectionItems.js.map +1 -1
- package/dist-cjs/common-hooks/useKeyboardNavigationPanel.js +7 -7
- package/dist-cjs/common-hooks/useKeyboardNavigationPanel.js.map +1 -1
- package/dist-cjs/common-hooks/useSelection.js +1 -1
- package/dist-cjs/common-hooks/useSelection.js.map +1 -1
- package/dist-cjs/common-hooks/useTypeahead.js +2 -2
- package/dist-cjs/common-hooks/useTypeahead.js.map +1 -1
- package/dist-cjs/common-hooks/useViewportTracking.js +1 -1
- package/dist-cjs/common-hooks/useViewportTracking.js.map +1 -1
- package/dist-cjs/common-hooks/utils/collection-item-utils.js +1 -1
- package/dist-cjs/common-hooks/utils/collection-item-utils.js.map +1 -1
- package/dist-cjs/contact-details/ContactAction.js +1 -0
- package/dist-cjs/contact-details/ContactAction.js.map +1 -1
- package/dist-cjs/contact-details/ContactSecondaryInfo.js +1 -1
- package/dist-cjs/contact-details/ContactSecondaryInfo.js.map +1 -1
- package/dist-cjs/contact-details/internal/ContactDetailsContext.js +2 -2
- package/dist-cjs/contact-details/internal/ContactDetailsContext.js.map +1 -1
- package/dist-cjs/contact-details/internal/FavoriteToggleWithTooltip.js +10 -1
- package/dist-cjs/contact-details/internal/FavoriteToggleWithTooltip.js.map +1 -1
- package/dist-cjs/content-status/ContentStatus.js.map +1 -1
- package/dist-cjs/content-status/internal/StatusIndicator.js.map +1 -1
- package/dist-cjs/date-input/DateInput.css.js +1 -1
- package/dist-cjs/date-picker/useFocusOut.js +1 -1
- package/dist-cjs/date-picker/useFocusOut.js.map +1 -1
- package/dist-cjs/dropdown/DropdownButton.js.map +1 -1
- package/dist-cjs/dropdown/useDropdown.js.map +1 -1
- package/dist-cjs/index.js +36 -0
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/input-legacy/InputLegacy.css.js +1 -1
- package/dist-cjs/list/List.js +1 -1
- package/dist-cjs/list/List.js.map +1 -1
- package/dist-cjs/list/ListItem.css.js +1 -1
- package/dist-cjs/list/ListItem.js +2 -1
- package/dist-cjs/list/ListItem.js.map +1 -1
- package/dist-cjs/list/keyset.js.map +1 -1
- package/dist-cjs/list/useList.js +1 -3
- package/dist-cjs/list/useList.js.map +1 -1
- package/dist-cjs/list/useListHeight.js +3 -3
- package/dist-cjs/list/useListHeight.js.map +1 -1
- package/dist-cjs/list-deprecated/List.js +4 -1
- package/dist-cjs/list-deprecated/List.js.map +1 -1
- package/dist-cjs/list-deprecated/ListBase.js +18 -17
- package/dist-cjs/list-deprecated/ListBase.js.map +1 -1
- package/dist-cjs/list-deprecated/ListItem.js.map +1 -1
- package/dist-cjs/list-deprecated/ListItemBase.js +1 -0
- package/dist-cjs/list-deprecated/ListItemBase.js.map +1 -1
- package/dist-cjs/list-deprecated/internal/helpers.js.map +1 -1
- package/dist-cjs/list-deprecated/internal/scrollIntoView.js +2 -2
- package/dist-cjs/list-deprecated/internal/scrollIntoView.js.map +1 -1
- package/dist-cjs/list-deprecated/internal/useListAutoSizer.js.map +1 -1
- package/dist-cjs/list-deprecated/itemToString.js.map +1 -1
- package/dist-cjs/list-deprecated/useList.js +3 -10
- package/dist-cjs/list-deprecated/useList.js.map +1 -1
- package/dist-cjs/list-deprecated/useListItem.js.map +1 -1
- package/dist-cjs/list-next/ListNext.js.map +1 -1
- package/dist-cjs/metric/MetricContent.js +1 -0
- package/dist-cjs/metric/MetricContent.js.map +1 -1
- package/dist-cjs/number-input/NumberInput.css.js +1 -1
- package/dist-cjs/number-input/internal/utils.js +1 -1
- package/dist-cjs/number-input/internal/utils.js.map +1 -1
- package/dist-cjs/query-input/QueryInput.js +10 -10
- package/dist-cjs/query-input/QueryInput.js.map +1 -1
- package/dist-cjs/query-input/internal/QueryInputBody.js +1 -1
- package/dist-cjs/query-input/internal/QueryInputBody.js.map +1 -1
- package/dist-cjs/query-input/internal/SearchList.js +1 -1
- package/dist-cjs/query-input/internal/SearchList.js.map +1 -1
- package/dist-cjs/query-input/internal/usePopperStatus.js +2 -2
- package/dist-cjs/query-input/internal/usePopperStatus.js.map +1 -1
- package/dist-cjs/query-input/useQueryInput.js +6 -6
- package/dist-cjs/query-input/useQueryInput.js.map +1 -1
- package/dist-cjs/responsive/OverflowReducer.js +0 -2
- package/dist-cjs/responsive/OverflowReducer.js.map +1 -1
- package/dist-cjs/responsive/overflowUtils.js +6 -3
- package/dist-cjs/responsive/overflowUtils.js.map +1 -1
- package/dist-cjs/responsive/useDynamicCollapse.js +6 -3
- package/dist-cjs/responsive/useDynamicCollapse.js.map +1 -1
- package/dist-cjs/responsive/useOverflow.js +2 -2
- package/dist-cjs/responsive/useOverflow.js.map +1 -1
- package/dist-cjs/responsive/useOverflowCollectionItems.js +1 -1
- package/dist-cjs/responsive/useOverflowCollectionItems.js.map +1 -1
- package/dist-cjs/responsive/useOverflowLayout.js +1 -1
- package/dist-cjs/responsive/useOverflowLayout.js.map +1 -1
- package/dist-cjs/responsive/useReclaimSpace.js +1 -1
- package/dist-cjs/responsive/useReclaimSpace.js.map +1 -1
- package/dist-cjs/responsive/useResizeObserver.js +7 -2
- package/dist-cjs/responsive/useResizeObserver.js.map +1 -1
- package/dist-cjs/search-input/SearchInput.js.map +1 -1
- package/dist-cjs/table/TBody.js +32 -0
- package/dist-cjs/table/TBody.js.map +1 -0
- package/dist-cjs/table/TD.js +30 -0
- package/dist-cjs/table/TD.js.map +1 -0
- package/dist-cjs/table/TFoot.js +45 -0
- package/dist-cjs/table/TFoot.js.map +1 -0
- package/dist-cjs/table/TH.js +30 -0
- package/dist-cjs/table/TH.js.map +1 -0
- package/dist-cjs/table/THead.js +45 -0
- package/dist-cjs/table/THead.js.map +1 -0
- package/dist-cjs/table/TR.js +30 -0
- package/dist-cjs/table/TR.js.map +1 -0
- package/dist-cjs/table/Table.css.js +6 -0
- package/dist-cjs/table/Table.css.js.map +1 -0
- package/dist-cjs/table/Table.js +47 -0
- package/dist-cjs/table/Table.js.map +1 -0
- package/dist-cjs/tabs/TabActivationIndicator.css.js +1 -1
- package/dist-cjs/tabs/Tabs.js +0 -8
- package/dist-cjs/tabs/Tabs.js.map +1 -1
- package/dist-cjs/tabs/drag-drop/useDragSpacers.js +6 -7
- package/dist-cjs/tabs/drag-drop/useDragSpacers.js.map +1 -1
- package/dist-cjs/tabs/useActivationIndicator.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextTrigger.js +2 -1
- package/dist-cjs/tabs-next/TabNextTrigger.js.map +1 -1
- package/dist-cjs/tabs-next/hooks/useOverflow.js +3 -5
- package/dist-cjs/tabs-next/hooks/useOverflow.js.map +1 -1
- package/dist-cjs/tokenized-input/useTokenizedInput.js +5 -5
- package/dist-cjs/tokenized-input/useTokenizedInput.js.map +1 -1
- package/dist-cjs/tokenized-input-next/TokenizedInputNext.css.js +1 -1
- package/dist-cjs/tree/Tree.js.map +1 -1
- package/dist-cjs/vertical-navigation/SubMenuContext.js +34 -0
- package/dist-cjs/vertical-navigation/SubMenuContext.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigation.css.js +6 -0
- package/dist-cjs/vertical-navigation/VerticalNavigation.css.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigation.js +34 -0
- package/dist-cjs/vertical-navigation/VerticalNavigation.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItem.js +48 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItem.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemContent.css.js +6 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemContent.css.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemContent.js +83 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemContent.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemExpansionIcon.js +29 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemExpansionIcon.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemLabel.css.js +6 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemLabel.css.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemLabel.js +24 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemLabel.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemTrigger.css.js +6 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemTrigger.css.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemTrigger.js +69 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationItemTrigger.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationSubMenu.css.js +6 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationSubMenu.css.js.map +1 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationSubMenu.js +35 -0
- package/dist-cjs/vertical-navigation/VerticalNavigationSubMenu.js.map +1 -0
- package/dist-es/app-header/AppHeader.js +5 -1
- package/dist-es/app-header/AppHeader.js.map +1 -1
- package/dist-es/breadcrumbs/Breadcrumb.js.map +1 -1
- package/dist-es/breadcrumbs/Breadcrumbs.js +11 -2
- package/dist-es/breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist-es/breadcrumbs/internal/BreadcrumbsCollapsed.js +3 -6
- package/dist-es/breadcrumbs/internal/BreadcrumbsCollapsed.js.map +1 -1
- package/dist-es/button-bar/ButtonBar.js +1 -1
- package/dist-es/button-bar/ButtonBar.js.map +1 -1
- package/dist-es/button-bar/internal/DescendantContext.js.map +1 -1
- package/dist-es/calendar/useCalendarSelection.js +2 -2
- package/dist-es/calendar/useCalendarSelection.js.map +1 -1
- package/dist-es/cascading-menu/CascadingMenu.js +19 -13
- package/dist-es/cascading-menu/CascadingMenu.js.map +1 -1
- package/dist-es/cascading-menu/CascadingMenuItem.js +2 -4
- package/dist-es/cascading-menu/CascadingMenuItem.js.map +1 -1
- package/dist-es/cascading-menu/CascadingMenuList.js +1 -2
- package/dist-es/cascading-menu/CascadingMenuList.js.map +1 -1
- package/dist-es/cascading-menu/internal/useMenuTriggerHandlers.js +4 -1
- package/dist-es/cascading-menu/internal/useMenuTriggerHandlers.js.map +1 -1
- package/dist-es/cascading-menu/internal/useMouseHandlers.js +1 -1
- package/dist-es/cascading-menu/internal/useMouseHandlers.js.map +1 -1
- package/dist-es/cascading-menu/internal/useRefsManager.js +3 -1
- package/dist-es/cascading-menu/internal/useRefsManager.js.map +1 -1
- package/dist-es/collapsible/Collapsible.js +45 -0
- package/dist-es/collapsible/Collapsible.js.map +1 -0
- package/dist-es/collapsible/CollapsibleContext.js +20 -0
- package/dist-es/collapsible/CollapsibleContext.js.map +1 -0
- package/dist-es/collapsible/CollapsiblePanel.css.js +4 -0
- package/dist-es/collapsible/CollapsiblePanel.css.js.map +1 -0
- package/dist-es/collapsible/CollapsiblePanel.js +40 -0
- package/dist-es/collapsible/CollapsiblePanel.js.map +1 -0
- package/dist-es/collapsible/CollapsibleTrigger.js +33 -0
- package/dist-es/collapsible/CollapsibleTrigger.js.map +1 -0
- package/dist-es/color-chooser/AlphaInputField.js +1 -1
- package/dist-es/color-chooser/AlphaInputField.js.map +1 -1
- package/dist-es/color-chooser/ColorChooser.js.map +1 -1
- package/dist-es/color-chooser/DictTabs.js +1 -1
- package/dist-es/color-chooser/DictTabs.js.map +1 -1
- package/dist-es/color-chooser/RGBAInputField.js +2 -2
- package/dist-es/color-chooser/RGBAInputField.js.map +1 -1
- package/dist-es/combo-box/useCombobox.js.map +1 -1
- package/dist-es/combo-box-deprecated/ComboBoxDeprecated.js +1 -1
- package/dist-es/combo-box-deprecated/ComboBoxDeprecated.js.map +1 -1
- package/dist-es/combo-box-deprecated/internal/DefaultComboBox.js +1 -2
- package/dist-es/combo-box-deprecated/internal/DefaultComboBox.js.map +1 -1
- package/dist-es/combo-box-deprecated/internal/MultiSelectComboBox.js +1 -5
- package/dist-es/combo-box-deprecated/internal/MultiSelectComboBox.js.map +1 -1
- package/dist-es/combo-box-deprecated/internal/useComboBox.js +4 -1
- package/dist-es/combo-box-deprecated/internal/useComboBox.js.map +1 -1
- package/dist-es/combo-box-deprecated/internal/useMultiSelectComboBox.js +7 -2
- package/dist-es/combo-box-deprecated/internal/useMultiSelectComboBox.js.map +1 -1
- package/dist-es/common-hooks/useAutoSizer.js +0 -9
- package/dist-es/common-hooks/useAutoSizer.js.map +1 -1
- package/dist-es/common-hooks/useCollapsibleGroups.js +38 -50
- package/dist-es/common-hooks/useCollapsibleGroups.js.map +1 -1
- package/dist-es/common-hooks/useCollectionItems.js +6 -11
- package/dist-es/common-hooks/useCollectionItems.js.map +1 -1
- package/dist-es/common-hooks/useKeyboardNavigationPanel.js +8 -8
- package/dist-es/common-hooks/useKeyboardNavigationPanel.js.map +1 -1
- package/dist-es/common-hooks/useSelection.js +1 -1
- package/dist-es/common-hooks/useSelection.js.map +1 -1
- package/dist-es/common-hooks/useTypeahead.js +2 -2
- package/dist-es/common-hooks/useTypeahead.js.map +1 -1
- package/dist-es/common-hooks/useViewportTracking.js +1 -1
- package/dist-es/common-hooks/useViewportTracking.js.map +1 -1
- package/dist-es/common-hooks/utils/collection-item-utils.js +1 -1
- package/dist-es/common-hooks/utils/collection-item-utils.js.map +1 -1
- package/dist-es/contact-details/ContactAction.js +1 -0
- package/dist-es/contact-details/ContactAction.js.map +1 -1
- package/dist-es/contact-details/ContactSecondaryInfo.js +1 -1
- package/dist-es/contact-details/ContactSecondaryInfo.js.map +1 -1
- package/dist-es/contact-details/internal/ContactDetailsContext.js +2 -2
- package/dist-es/contact-details/internal/ContactDetailsContext.js.map +1 -1
- package/dist-es/contact-details/internal/FavoriteToggleWithTooltip.js +10 -1
- package/dist-es/contact-details/internal/FavoriteToggleWithTooltip.js.map +1 -1
- package/dist-es/content-status/ContentStatus.js.map +1 -1
- package/dist-es/content-status/internal/StatusIndicator.js.map +1 -1
- package/dist-es/date-input/DateInput.css.js +1 -1
- package/dist-es/date-picker/useFocusOut.js +1 -1
- package/dist-es/date-picker/useFocusOut.js.map +1 -1
- package/dist-es/dropdown/DropdownButton.js.map +1 -1
- package/dist-es/dropdown/useDropdown.js.map +1 -1
- package/dist-es/index.js +17 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/input-legacy/InputLegacy.css.js +1 -1
- package/dist-es/list/List.js +2 -2
- package/dist-es/list/List.js.map +1 -1
- package/dist-es/list/ListItem.css.js +1 -1
- package/dist-es/list/ListItem.js +2 -1
- package/dist-es/list/ListItem.js.map +1 -1
- package/dist-es/list/keyset.js.map +1 -1
- package/dist-es/list/useList.js +1 -3
- package/dist-es/list/useList.js.map +1 -1
- package/dist-es/list/useListHeight.js +3 -3
- package/dist-es/list/useListHeight.js.map +1 -1
- package/dist-es/list-deprecated/List.js +4 -1
- package/dist-es/list-deprecated/List.js.map +1 -1
- package/dist-es/list-deprecated/ListBase.js +19 -18
- package/dist-es/list-deprecated/ListBase.js.map +1 -1
- package/dist-es/list-deprecated/ListItem.js.map +1 -1
- package/dist-es/list-deprecated/ListItemBase.js +1 -0
- package/dist-es/list-deprecated/ListItemBase.js.map +1 -1
- package/dist-es/list-deprecated/internal/helpers.js.map +1 -1
- package/dist-es/list-deprecated/internal/scrollIntoView.js +2 -2
- package/dist-es/list-deprecated/internal/scrollIntoView.js.map +1 -1
- package/dist-es/list-deprecated/internal/useListAutoSizer.js.map +1 -1
- package/dist-es/list-deprecated/itemToString.js.map +1 -1
- package/dist-es/list-deprecated/useList.js +3 -10
- package/dist-es/list-deprecated/useList.js.map +1 -1
- package/dist-es/list-deprecated/useListItem.js.map +1 -1
- package/dist-es/list-next/ListNext.js.map +1 -1
- package/dist-es/metric/MetricContent.js +1 -0
- package/dist-es/metric/MetricContent.js.map +1 -1
- package/dist-es/number-input/NumberInput.css.js +1 -1
- package/dist-es/number-input/internal/utils.js +1 -1
- package/dist-es/number-input/internal/utils.js.map +1 -1
- package/dist-es/query-input/QueryInput.js +10 -10
- package/dist-es/query-input/QueryInput.js.map +1 -1
- package/dist-es/query-input/internal/QueryInputBody.js +1 -1
- package/dist-es/query-input/internal/QueryInputBody.js.map +1 -1
- package/dist-es/query-input/internal/SearchList.js +1 -1
- package/dist-es/query-input/internal/SearchList.js.map +1 -1
- package/dist-es/query-input/internal/usePopperStatus.js +2 -2
- package/dist-es/query-input/internal/usePopperStatus.js.map +1 -1
- package/dist-es/query-input/useQueryInput.js +6 -6
- package/dist-es/query-input/useQueryInput.js.map +1 -1
- package/dist-es/responsive/OverflowReducer.js +0 -2
- package/dist-es/responsive/OverflowReducer.js.map +1 -1
- package/dist-es/responsive/overflowUtils.js +6 -3
- package/dist-es/responsive/overflowUtils.js.map +1 -1
- package/dist-es/responsive/useDynamicCollapse.js +6 -3
- package/dist-es/responsive/useDynamicCollapse.js.map +1 -1
- package/dist-es/responsive/useOverflow.js +2 -2
- package/dist-es/responsive/useOverflow.js.map +1 -1
- package/dist-es/responsive/useOverflowCollectionItems.js +1 -1
- package/dist-es/responsive/useOverflowCollectionItems.js.map +1 -1
- package/dist-es/responsive/useOverflowLayout.js +1 -1
- package/dist-es/responsive/useOverflowLayout.js.map +1 -1
- package/dist-es/responsive/useReclaimSpace.js +1 -1
- package/dist-es/responsive/useReclaimSpace.js.map +1 -1
- package/dist-es/responsive/useResizeObserver.js +7 -2
- package/dist-es/responsive/useResizeObserver.js.map +1 -1
- package/dist-es/search-input/SearchInput.js.map +1 -1
- package/dist-es/table/TBody.js +30 -0
- package/dist-es/table/TBody.js.map +1 -0
- package/dist-es/table/TD.js +28 -0
- package/dist-es/table/TD.js.map +1 -0
- package/dist-es/table/TFoot.js +43 -0
- package/dist-es/table/TFoot.js.map +1 -0
- package/dist-es/table/TH.js +28 -0
- package/dist-es/table/TH.js.map +1 -0
- package/dist-es/table/THead.js +43 -0
- package/dist-es/table/THead.js.map +1 -0
- package/dist-es/table/TR.js +28 -0
- package/dist-es/table/TR.js.map +1 -0
- package/dist-es/table/Table.css.js +4 -0
- package/dist-es/table/Table.css.js.map +1 -0
- package/dist-es/table/Table.js +44 -0
- package/dist-es/table/Table.js.map +1 -0
- package/dist-es/tabs/TabActivationIndicator.css.js +1 -1
- package/dist-es/tabs/Tabs.js +1 -9
- package/dist-es/tabs/Tabs.js.map +1 -1
- package/dist-es/tabs/drag-drop/useDragSpacers.js +6 -7
- package/dist-es/tabs/drag-drop/useDragSpacers.js.map +1 -1
- package/dist-es/tabs/useActivationIndicator.js.map +1 -1
- package/dist-es/tabs-next/TabNextTrigger.js +2 -1
- package/dist-es/tabs-next/TabNextTrigger.js.map +1 -1
- package/dist-es/tabs-next/hooks/useOverflow.js +4 -6
- package/dist-es/tabs-next/hooks/useOverflow.js.map +1 -1
- package/dist-es/tokenized-input/useTokenizedInput.js +5 -5
- package/dist-es/tokenized-input/useTokenizedInput.js.map +1 -1
- package/dist-es/tokenized-input-next/TokenizedInputNext.css.js +1 -1
- package/dist-es/tree/Tree.js.map +1 -1
- package/dist-es/vertical-navigation/SubMenuContext.js +30 -0
- package/dist-es/vertical-navigation/SubMenuContext.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigation.css.js +4 -0
- package/dist-es/vertical-navigation/VerticalNavigation.css.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigation.js +32 -0
- package/dist-es/vertical-navigation/VerticalNavigation.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItem.js +45 -0
- package/dist-es/vertical-navigation/VerticalNavigationItem.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemContent.css.js +4 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemContent.css.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemContent.js +81 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemContent.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemExpansionIcon.js +27 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemExpansionIcon.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemLabel.css.js +4 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemLabel.css.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemLabel.js +22 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemLabel.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemTrigger.css.js +4 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemTrigger.css.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemTrigger.js +67 -0
- package/dist-es/vertical-navigation/VerticalNavigationItemTrigger.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationSubMenu.css.js +4 -0
- package/dist-es/vertical-navigation/VerticalNavigationSubMenu.css.js.map +1 -0
- package/dist-es/vertical-navigation/VerticalNavigationSubMenu.js +33 -0
- package/dist-es/vertical-navigation/VerticalNavigationSubMenu.js.map +1 -0
- package/dist-types/breadcrumbs/Breadcrumb.d.ts +2 -2
- package/dist-types/breadcrumbs/Breadcrumbs.d.ts +2 -2
- package/dist-types/cascading-menu/CascadingMenuList.d.ts +3 -1
- package/dist-types/cascading-menu/CascadingMenuProps.d.ts +1 -1
- package/dist-types/cascading-menu/internal/useMenuTriggerHandlers.d.ts +3 -2
- package/dist-types/collapsible/Collapsible.d.ts +16 -0
- package/dist-types/collapsible/CollapsibleContext.d.ts +9 -0
- package/dist-types/collapsible/CollapsiblePanel.d.ts +4 -0
- package/dist-types/collapsible/CollapsibleTrigger.d.ts +5 -0
- package/dist-types/collapsible/index.d.ts +3 -0
- package/dist-types/combo-box-deprecated/internal/useComboBox.d.ts +5 -5
- package/dist-types/combo-box-deprecated/internal/useMultiSelectComboBox.d.ts +7 -7
- package/dist-types/common-hooks/useAutoSizer.d.ts +1 -1
- package/dist-types/common-hooks/useCollapsibleGroups.d.ts +2 -2
- package/dist-types/common-hooks/useCollectionItems.d.ts +1 -1
- package/dist-types/common-hooks/useSelection.d.ts +1 -1
- package/dist-types/content-status/ContentStatus.d.ts +1 -1
- package/dist-types/dropdown/DropdownButton.d.ts +1 -1
- package/dist-types/dropdown/dropdownTypes.d.ts +2 -2
- package/dist-types/dropdown/useDropdown.d.ts +1 -1
- package/dist-types/index.d.ts +3 -0
- package/dist-types/list/useListHeight.d.ts +1 -1
- package/dist-types/list-deprecated/ListBase.d.ts +4 -8
- package/dist-types/list-deprecated/ListProps.d.ts +7 -6
- package/dist-types/list-deprecated/internal/helpers.d.ts +3 -2
- package/dist-types/list-deprecated/internal/useListAutoSizer.d.ts +2 -7
- package/dist-types/list-deprecated/itemToString.d.ts +2 -2
- package/dist-types/list-deprecated/useList.d.ts +1 -1
- package/dist-types/metric/internal/helpers.d.ts +1 -1
- package/dist-types/query-input/internal/usePopperStatus.d.ts +3 -3
- package/dist-types/responsive/overflowTypes.d.ts +1 -1
- package/dist-types/responsive/overflowUtils.d.ts +1 -1
- package/dist-types/responsive/useReclaimSpace.d.ts +1 -1
- package/dist-types/search-input/SearchInput.d.ts +1 -1
- package/dist-types/table/TBody.d.ts +4 -0
- package/dist-types/table/TD.d.ts +4 -0
- package/dist-types/table/TFoot.d.ts +20 -0
- package/dist-types/table/TH.d.ts +4 -0
- package/dist-types/table/THead.d.ts +20 -0
- package/dist-types/table/TR.d.ts +4 -0
- package/dist-types/table/Table.d.ts +20 -0
- package/dist-types/table/index.d.ts +7 -0
- package/dist-types/vertical-navigation/SubMenuContext.d.ts +14 -0
- package/dist-types/vertical-navigation/VerticalNavigation.d.ts +5 -0
- package/dist-types/vertical-navigation/VerticalNavigationItem.d.ts +12 -0
- package/dist-types/vertical-navigation/VerticalNavigationItemContent.d.ts +4 -0
- package/dist-types/vertical-navigation/VerticalNavigationItemExpansionIcon.d.ts +2 -0
- package/dist-types/vertical-navigation/VerticalNavigationItemLabel.d.ts +4 -0
- package/dist-types/vertical-navigation/VerticalNavigationItemTrigger.d.ts +6 -0
- package/dist-types/vertical-navigation/VerticalNavigationSubMenu.d.ts +4 -0
- package/dist-types/vertical-navigation/index.d.ts +7 -0
- package/package.json +3 -6
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
|
+
var useEventCallback = require('../utils/useEventCallback.js');
|
|
4
5
|
var keyUtils = require('./keyUtils.js');
|
|
5
6
|
|
|
6
7
|
const NO_HANDLERS = {};
|
|
@@ -17,64 +18,51 @@ const useCollapsibleGroups = ({
|
|
|
17
18
|
highlightedIdx,
|
|
18
19
|
onToggle
|
|
19
20
|
}) => {
|
|
20
|
-
const handleKeyDown =
|
|
21
|
-
(e)
|
|
22
|
-
if (e.key === keyUtils.ArrowRight || e.key === keyUtils.Enter) {
|
|
23
|
-
const item = collectionHook.data[highlightedIdx];
|
|
24
|
-
if (item) {
|
|
25
|
-
if (item.expanded === false && item.value) {
|
|
26
|
-
e.preventDefault();
|
|
27
|
-
collectionHook.expandGroupItem(item);
|
|
28
|
-
onToggle == null ? void 0 : onToggle(item.value);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (e.key === keyUtils.ArrowLeft || e.key === keyUtils.Enter) {
|
|
33
|
-
const item = collectionHook.data[highlightedIdx];
|
|
34
|
-
if (item) {
|
|
35
|
-
if (item.expanded && item.value) {
|
|
36
|
-
e.preventDefault();
|
|
37
|
-
collectionHook.collapseGroupItem(item);
|
|
38
|
-
onToggle == null ? void 0 : onToggle(item.value);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
[
|
|
44
|
-
collectionHook.collapseGroupItem,
|
|
45
|
-
collectionHook.data,
|
|
46
|
-
collectionHook.expandGroupItem,
|
|
47
|
-
highlightedIdx
|
|
48
|
-
]
|
|
49
|
-
);
|
|
50
|
-
const handleClick = react.useCallback(
|
|
51
|
-
(evt) => {
|
|
52
|
-
console.log(`useCollapsibleGroups idx=${highlightedIdx}`);
|
|
21
|
+
const handleKeyDown = useEventCallback.useEventCallback((e) => {
|
|
22
|
+
if (e.key === keyUtils.ArrowRight || e.key === keyUtils.Enter) {
|
|
53
23
|
const item = collectionHook.data[highlightedIdx];
|
|
54
|
-
|
|
55
|
-
if (item && canToggleItem(item) && (toggleIconClicked(evt.target))) {
|
|
56
|
-
evt.stopPropagation();
|
|
57
|
-
evt.preventDefault();
|
|
24
|
+
if (item) {
|
|
58
25
|
if (item.expanded === false && item.value) {
|
|
26
|
+
e.preventDefault();
|
|
59
27
|
collectionHook.expandGroupItem(item);
|
|
60
28
|
onToggle == null ? void 0 : onToggle(item.value);
|
|
61
|
-
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (e.key === keyUtils.ArrowLeft || e.key === keyUtils.Enter) {
|
|
33
|
+
const item = collectionHook.data[highlightedIdx];
|
|
34
|
+
if (item) {
|
|
35
|
+
if (item.expanded && item.value) {
|
|
36
|
+
e.preventDefault();
|
|
62
37
|
collectionHook.collapseGroupItem(item);
|
|
63
38
|
onToggle == null ? void 0 : onToggle(item.value);
|
|
64
39
|
}
|
|
65
40
|
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const handleClick = useEventCallback.useEventCallback((evt) => {
|
|
44
|
+
console.log(`useCollapsibleGroups idx=${highlightedIdx}`);
|
|
45
|
+
const item = collectionHook.data[highlightedIdx];
|
|
46
|
+
console.log(evt.target, evt.currentTarget);
|
|
47
|
+
if (item && canToggleItem(item) && (toggleIconClicked(evt.target))) {
|
|
48
|
+
evt.stopPropagation();
|
|
49
|
+
evt.preventDefault();
|
|
50
|
+
if (item.expanded === false && item.value) {
|
|
51
|
+
collectionHook.expandGroupItem(item);
|
|
52
|
+
onToggle == null ? void 0 : onToggle(item.value);
|
|
53
|
+
} else if (item.expanded === true && item.value) {
|
|
54
|
+
collectionHook.collapseGroupItem(item);
|
|
55
|
+
onToggle == null ? void 0 : onToggle(item.value);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
const listHandlers = react.useMemo(
|
|
60
|
+
() => ({
|
|
61
|
+
onClick: handleClick,
|
|
62
|
+
onKeyDown: handleKeyDown
|
|
63
|
+
}),
|
|
64
|
+
[handleClick, handleKeyDown]
|
|
73
65
|
);
|
|
74
|
-
const listHandlers = {
|
|
75
|
-
onClick: handleClick,
|
|
76
|
-
onKeyDown: handleKeyDown
|
|
77
|
-
};
|
|
78
66
|
return collapsibleHeaders ? listHandlers : NO_HANDLERS;
|
|
79
67
|
};
|
|
80
68
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCollapsibleGroups.js","sources":["../src/common-hooks/useCollapsibleGroups.ts"],"sourcesContent":["import { type KeyboardEvent, type MouseEvent,
|
|
1
|
+
{"version":3,"file":"useCollapsibleGroups.js","sources":["../src/common-hooks/useCollapsibleGroups.ts"],"sourcesContent":["import { type KeyboardEvent, type MouseEvent, useMemo } from \"react\";\nimport { useEventCallback } from \"../utils/useEventCallback\";\nimport type { CollectionHookResult, CollectionItem } from \"./collectionTypes\";\nimport { ArrowLeft, ArrowRight, Enter } from \"./keyUtils\";\nimport type { ListHandlers } from \"./selectionTypes\";\n\nconst NO_HANDLERS = {};\nconst canToggleItem = (item: CollectionItem<unknown>) =>\n Array.isArray(item.childNodes);\n// TODO how do we determine this and where does this function belong = in the collectionHook ?\nconst canSelectItem = () => true;\n\nconst toggleIconClicked = (el: HTMLElement) => {\n const closestToggle = el.closest(\n \"[data-toggle],[aria-expanded]\",\n ) as HTMLElement;\n return closestToggle.dataset.toggle === \"true\";\n};\n\ninterface CollapsibleHookProps<Item> {\n collapsibleHeaders?: boolean;\n collectionHook: CollectionHookResult<Item>;\n highlightedIdx: number;\n onToggle?: (node: Item) => void;\n}\n\ninterface CollapsibleHookResult {\n onClick?: ListHandlers[\"onClick\"];\n onKeyDown?: ListHandlers[\"onKeyDown\"];\n}\n\nexport const useCollapsibleGroups = <Item>({\n collapsibleHeaders,\n collectionHook,\n highlightedIdx,\n onToggle,\n}: CollapsibleHookProps<Item>): CollapsibleHookResult => {\n const handleKeyDown = useEventCallback((e: KeyboardEvent) => {\n if (e.key === ArrowRight || e.key === Enter) {\n const item = collectionHook.data[highlightedIdx];\n if (item) {\n if (item.expanded === false && item.value) {\n e.preventDefault();\n collectionHook.expandGroupItem(item);\n onToggle?.(item.value);\n }\n }\n }\n\n if (e.key === ArrowLeft || e.key === Enter) {\n const item = collectionHook.data[highlightedIdx];\n if (item) {\n if (item.expanded && item.value) {\n e.preventDefault();\n collectionHook.collapseGroupItem(item);\n onToggle?.(item.value);\n }\n }\n }\n });\n\n const handleClick = useEventCallback((evt: MouseEvent<HTMLElement>) => {\n console.log(`useCollapsibleGroups idx=${highlightedIdx}`);\n const item = collectionHook.data[highlightedIdx];\n console.log(evt.target, evt.currentTarget);\n if (\n item &&\n canToggleItem(item) &&\n (!canSelectItem() || toggleIconClicked(evt.target as HTMLElement))\n ) {\n evt.stopPropagation();\n evt.preventDefault();\n if (item.expanded === false && item.value) {\n collectionHook.expandGroupItem(item);\n onToggle?.(item.value);\n } else if (item.expanded === true && item.value) {\n collectionHook.collapseGroupItem(item);\n onToggle?.(item.value);\n }\n }\n });\n\n /**\n * These are List handlers, so we will not have reference to the actual node\n * element. We must rely on highlightedIdx to tell us which node is interactive.\n */\n const listHandlers = useMemo(\n () => ({\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n }),\n [handleClick, handleKeyDown],\n );\n\n return collapsibleHeaders ? listHandlers : NO_HANDLERS;\n};\n"],"names":["useEventCallback","ArrowRight","Enter","ArrowLeft","useMemo"],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ const defaultCollectionOptions = {};
|
|
|
10
10
|
const useCollectionItems = ({
|
|
11
11
|
children,
|
|
12
12
|
id: idRoot,
|
|
13
|
-
label = "",
|
|
13
|
+
label: _label = "",
|
|
14
14
|
options = defaultCollectionOptions,
|
|
15
15
|
// revealSelected = false,
|
|
16
16
|
source
|
|
@@ -27,12 +27,9 @@ const useCollectionItems = ({
|
|
|
27
27
|
noChildrenLabel,
|
|
28
28
|
itemToString: itemToString$1 = itemToString.itemToString
|
|
29
29
|
} = options;
|
|
30
|
-
const isExpanded = react.useCallback(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
[options.defaultExpanded]
|
|
35
|
-
);
|
|
30
|
+
const isExpanded = react.useCallback(() => {
|
|
31
|
+
return options.defaultExpanded || false;
|
|
32
|
+
}, [options.defaultExpanded]);
|
|
36
33
|
const addMetadataToItems = react.useCallback(
|
|
37
34
|
(items, indexer, level = 1, path = "", results = [], flattenedCollection2 = [], flattenedSource2 = []) => {
|
|
38
35
|
items.forEach((item, i, all) => {
|
|
@@ -42,7 +39,7 @@ const useCollectionItems = ({
|
|
|
42
39
|
const nonCollapsible = isNonCollapsibleGroupNode || isLeaf && !isCollapsibleHeader;
|
|
43
40
|
const childPath = path ? `${path}.${i}` : `item-${i}`;
|
|
44
41
|
const id = item.id ?? (getItemId ? getItemId(i) : `${idRoot}-${childPath}`);
|
|
45
|
-
const expanded = nonCollapsible ? void 0 : item.expanded ?? isExpanded(
|
|
42
|
+
const expanded = nonCollapsible ? void 0 : item.expanded ?? isExpanded();
|
|
46
43
|
const normalisedItem = {
|
|
47
44
|
...item,
|
|
48
45
|
childNodes: void 0,
|
|
@@ -156,7 +153,7 @@ const useCollectionItems = ({
|
|
|
156
153
|
return i.id === id || ((_a = i == null ? void 0 : i.childNodes) == null ? void 0 : _a.length) && collectionItemUtils.isParentPath(i.id, id);
|
|
157
154
|
}
|
|
158
155
|
);
|
|
159
|
-
if ((sourceWithId == null ? void 0 : sourceWithId.id) === id) {
|
|
156
|
+
if ((sourceWithId == null ? void 0 : sourceWithId.id) === id && sourceWithId.index != null) {
|
|
160
157
|
return flattenedSource == null ? void 0 : flattenedSource[sourceWithId.index];
|
|
161
158
|
}
|
|
162
159
|
if (sourceWithId) {
|
|
@@ -171,7 +168,6 @@ const useCollectionItems = ({
|
|
|
171
168
|
const collectionItem = flattenedDataRef.current.find(
|
|
172
169
|
(i) => (
|
|
173
170
|
// const collectionItem = collectionItemsRef.current.find((i) =>
|
|
174
|
-
//@ts-ignore
|
|
175
171
|
react.isValidElement(i.value) ? i.label === item : i.value === item
|
|
176
172
|
)
|
|
177
173
|
);
|
|
@@ -208,7 +204,6 @@ const useCollectionItems = ({
|
|
|
208
204
|
const collectionItem = flattenedDataRef.current.find(
|
|
209
205
|
(i) => (
|
|
210
206
|
// const collectionItem = collectionItemsRef.current.find((i) =>
|
|
211
|
-
//@ts-ignore
|
|
212
207
|
react.isValidElement(i.value) ? i.label === item : i.value !== null && itemToString$1(i.value) === item
|
|
213
208
|
)
|
|
214
209
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCollectionItems.js","sources":["../src/common-hooks/useCollectionItems.ts"],"sourcesContent":["import { isValidElement, useCallback, useMemo, useRef, useState } from \"react\";\nimport { useCollection } from \"./collectionProvider\";\nimport type {\n CollectionHookProps,\n CollectionHookResult,\n CollectionIndexer,\n CollectionItem,\n} from \"./collectionTypes\";\nimport { itemToString as defaultItemToString } from \"./itemToString\";\nimport type {\n SelectionStrategy,\n SingleSelectionStrategy,\n} from \"./selectionTypes\";\nimport {\n childItems,\n countChildItems,\n type FilterPredicate,\n getDefaultFilter,\n getDefaultFilterRegex,\n isDisabled,\n isFocusable,\n isGroupNode,\n isHeader,\n isParentPath,\n replaceCollectionItem,\n sourceItems,\n} from \"./utils\";\n\nconst defaultCollectionOptions = {};\n\nexport const useCollectionItems = <Item>({\n children,\n id: idRoot,\n label = \"\",\n options = defaultCollectionOptions,\n // revealSelected = false,\n source,\n}: CollectionHookProps<Item>): CollectionHookResult<Item> => {\n const { getItemId } = options;\n\n const [, forceUpdate] = useState<unknown>(null);\n const inheritedCollectionHook = useCollection<Item>();\n const dataRef = useRef<CollectionItem<Item>[]>([]);\n const flattenedDataRef = useRef<CollectionItem<Item>[]>([]);\n const EMPTY_COLLECTION: CollectionItem<Item>[] = useMemo(() => [], []);\n const filterPattern = useRef<string>(options.filterPattern ?? \"\");\n\n // destructure individual option values so we can safely reference them in dependency arrays\n const {\n getFilterRegex = getDefaultFilterRegex,\n noChildrenLabel,\n itemToString = defaultItemToString,\n } = options;\n\n const isExpanded = useCallback(\n (path: string) => {\n // We can't do this here because itemToId won't work until we complete this phase\n // if (Array.isArray(revealSelected)) {\n // const selectedIds = revealSelected.map(itemToId);\n // return selectedIds.some((id) => isParentPath(path, id));\n // }\n return options.defaultExpanded || false;\n },\n [options.defaultExpanded],\n );\n\n const addMetadataToItems = useCallback(\n <Item>(\n items: CollectionItem<Item>[],\n indexer: CollectionIndexer,\n level = 1,\n path = \"\",\n results: CollectionItem<Item>[] = [],\n flattenedCollection: CollectionItem<Item>[] = [],\n flattenedSource: (Item | null)[] = [],\n ): [CollectionItem<Item>[], (Item | null)[], CollectionItem<Item>[]] => {\n items.forEach((item, i, all) => {\n const isCollapsibleHeader = item.header && options.collapsibleHeaders;\n const isNonCollapsibleGroupNode =\n item.childNodes && options.collapsibleHeaders === false;\n const isLeaf = !item.childNodes || item.childNodes.length === 0;\n const nonCollapsible =\n isNonCollapsibleGroupNode || (isLeaf && !isCollapsibleHeader);\n const childPath = path ? `${path}.${i}` : `item-${i}`;\n // getItemId is backward compatible with earlier List implementation.\n // It is not appropriate for a nested source structure, where index\n // will not always be an absolute offset.\n const id =\n item.id ?? (getItemId ? getItemId(i) : `${idRoot}-${childPath}`);\n\n const expanded = nonCollapsible\n ? undefined\n : (item.expanded ?? isExpanded(id));\n //TODO dev time check - if id is provided by user, make sure\n // hierarchical pattern is consistent\n const normalisedItem: CollectionItem<Item> = {\n ...item,\n childNodes: undefined,\n count:\n !isNonCollapsibleGroupNode && expanded === undefined\n ? 0\n : countChildItems(item, all, i),\n description: item.description,\n disabled: isDisabled(item.value),\n focusable: isFocusable(item.value) ? undefined : false,\n id,\n index: indexer.value,\n expanded,\n level,\n };\n results.push(normalisedItem);\n flattenedCollection.push(normalisedItem);\n flattenedSource.push(items[i].value);\n\n indexer.value += 1;\n\n // if ((isNonCollapsibleGroupNode || expanded !== undefined) && !isCollapsibleHeader) {\n if (item.childNodes) {\n const [children] = addMetadataToItems<Item>(\n item.childNodes,\n indexer,\n level + 1,\n childPath,\n [],\n flattenedCollection,\n flattenedSource,\n );\n normalisedItem.childNodes = children;\n }\n });\n return [results, flattenedSource, flattenedCollection];\n },\n [options.collapsibleHeaders, getItemId, idRoot, isExpanded],\n );\n\n const getFilter = useCallback(() => {\n if (filterPattern.current) {\n return getDefaultFilter(filterPattern.current, getFilterRegex);\n }\n return null;\n }, [getFilterRegex]);\n\n const collectVisibleItems = useCallback(\n (\n items: CollectionItem<Item>[],\n filter: null | FilterPredicate = getFilter(),\n results: CollectionItem<Item>[] = [],\n idx: { value: number } = { value: 0 },\n ): CollectionItem<Item>[] => {\n let skipToNextHeader = false;\n for (const item of items) {\n if (!(skipToNextHeader && !isHeader(item))) {\n if (\n item.value !== null &&\n (filter === null || filter(itemToString(item.value)))\n ) {\n results[idx.value] = item;\n idx.value += 1;\n }\n skipToNextHeader = false;\n if (isHeader(item) && item.expanded === false) {\n skipToNextHeader = true;\n } else if (isGroupNode(item)) {\n if (item.expanded !== false && item.childNodes) {\n collectVisibleItems(item.childNodes, filter, results, idx);\n }\n }\n }\n }\n return results;\n },\n [getFilter, itemToString],\n );\n\n // Stage 1 - convert source or children to CollectionItems.\n const partialCollectionItems = useMemo(() => {\n return inheritedCollectionHook\n ? EMPTY_COLLECTION\n : sourceItems<Item>(source, { itemToString, noChildrenLabel }) ||\n childItems(children) ||\n [];\n }, [\n inheritedCollectionHook,\n EMPTY_COLLECTION,\n source,\n itemToString,\n noChildrenLabel,\n children,\n ]);\n\n // Stage 2 - extend the collectionItems with additional metadata\n const [collectionItems, flattenedSource, flattenedCollection] = useMemo(\n () =>\n inheritedCollectionHook\n ? [EMPTY_COLLECTION, EMPTY_COLLECTION, EMPTY_COLLECTION]\n : //@ts-ignore\n addMetadataToItems<Item>(partialCollectionItems, { value: 0 }),\n [\n EMPTY_COLLECTION,\n addMetadataToItems,\n inheritedCollectionHook,\n partialCollectionItems,\n ],\n );\n flattenedDataRef.current = flattenedCollection;\n\n // Stage 3 prepare the list of visible items, this is what will be rendered\n useMemo(\n () =>\n inheritedCollectionHook\n ? EMPTY_COLLECTION\n : (dataRef.current = collectVisibleItems(collectionItems)),\n [\n EMPTY_COLLECTION,\n collectVisibleItems,\n collectionItems,\n inheritedCollectionHook,\n ],\n );\n\n const collectionItemsRef = useRef(collectionItems);\n\n const setFilterPattern = useCallback(\n (pattern = \"\") => {\n if (typeof pattern === \"string\") {\n filterPattern.current = pattern;\n dataRef.current = collectVisibleItems(collectionItems);\n forceUpdate({});\n }\n },\n [collectionItems, collectVisibleItems],\n );\n\n const itemById = useCallback(\n (\n id: string,\n target: CollectionItem<Item>[] = collectionItems,\n ): Item | never => {\n const sourceWithId = target.find(\n (i) => i.id === id || (i?.childNodes?.length && isParentPath(i.id, id)),\n );\n if (sourceWithId?.id === id) {\n //TODO do we need the flattered source at all ?\n return flattenedSource?.[sourceWithId.index!] as Item;\n }\n if (sourceWithId) {\n return itemById(id, sourceWithId.childNodes);\n }\n throw Error(`useCollectionData itemById, id ${id} not found `);\n },\n [flattenedSource, collectionItems],\n );\n\n const toCollectionItem = useCallback(\n (item: Item): CollectionItem<Item> | never => {\n // TODO what about Tree structures, we need to search flattened source\n const collectionItem = flattenedDataRef.current.find((i) =>\n // const collectionItem = collectionItemsRef.current.find((i) =>\n //@ts-ignore\n isValidElement(i.value) ? i.label === item : i.value === item,\n );\n if (collectionItem) {\n return collectionItem;\n }\n throw Error(\"useCollectionData toCollectionItem, item not found \");\n },\n [],\n );\n\n // TODO types need more work, these are correct but we\n // don't really want references to Selection in here\n const itemToCollectionItem = useCallback(\n <\n Selection extends SelectionStrategy,\n U extends Item | Item[] | null | undefined,\n >(\n sel: U,\n ): Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[] => {\n type returnType = Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[];\n\n if (sel === null) {\n return null as returnType;\n }\n if (Array.isArray(sel)) {\n const result: CollectionItem<Item>[] = [];\n for (const item of sel) {\n const collectionItem = toCollectionItem(item);\n result.push(collectionItem);\n }\n return result as returnType;\n }\n if (sel !== undefined) {\n return toCollectionItem(sel as Item) as returnType;\n }\n\n return undefined as unknown as returnType;\n },\n [toCollectionItem],\n );\n\n const stringToCollectionItem = useCallback(\n <Selection extends SelectionStrategy>(\n value: string | null | undefined,\n ): Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[] => {\n type returnType = Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[];\n\n const toCollectionItem = (\n item: string,\n ): undefined | CollectionItem<Item> | never => {\n // TODO what about Tree structures, we need to search flattened source\n const collectionItem = flattenedDataRef.current.find((i) =>\n // const collectionItem = collectionItemsRef.current.find((i) =>\n //@ts-ignore\n isValidElement(i.value)\n ? i.label === item\n : i.value !== null && itemToString(i.value) === item,\n );\n if (collectionItem) {\n return collectionItem;\n }\n };\n\n if (value === null) {\n return null as returnType;\n }\n if (Array.isArray(value)) {\n const result: CollectionItem<Item>[] = [];\n for (const item of value) {\n const collectionItem = toCollectionItem(item);\n if (collectionItem) {\n result.push(collectionItem);\n }\n }\n return result as returnType;\n }\n if (value !== undefined) {\n return toCollectionItem(value) as returnType;\n }\n\n return undefined as unknown as returnType;\n },\n [itemToString],\n );\n\n const itemToId = useCallback((item: Item): string => {\n for (const collectionItem of collectionItemsRef.current) {\n if (item === collectionItem.value) {\n return collectionItem.id;\n }\n }\n throw Error(\"useCollectionData itemToId, item not found\");\n }, []);\n\n const collapseGroupItem = useCallback(\n (item: CollectionItem<Item>) => {\n collectionItemsRef.current = replaceCollectionItem(\n collectionItemsRef.current,\n item.id,\n {\n expanded: false,\n },\n );\n dataRef.current = collectVisibleItems(collectionItemsRef.current);\n forceUpdate({});\n },\n [collectVisibleItems],\n );\n\n const expandGroupItem = useCallback(\n (item: CollectionItem<Item>) => {\n collectionItemsRef.current = replaceCollectionItem<Item>(\n collectionItemsRef.current,\n item.id,\n {\n expanded: true,\n },\n );\n dataRef.current = collectVisibleItems(collectionItemsRef.current);\n forceUpdate({});\n },\n [collectVisibleItems],\n );\n\n return (\n inheritedCollectionHook || {\n collapseGroupItem,\n data: dataRef.current,\n expandGroupItem, // why not toggle, or just rely on setdata ?\n setFilterPattern,\n itemById,\n itemToId,\n toCollectionItem,\n itemToCollectionItem,\n stringToCollectionItem,\n }\n );\n};\n"],"names":["useState","useCollection","useRef","useMemo","getDefaultFilterRegex","itemToString","defaultItemToString","useCallback","flattenedCollection","flattenedSource","countChildItems","isDisabled","isFocusable","children","getDefaultFilter","isHeader","isGroupNode","sourceItems","childItems","isParentPath","isValidElement","toCollectionItem","replaceCollectionItem"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useCollectionItems.js","sources":["../src/common-hooks/useCollectionItems.ts"],"sourcesContent":["import { isValidElement, useCallback, useMemo, useRef, useState } from \"react\";\nimport { useCollection } from \"./collectionProvider\";\nimport type {\n CollectionHookProps,\n CollectionHookResult,\n CollectionIndexer,\n CollectionItem,\n} from \"./collectionTypes\";\nimport { itemToString as defaultItemToString } from \"./itemToString\";\nimport type {\n SelectionStrategy,\n SingleSelectionStrategy,\n} from \"./selectionTypes\";\nimport {\n childItems,\n countChildItems,\n type FilterPredicate,\n getDefaultFilter,\n getDefaultFilterRegex,\n isDisabled,\n isFocusable,\n isGroupNode,\n isHeader,\n isParentPath,\n replaceCollectionItem,\n sourceItems,\n} from \"./utils\";\n\nconst defaultCollectionOptions = {};\n\nexport const useCollectionItems = <Item>({\n children,\n id: idRoot,\n label: _label = \"\",\n options = defaultCollectionOptions,\n // revealSelected = false,\n source,\n}: CollectionHookProps<Item>): CollectionHookResult<Item> => {\n const { getItemId } = options;\n\n const [, forceUpdate] = useState<unknown>(null);\n const inheritedCollectionHook = useCollection<Item>();\n const dataRef = useRef<CollectionItem<Item>[]>([]);\n const flattenedDataRef = useRef<CollectionItem<Item>[]>([]);\n const EMPTY_COLLECTION: CollectionItem<Item>[] = useMemo(() => [], []);\n const filterPattern = useRef<string>(options.filterPattern ?? \"\");\n\n // destructure individual option values so we can safely reference them in dependency arrays\n const {\n getFilterRegex = getDefaultFilterRegex,\n noChildrenLabel,\n itemToString = defaultItemToString,\n } = options;\n\n const isExpanded = useCallback(() => {\n // We can't do this here because itemToId won't work until we complete this phase\n // if (Array.isArray(revealSelected)) {\n // const selectedIds = revealSelected.map(itemToId);\n // return selectedIds.some((id) => isParentPath(path, id));\n // }\n return options.defaultExpanded || false;\n }, [options.defaultExpanded]);\n\n const addMetadataToItems = useCallback(\n <Item>(\n items: CollectionItem<Item>[],\n indexer: CollectionIndexer,\n level = 1,\n path = \"\",\n results: CollectionItem<Item>[] = [],\n flattenedCollection: CollectionItem<Item>[] = [],\n flattenedSource: (Item | null)[] = [],\n ): [CollectionItem<Item>[], (Item | null)[], CollectionItem<Item>[]] => {\n items.forEach((item, i, all) => {\n const isCollapsibleHeader = item.header && options.collapsibleHeaders;\n const isNonCollapsibleGroupNode =\n item.childNodes && options.collapsibleHeaders === false;\n const isLeaf = !item.childNodes || item.childNodes.length === 0;\n const nonCollapsible =\n isNonCollapsibleGroupNode || (isLeaf && !isCollapsibleHeader);\n const childPath = path ? `${path}.${i}` : `item-${i}`;\n // getItemId is backward compatible with earlier List implementation.\n // It is not appropriate for a nested source structure, where index\n // will not always be an absolute offset.\n const id =\n item.id ?? (getItemId ? getItemId(i) : `${idRoot}-${childPath}`);\n\n const expanded = nonCollapsible\n ? undefined\n : (item.expanded ?? isExpanded());\n //TODO dev time check - if id is provided by user, make sure\n // hierarchical pattern is consistent\n const normalisedItem: CollectionItem<Item> = {\n ...item,\n childNodes: undefined,\n count:\n !isNonCollapsibleGroupNode && expanded === undefined\n ? 0\n : countChildItems(item, all, i),\n description: item.description,\n disabled: isDisabled(item.value),\n focusable: isFocusable(item.value) ? undefined : false,\n id,\n index: indexer.value,\n expanded,\n level,\n };\n results.push(normalisedItem);\n flattenedCollection.push(normalisedItem);\n flattenedSource.push(items[i].value);\n\n indexer.value += 1;\n\n // if ((isNonCollapsibleGroupNode || expanded !== undefined) && !isCollapsibleHeader) {\n if (item.childNodes) {\n const [children] = addMetadataToItems<Item>(\n item.childNodes,\n indexer,\n level + 1,\n childPath,\n [],\n flattenedCollection,\n flattenedSource,\n );\n normalisedItem.childNodes = children;\n }\n });\n return [results, flattenedSource, flattenedCollection];\n },\n [options.collapsibleHeaders, getItemId, idRoot, isExpanded],\n );\n\n const getFilter = useCallback(() => {\n if (filterPattern.current) {\n return getDefaultFilter(filterPattern.current, getFilterRegex);\n }\n return null;\n }, [getFilterRegex]);\n\n const collectVisibleItems = useCallback(\n (\n items: CollectionItem<Item>[],\n filter: null | FilterPredicate = getFilter(),\n results: CollectionItem<Item>[] = [],\n idx: { value: number } = { value: 0 },\n ): CollectionItem<Item>[] => {\n let skipToNextHeader = false;\n for (const item of items) {\n if (!(skipToNextHeader && !isHeader(item))) {\n if (\n item.value !== null &&\n (filter === null || filter(itemToString(item.value)))\n ) {\n results[idx.value] = item;\n idx.value += 1;\n }\n skipToNextHeader = false;\n if (isHeader(item) && item.expanded === false) {\n skipToNextHeader = true;\n } else if (isGroupNode(item)) {\n if (item.expanded !== false && item.childNodes) {\n collectVisibleItems(item.childNodes, filter, results, idx);\n }\n }\n }\n }\n return results;\n },\n [getFilter, itemToString],\n );\n\n // Stage 1 - convert source or children to CollectionItems.\n const partialCollectionItems = useMemo(() => {\n return inheritedCollectionHook\n ? EMPTY_COLLECTION\n : sourceItems<Item>(source, { itemToString, noChildrenLabel }) ||\n childItems(children) ||\n [];\n }, [\n inheritedCollectionHook,\n EMPTY_COLLECTION,\n source,\n itemToString,\n noChildrenLabel,\n children,\n ]);\n\n // Stage 2 - extend the collectionItems with additional metadata\n const [collectionItems, flattenedSource, flattenedCollection] = useMemo(\n () =>\n inheritedCollectionHook\n ? [EMPTY_COLLECTION, EMPTY_COLLECTION, EMPTY_COLLECTION]\n : //@ts-ignore\n addMetadataToItems<Item>(partialCollectionItems, { value: 0 }),\n [\n EMPTY_COLLECTION,\n addMetadataToItems,\n inheritedCollectionHook,\n partialCollectionItems,\n ],\n );\n flattenedDataRef.current = flattenedCollection;\n\n // Stage 3 prepare the list of visible items, this is what will be rendered\n useMemo(\n () =>\n inheritedCollectionHook\n ? EMPTY_COLLECTION\n : (dataRef.current = collectVisibleItems(collectionItems)),\n [\n EMPTY_COLLECTION,\n collectVisibleItems,\n collectionItems,\n inheritedCollectionHook,\n ],\n );\n\n const collectionItemsRef = useRef(collectionItems);\n\n const setFilterPattern = useCallback(\n (pattern = \"\") => {\n if (typeof pattern === \"string\") {\n filterPattern.current = pattern;\n dataRef.current = collectVisibleItems(collectionItems);\n forceUpdate({});\n }\n },\n [collectionItems, collectVisibleItems],\n );\n\n const itemById = useCallback(\n (\n id: string,\n target: CollectionItem<Item>[] = collectionItems,\n ): Item | never => {\n const sourceWithId = target.find(\n (i) => i.id === id || (i?.childNodes?.length && isParentPath(i.id, id)),\n );\n if (sourceWithId?.id === id && sourceWithId.index != null) {\n //TODO do we need the flattered source at all ?\n return flattenedSource?.[sourceWithId.index] as Item;\n }\n if (sourceWithId) {\n return itemById(id, sourceWithId.childNodes);\n }\n throw Error(`useCollectionData itemById, id ${id} not found `);\n },\n [flattenedSource, collectionItems],\n );\n\n const toCollectionItem = useCallback(\n (item: Item): CollectionItem<Item> | never => {\n // TODO what about Tree structures, we need to search flattened source\n const collectionItem = flattenedDataRef.current.find((i) =>\n // const collectionItem = collectionItemsRef.current.find((i) =>\n isValidElement(i.value) ? i.label === item : i.value === item,\n );\n if (collectionItem) {\n return collectionItem;\n }\n throw Error(\"useCollectionData toCollectionItem, item not found \");\n },\n [],\n );\n\n // TODO types need more work, these are correct but we\n // don't really want references to Selection in here\n const itemToCollectionItem = useCallback(\n <\n Selection extends SelectionStrategy,\n U extends Item | Item[] | null | undefined,\n >(\n sel: U,\n ): Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[] => {\n type returnType = Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[];\n\n if (sel === null) {\n return null as returnType;\n }\n if (Array.isArray(sel)) {\n const result: CollectionItem<Item>[] = [];\n for (const item of sel) {\n const collectionItem = toCollectionItem(item);\n result.push(collectionItem);\n }\n return result as returnType;\n }\n if (sel !== undefined) {\n return toCollectionItem(sel as Item) as returnType;\n }\n\n return undefined as unknown as returnType;\n },\n [toCollectionItem],\n );\n\n const stringToCollectionItem = useCallback(\n <Selection extends SelectionStrategy>(\n value: string | null | undefined,\n ): Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[] => {\n type returnType = Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[];\n\n const toCollectionItem = (\n item: string,\n ): undefined | CollectionItem<Item> | never => {\n // TODO what about Tree structures, we need to search flattened source\n const collectionItem = flattenedDataRef.current.find((i) =>\n // const collectionItem = collectionItemsRef.current.find((i) =>\n isValidElement(i.value)\n ? i.label === item\n : i.value !== null && itemToString(i.value) === item,\n );\n if (collectionItem) {\n return collectionItem;\n }\n };\n\n if (value === null) {\n return null as returnType;\n }\n if (Array.isArray(value)) {\n const result: CollectionItem<Item>[] = [];\n for (const item of value) {\n const collectionItem = toCollectionItem(item);\n if (collectionItem) {\n result.push(collectionItem);\n }\n }\n return result as returnType;\n }\n if (value !== undefined) {\n return toCollectionItem(value) as returnType;\n }\n\n return undefined as unknown as returnType;\n },\n [itemToString],\n );\n\n const itemToId = useCallback((item: Item): string => {\n for (const collectionItem of collectionItemsRef.current) {\n if (item === collectionItem.value) {\n return collectionItem.id;\n }\n }\n throw Error(\"useCollectionData itemToId, item not found\");\n }, []);\n\n const collapseGroupItem = useCallback(\n (item: CollectionItem<Item>) => {\n collectionItemsRef.current = replaceCollectionItem(\n collectionItemsRef.current,\n item.id,\n {\n expanded: false,\n },\n );\n dataRef.current = collectVisibleItems(collectionItemsRef.current);\n forceUpdate({});\n },\n [collectVisibleItems],\n );\n\n const expandGroupItem = useCallback(\n (item: CollectionItem<Item>) => {\n collectionItemsRef.current = replaceCollectionItem<Item>(\n collectionItemsRef.current,\n item.id,\n {\n expanded: true,\n },\n );\n dataRef.current = collectVisibleItems(collectionItemsRef.current);\n forceUpdate({});\n },\n [collectVisibleItems],\n );\n\n return (\n inheritedCollectionHook || {\n collapseGroupItem,\n data: dataRef.current,\n expandGroupItem, // why not toggle, or just rely on setdata ?\n setFilterPattern,\n itemById,\n itemToId,\n toCollectionItem,\n itemToCollectionItem,\n stringToCollectionItem,\n }\n );\n};\n"],"names":["useState","useCollection","useRef","useMemo","getDefaultFilterRegex","itemToString","defaultItemToString","useCallback","flattenedCollection","flattenedSource","countChildItems","isDisabled","isFocusable","children","getDefaultFilter","isHeader","isGroupNode","sourceItems","childItems","isParentPath","isValidElement","toCollectionItem","replaceCollectionItem"],"mappings":"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"}
|
|
@@ -34,6 +34,12 @@ const useKeyboardNavigationPanel = ({
|
|
|
34
34
|
default: defaultHighlightedIdx,
|
|
35
35
|
name: "UseKeyboardNavigation"
|
|
36
36
|
});
|
|
37
|
+
const keyboardNavigation = react.useRef(true);
|
|
38
|
+
const ignoreFocus = react.useRef(false);
|
|
39
|
+
const setIgnoreFocus = react.useCallback(
|
|
40
|
+
(value) => ignoreFocus.current = value,
|
|
41
|
+
[]
|
|
42
|
+
);
|
|
37
43
|
const setHighlightedIndex = react.useCallback(
|
|
38
44
|
(idx) => {
|
|
39
45
|
onHighlight == null ? void 0 : onHighlight(idx);
|
|
@@ -46,7 +52,7 @@ const useKeyboardNavigationPanel = ({
|
|
|
46
52
|
targetEl == null ? void 0 : targetEl.focus();
|
|
47
53
|
}
|
|
48
54
|
},
|
|
49
|
-
[focusOnHighlight, indexPositions, onHighlight]
|
|
55
|
+
[focusOnHighlight, indexPositions, onHighlight, setIgnoreFocus]
|
|
50
56
|
);
|
|
51
57
|
const nextFocusableItemIdx = react.useCallback(
|
|
52
58
|
(direction = "FWD", idx = direction === "FWD" ? -1 : indexPositions.length) => {
|
|
@@ -68,12 +74,6 @@ const useKeyboardNavigationPanel = ({
|
|
|
68
74
|
},
|
|
69
75
|
[cycleFocus, indexPositions]
|
|
70
76
|
);
|
|
71
|
-
const keyboardNavigation = react.useRef(true);
|
|
72
|
-
const ignoreFocus = react.useRef(false);
|
|
73
|
-
const setIgnoreFocus = react.useCallback(
|
|
74
|
-
(value) => ignoreFocus.current = value,
|
|
75
|
-
[]
|
|
76
|
-
);
|
|
77
77
|
const handleFocus = react.useCallback(() => {
|
|
78
78
|
if (ignoreFocus.current) {
|
|
79
79
|
ignoreFocus.current = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useKeyboardNavigationPanel.js","sources":["../src/common-hooks/useKeyboardNavigationPanel.ts"],"sourcesContent":["import { useControlled } from \"@salt-ds/core\";\nimport { type KeyboardEvent, useCallback, useMemo, useRef } from \"react\";\nimport type { CollectionItem } from \"./collectionTypes\";\nimport type { NavigationHookResult, NavigationProps } from \"./navigationTypes\";\n\ntype NavigationDirection = \"FWD\" | \"BWD\";\n\nfunction nextItemIdx(\n count: number,\n direction: NavigationDirection,\n idx: number,\n cycleFocus = false,\n) {\n if (direction === \"BWD\") {\n if (idx > 0) {\n return idx - 1;\n }\n return cycleFocus ? count - 1 : idx;\n }\n if (idx === null) {\n return 0;\n }\n if (idx === count - 1) {\n return cycleFocus ? 0 : idx;\n }\n return idx + 1;\n}\n\nconst isLeaf = <Item>(item: CollectionItem<Item>): boolean =>\n !item.header && !item.childNodes;\nconst isFocusable = <Item>(item: CollectionItem<Item>) =>\n (isLeaf(item) || item.expanded !== undefined) && item.focusable !== false;\n\n// we need a way to set highlightedIdx when selection changes\nexport const useKeyboardNavigationPanel = ({\n cycleFocus = false,\n defaultHighlightedIndex: defaultHighlightedIdx = -1,\n focusOnHighlight = false,\n highlightedIndex: highlightedIdxProp,\n indexPositions,\n onHighlight,\n onKeyboardNavigation,\n}: NavigationProps): NavigationHookResult => {\n const [highlightedIdx, setHighlightedIdx, isControlledHighlighting] =\n useControlled({\n controlled: highlightedIdxProp,\n default: defaultHighlightedIdx,\n name: \"UseKeyboardNavigation\",\n });\n\n const setHighlightedIndex = useCallback(\n (idx: number) => {\n onHighlight?.(idx);\n setHighlightedIdx(idx);\n if (focusOnHighlight && idx !== -1) {\n const { id } = indexPositions[idx];\n const formField = document.getElementById(id);\n const targetEl = formField?.querySelector(\"[tabindex]\") as HTMLElement;\n setIgnoreFocus(true);\n targetEl?.focus();\n }\n },\n [focusOnHighlight, indexPositions, onHighlight],\n );\n\n const nextFocusableItemIdx = useCallback(\n (\n direction: NavigationDirection = \"FWD\",\n idx = direction === \"FWD\" ? -1 : indexPositions.length,\n ) => {\n let nextIdx = nextItemIdx(\n indexPositions.length,\n direction,\n idx,\n cycleFocus,\n );\n while (\n ((direction === \"FWD\" && nextIdx < indexPositions.length) ||\n (direction === \"BWD\" && nextIdx > 0)) &&\n !isFocusable(indexPositions[nextIdx])\n ) {\n nextIdx = nextItemIdx(\n indexPositions.length,\n direction,\n nextIdx,\n cycleFocus,\n );\n }\n return nextIdx;\n },\n [cycleFocus, indexPositions],\n );\n\n
|
|
1
|
+
{"version":3,"file":"useKeyboardNavigationPanel.js","sources":["../src/common-hooks/useKeyboardNavigationPanel.ts"],"sourcesContent":["import { useControlled } from \"@salt-ds/core\";\nimport { type KeyboardEvent, useCallback, useMemo, useRef } from \"react\";\nimport type { CollectionItem } from \"./collectionTypes\";\nimport type { NavigationHookResult, NavigationProps } from \"./navigationTypes\";\n\ntype NavigationDirection = \"FWD\" | \"BWD\";\n\nfunction nextItemIdx(\n count: number,\n direction: NavigationDirection,\n idx: number,\n cycleFocus = false,\n) {\n if (direction === \"BWD\") {\n if (idx > 0) {\n return idx - 1;\n }\n return cycleFocus ? count - 1 : idx;\n }\n if (idx === null) {\n return 0;\n }\n if (idx === count - 1) {\n return cycleFocus ? 0 : idx;\n }\n return idx + 1;\n}\n\nconst isLeaf = <Item>(item: CollectionItem<Item>): boolean =>\n !item.header && !item.childNodes;\nconst isFocusable = <Item>(item: CollectionItem<Item>) =>\n (isLeaf(item) || item.expanded !== undefined) && item.focusable !== false;\n\n// we need a way to set highlightedIdx when selection changes\nexport const useKeyboardNavigationPanel = ({\n cycleFocus = false,\n defaultHighlightedIndex: defaultHighlightedIdx = -1,\n focusOnHighlight = false,\n highlightedIndex: highlightedIdxProp,\n indexPositions,\n onHighlight,\n onKeyboardNavigation,\n}: NavigationProps): NavigationHookResult => {\n const [highlightedIdx, setHighlightedIdx, isControlledHighlighting] =\n useControlled({\n controlled: highlightedIdxProp,\n default: defaultHighlightedIdx,\n name: \"UseKeyboardNavigation\",\n });\n\n // does this belong here or should it be a method passed in?\n const keyboardNavigation = useRef(true);\n const ignoreFocus = useRef<boolean>(false);\n const setIgnoreFocus = useCallback(\n (value: boolean) => (ignoreFocus.current = value),\n [],\n );\n\n const setHighlightedIndex = useCallback(\n (idx: number) => {\n onHighlight?.(idx);\n setHighlightedIdx(idx);\n if (focusOnHighlight && idx !== -1) {\n const { id } = indexPositions[idx];\n const formField = document.getElementById(id);\n const targetEl = formField?.querySelector(\"[tabindex]\") as HTMLElement;\n setIgnoreFocus(true);\n targetEl?.focus();\n }\n },\n [focusOnHighlight, indexPositions, onHighlight, setIgnoreFocus],\n );\n\n const nextFocusableItemIdx = useCallback(\n (\n direction: NavigationDirection = \"FWD\",\n idx = direction === \"FWD\" ? -1 : indexPositions.length,\n ) => {\n let nextIdx = nextItemIdx(\n indexPositions.length,\n direction,\n idx,\n cycleFocus,\n );\n while (\n ((direction === \"FWD\" && nextIdx < indexPositions.length) ||\n (direction === \"BWD\" && nextIdx > 0)) &&\n !isFocusable(indexPositions[nextIdx])\n ) {\n nextIdx = nextItemIdx(\n indexPositions.length,\n direction,\n nextIdx,\n cycleFocus,\n );\n }\n return nextIdx;\n },\n [cycleFocus, indexPositions],\n );\n\n const handleFocus = useCallback(() => {\n if (ignoreFocus.current) {\n ignoreFocus.current = false;\n } else {\n setHighlightedIndex(nextFocusableItemIdx());\n }\n }, [nextFocusableItemIdx, setHighlightedIndex]);\n\n const navigateChildItems = useCallback(\n (e: KeyboardEvent<HTMLElement>) => {\n const direction: NavigationDirection = e.shiftKey ? \"BWD\" : \"FWD\";\n const nextIdx = nextFocusableItemIdx(direction, highlightedIdx);\n console.log(`nextFocusableItem from ${highlightedIdx} is ${nextIdx}`);\n if (nextIdx !== highlightedIdx) {\n setHighlightedIndex(nextIdx);\n // What exactly is the point of this ?\n onKeyboardNavigation?.(e, nextIdx);\n }\n },\n [\n highlightedIdx,\n nextFocusableItemIdx,\n onKeyboardNavigation,\n setHighlightedIndex,\n ],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent<HTMLElement>) => {\n if (indexPositions.length > 0 && evt.key === \"Tab\") {\n evt.preventDefault();\n evt.stopPropagation();\n keyboardNavigation.current = true;\n navigateChildItems(evt);\n }\n },\n [indexPositions, navigateChildItems],\n );\n\n const listProps = useMemo(\n () => ({\n onBlur: () => {\n // This sets highlightedIdx to -1 before a click on ListItem can effect selection\n // maybe in a timeout\n // setHighlightedIndex(-1);\n },\n onFocus: handleFocus,\n // Does this have to be capture ? We'll have to change the types\n // onKeyDownCapture: handleKeyDown,\n onKeyDown: handleKeyDown,\n onMouseDownCapture: () => {\n keyboardNavigation.current = false;\n setIgnoreFocus(true);\n },\n\n // onMouseEnter would seem less expensive but it misses some cases\n onMouseMove: () => {\n if (keyboardNavigation.current) {\n keyboardNavigation.current = false;\n }\n },\n onMouseLeave: () => {\n keyboardNavigation.current = true;\n setIgnoreFocus(false);\n setHighlightedIndex(-1);\n },\n }),\n [handleFocus, handleKeyDown, setHighlightedIndex, setIgnoreFocus],\n );\n\n return {\n focusVisible: keyboardNavigation.current ? highlightedIdx : -1,\n controlledHighlighting: isControlledHighlighting,\n highlightedIndex: highlightedIdx,\n setHighlightedIndex,\n keyboardNavigation,\n listProps,\n setIgnoreFocus,\n };\n};\n"],"names":["useControlled","useRef","useCallback","useMemo"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSelection.js","sources":["../src/common-hooks/useSelection.ts"],"sourcesContent":["import { useControlled } from \"@salt-ds/core\";\nimport {\n type KeyboardEvent,\n type MouseEvent,\n useCallback,\n useRef,\n} from \"react\";\nimport type { CollectionItem } from \"./collectionTypes\";\nimport type {\n SelectionHookProps,\n SelectionHookResult,\n SelectionStrategy,\n SingleSelectionStrategy,\n} from \"./selectionTypes\";\n\nexport const CHECKBOX = \"checkbox\";\n\nexport const GROUP_SELECTION_NONE = \"none\";\nexport const GROUP_SELECTION_SINGLE = \"single\";\nexport const GROUP_SELECTION_CASCADE = \"cascade\";\n\nexport type GroupSelectionMode = \"none\" | \"single\" | \"cascade\";\n\nconst defaultSelectionKeys = [\"Enter\", \" \"];\n\nconst isSelectable = (item?: CollectionItem<unknown>) =>\n item && item.disabled !== true && item.selectable !== false;\n\nconst byItemIndex = (\n i1: CollectionItem<unknown>,\n i2: CollectionItem<unknown>,\n) => (i1.index ?? 0) - (i2.index ?? 0);\n\nexport const groupSelectionEnabled = (\n groupSelection: GroupSelectionMode,\n): boolean => groupSelection && groupSelection !== GROUP_SELECTION_NONE;\n\nexport const useSelection = <\n Item,\n Selection extends SelectionStrategy = \"default\",\n>({\n defaultSelected,\n disableSelection = false,\n // groupSelection = GROUP_SELECTION_NONE,\n highlightedIdx,\n indexPositions,\n label = \"\",\n onSelect,\n onSelectionChange,\n selected: selectedProp,\n selectionStrategy,\n selectionKeys = defaultSelectionKeys,\n tabToSelect,\n}: SelectionHookProps<Item, Selection>): SelectionHookResult<\n Item,\n Selection\n> => {\n type collectionItem = CollectionItem<Item>;\n\n const isDeselectable = selectionStrategy === \"deselectable\";\n const isMultipleSelect = selectionStrategy === \"multiple\";\n const isExtendedSelect = selectionStrategy === \"extended\";\n\n const lastActive = useRef(-1);\n\n const isSelectionEvent = useCallback(\n (evt: KeyboardEvent) => selectionKeys.includes(evt.key),\n [selectionKeys],\n );\n\n const emptyValue = useCallback(<\n Item,\n >(): Selection extends SingleSelectionStrategy\n ? null\n : CollectionItem<Item>[] => {\n type returnType = Selection extends SingleSelectionStrategy\n ? null\n : CollectionItem<Item>[];\n return isMultipleSelect || isExtendedSelect\n ? ([] as unknown as returnType)\n : (null as returnType);\n }, [isMultipleSelect, isExtendedSelect]);\n\n const [selected, setSelected] = useControlled<\n Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[]\n >({\n controlled: selectedProp,\n default: defaultSelected ?? emptyValue(),\n name: \"UseSelection\",\n state: \"selected\",\n });\n\n const isItemSelected = useCallback(\n (item: collectionItem) => {\n return Array.isArray(selected)\n ? selected.includes(item)\n : selected === item;\n },\n [selected],\n );\n\n const selectDefault = useCallback((item: collectionItem) => item, []);\n const selectDeselectable = useCallback(\n (item: collectionItem) => (isItemSelected(item) ? null : item),\n [isItemSelected],\n );\n const selectMultiple = useCallback(\n (item: collectionItem) => {\n const nextItems = isItemSelected(item)\n ? (selected as collectionItem[]).filter((i) => i !== item)\n : (selected as collectionItem[]).concat(item);\n nextItems.sort(byItemIndex);\n return nextItems;\n },\n [isItemSelected, selected],\n );\n const selectRange = useCallback(\n (idx: number, preserveExistingSelection?: boolean) => {\n const currentSelection = preserveExistingSelection\n ? (selected as collectionItem[])\n : ([] as collectionItem[]);\n\n const [lastSelectedItem] = (selected as collectionItem[]).slice(-1);\n const lastSelectedItemIndex = lastSelectedItem\n ? indexPositions.indexOf(lastSelectedItem)\n : 0;\n\n const startRegion = Math.min(idx, lastSelectedItemIndex);\n const endRegion = Math.max(idx, lastSelectedItemIndex);\n const rangeSelection = indexPositions.slice(startRegion, endRegion + 1);\n // concat the current selection with a new selection and remove duplicates for overlaps\n const nextItems = [...new Set([...currentSelection, ...rangeSelection])];\n nextItems.sort(byItemIndex);\n return nextItems;\n },\n [indexPositions, selected],\n );\n\n const selectItemAtIndex = useCallback(\n (\n evt: any,\n idx: number,\n item: collectionItem,\n rangeSelect: boolean,\n preserveExistingSelection?: boolean,\n ) => {\n type returnType = Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[];\n let newSelected: returnType;\n if (isMultipleSelect) {\n newSelected = selectMultiple(item) as returnType;\n } else if (isExtendedSelect) {\n if (preserveExistingSelection && !rangeSelect) {\n newSelected = selectMultiple(item) as returnType;\n } else if (rangeSelect) {\n newSelected = selectRange(\n idx,\n preserveExistingSelection,\n ) as returnType;\n } else {\n newSelected = [item] as returnType;\n }\n } else if (isDeselectable) {\n newSelected = selectDeselectable(item) as returnType;\n } else {\n newSelected = selectDefault(item) as returnType;\n }\n\n if (newSelected !== selected) {\n setSelected(newSelected);\n }\n\n // We fire onSelect irrespective of whether selection changes\n onSelect?.(evt, item);\n\n if (newSelected !== selected) {\n if (onSelectionChange) {\n onSelectionChange(evt, newSelected);\n }\n }\n },\n [\n isMultipleSelect,\n isExtendedSelect,\n isDeselectable,\n selected,\n onSelect,\n selectMultiple,\n selectRange,\n selectDeselectable,\n selectDefault,\n onSelectionChange,\n ],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent) => {\n const item = indexPositions[highlightedIdx];\n if (isSelectable(item)) {\n if (isSelectionEvent(evt) || (tabToSelect && evt.key === \"Tab\")) {\n // We do not inhibit Tab behaviour, if we are selecting on Tab then we apply\n // selection as a side effect of the Tab, not as a replacement for Tabbing.\n if (evt.key !== \"Tab\") {\n evt.preventDefault();\n }\n selectItemAtIndex(\n evt,\n highlightedIdx,\n item,\n false,\n evt.ctrlKey || evt.metaKey,\n );\n if (isExtendedSelect) {\n lastActive.current = highlightedIdx;\n }\n }\n }\n },\n [\n indexPositions,\n highlightedIdx,\n isSelectionEvent,\n tabToSelect,\n selectItemAtIndex,\n isExtendedSelect,\n ],\n );\n\n const handleKeyboardNavigation = useCallback(\n (evt: KeyboardEvent, currentIndex: number) => {\n if (isExtendedSelect && evt.shiftKey) {\n const item = indexPositions[currentIndex];\n if (isSelectable(item)) {\n selectItemAtIndex(evt, currentIndex, item, true);\n }\n }\n },\n [isExtendedSelect, indexPositions, selectItemAtIndex],\n );\n\n const handleClick = useCallback(\n (evt: MouseEvent) => {\n const item = indexPositions[highlightedIdx];\n if (!disableSelection && isSelectable(item)) {\n // if (!isCollapsibleItem(item)) {\n evt.preventDefault();\n evt.stopPropagation();\n selectItemAtIndex(\n evt,\n highlightedIdx,\n item,\n evt.shiftKey,\n evt.ctrlKey || evt.metaKey,\n );\n if (isExtendedSelect) {\n lastActive.current = highlightedIdx;\n }\n // }\n }\n },\n [\n disableSelection,\n isExtendedSelect,\n highlightedIdx,\n indexPositions,\n selectItemAtIndex,\n ],\n );\n\n const listHandlers = {\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onKeyboardNavigation: handleKeyboardNavigation,\n };\n\n return {\n listHandlers,\n selected,\n setSelected,\n };\n};\n"],"names":["useRef","useCallback","useControlled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useSelection.js","sources":["../src/common-hooks/useSelection.ts"],"sourcesContent":["import { useControlled } from \"@salt-ds/core\";\nimport {\n type KeyboardEvent,\n type MouseEvent,\n type SyntheticEvent,\n useCallback,\n useRef,\n} from \"react\";\nimport type { CollectionItem } from \"./collectionTypes\";\nimport type {\n SelectionHookProps,\n SelectionHookResult,\n SelectionStrategy,\n SingleSelectionStrategy,\n} from \"./selectionTypes\";\n\nexport const CHECKBOX = \"checkbox\";\n\nexport const GROUP_SELECTION_NONE = \"none\";\nexport const GROUP_SELECTION_SINGLE = \"single\";\nexport const GROUP_SELECTION_CASCADE = \"cascade\";\n\nexport type GroupSelectionMode = \"none\" | \"single\" | \"cascade\";\n\nconst defaultSelectionKeys = [\"Enter\", \" \"];\n\nconst isSelectable = (item?: CollectionItem<unknown>) =>\n item && item.disabled !== true && item.selectable !== false;\n\nconst byItemIndex = (\n i1: CollectionItem<unknown>,\n i2: CollectionItem<unknown>,\n) => (i1.index ?? 0) - (i2.index ?? 0);\n\nexport const groupSelectionEnabled = (\n groupSelection: GroupSelectionMode,\n): boolean => groupSelection && groupSelection !== GROUP_SELECTION_NONE;\n\nexport const useSelection = <\n Item,\n Selection extends SelectionStrategy = \"default\",\n>({\n defaultSelected,\n disableSelection = false,\n // groupSelection = GROUP_SELECTION_NONE,\n highlightedIdx,\n indexPositions,\n label: _label = \"\",\n onSelect,\n onSelectionChange,\n selected: selectedProp,\n selectionStrategy,\n selectionKeys = defaultSelectionKeys,\n tabToSelect,\n}: SelectionHookProps<Item, Selection>): SelectionHookResult<\n Item,\n Selection\n> => {\n type collectionItem = CollectionItem<Item>;\n\n const isDeselectable = selectionStrategy === \"deselectable\";\n const isMultipleSelect = selectionStrategy === \"multiple\";\n const isExtendedSelect = selectionStrategy === \"extended\";\n\n const lastActive = useRef(-1);\n\n const isSelectionEvent = useCallback(\n (evt: KeyboardEvent) => selectionKeys.includes(evt.key),\n [selectionKeys],\n );\n\n const emptyValue = useCallback(<\n Item,\n >(): Selection extends SingleSelectionStrategy\n ? null\n : CollectionItem<Item>[] => {\n type returnType = Selection extends SingleSelectionStrategy\n ? null\n : CollectionItem<Item>[];\n return isMultipleSelect || isExtendedSelect\n ? ([] as unknown as returnType)\n : (null as returnType);\n }, [isMultipleSelect, isExtendedSelect]);\n\n const [selected, setSelected] = useControlled<\n Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[]\n >({\n controlled: selectedProp,\n default: defaultSelected ?? emptyValue(),\n name: \"UseSelection\",\n state: \"selected\",\n });\n\n const isItemSelected = useCallback(\n (item: collectionItem) => {\n return Array.isArray(selected)\n ? selected.includes(item)\n : selected === item;\n },\n [selected],\n );\n\n const selectDefault = useCallback((item: collectionItem) => item, []);\n const selectDeselectable = useCallback(\n (item: collectionItem) => (isItemSelected(item) ? null : item),\n [isItemSelected],\n );\n const selectMultiple = useCallback(\n (item: collectionItem) => {\n const nextItems = isItemSelected(item)\n ? (selected as collectionItem[]).filter((i) => i !== item)\n : (selected as collectionItem[]).concat(item);\n nextItems.sort(byItemIndex);\n return nextItems;\n },\n [isItemSelected, selected],\n );\n const selectRange = useCallback(\n (idx: number, preserveExistingSelection?: boolean) => {\n const currentSelection = preserveExistingSelection\n ? (selected as collectionItem[])\n : ([] as collectionItem[]);\n\n const [lastSelectedItem] = (selected as collectionItem[]).slice(-1);\n const lastSelectedItemIndex = lastSelectedItem\n ? indexPositions.indexOf(lastSelectedItem)\n : 0;\n\n const startRegion = Math.min(idx, lastSelectedItemIndex);\n const endRegion = Math.max(idx, lastSelectedItemIndex);\n const rangeSelection = indexPositions.slice(startRegion, endRegion + 1);\n // concat the current selection with a new selection and remove duplicates for overlaps\n const nextItems = [...new Set([...currentSelection, ...rangeSelection])];\n nextItems.sort(byItemIndex);\n return nextItems;\n },\n [indexPositions, selected],\n );\n\n const selectItemAtIndex = useCallback(\n (\n evt: SyntheticEvent,\n idx: number,\n item: collectionItem,\n rangeSelect: boolean,\n preserveExistingSelection?: boolean,\n ) => {\n type returnType = Selection extends SingleSelectionStrategy\n ? CollectionItem<Item> | null\n : CollectionItem<Item>[];\n let newSelected: returnType;\n if (isMultipleSelect) {\n newSelected = selectMultiple(item) as returnType;\n } else if (isExtendedSelect) {\n if (preserveExistingSelection && !rangeSelect) {\n newSelected = selectMultiple(item) as returnType;\n } else if (rangeSelect) {\n newSelected = selectRange(\n idx,\n preserveExistingSelection,\n ) as returnType;\n } else {\n newSelected = [item] as returnType;\n }\n } else if (isDeselectable) {\n newSelected = selectDeselectable(item) as returnType;\n } else {\n newSelected = selectDefault(item) as returnType;\n }\n\n if (newSelected !== selected) {\n setSelected(newSelected);\n }\n\n // We fire onSelect irrespective of whether selection changes\n onSelect?.(evt, item);\n\n if (newSelected !== selected) {\n if (onSelectionChange) {\n onSelectionChange(evt, newSelected);\n }\n }\n },\n [\n isMultipleSelect,\n isExtendedSelect,\n isDeselectable,\n selected,\n onSelect,\n selectMultiple,\n selectRange,\n selectDeselectable,\n selectDefault,\n onSelectionChange,\n ],\n );\n\n const handleKeyDown = useCallback(\n (evt: KeyboardEvent) => {\n const item = indexPositions[highlightedIdx];\n if (isSelectable(item)) {\n if (isSelectionEvent(evt) || (tabToSelect && evt.key === \"Tab\")) {\n // We do not inhibit Tab behaviour, if we are selecting on Tab then we apply\n // selection as a side effect of the Tab, not as a replacement for Tabbing.\n if (evt.key !== \"Tab\") {\n evt.preventDefault();\n }\n selectItemAtIndex(\n evt,\n highlightedIdx,\n item,\n false,\n evt.ctrlKey || evt.metaKey,\n );\n if (isExtendedSelect) {\n lastActive.current = highlightedIdx;\n }\n }\n }\n },\n [\n indexPositions,\n highlightedIdx,\n isSelectionEvent,\n tabToSelect,\n selectItemAtIndex,\n isExtendedSelect,\n ],\n );\n\n const handleKeyboardNavigation = useCallback(\n (evt: KeyboardEvent, currentIndex: number) => {\n if (isExtendedSelect && evt.shiftKey) {\n const item = indexPositions[currentIndex];\n if (isSelectable(item)) {\n selectItemAtIndex(evt, currentIndex, item, true);\n }\n }\n },\n [isExtendedSelect, indexPositions, selectItemAtIndex],\n );\n\n const handleClick = useCallback(\n (evt: MouseEvent) => {\n const item = indexPositions[highlightedIdx];\n if (!disableSelection && isSelectable(item)) {\n // if (!isCollapsibleItem(item)) {\n evt.preventDefault();\n evt.stopPropagation();\n selectItemAtIndex(\n evt,\n highlightedIdx,\n item,\n evt.shiftKey,\n evt.ctrlKey || evt.metaKey,\n );\n if (isExtendedSelect) {\n lastActive.current = highlightedIdx;\n }\n // }\n }\n },\n [\n disableSelection,\n isExtendedSelect,\n highlightedIdx,\n indexPositions,\n selectItemAtIndex,\n ],\n );\n\n const listHandlers = {\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onKeyboardNavigation: handleKeyboardNavigation,\n };\n\n return {\n listHandlers,\n selected,\n setSelected,\n };\n};\n"],"names":["useRef","useCallback","useControlled"],"mappings":"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"}
|
|
@@ -19,11 +19,11 @@ const useTypeahead = ({
|
|
|
19
19
|
if (intermediateSearch || !applyIncrementalSearch) {
|
|
20
20
|
const regex = new RegExp(`^${searchChars.current}`, "i");
|
|
21
21
|
let idx = items.findIndex(
|
|
22
|
-
({ label }, i) => i > startIdx.current && regex.test(label)
|
|
22
|
+
({ label }, i) => i > startIdx.current && label && regex.test(label)
|
|
23
23
|
);
|
|
24
24
|
if (idx === -1) {
|
|
25
25
|
idx = items.findIndex(
|
|
26
|
-
({ label }, i) => i <= startIdx.current && regex.test(label)
|
|
26
|
+
({ label }, i) => i <= startIdx.current && label && regex.test(label)
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
29
|
if (idx !== -1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTypeahead.js","sources":["../src/common-hooks/useTypeahead.ts"],"sourcesContent":["import { type KeyboardEvent, useCallback, useRef } from \"react\";\nimport type { CollectionItem } from \"./collectionTypes\";\nimport { isCharacterKey, Space } from \"./keyUtils\";\n\ninterface TypeaheadHookProps<Item> {\n disableTypeToSelect?: boolean;\n highlightedIdx: number;\n highlightItemAtIndex: (idx: number) => void;\n applyIncrementalSearch?: boolean;\n typeToNavigate: boolean;\n items: CollectionItem<Item>[];\n}\n\ninterface TypeaheadHookResult {\n onKeyDown?: (e: KeyboardEvent) => void;\n}\n\nexport const useTypeahead = <Item>({\n disableTypeToSelect,\n highlightedIdx,\n highlightItemAtIndex,\n typeToNavigate,\n items,\n applyIncrementalSearch = true,\n}: TypeaheadHookProps<Item>): TypeaheadHookResult => {\n const keyDownTimer = useRef<number | null>(null);\n const searchChars = useRef(\"\");\n const startIdx = useRef(-1);\n\n const applySearch = useCallback(\n (intermediateSearch?: true | undefined) => {\n if (intermediateSearch || !applyIncrementalSearch) {\n const regex = new RegExp(`^${searchChars.current}`, \"i\");\n let idx = items.findIndex(\n ({ label }, i) => i > startIdx.current && regex.test(label
|
|
1
|
+
{"version":3,"file":"useTypeahead.js","sources":["../src/common-hooks/useTypeahead.ts"],"sourcesContent":["import { type KeyboardEvent, useCallback, useRef } from \"react\";\nimport type { CollectionItem } from \"./collectionTypes\";\nimport { isCharacterKey, Space } from \"./keyUtils\";\n\ninterface TypeaheadHookProps<Item> {\n disableTypeToSelect?: boolean;\n highlightedIdx: number;\n highlightItemAtIndex: (idx: number) => void;\n applyIncrementalSearch?: boolean;\n typeToNavigate: boolean;\n items: CollectionItem<Item>[];\n}\n\ninterface TypeaheadHookResult {\n onKeyDown?: (e: KeyboardEvent) => void;\n}\n\nexport const useTypeahead = <Item>({\n disableTypeToSelect,\n highlightedIdx,\n highlightItemAtIndex,\n typeToNavigate,\n items,\n applyIncrementalSearch = true,\n}: TypeaheadHookProps<Item>): TypeaheadHookResult => {\n const keyDownTimer = useRef<number | null>(null);\n const searchChars = useRef(\"\");\n const startIdx = useRef(-1);\n\n const applySearch = useCallback(\n (intermediateSearch?: true | undefined) => {\n if (intermediateSearch || !applyIncrementalSearch) {\n const regex = new RegExp(`^${searchChars.current}`, \"i\");\n let idx = items.findIndex(\n ({ label }, i) => i > startIdx.current && label && regex.test(label),\n );\n if (idx === -1) {\n idx = items.findIndex(\n ({ label }, i) =>\n i <= startIdx.current && label && regex.test(label),\n );\n }\n if (idx !== -1) {\n highlightItemAtIndex(idx);\n }\n } else {\n searchChars.current = \"\";\n keyDownTimer.current = null;\n startIdx.current = -1;\n }\n },\n [applyIncrementalSearch, highlightItemAtIndex, items],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n const searchInProgress = startIdx.current !== -1;\n if (isCharacterKey(e) || (searchInProgress && e.key === Space)) {\n if (typeToNavigate) {\n e.preventDefault();\n e.stopPropagation();\n // If we type the same key repeatedly, we cycle through the matches\n if (startIdx.current === -1 || e.key === searchChars.current) {\n startIdx.current = highlightedIdx;\n }\n if (keyDownTimer.current !== null) {\n clearTimeout(keyDownTimer.current);\n keyDownTimer.current = null;\n }\n if (e.key !== searchChars.current) {\n searchChars.current += e.key;\n }\n if (applyIncrementalSearch) {\n applySearch(true);\n }\n // keyDownTimer.current = window.setTimeout(applySearch, 100);\n keyDownTimer.current = window.setTimeout(() => {\n applySearch();\n }, 100);\n }\n }\n },\n [typeToNavigate, applyIncrementalSearch, highlightedIdx, applySearch],\n );\n\n return {\n onKeyDown: disableTypeToSelect ? undefined : handleKeyDown,\n };\n};\n"],"names":["useRef","useCallback","isCharacterKey","Space"],"mappings":";;;;;AAiBO,MAAM,eAAe,CAAO;AAAA,EACjC,mBAAA;AAAA,EACA,cAAA;AAAA,EACA,oBAAA;AAAA,EACA,cAAA;AAAA,EACA,KAAA;AAAA,EACA,sBAAyB,GAAA;AAC3B,CAAqD,KAAA;AACnD,EAAM,MAAA,YAAA,GAAeA,aAAsB,IAAI,CAAA;AAC/C,EAAM,MAAA,WAAA,GAAcA,aAAO,EAAE,CAAA;AAC7B,EAAM,MAAA,QAAA,GAAWA,aAAO,EAAE,CAAA;AAE1B,EAAA,MAAM,WAAc,GAAAC,iBAAA;AAAA,IAClB,CAAC,kBAA0C,KAAA;AACzC,MAAI,IAAA,kBAAA,IAAsB,CAAC,sBAAwB,EAAA;AACjD,QAAA,MAAM,QAAQ,IAAI,MAAA,CAAO,IAAI,WAAY,CAAA,OAAO,IAAI,GAAG,CAAA;AACvD,QAAA,IAAI,MAAM,KAAM,CAAA,SAAA;AAAA,UACd,CAAC,EAAE,KAAA,EAAS,EAAA,CAAA,KAAM,CAAI,GAAA,QAAA,CAAS,OAAW,IAAA,KAAA,IAAS,KAAM,CAAA,IAAA,CAAK,KAAK;AAAA,SACrE;AACA,QAAA,IAAI,QAAQ,EAAI,EAAA;AACd,UAAA,GAAA,GAAM,KAAM,CAAA,SAAA;AAAA,YACV,CAAC,EAAE,KAAA,EAAS,EAAA,CAAA,KACV,CAAK,IAAA,QAAA,CAAS,OAAW,IAAA,KAAA,IAAS,KAAM,CAAA,IAAA,CAAK,KAAK;AAAA,WACtD;AAAA;AAEF,QAAA,IAAI,QAAQ,EAAI,EAAA;AACd,UAAA,oBAAA,CAAqB,GAAG,CAAA;AAAA;AAC1B,OACK,MAAA;AACL,QAAA,WAAA,CAAY,OAAU,GAAA,EAAA;AACtB,QAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AACvB,QAAA,QAAA,CAAS,OAAU,GAAA,EAAA;AAAA;AACrB,KACF;AAAA,IACA,CAAC,sBAAwB,EAAA,oBAAA,EAAsB,KAAK;AAAA,GACtD;AAEA,EAAA,MAAM,aAAgB,GAAAA,iBAAA;AAAA,IACpB,CAAC,CAAqB,KAAA;AACpB,MAAM,MAAA,gBAAA,GAAmB,SAAS,OAAY,KAAA,EAAA;AAC9C,MAAA,IAAIC,wBAAe,CAAC,CAAA,IAAM,gBAAoB,IAAA,CAAA,CAAE,QAAQC,cAAQ,EAAA;AAC9D,QAAoB;AAClB,UAAA,CAAA,CAAE,cAAe,EAAA;AACjB,UAAA,CAAA,CAAE,eAAgB,EAAA;AAElB,UAAA,IAAI,SAAS,OAAY,KAAA,EAAA,IAAM,CAAE,CAAA,GAAA,KAAQ,YAAY,OAAS,EAAA;AAC5D,YAAA,QAAA,CAAS,OAAU,GAAA,cAAA;AAAA;AAErB,UAAI,IAAA,YAAA,CAAa,YAAY,IAAM,EAAA;AACjC,YAAA,YAAA,CAAa,aAAa,OAAO,CAAA;AACjC,YAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AAAA;AAEzB,UAAI,IAAA,CAAA,CAAE,GAAQ,KAAA,WAAA,CAAY,OAAS,EAAA;AACjC,YAAA,WAAA,CAAY,WAAW,CAAE,CAAA,GAAA;AAAA;AAE3B,UAAA,IAAI,sBAAwB,EAAA;AAC1B,YAAA,WAAA,CAAY,IAAI,CAAA;AAAA;AAGlB,UAAa,YAAA,CAAA,OAAA,GAAU,MAAO,CAAA,UAAA,CAAW,MAAM;AAC7C,YAAY,WAAA,EAAA;AAAA,aACX,GAAG,CAAA;AAAA;AACR;AACF,KACF;AAAA,IACA,CAAC,cAAA,EAAgB,sBAAwB,EAAA,cAAA,EAAgB,WAAW;AAAA,GACtE;AAEA,EAAO,OAAA;AAAA,IACL,SAAA,EAAW,sBAAsB,MAAY,GAAA;AAAA,GAC/C;AACF;;;;"}
|
|
@@ -18,7 +18,7 @@ const getItemTop = (element, offsetContainer) => {
|
|
|
18
18
|
const { transform = "none" } = getComputedStyle(element);
|
|
19
19
|
if (transform.startsWith("matrix")) {
|
|
20
20
|
const pos = transform.lastIndexOf(",");
|
|
21
|
-
return Number.parseInt(transform.slice(pos + 1));
|
|
21
|
+
return Number.parseInt(transform.slice(pos + 1), 10);
|
|
22
22
|
}
|
|
23
23
|
let offsetParent = element.offsetParent;
|
|
24
24
|
if (offsetParent === offsetContainer || offsetContainer === null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useViewportTracking.js","sources":["../src/common-hooks/useViewportTracking.ts"],"sourcesContent":["import { useIsomorphicLayoutEffect } from \"@salt-ds/core\";\nimport {\n type MutableRefObject,\n type RefObject,\n useCallback,\n useRef,\n} from \"react\";\nimport { type ResizeHandler, useResizeObserver } from \"../responsive\";\nimport type { CollectionItem } from \"./collectionTypes\";\n\nconst HeightOnly = [\"height\"];\nconst HeightWithScroll = [\"height\", \"scrollHeight\"];\nconst EMPTY_ARRAY: any[] = [];\n\nconst ObservedDimensions = {\n containerOnly: [HeightWithScroll, EMPTY_ARRAY],\n withContent: [HeightOnly, HeightOnly],\n};\nconst getObservedDimensions = (containerOnly: boolean) =>\n containerOnly\n ? ObservedDimensions.containerOnly\n : ObservedDimensions.withContent;\n\nconst NULL_REF = { current: null };\n\nconst getItemTop = (\n element: HTMLElement,\n offsetContainer: HTMLElement | null,\n) => {\n const { transform = \"none\" } = getComputedStyle(element);\n if (transform.startsWith(\"matrix\")) {\n const pos = transform.lastIndexOf(\",\");\n return Number.parseInt(transform.slice(pos + 1));\n }\n let offsetParent = element.offsetParent as HTMLElement;\n if (offsetParent === offsetContainer || offsetContainer === null) {\n return element.offsetTop;\n }\n let top = element.offsetTop;\n while (offsetParent !== null && offsetParent !== offsetContainer) {\n top += offsetParent.offsetTop;\n offsetParent = offsetParent.offsetParent as HTMLElement;\n }\n return top;\n};\n\nexport interface ViewportTrackingProps<Item> {\n containerRef: RefObject<HTMLElement>;\n contentRef?: RefObject<HTMLElement>;\n highlightedIdx?: number;\n indexPositions: CollectionItem<Item>[];\n stickyHeaders?: boolean;\n}\n\nexport interface ViewportTrackingResult<Item> {\n isScrolling: MutableRefObject<boolean>;\n scrollIntoView: (item: CollectionItem<Item>) => void;\n}\n\nexport const useViewportTracking = <Item>({\n containerRef,\n contentRef = NULL_REF,\n highlightedIdx = -1,\n indexPositions,\n stickyHeaders = false,\n}: ViewportTrackingProps<Item>): ViewportTrackingResult<Item> => {\n const scrolling = useRef<boolean>(false);\n const viewport = useRef({\n height: 0,\n contentHeight: 0,\n });\n\n const scrollTo = useCallback(\n (scrollPos: number) => {\n scrolling.current = true;\n if (containerRef.current) {\n containerRef.current.scrollTop = scrollPos;\n }\n setTimeout(() => {\n scrolling.current = false;\n });\n },\n [containerRef],\n );\n\n const scrollToStart = useCallback(() => scrollTo(0), [scrollTo]);\n\n const scrollToEnd = useCallback(() => {\n scrollTo(viewport.current.contentHeight - viewport.current.height);\n }, [scrollTo]);\n\n const scrollIntoViewIfNeeded = useCallback(\n (item: CollectionItem<Item>) => {\n const offsetContainer = contentRef.current || containerRef.current;\n if (item.id) {\n const el = document.getElementById(item.id);\n if (el && containerRef.current) {\n const { height: viewportHeight } = viewport.current;\n const targetEl =\n el.ariaExpanded && el.firstChild\n ? (el.firstChild as HTMLElement)\n : el;\n const headerHeight = stickyHeaders ? 36 : 0;\n const itemTop = getItemTop(targetEl, offsetContainer);\n const itemHeight = targetEl.offsetHeight;\n const { scrollTop } = containerRef.current;\n const viewportStart = scrollTop + headerHeight;\n const viewportEnd = viewportStart + viewportHeight - headerHeight;\n\n if (itemTop + itemHeight > viewportEnd || itemTop < viewportStart) {\n const newScrollTop =\n itemTop + itemHeight > viewportEnd\n ? scrollTop + (itemTop + itemHeight) - viewportEnd\n : itemTop - headerHeight;\n\n scrollTo(newScrollTop);\n }\n }\n }\n },\n [containerRef, contentRef, scrollTo, stickyHeaders],\n );\n\n useIsomorphicLayoutEffect(() => {\n const { height, contentHeight } = viewport.current;\n const item = indexPositions[highlightedIdx];\n if (contentHeight > height && item) {\n const [firstItem] = indexPositions;\n const [lastItem] = indexPositions.slice(-1);\n if (item === firstItem) {\n scrollToStart();\n } else if (item === lastItem) {\n scrollToEnd();\n } else {\n scrollIntoViewIfNeeded(indexPositions[highlightedIdx]);\n }\n }\n }, [\n highlightedIdx,\n indexPositions,\n scrollIntoViewIfNeeded,\n scrollToEnd,\n scrollToStart,\n ]);\n\n const onContainerResize: ResizeHandler = useCallback(\n ({ height, scrollHeight }) => {\n if (typeof height === \"number\") {\n viewport.current.height = height;\n }\n if (typeof scrollHeight === \"number\") {\n viewport.current.contentHeight = scrollHeight;\n }\n },\n [],\n );\n\n const onContentResize: ResizeHandler = useCallback(({ height }) => {\n if (typeof height === \"number\") {\n viewport.current.contentHeight = height;\n }\n }, []);\n\n // If we only have a container, then we will observe its height and scrollHeight,\n // contentRef will be null, so second call to observer will observe nothing.\n // If we have both container and content, then we observe the height of each.\n const [containerDimensions, contentDimensions] = getObservedDimensions(\n contentRef === NULL_REF,\n );\n useResizeObserver(containerRef, containerDimensions, onContainerResize, true);\n useResizeObserver(contentRef, contentDimensions, onContentResize, true);\n\n return {\n isScrolling: scrolling,\n scrollIntoView: scrollIntoViewIfNeeded,\n };\n};\n"],"names":["useRef","useCallback","useIsomorphicLayoutEffect","useResizeObserver"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useViewportTracking.js","sources":["../src/common-hooks/useViewportTracking.ts"],"sourcesContent":["import { useIsomorphicLayoutEffect } from \"@salt-ds/core\";\nimport {\n type MutableRefObject,\n type RefObject,\n useCallback,\n useRef,\n} from \"react\";\nimport { type ResizeHandler, useResizeObserver } from \"../responsive\";\nimport type { CollectionItem } from \"./collectionTypes\";\n\nconst HeightOnly = [\"height\"];\nconst HeightWithScroll = [\"height\", \"scrollHeight\"];\nconst EMPTY_ARRAY: string[] = [];\n\nconst ObservedDimensions = {\n containerOnly: [HeightWithScroll, EMPTY_ARRAY],\n withContent: [HeightOnly, HeightOnly],\n};\nconst getObservedDimensions = (containerOnly: boolean) =>\n containerOnly\n ? ObservedDimensions.containerOnly\n : ObservedDimensions.withContent;\n\nconst NULL_REF = { current: null };\n\nconst getItemTop = (\n element: HTMLElement,\n offsetContainer: HTMLElement | null,\n) => {\n const { transform = \"none\" } = getComputedStyle(element);\n if (transform.startsWith(\"matrix\")) {\n const pos = transform.lastIndexOf(\",\");\n return Number.parseInt(transform.slice(pos + 1), 10);\n }\n let offsetParent = element.offsetParent as HTMLElement;\n if (offsetParent === offsetContainer || offsetContainer === null) {\n return element.offsetTop;\n }\n let top = element.offsetTop;\n while (offsetParent !== null && offsetParent !== offsetContainer) {\n top += offsetParent.offsetTop;\n offsetParent = offsetParent.offsetParent as HTMLElement;\n }\n return top;\n};\n\nexport interface ViewportTrackingProps<Item> {\n containerRef: RefObject<HTMLElement>;\n contentRef?: RefObject<HTMLElement>;\n highlightedIdx?: number;\n indexPositions: CollectionItem<Item>[];\n stickyHeaders?: boolean;\n}\n\nexport interface ViewportTrackingResult<Item> {\n isScrolling: MutableRefObject<boolean>;\n scrollIntoView: (item: CollectionItem<Item>) => void;\n}\n\nexport const useViewportTracking = <Item>({\n containerRef,\n contentRef = NULL_REF,\n highlightedIdx = -1,\n indexPositions,\n stickyHeaders = false,\n}: ViewportTrackingProps<Item>): ViewportTrackingResult<Item> => {\n const scrolling = useRef<boolean>(false);\n const viewport = useRef({\n height: 0,\n contentHeight: 0,\n });\n\n const scrollTo = useCallback(\n (scrollPos: number) => {\n scrolling.current = true;\n if (containerRef.current) {\n containerRef.current.scrollTop = scrollPos;\n }\n setTimeout(() => {\n scrolling.current = false;\n });\n },\n [containerRef],\n );\n\n const scrollToStart = useCallback(() => scrollTo(0), [scrollTo]);\n\n const scrollToEnd = useCallback(() => {\n scrollTo(viewport.current.contentHeight - viewport.current.height);\n }, [scrollTo]);\n\n const scrollIntoViewIfNeeded = useCallback(\n (item: CollectionItem<Item>) => {\n const offsetContainer = contentRef.current || containerRef.current;\n if (item.id) {\n const el = document.getElementById(item.id);\n if (el && containerRef.current) {\n const { height: viewportHeight } = viewport.current;\n const targetEl =\n el.ariaExpanded && el.firstChild\n ? (el.firstChild as HTMLElement)\n : el;\n const headerHeight = stickyHeaders ? 36 : 0;\n const itemTop = getItemTop(targetEl, offsetContainer);\n const itemHeight = targetEl.offsetHeight;\n const { scrollTop } = containerRef.current;\n const viewportStart = scrollTop + headerHeight;\n const viewportEnd = viewportStart + viewportHeight - headerHeight;\n\n if (itemTop + itemHeight > viewportEnd || itemTop < viewportStart) {\n const newScrollTop =\n itemTop + itemHeight > viewportEnd\n ? scrollTop + (itemTop + itemHeight) - viewportEnd\n : itemTop - headerHeight;\n\n scrollTo(newScrollTop);\n }\n }\n }\n },\n [containerRef, contentRef, scrollTo, stickyHeaders],\n );\n\n useIsomorphicLayoutEffect(() => {\n const { height, contentHeight } = viewport.current;\n const item = indexPositions[highlightedIdx];\n if (contentHeight > height && item) {\n const [firstItem] = indexPositions;\n const [lastItem] = indexPositions.slice(-1);\n if (item === firstItem) {\n scrollToStart();\n } else if (item === lastItem) {\n scrollToEnd();\n } else {\n scrollIntoViewIfNeeded(indexPositions[highlightedIdx]);\n }\n }\n }, [\n highlightedIdx,\n indexPositions,\n scrollIntoViewIfNeeded,\n scrollToEnd,\n scrollToStart,\n ]);\n\n const onContainerResize: ResizeHandler = useCallback(\n ({ height, scrollHeight }) => {\n if (typeof height === \"number\") {\n viewport.current.height = height;\n }\n if (typeof scrollHeight === \"number\") {\n viewport.current.contentHeight = scrollHeight;\n }\n },\n [],\n );\n\n const onContentResize: ResizeHandler = useCallback(({ height }) => {\n if (typeof height === \"number\") {\n viewport.current.contentHeight = height;\n }\n }, []);\n\n // If we only have a container, then we will observe its height and scrollHeight,\n // contentRef will be null, so second call to observer will observe nothing.\n // If we have both container and content, then we observe the height of each.\n const [containerDimensions, contentDimensions] = getObservedDimensions(\n contentRef === NULL_REF,\n );\n useResizeObserver(containerRef, containerDimensions, onContainerResize, true);\n useResizeObserver(contentRef, contentDimensions, onContentResize, true);\n\n return {\n isScrolling: scrolling,\n scrollIntoView: scrollIntoViewIfNeeded,\n };\n};\n"],"names":["useRef","useCallback","useIsomorphicLayoutEffect","useResizeObserver"],"mappings":"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"}
|