chakra-ui
Version:
Responsive and accessible React UI components built with React and Emotion
124 lines (103 loc) • 3.56 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
/** @jsx jsx */
import { jsx } from "@emotion/core";
import { Children, cloneElement, useState, useRef } from "react";
import { genId } from "../utils";
import Box from "../Box";
var RadioButtonGroup = function RadioButtonGroup(_ref) {
var id = _ref.id,
name = _ref.name,
children = _ref.children,
defaultValue = _ref.defaultValue,
controlledValue = _ref.value,
onChange = _ref.onChange,
_ref$spacing = _ref.spacing,
spacing = _ref$spacing === void 0 ? "12px" : _ref$spacing,
isInline = _ref.isInline,
rest = _objectWithoutProperties(_ref, ["id", "name", "children", "defaultValue", "value", "onChange", "spacing", "isInline"]);
var isControlled = controlledValue != null;
var _useState = useState(defaultValue || null),
_useState2 = _slicedToArray(_useState, 2),
value = _useState2[0],
setValue = _useState2[1];
var _value = isControlled ? controlledValue : value;
var allNodes = useRef([]);
var focusableValues = Children.map(children, function (child) {
return child.props.isDisabled === true ? null : child.props.value;
}).filter(function (val) {
return val != null;
});
var allValues = Children.map(children, function (child) {
return child.props.value;
});
var updateIndex = function updateIndex(index) {
var childValue = focusableValues[index];
var _index = allValues.indexOf(childValue);
allNodes.current[_index].focus();
!isControlled && setValue(childValue);
onChange && onChange(childValue);
};
var handleKeyDown = function handleKeyDown(event) {
var count = focusableValues.length;
var enabledCheckedIndex = focusableValues.indexOf(_value);
if (enabledCheckedIndex === -1) {
enabledCheckedIndex = 0;
}
switch (event.key) {
case "ArrowRight":
case "ArrowDown":
{
var nextIndex = (enabledCheckedIndex + 1) % count;
updateIndex(nextIndex);
break;
}
case "ArrowLeft":
case "ArrowUp":
{
var _nextIndex = (enabledCheckedIndex - 1 + count) % count;
updateIndex(_nextIndex);
break;
}
default:
break;
}
};
var clones = Children.map(children, function (child, index) {
var isLastChild = children.length === index + 1;
var isFirstChild = index === 0;
var spacingProps = isInline ? {
mr: spacing
} : {
mb: spacing
};
var isChecked = child.props.value === _value;
var handleClick = function handleClick() {
setValue(child.props.value);
};
var getTabIndex = function getTabIndex() {
// If a RadioGroup has no radio selected the first enabled radio should be focusable
if (_value == null) {
return isFirstChild ? 0 : -1;
} else {
return isChecked ? 0 : -1;
}
};
return cloneElement(child, _extends({
ref: function ref(node) {
return allNodes.current[index] = node;
},
name: name || genId("radio"),
onClick: handleClick,
tabIndex: getTabIndex(),
isChecked: isChecked
}, !isLastChild && spacingProps));
});
return jsx(Box, _extends({
role: "radiogroup",
onKeyDown: handleKeyDown,
"aria-labelledby": id
}, rest), clones);
};
export default RadioButtonGroup;