Skip to content

Commit

Permalink
Merge pull request #42 from szhsin/feat/auto-focus
Browse files Browse the repository at this point in the history
feat: auto focus
  • Loading branch information
szhsin authored Jul 5, 2024
2 parents f5ef6f3 + 62dd957 commit 631a966
Show file tree
Hide file tree
Showing 22 changed files with 174 additions and 76 deletions.
29 changes: 23 additions & 6 deletions dist/cjs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,22 @@ const autocompleteLite = ({
};
};

const autoFocus = ({
getFocusItem
}) => ({
setFocusItem
}) => ({
getInputProps: () => ({
onChange: async e => {
const nextValue = e.target.value;
if (nextValue) {
const item = await getFocusItem(nextValue);
item && setFocusItem(item);
}
}
})
});

const mergeObjects = (obj1, obj2) => {
const merged = {
...obj1
Expand Down Expand Up @@ -444,8 +460,8 @@ const multiSelectDropdown = (props = {}) => mergeModules(autocompleteLite({
selectOnBlur: false
}), dropdownToggle(props), multiInput());

const inline = ({
getInlineItem
const autoInline = ({
getFocusItem
}) => ({
getItemValue,
setTmpValue,
Expand All @@ -460,7 +476,7 @@ const inline = ({
return;
}
const nextValue = target.value;
const item = await getInlineItem(nextValue);
const item = await getFocusItem(nextValue);
if (!item) return;
setFocusItem(item);
const itemValue = getItemValue(item);
Expand All @@ -473,13 +489,13 @@ const inline = ({
});

const supercomplete = ({
getInlineItem,
getFocusItem,
...rest
}) => mergeModules(autocomplete({
...rest,
rovingText: true
}), inline({
getInlineItem
}), autoInline({
getFocusItem
}));

const linearTraversal = ({
Expand Down Expand Up @@ -537,6 +553,7 @@ const groupedTraversal = ({
});
};

exports.autoFocus = autoFocus;
exports.autocomplete = autocomplete;
exports.autocompleteLite = autocompleteLite;
exports.dropdown = dropdown;
Expand Down
17 changes: 17 additions & 0 deletions dist/esm/features/atom/autoFocus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const autoFocus = ({
getFocusItem
}) => ({
setFocusItem
}) => ({
getInputProps: () => ({
onChange: async e => {
const nextValue = e.target.value;
if (nextValue) {
const item = await getFocusItem(nextValue);
item && setFocusItem(item);
}
}
})
});

export { autoFocus };
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const inline = ({
getInlineItem
const autoInline = ({
getFocusItem
}) => ({
getItemValue,
setTmpValue,
Expand All @@ -14,7 +14,7 @@ const inline = ({
return;
}
const nextValue = target.value;
const item = await getInlineItem(nextValue);
const item = await getFocusItem(nextValue);
if (!item) return;
setFocusItem(item);
const itemValue = getItemValue(item);
Expand All @@ -26,4 +26,4 @@ const inline = ({
})
});

export { inline };
export { autoInline };
8 changes: 4 additions & 4 deletions dist/esm/features/molecule/supercomplete.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { mergeModules } from '../../utils/mergeModules.js';
import { autocomplete } from './autocomplete.js';
import { inline } from '../atom/inline.js';
import { autoInline } from '../atom/autoInline.js';

const supercomplete = ({
getInlineItem,
getFocusItem,
...rest
}) => mergeModules(autocomplete({
...rest,
rovingText: true
}), inline({
getInlineItem
}), autoInline({
getFocusItem
}));

export { supercomplete };
1 change: 1 addition & 0 deletions dist/esm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { useCombobox } from './hooks/useCombobox.js';
export { useMultiSelect } from './hooks/useMultiSelect.js';
export { useAutoHeight } from './hooks/useAutoHeight.js';
export { autocompleteLite } from './features/atom/autocompleteLite.js';
export { autoFocus } from './features/atom/autoFocus.js';
export { autocomplete } from './features/molecule/autocomplete.js';
export { dropdown } from './features/molecule/dropdown.js';
export { multiSelect } from './features/molecule/multiSelect.js';
Expand Down
19 changes: 19 additions & 0 deletions examples/features/autocompleteFocus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {
mergeModules,
MergedFeature,
FeatureProps,
AutocompleteFeature,
AutoFocusFeature,
autocomplete,
autoFocus
} from '@szhsin/react-autocomplete';

type AutocompleteFocusFeature<T> = MergedFeature<
T,
[AutocompleteFeature<T>, AutoFocusFeature<T>]
>;

const autocompleteFocus = <T>(props: FeatureProps<T>): AutocompleteFocusFeature<T> =>
mergeModules(autocomplete<T>(props), autoFocus<T>(props));

export { autocompleteFocus };
2 changes: 1 addition & 1 deletion examples/package-lock.json

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

83 changes: 45 additions & 38 deletions examples/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@szhsin/react-autocomplete';
import styles from '@/styles/Home.module.css';
import { LIST_GROUP_PLAIN, KEYED_GROUP_PLAIN, LIST_GROUP, KEYED_GROUP } from '../data';
import { autocompleteFocus } from '../features/autocompleteFocus';

type Item = { name: string; abbr: string };
const getItemValue = (item: Item) => item.name;
Expand All @@ -22,7 +23,7 @@ const getGroupedItems = (value: string) =>
})).filter((group) => !!group.states.length);

export default function Home() {
const [isSupercomplete, setSupercomplete] = useState(true);
const [selectedFeature, setSelectedFeature] = useState('supercomplete');
const [select, setselect] = useState(false);
const [rovingText, setRovingText] = useState(true);
const [selectOnBlur, setSelectOnBlur] = useState(true);
Expand All @@ -40,6 +41,15 @@ export default function Home() {
// const [items, setItems] = useState(US_STATES);
// const feature = supercomplete<{ name: string; abbr: string }>();

const featureProps = {
select,
selectOnBlur,
deselectOnClear,
deselectOnChange,
closeOnSelect,
rovingText
};

const groupedItems = getGroupedItems(value || '');

const {
Expand All @@ -60,7 +70,7 @@ export default function Home() {
isItemDisabled,
value,
onChange: (value) => {
// console.log('onChange', value);
console.log('onChange', value);
setValue(value);
},
selected: selectedItem,
Expand All @@ -69,31 +79,28 @@ export default function Home() {
setSelectedItem(item);
},

feature: isSupercomplete
? supercomplete({
select,
selectOnBlur,
deselectOnClear,
deselectOnChange,
closeOnSelect,
getInlineItem: (newValue) =>
getGroupedItems(newValue)[0]?.states.find((item) => !isItemDisabled(item))
// getInlineItem: (newValue) =>
// new Promise((res) =>
// setTimeout(
// () => res(getGroupedItems(newValue)[0]?.states.find((item) => !isItemDisabled(item))),
// 1000
// )
// )
})
: autocomplete({
select,
selectOnBlur,
deselectOnClear,
deselectOnChange,
rovingText,
closeOnSelect
}),
feature:
selectedFeature === 'supercomplete'
? supercomplete({
...featureProps,
getFocusItem: (newValue) =>
getGroupedItems(newValue)[0]?.states.find((item) => !isItemDisabled(item))
// getInlineItem: (newValue) =>
// new Promise((res) =>
// setTimeout(
// () => res(getGroupedItems(newValue)[0]?.states.find((item) => !isItemDisabled(item))),
// 1000
// )
// )
})
: selectedFeature === 'autocompleteFocus'
? autocompleteFocus({
...featureProps,
getFocusItem: (newValue) =>
getGroupedItems(newValue)[0]?.states.find((item) => !isItemDisabled(item))
})
: autocomplete(featureProps),

traversal: groupedTraversal({
traverseInput: true,
groupedItems,
Expand All @@ -108,16 +115,16 @@ export default function Home() {
<div>value: {value}</div>
<div>Selected item: {selectedItem?.name}</div>
<div>Focus item: {focusItem?.name}</div>
<div>
<label>
Supercomplete
<input
type="checkbox"
checked={isSupercomplete}
onChange={(e) => setSupercomplete(e.target.checked)}
/>
</label>
</div>

<select
value={selectedFeature} // ...force the select's value to match the state variable...
onChange={(e) => setSelectedFeature(e.target.value)} // ... and update the state variable on any change!
>
<option value="supercomplete">supercomplete</option>
<option value="autocomplete">autocomplete</option>
<option value="autocompleteFocus">autocompleteFocus</option>
</select>

<div>
<label>
select
Expand All @@ -128,7 +135,7 @@ export default function Home() {
/>
</label>
</div>
{!isSupercomplete && (
{selectedFeature !== 'supercomplete' && (
<div>
<label>
rovingText
Expand Down
5 changes: 4 additions & 1 deletion examples/pages/multiSelectAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export default function Home() {
const [closeOnSelect, setCloseOnSelect] = useState(false);

const [value, setValue] = useState<string | undefined>();
const [selectedItems, setSelectedItems] = useState<Item[]>([]);
const [selectedItems, setSelectedItems] = useState<Item[]>([
{ name: 'Alaska', abbr: 'AK' },
{ name: 'Connecticut', abbr: 'CT' }
]);

const [anotherValue, setAnotherValue] = useState('');
const anotherRef = useRef(null);
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.1",
"version": "0.9.2",
"description": "",
"author": "Zheng Song",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export interface FeatureProps<T> {
deselectOnClear?: boolean;
deselectOnChange?: boolean;
closeOnSelect?: boolean;
getInlineItem: (
getFocusItem: (
value: string
) => T | undefined | null | void | Promise<T | undefined | null | void>;
}
Expand Down
19 changes: 19 additions & 0 deletions src/features/atom/autoFocus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Feature, GetPropsFunctions, FeatureProps } from '../../common';

type AutoFocusFeature<T> = Feature<T, Pick<GetPropsFunctions<T>, 'getInputProps'>>;

const autoFocus =
<T>({ getFocusItem }: Pick<FeatureProps<T>, 'getFocusItem'>): AutoFocusFeature<T> =>
({ setFocusItem }) => ({
getInputProps: () => ({
onChange: async (e) => {
const nextValue = e.target.value;
if (nextValue) {
const item = await getFocusItem(nextValue);
item && setFocusItem(item);
}
}
})
});

export { type AutoFocusFeature, autoFocus };
10 changes: 5 additions & 5 deletions src/features/atom/inline.ts → src/features/atom/autoInline.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { Feature, GetPropsFunctions, FeatureProps } from '../../common';

type InlineFeature<T> = Feature<T, Pick<GetPropsFunctions<T>, 'getInputProps'>>;
type AutoInlineFeature<T> = Feature<T, Pick<GetPropsFunctions<T>, 'getInputProps'>>;

const inline =
<T>({ getInlineItem }: Pick<FeatureProps<T>, 'getInlineItem'>): InlineFeature<T> =>
const autoInline =
<T>({ getFocusItem }: Pick<FeatureProps<T>, 'getFocusItem'>): AutoInlineFeature<T> =>
({ getItemValue, setTmpValue, setFocusItem }) => ({
getInputProps: () => ({
onChange: async ({ target, nativeEvent }) => {
Expand All @@ -12,7 +12,7 @@ const inline =
}

const nextValue = target.value;
const item = await getInlineItem(nextValue);
const item = await getFocusItem(nextValue);
if (!item) return;

setFocusItem(item);
Expand All @@ -25,4 +25,4 @@ const inline =
})
});

export { type InlineFeature, inline };
export { type AutoInlineFeature, autoInline };
Loading

0 comments on commit 631a966

Please sign in to comment.