@fluentui/react-northstar
Version:
A themable React component library.
191 lines (190 loc) • 7.21 kB
JavaScript
import _map from "lodash/map";
import _invoke from "lodash/invoke";
import _findIndex from "lodash/findIndex";
// TODO:
// vertical - padding variable?
import { radioGroupBehavior } from '@fluentui/accessibility';
import * as customPropTypes from '@fluentui/react-proptypes';
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { childrenExist, commonPropTypes, rtlTextContainer, createShorthandFactory } from '../../utils';
import { RadioGroupItem } from './RadioGroupItem';
import { useAutoControlled, useTelemetry, useFluentContext, getElementType, useUnhandledProps, useAccessibility, useStyles } from '@fluentui/react-bindings';
export var radioGroupClassName = 'ui-radiogroup';
/**
* A RadioGroup allows user to select a value from a small set of mutually exclusive options.
*
* @accessibility
* Implements [ARIA Radio Group](https://www.w3.org/TR/wai-aria-practices-1.1/#radiobutton) design pattern.
* @accessibilityIssues
* [JAWS narrates instruction message on each radio in radiogroup](https://github.com/FreedomScientific/VFO-standards-support/issues/473)
*/
export var RadioGroup = /*#__PURE__*/function () {
var RadioGroup = /*#__PURE__*/React.forwardRef(function (props, ref) {
var context = useFluentContext();
var _useTelemetry = useTelemetry(RadioGroup.displayName, context.telemetry),
setStart = _useTelemetry.setStart,
setEnd = _useTelemetry.setEnd;
setStart();
var children = props.children,
vertical = props.vertical,
items = props.items,
className = props.className,
design = props.design,
styles = props.styles,
variables = props.variables;
var ElementType = getElementType(props);
var unhandledProps = useUnhandledProps(RadioGroup.handledProps, props);
var getA11yProps = useAccessibility(props.accessibility, {
debugName: RadioGroup.displayName,
actionHandlers: {
nextItem: function nextItem(event) {
return setCheckedItem(event, 1);
},
prevItem: function prevItem(event) {
return setCheckedItem(event, -1);
}
},
rtl: context.rtl
});
var _useStyles = useStyles(RadioGroup.displayName, {
className: radioGroupClassName,
mapPropsToStyles: function mapPropsToStyles() {
return {
vertical: vertical
};
},
mapPropsToInlineStyles: function mapPropsToInlineStyles() {
return {
className: className,
design: design,
styles: styles,
variables: variables
};
},
rtl: context.rtl
}),
classes = _useStyles.classes;
var _useAutoControlled = useAutoControlled({
defaultValue: props.defaultCheckedValue,
value: props.checkedValue,
initialValue: undefined
}),
checkedValue = _useAutoControlled[0],
setCheckedValue = _useAutoControlled[1];
var _React$useState = React.useState(false),
shouldFocus = _React$useState[0],
setShouldFocus = _React$useState[1];
var getItemProps = function getItemProps(item) {
return item.props || item;
};
var setCheckedItem = function setCheckedItem(event, direction) {
var nextItem = findNextEnabledCheckedItem(direction);
if (nextItem) {
checkedValueChange({
nextCheckedValue: nextItem.value,
shouldFocus: true,
event: event,
itemProps: nextItem
});
}
event.preventDefault();
};
var findNextEnabledCheckedItem = function findNextEnabledCheckedItem(direction) {
if (!props.items || !props.items.length) {
return undefined;
}
var currentIndex =
// if none of the values selected, set current index to the first item
checkedValue !== undefined ? _findIndex(props.items, function (item) {
return getItemProps(item).value === checkedValue;
}) : 0;
for (var newIndex = currentIndex + direction; newIndex !== currentIndex; newIndex += direction) {
if (newIndex < 0) {
newIndex = props.items.length - 1;
} else if (newIndex >= props.items.length) {
newIndex = 0;
}
if (newIndex === currentIndex) {
return undefined;
}
var itemProps = getItemProps(props.items[newIndex]);
if (!itemProps.disabled) {
return itemProps;
}
}
return undefined;
};
var handleItemOverrides = function handleItemOverrides(predefinedProps) {
return {
checked: typeof checkedValue !== 'undefined' && checkedValue === predefinedProps.value,
onClick: function onClick(event, itemProps) {
var value = itemProps.value,
disabled = itemProps.disabled;
if (!disabled && value !== checkedValue) {
checkedValueChange({
nextCheckedValue: value,
shouldFocus: false,
event: event,
itemProps: itemProps
});
}
_invoke(predefinedProps, 'onClick', event, itemProps);
},
shouldFocus: shouldFocus
};
};
var renderItems = function renderItems(vertical) {
var isNoneValueSelected = checkedValue === undefined;
return _map(items, function (item, index) {
return RadioGroupItem.create(item, {
defaultProps: function defaultProps() {
return getA11yProps('item', Object.assign({
vertical: vertical
}, index === 0 && isNoneValueSelected && {
tabIndex: 0
}));
},
overrideProps: handleItemOverrides
});
});
};
var checkedValueChange = function checkedValueChange(_ref) {
var nextCheckedValue = _ref.nextCheckedValue,
shouldFocus = _ref.shouldFocus,
event = _ref.event,
itemProps = _ref.itemProps;
setCheckedValue(nextCheckedValue);
setShouldFocus(shouldFocus);
_invoke(props, 'onCheckedValueChange', event, itemProps);
};
var element = getA11yProps.unstable_wrapWithFocusZone( /*#__PURE__*/React.createElement(ElementType, getA11yProps('root', Object.assign({
className: classes.root,
ref: ref
}, unhandledProps, rtlTextContainer.getAttributes({
forElements: [children]
}))), childrenExist(children) ? children : renderItems(vertical)));
setEnd();
return element;
});
RadioGroup.displayName = 'RadioGroup';
RadioGroup.propTypes = Object.assign({}, commonPropTypes.createCommon({
content: false
}), {
checkedValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
defaultCheckedValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
items: customPropTypes.collectionShorthand,
onCheckedValueChange: PropTypes.func,
vertical: PropTypes.bool
});
RadioGroup.defaultProps = {
accessibility: radioGroupBehavior
};
RadioGroup.handledProps = Object.keys(RadioGroup.propTypes);
RadioGroup.Item = RadioGroupItem;
RadioGroup.create = createShorthandFactory({
Component: RadioGroup
});
return RadioGroup;
}();
//# sourceMappingURL=RadioGroup.js.map