Socket
Socket
Sign inDemoInstall

@szhsin/react-autocomplete

Package Overview
Dependencies
5
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.8.6 to 0.8.7

dist/esm/features/dropdown.js

237

dist/cjs/index.js

@@ -7,19 +7,2 @@ 'use strict';

const mergeEvents = (events1, events2) => {
const result = {
...events1
};
Object.keys(events2).forEach(key => {
const e2 = events2[key];
if (e2) {
const e1 = events1[key];
result[key] = e1 ? e => {
e1(e);
e2(e);
} : e2;
}
});
return result;
};
const useAutocomplete = ({

@@ -37,4 +20,3 @@ onChange = () => {},

const mutable = useMutableState({
b: '',
c: []
b: ''
});

@@ -63,36 +45,9 @@ const getItemValue = react.useCallback(item => item == null ? '' : _getItemValue ? _getItemValue(item) : item.toString(), [_getItemValue]);

};
const {
getInputProps: _getInputProps,
getListProps: _getListProps,
...restFeature
} = useFeature({
const featureYield = useFeature({
...contextual,
...useTraversal(contextual)
});
const getInputProps = () => {
const {
onBlur,
...rest
} = _getInputProps();
return {
...rest,
onBlur: e => !mutable.a && (onBlur == null ? void 0 : onBlur(e)),
ref: inputRef
};
};
const getListProps = () => mergeEvents(_getListProps(), {
onMouseDown: () => {
mutable.a = 1;
},
onClick: () => {
var _inputRef$current;
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
mutable.a = 0;
}
});
return {
getInputProps,
getListProps,
...state,
...restFeature
...featureYield
};

@@ -155,2 +110,3 @@ };

}) => {
const mutable = useMutableState({});
const updateValue = (value, moveCaretToEnd = true) => {

@@ -174,11 +130,14 @@ setInputValue(value);

};
const traverseItems = isForward => {
const nextItem = traverse(isForward);
if (rovingText) {
setInputValue(getItemValue(nextItem) || cxMutable.b);
const input = inputRef.current;
cxMutable.c = [input.selectionStart, input.selectionEnd];
const getListProps = () => ({
onMouseDown: () => {
mutable.a = 1;
},
onClick: () => {
var _inputRef$current;
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
mutable.a = 0;
}
};
});
const getInputProps = () => ({
ref: inputRef,
onChange: e => {

@@ -189,17 +148,5 @@ setFocusItem();

},
onSelect: e => {
const {
value,
selectionStart,
selectionEnd
} = e.target;
const [start, end] = cxMutable.c;
if (cxMutable.b != value && (selectionStart != start || selectionEnd != end)) {
setFocusItem();
updateValue(value, false);
}
},
onClick: () => setOpen(true),
onBlur: () => {
if (!open) return;
if (mutable.a || !open) return;
if (focusItem) {

@@ -220,3 +167,4 @@ updateAll(focusItem);

if (open) {
traverseItems(e.key != 'ArrowUp');
const nextItem = traverse(e.key != 'ArrowUp');
if (rovingText) setInputValue(getItemValue(nextItem) || cxMutable.b);
} else {

@@ -260,50 +208,122 @@ setOpen(true);

getItemProps,
getListProps: () => ({})
getListProps
};
};
const supercomplete = props => {
const useAutocomplete = autocomplete({
...props,
rovingText: true
const mergeObjects = (obj1, obj2) => {
const merged = {
...obj1
};
Object.entries(obj2).forEach(([key, prop2]) => {
if (typeof prop2 === 'function') {
const prop1 = obj1[key];
merged[key] = prop1 ? (...args) => {
const result1 = prop1(...args);
const result2 = prop2(...args);
if (typeof result1 === 'object') {
return mergeObjects(result1, result2);
}
} : prop2;
} else {
merged[key] = prop2;
}
});
return cx => {
const {
getInputProps: _getInputProps,
...rest
} = useAutocomplete(cx);
const mutable = useMutableState({});
const {
inputRef,
getItemValue,
setInputValue,
setFocusItem,
$: cxMutable
} = cx;
return {
...rest,
getInputProps: () => mergeEvents({
onChange: e => {
mutable.c = e.nativeEvent.inputType === 'insertText';
return merged;
};
const mergeFeatures = (...features) => cx => features.reduce((accu, curr) => mergeObjects(accu, curr(cx)), {});
const inline = () => ({
inputRef,
getItemValue,
setInputValue,
setFocusItem,
$: cxMutable
}) => {
const mutable = useMutableState({});
return {
getInputProps: () => ({
onChange: e => {
mutable.c = e.nativeEvent.inputType === 'insertText';
}
}),
inlineComplete: react.useCallback(({
item
}) => {
if (mutable.c) {
var _inputRef$current;
mutable.c = 0;
setFocusItem(item);
const value = getItemValue(item);
const start = cxMutable.b.length;
const end = value.length;
setInputValue(cxMutable.b + value.slice(start));
(_inputRef$current = inputRef.current) == null || _inputRef$current.setSelectionRange(start, end);
}
}, [cxMutable, mutable, inputRef, getItemValue, setFocusItem, setInputValue])
};
};
const supercomplete = props => mergeFeatures(inline(), autocomplete({
...props,
rovingText: true
}));
const toggle = () => ({
inputRef,
open,
setOpen,
focusItem
}) => {
const mutable = useMutableState({});
const toggleRef = react.useRef(null);
react.useEffect(() => {
var _inputRef$current;
if (open) (_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
}, [open, inputRef]);
return {
getToggleProps: () => ({
ref: toggleRef,
onMouseDown: () => {
mutable.a = open;
},
onClick: () => {
if (mutable.a) {
mutable.a = 0;
} else {
setOpen(true);
}
}, _getInputProps()),
inlineComplete: react.useCallback(({
item
}) => {
if (mutable.c) {
var _inputRef$current;
mutable.c = 0;
setFocusItem(item);
const value = getItemValue(item);
const start = cxMutable.b.length;
const end = value.length;
setInputValue(cxMutable.b + value.slice(start));
cxMutable.c = [start, end];
(_inputRef$current = inputRef.current) == null || _inputRef$current.setSelectionRange(start, end);
},
onKeyDown: e => {
const {
key
} = e;
if (key === 'ArrowUp' || key === 'ArrowDown') {
e.preventDefault();
setOpen(true);
}
}, [cxMutable, mutable, inputRef, getItemValue, setFocusItem, setInputValue])
};
}
}),
getInputProps: () => ({
onKeyDown: e => {
var _toggleRef$current;
const {
key
} = e;
if (key === 'Escape') (_toggleRef$current = toggleRef.current) == null || _toggleRef$current.focus();
if (key === 'Enter' && focusItem) {
var _toggleRef$current2;
e.preventDefault();
(_toggleRef$current2 = toggleRef.current) == null || _toggleRef$current2.focus();
}
}
})
};
};
const dropdown = props => mergeFeatures(autocomplete({
...props,
constricted: true
}), toggle());
const linearTraversal = ({

@@ -364,2 +384,3 @@ traverseInput,

exports.autocomplete = autocomplete;
exports.dropdown = dropdown;
exports.groupedTraversal = groupedTraversal;

@@ -366,0 +387,0 @@ exports.linearTraversal = linearTraversal;

@@ -0,1 +1,3 @@

import { useMutableState } from '../hooks/useMutableState.js';
const scrollIntoView = element => element == null ? void 0 : element.scrollIntoView({

@@ -22,2 +24,3 @@ block: 'nearest'

}) => {
const mutable = useMutableState({});
const updateValue = (value, moveCaretToEnd = true) => {

@@ -41,11 +44,14 @@ setInputValue(value);

};
const traverseItems = isForward => {
const nextItem = traverse(isForward);
if (rovingText) {
setInputValue(getItemValue(nextItem) || cxMutable.b);
const input = inputRef.current;
cxMutable.c = [input.selectionStart, input.selectionEnd];
const getListProps = () => ({
onMouseDown: () => {
mutable.a = 1;
},
onClick: () => {
var _inputRef$current;
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
mutable.a = 0;
}
};
});
const getInputProps = () => ({
ref: inputRef,
onChange: e => {

@@ -56,17 +62,5 @@ setFocusItem();

},
onSelect: e => {
const {
value,
selectionStart,
selectionEnd
} = e.target;
const [start, end] = cxMutable.c;
if (cxMutable.b != value && (selectionStart != start || selectionEnd != end)) {
setFocusItem();
updateValue(value, false);
}
},
onClick: () => setOpen(true),
onBlur: () => {
if (!open) return;
if (mutable.a || !open) return;
if (focusItem) {

@@ -87,3 +81,4 @@ updateAll(focusItem);

if (open) {
traverseItems(e.key != 'ArrowUp');
const nextItem = traverse(e.key != 'ArrowUp');
if (rovingText) setInputValue(getItemValue(nextItem) || cxMutable.b);
} else {

@@ -127,3 +122,3 @@ setOpen(true);

getItemProps,
getListProps: () => ({})
getListProps
};

@@ -130,0 +125,0 @@ };

@@ -1,50 +0,10 @@

import { useCallback } from 'react';
import { mergeEvents } from '../utils/mergeEvents.js';
import { useMutableState } from '../hooks/useMutableState.js';
import { mergeFeatures } from '../utils/mergeFeatures.js';
import { autocomplete } from './autocomplete.js';
import { inline } from './inline.js';
const supercomplete = props => {
const useAutocomplete = autocomplete({
...props,
rovingText: true
});
return cx => {
const {
getInputProps: _getInputProps,
...rest
} = useAutocomplete(cx);
const mutable = useMutableState({});
const {
inputRef,
getItemValue,
setInputValue,
setFocusItem,
$: cxMutable
} = cx;
return {
...rest,
getInputProps: () => mergeEvents({
onChange: e => {
mutable.c = e.nativeEvent.inputType === 'insertText';
}
}, _getInputProps()),
inlineComplete: useCallback(({
item
}) => {
if (mutable.c) {
var _inputRef$current;
mutable.c = 0;
setFocusItem(item);
const value = getItemValue(item);
const start = cxMutable.b.length;
const end = value.length;
setInputValue(cxMutable.b + value.slice(start));
cxMutable.c = [start, end];
(_inputRef$current = inputRef.current) == null || _inputRef$current.setSelectionRange(start, end);
}
}, [cxMutable, mutable, inputRef, getItemValue, setFocusItem, setInputValue])
};
};
};
const supercomplete = props => mergeFeatures(inline(), autocomplete({
...props,
rovingText: true
}));
export { supercomplete };
import { useRef, useState, useCallback } from 'react';
import { useMutableState } from './useMutableState.js';
import { mergeEvents } from '../utils/mergeEvents.js';

@@ -17,4 +16,3 @@ const useAutocomplete = ({

const mutable = useMutableState({
b: '',
c: []
b: ''
});

@@ -43,36 +41,9 @@ const getItemValue = useCallback(item => item == null ? '' : _getItemValue ? _getItemValue(item) : item.toString(), [_getItemValue]);

};
const {
getInputProps: _getInputProps,
getListProps: _getListProps,
...restFeature
} = useFeature({
const featureYield = useFeature({
...contextual,
...useTraversal(contextual)
});
const getInputProps = () => {
const {
onBlur,
...rest
} = _getInputProps();
return {
...rest,
onBlur: e => !mutable.a && (onBlur == null ? void 0 : onBlur(e)),
ref: inputRef
};
};
const getListProps = () => mergeEvents(_getListProps(), {
onMouseDown: () => {
mutable.a = 1;
},
onClick: () => {
var _inputRef$current;
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
mutable.a = 0;
}
});
return {
getInputProps,
getListProps,
...state,
...restFeature
...featureYield
};

@@ -79,0 +50,0 @@ };

@@ -5,3 +5,4 @@ export { useAutocomplete } from './hooks/useAutocomplete.js';

export { supercomplete } from './features/supercomplete.js';
export { dropdown } from './features/dropdown.js';
export { linearTraversal } from './traversals/linearTraversal.js';
export { groupedTraversal } from './traversals/groupedTraversal.js';
{
"name": "@szhsin/react-autocomplete",
"version": "0.8.6",
"version": "0.8.7",
"description": "",

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

@@ -1,2 +0,2 @@

import type { HTMLAttributes, InputHTMLAttributes } from 'react';
import type { HTMLAttributes, InputHTMLAttributes, ButtonHTMLAttributes } from 'react';
export type PropsWithObjectRef<T> = T extends HTMLAttributes<infer E> ? T & {

@@ -6,3 +6,4 @@ ref: React.RefObject<E>;

export interface GetProps<T> {
getInputProps: () => InputHTMLAttributes<HTMLInputElement>;
getInputProps: () => PropsWithObjectRef<InputHTMLAttributes<HTMLInputElement>>;
getToggleProps: () => PropsWithObjectRef<ButtonHTMLAttributes<HTMLButtonElement>>;
getListProps: () => HTMLAttributes<HTMLElement>;

@@ -29,15 +30,5 @@ getItemProps: (option: {

* ### INTERNAL API ###
* Whether to bypass onblur event on input
*/
a?: number;
/**
* ### INTERNAL API ###
* The most recent value
*/
b: string;
/**
* ### INTERNAL API ###
* The last recorded selection position
*/
c: [number | null, number | null] | [];
}

@@ -58,10 +49,12 @@ export interface Contextual<T> extends ContextualProps<T>, AutocompleteState<T> {

};
export type Feature<T, Actions = object> = (cx: Contextual<T> & ReturnType<Traversal<T>>) => GetProps<T> & Actions;
export type Feature<T, Yield extends object> = (cx: Contextual<T> & ReturnType<Traversal<T>>) => Yield;
export type MergedFeatureYield<T, Features> = Features extends readonly [Feature<T, infer S>] ? S : Features extends readonly [Feature<T, infer F>, ...infer R] ? F & MergedFeatureYield<T, R> : never;
export type MergedFeature<T, Features> = Feature<T, MergedFeatureYield<T, Features>>;
interface GetItemValue<T> {
getItemValue: (item: T) => string;
}
export type AutocompleteProps<T, FeatureActions = object> = Partial<ContextualProps<T>> & {
feature: Feature<T, FeatureActions>;
export type AutocompleteProps<T, FeatureYield extends object = object> = Partial<ContextualProps<T>> & {
feature: Feature<T, FeatureYield>;
traversal: Traversal<T>;
} & (T extends string ? Partial<GetItemValue<T>> : GetItemValue<T>);
export {};

@@ -1,6 +0,7 @@

import type { Feature } from '../common';
import type { Feature, GetProps } from '../common';
type AutocompleteFeature<T> = Feature<T, Pick<GetProps<T>, 'getInputProps' | 'getListProps' | 'getItemProps'>>;
declare const autocomplete: <T>({ rovingText, constricted }?: {
rovingText?: boolean | undefined;
constricted?: boolean | undefined;
}) => Feature<T>;
export { autocomplete };
}) => AutocompleteFeature<T>;
export { type AutocompleteFeature, autocomplete };

@@ -1,9 +0,8 @@

import type { Feature } from '../common';
import type { MergedFeature } from '../common';
import { type AutocompleteFeature } from './autocomplete';
import { type InlineFeature } from './inline';
type SupercompleteFeature<T> = MergedFeature<T, [InlineFeature<T>, AutocompleteFeature<T>]>;
declare const supercomplete: <T>(props?: {
constricted?: boolean;
}) => Feature<T, {
inlineComplete: (props: {
item: T;
}) => void;
}>;
export { supercomplete };
}) => SupercompleteFeature<T>;
export { type SupercompleteFeature, supercomplete };

@@ -1,4 +0,3 @@

import type { InputHTMLAttributes } from 'react';
import type { GetProps, AutocompleteProps, PropsWithObjectRef } from '../common';
declare const useAutocomplete: <T, FeatureActions>({ onChange, isItemDisabled, feature: useFeature, traversal: useTraversal, getItemValue: _getItemValue }: AutocompleteProps<T, FeatureActions>) => {
import type { AutocompleteProps } from '../common';
declare const useAutocomplete: <T, FeatureYield extends object>({ onChange, isItemDisabled, feature: useFeature, traversal: useTraversal, getItemValue: _getItemValue }: AutocompleteProps<T, FeatureYield>) => {
setInputValue: (value: string) => void;

@@ -11,5 +10,3 @@ focusItem: T | undefined;

setOpen: (value: boolean) => void;
getInputProps: () => PropsWithObjectRef<InputHTMLAttributes<HTMLInputElement>>;
getListProps: () => import("react").HTMLAttributes<HTMLElement>;
} & Omit<GetProps<T> & FeatureActions, "getListProps" | "getInputProps">;
} & FeatureYield;
export { useAutocomplete };

@@ -5,4 +5,5 @@ export { useAutocomplete } from './hooks/useAutocomplete';

export { supercomplete } from './features/supercomplete';
export { dropdown } from './features/dropdown';
export { linearTraversal } from './traversals/linearTraversal';
export { groupedTraversal } from './traversals/groupedTraversal';
export type { AutocompleteProps, AutocompleteState, Feature } from './common';
SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc