UNPKG

@momentum-ui/react-collaboration

Version:

Cisco Momentum UI Framework for React Collaboration Applications

289 lines 13.8 kB
/** @component button-group */ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import React from 'react'; import PropTypes from 'prop-types'; import omit from 'lodash/omit'; import qsa from 'dom-helpers/query/querySelectorAll'; import { UIDReset } from 'react-uid'; import ButtonGroupContext from '../ButtonGroupContext'; import SelectableContext from '../SelectableContext'; /** * @deprecated - Components in the legacy folder (/src/legacy) are deprecated. Please use a component from the components folder (/src/components) instead. Legacy components may not follow accessibility standards. **/ var ButtonGroup = /** @class */ (function (_super) { __extends(ButtonGroup, _super); function ButtonGroup(props) { var _this = _super.call(this, props) || this; _this.determineInitialFocus = function () { var bgContext = _this.state.bgContext; var _a = _this.props, focusFirstQuery = _a.focusFirstQuery, focusOnLoad = _a.focusOnLoad; var items = qsa(_this.containerNode, focusFirstQuery || ".md-button:not(.disabled):not(:disabled)"); var focus = bgContext.focus; if (items.length) { if (!focus) { focus = _this.getNextFocusedChild(items, items[0], 0); } if (focus && focusOnLoad) { _this.containerNode.querySelector("[data-md-event-key=\"".concat(focus, "\"]")).focus(); } } }; _this.handleSelect = function (e, opts) { var _a = _this.props, highlightSelected = _a.highlightSelected, onSelect = _a.onSelect, type = _a.type; var active = _this.state.bgContext.active; var eventKey = opts.eventKey; var items = _this.getFocusableItems(); var index = items.indexOf(_this.containerNode.querySelector("[data-md-event-key=\"".concat(eventKey, "\"]"))); _this.setFocus(items, index); // Don't do anything if onSelect Event Handler is present if (onSelect) { return onSelect(e, { eventKey: _this.getValue(items, index, 'event'), }); } // Don't do anything if index is the same or outside of the bounds if (eventKey === active || index < 0 || index > items.length - 1) return; // Call change event handler _this.setState(function (state) { return ({ bgContext: __assign(__assign({}, state.bgContext), { active: type === 'pill' ? false : highlightSelected && _this.getValue(items, index, 'event') }), }); }); }; _this.getValue = function (arr, index, attribute) { return arr[index].attributes["data-md-".concat(attribute, "-key")] && arr[index].attributes["data-md-".concat(attribute, "-key")].value; }; _this.getIncludesFirstCharacter = function (str, char) { return str.charAt(0).toLowerCase().includes(char); }; _this.setFocus = function (items, index) { _this.setState(function (state) { return ({ bgContext: __assign(__assign({}, state.bgContext), { focus: _this.getValue(items, index, 'event') }), }); }); }; _this.setActiveAndFocus = function (active, focus) { var _a = _this.props, type = _a.type, highlightSelected = _a.highlightSelected; _this._needsRefocus = false; _this.setState(function (state) { return ({ bgContext: __assign(__assign({}, state.bgContext), { active: type === 'pill' ? false : highlightSelected && active, focus: active || focus }), }); }); }; _this.setFocusByFirstCharacter = function (char, focusIdx, items, length) { var bgContext = _this.state.bgContext; var newIndex = items.reduce(function (agg, item, idx, arr) { var index = focusIdx + idx + 1 > length ? Math.abs(focusIdx + idx - length) : focusIdx + idx + 1; return !agg.length && _this.getValue(arr, index, 'keyboard') && _this.getIncludesFirstCharacter(_this.getValue(arr, index, 'keyboard'), char) ? agg.concat(_this.getValue(arr, index, 'event')) : agg; }, []); typeof newIndex[0] === 'string' && bgContext.focus !== newIndex[0] && _this.setState(function (state) { return ({ bgContext: __assign(__assign({}, state.bgContext), { focus: newIndex[0] }), }); }); }; _this.getFocusableItems = function () { if (!_this.containerNode) return null; var focusQuery = _this.props.focusQuery; var defaultItems = qsa(_this.containerNode, ".md-button:not(.disabled):not(:disabled)"); var customItems = (focusQuery && qsa(_this.containerNode, focusQuery)) || []; return customItems.length ? customItems.filter(function (item) { return customItems.indexOf(item) >= 0; }) : defaultItems; }; _this.handleKeyDown = function (e) { var focus = _this.state.bgContext.focus; var flag = false; var tgt = e.currentTarget; var char = e.key; var items = _this.getFocusableItems(); var focusIdx = (focus && items.indexOf(_this.containerNode.querySelector("[data-md-event-key=\"".concat(focus, "\"]")))) || 0; var length = (items.length && items.length - 1) || 0; var isPrintableCharacter = function (str) { return str.length === 1 && str.match(/\S/); }; switch (e.which) { case 38: case 37: _this.getNextFocusedChild(items, tgt, -1); _this._needsRefocus = true; flag = true; break; case 39: case 40: _this.getNextFocusedChild(items, tgt, 1); _this._needsRefocus = true; flag = true; break; default: if (isPrintableCharacter(char)) { _this.setFocusByFirstCharacter(char, focusIdx, items, length); _this._needsRefocus = true; flag = true; } break; } if (flag) { e.stopPropagation(); e.preventDefault(); } }; _this.state = { bgContext: __assign({ active: props.type === 'pill' ? false : props.highlightSelected && props.active, focus: props.active || null, isButtonGroup: true }, (props.pillWidth && { width: props.pillWidth })), selectContext: { parentOnSelect: _this.handleSelect, parentKeyDown: _this.handleKeyDown, }, }; return _this; } ButtonGroup.getDerivedStateFromProps = function (_a, state) { var active = _a.active; return active ? __assign(__assign({}, state), { bgContext: __assign(__assign({}, state.bgContext), { active: active }) }) : state; }; ButtonGroup.prototype.componentDidMount = function () { this.containerNode && this.determineInitialFocus(); }; ButtonGroup.prototype.componentDidUpdate = function (prevProps, prevState) { var bgContext = this.state.bgContext; var active = this.props.active; if (prevProps.active !== active) { this.setActiveAndFocus(active, focus); } if (!this._needsRefocus || !this.containerNode) return; if (bgContext.focus && prevState.bgContext.focus !== bgContext.focus) { this.containerNode.querySelector("[data-md-event-key=\"".concat(bgContext.focus, "\"]")).focus(); } }; ButtonGroup.prototype.getNextFocusedChild = function (items, current, offset) { if (!this.containerNode) return null; var bgContext = this.state.bgContext; var possibleIndex = items.indexOf(current) + offset; var getIndex = function () { if (possibleIndex < 0) { return items.length - 1; } else if (possibleIndex > items.length - 1) { return 0; } else return possibleIndex; }; bgContext.focus !== this.getValue(items, getIndex(), 'event') && this.setState({ bgContext: __assign(__assign({}, bgContext), { focus: this.getValue(items, getIndex(), 'event') }), }); return this.getValue(items, getIndex(), 'event'); }; ButtonGroup.prototype.render = function () { var _this = this; var _a = this.props, ariaLabel = _a.ariaLabel, children = _a.children, className = _a.className, justified = _a.justified, theme = _a.theme, type = _a.type, props = __rest(_a, ["ariaLabel", "children", "className", "justified", "theme", "type"]); var _b = this.state, bgContext = _b.bgContext, selectContext = _b.selectContext; var otherProps = omit(__assign({}, props), [ 'active', 'focusOnLoad', 'focusFirstQuery', 'focusQuery', 'highlightSelected', 'onSelect', 'pillWidth', ]); return (React.createElement(SelectableContext.Provider, { value: selectContext }, React.createElement("div", __assign({ "aria-label": ariaLabel, className: 'md-button-group' + "".concat((theme && " md-button-group--".concat(theme)) || '') + "".concat((justified && " md-button-group--justified") || '') + "".concat((type && " md-button-group--".concat(type)) || '') + "".concat((className && " ".concat(className)) || ''), role: "group", ref: function (ref) { return (_this.containerNode = ref); } }, otherProps), React.createElement(UIDReset, null, React.createElement(ButtonGroupContext.Provider, { value: bgContext }, children))))); }; return ButtonGroup; }(React.Component)); ButtonGroup.propTypes = { /** @prop Sets initial active Button by index | null */ active: PropTypes.string, /** @prop Text to display for blindness accessibility features | '' */ ariaLabel: PropTypes.string, /** @prop Children nodes to render inside ButtonGroup | null */ children: PropTypes.node, /** @prop Optional css class string | '' */ className: PropTypes.string, /** @prop Set focus to ButtonGroup when page is loaded | false */ focusOnLoad: PropTypes.bool, /** @prop Queries children to find matching item to have focus | '' */ focusFirstQuery: PropTypes.string, /** @prop Additional elements that can be focused by selector | '' */ focusQuery: PropTypes.string, /** @prop Highlights the selected button within group | true */ highlightSelected: PropTypes.bool, /** @prop Optional text-justified css styling | true */ justified: PropTypes.bool, /** @prop Handler to be called when the user selects ButtonGroup | null */ onSelect: PropTypes.func, /** @prop Sets width of a pill Button | '60px' */ pillWidth: PropTypes.string, /** @prop Optional Button color theme for ButtonGroup | '' */ theme: PropTypes.oneOf(['', 'dark']), /** @prop Optional Button type for ButtonGroup | '' */ type: PropTypes.oneOf(['', 'pill', 'unstyled']), }; ButtonGroup.defaultProps = { active: '', ariaLabel: '', children: null, className: '', focusOnLoad: false, focusFirstQuery: '', focusQuery: '', highlightSelected: true, justified: true, onSelect: null, pillWidth: '60px', theme: '', type: '', }; ButtonGroup.displayName = 'ButtonGroup'; export default ButtonGroup; //# sourceMappingURL=index.js.map