UNPKG

azure-devops-ui

Version:

React components for building web UI in Azure DevOps

130 lines (129 loc) 7.26 kB
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(); } } }