@salt-ds/core 1.71.0 → 1.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +82 -0
- package/css/salt-core.css +189 -77
- package/dist-cjs/accordion/AccordionHeader.css.js +1 -1
- package/dist-cjs/avatar/Avatar.css.js +1 -1
- package/dist-cjs/badge/Badge.css.js +1 -1
- package/dist-cjs/banner/Banner.css.js +1 -1
- package/dist-cjs/breadcrumbs/Breadcrumb.css.js +1 -1
- package/dist-cjs/breadcrumbs/Breadcrumbs.css.js +1 -1
- package/dist-cjs/checkbox/Checkbox.css.js +1 -1
- package/dist-cjs/checkbox/CheckboxIcon.css.js +1 -1
- package/dist-cjs/combo-box/ComboBox.js +18 -36
- package/dist-cjs/combo-box/ComboBox.js.map +1 -1
- package/dist-cjs/combo-box/useComboBox.js +21 -21
- package/dist-cjs/combo-box/useComboBox.js.map +1 -1
- package/dist-cjs/dropdown/Dropdown.js +29 -30
- package/dist-cjs/dropdown/Dropdown.js.map +1 -1
- package/dist-cjs/file-drop-zone/FileDropZone.css.js +1 -1
- package/dist-cjs/form-field/FormField.css.js +1 -1
- package/dist-cjs/form-field/FormFieldHelperText.css.js +1 -1
- package/dist-cjs/form-field/FormFieldLabel.css.js +1 -1
- package/dist-cjs/form-field/FormFieldLabel.js +1 -1
- package/dist-cjs/form-field/FormFieldLabel.js.map +1 -1
- package/dist-cjs/index.js +2 -0
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/input/Input.css.js +1 -1
- package/dist-cjs/interactable-card/InteractableCard.css.js +1 -1
- package/dist-cjs/interactable-card/InteractableCard.js +18 -7
- package/dist-cjs/interactable-card/InteractableCard.js.map +1 -1
- package/dist-cjs/interactable-card/InteractableCardGroup.js +71 -39
- package/dist-cjs/interactable-card/InteractableCardGroup.js.map +1 -1
- package/dist-cjs/interactable-card/InteractableCardGroupContext.js.map +1 -1
- package/dist-cjs/interactable-card/useInteractableCard.js +2 -3
- package/dist-cjs/interactable-card/useInteractableCard.js.map +1 -1
- package/dist-cjs/kbd/Kbd.css.js +1 -1
- package/dist-cjs/link/Link.css.js +1 -1
- package/dist-cjs/list-box/ListBox.js +19 -26
- package/dist-cjs/list-box/ListBox.js.map +1 -1
- package/dist-cjs/list-control/ListControlNavigationKeys.js +74 -0
- package/dist-cjs/list-control/ListControlNavigationKeys.js.map +1 -0
- package/dist-cjs/list-control/ListControlOptionContext.js +47 -0
- package/dist-cjs/list-control/ListControlOptionContext.js.map +1 -0
- package/dist-cjs/list-control/ListControlOptionStore.js +159 -0
- package/dist-cjs/list-control/ListControlOptionStore.js.map +1 -0
- package/dist-cjs/list-control/ListControlProvider.js +39 -0
- package/dist-cjs/list-control/ListControlProvider.js.map +1 -0
- package/dist-cjs/list-control/ListControlRegistry.js +161 -0
- package/dist-cjs/list-control/ListControlRegistry.js.map +1 -0
- package/dist-cjs/list-control/ListControlState.js +137 -109
- package/dist-cjs/list-control/ListControlState.js.map +1 -1
- package/dist-cjs/mega-menu/MegaMenuGroupHeading.css.js +1 -1
- package/dist-cjs/mega-menu/MegaMenuListItem.css.js +1 -1
- package/dist-cjs/menu/MenuGroup.css.js +1 -1
- package/dist-cjs/menu/MenuItem.css.js +1 -1
- package/dist-cjs/navigation-item/NavigationItem.css.js +1 -1
- package/dist-cjs/number-input/NumberInput.js +2 -2
- package/dist-cjs/number-input/NumberInput.js.map +1 -1
- package/dist-cjs/option/Option.js +58 -39
- package/dist-cjs/option/Option.js.map +1 -1
- package/dist-cjs/option/OptionGroup.css.js +1 -1
- package/dist-cjs/overlay/Overlay.js +12 -2
- package/dist-cjs/overlay/Overlay.js.map +1 -1
- package/dist-cjs/overlay/OverlayContext.js +6 -0
- package/dist-cjs/overlay/OverlayContext.js.map +1 -1
- package/dist-cjs/overlay/OverlayFooter.css.js +6 -0
- package/dist-cjs/overlay/OverlayFooter.css.js.map +1 -0
- package/dist-cjs/overlay/OverlayFooter.js +30 -0
- package/dist-cjs/overlay/OverlayFooter.js.map +1 -0
- package/dist-cjs/overlay/OverlayHeader.css.js +1 -1
- package/dist-cjs/overlay/OverlayHeader.js +51 -11
- package/dist-cjs/overlay/OverlayHeader.js.map +1 -1
- package/dist-cjs/overlay/OverlayPanel.css.js +1 -1
- package/dist-cjs/overlay/OverlayPanel.js +20 -7
- package/dist-cjs/overlay/OverlayPanel.js.map +1 -1
- package/dist-cjs/overlay/OverlayPanelContent.css.js +1 -1
- package/dist-cjs/overlay/OverlayPanelContent.js +11 -13
- package/dist-cjs/overlay/OverlayPanelContent.js.map +1 -1
- package/dist-cjs/overlay/hasOverlaySection.js +24 -0
- package/dist-cjs/overlay/hasOverlaySection.js.map +1 -0
- package/dist-cjs/pill-input/PillInput.css.js +1 -1
- package/dist-cjs/pill-input/PillInput.js +2 -2
- package/dist-cjs/pill-input/PillInput.js.map +1 -1
- package/dist-cjs/radio-button/RadioButton.css.js +1 -1
- package/dist-cjs/radio-button/RadioButtonIcon.css.js +1 -1
- package/dist-cjs/rating/Rating.css.js +1 -1
- package/dist-cjs/slider/internal/SliderTrack.css.js +1 -1
- package/dist-cjs/stepper/internal/StepText.css.js +1 -1
- package/dist-cjs/switch/Switch.css.js +1 -1
- package/dist-cjs/table/Table.css.js +1 -1
- package/dist-cjs/tag/Tag.css.js +1 -1
- package/dist-cjs/text/Text.css.js +1 -1
- package/dist-cjs/toast/Toast.css.js +1 -1
- package/dist-cjs/toggle-button/ToggleButton.js +8 -2
- package/dist-cjs/toggle-button/ToggleButton.js.map +1 -1
- package/dist-cjs/toggle-button-group/ToggleButtonGroup.js +71 -8
- package/dist-cjs/toggle-button-group/ToggleButtonGroup.js.map +1 -1
- package/dist-cjs/toggle-button-group/ToggleButtonGroupContext.js.map +1 -1
- package/dist-cjs/toggletip/ToggletipPanel.css.js +1 -1
- package/dist-cjs/tooltip/Tooltip.css.js +1 -1
- package/dist-cjs/vertical-navigation/VerticalNavigationItemContent.css.js +1 -1
- package/dist-cjs/vertical-navigation/VerticalNavigationSubMenu.css.js +1 -1
- package/dist-es/accordion/AccordionHeader.css.js +1 -1
- package/dist-es/avatar/Avatar.css.js +1 -1
- package/dist-es/badge/Badge.css.js +1 -1
- package/dist-es/banner/Banner.css.js +1 -1
- package/dist-es/breadcrumbs/Breadcrumb.css.js +1 -1
- package/dist-es/breadcrumbs/Breadcrumbs.css.js +1 -1
- package/dist-es/checkbox/Checkbox.css.js +1 -1
- package/dist-es/checkbox/CheckboxIcon.css.js +1 -1
- package/dist-es/combo-box/ComboBox.js +18 -36
- package/dist-es/combo-box/ComboBox.js.map +1 -1
- package/dist-es/combo-box/useComboBox.js +21 -21
- package/dist-es/combo-box/useComboBox.js.map +1 -1
- package/dist-es/dropdown/Dropdown.js +29 -30
- package/dist-es/dropdown/Dropdown.js.map +1 -1
- package/dist-es/file-drop-zone/FileDropZone.css.js +1 -1
- package/dist-es/form-field/FormField.css.js +1 -1
- package/dist-es/form-field/FormFieldHelperText.css.js +1 -1
- package/dist-es/form-field/FormFieldLabel.css.js +1 -1
- package/dist-es/form-field/FormFieldLabel.js +1 -1
- package/dist-es/form-field/FormFieldLabel.js.map +1 -1
- package/dist-es/index.js +1 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/input/Input.css.js +1 -1
- package/dist-es/interactable-card/InteractableCard.css.js +1 -1
- package/dist-es/interactable-card/InteractableCard.js +18 -7
- package/dist-es/interactable-card/InteractableCard.js.map +1 -1
- package/dist-es/interactable-card/InteractableCardGroup.js +72 -40
- package/dist-es/interactable-card/InteractableCardGroup.js.map +1 -1
- package/dist-es/interactable-card/InteractableCardGroupContext.js.map +1 -1
- package/dist-es/interactable-card/useInteractableCard.js +2 -3
- package/dist-es/interactable-card/useInteractableCard.js.map +1 -1
- package/dist-es/kbd/Kbd.css.js +1 -1
- package/dist-es/link/Link.css.js +1 -1
- package/dist-es/list-box/ListBox.js +19 -26
- package/dist-es/list-box/ListBox.js.map +1 -1
- package/dist-es/list-control/ListControlNavigationKeys.js +69 -0
- package/dist-es/list-control/ListControlNavigationKeys.js.map +1 -0
- package/dist-es/list-control/ListControlOptionContext.js +44 -0
- package/dist-es/list-control/ListControlOptionContext.js.map +1 -0
- package/dist-es/list-control/ListControlOptionStore.js +153 -0
- package/dist-es/list-control/ListControlOptionStore.js.map +1 -0
- package/dist-es/list-control/ListControlProvider.js +37 -0
- package/dist-es/list-control/ListControlProvider.js.map +1 -0
- package/dist-es/list-control/ListControlRegistry.js +158 -0
- package/dist-es/list-control/ListControlRegistry.js.map +1 -0
- package/dist-es/list-control/ListControlState.js +137 -110
- package/dist-es/list-control/ListControlState.js.map +1 -1
- package/dist-es/mega-menu/MegaMenuGroupHeading.css.js +1 -1
- package/dist-es/mega-menu/MegaMenuListItem.css.js +1 -1
- package/dist-es/menu/MenuGroup.css.js +1 -1
- package/dist-es/menu/MenuItem.css.js +1 -1
- package/dist-es/navigation-item/NavigationItem.css.js +1 -1
- package/dist-es/number-input/NumberInput.js +2 -2
- package/dist-es/number-input/NumberInput.js.map +1 -1
- package/dist-es/option/Option.js +59 -40
- package/dist-es/option/Option.js.map +1 -1
- package/dist-es/option/OptionGroup.css.js +1 -1
- package/dist-es/overlay/Overlay.js +13 -3
- package/dist-es/overlay/Overlay.js.map +1 -1
- package/dist-es/overlay/OverlayContext.js +6 -0
- package/dist-es/overlay/OverlayContext.js.map +1 -1
- package/dist-es/overlay/OverlayFooter.css.js +4 -0
- package/dist-es/overlay/OverlayFooter.css.js.map +1 -0
- package/dist-es/overlay/OverlayFooter.js +28 -0
- package/dist-es/overlay/OverlayFooter.js.map +1 -0
- package/dist-es/overlay/OverlayHeader.css.js +1 -1
- package/dist-es/overlay/OverlayHeader.js +51 -11
- package/dist-es/overlay/OverlayHeader.js.map +1 -1
- package/dist-es/overlay/OverlayPanel.css.js +1 -1
- package/dist-es/overlay/OverlayPanel.js +20 -7
- package/dist-es/overlay/OverlayPanel.js.map +1 -1
- package/dist-es/overlay/OverlayPanelContent.css.js +1 -1
- package/dist-es/overlay/OverlayPanelContent.js +11 -13
- package/dist-es/overlay/OverlayPanelContent.js.map +1 -1
- package/dist-es/overlay/hasOverlaySection.js +22 -0
- package/dist-es/overlay/hasOverlaySection.js.map +1 -0
- package/dist-es/pill-input/PillInput.css.js +1 -1
- package/dist-es/pill-input/PillInput.js +2 -2
- package/dist-es/pill-input/PillInput.js.map +1 -1
- package/dist-es/radio-button/RadioButton.css.js +1 -1
- package/dist-es/radio-button/RadioButtonIcon.css.js +1 -1
- package/dist-es/rating/Rating.css.js +1 -1
- package/dist-es/slider/internal/SliderTrack.css.js +1 -1
- package/dist-es/stepper/internal/StepText.css.js +1 -1
- package/dist-es/switch/Switch.css.js +1 -1
- package/dist-es/table/Table.css.js +1 -1
- package/dist-es/tag/Tag.css.js +1 -1
- package/dist-es/text/Text.css.js +1 -1
- package/dist-es/toast/Toast.css.js +1 -1
- package/dist-es/toggle-button/ToggleButton.js +8 -2
- package/dist-es/toggle-button/ToggleButton.js.map +1 -1
- package/dist-es/toggle-button-group/ToggleButtonGroup.js +71 -8
- package/dist-es/toggle-button-group/ToggleButtonGroup.js.map +1 -1
- package/dist-es/toggle-button-group/ToggleButtonGroupContext.js.map +1 -1
- package/dist-es/toggletip/ToggletipPanel.css.js +1 -1
- package/dist-es/tooltip/Tooltip.css.js +1 -1
- package/dist-es/vertical-navigation/VerticalNavigationItemContent.css.js +1 -1
- package/dist-es/vertical-navigation/VerticalNavigationSubMenu.css.js +1 -1
- package/dist-types/combo-box/useComboBox.d.ts +3 -6
- package/dist-types/interactable-card/InteractableCardGroupContext.d.ts +2 -0
- package/dist-types/interactable-card/useInteractableCard.d.ts +1 -2
- package/dist-types/list-control/ListControlNavigationKeys.d.ts +30 -0
- package/dist-types/list-control/ListControlOptionContext.d.ts +18 -0
- package/dist-types/list-control/ListControlOptionStore.d.ts +17 -0
- package/dist-types/list-control/ListControlProvider.d.ts +11 -0
- package/dist-types/list-control/ListControlRegistry.d.ts +22 -0
- package/dist-types/list-control/ListControlState.d.ts +6 -6
- package/dist-types/option/Option.d.ts +3 -1
- package/dist-types/overlay/Overlay.d.ts +2 -1
- package/dist-types/overlay/OverlayContext.d.ts +4 -0
- package/dist-types/overlay/OverlayFooter.d.ts +4 -0
- package/dist-types/overlay/hasOverlaySection.d.ts +2 -0
- package/dist-types/overlay/index.d.ts +1 -0
- package/dist-types/toggle-button-group/ToggleButtonGroupContext.d.ts +2 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListBox.js","sources":["../src/list-box/ListBox.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type FocusEvent,\n type ForwardedRef,\n forwardRef,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n useRef,\n} from \"react\";\nimport {\n ListControlContext,\n type OptionValue,\n} from \"../list-control/ListControlContext\";\nimport {\n defaultValueToString,\n type ListControlProps,\n useListControl,\n} from \"../list-control/ListControlState\";\nimport { makePrefixer, useForkRef } from \"../utils\";\n\nimport listBoxCss from \"./ListBox.css\";\n\nexport type ListBoxProps<Item = string> = {\n /**\n * If `true`, the list box will be disabled.\n */\n disabled?: boolean;\n /**\n * If `false`, the list box will have not a border.\n */\n bordered?: boolean;\n /**\n * The options to display in the list box.\n */\n children?: ReactNode;\n /**\n * If `true`, the list box will be multiselect.\n */\n multiselect?: boolean;\n} & ComponentPropsWithoutRef<\"div\"> &\n Omit<ListControlProps<Item>, \"onOpenChange\">;\n\nconst withBaseName = makePrefixer(\"saltListBox\");\n\nexport const ListBox = forwardRef(function ListBox<Item>(\n props: ListBoxProps<Item>,\n ref: ForwardedRef<HTMLDivElement>,\n) {\n const {\n bordered,\n className,\n children,\n defaultSelected,\n disabled,\n selected,\n onSelectionChange,\n multiselect,\n valueToString = defaultValueToString,\n onKeyDown,\n onFocus,\n onBlur,\n ...rest\n } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-list-box\",\n css: listBoxCss,\n window: targetWindow,\n });\n\n const listControl = useListControl<Item>({\n multiselect,\n defaultSelected,\n selected,\n onSelectionChange,\n valueToString,\n disabled,\n });\n\n const {\n activeState,\n setActive,\n getOptionAtIndex,\n getIndexOfOption,\n getOptionsMatching,\n getOptionFromSearch,\n getFirstOption,\n getLastOption,\n getOptionAfter,\n getOptionBefore,\n getOptionPageAbove,\n getOptionPageBelow,\n selectedState,\n select,\n setFocusVisibleState,\n setFocusedState,\n setListRef,\n } = listControl;\n\n const typeaheadString = useRef(\"\");\n const typeaheadTimeout = useRef<number | undefined>();\n\n const handleTypeahead = (event: KeyboardEvent<HTMLDivElement>) => {\n if (typeaheadTimeout.current) {\n clearTimeout(typeaheadTimeout.current);\n }\n typeaheadString.current += event.key;\n typeaheadTimeout.current = window.setTimeout(() => {\n typeaheadString.current = \"\";\n }, 500);\n\n let newOption = getOptionFromSearch(typeaheadString.current, activeState);\n\n if (!newOption) {\n newOption = getOptionFromSearch(typeaheadString.current);\n }\n\n if (newOption) {\n setActive(newOption);\n setFocusVisibleState(true);\n }\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey\n ) {\n event.preventDefault();\n event.stopPropagation();\n handleTypeahead(event);\n }\n\n const activeOption = activeState ?? getFirstOption()?.data;\n\n if (activeOption === undefined) {\n return;\n }\n\n let newActive:\n | { data: OptionValue<Item>; element: HTMLElement }\n | undefined;\n switch (event.key) {\n case \"ArrowDown\":\n newActive = getOptionAfter(activeOption) ?? getLastOption();\n break;\n case \"ArrowUp\":\n newActive = getOptionBefore(activeOption) ?? getFirstOption();\n break;\n case \"Home\":\n newActive = getFirstOption();\n break;\n case \"End\":\n newActive = getLastOption();\n break;\n case \"PageUp\":\n newActive = getOptionPageAbove(activeOption);\n break;\n case \"PageDown\":\n newActive = getOptionPageBelow(activeOption);\n break;\n case \"Enter\":\n case \" \":\n if (\n activeState?.disabled ||\n (typeaheadString.current.trim().length > 0 && event.key === \" \")\n ) {\n event.preventDefault();\n return;\n }\n\n if (!activeState) {\n return;\n }\n\n event.preventDefault();\n select(event, activeState);\n\n break;\n }\n\n if (newActive && newActive.data.id !== activeState?.id) {\n event.preventDefault();\n setActive(newActive.data);\n setFocusVisibleState(true);\n }\n };\n\n const wasMouseDown = useRef(false);\n\n const handleMouseDown = () => {\n wasMouseDown.current = true;\n };\n\n const handleFocus = (event: FocusEvent<HTMLDivElement>) => {\n if (wasMouseDown.current) {\n wasMouseDown.current = false;\n return;\n }\n\n setFocusVisibleState(true);\n wasMouseDown.current = false;\n\n // We check the active index because the active item may have been removed\n const activeIndex = activeState ? getIndexOfOption(activeState) : -1;\n let newActive: ReturnType<typeof getOptionAtIndex>;\n\n // If the active item is still in the list, we don't need to do anything\n if (activeIndex > 0) {\n return;\n }\n\n // If we have selected an item, we should make that the active item\n if (selectedState.length > 0) {\n newActive = getOptionsMatching(\n (option) => option.value === selectedState[0],\n ).pop();\n }\n\n // If we still don't have an active item, we should just select the first item\n if (!newActive) {\n newActive = getOptionAtIndex(0);\n }\n\n setActive(newActive?.data);\n setFocusedState(true);\n onFocus?.(event);\n };\n\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n setFocusedState(false);\n setActive(undefined);\n onBlur?.(event);\n };\n\n const handleListMouseOver = () => {\n setFocusVisibleState(false);\n setActive(undefined);\n };\n\n const handleRef = useForkRef(setListRef, ref);\n\n return (\n <ListControlContext.Provider value={listControl}>\n <div\n className={clsx(\n withBaseName(),\n { [withBaseName(\"bordered\")]: bordered },\n className,\n )}\n role=\"listbox\"\n aria-activedescendant={activeState?.id}\n aria-disabled={disabled || undefined}\n aria-multiselectable={multiselect}\n tabIndex={disabled ? -1 : 0}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n onFocus={handleFocus}\n onMouseOver={handleListMouseOver}\n onMouseDown={handleMouseDown}\n ref={handleRef}\n {...rest}\n >\n {children}\n </div>\n </ListControlContext.Provider>\n );\n}) as <Item = string>(\n props: ListBoxProps<Item> & { ref?: Ref<HTMLDivElement> },\n) => JSX.Element;\n"],"names":["ListBox","listBoxCss"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ListBox.js","sources":["../src/list-box/ListBox.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type FocusEvent,\n type ForwardedRef,\n forwardRef,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n useRef,\n} from \"react\";\nimport {\n getListControlNavigationTarget,\n isListControlNavigationKey,\n isModifiedListControlNavigationKey,\n type OptionAndElement,\n} from \"../list-control/ListControlNavigationKeys\";\nimport { ListControlProvider } from \"../list-control/ListControlProvider\";\nimport {\n defaultValueToString,\n type ListControlProps,\n useListControl,\n} from \"../list-control/ListControlState\";\nimport { makePrefixer, useForkRef } from \"../utils\";\n\nimport listBoxCss from \"./ListBox.css\";\n\nexport type ListBoxProps<Item = string> = {\n /**\n * If `true`, the list box will be disabled.\n */\n disabled?: boolean;\n /**\n * If `false`, the list box will have not a border.\n */\n bordered?: boolean;\n /**\n * The options to display in the list box.\n */\n children?: ReactNode;\n /**\n * If `true`, the list box will be multiselect.\n */\n multiselect?: boolean;\n} & ComponentPropsWithoutRef<\"div\"> &\n Omit<ListControlProps<Item>, \"onOpenChange\">;\n\nconst withBaseName = makePrefixer(\"saltListBox\");\n\nexport const ListBox = forwardRef(function ListBox<Item>(\n props: ListBoxProps<Item>,\n ref: ForwardedRef<HTMLDivElement>,\n) {\n const {\n bordered,\n className,\n children,\n defaultSelected,\n disabled,\n selected,\n onSelectionChange,\n multiselect,\n valueToString = defaultValueToString,\n onKeyDown,\n onFocus,\n onBlur,\n ...rest\n } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-list-box\",\n css: listBoxCss,\n window: targetWindow,\n });\n\n const listControl = useListControl<Item>({\n multiselect,\n defaultSelected,\n selected,\n onSelectionChange,\n valueToString,\n disabled,\n });\n\n const {\n activeState,\n setActive,\n getOptionAtIndex,\n getIndexOfOption,\n getOptionsMatching,\n getOptionFromSearch,\n getFirstOption,\n getLastOption,\n getOptionAfter,\n getOptionBefore,\n getOptionPageAbove,\n getOptionPageBelow,\n selectedState,\n select,\n setFocusVisibleState,\n setFocusedState,\n setListRef,\n } = listControl;\n\n const typeaheadString = useRef(\"\");\n const typeaheadTimeout = useRef<number | undefined>();\n\n const handleTypeahead = (event: KeyboardEvent<HTMLDivElement>) => {\n if (typeaheadTimeout.current) {\n clearTimeout(typeaheadTimeout.current);\n }\n typeaheadString.current += event.key;\n typeaheadTimeout.current = window.setTimeout(() => {\n typeaheadString.current = \"\";\n }, 500);\n\n const newOption = getOptionFromSearch(typeaheadString.current, activeState);\n\n if (newOption) {\n setActive(newOption);\n setFocusVisibleState(true);\n }\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n if (isModifiedListControlNavigationKey(event)) {\n return;\n }\n\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey\n ) {\n event.preventDefault();\n event.stopPropagation();\n handleTypeahead(event);\n }\n\n const activeOption = activeState ?? getFirstOption()?.data;\n\n if (activeOption === undefined) {\n return;\n }\n\n const isNavigationKey = isListControlNavigationKey(event.key);\n if (isNavigationKey) {\n event.preventDefault();\n }\n\n const newActive: OptionAndElement<Item> | undefined = isNavigationKey\n ? getListControlNavigationTarget(event.key, activeOption, {\n getFirstOption,\n getLastOption,\n getOptionAfter,\n getOptionBefore,\n getOptionPageAbove,\n getOptionPageBelow,\n })\n : undefined;\n\n switch (event.key) {\n case \"Enter\":\n case \" \":\n if (\n activeState?.disabled ||\n (typeaheadString.current.trim().length > 0 && event.key === \" \")\n ) {\n event.preventDefault();\n return;\n }\n\n if (!activeState) {\n return;\n }\n\n event.preventDefault();\n select(event, activeState);\n\n break;\n }\n\n if (newActive && newActive.data.id !== activeState?.id) {\n setActive(newActive.data);\n setFocusVisibleState(true);\n }\n };\n\n const wasMouseDown = useRef(false);\n\n const handleMouseDown = () => {\n wasMouseDown.current = true;\n };\n\n const handleFocus = (event: FocusEvent<HTMLDivElement>) => {\n if (wasMouseDown.current) {\n wasMouseDown.current = false;\n return;\n }\n\n setFocusVisibleState(true);\n wasMouseDown.current = false;\n\n // We check the active index because the active item may have been removed\n const activeIndex = activeState ? getIndexOfOption(activeState) : -1;\n let newActive: ReturnType<typeof getOptionAtIndex>;\n\n // If the active item is still in the list, we don't need to do anything\n if (activeIndex > 0) {\n return;\n }\n\n // If we have selected an item, we should make that the active item\n if (selectedState.length > 0) {\n newActive = getOptionsMatching(\n (option) => option.value === selectedState[0],\n ).pop();\n }\n\n // If we still don't have an active item, we should just select the first item\n if (!newActive) {\n newActive = getOptionAtIndex(0);\n }\n\n setActive(newActive?.data);\n setFocusedState(true);\n onFocus?.(event);\n };\n\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n setFocusedState(false);\n setActive(undefined);\n onBlur?.(event);\n };\n\n const handleListMouseOver = () => {\n setFocusVisibleState(false);\n setActive(undefined);\n };\n\n const handleRef = useForkRef(setListRef, ref);\n\n return (\n <ListControlProvider value={listControl}>\n <div\n className={clsx(\n withBaseName(),\n { [withBaseName(\"bordered\")]: bordered },\n className,\n )}\n role=\"listbox\"\n aria-activedescendant={activeState?.id}\n aria-disabled={disabled || undefined}\n aria-multiselectable={multiselect}\n tabIndex={disabled ? -1 : 0}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n onFocus={handleFocus}\n onMouseOver={handleListMouseOver}\n onMouseDown={handleMouseDown}\n ref={handleRef}\n {...rest}\n >\n {children}\n </div>\n </ListControlProvider>\n );\n}) as <Item = string>(\n props: ListBoxProps<Item> & { ref?: Ref<HTMLDivElement> },\n) => JSX.Element;\n"],"names":["ListBox","listBoxCss"],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const LIST_CONTROL_NAVIGATION_KEYS = /* @__PURE__ */ new Set([
|
|
2
|
+
"ArrowDown",
|
|
3
|
+
"ArrowUp",
|
|
4
|
+
"Home",
|
|
5
|
+
"End",
|
|
6
|
+
"PageUp",
|
|
7
|
+
"PageDown"
|
|
8
|
+
]);
|
|
9
|
+
function isListControlNavigationKey(key) {
|
|
10
|
+
return LIST_CONTROL_NAVIGATION_KEYS.has(key);
|
|
11
|
+
}
|
|
12
|
+
function isModifiedListControlNavigationKey(event) {
|
|
13
|
+
if (!isListControlNavigationKey(event.key)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (event.ctrlKey || event.metaKey) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return event.altKey && event.key !== "ArrowUp" && event.key !== "ArrowDown";
|
|
20
|
+
}
|
|
21
|
+
function getListControlNavigationTarget(key, activeOption, getters) {
|
|
22
|
+
switch (key) {
|
|
23
|
+
case "ArrowDown":
|
|
24
|
+
return getters.getOptionAfter(activeOption) ?? getters.getLastOption();
|
|
25
|
+
case "ArrowUp":
|
|
26
|
+
return getters.getOptionBefore(activeOption) ?? getters.getFirstOption();
|
|
27
|
+
case "Home":
|
|
28
|
+
return getters.getFirstOption();
|
|
29
|
+
case "End":
|
|
30
|
+
return getters.getLastOption();
|
|
31
|
+
case "PageUp":
|
|
32
|
+
return getters.getOptionPageAbove(activeOption);
|
|
33
|
+
case "PageDown":
|
|
34
|
+
return getters.getOptionPageBelow(activeOption);
|
|
35
|
+
default:
|
|
36
|
+
return void 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function getComboBoxNavigationTarget(key, activeOption, getters) {
|
|
40
|
+
switch (key) {
|
|
41
|
+
case "ArrowDown":
|
|
42
|
+
return activeOption ? getters.getOptionAfter(activeOption) : getters.getFirstOption();
|
|
43
|
+
case "ArrowUp":
|
|
44
|
+
return activeOption ? getters.getOptionBefore(activeOption) : getters.getLastOption();
|
|
45
|
+
case "Home":
|
|
46
|
+
return getters.getFirstOption();
|
|
47
|
+
case "End":
|
|
48
|
+
return getters.getLastOption();
|
|
49
|
+
case "PageUp": {
|
|
50
|
+
if (activeOption) {
|
|
51
|
+
return getters.getOptionPageAbove(activeOption);
|
|
52
|
+
}
|
|
53
|
+
const lastOption = getters.getLastOption();
|
|
54
|
+
return lastOption ? getters.getOptionPageAbove(lastOption.data) : void 0;
|
|
55
|
+
}
|
|
56
|
+
case "PageDown": {
|
|
57
|
+
if (activeOption) {
|
|
58
|
+
return getters.getOptionPageBelow(activeOption);
|
|
59
|
+
}
|
|
60
|
+
const firstOption = getters.getFirstOption();
|
|
61
|
+
return firstOption ? getters.getOptionPageBelow(firstOption.data) : void 0;
|
|
62
|
+
}
|
|
63
|
+
default:
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { getComboBoxNavigationTarget, getListControlNavigationTarget, isListControlNavigationKey, isModifiedListControlNavigationKey };
|
|
69
|
+
//# sourceMappingURL=ListControlNavigationKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlNavigationKeys.js","sources":["../src/list-control/ListControlNavigationKeys.ts"],"sourcesContent":["import type { OptionValue } from \"./ListControlContext\";\n\n/**\n * Keys that move between options while the list is shown. When no list is\n * shown, Dropdown and ComboBox pass the keys they don't use to open the list\n * to the browser.\n */\nconst LIST_CONTROL_NAVIGATION_KEYS: ReadonlySet<string> = new Set([\n \"ArrowDown\",\n \"ArrowUp\",\n \"Home\",\n \"End\",\n \"PageUp\",\n \"PageDown\",\n]);\n\nexport function isListControlNavigationKey(key: string): boolean {\n return LIST_CONTROL_NAVIGATION_KEYS.has(key);\n}\n\n/**\n * Navigation keys pressed with Ctrl or Meta (e.g. Ctrl+End, Cmd+ArrowDown,\n * Ctrl+PageDown) are browser or OS shortcuts, so list controls leave them to\n * the browser. Alt is only used with ArrowUp and ArrowDown, as in the ARIA\n * combobox pattern.\n */\nexport function isModifiedListControlNavigationKey(event: {\n key: string;\n altKey: boolean;\n ctrlKey: boolean;\n metaKey: boolean;\n}): boolean {\n if (!isListControlNavigationKey(event.key)) {\n return false;\n }\n if (event.ctrlKey || event.metaKey) {\n return true;\n }\n return event.altKey && event.key !== \"ArrowUp\" && event.key !== \"ArrowDown\";\n}\n\nexport interface OptionAndElement<Item> {\n data: OptionValue<Item>;\n element: HTMLElement;\n}\n\nexport interface ListControlNavigationGetters<Item> {\n getFirstOption: () => OptionAndElement<Item> | undefined;\n getLastOption: () => OptionAndElement<Item> | undefined;\n getOptionAfter: (\n option: OptionValue<Item>,\n ) => OptionAndElement<Item> | undefined;\n getOptionBefore: (\n option: OptionValue<Item>,\n ) => OptionAndElement<Item> | undefined;\n getOptionPageAbove: (\n option: OptionValue<Item>,\n ) => OptionAndElement<Item> | undefined;\n getOptionPageBelow: (\n option: OptionValue<Item>,\n ) => OptionAndElement<Item> | undefined;\n}\n\n/** Shared by Dropdown and ListBox, which always have an active option. */\nexport function getListControlNavigationTarget<Item>(\n key: string,\n activeOption: OptionValue<Item>,\n getters: ListControlNavigationGetters<Item>,\n): OptionAndElement<Item> | undefined {\n switch (key) {\n case \"ArrowDown\":\n return getters.getOptionAfter(activeOption) ?? getters.getLastOption();\n case \"ArrowUp\":\n return getters.getOptionBefore(activeOption) ?? getters.getFirstOption();\n case \"Home\":\n return getters.getFirstOption();\n case \"End\":\n return getters.getLastOption();\n case \"PageUp\":\n return getters.getOptionPageAbove(activeOption);\n case \"PageDown\":\n return getters.getOptionPageBelow(activeOption);\n default:\n return undefined;\n }\n}\n\n/** For ComboBox, where the active option may be undefined. */\nexport function getComboBoxNavigationTarget<Item>(\n key: string,\n activeOption: OptionValue<Item> | undefined,\n getters: ListControlNavigationGetters<Item>,\n): OptionAndElement<Item> | undefined {\n switch (key) {\n case \"ArrowDown\":\n return activeOption\n ? getters.getOptionAfter(activeOption)\n : getters.getFirstOption();\n case \"ArrowUp\":\n return activeOption\n ? getters.getOptionBefore(activeOption)\n : getters.getLastOption();\n case \"Home\":\n return getters.getFirstOption();\n case \"End\":\n return getters.getLastOption();\n case \"PageUp\": {\n if (activeOption) {\n return getters.getOptionPageAbove(activeOption);\n }\n const lastOption = getters.getLastOption();\n return lastOption\n ? getters.getOptionPageAbove(lastOption.data)\n : undefined;\n }\n case \"PageDown\": {\n if (activeOption) {\n return getters.getOptionPageBelow(activeOption);\n }\n const firstOption = getters.getFirstOption();\n return firstOption\n ? getters.getOptionPageBelow(firstOption.data)\n : undefined;\n }\n default:\n return undefined;\n }\n}\n"],"names":[],"mappings":"AAOA,MAAM,4BAAA,uBAAwD,GAAA,CAAI;AAAA,EAChE,WAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAC,CAAA;AAEM,SAAS,2BAA2B,GAAA,EAAsB;AAC/D,EAAA,OAAO,4BAAA,CAA6B,IAAI,GAAG,CAAA;AAC7C;AAQO,SAAS,mCAAmC,KAAA,EAKvC;AACV,EAAA,IAAI,CAAC,0BAAA,CAA2B,KAAA,CAAM,GAAG,CAAA,EAAG;AAC1C,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,IAAW,KAAA,CAAM,OAAA,EAAS;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAM,MAAA,IAAU,KAAA,CAAM,GAAA,KAAQ,SAAA,IAAa,MAAM,GAAA,KAAQ,WAAA;AAClE;AAyBO,SAAS,8BAAA,CACd,GAAA,EACA,YAAA,EACA,OAAA,EACoC;AACpC,EAAA,QAAQ,GAAA;AAAK,IACX,KAAK,WAAA;AACH,MAAA,OAAO,OAAA,CAAQ,cAAA,CAAe,YAAY,CAAA,IAAK,QAAQ,aAAA,EAAc;AAAA,IACvE,KAAK,SAAA;AACH,MAAA,OAAO,OAAA,CAAQ,eAAA,CAAgB,YAAY,CAAA,IAAK,QAAQ,cAAA,EAAe;AAAA,IACzE,KAAK,MAAA;AACH,MAAA,OAAO,QAAQ,cAAA,EAAe;AAAA,IAChC,KAAK,KAAA;AACH,MAAA,OAAO,QAAQ,aAAA,EAAc;AAAA,IAC/B,KAAK,QAAA;AACH,MAAA,OAAO,OAAA,CAAQ,mBAAmB,YAAY,CAAA;AAAA,IAChD,KAAK,UAAA;AACH,MAAA,OAAO,OAAA,CAAQ,mBAAmB,YAAY,CAAA;AAAA,IAChD;AACE,MAAA,OAAO,MAAA;AAAA;AAEb;AAGO,SAAS,2BAAA,CACd,GAAA,EACA,YAAA,EACA,OAAA,EACoC;AACpC,EAAA,QAAQ,GAAA;AAAK,IACX,KAAK,WAAA;AACH,MAAA,OAAO,eACH,OAAA,CAAQ,cAAA,CAAe,YAAY,CAAA,GACnC,QAAQ,cAAA,EAAe;AAAA,IAC7B,KAAK,SAAA;AACH,MAAA,OAAO,eACH,OAAA,CAAQ,eAAA,CAAgB,YAAY,CAAA,GACpC,QAAQ,aAAA,EAAc;AAAA,IAC5B,KAAK,MAAA;AACH,MAAA,OAAO,QAAQ,cAAA,EAAe;AAAA,IAChC,KAAK,KAAA;AACH,MAAA,OAAO,QAAQ,aAAA,EAAc;AAAA,IAC/B,KAAK,QAAA,EAAU;AACb,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,OAAO,OAAA,CAAQ,mBAAmB,YAAY,CAAA;AAAA,MAChD;AACA,MAAA,MAAM,UAAA,GAAa,QAAQ,aAAA,EAAc;AACzC,MAAA,OAAO,UAAA,GACH,OAAA,CAAQ,kBAAA,CAAmB,UAAA,CAAW,IAAI,CAAA,GAC1C,MAAA;AAAA,IACN;AAAA,IACA,KAAK,UAAA,EAAY;AACf,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,OAAO,OAAA,CAAQ,mBAAmB,YAAY,CAAA;AAAA,MAChD;AACA,MAAA,MAAM,WAAA,GAAc,QAAQ,cAAA,EAAe;AAC3C,MAAA,OAAO,WAAA,GACH,OAAA,CAAQ,kBAAA,CAAmB,WAAA,CAAY,IAAI,CAAA,GAC3C,MAAA;AAAA,IACN;AAAA,IACA;AACE,MAAA,OAAO,MAAA;AAAA;AAEb;;;;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useContext } from 'react';
|
|
3
|
+
import { createContext } from '../utils/createContext.js';
|
|
4
|
+
import 'clsx';
|
|
5
|
+
import '../utils/useFloatingUI/useFloatingUI.js';
|
|
6
|
+
import '../utils/useId.js';
|
|
7
|
+
import '../salt-provider/SaltProvider.js';
|
|
8
|
+
import '../viewport/ViewportProvider.js';
|
|
9
|
+
import { ListControlOptionStore } from './ListControlOptionStore.js';
|
|
10
|
+
|
|
11
|
+
const fallbackOptionStateStore = new ListControlOptionStore();
|
|
12
|
+
const defaultListControlOptionContext = {
|
|
13
|
+
disabled: false,
|
|
14
|
+
listRef: void 0,
|
|
15
|
+
multiselect: false,
|
|
16
|
+
optionStateStore: fallbackOptionStateStore,
|
|
17
|
+
register: () => () => void 0,
|
|
18
|
+
select: () => void 0,
|
|
19
|
+
setActive: () => void 0,
|
|
20
|
+
valueToString: (item) => String(item)
|
|
21
|
+
};
|
|
22
|
+
const ListControlOptionContext = createContext(
|
|
23
|
+
"ListControlOptionContext",
|
|
24
|
+
defaultListControlOptionContext
|
|
25
|
+
);
|
|
26
|
+
function ListControlOptionContextProvider({
|
|
27
|
+
children,
|
|
28
|
+
value
|
|
29
|
+
}) {
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
ListControlOptionContext.Provider,
|
|
32
|
+
{
|
|
33
|
+
value,
|
|
34
|
+
children
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
function useListControlOptionContext() {
|
|
39
|
+
const context = useContext(ListControlOptionContext);
|
|
40
|
+
return context;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { ListControlOptionContextProvider, useListControlOptionContext };
|
|
44
|
+
//# sourceMappingURL=ListControlOptionContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlOptionContext.js","sources":["../src/list-control/ListControlOptionContext.tsx"],"sourcesContent":["import {\n type ReactNode,\n type RefObject,\n type SyntheticEvent,\n useContext,\n} from \"react\";\nimport { createContext } from \"../utils\";\nimport type { OptionValue } from \"./ListControlContext\";\nimport { ListControlOptionStore } from \"./ListControlOptionStore\";\n\nexport interface ListControlOptionContextValue<Item> {\n disabled?: boolean;\n listRef?: RefObject<HTMLDivElement>;\n multiselect: boolean;\n optionStateStore: ListControlOptionStore<Item>;\n register: (\n optionValue: OptionValue<Item>,\n element: HTMLElement,\n ) => () => void;\n select: (event: SyntheticEvent, option: OptionValue<Item>) => void;\n setActive: (option: OptionValue<Item>) => void;\n valueToString: (item: Item) => string;\n}\n\nconst fallbackOptionStateStore = new ListControlOptionStore<unknown>();\n\nconst defaultListControlOptionContext: ListControlOptionContextValue<unknown> =\n {\n disabled: false,\n listRef: undefined,\n multiselect: false,\n optionStateStore: fallbackOptionStateStore,\n register: () => () => undefined,\n select: () => undefined,\n setActive: () => undefined,\n valueToString: (item) => String(item),\n };\n\nconst ListControlOptionContext = createContext(\n \"ListControlOptionContext\",\n defaultListControlOptionContext,\n);\n\nexport function ListControlOptionContextProvider<Item>({\n children,\n value,\n}: {\n children: ReactNode;\n value: ListControlOptionContextValue<Item>;\n}) {\n return (\n <ListControlOptionContext.Provider\n value={value as unknown as ListControlOptionContextValue<unknown>}\n >\n {children}\n </ListControlOptionContext.Provider>\n );\n}\n\nexport function useListControlOptionContext<Item>() {\n const context = useContext(ListControlOptionContext);\n return context as unknown as ListControlOptionContextValue<Item>;\n}\n"],"names":[],"mappings":";;;;;;;;;;AAwBA,MAAM,wBAAA,GAA2B,IAAI,sBAAA,EAAgC;AAErE,MAAM,+BAAA,GACJ;AAAA,EACE,QAAA,EAAU,KAAA;AAAA,EACV,OAAA,EAAS,MAAA;AAAA,EACT,WAAA,EAAa,KAAA;AAAA,EACb,gBAAA,EAAkB,wBAAA;AAAA,EAClB,QAAA,EAAU,MAAM,MAAM,MAAA;AAAA,EACtB,QAAQ,MAAM,MAAA;AAAA,EACd,WAAW,MAAM,MAAA;AAAA,EACjB,aAAA,EAAe,CAAC,IAAA,KAAS,MAAA,CAAO,IAAI;AACtC,CAAA;AAEF,MAAM,wBAAA,GAA2B,aAAA;AAAA,EAC/B,0BAAA;AAAA,EACA;AACF,CAAA;AAEO,SAAS,gCAAA,CAAuC;AAAA,EACrD,QAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,uBACE,GAAA;AAAA,IAAC,wBAAA,CAAyB,QAAA;AAAA,IAAzB;AAAA,MACC,KAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,2BAAA,GAAoC;AAClD,EAAA,MAAM,OAAA,GAAU,WAAW,wBAAwB,CAAA;AACnD,EAAA,OAAO,OAAA;AACT;;;;"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
8
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
9
|
+
var __privateWrapper = (obj, member, setter, getter) => ({
|
|
10
|
+
set _(value) {
|
|
11
|
+
__privateSet(obj, member, value);
|
|
12
|
+
},
|
|
13
|
+
get _() {
|
|
14
|
+
return __privateGet(obj, member, getter);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
var _listeners, _options, _optionIdsByValue, _activeId, _focusVisible, _nextGeneration, _selected, _ListControlOptionStore_instances, notify_fn, deleteValueId_fn;
|
|
18
|
+
const OPTION_STATE_ACTIVE = 1;
|
|
19
|
+
const OPTION_STATE_SELECTED = 2;
|
|
20
|
+
const OPTION_STATE_FOCUS_VISIBLE = 4;
|
|
21
|
+
function hasOptionState(snapshot, state) {
|
|
22
|
+
return (snapshot & state) !== 0;
|
|
23
|
+
}
|
|
24
|
+
class ListControlOptionStore {
|
|
25
|
+
constructor(selected = []) {
|
|
26
|
+
__privateAdd(this, _ListControlOptionStore_instances);
|
|
27
|
+
__privateAdd(this, _listeners, /* @__PURE__ */ new Map());
|
|
28
|
+
__privateAdd(this, _options, /* @__PURE__ */ new Map());
|
|
29
|
+
__privateAdd(this, _optionIdsByValue, /* @__PURE__ */ new Map());
|
|
30
|
+
__privateAdd(this, _activeId);
|
|
31
|
+
__privateAdd(this, _focusVisible, false);
|
|
32
|
+
__privateAdd(this, _nextGeneration, 0);
|
|
33
|
+
__privateAdd(this, _selected);
|
|
34
|
+
__privateSet(this, _selected, new Set(selected));
|
|
35
|
+
}
|
|
36
|
+
subscribe(id, listener) {
|
|
37
|
+
let listeners = __privateGet(this, _listeners).get(id);
|
|
38
|
+
if (!listeners) {
|
|
39
|
+
listeners = /* @__PURE__ */ new Set();
|
|
40
|
+
__privateGet(this, _listeners).set(id, listeners);
|
|
41
|
+
}
|
|
42
|
+
listeners.add(listener);
|
|
43
|
+
return () => {
|
|
44
|
+
const currentListeners = __privateGet(this, _listeners).get(id);
|
|
45
|
+
currentListeners == null ? void 0 : currentListeners.delete(listener);
|
|
46
|
+
if ((currentListeners == null ? void 0 : currentListeners.size) === 0) {
|
|
47
|
+
__privateGet(this, _listeners).delete(id);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
register(option) {
|
|
52
|
+
const previousEntry = __privateGet(this, _options).get(option.id);
|
|
53
|
+
const previousSnapshot = this.getSnapshot(option.id);
|
|
54
|
+
if (previousEntry) {
|
|
55
|
+
__privateMethod(this, _ListControlOptionStore_instances, deleteValueId_fn).call(this, previousEntry.option.value, option.id);
|
|
56
|
+
}
|
|
57
|
+
const entry = {
|
|
58
|
+
generation: __privateWrapper(this, _nextGeneration)._++,
|
|
59
|
+
option
|
|
60
|
+
};
|
|
61
|
+
__privateGet(this, _options).set(option.id, entry);
|
|
62
|
+
const valueIds = __privateGet(this, _optionIdsByValue).get(option.value);
|
|
63
|
+
if (valueIds === void 0) {
|
|
64
|
+
__privateGet(this, _optionIdsByValue).set(option.value, option.id);
|
|
65
|
+
} else if (typeof valueIds === "string") {
|
|
66
|
+
__privateGet(this, _optionIdsByValue).set(option.value, /* @__PURE__ */ new Set([valueIds, option.id]));
|
|
67
|
+
} else {
|
|
68
|
+
valueIds.add(option.id);
|
|
69
|
+
}
|
|
70
|
+
if (previousEntry !== void 0 || previousSnapshot !== this.getSnapshot(option.id)) {
|
|
71
|
+
__privateMethod(this, _ListControlOptionStore_instances, notify_fn).call(this, option.id);
|
|
72
|
+
}
|
|
73
|
+
return () => {
|
|
74
|
+
const current = __privateGet(this, _options).get(option.id);
|
|
75
|
+
if ((current == null ? void 0 : current.generation) !== entry.generation) return;
|
|
76
|
+
const previousSnapshot2 = this.getSnapshot(option.id);
|
|
77
|
+
__privateGet(this, _options).delete(option.id);
|
|
78
|
+
__privateMethod(this, _ListControlOptionStore_instances, deleteValueId_fn).call(this, option.value, option.id);
|
|
79
|
+
if (previousSnapshot2 !== 0) __privateMethod(this, _ListControlOptionStore_instances, notify_fn).call(this, option.id);
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
getSnapshot(id, currentOption) {
|
|
83
|
+
var _a;
|
|
84
|
+
const option = currentOption ?? ((_a = __privateGet(this, _options).get(id)) == null ? void 0 : _a.option);
|
|
85
|
+
if (!option) return 0;
|
|
86
|
+
let snapshot = 0;
|
|
87
|
+
if (id === __privateGet(this, _activeId)) {
|
|
88
|
+
snapshot |= OPTION_STATE_ACTIVE;
|
|
89
|
+
if (__privateGet(this, _focusVisible)) snapshot |= OPTION_STATE_FOCUS_VISIBLE;
|
|
90
|
+
}
|
|
91
|
+
if (__privateGet(this, _selected).has(option.value)) {
|
|
92
|
+
snapshot |= OPTION_STATE_SELECTED;
|
|
93
|
+
}
|
|
94
|
+
return snapshot;
|
|
95
|
+
}
|
|
96
|
+
setActiveId(id) {
|
|
97
|
+
if (id === __privateGet(this, _activeId)) return;
|
|
98
|
+
const previousId = __privateGet(this, _activeId);
|
|
99
|
+
__privateSet(this, _activeId, id);
|
|
100
|
+
if (previousId !== void 0) __privateMethod(this, _ListControlOptionStore_instances, notify_fn).call(this, previousId);
|
|
101
|
+
if (id !== void 0) __privateMethod(this, _ListControlOptionStore_instances, notify_fn).call(this, id);
|
|
102
|
+
}
|
|
103
|
+
setFocusVisible(focusVisible) {
|
|
104
|
+
if (focusVisible === __privateGet(this, _focusVisible)) return;
|
|
105
|
+
__privateSet(this, _focusVisible, focusVisible);
|
|
106
|
+
if (__privateGet(this, _activeId) !== void 0) __privateMethod(this, _ListControlOptionStore_instances, notify_fn).call(this, __privateGet(this, _activeId));
|
|
107
|
+
}
|
|
108
|
+
setSelected(selected) {
|
|
109
|
+
const previous = __privateGet(this, _selected);
|
|
110
|
+
const nextSelected = new Set(selected);
|
|
111
|
+
__privateSet(this, _selected, nextSelected);
|
|
112
|
+
const candidateValues = /* @__PURE__ */ new Set([...previous, ...nextSelected]);
|
|
113
|
+
for (const value of candidateValues) {
|
|
114
|
+
if (previous.has(value) !== nextSelected.has(value)) {
|
|
115
|
+
const ids = __privateGet(this, _optionIdsByValue).get(value);
|
|
116
|
+
if (typeof ids === "string") {
|
|
117
|
+
__privateMethod(this, _ListControlOptionStore_instances, notify_fn).call(this, ids);
|
|
118
|
+
} else if (ids !== void 0) {
|
|
119
|
+
for (const id of ids) __privateMethod(this, _ListControlOptionStore_instances, notify_fn).call(this, id);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
_listeners = new WeakMap();
|
|
126
|
+
_options = new WeakMap();
|
|
127
|
+
_optionIdsByValue = new WeakMap();
|
|
128
|
+
_activeId = new WeakMap();
|
|
129
|
+
_focusVisible = new WeakMap();
|
|
130
|
+
_nextGeneration = new WeakMap();
|
|
131
|
+
_selected = new WeakMap();
|
|
132
|
+
_ListControlOptionStore_instances = new WeakSet();
|
|
133
|
+
notify_fn = function(id) {
|
|
134
|
+
const listeners = __privateGet(this, _listeners).get(id);
|
|
135
|
+
if (!listeners) return;
|
|
136
|
+
for (const listener of [...listeners]) listener();
|
|
137
|
+
};
|
|
138
|
+
deleteValueId_fn = function(value, id) {
|
|
139
|
+
const ids = __privateGet(this, _optionIdsByValue).get(value);
|
|
140
|
+
if (typeof ids === "string") {
|
|
141
|
+
if (ids === id) __privateGet(this, _optionIdsByValue).delete(value);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
ids == null ? void 0 : ids.delete(id);
|
|
145
|
+
if ((ids == null ? void 0 : ids.size) === 1) {
|
|
146
|
+
__privateGet(this, _optionIdsByValue).set(value, ids.values().next().value);
|
|
147
|
+
} else if ((ids == null ? void 0 : ids.size) === 0) {
|
|
148
|
+
__privateGet(this, _optionIdsByValue).delete(value);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export { ListControlOptionStore, OPTION_STATE_ACTIVE, OPTION_STATE_FOCUS_VISIBLE, OPTION_STATE_SELECTED, hasOptionState };
|
|
153
|
+
//# sourceMappingURL=ListControlOptionStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlOptionStore.js","sources":["../src/list-control/ListControlOptionStore.ts"],"sourcesContent":["import type { OptionValue } from \"./ListControlContext\";\n\nexport const OPTION_STATE_ACTIVE = 1;\nexport const OPTION_STATE_SELECTED = 2;\nexport const OPTION_STATE_FOCUS_VISIBLE = 4;\n\nexport type OptionStateSnapshot = number;\n\nexport function hasOptionState(\n snapshot: OptionStateSnapshot,\n state: OptionStateSnapshot,\n): boolean {\n return (snapshot & state) !== 0;\n}\n\ninterface OptionEntry<Item> {\n generation: number;\n option: OptionValue<Item>;\n}\n\n/** Internal per-list store used to target updates at affected Options. */\nexport class ListControlOptionStore<Item> {\n readonly #listeners = new Map<string, Set<() => void>>();\n readonly #options = new Map<string, OptionEntry<Item>>();\n readonly #optionIdsByValue = new Map<Item, string | Set<string>>();\n #activeId: string | undefined;\n #focusVisible = false;\n #nextGeneration = 0;\n #selected: ReadonlySet<Item>;\n\n constructor(selected: readonly Item[] = []) {\n this.#selected = new Set(selected);\n }\n\n subscribe(id: string, listener: () => void): () => void {\n let listeners = this.#listeners.get(id);\n if (!listeners) {\n listeners = new Set();\n this.#listeners.set(id, listeners);\n }\n listeners.add(listener);\n\n return () => {\n const currentListeners = this.#listeners.get(id);\n currentListeners?.delete(listener);\n if (currentListeners?.size === 0) {\n this.#listeners.delete(id);\n }\n };\n }\n\n register(option: OptionValue<Item>): () => void {\n const previousEntry = this.#options.get(option.id);\n const previousSnapshot = this.getSnapshot(option.id);\n if (previousEntry) {\n this.#deleteValueId(previousEntry.option.value, option.id);\n }\n const entry = {\n generation: this.#nextGeneration++,\n option,\n };\n this.#options.set(option.id, entry);\n const valueIds = this.#optionIdsByValue.get(option.value);\n if (valueIds === undefined) {\n this.#optionIdsByValue.set(option.value, option.id);\n } else if (typeof valueIds === \"string\") {\n this.#optionIdsByValue.set(option.value, new Set([valueIds, option.id]));\n } else {\n valueIds.add(option.id);\n }\n\n if (\n previousEntry !== undefined ||\n previousSnapshot !== this.getSnapshot(option.id)\n ) {\n this.#notify(option.id);\n }\n\n return () => {\n const current = this.#options.get(option.id);\n if (current?.generation !== entry.generation) return;\n const previousSnapshot = this.getSnapshot(option.id);\n this.#options.delete(option.id);\n this.#deleteValueId(option.value, option.id);\n if (previousSnapshot !== 0) this.#notify(option.id);\n };\n }\n\n getSnapshot(\n id: string,\n currentOption?: OptionValue<Item>,\n ): OptionStateSnapshot {\n const option = currentOption ?? this.#options.get(id)?.option;\n if (!option) return 0;\n\n let snapshot = 0;\n if (id === this.#activeId) {\n snapshot |= OPTION_STATE_ACTIVE;\n if (this.#focusVisible) snapshot |= OPTION_STATE_FOCUS_VISIBLE;\n }\n if (this.#selected.has(option.value)) {\n snapshot |= OPTION_STATE_SELECTED;\n }\n return snapshot;\n }\n\n setActiveId(id: string | undefined): void {\n if (id === this.#activeId) return;\n const previousId = this.#activeId;\n this.#activeId = id;\n if (previousId !== undefined) this.#notify(previousId);\n if (id !== undefined) this.#notify(id);\n }\n\n setFocusVisible(focusVisible: boolean): void {\n if (focusVisible === this.#focusVisible) return;\n this.#focusVisible = focusVisible;\n if (this.#activeId !== undefined) this.#notify(this.#activeId);\n }\n\n setSelected(selected: readonly Item[]): void {\n const previous = this.#selected;\n const nextSelected = new Set(selected);\n this.#selected = nextSelected;\n\n const candidateValues = new Set([...previous, ...nextSelected]);\n for (const value of candidateValues) {\n if (previous.has(value) !== nextSelected.has(value)) {\n const ids = this.#optionIdsByValue.get(value);\n if (typeof ids === \"string\") {\n this.#notify(ids);\n } else if (ids !== undefined) {\n for (const id of ids) this.#notify(id);\n }\n }\n }\n }\n\n #notify(id: string): void {\n const listeners = this.#listeners.get(id);\n if (!listeners) return;\n for (const listener of [...listeners]) listener();\n }\n\n #deleteValueId(value: Item, id: string): void {\n const ids = this.#optionIdsByValue.get(value);\n if (typeof ids === \"string\") {\n if (ids === id) this.#optionIdsByValue.delete(value);\n return;\n }\n ids?.delete(id);\n if (ids?.size === 1) {\n this.#optionIdsByValue.set(value, ids.values().next().value as string);\n } else if (ids?.size === 0) {\n this.#optionIdsByValue.delete(value);\n }\n }\n}\n"],"names":["previousSnapshot"],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { ListControlContext } from './ListControlContext.js';
|
|
4
|
+
import { ListControlOptionContextProvider } from './ListControlOptionContext.js';
|
|
5
|
+
|
|
6
|
+
function ListControlProvider({
|
|
7
|
+
children,
|
|
8
|
+
value
|
|
9
|
+
}) {
|
|
10
|
+
const { optionStateStore, ...publicValue } = value;
|
|
11
|
+
const optionValue = useMemo(
|
|
12
|
+
() => ({
|
|
13
|
+
disabled: value.disabled,
|
|
14
|
+
listRef: value.listRef,
|
|
15
|
+
multiselect: value.multiselect,
|
|
16
|
+
optionStateStore,
|
|
17
|
+
register: value.register,
|
|
18
|
+
select: value.select,
|
|
19
|
+
setActive: value.setActive,
|
|
20
|
+
valueToString: value.valueToString
|
|
21
|
+
}),
|
|
22
|
+
[
|
|
23
|
+
optionStateStore,
|
|
24
|
+
value.disabled,
|
|
25
|
+
value.listRef,
|
|
26
|
+
value.multiselect,
|
|
27
|
+
value.register,
|
|
28
|
+
value.select,
|
|
29
|
+
value.setActive,
|
|
30
|
+
value.valueToString
|
|
31
|
+
]
|
|
32
|
+
);
|
|
33
|
+
return /* @__PURE__ */ jsx(ListControlContext.Provider, { value: publicValue, children: /* @__PURE__ */ jsx(ListControlOptionContextProvider, { value: optionValue, children }) });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { ListControlProvider };
|
|
37
|
+
//# sourceMappingURL=ListControlProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlProvider.js","sources":["../src/list-control/ListControlProvider.tsx"],"sourcesContent":["import { type ReactNode, useMemo } from \"react\";\nimport {\n ListControlContext,\n type ListControlContextValue,\n} from \"./ListControlContext\";\nimport {\n ListControlOptionContextProvider,\n type ListControlOptionContextValue,\n} from \"./ListControlOptionContext\";\nimport type { ListControlOptionStore } from \"./ListControlOptionStore\";\n\ntype ListControlProviderValue<Item> = ListControlContextValue<Item> & {\n optionStateStore: ListControlOptionStore<Item>;\n};\n\nexport function ListControlProvider<Item>({\n children,\n value,\n}: {\n children: ReactNode;\n value: ListControlProviderValue<Item>;\n}) {\n const { optionStateStore, ...publicValue } = value;\n const optionValue = useMemo<ListControlOptionContextValue<Item>>(\n () => ({\n disabled: value.disabled,\n listRef: value.listRef,\n multiselect: value.multiselect,\n optionStateStore,\n register: value.register,\n select: value.select,\n setActive: value.setActive,\n valueToString: value.valueToString,\n }),\n [\n optionStateStore,\n value.disabled,\n value.listRef,\n value.multiselect,\n value.register,\n value.select,\n value.setActive,\n value.valueToString,\n ],\n );\n\n return (\n <ListControlContext.Provider value={publicValue}>\n <ListControlOptionContextProvider value={optionValue}>\n {children}\n </ListControlOptionContextProvider>\n </ListControlContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;;AAeO,SAAS,mBAAA,CAA0B;AAAA,EACxC,QAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,MAAM,EAAE,gBAAA,EAAkB,GAAG,WAAA,EAAY,GAAI,KAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,OAAA;AAAA,IAClB,OAAO;AAAA,MACL,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,gBAAA;AAAA,MACA,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,WAAW,KAAA,CAAM,SAAA;AAAA,MACjB,eAAe,KAAA,CAAM;AAAA,KACvB,CAAA;AAAA,IACA;AAAA,MACE,gBAAA;AAAA,MACA,KAAA,CAAM,QAAA;AAAA,MACN,KAAA,CAAM,OAAA;AAAA,MACN,KAAA,CAAM,WAAA;AAAA,MACN,KAAA,CAAM,QAAA;AAAA,MACN,KAAA,CAAM,MAAA;AAAA,MACN,KAAA,CAAM,SAAA;AAAA,MACN,KAAA,CAAM;AAAA;AACR,GACF;AAEA,EAAA,uBACE,GAAA,CAAC,kBAAA,CAAmB,QAAA,EAAnB,EAA4B,KAAA,EAAO,WAAA,EAClC,QAAA,kBAAA,GAAA,CAAC,gCAAA,EAAA,EAAiC,KAAA,EAAO,WAAA,EACtC,QAAA,EACH,CAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
8
|
+
var __privateWrapper = (obj, member, setter, getter) => ({
|
|
9
|
+
set _(value) {
|
|
10
|
+
__privateSet(obj, member, value);
|
|
11
|
+
},
|
|
12
|
+
get _() {
|
|
13
|
+
return __privateGet(obj, member, getter);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
var _entries, _ordered, _indexById, _nextGeneration, _hasGaps;
|
|
17
|
+
function createCoalescedRebuild(rebuild, enqueue = (callback) => {
|
|
18
|
+
Promise.resolve().then(callback);
|
|
19
|
+
}) {
|
|
20
|
+
let pending = false;
|
|
21
|
+
let cancelled = false;
|
|
22
|
+
return {
|
|
23
|
+
schedule() {
|
|
24
|
+
if (pending || cancelled) return;
|
|
25
|
+
pending = true;
|
|
26
|
+
enqueue(() => {
|
|
27
|
+
pending = false;
|
|
28
|
+
if (!cancelled) rebuild();
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
cancel() {
|
|
32
|
+
cancelled = true;
|
|
33
|
+
pending = false;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
class ListControlRegistry {
|
|
38
|
+
constructor() {
|
|
39
|
+
__privateAdd(this, _entries, /* @__PURE__ */ new Map());
|
|
40
|
+
__privateAdd(this, _ordered, []);
|
|
41
|
+
__privateAdd(this, _indexById, /* @__PURE__ */ new Map());
|
|
42
|
+
__privateAdd(this, _nextGeneration, 0);
|
|
43
|
+
__privateAdd(this, _hasGaps, false);
|
|
44
|
+
}
|
|
45
|
+
register(option, element) {
|
|
46
|
+
const entry = {
|
|
47
|
+
data: option,
|
|
48
|
+
element,
|
|
49
|
+
generation: __privateWrapper(this, _nextGeneration)._++
|
|
50
|
+
};
|
|
51
|
+
__privateGet(this, _entries).set(option.id, entry);
|
|
52
|
+
const currentIndex = __privateGet(this, _indexById).get(option.id);
|
|
53
|
+
if (currentIndex === void 0) {
|
|
54
|
+
__privateGet(this, _indexById).set(option.id, __privateGet(this, _ordered).length);
|
|
55
|
+
__privateGet(this, _ordered).push(entry);
|
|
56
|
+
} else {
|
|
57
|
+
__privateGet(this, _ordered)[currentIndex] = entry;
|
|
58
|
+
}
|
|
59
|
+
return () => {
|
|
60
|
+
const current = __privateGet(this, _entries).get(option.id);
|
|
61
|
+
if ((current == null ? void 0 : current.generation) !== entry.generation) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
__privateGet(this, _entries).delete(option.id);
|
|
65
|
+
const index = __privateGet(this, _indexById).get(option.id);
|
|
66
|
+
if (index !== void 0 && __privateGet(this, _ordered)[index] === entry) {
|
|
67
|
+
__privateGet(this, _ordered)[index] = void 0;
|
|
68
|
+
__privateGet(this, _indexById).delete(option.id);
|
|
69
|
+
__privateSet(this, _hasGaps, true);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
rebuild(listElement) {
|
|
74
|
+
const ordered = [];
|
|
75
|
+
const indexById = /* @__PURE__ */ new Map();
|
|
76
|
+
for (const element of listElement.querySelectorAll(
|
|
77
|
+
'[role="option"]'
|
|
78
|
+
)) {
|
|
79
|
+
const entry = __privateGet(this, _entries).get(element.id);
|
|
80
|
+
if ((entry == null ? void 0 : entry.element) === element && element.isConnected) {
|
|
81
|
+
indexById.set(entry.data.id, ordered.length);
|
|
82
|
+
ordered.push(entry);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const id of __privateGet(this, _entries).keys()) {
|
|
86
|
+
if (!indexById.has(id)) {
|
|
87
|
+
__privateGet(this, _entries).delete(id);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
__privateSet(this, _ordered, ordered);
|
|
91
|
+
__privateSet(this, _indexById, indexById);
|
|
92
|
+
__privateSet(this, _hasGaps, false);
|
|
93
|
+
}
|
|
94
|
+
getAt(index) {
|
|
95
|
+
if (!__privateGet(this, _hasGaps)) {
|
|
96
|
+
return __privateGet(this, _ordered)[index];
|
|
97
|
+
}
|
|
98
|
+
let currentIndex = 0;
|
|
99
|
+
for (const entry of __privateGet(this, _ordered)) {
|
|
100
|
+
if (entry && __privateGet(this, _entries).get(entry.data.id) === entry) {
|
|
101
|
+
if (currentIndex === index) return entry;
|
|
102
|
+
currentIndex++;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return void 0;
|
|
106
|
+
}
|
|
107
|
+
get length() {
|
|
108
|
+
return __privateGet(this, _hasGaps) ? __privateGet(this, _entries).size : __privateGet(this, _ordered).length;
|
|
109
|
+
}
|
|
110
|
+
indexOfId(id) {
|
|
111
|
+
const physicalIndex = __privateGet(this, _indexById).get(id);
|
|
112
|
+
if (physicalIndex === void 0 || !__privateGet(this, _hasGaps)) {
|
|
113
|
+
return physicalIndex ?? -1;
|
|
114
|
+
}
|
|
115
|
+
let logicalIndex = 0;
|
|
116
|
+
for (let index = 0; index < physicalIndex; index++) {
|
|
117
|
+
const entry = __privateGet(this, _ordered)[index];
|
|
118
|
+
if (entry && __privateGet(this, _entries).get(entry.data.id) === entry) logicalIndex++;
|
|
119
|
+
}
|
|
120
|
+
return logicalIndex;
|
|
121
|
+
}
|
|
122
|
+
indexOfValue(value) {
|
|
123
|
+
let logicalIndex = 0;
|
|
124
|
+
for (const entry of __privateGet(this, _ordered)) {
|
|
125
|
+
if (entry && __privateGet(this, _entries).get(entry.data.id) === entry) {
|
|
126
|
+
if (entry.data.value === value) return logicalIndex;
|
|
127
|
+
logicalIndex++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return -1;
|
|
131
|
+
}
|
|
132
|
+
findByData(option) {
|
|
133
|
+
const entry = __privateGet(this, _entries).get(option.id);
|
|
134
|
+
return (entry == null ? void 0 : entry.data) === option ? entry : void 0;
|
|
135
|
+
}
|
|
136
|
+
matching(predicate) {
|
|
137
|
+
const matches = [];
|
|
138
|
+
for (const entry of __privateGet(this, _ordered)) {
|
|
139
|
+
if (entry !== void 0 && __privateGet(this, _entries).get(entry.data.id) === entry && predicate(entry.data)) {
|
|
140
|
+
matches.push(entry);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return matches;
|
|
144
|
+
}
|
|
145
|
+
snapshot() {
|
|
146
|
+
return __privateGet(this, _ordered).filter(
|
|
147
|
+
(entry) => entry !== void 0
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
_entries = new WeakMap();
|
|
152
|
+
_ordered = new WeakMap();
|
|
153
|
+
_indexById = new WeakMap();
|
|
154
|
+
_nextGeneration = new WeakMap();
|
|
155
|
+
_hasGaps = new WeakMap();
|
|
156
|
+
|
|
157
|
+
export { ListControlRegistry, createCoalescedRebuild };
|
|
158
|
+
//# sourceMappingURL=ListControlRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListControlRegistry.js","sources":["../src/list-control/ListControlRegistry.ts"],"sourcesContent":["import type { OptionValue } from \"./ListControlContext\";\n\nexport interface RegisteredOption<Item> {\n data: OptionValue<Item>;\n element: HTMLElement;\n}\n\ninterface RegistryEntry<Item> extends RegisteredOption<Item> {\n generation: number;\n}\n\nexport function createCoalescedRebuild(\n rebuild: () => void,\n enqueue: (callback: () => void) => void = (callback) => {\n // Promise jobs are supported by Chrome 86.\n Promise.resolve().then(callback);\n },\n): { schedule: () => void; cancel: () => void } {\n let pending = false;\n let cancelled = false;\n\n return {\n schedule() {\n if (pending || cancelled) return;\n pending = true;\n enqueue(() => {\n pending = false;\n if (!cancelled) rebuild();\n });\n },\n cancel() {\n cancelled = true;\n pending = false;\n },\n };\n}\n\n/** Internal option registry optimized for large, non-virtualized lists. */\nexport class ListControlRegistry<Item> {\n readonly #entries = new Map<string, RegistryEntry<Item>>();\n #ordered: (RegistryEntry<Item> | undefined)[] = [];\n #indexById = new Map<string, number>();\n #nextGeneration = 0;\n #hasGaps = false;\n\n register(option: OptionValue<Item>, element: HTMLElement): () => void {\n const entry: RegistryEntry<Item> = {\n data: option,\n element,\n generation: this.#nextGeneration++,\n };\n this.#entries.set(option.id, entry);\n\n const currentIndex = this.#indexById.get(option.id);\n if (currentIndex === undefined) {\n this.#indexById.set(option.id, this.#ordered.length);\n this.#ordered.push(entry);\n } else {\n this.#ordered[currentIndex] = entry;\n }\n\n return () => {\n const current = this.#entries.get(option.id);\n if (current?.generation !== entry.generation) {\n return;\n }\n this.#entries.delete(option.id);\n\n const index = this.#indexById.get(option.id);\n if (index !== undefined && this.#ordered[index] === entry) {\n // Rebuild compacts the snapshot after the corresponding DOM removal.\n this.#ordered[index] = undefined;\n this.#indexById.delete(option.id);\n this.#hasGaps = true;\n }\n };\n }\n\n rebuild(listElement: Pick<HTMLElement, \"querySelectorAll\">): void {\n const ordered: RegistryEntry<Item>[] = [];\n const indexById = new Map<string, number>();\n\n for (const element of listElement.querySelectorAll<HTMLElement>(\n '[role=\"option\"]',\n )) {\n const entry = this.#entries.get(element.id);\n if (entry?.element === element && element.isConnected) {\n indexById.set(entry.data.id, ordered.length);\n ordered.push(entry);\n }\n }\n\n for (const id of this.#entries.keys()) {\n if (!indexById.has(id)) {\n this.#entries.delete(id);\n }\n }\n\n this.#ordered = ordered;\n this.#indexById = indexById;\n this.#hasGaps = false;\n }\n\n getAt(index: number): RegisteredOption<Item> | undefined {\n if (!this.#hasGaps) {\n return this.#ordered[index];\n }\n\n let currentIndex = 0;\n for (const entry of this.#ordered) {\n if (entry && this.#entries.get(entry.data.id) === entry) {\n if (currentIndex === index) return entry;\n currentIndex++;\n }\n }\n return undefined;\n }\n\n get length(): number {\n return this.#hasGaps ? this.#entries.size : this.#ordered.length;\n }\n\n indexOfId(id: string): number {\n const physicalIndex = this.#indexById.get(id);\n if (physicalIndex === undefined || !this.#hasGaps) {\n return physicalIndex ?? -1;\n }\n\n let logicalIndex = 0;\n for (let index = 0; index < physicalIndex; index++) {\n const entry = this.#ordered[index];\n if (entry && this.#entries.get(entry.data.id) === entry) logicalIndex++;\n }\n return logicalIndex;\n }\n\n indexOfValue(value: Item): number {\n let logicalIndex = 0;\n for (const entry of this.#ordered) {\n if (entry && this.#entries.get(entry.data.id) === entry) {\n if (entry.data.value === value) return logicalIndex;\n logicalIndex++;\n }\n }\n return -1;\n }\n\n findByData(option: OptionValue<Item>): RegisteredOption<Item> | undefined {\n const entry = this.#entries.get(option.id);\n return entry?.data === option ? entry : undefined;\n }\n\n matching(\n predicate: (option: OptionValue<Item>) => boolean,\n ): RegisteredOption<Item>[] {\n const matches: RegistryEntry<Item>[] = [];\n for (const entry of this.#ordered) {\n if (\n entry !== undefined &&\n this.#entries.get(entry.data.id) === entry &&\n predicate(entry.data)\n ) {\n matches.push(entry);\n }\n }\n return matches;\n }\n\n snapshot(): readonly RegisteredOption<Item>[] {\n return this.#ordered.filter(\n (entry): entry is RegistryEntry<Item> => entry !== undefined,\n );\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,IAAA,QAAA,EAAA,QAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA;AAWO,SAAS,sBAAA,CACd,OAAA,EACA,OAAA,GAA0C,CAAC,QAAA,KAAa;AAEtD,EAAA,OAAA,CAAQ,OAAA,EAAQ,CAAE,IAAA,CAAK,QAAQ,CAAA;AACjC,CAAA,EAC8C;AAC9C,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,EAAA,OAAO;AAAA,IACL,QAAA,GAAW;AACT,MAAA,IAAI,WAAW,SAAA,EAAW;AAC1B,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,OAAA,CAAQ,MAAM;AACZ,QAAA,OAAA,GAAU,KAAA;AACV,QAAA,IAAI,CAAC,WAAW,OAAA,EAAQ;AAAA,MAC1B,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,MAAA,GAAS;AACP,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,OAAA,GAAU,KAAA;AAAA,IACZ;AAAA,GACF;AACF;AAGO,MAAM,mBAAA,CAA0B;AAAA,EAAhC,WAAA,GAAA;AACL,IAAA,YAAA,CAAA,IAAA,EAAS,QAAA,sBAAe,GAAA,EAAiC,CAAA;AACzD,IAAA,YAAA,CAAA,IAAA,EAAA,QAAA,EAAgD,EAAC,CAAA;AACjD,IAAA,YAAA,CAAA,IAAA,EAAA,UAAA,sBAAiB,GAAA,EAAoB,CAAA;AACrC,IAAA,YAAA,CAAA,IAAA,EAAA,eAAA,EAAkB,CAAA,CAAA;AAClB,IAAA,YAAA,CAAA,IAAA,EAAA,QAAA,EAAW,KAAA,CAAA;AAAA,EAAA;AAAA,EAEX,QAAA,CAAS,QAA2B,OAAA,EAAkC;AACpE,IAAA,MAAM,KAAA,GAA6B;AAAA,MACjC,IAAA,EAAM,MAAA;AAAA,MACN,OAAA;AAAA,MACA,UAAA,EAAY,uBAAK,eAAA,CAAA,CAAL,CAAA;AAAA,KACd;AACA,IAAA,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,KAAK,CAAA;AAElC,IAAA,MAAM,YAAA,GAAe,YAAA,CAAA,IAAA,EAAK,UAAA,CAAA,CAAW,GAAA,CAAI,OAAO,EAAE,CAAA;AAClD,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,YAAA,CAAA,IAAA,EAAK,YAAW,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,YAAA,CAAA,IAAA,EAAK,UAAS,MAAM,CAAA;AACnD,MAAA,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,KAAK,KAAK,CAAA;AAAA,IAC1B,CAAA,MAAO;AACL,MAAA,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,YAAY,CAAA,GAAI,KAAA;AAAA,IAChC;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,MAAM,OAAA,GAAU,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,OAAO,EAAE,CAAA;AAC3C,MAAA,IAAA,CAAI,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,UAAA,MAAe,KAAA,CAAM,UAAA,EAAY;AAC5C,QAAA;AAAA,MACF;AACA,MAAA,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAE9B,MAAA,MAAM,KAAA,GAAQ,YAAA,CAAA,IAAA,EAAK,UAAA,CAAA,CAAW,GAAA,CAAI,OAAO,EAAE,CAAA;AAC3C,MAAA,IAAI,UAAU,MAAA,IAAa,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,KAAK,MAAM,KAAA,EAAO;AAEzD,QAAA,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,KAAK,CAAA,GAAI,MAAA;AACvB,QAAA,YAAA,CAAA,IAAA,EAAK,UAAA,CAAA,CAAW,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAChC,QAAA,YAAA,CAAA,IAAA,EAAK,QAAA,EAAW,IAAA,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAAA,EACF;AAAA,EAEA,QAAQ,WAAA,EAA0D;AAChE,IAAA,MAAM,UAAiC,EAAC;AACxC,IAAA,MAAM,SAAA,uBAAgB,GAAA,EAAoB;AAE1C,IAAA,KAAA,MAAW,WAAW,WAAA,CAAY,gBAAA;AAAA,MAChC;AAAA,KACF,EAAG;AACD,MAAA,MAAM,KAAA,GAAQ,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,QAAQ,EAAE,CAAA;AAC1C,MAAA,IAAA,CAAI,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,OAAA,MAAY,OAAA,IAAW,OAAA,CAAQ,WAAA,EAAa;AACrD,QAAA,SAAA,CAAU,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,EAAA,EAAI,QAAQ,MAAM,CAAA;AAC3C,QAAA,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,MACpB;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,EAAA,IAAM,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,IAAA,EAAK,EAAG;AACrC,MAAA,IAAI,CAAC,SAAA,CAAU,GAAA,CAAI,EAAE,CAAA,EAAG;AACtB,QAAA,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,OAAO,EAAE,CAAA;AAAA,MACzB;AAAA,IACF;AAEA,IAAA,YAAA,CAAA,IAAA,EAAK,QAAA,EAAW,OAAA,CAAA;AAChB,IAAA,YAAA,CAAA,IAAA,EAAK,UAAA,EAAa,SAAA,CAAA;AAClB,IAAA,YAAA,CAAA,IAAA,EAAK,QAAA,EAAW,KAAA,CAAA;AAAA,EAClB;AAAA,EAEA,MAAM,KAAA,EAAmD;AACvD,IAAA,IAAI,CAAC,mBAAK,QAAA,CAAA,EAAU;AAClB,MAAA,OAAO,YAAA,CAAA,IAAA,EAAK,UAAS,KAAK,CAAA;AAAA,IAC5B;AAEA,IAAA,IAAI,YAAA,GAAe,CAAA;AACnB,IAAA,KAAA,MAAW,KAAA,IAAS,mBAAK,QAAA,CAAA,EAAU;AACjC,MAAA,IAAI,KAAA,IAAS,mBAAK,QAAA,CAAA,CAAS,GAAA,CAAI,MAAM,IAAA,CAAK,EAAE,MAAM,KAAA,EAAO;AACvD,QAAA,IAAI,YAAA,KAAiB,OAAO,OAAO,KAAA;AACnC,QAAA,YAAA,EAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,IAAI,MAAA,GAAiB;AACnB,IAAA,OAAO,mBAAK,QAAA,CAAA,GAAW,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,IAAA,GAAO,mBAAK,QAAA,CAAA,CAAS,MAAA;AAAA,EAC5D;AAAA,EAEA,UAAU,EAAA,EAAoB;AAC5B,IAAA,MAAM,aAAA,GAAgB,YAAA,CAAA,IAAA,EAAK,UAAA,CAAA,CAAW,GAAA,CAAI,EAAE,CAAA;AAC5C,IAAA,IAAI,aAAA,KAAkB,MAAA,IAAa,CAAC,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,EAAU;AACjD,MAAA,OAAO,aAAA,IAAiB,EAAA;AAAA,IAC1B;AAEA,IAAA,IAAI,YAAA,GAAe,CAAA;AACnB,IAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,aAAA,EAAe,KAAA,EAAA,EAAS;AAClD,MAAA,MAAM,KAAA,GAAQ,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,KAAK,CAAA;AACjC,MAAA,IAAI,KAAA,IAAS,mBAAK,QAAA,CAAA,CAAS,GAAA,CAAI,MAAM,IAAA,CAAK,EAAE,MAAM,KAAA,EAAO,YAAA,EAAA;AAAA,IAC3D;AACA,IAAA,OAAO,YAAA;AAAA,EACT;AAAA,EAEA,aAAa,KAAA,EAAqB;AAChC,IAAA,IAAI,YAAA,GAAe,CAAA;AACnB,IAAA,KAAA,MAAW,KAAA,IAAS,mBAAK,QAAA,CAAA,EAAU;AACjC,MAAA,IAAI,KAAA,IAAS,mBAAK,QAAA,CAAA,CAAS,GAAA,CAAI,MAAM,IAAA,CAAK,EAAE,MAAM,KAAA,EAAO;AACvD,QAAA,IAAI,KAAA,CAAM,IAAA,CAAK,KAAA,KAAU,KAAA,EAAO,OAAO,YAAA;AACvC,QAAA,YAAA,EAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,EAAA;AAAA,EACT;AAAA,EAEA,WAAW,MAAA,EAA+D;AACxE,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,OAAO,EAAE,CAAA;AACzC,IAAA,OAAA,CAAO,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,IAAA,MAAS,MAAA,GAAS,KAAA,GAAQ,MAAA;AAAA,EAC1C;AAAA,EAEA,SACE,SAAA,EAC0B;AAC1B,IAAA,MAAM,UAAiC,EAAC;AACxC,IAAA,KAAA,MAAW,KAAA,IAAS,mBAAK,QAAA,CAAA,EAAU;AACjC,MAAA,IACE,KAAA,KAAU,MAAA,IACV,YAAA,CAAA,IAAA,EAAK,QAAA,CAAA,CAAS,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,KAAM,KAAA,IACrC,SAAA,CAAU,KAAA,CAAM,IAAI,CAAA,EACpB;AACA,QAAA,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,MACpB;AAAA,IACF;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,QAAA,GAA8C;AAC5C,IAAA,OAAO,mBAAK,QAAA,CAAA,CAAS,MAAA;AAAA,MACnB,CAAC,UAAwC,KAAA,KAAU;AAAA,KACrD;AAAA,EACF;AACF;AAtIW,QAAA,GAAA,IAAA,OAAA,EAAA;AACT,QAAA,GAAA,IAAA,OAAA,EAAA;AACA,UAAA,GAAA,IAAA,OAAA,EAAA;AACA,eAAA,GAAA,IAAA,OAAA,EAAA;AACA,QAAA,GAAA,IAAA,OAAA,EAAA;;;;"}
|