@momentum-ui/react-collaboration
Version:
Cisco Momentum UI Framework for React Collaboration Applications
153 lines • 8.46 kB
JavaScript
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);
};
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/ban-ts-comment */
import React, { useCallback, useRef, forwardRef, useState, useEffect, } from 'react';
import classnames from 'classnames';
import './Select.style.scss';
import { DEFAULTS, STYLE } from './Select.constants';
import { useSelectState } from '@react-stately/select';
import { useButton } from '@react-aria/button';
import { HiddenSelect, useSelect } from '@react-aria/select';
import Icon from '../Icon';
import ListBoxBase from '../ListBoxBase';
import Popover from '../Popover';
import Text from '../Text';
import { useSpatialNavigationContext } from '../SpatialNavigationProvider/SpatialNavigationProvider.utils';
import { useKeyboard } from '@react-aria/interactions';
/**
* @deprecated Use the equivalent from momentum.design (NPM: `@momentum-design/components/dist/react`)
*/
function Select(props, ref) {
var _a, _b, _c;
var _d, _e;
var ariaLabelledBy = props["aria-labelledby"], className = props.className, style = props.style, id = props.id, isDisabled = props.isDisabled, label = props.label, name = props.name, placeholder = props.placeholder, _f = props.direction, direction = _f === void 0 ? DEFAULTS.DIRECTION : _f, title = props.title, _g = props.showBorder, showBorder = _g === void 0 ? DEFAULTS.SHOULD_SHOW_BORDER : _g, listboxMaxHeight = props.listboxMaxHeight, _h = props.isInForm, isInForm = _h === void 0 ? DEFAULTS.IS_IN_FORM : _h, listboxWidth = props.listboxWidth, shallowDisabled = props.shallowDisabled, popoverSingleOpenGroupId = props.popoverSingleOpenGroupId;
var _j = useState(), popoverInstance = _j[0], setPopoverInstance = _j[1];
var hasBeenOpened = useRef(false);
var selectRef = useRef(null);
var boxRef = useRef(null);
var spatialNav = useSpatialNavigationContext();
var state = useSelectState(props);
var _k = useSelect(props, state, selectRef), labelProps = _k.labelProps, triggerProps = _k.triggerProps, valueProps = _k.valueProps, menuProps = _k.menuProps;
var buttonProps = useButton(__assign(__assign(__assign({}, triggerProps), { isDisabled: isDisabled }), (ariaLabelledBy === ''
? { 'aria-labelledby': null }
: ariaLabelledBy
? { 'aria-labelledby': ariaLabelledBy }
: {})), selectRef).buttonProps;
var ariaActivedesecendant = (menuProps === null || menuProps === void 0 ? void 0 : menuProps.id) &&
((_d = state === null || state === void 0 ? void 0 : state.selectionManager) === null || _d === void 0 ? void 0 : _d.focusedKey) &&
"".concat(menuProps.id, "-option-").concat(state.selectionManager.focusedKey);
delete buttonProps.color;
delete buttonProps.onKeyDown;
var getArrowIcon = function (isOpen) { return (isOpen ? 'arrow-up' : 'arrow-down'); };
var handleFocusBackOnTrigger = useCallback(function () {
var _a;
(_a = selectRef.current) === null || _a === void 0 ? void 0 : _a.focus();
}, []);
useEffect(function () {
if (popoverInstance) {
if (state.isOpen) {
// show popover once state changes to isOpen = true
popoverInstance.show();
hasBeenOpened.current = true;
}
else {
// hide popover once state changes to isOpen = false
popoverInstance.hide();
if (hasBeenOpened.current) {
// only do this if it has been opened previously to prevent unexpected focus
handleFocusBackOnTrigger();
}
}
}
}, [state.isOpen, popoverInstance, handleFocusBackOnTrigger]);
/**
* Handle closeOnSelect from @react-aria manually
*/
var closePopover = useCallback(function () {
state.close();
}, [state]);
/**
* Handle onKeyDown from @react-aria manually
*/
var onKeyDown = useCallback(function (e) {
if (spatialNav) {
return;
}
switch (e.key) {
// useButton already provides Keyboard event support for Enter and Space
case 'ArrowUp':
case 'ArrowDown':
e.preventDefault();
state.open();
break;
}
}, [spatialNav, state]);
var otherProps = shallowDisabled
? {
'aria-disabled': true,
'data-shallow-disabled': true,
onMouseDown: function (e) {
e.currentTarget.focus();
},
onKeyDown: function (e) {
if (e.key !== 'Tab') {
e.preventDefault();
}
},
onPointerDown: undefined,
}
: {
onKeyDown: onKeyDown,
};
var triggerComponent = (React.createElement("button", __assign({ id: name }, buttonProps, { role: "combobox", "aria-expanded": !!state.isOpen, "aria-controls": id, "aria-activedescendant": ariaActivedesecendant, className: classnames(STYLE.dropdownInput, (_a = {}, _a[STYLE.selected] = state.selectedItem, _a), (_b = {}, _b[STYLE.open] = state.isOpen, _b), (_c = {}, _c[STYLE.borderLess] = !showBorder, _c)), title: title }, otherProps),
React.createElement("span", __assign({ title: (_e = state.selectedItem) === null || _e === void 0 ? void 0 : _e.textValue }, valueProps, { className: STYLE.selectedItemWrapper }), state.selectedItem ? state.selectedItem.rendered : placeholder),
React.createElement("span", { "aria-hidden": "true", className: STYLE.iconWrapper },
React.createElement(Icon, { name: getArrowIcon(state.isOpen), weight: "bold", scale: 16 }))));
// special handling for spatial navigation
var keyboardProps = useKeyboard({
onKeyDown: function (event) {
if (spatialNav && event.key === spatialNav.back) {
closePopover();
event.nativeEvent.stopImmediatePropagation();
}
},
}).keyboardProps;
// delete color prop which is passed down and used in the ModalContainer
// because it conflicts with the HTML color property
delete keyboardProps.color;
return (React.createElement("div", { className: classnames(className, STYLE.wrapper), ref: ref,
/* @ts-ignore: next-line */
style: __assign({ '--local-width': listboxWidth || '100%' }, style), id: id },
label && (React.createElement("label", __assign({ htmlFor: name }, labelProps),
React.createElement(Text, { tagName: "p" }, label))),
isInForm && (React.createElement(HiddenSelect, { isDisabled: isDisabled, state: state, triggerRef: selectRef, label: label, name: name })),
React.createElement(Popover, __assign({ interactive: true, showArrow: false,
// remove role of Popover ModalContainer since the listbox role is passed through the ListBoxBase component via menuProps
// eslint-disable-next-line jsx-a11y/aria-role
role: null, triggerComponent: React.cloneElement(triggerComponent, {
ref: selectRef,
}), trigger: "manual", setInstance: setPopoverInstance, placement: direction, onClickOutside: closePopover, onHide: closePopover, hideOnEsc: !spatialNav, style: { maxHeight: listboxMaxHeight || 'none' }, className: STYLE.popover, strategy: listboxWidth ? 'fixed' : 'absolute', singleOpenGroupId: popoverSingleOpenGroupId }, (spatialNav ? keyboardProps : {})),
React.createElement(ListBoxBase, __assign({}, menuProps, { ref: boxRef, state: state, disallowEmptySelection: true,
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus: state.focusStrategy || DEFAULTS.FOCUS_STRATEGY, className: STYLE.menuListBox })))));
}
/**
* Dropdown / Select Element which displays a listbox with options.
*/
/**
* @deprecated Use the equivalent from momentum.design (NPM: `@momentum-design/components/dist/react`)
*/
var _Select = forwardRef(Select);
_Select.displayName = 'Select';
export default _Select;
//# sourceMappingURL=Select.js.map