New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@snack-uikit/input-private

Package Overview
Dependencies
Maintainers
0
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@snack-uikit/input-private - npm Package Compare versions

Comparing version 3.2.1 to 4.0.0

11

CHANGELOG.md

@@ -6,2 +6,13 @@ # Change Log

# 4.0.0 (2024-09-27)
### BREAKING CHANGES
* **PDS-199:** differentiate postfix and prefix buttons in useButtonNavigation hook ([662f72c](https://github.com/cloud-ru-tech/snack-uikit/commit/662f72ce6797a563f6e13535dcf3912c961b632c))
## 3.2.1 (2024-09-23)

@@ -8,0 +19,0 @@

@@ -17,2 +17,7 @@ /**

/**
* Проверяет находится ли курсор в начале поля ввода
* @function helper
*/
export declare function isCursorInTheBeginning(input: HTMLInputElement | HTMLTextAreaElement | null): boolean;
/**
* Проверяет находится ли курсор в конце поля ввода

@@ -19,0 +24,0 @@ * @function helper

@@ -25,2 +25,9 @@ /**

/**
* Проверяет находится ли курсор в начале поля ввода
* @function helper
*/
export function isCursorInTheBeginning(input) {
return (input === null || input === void 0 ? void 0 : input.selectionStart) === 0;
}
/**
* Проверяет находится ли курсор в конце поля ввода

@@ -27,0 +34,0 @@ * @function helper

17

dist/hooks/types.d.ts
import { KeyboardEventHandler, MouseEventHandler, ReactElement, RefObject } from 'react';
type RenderButtonProps = {
type RenderActiveButtonProps = {
key: string;

@@ -9,8 +9,19 @@ ref: RefObject<HTMLButtonElement>;

};
export type ButtonProps = {
type RenderInactiveButtonProps = {
key: string;
};
export type InactiveItem = {
active: false;
id: string;
render(props: RenderInactiveButtonProps): ReactElement;
show: boolean;
};
export type ActiveItem = {
active: true;
id: string;
ref: RefObject<HTMLButtonElement>;
show: boolean;
render(props: RenderButtonProps): ReactElement;
render(props: RenderActiveButtonProps): ReactElement;
};
export type ButtonProps = InactiveItem | ActiveItem;
export {};

8

dist/hooks/useButtonNavigation.d.ts

@@ -6,3 +6,4 @@ import { KeyboardEventHandler, RefObject } from 'react';

inputRef: RefObject<T>;
buttons: ButtonProps[];
postfixButtons: ButtonProps[];
prefixButtons?: ButtonProps[];
onButtonKeyDown?: KeyboardEventHandler<HTMLButtonElement>;

@@ -16,8 +17,9 @@ readonly: boolean;

*/
export declare function useButtonNavigation<T extends HTMLInputElement | HTMLTextAreaElement>({ inputRef, setInputFocus, buttons, onButtonKeyDown, readonly, submitKeys, }: UseButtonNavigationProps<T>): {
export declare function useButtonNavigation<T extends HTMLInputElement | HTMLTextAreaElement>({ inputRef, setInputFocus, postfixButtons, prefixButtons, onButtonKeyDown, readonly, submitKeys, }: UseButtonNavigationProps<T>): {
inputTabIndex: number;
onInputKeyDown: KeyboardEventHandler<T>;
setInitialTabIndices: () => void;
buttons: import("react/jsx-runtime").JSX.Element;
prefixButtons: import("react/jsx-runtime").JSX.Element | undefined;
postfixButtons: import("react/jsx-runtime").JSX.Element | undefined;
};
export {};
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useState } from 'react';
import { useEventHandler } from '@snack-uikit/utils';
import { isCursorInTheEnd, runAfterRerender, selectAll } from '../helpers';
import { isCursorInTheBeginning, isCursorInTheEnd, runAfterRerender, selectAll } from '../helpers';
/**

@@ -9,12 +9,14 @@ * Позволяет использовать клавиатуру для навигации по элементам управления

*/
export function useButtonNavigation({ inputRef, setInputFocus = () => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, buttons, onButtonKeyDown = () => { }, readonly, submitKeys, }) {
const getInitialButtonTabIndices = useCallback(() => buttons.map(() => -1), [buttons]);
export function useButtonNavigation({ inputRef, setInputFocus = () => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, postfixButtons, prefixButtons = [], onButtonKeyDown = () => { }, readonly, submitKeys, }) {
const [inputTabIndex, setInputTabIndex] = useState(0);
const [buttonTabIndices, setButtonTabIndices] = useState(getInitialButtonTabIndices);
const buttonKeyDownEventHandler = useEventHandler(onButtonKeyDown);
const findVisibleButton = useCallback((index, direction) => {
const getInitialPrefixButtonTabIndices = useCallback(() => prefixButtons.map(() => -1), [prefixButtons]);
const [prefixButtonTabIndices, setPrefixButtonTabIndices] = useState(getInitialPrefixButtonTabIndices);
const getInitialPostfixButtonTabIndices = useCallback(() => postfixButtons.map(() => -1), [postfixButtons]);
const [postfixButtonTabIndices, setPostfixButtonTabIndices] = useState(getInitialPostfixButtonTabIndices);
const findVisiblePrefixButton = useCallback((index, direction) => {
const delta = direction === 'ArrowLeft' ? -1 : 1;
const condition = (i) => (direction === 'ArrowLeft' ? i >= 0 : i < buttons.length);
const condition = (i) => (direction === 'ArrowLeft' ? i >= 0 : i < prefixButtons.length);
for (let i = index + delta; condition(i); i += delta) {
if (buttons[i].show) {
if (prefixButtons[i].active && prefixButtons[i].show) {
return i;

@@ -24,7 +26,18 @@ }

return index;
}, [buttons]);
}, [prefixButtons]);
const findVisiblePostfixButton = useCallback((index, direction) => {
const delta = direction === 'ArrowLeft' ? -1 : 1;
const condition = (i) => (direction === 'ArrowLeft' ? i >= 0 : i < postfixButtons.length);
for (let i = index + delta; condition(i); i += delta) {
if (postfixButtons[i].active && postfixButtons[i].show) {
return i;
}
}
return index;
}, [postfixButtons]);
const setInitialTabIndices = useCallback(() => {
setInputTabIndex(0);
setButtonTabIndices(getInitialButtonTabIndices);
}, [getInitialButtonTabIndices]);
setPrefixButtonTabIndices(getInitialPrefixButtonTabIndices);
setPostfixButtonTabIndices(getInitialPostfixButtonTabIndices);
}, [getInitialPrefixButtonTabIndices, getInitialPostfixButtonTabIndices]);
const focusInput = useCallback(() => {

@@ -34,20 +47,77 @@ setInitialTabIndices();

}, [setInitialTabIndices, setInputFocus]);
const focusButton = useCallback((index) => {
const focusPrefixButton = useCallback((index) => {
var _a;
setInputTabIndex(-1);
setButtonTabIndices(tabIndices => tabIndices.map((_, i) => (i === index ? 0 : -1)));
(_a = buttons[index].ref.current) === null || _a === void 0 ? void 0 : _a.focus();
}, [buttons]);
setPrefixButtonTabIndices(tabIndices => tabIndices.map((_, i) => (i === index ? 0 : -1)));
setPostfixButtonTabIndices(getInitialPostfixButtonTabIndices);
prefixButtons[index].active && ((_a = prefixButtons[index].ref.current) === null || _a === void 0 ? void 0 : _a.focus());
}, [getInitialPostfixButtonTabIndices, prefixButtons]);
const focusPostfixButton = useCallback((index) => {
var _a;
setInputTabIndex(-1);
setPrefixButtonTabIndices(getInitialPrefixButtonTabIndices);
setPostfixButtonTabIndices(tabIndices => tabIndices.map((_, i) => (i === index ? 0 : -1)));
postfixButtons[index].active && ((_a = postfixButtons[index].ref.current) === null || _a === void 0 ? void 0 : _a.focus());
}, [getInitialPrefixButtonTabIndices, postfixButtons]);
const handleInputKeyDown = useCallback(event => {
setInitialTabIndices();
if (event.key === 'ArrowRight' && (readonly || isCursorInTheEnd(inputRef.current))) {
const index = findVisibleButton(-1, event.key);
const index = findVisiblePostfixButton(-1, event.key);
if (index >= 0) {
focusButton(index);
focusPostfixButton(index);
}
}
}, [findVisibleButton, focusButton, inputRef, readonly, setInitialTabIndices]);
const handleButtonKeyDown = useCallback((index) => event => {
if (event.key === 'ArrowLeft' && (readonly || isCursorInTheBeginning(inputRef.current))) {
const index = findVisiblePrefixButton(prefixButtons.length, event.key);
if (index >= 0) {
focusPrefixButton(index);
}
}
}, [
findVisiblePostfixButton,
findVisiblePrefixButton,
focusPostfixButton,
focusPrefixButton,
inputRef,
prefixButtons.length,
readonly,
setInitialTabIndices,
]);
const handlePrefixButtonKeyDown = useCallback((index) => event => {
if (event.key === 'ArrowRight') {
const nextIndex = findVisiblePrefixButton(index, event.key);
if (index === nextIndex) {
event.preventDefault();
focusInput();
if (readonly) {
runAfterRerender(() => selectAll(inputRef.current));
}
}
else {
focusPrefixButton(nextIndex);
}
}
if (event.key === 'ArrowLeft') {
const nextIndex = findVisibleButton(index, event.key);
if (index <= prefixButtons.length - 1) {
focusPrefixButton(findVisiblePrefixButton(index, event.key));
}
}
if (submitKeys.includes(event.key)) {
runAfterRerender(() => setInitialTabIndices());
}
buttonKeyDownEventHandler === null || buttonKeyDownEventHandler === void 0 ? void 0 : buttonKeyDownEventHandler(event);
}, [
buttonKeyDownEventHandler,
prefixButtons.length,
findVisiblePrefixButton,
focusPrefixButton,
focusInput,
inputRef,
readonly,
setInitialTabIndices,
submitKeys,
]);
const handlePostfixButtonKeyDown = useCallback((index) => event => {
if (event.key === 'ArrowLeft') {
const nextIndex = findVisiblePostfixButton(index, event.key);
if (index === nextIndex) {

@@ -61,8 +131,8 @@ event.preventDefault();

else {
focusButton(nextIndex);
focusPostfixButton(nextIndex);
}
}
if (event.key === 'ArrowRight') {
if (index <= buttons.length - 1) {
focusButton(findVisibleButton(index, event.key));
if (index <= postfixButtons.length - 1) {
focusPostfixButton(findVisiblePostfixButton(index, event.key));
}

@@ -76,5 +146,5 @@ }

buttonKeyDownEventHandler,
buttons.length,
findVisibleButton,
focusButton,
postfixButtons.length,
findVisiblePostfixButton,
focusPostfixButton,
focusInput,

@@ -93,12 +163,31 @@ inputRef,

setInitialTabIndices,
buttons: (_jsx(_Fragment, { children: buttons.map(({ id, render, ref, show }, index) => show
? render({
key: id,
ref,
tabIndex: buttonTabIndices[index],
onKeyDown: handleButtonKeyDown(index),
onClick: onButtonClick,
})
: null) })),
prefixButtons: prefixButtons.some(button => button.show) ? (_jsx(_Fragment, { children: prefixButtons.map((props, index) => {
if (!props.show) {
return null;
}
return props.active
? props.render({
key: props.id,
ref: props.ref,
tabIndex: prefixButtonTabIndices[index],
onKeyDown: handlePrefixButtonKeyDown(index),
onClick: onButtonClick,
})
: props.render({ key: props.id });
}) })) : undefined,
postfixButtons: postfixButtons.some(button => button.show) ? (_jsx(_Fragment, { children: postfixButtons.map((props, index) => {
if (!props.show) {
return null;
}
return props.active
? props.render({
key: props.id,
ref: props.ref,
tabIndex: postfixButtonTabIndices[index],
onKeyDown: handlePostfixButtonKeyDown(index),
onClick: onButtonClick,
})
: props.render({ key: props.id });
}) })) : undefined,
};
}

@@ -14,2 +14,3 @@ import { jsx as _jsx } from "react/jsx-runtime";

id: 'clear',
active: true,
ref: clearButtonRef,

@@ -16,0 +17,0 @@ show: showClearButton,

@@ -7,3 +7,3 @@ {

"title": "Input Private",
"version": "3.2.1",
"version": "4.0.0",
"sideEffects": [

@@ -40,3 +40,3 @@ "*.css",

},
"gitHead": "f9212fe04b0dbba9bedea1bb3a034ab612287841"
"gitHead": "36a86f3bf30c115e8c6b49f6c8d7a2d2ffb86ff1"
}

@@ -80,2 +80,6 @@ # Input Private

Откладывает колбек на следующий цикл EventLoop
## isCursorInTheBeginning
`helper`
Проверяет находится ли курсор в начале поля ввода
## isCursorInTheEnd

@@ -82,0 +86,0 @@ `helper`

@@ -27,2 +27,10 @@ /**

/**
* Проверяет находится ли курсор в начале поля ввода
* @function helper
*/
export function isCursorInTheBeginning(input: HTMLInputElement | HTMLTextAreaElement | null) {
return input?.selectionStart === 0;
}
/**
* Проверяет находится ли курсор в конце поля ввода

@@ -29,0 +37,0 @@ * @function helper

import { KeyboardEventHandler, MouseEventHandler, ReactElement, RefObject } from 'react';
type RenderButtonProps = {
type RenderActiveButtonProps = {
key: string;

@@ -11,7 +11,21 @@ ref: RefObject<HTMLButtonElement>;

export type ButtonProps = {
type RenderInactiveButtonProps = {
key: string;
};
export type InactiveItem = {
active: false;
id: string;
render(props: RenderInactiveButtonProps): ReactElement;
show: boolean;
};
export type ActiveItem = {
active: true;
id: string;
ref: RefObject<HTMLButtonElement>;
show: boolean;
render(props: RenderButtonProps): ReactElement;
render(props: RenderActiveButtonProps): ReactElement;
};
export type ButtonProps = InactiveItem | ActiveItem;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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