@react-stately/combobox
Advanced tools
Comparing version 3.0.0-alpha.0 to 3.0.0-alpha.1
@@ -27,4 +27,9 @@ var { | ||
/** | ||
* Provides state management for a combo box component. Handles building a collection | ||
* of items from props and manages the option selection state of the combo box. In addition, it tracks the input value, | ||
* focus state, and other properties of the combo box. | ||
*/ | ||
function useComboBoxState(props) { | ||
var _props$defaultInputVa, _props$items; | ||
var _props$defaultInputVa, _props$items, _ref, _props$selectedKey; | ||
@@ -40,2 +45,18 @@ let { | ||
let [inputValue, setInputValue] = useControlledState(props.inputValue, (_props$defaultInputVa = props.defaultInputValue) != null ? _props$defaultInputVa : '', props.onInputChange); | ||
let onSelectionChange = key => { | ||
if (props.onSelectionChange) { | ||
props.onSelectionChange(key); | ||
} // If open state or selectedKey is uncontrolled and key is the same, reset the inputValue and close the menu | ||
// (scenario: user clicks on already selected option) | ||
if (props.isOpen === undefined || props.selectedKey === undefined) { | ||
if (key === selectedKey) { | ||
resetInputValue(); | ||
triggerState.close(); | ||
} | ||
} | ||
}; | ||
let { | ||
@@ -49,2 +70,3 @@ collection, | ||
} = useSingleSelectListState(_babelRuntimeHelpersExtends({}, props, { | ||
onSelectionChange, | ||
items: (_props$items = props.items) != null ? _props$items : props.defaultItems | ||
@@ -63,2 +85,11 @@ })); | ||
let toggle = focusStrategy => { | ||
// If the menu is closed and there is nothing to display, early return so toggle isn't called to prevent extraneous onOpenChange | ||
if (!(allowsEmptyCollection || filteredCollection.size > 0) && !triggerState.isOpen) { | ||
return; | ||
} | ||
triggerState.toggle(focusStrategy); | ||
}; | ||
let lastValue = useRef(inputValue); | ||
@@ -75,3 +106,3 @@ | ||
let isInitialRender = useRef(true); | ||
let lastSelectedKey = useRef(null); | ||
let lastSelectedKey = useRef((_ref = (_props$selectedKey = props.selectedKey) != null ? _props$selectedKey : props.defaultSelectedKey) != null ? _ref : null); | ||
useEffect(() => { | ||
@@ -102,2 +133,7 @@ // If open state or inputValue is uncontrolled, open and close automatically when the input value changes, | ||
} | ||
} // If it is the intial render and inputValue isn't controlled nor has an intial value, set input to match current selected key if any | ||
if (isInitialRender.current && props.inputValue === undefined && props.defaultInputValue === undefined) { | ||
resetInputValue(); | ||
} // If the selectedKey changed, update the input value. | ||
@@ -109,3 +145,3 @@ // Do nothing if both inputValue and selectedKey are controlled. | ||
if (selectedKey !== lastSelectedKey.current && (props.inputValue === undefined || props.selectedKey === undefined) && !(isInitialRender.current && props.defaultInputValue !== undefined)) { | ||
if (selectedKey !== lastSelectedKey.current && (props.inputValue === undefined || props.selectedKey === undefined)) { | ||
resetInputValue(); | ||
@@ -128,14 +164,14 @@ } else { | ||
let shouldClose = false; | ||
lastSelectedKey.current = null; | ||
setSelectedKey(null); // If previous key was already null, need to manually call onSelectionChange since it won't be triggered by a setSelectedKey call | ||
// This allows the application to control whether or not to close the menu on custom value commit | ||
if (!allowsCustomValue) { | ||
resetInputValue(); | ||
shouldClose = inputValue === lastValue.current; | ||
} else { | ||
lastSelectedKey.current = null; | ||
setSelectedKey(null); | ||
shouldClose = selectedKey === null; | ||
} // Close if no other event will be fired. Otherwise, allow the | ||
if (selectedKey === null && props.onSelectionChange) { | ||
props.onSelectionChange(null); | ||
} // Should close menu ourselves if component open state or selected key is uncontrolled and therefore won't be closed by a user defined event handler | ||
shouldClose = props.isOpen == null || props.selectedKey === undefined; // Close if no other event will be fired. Otherwise, allow the | ||
// application to control this based on that event. | ||
if (shouldClose) { | ||
@@ -148,5 +184,6 @@ triggerState.close(); | ||
if (triggerState.isOpen && selectionManager.focusedKey != null) { | ||
// Close here if the selected key is already the focused key. Otherwise | ||
// Reset inputValue and close menu here if the selected key is already the focused key. Otherwise | ||
// fire onSelectionChange to allow the application to control the closing. | ||
if (selectedKey === selectionManager.focusedKey) { | ||
resetInputValue(); | ||
triggerState.close(); | ||
@@ -156,3 +193,3 @@ } else { | ||
} | ||
} else { | ||
} else if (allowsCustomValue) { | ||
commitCustomValue(); | ||
@@ -168,3 +205,14 @@ } | ||
} else if (shouldCloseOnBlur) { | ||
commitCustomValue(); | ||
var _collection$getItem$t2, _collection$getItem2; | ||
let itemText = (_collection$getItem$t2 = (_collection$getItem2 = collection.getItem(selectedKey)) == null ? void 0 : _collection$getItem2.textValue) != null ? _collection$getItem$t2 : ''; | ||
if (allowsCustomValue && inputValue !== itemText) { | ||
commitCustomValue(); | ||
} else { | ||
resetInputValue(); // Close menu if blurring away from the combobox | ||
// Specifically handles case where user clicks away from the field | ||
triggerState.close(); | ||
} | ||
} | ||
@@ -176,2 +224,3 @@ | ||
return _babelRuntimeHelpersExtends({}, triggerState, { | ||
toggle, | ||
open, | ||
@@ -178,0 +227,0 @@ selectionManager, |
@@ -6,4 +6,10 @@ import { useMenuTriggerState } from "@react-stately/menu"; | ||
import _babelRuntimeHelpersEsmExtends from "@babel/runtime/helpers/esm/extends"; | ||
/** | ||
* Provides state management for a combo box component. Handles building a collection | ||
* of items from props and manages the option selection state of the combo box. In addition, it tracks the input value, | ||
* focus state, and other properties of the combo box. | ||
*/ | ||
export function useComboBoxState(props) { | ||
var _props$defaultInputVa, _props$items; | ||
var _props$defaultInputVa, _props$items, _ref, _props$selectedKey; | ||
@@ -19,2 +25,18 @@ let { | ||
let [inputValue, setInputValue] = useControlledState(props.inputValue, (_props$defaultInputVa = props.defaultInputValue) != null ? _props$defaultInputVa : '', props.onInputChange); | ||
let onSelectionChange = key => { | ||
if (props.onSelectionChange) { | ||
props.onSelectionChange(key); | ||
} // If open state or selectedKey is uncontrolled and key is the same, reset the inputValue and close the menu | ||
// (scenario: user clicks on already selected option) | ||
if (props.isOpen === undefined || props.selectedKey === undefined) { | ||
if (key === selectedKey) { | ||
resetInputValue(); | ||
triggerState.close(); | ||
} | ||
} | ||
}; | ||
let { | ||
@@ -28,2 +50,3 @@ collection, | ||
} = useSingleSelectListState(_babelRuntimeHelpersEsmExtends({}, props, { | ||
onSelectionChange, | ||
items: (_props$items = props.items) != null ? _props$items : props.defaultItems | ||
@@ -42,2 +65,11 @@ })); | ||
let toggle = focusStrategy => { | ||
// If the menu is closed and there is nothing to display, early return so toggle isn't called to prevent extraneous onOpenChange | ||
if (!(allowsEmptyCollection || filteredCollection.size > 0) && !triggerState.isOpen) { | ||
return; | ||
} | ||
triggerState.toggle(focusStrategy); | ||
}; | ||
let lastValue = useRef(inputValue); | ||
@@ -54,3 +86,3 @@ | ||
let isInitialRender = useRef(true); | ||
let lastSelectedKey = useRef(null); | ||
let lastSelectedKey = useRef((_ref = (_props$selectedKey = props.selectedKey) != null ? _props$selectedKey : props.defaultSelectedKey) != null ? _ref : null); | ||
useEffect(() => { | ||
@@ -81,2 +113,7 @@ // If open state or inputValue is uncontrolled, open and close automatically when the input value changes, | ||
} | ||
} // If it is the intial render and inputValue isn't controlled nor has an intial value, set input to match current selected key if any | ||
if (isInitialRender.current && props.inputValue === undefined && props.defaultInputValue === undefined) { | ||
resetInputValue(); | ||
} // If the selectedKey changed, update the input value. | ||
@@ -88,3 +125,3 @@ // Do nothing if both inputValue and selectedKey are controlled. | ||
if (selectedKey !== lastSelectedKey.current && (props.inputValue === undefined || props.selectedKey === undefined) && !(isInitialRender.current && props.defaultInputValue !== undefined)) { | ||
if (selectedKey !== lastSelectedKey.current && (props.inputValue === undefined || props.selectedKey === undefined)) { | ||
resetInputValue(); | ||
@@ -107,14 +144,14 @@ } else { | ||
let shouldClose = false; | ||
lastSelectedKey.current = null; | ||
setSelectedKey(null); // If previous key was already null, need to manually call onSelectionChange since it won't be triggered by a setSelectedKey call | ||
// This allows the application to control whether or not to close the menu on custom value commit | ||
if (!allowsCustomValue) { | ||
resetInputValue(); | ||
shouldClose = inputValue === lastValue.current; | ||
} else { | ||
lastSelectedKey.current = null; | ||
setSelectedKey(null); | ||
shouldClose = selectedKey === null; | ||
} // Close if no other event will be fired. Otherwise, allow the | ||
if (selectedKey === null && props.onSelectionChange) { | ||
props.onSelectionChange(null); | ||
} // Should close menu ourselves if component open state or selected key is uncontrolled and therefore won't be closed by a user defined event handler | ||
shouldClose = props.isOpen == null || props.selectedKey === undefined; // Close if no other event will be fired. Otherwise, allow the | ||
// application to control this based on that event. | ||
if (shouldClose) { | ||
@@ -127,5 +164,6 @@ triggerState.close(); | ||
if (triggerState.isOpen && selectionManager.focusedKey != null) { | ||
// Close here if the selected key is already the focused key. Otherwise | ||
// Reset inputValue and close menu here if the selected key is already the focused key. Otherwise | ||
// fire onSelectionChange to allow the application to control the closing. | ||
if (selectedKey === selectionManager.focusedKey) { | ||
resetInputValue(); | ||
triggerState.close(); | ||
@@ -135,3 +173,3 @@ } else { | ||
} | ||
} else { | ||
} else if (allowsCustomValue) { | ||
commitCustomValue(); | ||
@@ -147,3 +185,14 @@ } | ||
} else if (shouldCloseOnBlur) { | ||
commitCustomValue(); | ||
var _collection$getItem$t2, _collection$getItem2; | ||
let itemText = (_collection$getItem$t2 = (_collection$getItem2 = collection.getItem(selectedKey)) == null ? void 0 : _collection$getItem2.textValue) != null ? _collection$getItem$t2 : ''; | ||
if (allowsCustomValue && inputValue !== itemText) { | ||
commitCustomValue(); | ||
} else { | ||
resetInputValue(); // Close menu if blurring away from the combobox | ||
// Specifically handles case where user clicks away from the field | ||
triggerState.close(); | ||
} | ||
} | ||
@@ -155,2 +204,3 @@ | ||
return _babelRuntimeHelpersEsmExtends({}, triggerState, { | ||
toggle, | ||
open, | ||
@@ -157,0 +207,0 @@ selectionManager, |
import { ComboBoxProps } from "@react-types/combobox"; | ||
import { SelectState } from "@react-stately/select"; | ||
export interface ComboBoxState<T> extends SelectState<T> { | ||
/** The current value of the combo box input. */ | ||
inputValue: string; | ||
/** Sets the value of the combo box input. */ | ||
setInputValue(value: string): void; | ||
/** Selects the currently focused item and updates the input value. */ | ||
commit(): void; | ||
@@ -10,8 +13,16 @@ } | ||
interface ComboBoxStateProps<T> extends ComboBoxProps<T> { | ||
/** The filter function used to determine if a option should be included in the combo box list. */ | ||
defaultFilter?: FilterFn; | ||
/** Whether the combo box allows the menu to be open when the collection is empty. */ | ||
allowsEmptyCollection?: boolean; | ||
/** Whether the combo box menu should close on blur. */ | ||
shouldCloseOnBlur?: boolean; | ||
} | ||
/** | ||
* Provides state management for a combo box component. Handles building a collection | ||
* of items from props and manages the option selection state of the combo box. In addition, it tracks the input value, | ||
* focus state, and other properties of the combo box. | ||
*/ | ||
export function useComboBoxState<T extends object>(props: ComboBoxStateProps<T>): ComboBoxState<T>; | ||
//# sourceMappingURL=types.d.ts.map |
{ | ||
"name": "@react-stately/combobox", | ||
"version": "3.0.0-alpha.0", | ||
"version": "3.0.0-alpha.1", | ||
"description": "Spectrum UI components in React", | ||
@@ -24,5 +24,5 @@ "license": "Apache-2.0", | ||
"@react-stately/select": "^3.1.0", | ||
"@react-stately/utils": "^3.1.0", | ||
"@react-types/combobox": "3.0.0-alpha.0", | ||
"@react-types/shared": "^3.1.0" | ||
"@react-stately/utils": "^3.2.0", | ||
"@react-types/combobox": "3.0.0-alpha.1", | ||
"@react-types/shared": "^3.4.0" | ||
}, | ||
@@ -35,3 +35,3 @@ "peerDependencies": { | ||
}, | ||
"gitHead": "f5b429ee8615248f2e3c76754bad2ece83f1c444" | ||
"gitHead": "7f9dc7fa5144679d2dc733170cb5c1f40d0c5ee5" | ||
} |
@@ -22,4 +22,7 @@ /* | ||
export interface ComboBoxState<T> extends SelectState<T> { | ||
/** The current value of the combo box input. */ | ||
inputValue: string, | ||
/** Sets the value of the combo box input. */ | ||
setInputValue(value: string): void, | ||
/** Selects the currently focused item and updates the input value. */ | ||
commit(): void | ||
@@ -30,7 +33,15 @@ } | ||
interface ComboBoxStateProps<T> extends ComboBoxProps<T> { | ||
/** The filter function used to determine if a option should be included in the combo box list. */ | ||
defaultFilter?: FilterFn, | ||
/** Whether the combo box allows the menu to be open when the collection is empty. */ | ||
allowsEmptyCollection?: boolean, | ||
/** Whether the combo box menu should close on blur. */ | ||
shouldCloseOnBlur?: boolean | ||
} | ||
/** | ||
* Provides state management for a combo box component. Handles building a collection | ||
* of items from props and manages the option selection state of the combo box. In addition, it tracks the input value, | ||
* focus state, and other properties of the combo box. | ||
*/ | ||
export function useComboBoxState<T extends object>(props: ComboBoxStateProps<T>): ComboBoxState<T> { | ||
@@ -52,4 +63,20 @@ let { | ||
let onSelectionChange = (key) => { | ||
if (props.onSelectionChange) { | ||
props.onSelectionChange(key); | ||
} | ||
// If open state or selectedKey is uncontrolled and key is the same, reset the inputValue and close the menu | ||
// (scenario: user clicks on already selected option) | ||
if (props.isOpen === undefined || props.selectedKey === undefined) { | ||
if (key === selectedKey) { | ||
resetInputValue(); | ||
triggerState.close(); | ||
} | ||
} | ||
}; | ||
let {collection, selectionManager, selectedKey, setSelectedKey, selectedItem, disabledKeys} = useSingleSelectListState({ | ||
...props, | ||
onSelectionChange, | ||
items: props.items ?? props.defaultItems | ||
@@ -73,2 +100,11 @@ }); | ||
let toggle = (focusStrategy?: FocusStrategy) => { | ||
// If the menu is closed and there is nothing to display, early return so toggle isn't called to prevent extraneous onOpenChange | ||
if (!(allowsEmptyCollection || filteredCollection.size > 0) && !triggerState.isOpen) { | ||
return; | ||
} | ||
triggerState.toggle(focusStrategy); | ||
}; | ||
let lastValue = useRef(inputValue); | ||
@@ -82,3 +118,3 @@ let resetInputValue = () => { | ||
let isInitialRender = useRef(true); | ||
let lastSelectedKey = useRef(null); | ||
let lastSelectedKey = useRef(props.selectedKey ?? props.defaultSelectedKey ?? null); | ||
useEffect(() => { | ||
@@ -128,2 +164,7 @@ // If open state or inputValue is uncontrolled, open and close automatically when the input value changes, | ||
// If it is the intial render and inputValue isn't controlled nor has an intial value, set input to match current selected key if any | ||
if (isInitialRender.current && (props.inputValue === undefined && props.defaultInputValue === undefined)) { | ||
resetInputValue(); | ||
} | ||
// If the selectedKey changed, update the input value. | ||
@@ -135,4 +176,3 @@ // Do nothing if both inputValue and selectedKey are controlled. | ||
selectedKey !== lastSelectedKey.current && | ||
(props.inputValue === undefined || props.selectedKey === undefined) && | ||
!(isInitialRender.current && props.defaultInputValue !== undefined) | ||
(props.inputValue === undefined || props.selectedKey === undefined) | ||
) { | ||
@@ -157,11 +197,15 @@ resetInputValue(); | ||
let shouldClose = false; | ||
if (!allowsCustomValue) { | ||
resetInputValue(); | ||
shouldClose = inputValue === lastValue.current; | ||
} else { | ||
lastSelectedKey.current = null; | ||
setSelectedKey(null); | ||
shouldClose = selectedKey === null; | ||
lastSelectedKey.current = null; | ||
setSelectedKey(null); | ||
// If previous key was already null, need to manually call onSelectionChange since it won't be triggered by a setSelectedKey call | ||
// This allows the application to control whether or not to close the menu on custom value commit | ||
if (selectedKey === null && props.onSelectionChange) { | ||
props.onSelectionChange(null); | ||
} | ||
// Should close menu ourselves if component open state or selected key is uncontrolled and therefore won't be closed by a user defined event handler | ||
shouldClose = props.isOpen == null || props.selectedKey === undefined; | ||
// Close if no other event will be fired. Otherwise, allow the | ||
@@ -176,5 +220,6 @@ // application to control this based on that event. | ||
if (triggerState.isOpen && selectionManager.focusedKey != null) { | ||
// Close here if the selected key is already the focused key. Otherwise | ||
// Reset inputValue and close menu here if the selected key is already the focused key. Otherwise | ||
// fire onSelectionChange to allow the application to control the closing. | ||
if (selectedKey === selectionManager.focusedKey) { | ||
resetInputValue(); | ||
triggerState.close(); | ||
@@ -184,3 +229,3 @@ } else { | ||
} | ||
} else { | ||
} else if (allowsCustomValue) { | ||
commitCustomValue(); | ||
@@ -196,3 +241,11 @@ } | ||
} else if (shouldCloseOnBlur) { | ||
commitCustomValue(); | ||
let itemText = collection.getItem(selectedKey)?.textValue ?? ''; | ||
if (allowsCustomValue && inputValue !== itemText) { | ||
commitCustomValue(); | ||
} else { | ||
resetInputValue(); | ||
// Close menu if blurring away from the combobox | ||
// Specifically handles case where user clicks away from the field | ||
triggerState.close(); | ||
} | ||
} | ||
@@ -205,2 +258,3 @@ | ||
...triggerState, | ||
toggle, | ||
open, | ||
@@ -207,0 +261,0 @@ selectionManager, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
79903
681
+ Added@react-types/combobox@3.0.0-alpha.1(transitive)
- Removed@react-types/combobox@3.0.0-alpha.0(transitive)
Updated@react-stately/utils@^3.2.0
Updated@react-types/shared@^3.4.0