azure-devops-ui
Version:
React components for building web UI in Azure DevOps
130 lines (129 loc) • 7.26 kB
JavaScript
import "../../CommonImports";
import "../../Core/core.css";
import "./RadioButton.css";
import * as React from "react";
import { ObservableLike } from '../../Core/Observable';
import { FocusGroupContext } from '../../FocusGroup';
import { FocusZone, FocusZoneContext, FocusZoneDirection, FocusZoneKeyStroke } from '../../FocusZone';
import { FormItem, FormItemContext } from '../../FormItem';
import { Observer } from '../../Observer';
import { Tooltip } from '../../TooltipEx';
import { css, getSafeId, isArrowKey, noop } from '../../Util';
import { getTabIndex } from '../../Utilities/Focus';
import { RadioButtonGroupDirection } from "./RadioButton.Props";
export const RadioButtonGroupContext = React.createContext({
onSelect: noop,
registerId: noop
});
export class RadioButtonGroup extends React.Component {
constructor() {
super(...arguments);
this.focusGroupContext = React.createRef();
this.idMap = {};
this.onChange = (buttonId) => {
if (this.props.onSelect) {
this.props.onSelect(buttonId);
}
};
this.getFirstButtonId = () => {
const children = React.Children.toArray(this.props.children);
if (children.length) {
const firstChild = children[0];
return firstChild.props.id;
}
return undefined;
};
this.postProcessKeystroke = (event) => {
if (document.activeElement && isArrowKey(event)) {
const id = this.idMap[document.activeElement.id];
if (id && id !== ObservableLike.getValue(this.props.selectedButtonId || "") && this.props.onSelect) {
this.props.onSelect(id);
}
}
return FocusZoneKeyStroke.IgnoreNone;
};
this.registerId = (safeId, id) => {
this.idMap[safeId] = id;
};
}
render() {
const { className, defaultButtonId, direction, excludeFocusZone, id, selectedButtonId, text, ariaInvalid, ariaErrorMessageId } = this.props;
const groupClassName = css("bolt-radio-button-group", direction === RadioButtonGroupDirection.Vertical ? "flex-column" : "flex-row", this.props.groupClassName);
return (React.createElement(Observer, { selectedButtonId: selectedButtonId }, (props) => (React.createElement(RadioButtonGroupContext.Provider, { value: {
onSelect: this.onChange,
registerId: this.registerId,
selectedButtonId: props.selectedButtonId || this.getFirstButtonId()
} },
React.createElement(FormItem, { className: css(className, "bolt-radio-button-group-container", excludeFocusZone && groupClassName), label: text }, excludeFocusZone ? (this.props.children) : (React.createElement(FormItemContext.Consumer, null, formItemContext => (React.createElement(FocusZone, { direction: direction === RadioButtonGroupDirection.Vertical
? FocusZoneDirection.Vertical
: FocusZoneDirection.Horizontal, circularNavigation: true, focusGroupProps: {
defaultElementId: defaultButtonId || props.selectedButtonId || this.getFirstButtonId(),
ref: this.focusGroupContext
}, postprocessKeyStroke: this.postProcessKeystroke },
React.createElement("div", { "aria-invalid": ariaInvalid, "aria-errormessage": ariaErrorMessageId, "aria-labelledby": getSafeId(formItemContext.ariaLabelledById), className: groupClassName, role: "radiogroup", id: getSafeId(id) }, this.props.children))))))))));
}
focus() {
if (this.focusGroupContext.current) {
this.focusGroupContext.current.focus();
}
}
}
RadioButtonGroup.defaultProps = {
direction: RadioButtonGroupDirection.Vertical,
ariaInvalid: false
};
export class RadioButton extends React.Component {
constructor() {
super(...arguments);
this.radioButtonInternal = React.createRef();
}
render() {
return (React.createElement(RadioButtonGroupContext.Consumer, null, groupContext => (React.createElement(FocusGroupContext.Consumer, null, focusGroupContext => (React.createElement(FocusZoneContext.Consumer, null, zoneContext => {
return (React.createElement(RadioButtonInternal, Object.assign({}, this.props, { focusGroupContext: focusGroupContext, focuszoneId: zoneContext.focuszoneId, onFocus: focusGroupContext.onFocus, onSelect: groupContext.onSelect, registerId: groupContext.registerId, selectedButton: groupContext.selectedButtonId === this.props.id, ref: this.radioButtonInternal })));
}))))));
}
focus() {
if (this.radioButtonInternal.current) {
this.radioButtonInternal.current.focus();
}
}
}
class RadioButtonInternal extends React.Component {
constructor() {
super(...arguments);
this.radioButton = React.createRef();
this.onClick = (event) => {
if (!event.defaultPrevented) {
if (!this.props.disabled) {
this.props.onSelect(this.props.id);
event.preventDefault();
}
}
};
this.onFocus = (event) => {
this.props.onFocus(this.props.id);
};
}
render() {
const tabIndex = getTabIndex(this.props, this.props.focusGroupContext);
const labelId = this.props.text && "rb-label-" + this.props.id;
let radio = (React.createElement("div", { "aria-checked": this.props.selectedButton, "aria-disabled": this.props.disabled, "aria-labelledby": getSafeId(this.props.ariaLabelledBy || labelId), "aria-describedby": getSafeId(this.props.ariaDescribedBy), className: css(this.props.className, "bolt-radio-button cursor-pointer", this.props.disabled ? "disabled" : "enabled", this.props.selectedButton && "checked", (this.props.text || React.Children.count(this.props.children) > 0) && "labelled", "bolt-focus-treatment"), "data-focuszone": !this.props.disabled && !this.props.excludeFocusZone ? this.props.focuszoneId : undefined, "data-is-focusable": !this.props.disabled ? "true" : "false", id: getSafeId(this.props.id), key: this.props.id, onClick: this.onClick, onFocus: this.onFocus, ref: this.radioButton, role: this.props.role || "radio", tabIndex: tabIndex },
React.createElement("div", { className: "bolt-radio-button-icon" },
React.createElement("div", { className: "bolt-radio-button-bullet" })),
this.props.text && (React.createElement("div", { className: "bolt-radio-button-label", id: getSafeId(labelId) }, this.props.text)),
this.props.children));
if (this.props.tooltipProps) {
radio = React.createElement(Tooltip, Object.assign({}, this.props.tooltipProps), radio);
}
return radio;
}
componentDidMount() {
const { id, registerId } = this.props;
registerId(getSafeId(id), id);
}
focus() {
if (this.radioButton.current) {
this.radioButton.current.focus();
}
}
}