Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@szhsin/react-autocomplete

Package Overview
Dependencies
Maintainers
1
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@szhsin/react-autocomplete - npm Package Compare versions

Comparing version 0.7.0 to 0.8.0

dist/esm/traversals/linearTraversal.js

136

dist/cjs/index.js

@@ -6,5 +6,5 @@ 'use strict';

const useAutocomplete = ({
items = [],
onChange = () => {},
feature: useFeature,
traversal: useTraversal,
getItemValue: _getItemValue

@@ -14,3 +14,3 @@ }) => {

const [open, setOpen] = react.useState(false);
const [focusIndex, setFocusIndex] = react.useState(-1);
const [focusItem, setFocusItem] = react.useState();
const [instance] = react.useState({

@@ -20,3 +20,3 @@ b: '',

});
const getItemValue = item => item == null ? null : _getItemValue ? _getItemValue(item) : typeof item === 'string' ? item : null;
const getItemValue = react.useCallback(item => item == null ? null : _getItemValue ? _getItemValue(item) : item.toString(), [_getItemValue]);
const setInputValue = react.useCallback(value => {

@@ -28,7 +28,14 @@ const input = inputRef.current;

setInputValue,
focusIndex,
setFocusIndex,
focusItem,
setFocusItem,
open,
setOpen
};
const contextual = {
_: instance,
getItemValue,
onChange,
inputRef,
...state
};
const {

@@ -39,12 +46,7 @@ getInputProps: _getInputProps,

} = useFeature({
_: instance,
items,
getItemValue,
onChange,
inputRef,
...state
...contextual,
...useTraversal(contextual)
});
const {
onBlur,
onKeyDown,
...featureInputProps

@@ -55,9 +57,2 @@ } = _getInputProps();

onBlur: e => !instance.a && (onBlur == null ? void 0 : onBlur(e)),
onKeyDown: e => {
const {
key
} = e;
if (items.length && (key === 'ArrowUp' || key === 'ArrowDown')) e.preventDefault();
onKeyDown == null || onKeyDown(e);
},
ref: inputRef

@@ -94,12 +89,11 @@ });

const autocomplete = ({
rovingText,
traverseInput
rovingText
} = {}) => ({
_: cxInstance,
items,
getItemValue,
traverse,
onChange,
setInputValue,
focusIndex,
setFocusIndex,
focusItem,
setFocusItem,
open,

@@ -122,18 +116,10 @@ setOpen,

setOpen(false);
setFocusIndex(-1);
setFocusItem();
}
};
const traverseItems = isUp => {
const baseIndex = (traverseInput != null ? traverseInput : rovingText) ? -1 : 0;
let nextIndex = focusIndex;
const itemLength = items.length;
if (isUp) {
if (--nextIndex < baseIndex) nextIndex = itemLength - 1;
} else {
if (++nextIndex >= itemLength) nextIndex = baseIndex;
}
setFocusIndex(nextIndex);
const traverseItems = isForward => {
const nextItem = traverse(isForward);
if (rovingText) {
var _getItemValue;
setInputValue((_getItemValue = getItemValue(items[nextIndex])) != null ? _getItemValue : cxInstance.b);
setInputValue((_getItemValue = getItemValue(nextItem)) != null ? _getItemValue : cxInstance.b);
const input = inputRef.current;

@@ -145,3 +131,3 @@ cxInstance.c = [input.selectionStart, input.selectionEnd];

onChange: e => {
setFocusIndex(-1);
setFocusItem();
setOpen(true);

@@ -158,3 +144,3 @@ updateValue(e.target.value, 'input');

if (cxInstance.b !== value && (selectionStart !== start || selectionEnd !== end)) {
setFocusIndex(-1);
setFocusItem();
updateValue(value, 'input');

@@ -164,17 +150,10 @@ }

onClick: () => setOpen(true),
onBlur: () => updateAndCloseList(getItemValue(items[focusIndex]), 'blur'),
onKeyDown: ({
key
}) => {
switch (key) {
onBlur: () => updateAndCloseList(getItemValue(focusItem), 'blur'),
onKeyDown: e => {
switch (e.key) {
case 'ArrowUp':
if (open) {
traverseItems(true);
} else {
setOpen(true);
}
break;
case 'ArrowDown':
e.preventDefault();
if (open) {
traverseItems(false);
traverseItems(e.key === 'ArrowDown');
} else {

@@ -185,3 +164,3 @@ setOpen(true);

case 'Enter':
updateAndCloseList(getItemValue(items[focusIndex]), 'submit');
updateAndCloseList(getItemValue(focusItem), 'submit');
break;

@@ -194,4 +173,6 @@ case 'Escape':

});
const getItemProps = option => ({
onClick: () => updateAndCloseList(getItemValue(items[option == null ? void 0 : option.index]), 'submit')
const getItemProps = ({
item
}) => ({
onClick: () => updateAndCloseList(getItemValue(item), 'submit')
});

@@ -208,3 +189,3 @@ return {

});
const useSupercomplete = cx => {
return cx => {
const {

@@ -217,4 +198,5 @@ getInputProps: _getInputProps,

inputRef,
getItemValue,
setInputValue,
setFocusIndex,
setFocusItem,
_: cxInstance

@@ -235,4 +217,3 @@ } = cx;

inlineComplete: react.useCallback(({
index = 0,
value
item
}) => {

@@ -242,3 +223,4 @@ if (instance.c) {

instance.c = 0;
setFocusIndex(index);
setFocusItem(item);
const value = getItemValue(item);
const start = cxInstance.b.length;

@@ -250,10 +232,44 @@ const end = value.length;

}
}, [cxInstance, instance, inputRef, setFocusIndex, setInputValue])
}, [cxInstance, instance, inputRef, getItemValue, setFocusItem, setInputValue])
};
};
return useSupercomplete;
};
const linearTraversal = ({
traverseInput,
isItemDisabled,
items = []
}) => ({
focusItem,
setFocusItem
}) => {
const [instance] = react.useState({
a: -1
});
return {
traverse: isForward => {
if (!focusItem) instance.a = -1;else if (focusItem !== items[instance.a]) instance.a = items.indexOf(focusItem);
const baseIndex = traverseInput ? -1 : 0;
let nextIndex = instance.a;
let nextItem;
const itemLength = items.length;
do {
if (isForward) {
if (++nextIndex >= itemLength) nextIndex = baseIndex;
} else {
if (--nextIndex < baseIndex) nextIndex = itemLength - 1;
}
nextItem = items[nextIndex];
if (!nextItem || !(isItemDisabled != null && isItemDisabled(nextItem))) break;
} while (nextIndex !== instance.a);
instance.a = nextIndex;
setFocusItem(nextItem);
return nextItem;
}
};
};
exports.autocomplete = autocomplete;
exports.linearTraversal = linearTraversal;
exports.supercomplete = supercomplete;
exports.useAutocomplete = useAutocomplete;
const autocomplete = ({
rovingText,
traverseInput
rovingText
} = {}) => ({
_: cxInstance,
items,
getItemValue,
traverse,
onChange,
setInputValue,
focusIndex,
setFocusIndex,
focusItem,
setFocusItem,
open,

@@ -29,18 +28,10 @@ setOpen,

setOpen(false);
setFocusIndex(-1);
setFocusItem();
}
};
const traverseItems = isUp => {
const baseIndex = (traverseInput != null ? traverseInput : rovingText) ? -1 : 0;
let nextIndex = focusIndex;
const itemLength = items.length;
if (isUp) {
if (--nextIndex < baseIndex) nextIndex = itemLength - 1;
} else {
if (++nextIndex >= itemLength) nextIndex = baseIndex;
}
setFocusIndex(nextIndex);
const traverseItems = isForward => {
const nextItem = traverse(isForward);
if (rovingText) {
var _getItemValue;
setInputValue((_getItemValue = getItemValue(items[nextIndex])) != null ? _getItemValue : cxInstance.b);
setInputValue((_getItemValue = getItemValue(nextItem)) != null ? _getItemValue : cxInstance.b);
const input = inputRef.current;

@@ -52,3 +43,3 @@ cxInstance.c = [input.selectionStart, input.selectionEnd];

onChange: e => {
setFocusIndex(-1);
setFocusItem();
setOpen(true);

@@ -65,3 +56,3 @@ updateValue(e.target.value, 'input');

if (cxInstance.b !== value && (selectionStart !== start || selectionEnd !== end)) {
setFocusIndex(-1);
setFocusItem();
updateValue(value, 'input');

@@ -71,17 +62,10 @@ }

onClick: () => setOpen(true),
onBlur: () => updateAndCloseList(getItemValue(items[focusIndex]), 'blur'),
onKeyDown: ({
key
}) => {
switch (key) {
onBlur: () => updateAndCloseList(getItemValue(focusItem), 'blur'),
onKeyDown: e => {
switch (e.key) {
case 'ArrowUp':
if (open) {
traverseItems(true);
} else {
setOpen(true);
}
break;
case 'ArrowDown':
e.preventDefault();
if (open) {
traverseItems(false);
traverseItems(e.key === 'ArrowDown');
} else {

@@ -92,3 +76,3 @@ setOpen(true);

case 'Enter':
updateAndCloseList(getItemValue(items[focusIndex]), 'submit');
updateAndCloseList(getItemValue(focusItem), 'submit');
break;

@@ -101,4 +85,6 @@ case 'Escape':

});
const getItemProps = option => ({
onClick: () => updateAndCloseList(getItemValue(items[option == null ? void 0 : option.index]), 'submit')
const getItemProps = ({
item
}) => ({
onClick: () => updateAndCloseList(getItemValue(item), 'submit')
});

@@ -105,0 +91,0 @@ return {

@@ -8,3 +8,3 @@ import { useState, useCallback } from 'react';

});
const useSupercomplete = cx => {
return cx => {
const {

@@ -17,4 +17,5 @@ getInputProps: _getInputProps,

inputRef,
getItemValue,
setInputValue,
setFocusIndex,
setFocusItem,
_: cxInstance

@@ -35,4 +36,3 @@ } = cx;

inlineComplete: useCallback(({
index = 0,
value
item
}) => {

@@ -42,3 +42,4 @@ if (instance.c) {

instance.c = 0;
setFocusIndex(index);
setFocusItem(item);
const value = getItemValue(item);
const start = cxInstance.b.length;

@@ -50,8 +51,7 @@ const end = value.length;

}
}, [cxInstance, instance, inputRef, setFocusIndex, setInputValue])
}, [cxInstance, instance, inputRef, getItemValue, setFocusItem, setInputValue])
};
};
return useSupercomplete;
};
export { supercomplete };
import { useRef, useState, useCallback } from 'react';
const useAutocomplete = ({
items = [],
onChange = () => {},
feature: useFeature,
traversal: useTraversal,
getItemValue: _getItemValue

@@ -11,3 +11,3 @@ }) => {

const [open, setOpen] = useState(false);
const [focusIndex, setFocusIndex] = useState(-1);
const [focusItem, setFocusItem] = useState();
const [instance] = useState({

@@ -17,3 +17,3 @@ b: '',

});
const getItemValue = item => item == null ? null : _getItemValue ? _getItemValue(item) : typeof item === 'string' ? item : null;
const getItemValue = useCallback(item => item == null ? null : _getItemValue ? _getItemValue(item) : item.toString(), [_getItemValue]);
const setInputValue = useCallback(value => {

@@ -25,7 +25,14 @@ const input = inputRef.current;

setInputValue,
focusIndex,
setFocusIndex,
focusItem,
setFocusItem,
open,
setOpen
};
const contextual = {
_: instance,
getItemValue,
onChange,
inputRef,
...state
};
const {

@@ -36,12 +43,7 @@ getInputProps: _getInputProps,

} = useFeature({
_: instance,
items,
getItemValue,
onChange,
inputRef,
...state
...contextual,
...useTraversal(contextual)
});
const {
onBlur,
onKeyDown,
...featureInputProps

@@ -52,9 +54,2 @@ } = _getInputProps();

onBlur: e => !instance.a && (onBlur == null ? void 0 : onBlur(e)),
onKeyDown: e => {
const {
key
} = e;
if (items.length && (key === 'ArrowUp' || key === 'ArrowDown')) e.preventDefault();
onKeyDown == null || onKeyDown(e);
},
ref: inputRef

@@ -61,0 +56,0 @@ });

export { useAutocomplete } from './hooks/useAutocomplete.js';
export { autocomplete } from './features/autocomplete.js';
export { supercomplete } from './features/supercomplete.js';
export { linearTraversal } from './traversals/linearTraversal.js';
{
"name": "@szhsin/react-autocomplete",
"version": "0.7.0",
"version": "0.8.0",
"description": "",

@@ -5,0 +5,0 @@ "author": "Zheng Song",

import type { HTMLAttributes, InputHTMLAttributes } from 'react';
export interface GetProps {
export interface GetProps<T> {
getInputProps: () => InputHTMLAttributes<HTMLInputElement>;
getItemProps: (option?: {
index?: number;
getItemProps: (option: {
item: T;
}) => HTMLAttributes<HTMLElement>;
}
export interface AutocompleteState {
export interface AutocompleteState<T> {
setInputValue: (value: string) => void;
focusIndex: number;
setFocusIndex: (value: number) => void;
focusItem: T | null | undefined;
setFocusItem: (item?: T | null | undefined) => void;
open: boolean;

@@ -16,7 +16,6 @@ setOpen: (value: boolean) => void;

export type ChangeType = 'submit' | 'input' | 'blur' | 'esc';
export interface ContextualProps<T> {
export interface ContextualProps {
onChange: (value: string, meta: {
type: ChangeType;
}) => void;
items: T[];
}

@@ -40,3 +39,3 @@ export interface Instance {

}
export interface Contextual<T> extends ContextualProps<T>, AutocompleteState {
export interface Contextual<T> extends ContextualProps, AutocompleteState<T> {
inputRef: React.RefObject<HTMLInputElement>;

@@ -49,9 +48,17 @@ getItemValue: (item: T | undefined | null) => string | undefined | null;

}
export type Feature<T, Actions = object> = (cx: Contextual<T>) => GetProps & Actions;
export interface TraversalProps<T> {
traverseInput?: boolean;
isItemDisabled?: (item: T) => boolean;
}
export type Traversal<T> = (cx: Contextual<T>) => {
traverse: (isForward: boolean) => T | null | undefined;
};
export type Feature<T, Actions = object> = (cx: Contextual<T> & ReturnType<Traversal<T>>) => GetProps<T> & Actions;
interface GetItemValue<T> {
getItemValue: (item: T) => string;
}
export type AutocompleteProps<T, FeatureActions = object> = Partial<ContextualProps<T>> & {
export type AutocompleteProps<T, FeatureActions = object> = Partial<ContextualProps> & {
feature: Feature<T, FeatureActions>;
traversal: Traversal<T>;
} & (T extends string ? Partial<GetItemValue<T>> : GetItemValue<T>);
export {};
import type { Feature } from '../common';
declare const autocomplete: <T>(props?: {
rovingText?: boolean;
traverseInput?: boolean;
declare const autocomplete: <T>({ rovingText }?: {
rovingText?: boolean | undefined;
}) => Feature<T>;
export { autocomplete };
import type { Feature } from '../common';
export interface Instance {
/**
* ### INTERNAL API ###
* Whether the last value change is "insertText"
*/
c?: boolean | 0 | 1;
}
declare const supercomplete: <T>() => Feature<T, {
inlineComplete: (props: {
index?: number;
value: string;
item: T;
}) => void;
}>;
export { supercomplete };
/// <reference types="react" />
import type { GetProps, AutocompleteProps } from '../common';
declare const useAutocomplete: <T, FeatureActions>({ items, onChange, feature: useFeature, getItemValue: _getItemValue }: AutocompleteProps<T, FeatureActions>) => {
declare const useAutocomplete: <T, FeatureActions>({ onChange, feature: useFeature, traversal: useTraversal, getItemValue: _getItemValue }: AutocompleteProps<T, FeatureActions>) => {
setInputValue: (value: string) => void;
focusIndex: number;
setFocusIndex: (value: number) => void;
focusItem: T | null | undefined;
setFocusItem: (item?: T | null | undefined) => void;
open: boolean;
setOpen: (value: boolean) => void;
getInputProps: () => import("react").InputHTMLAttributes<HTMLInputElement>;
getItemProps: (option?: {
index?: number | undefined;
} | undefined) => import("react").HTMLAttributes<HTMLElement>;
} & Omit<GetProps & FeatureActions, "getInputProps" | "getItemProps">;
getItemProps: (option: {
item: T;
}) => import("react").HTMLAttributes<HTMLElement>;
} & Omit<GetProps<T> & FeatureActions, "getInputProps" | "getItemProps">;
export { useAutocomplete };
export { useAutocomplete } from './hooks/useAutocomplete';
export { autocomplete } from './features/autocomplete';
export { supercomplete } from './features/supercomplete';
export { linearTraversal } from './traversals/linearTraversal';
export type { AutocompleteProps, AutocompleteState, Feature } from './common';
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc