react-stately 3.48.0 → 3.49.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.
Files changed (134) hide show
  1. package/dist/exports/index.cjs +6 -0
  2. package/dist/exports/index.cjs.map +1 -1
  3. package/dist/exports/index.js +5 -1
  4. package/dist/exports/index.js.map +1 -1
  5. package/dist/exports/index.mjs +5 -1
  6. package/dist/exports/index.mjs.map +1 -1
  7. package/dist/exports/useTokenFieldState.cjs +25 -0
  8. package/dist/exports/useTokenFieldState.cjs.map +1 -0
  9. package/dist/exports/useTokenFieldState.js +19 -0
  10. package/dist/exports/useTokenFieldState.js.map +1 -0
  11. package/dist/exports/useTokenFieldState.mjs +19 -0
  12. package/dist/exports/useTokenFieldState.mjs.map +1 -0
  13. package/dist/private/combobox/useComboBoxState.cjs +2 -1
  14. package/dist/private/combobox/useComboBoxState.cjs.map +1 -1
  15. package/dist/private/combobox/useComboBoxState.js +2 -1
  16. package/dist/private/combobox/useComboBoxState.js.map +1 -1
  17. package/dist/private/combobox/useComboBoxState.mjs +2 -1
  18. package/dist/private/combobox/useComboBoxState.mjs.map +1 -1
  19. package/dist/private/data/useTreeData.cjs +1 -0
  20. package/dist/private/data/useTreeData.cjs.map +1 -1
  21. package/dist/private/data/useTreeData.js +1 -0
  22. package/dist/private/data/useTreeData.js.map +1 -1
  23. package/dist/private/data/useTreeData.mjs +1 -0
  24. package/dist/private/data/useTreeData.mjs.map +1 -1
  25. package/dist/private/datepicker/useDateRangePickerState.cjs +1 -0
  26. package/dist/private/datepicker/useDateRangePickerState.cjs.map +1 -1
  27. package/dist/private/datepicker/useDateRangePickerState.js +1 -0
  28. package/dist/private/datepicker/useDateRangePickerState.js.map +1 -1
  29. package/dist/private/datepicker/useDateRangePickerState.mjs +1 -0
  30. package/dist/private/datepicker/useDateRangePickerState.mjs.map +1 -1
  31. package/dist/private/form/useFormValidationState.cjs +1 -1
  32. package/dist/private/form/useFormValidationState.cjs.map +1 -1
  33. package/dist/private/form/useFormValidationState.js +1 -1
  34. package/dist/private/form/useFormValidationState.js.map +1 -1
  35. package/dist/private/form/useFormValidationState.mjs +1 -1
  36. package/dist/private/form/useFormValidationState.mjs.map +1 -1
  37. package/dist/private/grid/useGridState.cjs +12 -10
  38. package/dist/private/grid/useGridState.cjs.map +1 -1
  39. package/dist/private/grid/useGridState.js +12 -10
  40. package/dist/private/grid/useGridState.js.map +1 -1
  41. package/dist/private/grid/useGridState.mjs +12 -10
  42. package/dist/private/grid/useGridState.mjs.map +1 -1
  43. package/dist/private/layout/ListLayout.cjs +0 -3
  44. package/dist/private/layout/ListLayout.cjs.map +1 -1
  45. package/dist/private/layout/ListLayout.js +0 -3
  46. package/dist/private/layout/ListLayout.js.map +1 -1
  47. package/dist/private/layout/ListLayout.mjs +0 -3
  48. package/dist/private/layout/ListLayout.mjs.map +1 -1
  49. package/dist/private/menu/useMenuTriggerState.cjs.map +1 -1
  50. package/dist/private/menu/useMenuTriggerState.js.map +1 -1
  51. package/dist/private/menu/useMenuTriggerState.mjs.map +1 -1
  52. package/dist/private/menu/useSubmenuTriggerState.cjs +3 -1
  53. package/dist/private/menu/useSubmenuTriggerState.cjs.map +1 -1
  54. package/dist/private/menu/useSubmenuTriggerState.js +3 -1
  55. package/dist/private/menu/useSubmenuTriggerState.js.map +1 -1
  56. package/dist/private/menu/useSubmenuTriggerState.mjs +3 -1
  57. package/dist/private/menu/useSubmenuTriggerState.mjs.map +1 -1
  58. package/dist/private/overlays/useOverlayTriggerState.cjs +4 -1
  59. package/dist/private/overlays/useOverlayTriggerState.cjs.map +1 -1
  60. package/dist/private/overlays/useOverlayTriggerState.js +5 -2
  61. package/dist/private/overlays/useOverlayTriggerState.js.map +1 -1
  62. package/dist/private/overlays/useOverlayTriggerState.mjs +5 -2
  63. package/dist/private/overlays/useOverlayTriggerState.mjs.map +1 -1
  64. package/dist/private/select/useSelectState.cjs +1 -0
  65. package/dist/private/select/useSelectState.cjs.map +1 -1
  66. package/dist/private/select/useSelectState.js +1 -0
  67. package/dist/private/select/useSelectState.js.map +1 -1
  68. package/dist/private/select/useSelectState.mjs +1 -0
  69. package/dist/private/select/useSelectState.mjs.map +1 -1
  70. package/dist/private/slider/useSliderState.cjs.map +1 -1
  71. package/dist/private/slider/useSliderState.js.map +1 -1
  72. package/dist/private/slider/useSliderState.mjs.map +1 -1
  73. package/dist/private/table/TableUtils.cjs +13 -1
  74. package/dist/private/table/TableUtils.cjs.map +1 -1
  75. package/dist/private/table/TableUtils.js +13 -1
  76. package/dist/private/table/TableUtils.js.map +1 -1
  77. package/dist/private/table/TableUtils.mjs +13 -1
  78. package/dist/private/table/TableUtils.mjs.map +1 -1
  79. package/dist/private/table/useTableState.cjs +1 -0
  80. package/dist/private/table/useTableState.cjs.map +1 -1
  81. package/dist/private/table/useTableState.js +1 -0
  82. package/dist/private/table/useTableState.js.map +1 -1
  83. package/dist/private/table/useTableState.mjs +1 -0
  84. package/dist/private/table/useTableState.mjs.map +1 -1
  85. package/dist/private/tokenfield/TokenFieldValue.cjs +287 -0
  86. package/dist/private/tokenfield/TokenFieldValue.cjs.map +1 -0
  87. package/dist/private/tokenfield/TokenFieldValue.js +285 -0
  88. package/dist/private/tokenfield/TokenFieldValue.js.map +1 -0
  89. package/dist/private/tokenfield/TokenFieldValue.mjs +282 -0
  90. package/dist/private/tokenfield/TokenFieldValue.mjs.map +1 -0
  91. package/dist/private/tokenfield/useTokenFieldState.cjs +37 -0
  92. package/dist/private/tokenfield/useTokenFieldState.cjs.map +1 -0
  93. package/dist/private/tokenfield/useTokenFieldState.js +32 -0
  94. package/dist/private/tokenfield/useTokenFieldState.js.map +1 -0
  95. package/dist/private/tokenfield/useTokenFieldState.mjs +32 -0
  96. package/dist/private/tokenfield/useTokenFieldState.mjs.map +1 -0
  97. package/dist/private/tooltip/useTooltipTriggerState.cjs +18 -6
  98. package/dist/private/tooltip/useTooltipTriggerState.cjs.map +1 -1
  99. package/dist/private/tooltip/useTooltipTriggerState.js +19 -7
  100. package/dist/private/tooltip/useTooltipTriggerState.js.map +1 -1
  101. package/dist/private/tooltip/useTooltipTriggerState.mjs +19 -7
  102. package/dist/private/tooltip/useTooltipTriggerState.mjs.map +1 -1
  103. package/dist/private/virtualizer/ScrollAnchor.cjs +136 -0
  104. package/dist/private/virtualizer/ScrollAnchor.cjs.map +1 -0
  105. package/dist/private/virtualizer/ScrollAnchor.js +132 -0
  106. package/dist/private/virtualizer/ScrollAnchor.js.map +1 -0
  107. package/dist/private/virtualizer/ScrollAnchor.mjs +131 -0
  108. package/dist/private/virtualizer/ScrollAnchor.mjs.map +1 -0
  109. package/dist/private/virtualizer/Virtualizer.cjs +50 -1
  110. package/dist/private/virtualizer/Virtualizer.cjs.map +1 -1
  111. package/dist/private/virtualizer/Virtualizer.js +54 -1
  112. package/dist/private/virtualizer/Virtualizer.js.map +1 -1
  113. package/dist/private/virtualizer/Virtualizer.mjs +50 -1
  114. package/dist/private/virtualizer/Virtualizer.mjs.map +1 -1
  115. package/dist/private/virtualizer/useVirtualizerState.cjs +2 -1
  116. package/dist/private/virtualizer/useVirtualizerState.cjs.map +1 -1
  117. package/dist/private/virtualizer/useVirtualizerState.js +2 -1
  118. package/dist/private/virtualizer/useVirtualizerState.js.map +1 -1
  119. package/dist/private/virtualizer/useVirtualizerState.mjs +2 -1
  120. package/dist/private/virtualizer/useVirtualizerState.mjs.map +1 -1
  121. package/dist/types/exports/index.d.ts +4 -0
  122. package/dist/types/exports/useTokenFieldState.d.ts +4 -0
  123. package/dist/types/src/combobox/useComboBoxState.d.ts +1 -1
  124. package/dist/types/src/menu/useMenuTriggerState.d.ts +1 -1
  125. package/dist/types/src/overlays/useOverlayTriggerState.d.ts +9 -0
  126. package/dist/types/src/table/useTableState.d.ts +7 -0
  127. package/dist/types/src/tokenfield/TokenFieldValue.d.ts +71 -0
  128. package/dist/types/src/tokenfield/useTokenFieldState.d.ts +19 -0
  129. package/dist/types/src/tooltip/useTooltipTriggerState.d.ts +5 -0
  130. package/dist/types/src/virtualizer/ScrollAnchor.d.ts +81 -0
  131. package/dist/types/src/virtualizer/Virtualizer.d.ts +1 -0
  132. package/dist/types/src/virtualizer/types.d.ts +2 -0
  133. package/package.json +5 -5
  134. package/useTokenFieldState/package.json +5 -0
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/react-stately/src/combobox/useComboBoxState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n Collection,\n CollectionBase,\n CollectionStateBase,\n FocusableProps,\n FocusStrategy,\n HelpTextProps,\n InputBase,\n Key,\n LabelableProps,\n Node,\n Selection,\n TextInputBase,\n Validation,\n ValueBase\n} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '../form/useFormValidationState';\nimport {getChildNodes} from '../collections/getChildNodes';\nimport {ListCollection} from '../list/ListCollection';\nimport {ListState, useListState} from '../list/useListState';\nimport {OverlayTriggerState, useOverlayTriggerState} from '../overlays/useOverlayTriggerState';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {useControlledState} from '../utils/useControlledState';\n\nexport type MenuTriggerAction = 'focus' | 'input' | 'manual';\nexport type SelectionMode = 'single' | 'multiple';\nexport type ValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\nexport type ChangeValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\ntype ValidationType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\n\nexport interface ComboBoxValidationValue<M extends SelectionMode = 'single'> {\n /**\n * The selected key in the ComboBox.\n *\n * @deprecated\n */\n selectedKey: Key | null;\n /** The keys of the currently selected items. */\n value: ValidationType<M>;\n /** The value of the ComboBox input. */\n inputValue: string;\n}\n\nexport interface ComboBoxProps<T, M extends SelectionMode = 'single'>\n extends\n CollectionBase<T>,\n InputBase,\n ValueBase<ValueType<M>, ChangeValueType<M>>,\n TextInputBase,\n Validation<ComboBoxValidationValue<M>>,\n FocusableProps<HTMLInputElement>,\n LabelableProps,\n HelpTextProps {\n /** The list of ComboBox items (uncontrolled). */\n defaultItems?: Iterable<T>;\n /** The list of ComboBox items (controlled). */\n items?: Iterable<T>;\n /**\n * Method that is called when the open state of the menu changes. Returns the new open state and\n * the action that caused the opening of the menu.\n */\n onOpenChange?: (isOpen: boolean, menuTrigger?: MenuTriggerAction) => void;\n /**\n * Whether single or multiple selection is enabled.\n *\n * @default 'single'\n */\n selectionMode?: M;\n /**\n * The currently selected key in the collection (controlled).\n *\n * @deprecated\n */\n selectedKey?: Key | null;\n /**\n * The initial selected key in the collection (uncontrolled).\n *\n * @deprecated\n */\n defaultSelectedKey?: Key | null;\n /**\n * Handler that is called when the selection changes.\n *\n * @deprecated\n */\n onSelectionChange?: (key: Key | null) => void;\n /** The value of the ComboBox input (controlled). */\n inputValue?: string;\n /** The default value of the ComboBox input (uncontrolled). */\n defaultInputValue?: string;\n /** Handler that is called when the ComboBox input value changes. */\n onInputChange?: (value: string) => void;\n /** Whether the ComboBox allows a non-item matching input value to be set. */\n allowsCustomValue?: boolean;\n // /**\n // * Whether the Combobox should only suggest matching options or autocomplete the field with the nearest matching option.\n // * @default 'suggest'\n // */\n // completionMode?: 'suggest' | 'complete',\n /**\n * The interaction required to display the ComboBox menu.\n *\n * @default 'input'\n */\n menuTrigger?: MenuTriggerAction;\n}\n\nexport interface ComboBoxState<T, M extends SelectionMode = 'single'>\n extends ListState<T>, OverlayTriggerState, FormValidationState {\n /**\n * The key for the first selected item.\n *\n * @deprecated\n */\n readonly selectedKey: Key | null;\n\n /**\n * The default selected key.\n *\n * @deprecated\n */\n readonly defaultSelectedKey: Key | null;\n /**\n * Sets the selected key.\n *\n * @deprecated\n */\n setSelectedKey(key: Key | null): void;\n /** The current combobox value. */\n readonly value: ValueType<M>;\n /** The default combobox value. */\n readonly defaultValue: ValueType<M>;\n /** Sets the combobox value. */\n setValue(value: Key | readonly Key[] | null): void;\n /**\n * The value of the first selected item.\n *\n * @deprecated\n */\n readonly selectedItem: Node<T> | null;\n /** The value of the selected items. */\n readonly selectedItems: Node<T>[];\n /** The current value of the combo box input. */\n inputValue: string;\n /** The default value of the combo box input. */\n defaultInputValue: string;\n /** Sets the value of the combo box input. */\n setInputValue(value: string): void;\n /** Selects the currently focused item and updates the input value. */\n commit(): void;\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null;\n /** Whether the select is currently focused. */\n readonly isFocused: boolean;\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void;\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Resets the input value to the previously selected item's text if any and closes the menu. */\n revert(): void;\n}\n\ntype FilterFn = (textValue: string, inputValue: string) => boolean;\n\nexport interface ComboBoxStateOptions<T, M extends SelectionMode = 'single'>\n extends Omit<ComboBoxProps<T, M>, 'children'>, CollectionStateBase<T> {\n /** The filter function used to determine if a option should be included in the combo box list. */\n defaultFilter?: FilterFn;\n /** Whether the combo box allows the menu to be open when the collection is empty. */\n allowsEmptyCollection?: boolean;\n /** Whether the combo box menu should close on blur. */\n shouldCloseOnBlur?: boolean;\n}\n\n/**\n * Provides state management for a combo box component. Handles building a collection of items from\n * props and manages the option selection state of the combo box. In addition, it tracks the input\n * value, focus state, and other properties of the combo box.\n */\nexport function useComboBoxState<T, M extends SelectionMode = 'single'>(\n props: ComboBoxStateOptions<T, M>\n): ComboBoxState<T, M> {\n let {\n defaultFilter,\n menuTrigger = 'input',\n allowsEmptyCollection = false,\n allowsCustomValue,\n shouldCloseOnBlur = true,\n selectionMode = 'single' as SelectionMode\n } = props;\n\n let [showAllItems, setShowAllItems] = useState(false);\n let [isFocused, setFocusedState] = useState(false);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n\n let defaultValue = useMemo(() => {\n return props.defaultValue !== undefined\n ? props.defaultValue\n : ((selectionMode === 'single' ? (props.defaultSelectedKey ?? null) : []) as ValueType<M>);\n }, [props.defaultValue, props.defaultSelectedKey, selectionMode]);\n let value = useMemo(() => {\n return props.value !== undefined\n ? props.value\n : ((selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>);\n }, [props.value, props.selectedKey, selectionMode]);\n let [controlledValue, setControlledValue] = useControlledState<Key | readonly Key[] | null>(\n value,\n defaultValue,\n props.onChange as any\n );\n // Only display the first selected item if in single selection mode but the value is an array.\n let displayValue: ValueType<M> =\n selectionMode === 'single' && Array.isArray(controlledValue)\n ? controlledValue[0]\n : controlledValue;\n\n let setValue = (value: Key | Key[] | null) => {\n if (selectionMode === 'single') {\n let key = Array.isArray(value) ? (value[0] ?? null) : value;\n setControlledValue(key);\n if (key !== displayValue) {\n props.onSelectionChange?.(key);\n }\n } else {\n let keys: Key[] = [];\n if (Array.isArray(value)) {\n keys = value;\n } else if (value != null) {\n keys = [value];\n }\n\n setControlledValue(keys);\n }\n };\n\n let {collection, selectionManager, disabledKeys} = useListState({\n ...props,\n items: props.items ?? props.defaultItems,\n selectionMode,\n disallowEmptySelection: selectionMode === 'single',\n allowDuplicateSelectionEvents: true,\n selectedKeys: useMemo(() => convertValue(displayValue), [displayValue]),\n onSelectionChange: (keys: Selection) => {\n // impossible, but TS doesn't know that\n if (keys === 'all') {\n return;\n }\n\n if (selectionMode === 'single') {\n let key = keys.values().next().value ?? null;\n if (key === displayValue) {\n props.onSelectionChange?.(key);\n // If key is the same, reset the inputValue and close the menu\n // (scenario: user clicks on already selected option)\n resetInputValue();\n closeMenu();\n } else {\n setValue(key);\n }\n } else {\n setValue([...keys]);\n }\n }\n });\n\n let selectedKey = selectionMode === 'single' ? selectionManager.firstSelectedKey : null;\n let selectedItems = useMemo(() => {\n return [...selectionManager.selectedKeys]\n .map(key => collection.getItem(key))\n .filter(item => item != null);\n }, [selectionManager.selectedKeys, collection]);\n\n let [inputValue, setInputValue] = useControlledState(\n props.inputValue,\n getDefaultInputValue(props.defaultInputValue, selectedKey, collection) || '',\n props.onInputChange\n );\n let [initialValue] = useState(displayValue);\n let [initialInputValue] = useState(inputValue);\n\n // Preserve original collection so we can show all items on demand\n let originalCollection = collection;\n let filteredCollection = useMemo(\n () =>\n // No default filter if items are controlled.\n props.items != null || !defaultFilter\n ? collection\n : filterCollection(collection, inputValue, defaultFilter),\n [collection, inputValue, defaultFilter, props.items]\n );\n let [lastCollection, setLastCollection] = useState(filteredCollection);\n\n // Track what action is attempting to open the menu\n let menuOpenTrigger = useRef<MenuTriggerAction | undefined>('focus');\n let onOpenChange = (open: boolean) => {\n if (props.onOpenChange) {\n props.onOpenChange(open, open ? menuOpenTrigger.current : undefined);\n }\n\n selectionManager.setFocused(open);\n if (!open) {\n selectionManager.setFocusedKey(null);\n }\n };\n\n let triggerState = useOverlayTriggerState({\n ...props,\n onOpenChange,\n isOpen: undefined,\n defaultOpen: undefined\n });\n let open = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // Prevent open operations from triggering if there is nothing to display\n // Also prevent open operations from triggering if items are uncontrolled but defaultItems is empty, even if displayAllItems is true.\n // This is to prevent comboboxes with empty defaultItems from opening but allow controlled items comboboxes to open even if the inital list is empty (assumption is user will provide swap the empty list with a base list via onOpenChange returning `menuTrigger` manual)\n if (\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) {\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is manually opened. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n menuOpenTrigger.current = trigger;\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n };\n\n let toggle = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // If the menu is closed and there is nothing to display, early return so toggle isn't called to prevent extraneous onOpenChange\n if (\n !(\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) &&\n !triggerState.isOpen\n ) {\n return;\n }\n\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is toggled open. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n // Only update the menuOpenTrigger if menu is currently closed\n if (!triggerState.isOpen) {\n menuOpenTrigger.current = trigger;\n }\n\n toggleMenu(focusStrategy);\n };\n\n let updateLastCollection = useCallback(() => {\n setLastCollection(showAllItems ? originalCollection : filteredCollection);\n }, [showAllItems, originalCollection, filteredCollection]);\n\n // If menu is going to close, save the current collection so we can freeze the displayed collection when the\n // user clicks outside the popover to close the menu. Prevents the menu contents from updating as the menu closes.\n let toggleMenu = useCallback(\n (focusStrategy: FocusStrategy | null = null) => {\n if (triggerState.isOpen) {\n updateLastCollection();\n }\n\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n },\n [triggerState, updateLastCollection]\n );\n\n let closeMenu = useCallback(() => {\n if (triggerState.isOpen) {\n updateLastCollection();\n triggerState.close();\n }\n }, [triggerState, updateLastCollection]);\n\n let [lastValue, setLastValue] = useState(inputValue);\n let resetInputValue = () => {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n setLastValue(itemText);\n setInputValue(itemText);\n };\n\n let lastValueRef = useRef(displayValue);\n let lastSelectedKeyText = useRef(\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : ''\n );\n // intentional omit dependency array, want this to happen on every render\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => {\n // Open and close menu automatically when the input value changes if the input is focused,\n // and there are items in the collection or allowEmptyCollection is true.\n if (\n isFocused &&\n (filteredCollection.size > 0 || allowsEmptyCollection) &&\n !triggerState.isOpen &&\n inputValue !== lastValue &&\n menuTrigger !== 'manual'\n ) {\n open(null, 'input');\n }\n\n // Close the menu if the collection is empty. Don't close menu if filtered collection size is 0\n // but we are currently showing all items via button press\n if (\n !showAllItems &&\n !allowsEmptyCollection &&\n triggerState.isOpen &&\n filteredCollection.size === 0\n ) {\n closeMenu();\n }\n\n // Close when an item is selected.\n if (\n displayValue != null &&\n displayValue !== lastValueRef.current &&\n selectionMode === 'single'\n ) {\n closeMenu();\n }\n\n // Clear focused key when input value changes and display filtered collection again.\n if (inputValue !== lastValue) {\n selectionManager.setFocusedKey(null);\n setShowAllItems(false);\n\n // Set value to null when the user clears the input.\n // If controlled, this is the application developer's responsibility.\n if (\n selectionMode === 'single' &&\n inputValue === '' &&\n (props.inputValue === undefined || value === undefined)\n ) {\n setValue(null);\n }\n }\n\n // If the value changed, update the input value.\n // Do nothing if both inputValue and value are controlled.\n // In this case, it's the user's responsibility to update inputValue in onSelectionChange.\n if (\n displayValue !== lastValueRef.current &&\n (props.inputValue === undefined || value === undefined)\n ) {\n resetInputValue();\n } else if (lastValue !== inputValue) {\n setLastValue(inputValue);\n }\n\n // Update the inputValue if the selected item's text changes from its last tracked value.\n // This is to handle cases where a selectedKey is specified but the items aren't available (async loading) or the selected item's text value updates.\n // Only reset if the user isn't currently within the field so we don't erroneously modify user input.\n // If inputValue is controlled, it is the user's responsibility to update the inputValue when items change.\n let selectedItemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (\n !isFocused &&\n selectedKey != null &&\n props.inputValue === undefined &&\n selectedKey === lastValueRef.current\n ) {\n if (lastSelectedKeyText.current !== selectedItemText) {\n setLastValue(selectedItemText);\n setInputValue(selectedItemText);\n }\n }\n\n lastValueRef.current = displayValue;\n lastSelectedKeyText.current = selectedItemText;\n });\n\n let validation = useFormValidationState({\n ...props,\n value: useMemo(\n () =>\n Array.isArray(displayValue) && displayValue.length === 0\n ? null\n : {inputValue, value: displayValue as any, selectedKey},\n [inputValue, selectedKey, displayValue]\n )\n });\n\n // Revert input value and close menu\n let revert = () => {\n if (allowsCustomValue && selectedKey == null) {\n commitCustomValue();\n } else {\n commitSelection();\n }\n };\n\n let commitCustomValue = () => {\n if (selectionMode === 'multiple') {\n // In multi-select mode, the input's custom text is independent from the selected items.\n // Closing or committing the field should not clear the existing selection.\n setLastValue(inputValue);\n closeMenu();\n return;\n }\n\n let value = null;\n lastValueRef.current = value as any;\n setValue(value);\n closeMenu();\n };\n\n let commitSelection = (shouldForceSelectionChange = false) => {\n // If multiple things are controlled, call onSelectionChange only when selecting the focused item,\n // or when inputValue needs to be synced back to the selected item on commit/blur.\n if (value !== undefined && props.inputValue !== undefined) {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (shouldForceSelectionChange || selectionMode === 'multiple' || inputValue !== itemText) {\n props.onSelectionChange?.(selectedKey);\n props.onChange?.(displayValue as ChangeValueType<M>);\n }\n\n // Stop menu from reopening from useEffect\n setLastValue(itemText);\n closeMenu();\n } else {\n // If only a single aspect of combobox is controlled, reset input value and close menu for the user\n resetInputValue();\n closeMenu();\n }\n };\n\n const commitValue = () => {\n if (allowsCustomValue) {\n const itemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n inputValue === itemText ? commitSelection() : commitCustomValue();\n } else {\n // Reset inputValue and close menu\n commitSelection();\n }\n };\n\n let commit = () => {\n if (triggerState.isOpen && selectionManager.focusedKey != null) {\n // Reset inputValue and close menu here if the selected key is already the focused key. Otherwise\n // fire onSelectionChange to allow the application to control the closing.\n if (selectionManager.isSelected(selectionManager.focusedKey) && selectionMode === 'single') {\n commitSelection(true);\n } else {\n selectionManager.select(selectionManager.focusedKey);\n }\n } else {\n commitValue();\n }\n };\n\n let valueOnFocus = useRef([inputValue, displayValue]);\n let setFocused = (isFocused: boolean) => {\n if (isFocused) {\n valueOnFocus.current = [inputValue, displayValue];\n if (menuTrigger === 'focus' && !props.isReadOnly) {\n open(null, 'focus');\n }\n } else {\n if (shouldCloseOnBlur) {\n commitValue();\n }\n\n // Commit validation if the input value or selected items changed.\n if (inputValue !== valueOnFocus.current[0] || displayValue !== valueOnFocus.current[1]) {\n validation.commitValidation();\n }\n }\n\n setFocusedState(isFocused);\n };\n\n let displayedCollection = useMemo(() => {\n if (triggerState.isOpen) {\n if (showAllItems) {\n return originalCollection;\n } else {\n return filteredCollection;\n }\n } else {\n return lastCollection;\n }\n }, [triggerState.isOpen, originalCollection, filteredCollection, showAllItems, lastCollection]);\n\n let defaultSelectedKey =\n props.defaultSelectedKey ?? (selectionMode === 'single' ? (initialValue as Key) : null);\n\n return {\n ...validation,\n ...triggerState,\n focusStrategy,\n toggle,\n open,\n close: commitValue,\n selectionManager,\n value: displayValue as any,\n defaultValue: defaultValue ?? (initialValue as any),\n setValue,\n selectedKey,\n selectedItems,\n defaultSelectedKey,\n setSelectedKey: setValue,\n disabledKeys,\n isFocused,\n setFocused,\n selectedItem: selectedItems[0] ?? null,\n collection: displayedCollection,\n inputValue,\n defaultInputValue:\n getDefaultInputValue(props.defaultInputValue, defaultSelectedKey, collection) ??\n initialInputValue,\n setInputValue,\n commit,\n revert\n };\n}\n\nfunction filterCollection<T>(\n collection: Collection<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Collection<Node<T>> {\n return new ListCollection(filterNodes(collection, collection, inputValue, filter));\n}\n\nfunction filterNodes<T>(\n collection: Collection<Node<T>>,\n nodes: Iterable<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Iterable<Node<T>> {\n let filteredNode: Node<T>[] = [];\n for (let node of nodes) {\n if (node.type === 'section' && node.hasChildNodes) {\n let filtered = filterNodes(collection, getChildNodes(node, collection), inputValue, filter);\n if ([...filtered].some(node => node.type === 'item')) {\n filteredNode.push({...node, childNodes: filtered});\n }\n } else if (node.type === 'item' && filter(node.textValue, inputValue)) {\n filteredNode.push({...node});\n } else if (node.type !== 'item') {\n filteredNode.push({...node});\n }\n }\n return filteredNode;\n}\n\nfunction getDefaultInputValue(\n defaultInputValue: string | null | undefined,\n selectedKey: Key | null,\n collection: Collection<Node<unknown>>\n) {\n if (defaultInputValue == null) {\n if (selectedKey != null) {\n return collection.getItem(selectedKey)?.textValue ?? '';\n }\n }\n\n return defaultInputValue;\n}\n\nfunction convertValue(value: Key | readonly Key[] | null | undefined) {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n"],"names":[],"version":3,"file":"useComboBoxState.js.map"}
1
+ {"mappings":"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","sources":["packages/react-stately/src/combobox/useComboBoxState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n Collection,\n CollectionBase,\n CollectionStateBase,\n FocusableProps,\n FocusStrategy,\n HelpTextProps,\n InputBase,\n Key,\n LabelableProps,\n Node,\n Selection,\n TextInputBase,\n Validation,\n ValueBase\n} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '../form/useFormValidationState';\nimport {getChildNodes} from '../collections/getChildNodes';\nimport {ListCollection} from '../list/ListCollection';\nimport {ListState, useListState} from '../list/useListState';\nimport {OverlayTriggerState, useOverlayTriggerState} from '../overlays/useOverlayTriggerState';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {useControlledState} from '../utils/useControlledState';\n\nexport type MenuTriggerAction = 'focus' | 'input' | 'manual';\nexport type SelectionMode = 'single' | 'multiple';\nexport type ValueType<M extends SelectionMode> = M extends 'single' ? Key | null : readonly Key[];\nexport type ChangeValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\ntype ValidationType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\n\nexport interface ComboBoxValidationValue<M extends SelectionMode = 'single'> {\n /**\n * The selected key in the ComboBox.\n *\n * @deprecated\n */\n selectedKey: Key | null;\n /** The keys of the currently selected items. */\n value: ValidationType<M>;\n /** The value of the ComboBox input. */\n inputValue: string;\n}\n\nexport interface ComboBoxProps<T, M extends SelectionMode = 'single'>\n extends\n CollectionBase<T>,\n InputBase,\n ValueBase<ValueType<M>, ChangeValueType<M>>,\n TextInputBase,\n Validation<ComboBoxValidationValue<M>>,\n FocusableProps<HTMLInputElement>,\n LabelableProps,\n HelpTextProps {\n /** The list of ComboBox items (uncontrolled). */\n defaultItems?: Iterable<T>;\n /** The list of ComboBox items (controlled). */\n items?: Iterable<T>;\n /**\n * Method that is called when the open state of the menu changes. Returns the new open state and\n * the action that caused the opening of the menu.\n */\n onOpenChange?: (isOpen: boolean, menuTrigger?: MenuTriggerAction) => void;\n /**\n * Whether single or multiple selection is enabled.\n *\n * @default 'single'\n */\n selectionMode?: M;\n /**\n * The currently selected key in the collection (controlled).\n *\n * @deprecated\n */\n selectedKey?: Key | null;\n /**\n * The initial selected key in the collection (uncontrolled).\n *\n * @deprecated\n */\n defaultSelectedKey?: Key | null;\n /**\n * Handler that is called when the selection changes.\n *\n * @deprecated\n */\n onSelectionChange?: (key: Key | null) => void;\n /** The value of the ComboBox input (controlled). */\n inputValue?: string;\n /** The default value of the ComboBox input (uncontrolled). */\n defaultInputValue?: string;\n /** Handler that is called when the ComboBox input value changes. */\n onInputChange?: (value: string) => void;\n /** Whether the ComboBox allows a non-item matching input value to be set. */\n allowsCustomValue?: boolean;\n // /**\n // * Whether the Combobox should only suggest matching options or autocomplete the field with the nearest matching option.\n // * @default 'suggest'\n // */\n // completionMode?: 'suggest' | 'complete',\n /**\n * The interaction required to display the ComboBox menu.\n *\n * @default 'input'\n */\n menuTrigger?: MenuTriggerAction;\n}\n\nexport interface ComboBoxState<T, M extends SelectionMode = 'single'>\n extends ListState<T>, OverlayTriggerState, FormValidationState {\n /**\n * The key for the first selected item.\n *\n * @deprecated\n */\n readonly selectedKey: Key | null;\n\n /**\n * The default selected key.\n *\n * @deprecated\n */\n readonly defaultSelectedKey: Key | null;\n /**\n * Sets the selected key.\n *\n * @deprecated\n */\n setSelectedKey(key: Key | null): void;\n /** The current combobox value. */\n readonly value: ValueType<M>;\n /** The default combobox value. */\n readonly defaultValue: ValueType<M>;\n /** Sets the combobox value. */\n setValue(value: Key | readonly Key[] | null): void;\n /**\n * The value of the first selected item.\n *\n * @deprecated\n */\n readonly selectedItem: Node<T> | null;\n /** The value of the selected items. */\n readonly selectedItems: Node<T>[];\n /** The current value of the combo box input. */\n inputValue: string;\n /** The default value of the combo box input. */\n defaultInputValue: string;\n /** Sets the value of the combo box input. */\n setInputValue(value: string): void;\n /** Selects the currently focused item and updates the input value. */\n commit(): void;\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null;\n /** Whether the select is currently focused. */\n readonly isFocused: boolean;\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void;\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Resets the input value to the previously selected item's text if any and closes the menu. */\n revert(): void;\n}\n\ntype FilterFn = (textValue: string, inputValue: string) => boolean;\n\nexport interface ComboBoxStateOptions<T, M extends SelectionMode = 'single'>\n extends Omit<ComboBoxProps<T, M>, 'children'>, CollectionStateBase<T> {\n /** The filter function used to determine if a option should be included in the combo box list. */\n defaultFilter?: FilterFn;\n /** Whether the combo box allows the menu to be open when the collection is empty. */\n allowsEmptyCollection?: boolean;\n /** Whether the combo box menu should close on blur. */\n shouldCloseOnBlur?: boolean;\n}\n\n/**\n * Provides state management for a combo box component. Handles building a collection of items from\n * props and manages the option selection state of the combo box. In addition, it tracks the input\n * value, focus state, and other properties of the combo box.\n */\nexport function useComboBoxState<T, M extends SelectionMode = 'single'>(\n props: ComboBoxStateOptions<T, M>\n): ComboBoxState<T, M> {\n let {\n defaultFilter,\n menuTrigger = 'input',\n allowsEmptyCollection = false,\n allowsCustomValue,\n shouldCloseOnBlur = true,\n selectionMode = 'single' as SelectionMode\n } = props;\n\n let [showAllItems, setShowAllItems] = useState(false);\n let [isFocused, setFocusedState] = useState(false);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n\n let defaultValue = useMemo(() => {\n return props.defaultValue !== undefined\n ? props.defaultValue\n : ((selectionMode === 'single' ? (props.defaultSelectedKey ?? null) : []) as ValueType<M>);\n }, [props.defaultValue, props.defaultSelectedKey, selectionMode]);\n let value = useMemo(() => {\n return props.value !== undefined\n ? props.value\n : ((selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>);\n }, [props.value, props.selectedKey, selectionMode]);\n let [controlledValue, setControlledValue] = useControlledState<Key | readonly Key[] | null>(\n value,\n defaultValue,\n props.onChange as any\n );\n // Only display the first selected item if in single selection mode but the value is an array.\n let displayValue: ValueType<M> =\n selectionMode === 'single' && Array.isArray(controlledValue)\n ? controlledValue[0]\n : controlledValue;\n\n let setValue = (value: Key | Key[] | null) => {\n if (selectionMode === 'single') {\n let key = Array.isArray(value) ? (value[0] ?? null) : value;\n setControlledValue(key);\n if (key !== displayValue) {\n props.onSelectionChange?.(key);\n }\n } else {\n let keys: Key[] = [];\n if (Array.isArray(value)) {\n keys = value;\n } else if (value != null) {\n keys = [value];\n }\n\n setControlledValue(keys);\n }\n };\n\n let {collection, selectionManager, disabledKeys} = useListState({\n ...props,\n items: props.items ?? props.defaultItems,\n selectionMode,\n disallowEmptySelection: selectionMode === 'single',\n allowDuplicateSelectionEvents: true,\n selectedKeys: useMemo(() => convertValue(displayValue), [displayValue]),\n onSelectionChange: (keys: Selection) => {\n // impossible, but TS doesn't know that\n if (keys === 'all') {\n return;\n }\n\n if (selectionMode === 'single') {\n let key = keys.values().next().value ?? null;\n if (key === displayValue) {\n props.onSelectionChange?.(key);\n // If key is the same, reset the inputValue and close the menu\n // (scenario: user clicks on already selected option)\n resetInputValue();\n closeMenu();\n } else {\n setValue(key);\n }\n } else {\n setValue([...keys]);\n }\n }\n });\n\n let selectedKey = selectionMode === 'single' ? selectionManager.firstSelectedKey : null;\n let selectedItems = useMemo(() => {\n return [...selectionManager.selectedKeys]\n .map(key => collection.getItem(key))\n .filter(item => item != null);\n }, [selectionManager.selectedKeys, collection]);\n\n let [inputValue, setInputValue] = useControlledState(\n props.inputValue,\n getDefaultInputValue(props.defaultInputValue, selectedKey, collection) || '',\n props.onInputChange\n );\n let [initialValue] = useState(displayValue);\n let [initialInputValue] = useState(inputValue);\n\n // Preserve original collection so we can show all items on demand\n let originalCollection = collection;\n let filteredCollection = useMemo(\n () =>\n // No default filter if items are controlled.\n props.items != null || !defaultFilter\n ? collection\n : filterCollection(collection, inputValue, defaultFilter),\n [collection, inputValue, defaultFilter, props.items]\n );\n let [lastCollection, setLastCollection] = useState(filteredCollection);\n\n // Track what action is attempting to open the menu\n let menuOpenTrigger = useRef<MenuTriggerAction | undefined>('focus');\n let onOpenChange = (open: boolean) => {\n if (props.onOpenChange) {\n props.onOpenChange(open, open ? menuOpenTrigger.current : undefined);\n }\n\n selectionManager.setFocused(open);\n if (!open) {\n selectionManager.setFocusedKey(null);\n }\n };\n\n let triggerState = useOverlayTriggerState({\n ...props,\n onOpenChange,\n isOpen: undefined,\n defaultOpen: undefined\n });\n let open = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // Prevent open operations from triggering if there is nothing to display\n // Also prevent open operations from triggering if items are uncontrolled but defaultItems is empty, even if displayAllItems is true.\n // This is to prevent comboboxes with empty defaultItems from opening but allow controlled items comboboxes to open even if the inital list is empty (assumption is user will provide swap the empty list with a base list via onOpenChange returning `menuTrigger` manual)\n if (\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) {\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is manually opened. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n menuOpenTrigger.current = trigger;\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n };\n\n let toggle = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // If the menu is closed and there is nothing to display, early return so toggle isn't called to prevent extraneous onOpenChange\n if (\n !(\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) &&\n !triggerState.isOpen\n ) {\n return;\n }\n\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is toggled open. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n // Only update the menuOpenTrigger if menu is currently closed\n if (!triggerState.isOpen) {\n menuOpenTrigger.current = trigger;\n }\n\n toggleMenu(focusStrategy);\n };\n\n let updateLastCollection = useCallback(() => {\n setLastCollection(showAllItems ? originalCollection : filteredCollection);\n }, [showAllItems, originalCollection, filteredCollection]);\n\n // If menu is going to close, save the current collection so we can freeze the displayed collection when the\n // user clicks outside the popover to close the menu. Prevents the menu contents from updating as the menu closes.\n let toggleMenu = useCallback(\n (focusStrategy: FocusStrategy | null = null) => {\n if (triggerState.isOpen) {\n updateLastCollection();\n }\n\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n },\n [triggerState, updateLastCollection]\n );\n\n let closeMenu = useCallback(() => {\n if (triggerState.isOpen) {\n updateLastCollection();\n triggerState.close();\n }\n }, [triggerState, updateLastCollection]);\n\n let [lastValue, setLastValue] = useState(inputValue);\n let resetInputValue = () => {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n setLastValue(itemText);\n setInputValue(itemText);\n };\n\n let lastValueRef = useRef(displayValue);\n let lastSelectedKeyText = useRef(\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : ''\n );\n // intentional omit dependency array, want this to happen on every render\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => {\n // Open and close menu automatically when the input value changes if the input is focused,\n // and there are items in the collection or allowEmptyCollection is true.\n if (\n isFocused &&\n (filteredCollection.size > 0 || allowsEmptyCollection) &&\n !triggerState.isOpen &&\n inputValue !== lastValue &&\n menuTrigger !== 'manual'\n ) {\n // oxlint-disable-next-line react/react-compiler\n open(null, 'input');\n }\n\n // Close the menu if the collection is empty. Don't close menu if filtered collection size is 0\n // but we are currently showing all items via button press\n if (\n !showAllItems &&\n !allowsEmptyCollection &&\n triggerState.isOpen &&\n filteredCollection.size === 0\n ) {\n closeMenu();\n }\n\n // Close when an item is selected.\n if (\n displayValue != null &&\n displayValue !== lastValueRef.current &&\n selectionMode === 'single'\n ) {\n closeMenu();\n }\n\n // Clear focused key when input value changes and display filtered collection again.\n if (inputValue !== lastValue) {\n selectionManager.setFocusedKey(null);\n setShowAllItems(false);\n\n // Set value to null when the user clears the input.\n // If controlled, this is the application developer's responsibility.\n if (\n selectionMode === 'single' &&\n inputValue === '' &&\n (props.inputValue === undefined || value === undefined)\n ) {\n setValue(null);\n }\n }\n\n // If the value changed, update the input value.\n // Do nothing if both inputValue and value are controlled.\n // In this case, it's the user's responsibility to update inputValue in onSelectionChange.\n if (\n displayValue !== lastValueRef.current &&\n (props.inputValue === undefined || value === undefined)\n ) {\n resetInputValue();\n } else if (lastValue !== inputValue) {\n setLastValue(inputValue);\n }\n\n // Update the inputValue if the selected item's text changes from its last tracked value.\n // This is to handle cases where a selectedKey is specified but the items aren't available (async loading) or the selected item's text value updates.\n // Only reset if the user isn't currently within the field so we don't erroneously modify user input.\n // If inputValue is controlled, it is the user's responsibility to update the inputValue when items change.\n let selectedItemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (\n !isFocused &&\n selectedKey != null &&\n props.inputValue === undefined &&\n selectedKey === lastValueRef.current\n ) {\n if (lastSelectedKeyText.current !== selectedItemText) {\n setLastValue(selectedItemText);\n setInputValue(selectedItemText);\n }\n }\n\n lastValueRef.current = displayValue;\n lastSelectedKeyText.current = selectedItemText;\n });\n\n let validation = useFormValidationState({\n ...props,\n value: useMemo(\n () =>\n Array.isArray(displayValue) && displayValue.length === 0\n ? null\n : {inputValue, value: displayValue as any, selectedKey},\n [inputValue, selectedKey, displayValue]\n )\n });\n\n // Revert input value and close menu\n let revert = () => {\n if (allowsCustomValue && selectedKey == null) {\n commitCustomValue();\n } else {\n commitSelection();\n }\n };\n\n let commitCustomValue = () => {\n if (selectionMode === 'multiple') {\n // In multi-select mode, the input's custom text is independent from the selected items.\n // Closing or committing the field should not clear the existing selection.\n setLastValue(inputValue);\n closeMenu();\n return;\n }\n\n let value = null;\n lastValueRef.current = value as any;\n setValue(value);\n closeMenu();\n };\n\n let commitSelection = (shouldForceSelectionChange = false) => {\n // If multiple things are controlled, call onSelectionChange only when selecting the focused item,\n // or when inputValue needs to be synced back to the selected item on commit/blur.\n if (value !== undefined && props.inputValue !== undefined) {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (shouldForceSelectionChange || selectionMode === 'multiple' || inputValue !== itemText) {\n props.onSelectionChange?.(selectedKey);\n props.onChange?.(displayValue as ChangeValueType<M>);\n }\n\n // Stop menu from reopening from useEffect\n setLastValue(itemText);\n closeMenu();\n } else {\n // If only a single aspect of combobox is controlled, reset input value and close menu for the user\n resetInputValue();\n closeMenu();\n }\n };\n\n const commitValue = () => {\n if (allowsCustomValue) {\n const itemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n inputValue === itemText ? commitSelection() : commitCustomValue();\n } else {\n // Reset inputValue and close menu\n commitSelection();\n }\n };\n\n let commit = () => {\n if (triggerState.isOpen && selectionManager.focusedKey != null) {\n // Reset inputValue and close menu here if the selected key is already the focused key. Otherwise\n // fire onSelectionChange to allow the application to control the closing.\n if (selectionManager.isSelected(selectionManager.focusedKey) && selectionMode === 'single') {\n commitSelection(true);\n } else {\n selectionManager.select(selectionManager.focusedKey);\n }\n } else {\n commitValue();\n }\n };\n\n let valueOnFocus = useRef([inputValue, displayValue]);\n let setFocused = (isFocused: boolean) => {\n if (isFocused) {\n valueOnFocus.current = [inputValue, displayValue];\n if (menuTrigger === 'focus' && !props.isReadOnly) {\n open(null, 'focus');\n }\n } else {\n if (shouldCloseOnBlur) {\n commitValue();\n }\n\n // Commit validation if the input value or selected items changed.\n if (inputValue !== valueOnFocus.current[0] || displayValue !== valueOnFocus.current[1]) {\n validation.commitValidation();\n }\n }\n\n setFocusedState(isFocused);\n };\n\n let displayedCollection = useMemo(() => {\n if (triggerState.isOpen) {\n if (showAllItems) {\n return originalCollection;\n } else {\n return filteredCollection;\n }\n } else {\n return lastCollection;\n }\n }, [triggerState.isOpen, originalCollection, filteredCollection, showAllItems, lastCollection]);\n\n let defaultSelectedKey =\n props.defaultSelectedKey ?? (selectionMode === 'single' ? (initialValue as Key) : null);\n\n return {\n ...validation,\n ...triggerState,\n focusStrategy,\n toggle,\n open,\n close: commitValue,\n selectionManager,\n value: displayValue as any,\n defaultValue: defaultValue ?? (initialValue as any),\n setValue,\n selectedKey,\n selectedItems,\n defaultSelectedKey,\n setSelectedKey: setValue,\n disabledKeys,\n isFocused,\n setFocused,\n selectedItem: selectedItems[0] ?? null,\n collection: displayedCollection,\n inputValue,\n defaultInputValue:\n getDefaultInputValue(props.defaultInputValue, defaultSelectedKey, collection) ??\n initialInputValue,\n setInputValue,\n commit,\n revert\n };\n}\n\nfunction filterCollection<T>(\n collection: Collection<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Collection<Node<T>> {\n return new ListCollection(filterNodes(collection, collection, inputValue, filter));\n}\n\nfunction filterNodes<T>(\n collection: Collection<Node<T>>,\n nodes: Iterable<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Iterable<Node<T>> {\n let filteredNode: Node<T>[] = [];\n for (let node of nodes) {\n if (node.type === 'section' && node.hasChildNodes) {\n let filtered = filterNodes(collection, getChildNodes(node, collection), inputValue, filter);\n if ([...filtered].some(node => node.type === 'item')) {\n filteredNode.push({...node, childNodes: filtered});\n }\n } else if (node.type === 'item' && filter(node.textValue, inputValue)) {\n filteredNode.push({...node});\n } else if (node.type !== 'item') {\n filteredNode.push({...node});\n }\n }\n return filteredNode;\n}\n\nfunction getDefaultInputValue(\n defaultInputValue: string | null | undefined,\n selectedKey: Key | null,\n collection: Collection<Node<unknown>>\n) {\n if (defaultInputValue == null) {\n if (selectedKey != null) {\n return collection.getItem(selectedKey)?.textValue ?? '';\n }\n }\n\n return defaultInputValue;\n}\n\nfunction convertValue(value: Key | readonly Key[] | null | undefined) {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n"],"names":[],"version":3,"file":"useComboBoxState.js.map"}
@@ -182,7 +182,8 @@ function $120eca7b9c40f820$export$b453a3bfd4a5fa9e(props) {
182
182
  (0, $eRFzl$useEffect)(()=>{
183
183
  // Open and close menu automatically when the input value changes if the input is focused,
184
184
  // and there are items in the collection or allowEmptyCollection is true.
185
- if (isFocused && (filteredCollection.size > 0 || allowsEmptyCollection) && !triggerState.isOpen && inputValue !== lastValue && menuTrigger !== 'manual') open(null, 'input');
185
+ if (isFocused && (filteredCollection.size > 0 || allowsEmptyCollection) && !triggerState.isOpen && inputValue !== lastValue && menuTrigger !== 'manual') // oxlint-disable-next-line react/react-compiler
186
+ open(null, 'input');
186
187
  // Close the menu if the collection is empty. Don't close menu if filtered collection size is 0
187
188
  // but we are currently showing all items via button press
188
189
  if (!showAllItems && !allowsEmptyCollection && triggerState.isOpen && filteredCollection.size === 0) closeMenu();
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/react-stately/src/combobox/useComboBoxState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n Collection,\n CollectionBase,\n CollectionStateBase,\n FocusableProps,\n FocusStrategy,\n HelpTextProps,\n InputBase,\n Key,\n LabelableProps,\n Node,\n Selection,\n TextInputBase,\n Validation,\n ValueBase\n} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '../form/useFormValidationState';\nimport {getChildNodes} from '../collections/getChildNodes';\nimport {ListCollection} from '../list/ListCollection';\nimport {ListState, useListState} from '../list/useListState';\nimport {OverlayTriggerState, useOverlayTriggerState} from '../overlays/useOverlayTriggerState';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {useControlledState} from '../utils/useControlledState';\n\nexport type MenuTriggerAction = 'focus' | 'input' | 'manual';\nexport type SelectionMode = 'single' | 'multiple';\nexport type ValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\nexport type ChangeValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\ntype ValidationType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\n\nexport interface ComboBoxValidationValue<M extends SelectionMode = 'single'> {\n /**\n * The selected key in the ComboBox.\n *\n * @deprecated\n */\n selectedKey: Key | null;\n /** The keys of the currently selected items. */\n value: ValidationType<M>;\n /** The value of the ComboBox input. */\n inputValue: string;\n}\n\nexport interface ComboBoxProps<T, M extends SelectionMode = 'single'>\n extends\n CollectionBase<T>,\n InputBase,\n ValueBase<ValueType<M>, ChangeValueType<M>>,\n TextInputBase,\n Validation<ComboBoxValidationValue<M>>,\n FocusableProps<HTMLInputElement>,\n LabelableProps,\n HelpTextProps {\n /** The list of ComboBox items (uncontrolled). */\n defaultItems?: Iterable<T>;\n /** The list of ComboBox items (controlled). */\n items?: Iterable<T>;\n /**\n * Method that is called when the open state of the menu changes. Returns the new open state and\n * the action that caused the opening of the menu.\n */\n onOpenChange?: (isOpen: boolean, menuTrigger?: MenuTriggerAction) => void;\n /**\n * Whether single or multiple selection is enabled.\n *\n * @default 'single'\n */\n selectionMode?: M;\n /**\n * The currently selected key in the collection (controlled).\n *\n * @deprecated\n */\n selectedKey?: Key | null;\n /**\n * The initial selected key in the collection (uncontrolled).\n *\n * @deprecated\n */\n defaultSelectedKey?: Key | null;\n /**\n * Handler that is called when the selection changes.\n *\n * @deprecated\n */\n onSelectionChange?: (key: Key | null) => void;\n /** The value of the ComboBox input (controlled). */\n inputValue?: string;\n /** The default value of the ComboBox input (uncontrolled). */\n defaultInputValue?: string;\n /** Handler that is called when the ComboBox input value changes. */\n onInputChange?: (value: string) => void;\n /** Whether the ComboBox allows a non-item matching input value to be set. */\n allowsCustomValue?: boolean;\n // /**\n // * Whether the Combobox should only suggest matching options or autocomplete the field with the nearest matching option.\n // * @default 'suggest'\n // */\n // completionMode?: 'suggest' | 'complete',\n /**\n * The interaction required to display the ComboBox menu.\n *\n * @default 'input'\n */\n menuTrigger?: MenuTriggerAction;\n}\n\nexport interface ComboBoxState<T, M extends SelectionMode = 'single'>\n extends ListState<T>, OverlayTriggerState, FormValidationState {\n /**\n * The key for the first selected item.\n *\n * @deprecated\n */\n readonly selectedKey: Key | null;\n\n /**\n * The default selected key.\n *\n * @deprecated\n */\n readonly defaultSelectedKey: Key | null;\n /**\n * Sets the selected key.\n *\n * @deprecated\n */\n setSelectedKey(key: Key | null): void;\n /** The current combobox value. */\n readonly value: ValueType<M>;\n /** The default combobox value. */\n readonly defaultValue: ValueType<M>;\n /** Sets the combobox value. */\n setValue(value: Key | readonly Key[] | null): void;\n /**\n * The value of the first selected item.\n *\n * @deprecated\n */\n readonly selectedItem: Node<T> | null;\n /** The value of the selected items. */\n readonly selectedItems: Node<T>[];\n /** The current value of the combo box input. */\n inputValue: string;\n /** The default value of the combo box input. */\n defaultInputValue: string;\n /** Sets the value of the combo box input. */\n setInputValue(value: string): void;\n /** Selects the currently focused item and updates the input value. */\n commit(): void;\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null;\n /** Whether the select is currently focused. */\n readonly isFocused: boolean;\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void;\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Resets the input value to the previously selected item's text if any and closes the menu. */\n revert(): void;\n}\n\ntype FilterFn = (textValue: string, inputValue: string) => boolean;\n\nexport interface ComboBoxStateOptions<T, M extends SelectionMode = 'single'>\n extends Omit<ComboBoxProps<T, M>, 'children'>, CollectionStateBase<T> {\n /** The filter function used to determine if a option should be included in the combo box list. */\n defaultFilter?: FilterFn;\n /** Whether the combo box allows the menu to be open when the collection is empty. */\n allowsEmptyCollection?: boolean;\n /** Whether the combo box menu should close on blur. */\n shouldCloseOnBlur?: boolean;\n}\n\n/**\n * Provides state management for a combo box component. Handles building a collection of items from\n * props and manages the option selection state of the combo box. In addition, it tracks the input\n * value, focus state, and other properties of the combo box.\n */\nexport function useComboBoxState<T, M extends SelectionMode = 'single'>(\n props: ComboBoxStateOptions<T, M>\n): ComboBoxState<T, M> {\n let {\n defaultFilter,\n menuTrigger = 'input',\n allowsEmptyCollection = false,\n allowsCustomValue,\n shouldCloseOnBlur = true,\n selectionMode = 'single' as SelectionMode\n } = props;\n\n let [showAllItems, setShowAllItems] = useState(false);\n let [isFocused, setFocusedState] = useState(false);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n\n let defaultValue = useMemo(() => {\n return props.defaultValue !== undefined\n ? props.defaultValue\n : ((selectionMode === 'single' ? (props.defaultSelectedKey ?? null) : []) as ValueType<M>);\n }, [props.defaultValue, props.defaultSelectedKey, selectionMode]);\n let value = useMemo(() => {\n return props.value !== undefined\n ? props.value\n : ((selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>);\n }, [props.value, props.selectedKey, selectionMode]);\n let [controlledValue, setControlledValue] = useControlledState<Key | readonly Key[] | null>(\n value,\n defaultValue,\n props.onChange as any\n );\n // Only display the first selected item if in single selection mode but the value is an array.\n let displayValue: ValueType<M> =\n selectionMode === 'single' && Array.isArray(controlledValue)\n ? controlledValue[0]\n : controlledValue;\n\n let setValue = (value: Key | Key[] | null) => {\n if (selectionMode === 'single') {\n let key = Array.isArray(value) ? (value[0] ?? null) : value;\n setControlledValue(key);\n if (key !== displayValue) {\n props.onSelectionChange?.(key);\n }\n } else {\n let keys: Key[] = [];\n if (Array.isArray(value)) {\n keys = value;\n } else if (value != null) {\n keys = [value];\n }\n\n setControlledValue(keys);\n }\n };\n\n let {collection, selectionManager, disabledKeys} = useListState({\n ...props,\n items: props.items ?? props.defaultItems,\n selectionMode,\n disallowEmptySelection: selectionMode === 'single',\n allowDuplicateSelectionEvents: true,\n selectedKeys: useMemo(() => convertValue(displayValue), [displayValue]),\n onSelectionChange: (keys: Selection) => {\n // impossible, but TS doesn't know that\n if (keys === 'all') {\n return;\n }\n\n if (selectionMode === 'single') {\n let key = keys.values().next().value ?? null;\n if (key === displayValue) {\n props.onSelectionChange?.(key);\n // If key is the same, reset the inputValue and close the menu\n // (scenario: user clicks on already selected option)\n resetInputValue();\n closeMenu();\n } else {\n setValue(key);\n }\n } else {\n setValue([...keys]);\n }\n }\n });\n\n let selectedKey = selectionMode === 'single' ? selectionManager.firstSelectedKey : null;\n let selectedItems = useMemo(() => {\n return [...selectionManager.selectedKeys]\n .map(key => collection.getItem(key))\n .filter(item => item != null);\n }, [selectionManager.selectedKeys, collection]);\n\n let [inputValue, setInputValue] = useControlledState(\n props.inputValue,\n getDefaultInputValue(props.defaultInputValue, selectedKey, collection) || '',\n props.onInputChange\n );\n let [initialValue] = useState(displayValue);\n let [initialInputValue] = useState(inputValue);\n\n // Preserve original collection so we can show all items on demand\n let originalCollection = collection;\n let filteredCollection = useMemo(\n () =>\n // No default filter if items are controlled.\n props.items != null || !defaultFilter\n ? collection\n : filterCollection(collection, inputValue, defaultFilter),\n [collection, inputValue, defaultFilter, props.items]\n );\n let [lastCollection, setLastCollection] = useState(filteredCollection);\n\n // Track what action is attempting to open the menu\n let menuOpenTrigger = useRef<MenuTriggerAction | undefined>('focus');\n let onOpenChange = (open: boolean) => {\n if (props.onOpenChange) {\n props.onOpenChange(open, open ? menuOpenTrigger.current : undefined);\n }\n\n selectionManager.setFocused(open);\n if (!open) {\n selectionManager.setFocusedKey(null);\n }\n };\n\n let triggerState = useOverlayTriggerState({\n ...props,\n onOpenChange,\n isOpen: undefined,\n defaultOpen: undefined\n });\n let open = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // Prevent open operations from triggering if there is nothing to display\n // Also prevent open operations from triggering if items are uncontrolled but defaultItems is empty, even if displayAllItems is true.\n // This is to prevent comboboxes with empty defaultItems from opening but allow controlled items comboboxes to open even if the inital list is empty (assumption is user will provide swap the empty list with a base list via onOpenChange returning `menuTrigger` manual)\n if (\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) {\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is manually opened. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n menuOpenTrigger.current = trigger;\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n };\n\n let toggle = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // If the menu is closed and there is nothing to display, early return so toggle isn't called to prevent extraneous onOpenChange\n if (\n !(\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) &&\n !triggerState.isOpen\n ) {\n return;\n }\n\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is toggled open. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n // Only update the menuOpenTrigger if menu is currently closed\n if (!triggerState.isOpen) {\n menuOpenTrigger.current = trigger;\n }\n\n toggleMenu(focusStrategy);\n };\n\n let updateLastCollection = useCallback(() => {\n setLastCollection(showAllItems ? originalCollection : filteredCollection);\n }, [showAllItems, originalCollection, filteredCollection]);\n\n // If menu is going to close, save the current collection so we can freeze the displayed collection when the\n // user clicks outside the popover to close the menu. Prevents the menu contents from updating as the menu closes.\n let toggleMenu = useCallback(\n (focusStrategy: FocusStrategy | null = null) => {\n if (triggerState.isOpen) {\n updateLastCollection();\n }\n\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n },\n [triggerState, updateLastCollection]\n );\n\n let closeMenu = useCallback(() => {\n if (triggerState.isOpen) {\n updateLastCollection();\n triggerState.close();\n }\n }, [triggerState, updateLastCollection]);\n\n let [lastValue, setLastValue] = useState(inputValue);\n let resetInputValue = () => {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n setLastValue(itemText);\n setInputValue(itemText);\n };\n\n let lastValueRef = useRef(displayValue);\n let lastSelectedKeyText = useRef(\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : ''\n );\n // intentional omit dependency array, want this to happen on every render\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => {\n // Open and close menu automatically when the input value changes if the input is focused,\n // and there are items in the collection or allowEmptyCollection is true.\n if (\n isFocused &&\n (filteredCollection.size > 0 || allowsEmptyCollection) &&\n !triggerState.isOpen &&\n inputValue !== lastValue &&\n menuTrigger !== 'manual'\n ) {\n open(null, 'input');\n }\n\n // Close the menu if the collection is empty. Don't close menu if filtered collection size is 0\n // but we are currently showing all items via button press\n if (\n !showAllItems &&\n !allowsEmptyCollection &&\n triggerState.isOpen &&\n filteredCollection.size === 0\n ) {\n closeMenu();\n }\n\n // Close when an item is selected.\n if (\n displayValue != null &&\n displayValue !== lastValueRef.current &&\n selectionMode === 'single'\n ) {\n closeMenu();\n }\n\n // Clear focused key when input value changes and display filtered collection again.\n if (inputValue !== lastValue) {\n selectionManager.setFocusedKey(null);\n setShowAllItems(false);\n\n // Set value to null when the user clears the input.\n // If controlled, this is the application developer's responsibility.\n if (\n selectionMode === 'single' &&\n inputValue === '' &&\n (props.inputValue === undefined || value === undefined)\n ) {\n setValue(null);\n }\n }\n\n // If the value changed, update the input value.\n // Do nothing if both inputValue and value are controlled.\n // In this case, it's the user's responsibility to update inputValue in onSelectionChange.\n if (\n displayValue !== lastValueRef.current &&\n (props.inputValue === undefined || value === undefined)\n ) {\n resetInputValue();\n } else if (lastValue !== inputValue) {\n setLastValue(inputValue);\n }\n\n // Update the inputValue if the selected item's text changes from its last tracked value.\n // This is to handle cases where a selectedKey is specified but the items aren't available (async loading) or the selected item's text value updates.\n // Only reset if the user isn't currently within the field so we don't erroneously modify user input.\n // If inputValue is controlled, it is the user's responsibility to update the inputValue when items change.\n let selectedItemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (\n !isFocused &&\n selectedKey != null &&\n props.inputValue === undefined &&\n selectedKey === lastValueRef.current\n ) {\n if (lastSelectedKeyText.current !== selectedItemText) {\n setLastValue(selectedItemText);\n setInputValue(selectedItemText);\n }\n }\n\n lastValueRef.current = displayValue;\n lastSelectedKeyText.current = selectedItemText;\n });\n\n let validation = useFormValidationState({\n ...props,\n value: useMemo(\n () =>\n Array.isArray(displayValue) && displayValue.length === 0\n ? null\n : {inputValue, value: displayValue as any, selectedKey},\n [inputValue, selectedKey, displayValue]\n )\n });\n\n // Revert input value and close menu\n let revert = () => {\n if (allowsCustomValue && selectedKey == null) {\n commitCustomValue();\n } else {\n commitSelection();\n }\n };\n\n let commitCustomValue = () => {\n if (selectionMode === 'multiple') {\n // In multi-select mode, the input's custom text is independent from the selected items.\n // Closing or committing the field should not clear the existing selection.\n setLastValue(inputValue);\n closeMenu();\n return;\n }\n\n let value = null;\n lastValueRef.current = value as any;\n setValue(value);\n closeMenu();\n };\n\n let commitSelection = (shouldForceSelectionChange = false) => {\n // If multiple things are controlled, call onSelectionChange only when selecting the focused item,\n // or when inputValue needs to be synced back to the selected item on commit/blur.\n if (value !== undefined && props.inputValue !== undefined) {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (shouldForceSelectionChange || selectionMode === 'multiple' || inputValue !== itemText) {\n props.onSelectionChange?.(selectedKey);\n props.onChange?.(displayValue as ChangeValueType<M>);\n }\n\n // Stop menu from reopening from useEffect\n setLastValue(itemText);\n closeMenu();\n } else {\n // If only a single aspect of combobox is controlled, reset input value and close menu for the user\n resetInputValue();\n closeMenu();\n }\n };\n\n const commitValue = () => {\n if (allowsCustomValue) {\n const itemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n inputValue === itemText ? commitSelection() : commitCustomValue();\n } else {\n // Reset inputValue and close menu\n commitSelection();\n }\n };\n\n let commit = () => {\n if (triggerState.isOpen && selectionManager.focusedKey != null) {\n // Reset inputValue and close menu here if the selected key is already the focused key. Otherwise\n // fire onSelectionChange to allow the application to control the closing.\n if (selectionManager.isSelected(selectionManager.focusedKey) && selectionMode === 'single') {\n commitSelection(true);\n } else {\n selectionManager.select(selectionManager.focusedKey);\n }\n } else {\n commitValue();\n }\n };\n\n let valueOnFocus = useRef([inputValue, displayValue]);\n let setFocused = (isFocused: boolean) => {\n if (isFocused) {\n valueOnFocus.current = [inputValue, displayValue];\n if (menuTrigger === 'focus' && !props.isReadOnly) {\n open(null, 'focus');\n }\n } else {\n if (shouldCloseOnBlur) {\n commitValue();\n }\n\n // Commit validation if the input value or selected items changed.\n if (inputValue !== valueOnFocus.current[0] || displayValue !== valueOnFocus.current[1]) {\n validation.commitValidation();\n }\n }\n\n setFocusedState(isFocused);\n };\n\n let displayedCollection = useMemo(() => {\n if (triggerState.isOpen) {\n if (showAllItems) {\n return originalCollection;\n } else {\n return filteredCollection;\n }\n } else {\n return lastCollection;\n }\n }, [triggerState.isOpen, originalCollection, filteredCollection, showAllItems, lastCollection]);\n\n let defaultSelectedKey =\n props.defaultSelectedKey ?? (selectionMode === 'single' ? (initialValue as Key) : null);\n\n return {\n ...validation,\n ...triggerState,\n focusStrategy,\n toggle,\n open,\n close: commitValue,\n selectionManager,\n value: displayValue as any,\n defaultValue: defaultValue ?? (initialValue as any),\n setValue,\n selectedKey,\n selectedItems,\n defaultSelectedKey,\n setSelectedKey: setValue,\n disabledKeys,\n isFocused,\n setFocused,\n selectedItem: selectedItems[0] ?? null,\n collection: displayedCollection,\n inputValue,\n defaultInputValue:\n getDefaultInputValue(props.defaultInputValue, defaultSelectedKey, collection) ??\n initialInputValue,\n setInputValue,\n commit,\n revert\n };\n}\n\nfunction filterCollection<T>(\n collection: Collection<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Collection<Node<T>> {\n return new ListCollection(filterNodes(collection, collection, inputValue, filter));\n}\n\nfunction filterNodes<T>(\n collection: Collection<Node<T>>,\n nodes: Iterable<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Iterable<Node<T>> {\n let filteredNode: Node<T>[] = [];\n for (let node of nodes) {\n if (node.type === 'section' && node.hasChildNodes) {\n let filtered = filterNodes(collection, getChildNodes(node, collection), inputValue, filter);\n if ([...filtered].some(node => node.type === 'item')) {\n filteredNode.push({...node, childNodes: filtered});\n }\n } else if (node.type === 'item' && filter(node.textValue, inputValue)) {\n filteredNode.push({...node});\n } else if (node.type !== 'item') {\n filteredNode.push({...node});\n }\n }\n return filteredNode;\n}\n\nfunction getDefaultInputValue(\n defaultInputValue: string | null | undefined,\n selectedKey: Key | null,\n collection: Collection<Node<unknown>>\n) {\n if (defaultInputValue == null) {\n if (selectedKey != null) {\n return collection.getItem(selectedKey)?.textValue ?? '';\n }\n }\n\n return defaultInputValue;\n}\n\nfunction convertValue(value: Key | readonly Key[] | null | undefined) {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n"],"names":[],"version":3,"file":"useComboBoxState.mjs.map"}
1
+ {"mappings":"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","sources":["packages/react-stately/src/combobox/useComboBoxState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n Collection,\n CollectionBase,\n CollectionStateBase,\n FocusableProps,\n FocusStrategy,\n HelpTextProps,\n InputBase,\n Key,\n LabelableProps,\n Node,\n Selection,\n TextInputBase,\n Validation,\n ValueBase\n} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '../form/useFormValidationState';\nimport {getChildNodes} from '../collections/getChildNodes';\nimport {ListCollection} from '../list/ListCollection';\nimport {ListState, useListState} from '../list/useListState';\nimport {OverlayTriggerState, useOverlayTriggerState} from '../overlays/useOverlayTriggerState';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {useControlledState} from '../utils/useControlledState';\n\nexport type MenuTriggerAction = 'focus' | 'input' | 'manual';\nexport type SelectionMode = 'single' | 'multiple';\nexport type ValueType<M extends SelectionMode> = M extends 'single' ? Key | null : readonly Key[];\nexport type ChangeValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\ntype ValidationType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];\n\nexport interface ComboBoxValidationValue<M extends SelectionMode = 'single'> {\n /**\n * The selected key in the ComboBox.\n *\n * @deprecated\n */\n selectedKey: Key | null;\n /** The keys of the currently selected items. */\n value: ValidationType<M>;\n /** The value of the ComboBox input. */\n inputValue: string;\n}\n\nexport interface ComboBoxProps<T, M extends SelectionMode = 'single'>\n extends\n CollectionBase<T>,\n InputBase,\n ValueBase<ValueType<M>, ChangeValueType<M>>,\n TextInputBase,\n Validation<ComboBoxValidationValue<M>>,\n FocusableProps<HTMLInputElement>,\n LabelableProps,\n HelpTextProps {\n /** The list of ComboBox items (uncontrolled). */\n defaultItems?: Iterable<T>;\n /** The list of ComboBox items (controlled). */\n items?: Iterable<T>;\n /**\n * Method that is called when the open state of the menu changes. Returns the new open state and\n * the action that caused the opening of the menu.\n */\n onOpenChange?: (isOpen: boolean, menuTrigger?: MenuTriggerAction) => void;\n /**\n * Whether single or multiple selection is enabled.\n *\n * @default 'single'\n */\n selectionMode?: M;\n /**\n * The currently selected key in the collection (controlled).\n *\n * @deprecated\n */\n selectedKey?: Key | null;\n /**\n * The initial selected key in the collection (uncontrolled).\n *\n * @deprecated\n */\n defaultSelectedKey?: Key | null;\n /**\n * Handler that is called when the selection changes.\n *\n * @deprecated\n */\n onSelectionChange?: (key: Key | null) => void;\n /** The value of the ComboBox input (controlled). */\n inputValue?: string;\n /** The default value of the ComboBox input (uncontrolled). */\n defaultInputValue?: string;\n /** Handler that is called when the ComboBox input value changes. */\n onInputChange?: (value: string) => void;\n /** Whether the ComboBox allows a non-item matching input value to be set. */\n allowsCustomValue?: boolean;\n // /**\n // * Whether the Combobox should only suggest matching options or autocomplete the field with the nearest matching option.\n // * @default 'suggest'\n // */\n // completionMode?: 'suggest' | 'complete',\n /**\n * The interaction required to display the ComboBox menu.\n *\n * @default 'input'\n */\n menuTrigger?: MenuTriggerAction;\n}\n\nexport interface ComboBoxState<T, M extends SelectionMode = 'single'>\n extends ListState<T>, OverlayTriggerState, FormValidationState {\n /**\n * The key for the first selected item.\n *\n * @deprecated\n */\n readonly selectedKey: Key | null;\n\n /**\n * The default selected key.\n *\n * @deprecated\n */\n readonly defaultSelectedKey: Key | null;\n /**\n * Sets the selected key.\n *\n * @deprecated\n */\n setSelectedKey(key: Key | null): void;\n /** The current combobox value. */\n readonly value: ValueType<M>;\n /** The default combobox value. */\n readonly defaultValue: ValueType<M>;\n /** Sets the combobox value. */\n setValue(value: Key | readonly Key[] | null): void;\n /**\n * The value of the first selected item.\n *\n * @deprecated\n */\n readonly selectedItem: Node<T> | null;\n /** The value of the selected items. */\n readonly selectedItems: Node<T>[];\n /** The current value of the combo box input. */\n inputValue: string;\n /** The default value of the combo box input. */\n defaultInputValue: string;\n /** Sets the value of the combo box input. */\n setInputValue(value: string): void;\n /** Selects the currently focused item and updates the input value. */\n commit(): void;\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null;\n /** Whether the select is currently focused. */\n readonly isFocused: boolean;\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void;\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null, trigger?: MenuTriggerAction): void;\n /** Resets the input value to the previously selected item's text if any and closes the menu. */\n revert(): void;\n}\n\ntype FilterFn = (textValue: string, inputValue: string) => boolean;\n\nexport interface ComboBoxStateOptions<T, M extends SelectionMode = 'single'>\n extends Omit<ComboBoxProps<T, M>, 'children'>, CollectionStateBase<T> {\n /** The filter function used to determine if a option should be included in the combo box list. */\n defaultFilter?: FilterFn;\n /** Whether the combo box allows the menu to be open when the collection is empty. */\n allowsEmptyCollection?: boolean;\n /** Whether the combo box menu should close on blur. */\n shouldCloseOnBlur?: boolean;\n}\n\n/**\n * Provides state management for a combo box component. Handles building a collection of items from\n * props and manages the option selection state of the combo box. In addition, it tracks the input\n * value, focus state, and other properties of the combo box.\n */\nexport function useComboBoxState<T, M extends SelectionMode = 'single'>(\n props: ComboBoxStateOptions<T, M>\n): ComboBoxState<T, M> {\n let {\n defaultFilter,\n menuTrigger = 'input',\n allowsEmptyCollection = false,\n allowsCustomValue,\n shouldCloseOnBlur = true,\n selectionMode = 'single' as SelectionMode\n } = props;\n\n let [showAllItems, setShowAllItems] = useState(false);\n let [isFocused, setFocusedState] = useState(false);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n\n let defaultValue = useMemo(() => {\n return props.defaultValue !== undefined\n ? props.defaultValue\n : ((selectionMode === 'single' ? (props.defaultSelectedKey ?? null) : []) as ValueType<M>);\n }, [props.defaultValue, props.defaultSelectedKey, selectionMode]);\n let value = useMemo(() => {\n return props.value !== undefined\n ? props.value\n : ((selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>);\n }, [props.value, props.selectedKey, selectionMode]);\n let [controlledValue, setControlledValue] = useControlledState<Key | readonly Key[] | null>(\n value,\n defaultValue,\n props.onChange as any\n );\n // Only display the first selected item if in single selection mode but the value is an array.\n let displayValue: ValueType<M> =\n selectionMode === 'single' && Array.isArray(controlledValue)\n ? controlledValue[0]\n : controlledValue;\n\n let setValue = (value: Key | Key[] | null) => {\n if (selectionMode === 'single') {\n let key = Array.isArray(value) ? (value[0] ?? null) : value;\n setControlledValue(key);\n if (key !== displayValue) {\n props.onSelectionChange?.(key);\n }\n } else {\n let keys: Key[] = [];\n if (Array.isArray(value)) {\n keys = value;\n } else if (value != null) {\n keys = [value];\n }\n\n setControlledValue(keys);\n }\n };\n\n let {collection, selectionManager, disabledKeys} = useListState({\n ...props,\n items: props.items ?? props.defaultItems,\n selectionMode,\n disallowEmptySelection: selectionMode === 'single',\n allowDuplicateSelectionEvents: true,\n selectedKeys: useMemo(() => convertValue(displayValue), [displayValue]),\n onSelectionChange: (keys: Selection) => {\n // impossible, but TS doesn't know that\n if (keys === 'all') {\n return;\n }\n\n if (selectionMode === 'single') {\n let key = keys.values().next().value ?? null;\n if (key === displayValue) {\n props.onSelectionChange?.(key);\n // If key is the same, reset the inputValue and close the menu\n // (scenario: user clicks on already selected option)\n resetInputValue();\n closeMenu();\n } else {\n setValue(key);\n }\n } else {\n setValue([...keys]);\n }\n }\n });\n\n let selectedKey = selectionMode === 'single' ? selectionManager.firstSelectedKey : null;\n let selectedItems = useMemo(() => {\n return [...selectionManager.selectedKeys]\n .map(key => collection.getItem(key))\n .filter(item => item != null);\n }, [selectionManager.selectedKeys, collection]);\n\n let [inputValue, setInputValue] = useControlledState(\n props.inputValue,\n getDefaultInputValue(props.defaultInputValue, selectedKey, collection) || '',\n props.onInputChange\n );\n let [initialValue] = useState(displayValue);\n let [initialInputValue] = useState(inputValue);\n\n // Preserve original collection so we can show all items on demand\n let originalCollection = collection;\n let filteredCollection = useMemo(\n () =>\n // No default filter if items are controlled.\n props.items != null || !defaultFilter\n ? collection\n : filterCollection(collection, inputValue, defaultFilter),\n [collection, inputValue, defaultFilter, props.items]\n );\n let [lastCollection, setLastCollection] = useState(filteredCollection);\n\n // Track what action is attempting to open the menu\n let menuOpenTrigger = useRef<MenuTriggerAction | undefined>('focus');\n let onOpenChange = (open: boolean) => {\n if (props.onOpenChange) {\n props.onOpenChange(open, open ? menuOpenTrigger.current : undefined);\n }\n\n selectionManager.setFocused(open);\n if (!open) {\n selectionManager.setFocusedKey(null);\n }\n };\n\n let triggerState = useOverlayTriggerState({\n ...props,\n onOpenChange,\n isOpen: undefined,\n defaultOpen: undefined\n });\n let open = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // Prevent open operations from triggering if there is nothing to display\n // Also prevent open operations from triggering if items are uncontrolled but defaultItems is empty, even if displayAllItems is true.\n // This is to prevent comboboxes with empty defaultItems from opening but allow controlled items comboboxes to open even if the inital list is empty (assumption is user will provide swap the empty list with a base list via onOpenChange returning `menuTrigger` manual)\n if (\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) {\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is manually opened. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n menuOpenTrigger.current = trigger;\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n };\n\n let toggle = (focusStrategy: FocusStrategy | null = null, trigger?: MenuTriggerAction) => {\n let displayAllItems = trigger === 'manual' || (trigger === 'focus' && menuTrigger === 'focus');\n // If the menu is closed and there is nothing to display, early return so toggle isn't called to prevent extraneous onOpenChange\n if (\n !(\n allowsEmptyCollection ||\n filteredCollection.size > 0 ||\n (displayAllItems && originalCollection.size > 0) ||\n props.items\n ) &&\n !triggerState.isOpen\n ) {\n return;\n }\n\n if (displayAllItems && !triggerState.isOpen && props.items === undefined) {\n // Show all items if menu is toggled open. Only care about this if items are undefined\n setShowAllItems(true);\n }\n\n // Only update the menuOpenTrigger if menu is currently closed\n if (!triggerState.isOpen) {\n menuOpenTrigger.current = trigger;\n }\n\n toggleMenu(focusStrategy);\n };\n\n let updateLastCollection = useCallback(() => {\n setLastCollection(showAllItems ? originalCollection : filteredCollection);\n }, [showAllItems, originalCollection, filteredCollection]);\n\n // If menu is going to close, save the current collection so we can freeze the displayed collection when the\n // user clicks outside the popover to close the menu. Prevents the menu contents from updating as the menu closes.\n let toggleMenu = useCallback(\n (focusStrategy: FocusStrategy | null = null) => {\n if (triggerState.isOpen) {\n updateLastCollection();\n }\n\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n },\n [triggerState, updateLastCollection]\n );\n\n let closeMenu = useCallback(() => {\n if (triggerState.isOpen) {\n updateLastCollection();\n triggerState.close();\n }\n }, [triggerState, updateLastCollection]);\n\n let [lastValue, setLastValue] = useState(inputValue);\n let resetInputValue = () => {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n setLastValue(itemText);\n setInputValue(itemText);\n };\n\n let lastValueRef = useRef(displayValue);\n let lastSelectedKeyText = useRef(\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : ''\n );\n // intentional omit dependency array, want this to happen on every render\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => {\n // Open and close menu automatically when the input value changes if the input is focused,\n // and there are items in the collection or allowEmptyCollection is true.\n if (\n isFocused &&\n (filteredCollection.size > 0 || allowsEmptyCollection) &&\n !triggerState.isOpen &&\n inputValue !== lastValue &&\n menuTrigger !== 'manual'\n ) {\n // oxlint-disable-next-line react/react-compiler\n open(null, 'input');\n }\n\n // Close the menu if the collection is empty. Don't close menu if filtered collection size is 0\n // but we are currently showing all items via button press\n if (\n !showAllItems &&\n !allowsEmptyCollection &&\n triggerState.isOpen &&\n filteredCollection.size === 0\n ) {\n closeMenu();\n }\n\n // Close when an item is selected.\n if (\n displayValue != null &&\n displayValue !== lastValueRef.current &&\n selectionMode === 'single'\n ) {\n closeMenu();\n }\n\n // Clear focused key when input value changes and display filtered collection again.\n if (inputValue !== lastValue) {\n selectionManager.setFocusedKey(null);\n setShowAllItems(false);\n\n // Set value to null when the user clears the input.\n // If controlled, this is the application developer's responsibility.\n if (\n selectionMode === 'single' &&\n inputValue === '' &&\n (props.inputValue === undefined || value === undefined)\n ) {\n setValue(null);\n }\n }\n\n // If the value changed, update the input value.\n // Do nothing if both inputValue and value are controlled.\n // In this case, it's the user's responsibility to update inputValue in onSelectionChange.\n if (\n displayValue !== lastValueRef.current &&\n (props.inputValue === undefined || value === undefined)\n ) {\n resetInputValue();\n } else if (lastValue !== inputValue) {\n setLastValue(inputValue);\n }\n\n // Update the inputValue if the selected item's text changes from its last tracked value.\n // This is to handle cases where a selectedKey is specified but the items aren't available (async loading) or the selected item's text value updates.\n // Only reset if the user isn't currently within the field so we don't erroneously modify user input.\n // If inputValue is controlled, it is the user's responsibility to update the inputValue when items change.\n let selectedItemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (\n !isFocused &&\n selectedKey != null &&\n props.inputValue === undefined &&\n selectedKey === lastValueRef.current\n ) {\n if (lastSelectedKeyText.current !== selectedItemText) {\n setLastValue(selectedItemText);\n setInputValue(selectedItemText);\n }\n }\n\n lastValueRef.current = displayValue;\n lastSelectedKeyText.current = selectedItemText;\n });\n\n let validation = useFormValidationState({\n ...props,\n value: useMemo(\n () =>\n Array.isArray(displayValue) && displayValue.length === 0\n ? null\n : {inputValue, value: displayValue as any, selectedKey},\n [inputValue, selectedKey, displayValue]\n )\n });\n\n // Revert input value and close menu\n let revert = () => {\n if (allowsCustomValue && selectedKey == null) {\n commitCustomValue();\n } else {\n commitSelection();\n }\n };\n\n let commitCustomValue = () => {\n if (selectionMode === 'multiple') {\n // In multi-select mode, the input's custom text is independent from the selected items.\n // Closing or committing the field should not clear the existing selection.\n setLastValue(inputValue);\n closeMenu();\n return;\n }\n\n let value = null;\n lastValueRef.current = value as any;\n setValue(value);\n closeMenu();\n };\n\n let commitSelection = (shouldForceSelectionChange = false) => {\n // If multiple things are controlled, call onSelectionChange only when selecting the focused item,\n // or when inputValue needs to be synced back to the selected item on commit/blur.\n if (value !== undefined && props.inputValue !== undefined) {\n let itemText = selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n if (shouldForceSelectionChange || selectionMode === 'multiple' || inputValue !== itemText) {\n props.onSelectionChange?.(selectedKey);\n props.onChange?.(displayValue as ChangeValueType<M>);\n }\n\n // Stop menu from reopening from useEffect\n setLastValue(itemText);\n closeMenu();\n } else {\n // If only a single aspect of combobox is controlled, reset input value and close menu for the user\n resetInputValue();\n closeMenu();\n }\n };\n\n const commitValue = () => {\n if (allowsCustomValue) {\n const itemText =\n selectedKey != null ? (collection.getItem(selectedKey)?.textValue ?? '') : '';\n inputValue === itemText ? commitSelection() : commitCustomValue();\n } else {\n // Reset inputValue and close menu\n commitSelection();\n }\n };\n\n let commit = () => {\n if (triggerState.isOpen && selectionManager.focusedKey != null) {\n // Reset inputValue and close menu here if the selected key is already the focused key. Otherwise\n // fire onSelectionChange to allow the application to control the closing.\n if (selectionManager.isSelected(selectionManager.focusedKey) && selectionMode === 'single') {\n commitSelection(true);\n } else {\n selectionManager.select(selectionManager.focusedKey);\n }\n } else {\n commitValue();\n }\n };\n\n let valueOnFocus = useRef([inputValue, displayValue]);\n let setFocused = (isFocused: boolean) => {\n if (isFocused) {\n valueOnFocus.current = [inputValue, displayValue];\n if (menuTrigger === 'focus' && !props.isReadOnly) {\n open(null, 'focus');\n }\n } else {\n if (shouldCloseOnBlur) {\n commitValue();\n }\n\n // Commit validation if the input value or selected items changed.\n if (inputValue !== valueOnFocus.current[0] || displayValue !== valueOnFocus.current[1]) {\n validation.commitValidation();\n }\n }\n\n setFocusedState(isFocused);\n };\n\n let displayedCollection = useMemo(() => {\n if (triggerState.isOpen) {\n if (showAllItems) {\n return originalCollection;\n } else {\n return filteredCollection;\n }\n } else {\n return lastCollection;\n }\n }, [triggerState.isOpen, originalCollection, filteredCollection, showAllItems, lastCollection]);\n\n let defaultSelectedKey =\n props.defaultSelectedKey ?? (selectionMode === 'single' ? (initialValue as Key) : null);\n\n return {\n ...validation,\n ...triggerState,\n focusStrategy,\n toggle,\n open,\n close: commitValue,\n selectionManager,\n value: displayValue as any,\n defaultValue: defaultValue ?? (initialValue as any),\n setValue,\n selectedKey,\n selectedItems,\n defaultSelectedKey,\n setSelectedKey: setValue,\n disabledKeys,\n isFocused,\n setFocused,\n selectedItem: selectedItems[0] ?? null,\n collection: displayedCollection,\n inputValue,\n defaultInputValue:\n getDefaultInputValue(props.defaultInputValue, defaultSelectedKey, collection) ??\n initialInputValue,\n setInputValue,\n commit,\n revert\n };\n}\n\nfunction filterCollection<T>(\n collection: Collection<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Collection<Node<T>> {\n return new ListCollection(filterNodes(collection, collection, inputValue, filter));\n}\n\nfunction filterNodes<T>(\n collection: Collection<Node<T>>,\n nodes: Iterable<Node<T>>,\n inputValue: string,\n filter: FilterFn\n): Iterable<Node<T>> {\n let filteredNode: Node<T>[] = [];\n for (let node of nodes) {\n if (node.type === 'section' && node.hasChildNodes) {\n let filtered = filterNodes(collection, getChildNodes(node, collection), inputValue, filter);\n if ([...filtered].some(node => node.type === 'item')) {\n filteredNode.push({...node, childNodes: filtered});\n }\n } else if (node.type === 'item' && filter(node.textValue, inputValue)) {\n filteredNode.push({...node});\n } else if (node.type !== 'item') {\n filteredNode.push({...node});\n }\n }\n return filteredNode;\n}\n\nfunction getDefaultInputValue(\n defaultInputValue: string | null | undefined,\n selectedKey: Key | null,\n collection: Collection<Node<unknown>>\n) {\n if (defaultInputValue == null) {\n if (selectedKey != null) {\n return collection.getItem(selectedKey)?.textValue ?? '';\n }\n }\n\n return defaultInputValue;\n}\n\nfunction convertValue(value: Key | readonly Key[] | null | undefined) {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n"],"names":[],"version":3,"file":"useComboBoxState.mjs.map"}
@@ -23,6 +23,7 @@ function $ab40f19b6fb67f7e$export$d14e1352e21f4a16(options) {
23
23
  let [tree, setItems] = (0, $8NoZA$react.useState)(()=>buildTree(initialItems, new Map()));
24
24
  let { items: items, nodeMap: nodeMap } = tree;
25
25
  let [selectedKeys, setSelectedKeys] = (0, $8NoZA$react.useState)(new Set(initialSelectedKeys || []));
26
+ // oxlint-disable-next-line react/react-compiler
26
27
  function buildTree(initialItems = [], map, parentKey) {
27
28
  if (initialItems == null) initialItems = [];
28
29
  return {
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/react-stately/src/data/useTreeData.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {Key} from '@react-types/shared';\nimport {useState} from 'react';\n\nexport interface TreeOptions<T extends object> {\n /** Initial root items in the tree. */\n initialItems?: T[];\n /** The keys for the initially selected items. */\n initialSelectedKeys?: Iterable<Key>;\n /** A function that returns a unique key for an item object. */\n getKey?: (item: T) => Key;\n /** A function that returns the children for an item object. */\n getChildren?: (item: T) => T[];\n}\n\ninterface TreeNode<T extends object> {\n /** A unique key for the tree node. */\n key: Key;\n /** The key of the parent node. */\n parentKey?: Key | null;\n /** The value object for the tree node. */\n value: T;\n /** Children of the tree node. */\n children: TreeNode<T>[] | null;\n}\n\nexport interface TreeData<T extends object> {\n /** The root nodes in the tree. */\n items: TreeNode<T>[];\n\n /** The keys of the currently selected items in the tree. */\n selectedKeys: Set<Key>;\n\n /** Sets the selected keys. */\n setSelectedKeys(keys: Set<Key>): void;\n\n /**\n * Gets a node from the tree by key.\n *\n * @param key - The key of the item to retrieve.\n */\n getItem(key: Key): TreeNode<T> | undefined;\n\n /**\n * Inserts an item into a parent node as a child.\n *\n * @param parentKey - The key of the parent item to insert into. `null` for the root.\n * @param index - The index within the parent to insert into.\n * @param value - The value to insert.\n */\n insert(parentKey: Key | null, index: number, ...values: T[]): void;\n\n /**\n * Inserts items into the list before the item at the given key.\n *\n * @param key - The key of the item to insert before.\n * @param values - The values to insert.\n */\n insertBefore(key: Key, ...values: T[]): void;\n\n /**\n * Inserts items into the list after the item at the given key.\n *\n * @param key - The key of the item to insert after.\n * @param values - The values to insert.\n */\n insertAfter(key: Key, ...values: T[]): void;\n\n /**\n * Appends an item into a parent node as a child.\n *\n * @param parentKey - The key of the parent item to insert into. `null` for the root.\n * @param value - The value to insert.\n */\n append(parentKey: Key | null, ...values: T[]): void;\n\n /**\n * Prepends an item into a parent node as a child.\n *\n * @param parentKey - The key of the parent item to insert into. `null` for the root.\n * @param value - The value to insert.\n */\n prepend(parentKey: Key | null, ...value: T[]): void;\n\n /**\n * Removes an item from the tree by its key.\n *\n * @param key - The key of the item to remove.\n */\n remove(...keys: Key[]): void;\n\n /**\n * Removes all items from the tree that are currently\n * in the set of selected items.\n */\n removeSelectedItems(): void;\n\n /**\n * Moves an item within the tree.\n *\n * @param key - The key of the item to move.\n * @param toParentKey - The key of the new parent to insert into. `null` for the root.\n * @param index - The index within the new parent to insert at.\n */\n move(key: Key, toParentKey: Key | null, index: number): void;\n\n /**\n * Moves one or more items before a given key.\n *\n * @param key - The key of the item to move the items before.\n * @param keys - The keys of the items to move.\n */\n moveBefore(key: Key, keys: Iterable<Key>): void;\n\n /**\n * Moves one or more items after a given key.\n *\n * @param key - The key of the item to move the items after.\n * @param keys - The keys of the items to move.\n */\n moveAfter(key: Key, keys: Iterable<Key>): void;\n\n /**\n * Updates an item in the tree.\n *\n * @param key - The key of the item to update.\n * @param newValue - The new value for the item.\n */\n update(key: Key, newValue: T): void;\n}\n\ninterface TreeDataState<T extends object> {\n items: TreeNode<T>[];\n nodeMap: Map<Key, TreeNode<T>>;\n}\n\n/**\n * Manages state for an immutable tree data structure, and provides convenience methods to\n * update the data over time.\n */\nexport function useTreeData<T extends object>(options: TreeOptions<T>): TreeData<T> {\n let {\n initialItems = [],\n initialSelectedKeys,\n getKey = (item: any) => item.id ?? item.key,\n getChildren = (item: any) => item.children\n } = options;\n\n // We only want to compute this on initial render.\n let [tree, setItems] = useState<TreeDataState<T>>(() => buildTree(initialItems, new Map()));\n let {items, nodeMap} = tree;\n\n let [selectedKeys, setSelectedKeys] = useState(new Set<Key>(initialSelectedKeys || []));\n\n function buildTree(\n initialItems: T[] | null = [],\n map: Map<Key, TreeNode<T>>,\n parentKey?: Key | null\n ) {\n if (initialItems == null) {\n initialItems = [];\n }\n return {\n items: initialItems.map(item => {\n let node: TreeNode<T> = {\n key: getKey(item),\n parentKey: parentKey ?? null,\n value: item,\n children: null\n };\n\n node.children = buildTree(getChildren(item), map, node.key).items;\n map.set(node.key, node);\n return node;\n }),\n nodeMap: map\n };\n }\n\n function updateTree(\n items: TreeNode<T>[],\n key: Key | null,\n update: (node: TreeNode<T>) => TreeNode<T> | null,\n originalMap: Map<Key, TreeNode<T>>\n ) {\n let node = key == null ? null : originalMap.get(key);\n if (node == null) {\n return {items, nodeMap: originalMap};\n }\n let map = new Map<Key, TreeNode<T>>(originalMap);\n\n // Create a new node. If null, then delete the node, otherwise replace.\n let newNode = update(node);\n if (newNode == null) {\n deleteNode(node, map);\n } else {\n addNode(newNode, map);\n }\n\n // Walk up the tree and update each parent to refer to the new children.\n while (node && node.parentKey) {\n let nextParent = map.get(node.parentKey)!;\n let copy: TreeNode<T> = {\n key: nextParent.key,\n parentKey: nextParent.parentKey,\n value: nextParent.value,\n children: null\n };\n\n let children = nextParent.children;\n if (newNode == null && children) {\n children = children.filter(c => c !== node);\n }\n\n copy.children =\n children?.map(child => {\n if (child === node) {\n // newNode cannot be null here due to the above filter.\n return newNode!;\n }\n\n return child;\n }) ?? null;\n\n map.set(copy.key, copy);\n\n newNode = copy;\n node = nextParent;\n }\n\n if (newNode == null) {\n items = items.filter(c => c !== node);\n }\n\n return {\n items: items.map(item => {\n if (item === node) {\n // newNode cannot be null here due to the above filter.\n return newNode!;\n }\n\n return item;\n }),\n nodeMap: map\n };\n }\n\n function addNode(node: TreeNode<T>, map: Map<Key, TreeNode<T>>) {\n map.set(node.key, node);\n if (node.children) {\n for (let child of node.children) {\n addNode(child, map);\n }\n }\n }\n\n function deleteNode(node: TreeNode<T>, map: Map<Key, TreeNode<T>>) {\n map.delete(node.key);\n if (node.children) {\n for (let child of node.children) {\n deleteNode(child, map);\n }\n }\n }\n return {\n items,\n selectedKeys,\n setSelectedKeys,\n getItem(key: Key) {\n return nodeMap.get(key);\n },\n insert(parentKey: Key | null, index: number, ...values: T[]) {\n setItems(({items, nodeMap: originalMap}) => {\n let {items: newNodes, nodeMap: newMap} = buildTree(values, new Map(originalMap), parentKey);\n\n // If parentKey is null, insert into the root.\n if (parentKey == null) {\n return {\n items: [...items.slice(0, index), ...newNodes, ...items.slice(index)],\n nodeMap: newMap\n };\n }\n\n // Otherwise, update the parent node and its ancestors.\n return updateTree(\n items,\n parentKey,\n parentNode => ({\n key: parentNode.key,\n parentKey: parentNode.parentKey,\n value: parentNode.value,\n children: [\n ...parentNode.children!.slice(0, index),\n ...newNodes,\n ...parentNode.children!.slice(index)\n ]\n }),\n newMap\n );\n });\n },\n insertBefore(key: Key, ...values: T[]): void {\n let node = nodeMap.get(key);\n if (!node) {\n return;\n }\n\n let parentNode = nodeMap.get(node.parentKey!);\n let nodes = parentNode ? parentNode.children : items;\n let index = nodes!.indexOf(node);\n this.insert(parentNode?.key ?? null, index, ...values);\n },\n insertAfter(key: Key, ...values: T[]): void {\n let node = nodeMap.get(key);\n if (!node) {\n return;\n }\n\n let parentNode = nodeMap.get(node.parentKey!);\n let nodes = parentNode ? parentNode.children : items;\n let index = nodes!.indexOf(node);\n this.insert(parentNode?.key ?? null, index + 1, ...values);\n },\n prepend(parentKey: Key | null, ...values: T[]) {\n this.insert(parentKey, 0, ...values);\n },\n append(parentKey: Key | null, ...values: T[]) {\n if (parentKey == null) {\n this.insert(null, items.length, ...values);\n } else {\n let parentNode = nodeMap.get(parentKey);\n if (!parentNode) {\n return;\n }\n\n this.insert(parentKey, parentNode.children!.length, ...values);\n }\n },\n remove(...keys: Key[]) {\n if (keys.length === 0) {\n return;\n }\n\n let newItems = items;\n let prevMap = nodeMap;\n let newTree;\n for (let key of keys) {\n newTree = updateTree(newItems, key, () => null, prevMap);\n prevMap = newTree.nodeMap;\n newItems = newTree.items;\n }\n\n setItems(newTree);\n\n let selection = new Set(selectedKeys);\n for (let key of selectedKeys) {\n if (!newTree.nodeMap.has(key)) {\n selection.delete(key);\n }\n }\n\n setSelectedKeys(selection);\n },\n removeSelectedItems() {\n this.remove(...selectedKeys);\n },\n move(key: Key, toParentKey: Key | null, index: number) {\n setItems(({items, nodeMap: originalMap}) => {\n let node = originalMap.get(key);\n if (!node) {\n return {items, nodeMap: originalMap};\n }\n\n let {items: newItems, nodeMap: newMap} = updateTree(items, key, () => null, originalMap);\n\n const movedNode = {\n ...node,\n parentKey: toParentKey\n };\n\n // If parentKey is null, insert into the root.\n if (toParentKey == null) {\n addNode(movedNode, newMap);\n return {\n items: [...newItems.slice(0, index), movedNode, ...newItems.slice(index)],\n nodeMap: newMap\n };\n }\n\n // Otherwise, update the parent node and its ancestors.\n return updateTree(\n newItems,\n toParentKey,\n parentNode => ({\n key: parentNode.key,\n parentKey: parentNode.parentKey,\n value: parentNode.value,\n children: [\n ...parentNode.children!.slice(0, index),\n movedNode,\n ...parentNode.children!.slice(index)\n ]\n }),\n newMap\n );\n });\n },\n moveBefore(key: Key, keys: Iterable<Key>) {\n setItems(prevState => {\n let {items, nodeMap} = prevState;\n let node = nodeMap.get(key);\n if (!node) {\n return prevState;\n }\n let toParentKey = node.parentKey ?? null;\n let parent: null | TreeNode<T> = null;\n if (toParentKey != null) {\n parent = nodeMap.get(toParentKey) ?? null;\n }\n let toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);\n return moveItems(prevState, keys, parent, toIndex, updateTree, addNode);\n });\n },\n moveAfter(key: Key, keys: Iterable<Key>) {\n setItems(prevState => {\n let {items, nodeMap} = prevState;\n let node = nodeMap.get(key);\n if (!node) {\n return prevState;\n }\n let toParentKey = node.parentKey ?? null;\n let parent: null | TreeNode<T> = null;\n if (toParentKey != null) {\n parent = nodeMap.get(toParentKey) ?? null;\n }\n let toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);\n toIndex++;\n return moveItems(prevState, keys, parent, toIndex, updateTree, addNode);\n });\n },\n update(oldKey: Key, newValue: T) {\n setItems(({items, nodeMap: originalMap}) =>\n updateTree(\n items,\n oldKey,\n oldNode => {\n let node: TreeNode<T> = {\n key: oldNode.key,\n parentKey: oldNode.parentKey,\n value: newValue,\n children: null\n };\n\n let tree = buildTree(getChildren(newValue), originalMap, node.key);\n node.children = tree.items;\n return node;\n },\n originalMap\n )\n );\n }\n };\n}\n\nfunction moveItems<T extends object>(\n state: TreeDataState<T>,\n keys: Iterable<Key>,\n toParent: TreeNode<T> | null,\n toIndex: number,\n updateTree: (\n items: TreeNode<T>[],\n key: Key | null,\n update: (node: TreeNode<T>) => TreeNode<T> | null,\n originalMap: Map<Key, TreeNode<T>>\n ) => TreeDataState<T>,\n addNode: (node: TreeNode<T>, map: Map<Key, TreeNode<T>>) => void\n): TreeDataState<T> {\n let {items, nodeMap} = state;\n\n let parent = toParent;\n let removeKeys = new Set(keys);\n while (parent?.parentKey != null) {\n if (removeKeys.has(parent.key)) {\n throw new Error('Cannot move an item to be a child of itself.');\n }\n parent = nodeMap.get(parent.parentKey!) ?? null;\n }\n\n let originalToIndex = toIndex;\n\n let keyArray = Array.isArray(keys) ? keys : [...keys];\n // depth first search to put keys in order\n let inOrderKeys: Map<Key, number> = new Map();\n let removedItems: Array<TreeNode<T>> = [];\n let newItems = items;\n let newMap = nodeMap;\n let i = 0;\n\n function traversal(node, {inorder, postorder}) {\n inorder?.(node);\n if (node != null) {\n for (let child of node.children ?? []) {\n traversal(child, {inorder, postorder});\n postorder?.(child);\n }\n }\n }\n\n function inorder(child) {\n // in-order so we add items as we encounter them in the tree, then we can insert them in expected order later\n if (keyArray.includes(child.key)) {\n inOrderKeys.set(child.key, i++);\n }\n }\n\n function postorder(child) {\n // remove items and update the tree from the leaves and work upwards toward the root, this way\n // we don't copy child node references from parents inadvertently\n if (keyArray.includes(child.key)) {\n removedItems.push({...newMap.get(child.key)!, parentKey: toParent?.key ?? null});\n let {items: nextItems, nodeMap: nextMap} = updateTree(\n newItems,\n child.key,\n () => null,\n newMap\n );\n newItems = nextItems;\n newMap = nextMap;\n }\n // decrement the index if the child being removed is in the target parent and before the target index\n // the root node is special, it is null, and will not have a key, however, a parentKey can still point to it\n if (\n (child.parentKey === toParent || child.parentKey === toParent?.key) &&\n keyArray.includes(child.key) &&\n (toParent?.children ? toParent.children.indexOf(child) : items.indexOf(child)) <\n originalToIndex\n ) {\n toIndex--;\n }\n }\n\n traversal({children: items}, {inorder, postorder});\n\n let inOrderItems = removedItems.sort((a, b) =>\n inOrderKeys.get(a.key)! > inOrderKeys.get(b.key)! ? 1 : -1\n );\n // If parentKey is null, insert into the root.\n if (!toParent || toParent.key == null) {\n inOrderItems.forEach(movedNode => {\n addNode(movedNode, newMap);\n });\n return {\n items: [...newItems.slice(0, toIndex), ...inOrderItems, ...newItems.slice(toIndex)],\n nodeMap: newMap\n };\n }\n\n // Otherwise, update the parent node and its ancestors.\n return updateTree(\n newItems,\n toParent.key,\n parentNode => ({\n key: parentNode.key,\n parentKey: parentNode.parentKey,\n value: parentNode.value,\n children: [\n ...parentNode.children!.slice(0, toIndex),\n ...inOrderItems,\n ...parentNode.children!.slice(toIndex)\n ]\n }),\n newMap\n );\n}\n"],"names":[],"version":3,"file":"useTreeData.cjs.map"}
1
+ {"mappings":"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","sources":["packages/react-stately/src/data/useTreeData.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {Key} from '@react-types/shared';\nimport {useState} from 'react';\n\nexport interface TreeOptions<T extends object> {\n /** Initial root items in the tree. */\n initialItems?: T[];\n /** The keys for the initially selected items. */\n initialSelectedKeys?: Iterable<Key>;\n /** A function that returns a unique key for an item object. */\n getKey?: (item: T) => Key;\n /** A function that returns the children for an item object. */\n getChildren?: (item: T) => T[];\n}\n\ninterface TreeNode<T extends object> {\n /** A unique key for the tree node. */\n key: Key;\n /** The key of the parent node. */\n parentKey?: Key | null;\n /** The value object for the tree node. */\n value: T;\n /** Children of the tree node. */\n children: TreeNode<T>[] | null;\n}\n\nexport interface TreeData<T extends object> {\n /** The root nodes in the tree. */\n items: TreeNode<T>[];\n\n /** The keys of the currently selected items in the tree. */\n selectedKeys: Set<Key>;\n\n /** Sets the selected keys. */\n setSelectedKeys(keys: Set<Key>): void;\n\n /**\n * Gets a node from the tree by key.\n *\n * @param key - The key of the item to retrieve.\n */\n getItem(key: Key): TreeNode<T> | undefined;\n\n /**\n * Inserts an item into a parent node as a child.\n *\n * @param parentKey - The key of the parent item to insert into. `null` for the root.\n * @param index - The index within the parent to insert into.\n * @param value - The value to insert.\n */\n insert(parentKey: Key | null, index: number, ...values: T[]): void;\n\n /**\n * Inserts items into the list before the item at the given key.\n *\n * @param key - The key of the item to insert before.\n * @param values - The values to insert.\n */\n insertBefore(key: Key, ...values: T[]): void;\n\n /**\n * Inserts items into the list after the item at the given key.\n *\n * @param key - The key of the item to insert after.\n * @param values - The values to insert.\n */\n insertAfter(key: Key, ...values: T[]): void;\n\n /**\n * Appends an item into a parent node as a child.\n *\n * @param parentKey - The key of the parent item to insert into. `null` for the root.\n * @param value - The value to insert.\n */\n append(parentKey: Key | null, ...values: T[]): void;\n\n /**\n * Prepends an item into a parent node as a child.\n *\n * @param parentKey - The key of the parent item to insert into. `null` for the root.\n * @param value - The value to insert.\n */\n prepend(parentKey: Key | null, ...value: T[]): void;\n\n /**\n * Removes an item from the tree by its key.\n *\n * @param key - The key of the item to remove.\n */\n remove(...keys: Key[]): void;\n\n /**\n * Removes all items from the tree that are currently\n * in the set of selected items.\n */\n removeSelectedItems(): void;\n\n /**\n * Moves an item within the tree.\n *\n * @param key - The key of the item to move.\n * @param toParentKey - The key of the new parent to insert into. `null` for the root.\n * @param index - The index within the new parent to insert at.\n */\n move(key: Key, toParentKey: Key | null, index: number): void;\n\n /**\n * Moves one or more items before a given key.\n *\n * @param key - The key of the item to move the items before.\n * @param keys - The keys of the items to move.\n */\n moveBefore(key: Key, keys: Iterable<Key>): void;\n\n /**\n * Moves one or more items after a given key.\n *\n * @param key - The key of the item to move the items after.\n * @param keys - The keys of the items to move.\n */\n moveAfter(key: Key, keys: Iterable<Key>): void;\n\n /**\n * Updates an item in the tree.\n *\n * @param key - The key of the item to update.\n * @param newValue - The new value for the item.\n */\n update(key: Key, newValue: T): void;\n}\n\ninterface TreeDataState<T extends object> {\n items: TreeNode<T>[];\n nodeMap: Map<Key, TreeNode<T>>;\n}\n\n/**\n * Manages state for an immutable tree data structure, and provides convenience methods to\n * update the data over time.\n */\nexport function useTreeData<T extends object>(options: TreeOptions<T>): TreeData<T> {\n let {\n initialItems = [],\n initialSelectedKeys,\n getKey = (item: any) => item.id ?? item.key,\n getChildren = (item: any) => item.children\n } = options;\n\n // We only want to compute this on initial render.\n let [tree, setItems] = useState<TreeDataState<T>>(() => buildTree(initialItems, new Map()));\n let {items, nodeMap} = tree;\n\n let [selectedKeys, setSelectedKeys] = useState(new Set<Key>(initialSelectedKeys || []));\n\n // oxlint-disable-next-line react/react-compiler\n function buildTree(\n initialItems: T[] | null = [],\n map: Map<Key, TreeNode<T>>,\n parentKey?: Key | null\n ) {\n if (initialItems == null) {\n initialItems = [];\n }\n return {\n items: initialItems.map(item => {\n let node: TreeNode<T> = {\n key: getKey(item),\n parentKey: parentKey ?? null,\n value: item,\n children: null\n };\n\n node.children = buildTree(getChildren(item), map, node.key).items;\n map.set(node.key, node);\n return node;\n }),\n nodeMap: map\n };\n }\n\n function updateTree(\n items: TreeNode<T>[],\n key: Key | null,\n update: (node: TreeNode<T>) => TreeNode<T> | null,\n originalMap: Map<Key, TreeNode<T>>\n ) {\n let node = key == null ? null : originalMap.get(key);\n if (node == null) {\n return {items, nodeMap: originalMap};\n }\n let map = new Map<Key, TreeNode<T>>(originalMap);\n\n // Create a new node. If null, then delete the node, otherwise replace.\n let newNode = update(node);\n if (newNode == null) {\n deleteNode(node, map);\n } else {\n addNode(newNode, map);\n }\n\n // Walk up the tree and update each parent to refer to the new children.\n while (node && node.parentKey) {\n let nextParent = map.get(node.parentKey)!;\n let copy: TreeNode<T> = {\n key: nextParent.key,\n parentKey: nextParent.parentKey,\n value: nextParent.value,\n children: null\n };\n\n let children = nextParent.children;\n if (newNode == null && children) {\n children = children.filter(c => c !== node);\n }\n\n copy.children =\n children?.map(child => {\n if (child === node) {\n // newNode cannot be null here due to the above filter.\n return newNode!;\n }\n\n return child;\n }) ?? null;\n\n map.set(copy.key, copy);\n\n newNode = copy;\n node = nextParent;\n }\n\n if (newNode == null) {\n items = items.filter(c => c !== node);\n }\n\n return {\n items: items.map(item => {\n if (item === node) {\n // newNode cannot be null here due to the above filter.\n return newNode!;\n }\n\n return item;\n }),\n nodeMap: map\n };\n }\n\n function addNode(node: TreeNode<T>, map: Map<Key, TreeNode<T>>) {\n map.set(node.key, node);\n if (node.children) {\n for (let child of node.children) {\n addNode(child, map);\n }\n }\n }\n\n function deleteNode(node: TreeNode<T>, map: Map<Key, TreeNode<T>>) {\n map.delete(node.key);\n if (node.children) {\n for (let child of node.children) {\n deleteNode(child, map);\n }\n }\n }\n return {\n items,\n selectedKeys,\n setSelectedKeys,\n getItem(key: Key) {\n return nodeMap.get(key);\n },\n insert(parentKey: Key | null, index: number, ...values: T[]) {\n setItems(({items, nodeMap: originalMap}) => {\n let {items: newNodes, nodeMap: newMap} = buildTree(values, new Map(originalMap), parentKey);\n\n // If parentKey is null, insert into the root.\n if (parentKey == null) {\n return {\n items: [...items.slice(0, index), ...newNodes, ...items.slice(index)],\n nodeMap: newMap\n };\n }\n\n // Otherwise, update the parent node and its ancestors.\n return updateTree(\n items,\n parentKey,\n parentNode => ({\n key: parentNode.key,\n parentKey: parentNode.parentKey,\n value: parentNode.value,\n children: [\n ...parentNode.children!.slice(0, index),\n ...newNodes,\n ...parentNode.children!.slice(index)\n ]\n }),\n newMap\n );\n });\n },\n insertBefore(key: Key, ...values: T[]): void {\n let node = nodeMap.get(key);\n if (!node) {\n return;\n }\n\n let parentNode = nodeMap.get(node.parentKey!);\n let nodes = parentNode ? parentNode.children : items;\n let index = nodes!.indexOf(node);\n this.insert(parentNode?.key ?? null, index, ...values);\n },\n insertAfter(key: Key, ...values: T[]): void {\n let node = nodeMap.get(key);\n if (!node) {\n return;\n }\n\n let parentNode = nodeMap.get(node.parentKey!);\n let nodes = parentNode ? parentNode.children : items;\n let index = nodes!.indexOf(node);\n this.insert(parentNode?.key ?? null, index + 1, ...values);\n },\n prepend(parentKey: Key | null, ...values: T[]) {\n this.insert(parentKey, 0, ...values);\n },\n append(parentKey: Key | null, ...values: T[]) {\n if (parentKey == null) {\n this.insert(null, items.length, ...values);\n } else {\n let parentNode = nodeMap.get(parentKey);\n if (!parentNode) {\n return;\n }\n\n this.insert(parentKey, parentNode.children!.length, ...values);\n }\n },\n remove(...keys: Key[]) {\n if (keys.length === 0) {\n return;\n }\n\n let newItems = items;\n let prevMap = nodeMap;\n let newTree;\n for (let key of keys) {\n newTree = updateTree(newItems, key, () => null, prevMap);\n prevMap = newTree.nodeMap;\n newItems = newTree.items;\n }\n\n setItems(newTree);\n\n let selection = new Set(selectedKeys);\n for (let key of selectedKeys) {\n if (!newTree.nodeMap.has(key)) {\n selection.delete(key);\n }\n }\n\n setSelectedKeys(selection);\n },\n removeSelectedItems() {\n this.remove(...selectedKeys);\n },\n move(key: Key, toParentKey: Key | null, index: number) {\n setItems(({items, nodeMap: originalMap}) => {\n let node = originalMap.get(key);\n if (!node) {\n return {items, nodeMap: originalMap};\n }\n\n let {items: newItems, nodeMap: newMap} = updateTree(items, key, () => null, originalMap);\n\n const movedNode = {\n ...node,\n parentKey: toParentKey\n };\n\n // If parentKey is null, insert into the root.\n if (toParentKey == null) {\n addNode(movedNode, newMap);\n return {\n items: [...newItems.slice(0, index), movedNode, ...newItems.slice(index)],\n nodeMap: newMap\n };\n }\n\n // Otherwise, update the parent node and its ancestors.\n return updateTree(\n newItems,\n toParentKey,\n parentNode => ({\n key: parentNode.key,\n parentKey: parentNode.parentKey,\n value: parentNode.value,\n children: [\n ...parentNode.children!.slice(0, index),\n movedNode,\n ...parentNode.children!.slice(index)\n ]\n }),\n newMap\n );\n });\n },\n moveBefore(key: Key, keys: Iterable<Key>) {\n setItems(prevState => {\n let {items, nodeMap} = prevState;\n let node = nodeMap.get(key);\n if (!node) {\n return prevState;\n }\n let toParentKey = node.parentKey ?? null;\n let parent: null | TreeNode<T> = null;\n if (toParentKey != null) {\n parent = nodeMap.get(toParentKey) ?? null;\n }\n let toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);\n return moveItems(prevState, keys, parent, toIndex, updateTree, addNode);\n });\n },\n moveAfter(key: Key, keys: Iterable<Key>) {\n setItems(prevState => {\n let {items, nodeMap} = prevState;\n let node = nodeMap.get(key);\n if (!node) {\n return prevState;\n }\n let toParentKey = node.parentKey ?? null;\n let parent: null | TreeNode<T> = null;\n if (toParentKey != null) {\n parent = nodeMap.get(toParentKey) ?? null;\n }\n let toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);\n toIndex++;\n return moveItems(prevState, keys, parent, toIndex, updateTree, addNode);\n });\n },\n update(oldKey: Key, newValue: T) {\n setItems(({items, nodeMap: originalMap}) =>\n updateTree(\n items,\n oldKey,\n oldNode => {\n let node: TreeNode<T> = {\n key: oldNode.key,\n parentKey: oldNode.parentKey,\n value: newValue,\n children: null\n };\n\n let tree = buildTree(getChildren(newValue), originalMap, node.key);\n node.children = tree.items;\n return node;\n },\n originalMap\n )\n );\n }\n };\n}\n\nfunction moveItems<T extends object>(\n state: TreeDataState<T>,\n keys: Iterable<Key>,\n toParent: TreeNode<T> | null,\n toIndex: number,\n updateTree: (\n items: TreeNode<T>[],\n key: Key | null,\n update: (node: TreeNode<T>) => TreeNode<T> | null,\n originalMap: Map<Key, TreeNode<T>>\n ) => TreeDataState<T>,\n addNode: (node: TreeNode<T>, map: Map<Key, TreeNode<T>>) => void\n): TreeDataState<T> {\n let {items, nodeMap} = state;\n\n let parent = toParent;\n let removeKeys = new Set(keys);\n while (parent?.parentKey != null) {\n if (removeKeys.has(parent.key)) {\n throw new Error('Cannot move an item to be a child of itself.');\n }\n parent = nodeMap.get(parent.parentKey!) ?? null;\n }\n\n let originalToIndex = toIndex;\n\n let keyArray = Array.isArray(keys) ? keys : [...keys];\n // depth first search to put keys in order\n let inOrderKeys: Map<Key, number> = new Map();\n let removedItems: Array<TreeNode<T>> = [];\n let newItems = items;\n let newMap = nodeMap;\n let i = 0;\n\n function traversal(node, {inorder, postorder}) {\n inorder?.(node);\n if (node != null) {\n for (let child of node.children ?? []) {\n traversal(child, {inorder, postorder});\n postorder?.(child);\n }\n }\n }\n\n function inorder(child) {\n // in-order so we add items as we encounter them in the tree, then we can insert them in expected order later\n if (keyArray.includes(child.key)) {\n inOrderKeys.set(child.key, i++);\n }\n }\n\n function postorder(child) {\n // remove items and update the tree from the leaves and work upwards toward the root, this way\n // we don't copy child node references from parents inadvertently\n if (keyArray.includes(child.key)) {\n removedItems.push({...newMap.get(child.key)!, parentKey: toParent?.key ?? null});\n let {items: nextItems, nodeMap: nextMap} = updateTree(\n newItems,\n child.key,\n () => null,\n newMap\n );\n newItems = nextItems;\n newMap = nextMap;\n }\n // decrement the index if the child being removed is in the target parent and before the target index\n // the root node is special, it is null, and will not have a key, however, a parentKey can still point to it\n if (\n (child.parentKey === toParent || child.parentKey === toParent?.key) &&\n keyArray.includes(child.key) &&\n (toParent?.children ? toParent.children.indexOf(child) : items.indexOf(child)) <\n originalToIndex\n ) {\n toIndex--;\n }\n }\n\n traversal({children: items}, {inorder, postorder});\n\n let inOrderItems = removedItems.sort((a, b) =>\n inOrderKeys.get(a.key)! > inOrderKeys.get(b.key)! ? 1 : -1\n );\n // If parentKey is null, insert into the root.\n if (!toParent || toParent.key == null) {\n inOrderItems.forEach(movedNode => {\n addNode(movedNode, newMap);\n });\n return {\n items: [...newItems.slice(0, toIndex), ...inOrderItems, ...newItems.slice(toIndex)],\n nodeMap: newMap\n };\n }\n\n // Otherwise, update the parent node and its ancestors.\n return updateTree(\n newItems,\n toParent.key,\n parentNode => ({\n key: parentNode.key,\n parentKey: parentNode.parentKey,\n value: parentNode.value,\n children: [\n ...parentNode.children!.slice(0, toIndex),\n ...inOrderItems,\n ...parentNode.children!.slice(toIndex)\n ]\n }),\n newMap\n );\n}\n"],"names":[],"version":3,"file":"useTreeData.cjs.map"}
@@ -20,6 +20,7 @@ function $fed32bb7b9c8a2e7$export$d14e1352e21f4a16(options) {
20
20
  let [tree, setItems] = (0, $l7jaK$useState)(()=>buildTree(initialItems, new Map()));
21
21
  let { items: items, nodeMap: nodeMap } = tree;
22
22
  let [selectedKeys, setSelectedKeys] = (0, $l7jaK$useState)(new Set(initialSelectedKeys || []));
23
+ // oxlint-disable-next-line react/react-compiler
23
24
  function buildTree(initialItems = [], map, parentKey) {
24
25
  if (initialItems == null) initialItems = [];
25
26
  return {