@yandex/ui
Version:
Yandex UI components
83 lines (82 loc) • 4.35 kB
JavaScript
import { __read, __spread } from "tslib";
import React, { useCallback, useRef, useMemo, useEffect, } from 'react';
import { cn } from '@bem-react/classname';
import { Keys, isKeyCode } from '../lib/keyboard';
import { mergeRefs } from '../lib/mergeRefs';
import { useUniqId } from '../useUniqId';
import { TumblerLabel as Label } from './Label/Tumbler-Label';
import { TumblerButton as Button } from './Button/Tumbler-Button';
import { TumblerControl as Control } from './Control/Tumbler-Control';
import './Tumbler.css';
export var CHECKED_KEYS = [Keys.RIGHT, Keys.UP];
export var UNCHECKED_KEYS = [Keys.LEFT, Keys.DOWN];
export var cnTumbler = cn('Tumbler');
/**
* Компонент, предназначенный для создания переключателя.
*
* @param {TumblerProps} props Свойства компонента.
*/
export var Tumbler = function (_a) {
var checked = _a.checked, className = _a.className, htmlControlRef = _a.controlRef, disabled = _a.disabled,
// eslint-disable-next-line react-hooks/rules-of-hooks
_b = _a.id,
// eslint-disable-next-line react-hooks/rules-of-hooks
id = _b === void 0 ? useUniqId() : _b, innerRef = _a.innerRef, labelAfter = _a.labelAfter, labelBefore = _a.labelBefore, name = _a.name, onBlur = _a.onBlur, onChange = _a.onChange, htmlOnClick = _a.onClick, onFocus = _a.onFocus, htmlOnKeyDown = _a.onKeyDown, onKeyUp = _a.onKeyUp, tabIndex = _a.tabIndex, title = _a.title, autoFocus = _a.autoFocus, required = _a.required;
var buttonRef = useRef(null);
var controlRef = useRef(null);
var controlId = "control-" + id;
var beforeLabelId = "before-label-" + id;
var afterLabelId = "after-label-" + id;
useEffect(function () {
if (autoFocus && buttonRef.current !== null) {
buttonRef.current.focus();
}
}, []);
var labelledById = useMemo(function () {
if (labelBefore && labelAfter)
return checked ? beforeLabelId : afterLabelId;
if (labelBefore)
return beforeLabelId;
if (labelAfter)
return afterLabelId;
return undefined;
}, [checked, labelBefore, labelAfter, beforeLabelId, afterLabelId]);
// prettier-ignore
var onButtonClick = useCallback(function (event) {
if (controlRef.current !== null) {
controlRef.current.click();
}
if (buttonRef.current !== null) {
buttonRef.current.focus();
}
if (htmlOnClick !== undefined) {
htmlOnClick(event);
}
}, [htmlOnClick]);
// prettier-ignore
var onLabelClick = useCallback(function () {
if (buttonRef.current !== null) {
buttonRef.current.focus();
}
}, []);
// prettier-ignore
var onKeyDown = useCallback(function (event) {
if (isKeyCode(event.keyCode, __spread([Keys.ENTER], UNCHECKED_KEYS, CHECKED_KEYS))) {
event.preventDefault();
}
var shouldForceChange = (checked && isKeyCode(event.keyCode, UNCHECKED_KEYS)) ||
(!checked && isKeyCode(event.keyCode, CHECKED_KEYS));
if (shouldForceChange && controlRef.current !== null) {
controlRef.current.click();
}
if (htmlOnKeyDown !== undefined) {
htmlOnKeyDown(event);
}
}, [checked, htmlOnKeyDown]);
return (React.createElement("span", { ref: innerRef, className: cnTumbler(null, [className]), id: id, title: title, "aria-disabled": disabled },
labelBefore && (React.createElement(Label, { disabled: Boolean(!checked && labelBefore && labelAfter), htmlFor: controlId, id: beforeLabelId, onClick: onLabelClick }, labelBefore)),
React.createElement(Button, { tabIndex: disabled ? -1 : tabIndex, innerRef: buttonRef, checked: checked, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onBlur: onBlur, onFocus: onFocus, onClick: onButtonClick, labelledBy: labelledById, required: required }),
React.createElement(Control, { id: controlId, name: name, checked: checked, innerRef: mergeRefs(controlRef, htmlControlRef), onChange: onChange, required: required }),
labelAfter && (React.createElement(Label, { disabled: Boolean(checked && labelBefore && labelAfter), htmlFor: controlId, id: afterLabelId, onClick: onLabelClick }, labelAfter))));
};
Tumbler.displayName = 'Tumbler';