Skip to content

Commit

Permalink
Merge pull request #57 from szhsin/feat/remove-blur
Browse files Browse the repository at this point in the history
feat: remove prop
  • Loading branch information
szhsin authored Oct 26, 2024
2 parents 8ece350 + 5605dea commit 77e20a1
Show file tree
Hide file tree
Showing 20 changed files with 89 additions and 120 deletions.
30 changes: 14 additions & 16 deletions dist/cjs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,8 @@ const scrollIntoView = element => element?.scrollIntoView({
block: 'nearest'
});
const autocompleteLite = ({
rovingText,
select,
selectOnBlur = rovingText,
rovingText = !select,
deselectOnClear = true,
deselectOnChange = true,
closeOnSelect = true
Expand Down Expand Up @@ -166,15 +165,17 @@ const autocompleteLite = ({
const inputValue = (_ref = tmpValue || value) != null ? _ref : getSelectedValue();
const focusItem = items[focusIndex];
const listId = getId(id, 'l');
const selectItemOrAction = (item, noAction) => {
const applyValue = newValue => {
if (!select) onChange(newValue);
const endIndex = newValue.length;
inputRef.current?.setSelectionRange(endIndex, endIndex);
};
const selectItemOrAction = item => {
if (isItemAction?.(item)) {
!noAction && onAction?.(item);
onAction?.(item);
return true;
}
const itemValue = getItemValue(item);
if (!select) onChange(itemValue);
const endIndex = itemValue.length;
inputRef.current?.setSelectionRange(endIndex, endIndex);
applyValue(getItemValue(item));
onSelectChange(item);
};
const resetState = shouldClose => {
Expand Down Expand Up @@ -236,7 +237,8 @@ const autocompleteLite = ({
if (!isItemDisabled?.(item)) {
resetState(selectItemOrAction(item));
}
}
},
onPointerMove: () => setFocusIndex(index)
}),
getInputProps: () => ({
type: 'text',
Expand All @@ -260,9 +262,7 @@ const autocompleteLite = ({
},
onBlur: () => {
if (inCapture()) return;
if (selectOnBlur && focusItem) {
selectItemOrAction(focusItem, true);
}
applyValue(inputValue);
resetState(true);
},
onKeyDown: e => {
Expand Down Expand Up @@ -490,14 +490,12 @@ const multiInput = () => ({

const multiSelect = props => mergeModules(autocomplete({
...props,
select: true,
selectOnBlur: false
select: true
}), inputFocus(), multiInput());

const multiSelectDropdown = props => mergeModules(autocompleteLite({
...props,
select: true,
selectOnBlur: false
select: true
}), dropdownToggle(props), multiInput());

const autoInline = ({
Expand Down
24 changes: 12 additions & 12 deletions dist/esm/features/atom/autocompleteLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ const scrollIntoView = element => element?.scrollIntoView({
block: 'nearest'
});
const autocompleteLite = ({
rovingText,
select,
selectOnBlur = rovingText,
rovingText = !select,
deselectOnClear = true,
deselectOnChange = true,
closeOnSelect = true
Expand Down Expand Up @@ -36,15 +35,17 @@ const autocompleteLite = ({
const inputValue = (_ref = tmpValue || value) != null ? _ref : getSelectedValue();
const focusItem = items[focusIndex];
const listId = getId(id, 'l');
const selectItemOrAction = (item, noAction) => {
const applyValue = newValue => {
if (!select) onChange(newValue);
const endIndex = newValue.length;
inputRef.current?.setSelectionRange(endIndex, endIndex);
};
const selectItemOrAction = item => {
if (isItemAction?.(item)) {
!noAction && onAction?.(item);
onAction?.(item);
return true;
}
const itemValue = getItemValue(item);
if (!select) onChange(itemValue);
const endIndex = itemValue.length;
inputRef.current?.setSelectionRange(endIndex, endIndex);
applyValue(getItemValue(item));
onSelectChange(item);
};
const resetState = shouldClose => {
Expand Down Expand Up @@ -106,7 +107,8 @@ const autocompleteLite = ({
if (!isItemDisabled?.(item)) {
resetState(selectItemOrAction(item));
}
}
},
onPointerMove: () => setFocusIndex(index)
}),
getInputProps: () => ({
type: 'text',
Expand All @@ -130,9 +132,7 @@ const autocompleteLite = ({
},
onBlur: () => {
if (inCapture()) return;
if (selectOnBlur && focusItem) {
selectItemOrAction(focusItem, true);
}
applyValue(inputValue);
resetState(true);
},
onKeyDown: e => {
Expand Down
3 changes: 1 addition & 2 deletions dist/esm/features/molecule/multiSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { multiInput } from '../atom/multiInput.js';

const multiSelect = props => mergeModules(autocomplete({
...props,
select: true,
selectOnBlur: false
select: true
}), inputFocus(), multiInput());

export { multiSelect };
3 changes: 1 addition & 2 deletions dist/esm/features/molecule/multiSelectDropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { multiInput } from '../atom/multiInput.js';

const multiSelectDropdown = props => mergeModules(autocompleteLite({
...props,
select: true,
selectOnBlur: false
select: true
}), dropdownToggle(props), multiInput());

export { multiSelectDropdown };
14 changes: 1 addition & 13 deletions examples/pages/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const filterGroupedItems = (value: string = '') =>

export default function Dropdown() {
const [rovingText, setRovingText] = useState(false);
const [selectOnBlur, setSelectOnBlur] = useState(true);
const [closeOnSelect, setCloseOnSelect] = useState(true);
const [value, setValue] = useState<string | undefined>('');
const [selectedItem, setSelectedItem] = useState<Item | undefined>();
Expand Down Expand Up @@ -57,7 +56,7 @@ export default function Dropdown() {
selected: selectedItem,
onSelectChange: setSelectedItem,
// feature: autocomplete({ constricted, rovingText }),
feature: dropdown({ rovingText, selectOnBlur, closeOnSelect }),
feature: dropdown({ rovingText, closeOnSelect }),
items: mergeGroupedItems({
groups: groupedItems,
getItemsInGroup: (group) => group.states
Expand All @@ -84,17 +83,6 @@ export default function Dropdown() {
</label>
</div>

<div>
<label>
selectOnBlur
<input
type="checkbox"
checked={selectOnBlur}
onChange={(e) => setSelectOnBlur(e.target.checked)}
/>
</label>
</div>

<div>
<label>
closeOnSelect
Expand Down
12 changes: 0 additions & 12 deletions examples/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export default function Home() {
const [selectedFeature, setSelectedFeature] = useState('supercomplete');
const [select, setselect] = useState(false);
const [rovingText, setRovingText] = useState(true);
const [selectOnBlur, setSelectOnBlur] = useState(true);
const [deselectOnClear, setDeselectOnClear] = useState(true);
const [deselectOnChange, setDeselectOnChange] = useState(true);
const [closeOnSelect, setCloseOnSelect] = useState(true);
Expand All @@ -42,7 +41,6 @@ export default function Home() {

const featureProps = {
select,
selectOnBlur,
deselectOnClear,
deselectOnChange,
closeOnSelect,
Expand Down Expand Up @@ -153,16 +151,6 @@ export default function Home() {
</label>
</div>
)}
<div>
<label>
selectOnBlur
<input
type="checkbox"
checked={selectOnBlur}
onChange={(e) => setSelectOnBlur(e.target.checked)}
/>
</label>
</div>
<div>
<label>
deselectOnClear
Expand Down
1 change: 0 additions & 1 deletion examples/pages/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export default function Home() {
value,
onChange: setValue,
feature: supercomplete({
selectOnBlur: false,
requestItem: (newValue) => ({
index: 0,
item: US_STATES.filter((item) =>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@szhsin/react-autocomplete",
"version": "0.9.10",
"version": "0.9.11",
"description": "",
"author": "Zheng Song",
"license": "MIT",
Expand Down
55 changes: 35 additions & 20 deletions src/__tests__/autocomplete.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,27 +159,30 @@ describe('autocomplete', () => {
expect(screen.queryByRole('button', { name: 'Clear' })).toBeNull();
expect(screen.getAllByRole('option')).toHaveLength(TOTAL_DATA_COUNT);

// Focus an item and blur input
await user.keyboard('{ArrowDown>3/}');
expect(screen.getByRole('option', { name: 'Arizona' })).toHaveStyle({
backgroundColor: 'red'
});
await user.click(screen.getByTestId('value'));
expect(screen.queryByRole('listbox')).toBeNull();
expect(screen.getByTestId('selected')).toBeEmptyDOMElement();

/* { rovingText: true } */
// Focus an item and blur input
rerender(<Autocomplete select rovingText />);
await user.type(combobox, 'c');
expect(combobox).toHaveValue('c');
await user.keyboard('{ArrowDown}');
expect(combobox).toHaveValue('California');
await user.keyboard('{ArrowUp}');
expect(combobox).toHaveValue('c');
await user.keyboard('{ArrowUp>2/}');
await user.keyboard('c{ArrowDown>2/}{Enter}');
expect(screen.getByTestId('selected')).toHaveTextContent(/^Colorado$/);
expect(combobox).toHaveValue('Colorado');
await user.keyboard('{ArrowDown>3}');
expect(combobox).toHaveValue('Alaska');
await user.keyboard('{ArrowUp>2}');
expect(combobox).toHaveValue('Colorado');
await user.keyboard('{ArrowUp>2/}');
expect(combobox).toHaveValue('Wisconsin');
await user.hover(screen.getByRole('option', { name: 'Texas' }));
expect(screen.getByRole('option', { name: 'Texas' })).toHaveStyle({
backgroundColor: 'red'
});
expect(combobox).toHaveValue('Wisconsin');
await user.keyboard('{ArrowDown}');
expect(combobox).toHaveValue('Utah');
expect(screen.getByRole('option', { name: 'Texas' })).toHaveStyle({
backgroundColor: 'Utah'
});
await user.click(screen.getByTestId('value'));
expect(combobox).toHaveValue('Colorado');
expect(screen.getByTestId('selected')).toHaveTextContent(/^Colorado$/);

/* { deselectOnClear: false } */
Expand Down Expand Up @@ -252,7 +255,7 @@ describe('autocomplete', () => {

test('search mode', async () => {
const user = userEvent.setup();
const { rerender } = render(<Autocomplete deselectOnChange={false} />);
const { rerender } = render(<Autocomplete deselectOnChange={false} rovingText={false} />);
const combobox = screen.getByRole('combobox');

// select an option with keyboard
Expand Down Expand Up @@ -284,7 +287,7 @@ describe('autocomplete', () => {
expect(screen.getByTestId('value')).toHaveTextContent(/^Colorad$/);
expect(screen.getByTestId('selected')).toHaveTextContent(/^Colorado$/);

/* { deselectOnChange: true } */
/* { deselectOnChange: true, rovingText: true } */
// Deleting a character should clear selection
rerender(<Autocomplete />);
await user.keyboard('{Backspace}');
Expand All @@ -299,12 +302,22 @@ describe('autocomplete', () => {
expect(combobox).toHaveValue('Colora');
expect(screen.getByTestId('value')).toHaveTextContent(/^Colora$/);
expect(screen.getByTestId('selected')).toBeEmptyDOMElement();

// Apply the temp value on input blur
await user.keyboard('{Backspace}{ArrowDown}');
expect(combobox).toHaveValue('Colorado');
expect(screen.getByTestId('value')).toHaveTextContent(/^Color$/);
await user.click(screen.getByRole('button', { name: 'Close' }));
expect(combobox).toHaveFocus();
expect(combobox).toHaveValue('Colorado');
expect(screen.getByTestId('value')).toHaveTextContent(/^Colorado$/);
expect(screen.getByTestId('selected')).toBeEmptyDOMElement();
});

test('disabled items', async () => {
const user = userEvent.setup();
const { rerender } = render(
<Autocomplete isItemDisabled={(item) => item.name === 'California'} />
<Autocomplete isItemDisabled={(item) => item.name === 'California'} rovingText={false} />
);
const combobox = screen.getByRole('combobox');

Expand All @@ -327,7 +340,9 @@ describe('autocomplete', () => {
});
await user.keyboard('{Escape}');

rerender(<Autocomplete isItemDisabled={(item) => item.name !== 'California'} />);
rerender(
<Autocomplete isItemDisabled={(item) => item.name !== 'California'} rovingText={false} />
);
await user.keyboard('{ArrowDown}');
expect(screen.getByRole('option', { name: 'California' })).toHaveStyle({
color: 'white',
Expand Down
Loading

0 comments on commit 77e20a1

Please sign in to comment.