@szhsin/react-autocomplete
Advanced tools
Comparing version 0.4.0 to 0.5.0
@@ -6,6 +6,11 @@ 'use strict'; | ||
const useAutocomplete = ({ | ||
onChange, | ||
onSetInputValue, | ||
onSetOpen, | ||
items = [] | ||
feature: { | ||
onInputChange, | ||
onInputClick, | ||
onBlur, | ||
onKeyDown, | ||
onItemClick | ||
} = {}, | ||
items = [], | ||
onChange = () => {} | ||
}) => { | ||
@@ -22,52 +27,120 @@ const inputRef = react.useRef(); | ||
}; | ||
const itemLength = items.length; | ||
const setInputValue = onSetInputValue || setInputValueBase; | ||
const setOpen = (value, type) => onSetOpen ? onSetOpen(value, { | ||
type, | ||
state | ||
}, setOpenBase) : setOpenBase(value); | ||
const traverseItems = itemIndex => { | ||
setfocusIndex(itemIndex); | ||
setInputValue(items[itemIndex], { | ||
type: 'nav', | ||
state | ||
}, setInputValueBase); | ||
const featureEvent = { | ||
state, | ||
props: { | ||
items, | ||
onChange | ||
} | ||
}; | ||
const updateValue = (value, type) => { | ||
if (value != null) { | ||
setInputValue(value, { | ||
type, | ||
state | ||
}, setInputValueBase); | ||
onChange == null || onChange(value, { | ||
type, | ||
state | ||
const getInputProps = () => ({ | ||
value: inputValue, | ||
ref: inputRef, | ||
onChange: e => onInputChange == null ? void 0 : onInputChange({ | ||
value: e.target.value, | ||
...featureEvent | ||
}), | ||
onClick: () => onInputClick == null ? void 0 : onInputClick(featureEvent), | ||
onBlur: () => !instance.a && (onBlur == null ? void 0 : onBlur(featureEvent)), | ||
onKeyDown: ({ | ||
key | ||
}) => onKeyDown == null ? void 0 : onKeyDown({ | ||
key, | ||
...featureEvent | ||
}) | ||
}); | ||
const getItemProps = ({ | ||
index = -1 | ||
} = {}) => ({ | ||
onMouseDown: () => instance.a = 1, | ||
onClick: () => { | ||
var _inputRef$current; | ||
onItemClick == null || onItemClick({ | ||
index, | ||
...featureEvent | ||
}); | ||
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus(); | ||
instance.a = 0; | ||
} | ||
}); | ||
const getProps = (elementType, option) => { | ||
switch (elementType) { | ||
case 'input': | ||
return getInputProps(); | ||
default: | ||
return getItemProps(option); | ||
} | ||
}; | ||
const updateAndCloseList = (value, type) => { | ||
return { | ||
getProps, | ||
state | ||
}; | ||
}; | ||
const autocomplete = () => { | ||
const updateAndCloseList = ({ | ||
props: { | ||
onChange | ||
}, | ||
state: { | ||
inputValue: [, setInputValue], | ||
focusIndex: [, setfocusIndex], | ||
isOpen: [isOpen, setOpen] | ||
} | ||
}, value) => { | ||
if (isOpen) { | ||
updateValue(value, type); | ||
setOpen(false, type); | ||
if (value != null) { | ||
setInputValue(value); | ||
onChange(value); | ||
} | ||
setOpen(false); | ||
setfocusIndex(-1); | ||
} | ||
}; | ||
const getInputProps = () => ({ | ||
value: inputValue, | ||
ref: inputRef, | ||
onChange: e => { | ||
updateValue(e.target.value, 'type'); | ||
setOpen(true, 'type'); | ||
return { | ||
onItemClick: ({ | ||
index, | ||
...event | ||
}) => updateAndCloseList(event, event.props.items[index]), | ||
onInputChange: ({ | ||
value, | ||
props: { | ||
onChange | ||
}, | ||
state: { | ||
inputValue: [, setInputValue], | ||
focusIndex: [, setfocusIndex], | ||
isOpen: [, setOpen] | ||
} | ||
}) => { | ||
setInputValue(value); | ||
setfocusIndex(-1); | ||
setOpen(true); | ||
onChange(value); | ||
}, | ||
onClick: () => setOpen(true, 'focus'), | ||
onBlur: () => { | ||
if (!instance.a) { | ||
updateAndCloseList(inputValue, 'blur'); | ||
onInputClick: ({ | ||
state: { | ||
isOpen: [, setOpen] | ||
} | ||
}, | ||
}) => setOpen(true), | ||
onBlur: event => updateAndCloseList(event, event.state.inputValue[0]), | ||
onKeyDown: ({ | ||
key | ||
key, | ||
...event | ||
}) => { | ||
const { | ||
props: { | ||
items | ||
}, | ||
state: { | ||
focusIndex: [focusIndex, setfocusIndex], | ||
inputValue: [inputValue, setInputValue], | ||
isOpen: [isOpen, setOpen] | ||
} | ||
} = event; | ||
const traverseItems = itemIndex => { | ||
setfocusIndex(itemIndex); | ||
setInputValue(items[itemIndex]); | ||
}; | ||
let nextIndex = focusIndex; | ||
const itemLength = items.length; | ||
switch (key) { | ||
@@ -79,3 +152,3 @@ case 'ArrowDown': | ||
} else { | ||
setOpen(true, 'nav'); | ||
setOpen(true); | ||
} | ||
@@ -88,39 +161,17 @@ break; | ||
} else { | ||
setOpen(true, 'nav'); | ||
setOpen(true); | ||
} | ||
break; | ||
case 'Enter': | ||
updateAndCloseList(items[focusIndex], 'submit'); | ||
updateAndCloseList(event, items[focusIndex]); | ||
break; | ||
case 'Escape': | ||
updateAndCloseList(inputValue, 'esc'); | ||
updateAndCloseList(event, inputValue); | ||
break; | ||
} | ||
} | ||
}); | ||
const getOptionProps = ({ | ||
index = -1 | ||
} = {}) => ({ | ||
onMouseDown: () => instance.a = 1, | ||
onClick: () => { | ||
var _inputRef$current; | ||
updateAndCloseList(items[index], 'submit'); | ||
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus(); | ||
instance.a = 0; | ||
} | ||
}); | ||
const getProps = (elementType, option) => { | ||
switch (elementType) { | ||
case 'input': | ||
return getInputProps(); | ||
default: | ||
return getOptionProps(option); | ||
} | ||
}; | ||
return { | ||
getProps, | ||
state | ||
}; | ||
}; | ||
exports.autocomplete = autocomplete; | ||
exports.useAutocomplete = useAutocomplete; |
import { useRef, useState } from 'react'; | ||
const useAutocomplete = ({ | ||
onChange, | ||
onSetInputValue, | ||
onSetOpen, | ||
items = [] | ||
feature: { | ||
onInputChange, | ||
onInputClick, | ||
onBlur, | ||
onKeyDown, | ||
onItemClick | ||
} = {}, | ||
items = [], | ||
onChange = () => {} | ||
}) => { | ||
@@ -19,79 +24,26 @@ const inputRef = useRef(); | ||
}; | ||
const itemLength = items.length; | ||
const setInputValue = onSetInputValue || setInputValueBase; | ||
const setOpen = (value, type) => onSetOpen ? onSetOpen(value, { | ||
type, | ||
state | ||
}, setOpenBase) : setOpenBase(value); | ||
const traverseItems = itemIndex => { | ||
setfocusIndex(itemIndex); | ||
setInputValue(items[itemIndex], { | ||
type: 'nav', | ||
state | ||
}, setInputValueBase); | ||
}; | ||
const updateValue = (value, type) => { | ||
if (value != null) { | ||
setInputValue(value, { | ||
type, | ||
state | ||
}, setInputValueBase); | ||
onChange == null || onChange(value, { | ||
type, | ||
state | ||
}); | ||
const featureEvent = { | ||
state, | ||
props: { | ||
items, | ||
onChange | ||
} | ||
}; | ||
const updateAndCloseList = (value, type) => { | ||
if (isOpen) { | ||
updateValue(value, type); | ||
setOpen(false, type); | ||
setfocusIndex(-1); | ||
} | ||
}; | ||
const getInputProps = () => ({ | ||
value: inputValue, | ||
ref: inputRef, | ||
onChange: e => { | ||
updateValue(e.target.value, 'type'); | ||
setOpen(true, 'type'); | ||
setfocusIndex(-1); | ||
}, | ||
onClick: () => setOpen(true, 'focus'), | ||
onBlur: () => { | ||
if (!instance.a) { | ||
updateAndCloseList(inputValue, 'blur'); | ||
} | ||
}, | ||
onChange: e => onInputChange == null ? void 0 : onInputChange({ | ||
value: e.target.value, | ||
...featureEvent | ||
}), | ||
onClick: () => onInputClick == null ? void 0 : onInputClick(featureEvent), | ||
onBlur: () => !instance.a && (onBlur == null ? void 0 : onBlur(featureEvent)), | ||
onKeyDown: ({ | ||
key | ||
}) => { | ||
let nextIndex = focusIndex; | ||
switch (key) { | ||
case 'ArrowDown': | ||
if (isOpen) { | ||
if (++nextIndex >= itemLength) nextIndex = 0; | ||
traverseItems(nextIndex); | ||
} else { | ||
setOpen(true, 'nav'); | ||
} | ||
break; | ||
case 'ArrowUp': | ||
if (isOpen) { | ||
if (--nextIndex < 0) nextIndex = itemLength - 1; | ||
traverseItems(nextIndex); | ||
} else { | ||
setOpen(true, 'nav'); | ||
} | ||
break; | ||
case 'Enter': | ||
updateAndCloseList(items[focusIndex], 'submit'); | ||
break; | ||
case 'Escape': | ||
updateAndCloseList(inputValue, 'esc'); | ||
break; | ||
} | ||
} | ||
}) => onKeyDown == null ? void 0 : onKeyDown({ | ||
key, | ||
...featureEvent | ||
}) | ||
}); | ||
const getOptionProps = ({ | ||
const getItemProps = ({ | ||
index = -1 | ||
@@ -102,3 +54,6 @@ } = {}) => ({ | ||
var _inputRef$current; | ||
updateAndCloseList(items[index], 'submit'); | ||
onItemClick == null || onItemClick({ | ||
index, | ||
...featureEvent | ||
}); | ||
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus(); | ||
@@ -113,3 +68,3 @@ instance.a = 0; | ||
default: | ||
return getOptionProps(option); | ||
return getItemProps(option); | ||
} | ||
@@ -116,0 +71,0 @@ }; |
export { useAutocomplete } from './hooks/useAutocomplete.js'; | ||
export { autocomplete } from './features/autocomplete.js'; |
{ | ||
"name": "@szhsin/react-autocomplete", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "author": "Zheng Song", |
import type { InputHTMLAttributes, HTMLAttributes } from 'react'; | ||
import { AutocompleteProps, AutocompleteState } from '../common'; | ||
interface GetProps { | ||
input: [never, InputHTMLAttributes<HTMLInputElement>]; | ||
option: [{ | ||
item: [{ | ||
index?: number; | ||
}, HTMLAttributes<HTMLElement>]; | ||
} | ||
type ValueEventType = 'type' | 'submit' | 'esc' | 'blur' | 'nav' | 'focus'; | ||
export type AutocompleteState = ReturnType<typeof useAutocomplete>['state']; | ||
export interface AutocompleteProps { | ||
onChange?: (value: string, meta: { | ||
type: ValueEventType; | ||
state: AutocompleteState; | ||
}) => void; | ||
onSetInputValue?: (value: string, meta: { | ||
type: ValueEventType; | ||
state: AutocompleteState; | ||
}, base: AutocompleteState['inputValue'][1]) => void; | ||
onSetOpen?: (value: boolean, meta: { | ||
type: ValueEventType; | ||
state: AutocompleteState; | ||
}, base: AutocompleteState['isOpen'][1]) => void; | ||
items?: string[]; | ||
} | ||
declare const useAutocomplete: ({ onChange, onSetInputValue, onSetOpen, items }: AutocompleteProps) => { | ||
declare const useAutocomplete: ({ feature: { onInputChange, onInputClick, onBlur, onKeyDown, onItemClick }, items, onChange }: AutocompleteProps) => { | ||
getProps: <T extends keyof GetProps>(elementType: T, option?: GetProps[T][0] | undefined) => GetProps[T][1]; | ||
state: { | ||
readonly inputValue: readonly [string, import("react").Dispatch<import("react").SetStateAction<string>>]; | ||
readonly focusIndex: readonly [number, import("react").Dispatch<import("react").SetStateAction<number>>]; | ||
readonly isOpen: readonly [boolean, import("react").Dispatch<import("react").SetStateAction<boolean>>]; | ||
}; | ||
state: AutocompleteState; | ||
}; | ||
export { useAutocomplete }; |
export { useAutocomplete } from './hooks/useAutocomplete'; | ||
export type { AutocompleteProps, AutocompleteState } from './hooks/useAutocomplete'; | ||
export { autocomplete } from './features/autocomplete'; | ||
export type { AutocompleteProps, AutocompleteState } from './common'; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13287
10
390
1