Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f05790a
initial progress w/ combobox menu show all
LFDanLu Mar 25, 2021
e1a1ae5
removing memo for original collection now that collection is not modi…
LFDanLu Mar 26, 2021
99167ea
making it so combobox w/ empty items list does not open even with new…
LFDanLu Mar 26, 2021
20fdd5a
fixing bug where mobile combobox only showed filtered list upon two e…
LFDanLu Mar 26, 2021
2f80496
apply review comments from meeting
LFDanLu Mar 26, 2021
d7292af
tweaking story and fixing lint
LFDanLu Mar 29, 2021
02449b1
fixing tests
LFDanLu Mar 29, 2021
b7b0ef2
adding more tests
LFDanLu Mar 29, 2021
5f0319c
fixing lint and extra test
LFDanLu Mar 29, 2021
c00c7b1
cleanup and adding useCombobox hooks for show all items
LFDanLu Mar 30, 2021
8c34e09
fixing chain call
LFDanLu Mar 30, 2021
4bc15f0
updating docs with example of show all when items are controlled
LFDanLu Mar 31, 2021
6d17fba
fixing doc example
LFDanLu Mar 31, 2021
f9a805f
more clean up
LFDanLu Mar 31, 2021
e470fef
Merge branch 'main' into issue_1705
LFDanLu Mar 31, 2021
1ae5087
Merge branch 'main' of github.com:adobe/react-spectrum into issue_1705
LFDanLu Apr 14, 2021
5f5f0c3
first stab at making combobox onopenchange return reason for menu open
LFDanLu Apr 14, 2021
81bc207
updating useComboBox tests and docs
LFDanLu Apr 15, 2021
e4fd93e
fixing tests
LFDanLu Apr 15, 2021
d3e8ab1
updating useComboBoxState open/toggle conditional
LFDanLu Apr 15, 2021
ad7c695
addressing review comments
LFDanLu Apr 19, 2021
fc5b8e5
Merge branch 'main' into issue_1705
LFDanLu Apr 19, 2021
d775a39
removing docs changes
LFDanLu Apr 20, 2021
a8f94f1
Merge branch 'issue_1705' of github.com:adobe/react-spectrum into iss…
LFDanLu Apr 20, 2021
685863f
Merge branch 'main' into issue_1705
LFDanLu Apr 20, 2021
10dafe3
removing extraneous conditional from collection return statement
LFDanLu Apr 20, 2021
2c71421
Merge branch 'issue_1705' of github.com:adobe/react-spectrum into iss…
LFDanLu Apr 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions packages/@react-aria/combobox/src/useComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ export function useComboBox<T>(props: AriaComboBoxProps<T>, state: ComboBoxState
state.close();
break;
case 'ArrowDown':
state.open('first');
state.open('first', 'manual');
break;
case 'ArrowUp':
state.open('last');
state.open('last', 'manual');
break;
case 'ArrowLeft':
case 'ArrowRight':
Expand Down Expand Up @@ -165,14 +165,14 @@ export function useComboBox<T>(props: AriaComboBoxProps<T>, state: ComboBoxState
if (e.pointerType === 'touch') {
// Focus the input field in case it isn't focused yet
inputRef.current.focus();
state.toggle();
state.toggle(null, 'manual');
}
};

let onPressStart = (e: PressEvent) => {
if (e.pointerType !== 'touch') {
inputRef.current.focus();
state.toggle((e.pointerType === 'keyboard' || e.pointerType === 'virtual') ? 'first' : null);
state.toggle((e.pointerType === 'keyboard' || e.pointerType === 'virtual') ? 'first' : null, 'manual');
}
};

Expand Down Expand Up @@ -211,7 +211,7 @@ export function useComboBox<T>(props: AriaComboBoxProps<T>, state: ComboBoxState
if (touch.clientX === centerX && touch.clientY === centerY) {
e.preventDefault();
inputRef.current.focus();
state.toggle();
state.toggle(null, 'manual');

lastEventTime.current = e.timeStamp;
}
Expand Down
50 changes: 46 additions & 4 deletions packages/@react-aria/combobox/test/useComboBox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {useSingleSelectListState} from '@react-stately/list';
describe('useComboBox', function () {
let preventDefault = jest.fn();
let stopPropagation = jest.fn();
let event = (key) => ({
key,
let event = (e) => ({
...e,
preventDefault,
stopPropagation
});
Expand Down Expand Up @@ -89,11 +89,53 @@ describe('useComboBox', function () {
let {result, rerender} = renderHook((props) => useComboBox(props, useComboBoxState(props)), {initialProps: props});
let {inputProps} = result.current;

inputProps.onKeyDown(event('Enter'));
inputProps.onKeyDown(event({key: 'Enter'}));
expect(preventDefault).toHaveBeenCalledTimes(1);

rerender({...props, isOpen: false});
result.current.inputProps.onKeyDown(event('Enter'));
result.current.inputProps.onKeyDown(event({key: 'Enter'}));
expect(preventDefault).toHaveBeenCalledTimes(1);
});

it('calls open and toggle with the expected parameters when arrow down/up/trigger button is pressed', function () {
let openSpy = jest.fn();
let toggleSpy = jest.fn();
let props = {
label: 'test label',
popoverRef: React.createRef(),
buttonRef: React.createRef(),
inputRef: {
current: {
contains: jest.fn(),
focus: jest.fn()
}
},
listBoxRef: React.createRef(),
layout: mockLayout,
isOpen: false
};

let {result: state} = renderHook((props) => useComboBoxState(props), {initialProps: props});
state.current.open = openSpy;
state.current.toggle = toggleSpy;

let {result} = renderHook((props) => useComboBox(props, state.current), {initialProps: props});
let {inputProps, buttonProps} = result.current;
inputProps.onKeyDown(event({key: 'ArrowDown'}));
expect(openSpy).toHaveBeenCalledTimes(1);
expect(openSpy).toHaveBeenLastCalledWith('first', 'manual');
expect(toggleSpy).toHaveBeenCalledTimes(0);
inputProps.onKeyDown(event({key: 'ArrowUp'}));
expect(openSpy).toHaveBeenCalledTimes(2);
expect(openSpy).toHaveBeenLastCalledWith('last', 'manual');
expect(toggleSpy).toHaveBeenCalledTimes(0);
buttonProps.onPress(event({pointerType: 'touch'}));
expect(openSpy).toHaveBeenCalledTimes(2);
expect(toggleSpy).toHaveBeenCalledTimes(1);
expect(toggleSpy).toHaveBeenLastCalledWith(null, 'manual');
buttonProps.onPressStart(event({pointerType: 'mouse'}));
expect(openSpy).toHaveBeenCalledTimes(2);
expect(toggleSpy).toHaveBeenCalledTimes(2);
expect(toggleSpy).toHaveBeenLastCalledWith(null, 'manual');
});
});
69 changes: 62 additions & 7 deletions packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ storiesOf('ComboBox', module)
</ComboBox>
)
)
.add(
'with mapped items (defaultItem and items undef)',
() => (
<ComboBoxWithMap defaultSelectedKey="two" />
)
)
.add(
'with sections',
() => (
Expand Down Expand Up @@ -496,19 +502,39 @@ function ListDataExample() {
let {contains} = useFilter({sensitivity: 'base'});
let list = useListData({
initialItems: items,
initialFilterText: 'Snake',
filter(item, text) {
return contains(item.name, text);
}
});

let [showAll, setShowAll] = useState(false);

return (
<ComboBox
label="ComboBox"
items={list.items}
inputValue={list.filterText}
onInputChange={list.setFilterText}>
{item => <Item>{item.name}</Item>}
</ComboBox>
<Flex gap="size-300" direction="column" >
<ComboBox
onOpenChange={(open, reason) => {
if (reason === 'manual' && open) {
setShowAll(true);
}
}}
label="ComboBox (show all on open)"
items={showAll ? items : list.items}
inputValue={list.filterText}
onInputChange={(value) => {
setShowAll(false);
list.setFilterText(value);
}}>
{item => <Item>{item.name}</Item>}
</ComboBox>
<ComboBox
label="ComboBox (default controlled items behavior)"
items={list.items}
inputValue={list.filterText}
onInputChange={list.setFilterText}>
{item => <Item>{item.name}</Item>}
</ComboBox>
</Flex>
);
}

Expand Down Expand Up @@ -893,3 +919,32 @@ function render(props = {}) {
</ComboBox>
);
}

function ComboBoxWithMap(props) {
let [items, setItems] = React.useState([
{name: 'The first item', id: 'one'},
{name: 'The second item', id: 'two'},
{name: 'The third item', id: 'three'}
]);

let onClick = () => {
setItems([
{name: 'The first item new text', id: 'one'},
{name: 'The second item new text', id: 'two'},
{name: 'The third item new text', id: 'three'}
]);
};

return (
<Flex direction="column">
<button onClick={onClick}>Press to change items</button>
<ComboBox label="Combobox" {...mergeProps(props, actions)}>
{items.map((item) => (
<Item key={item.id}>
{item.name}
</Item>
))}
</ComboBox>
</Flex>
);
}
Loading