1 | import { __rest } from "tslib";
|
2 | import * as React from 'react';
|
3 | import * as ReactDOM from 'react-dom';
|
4 | import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown';
|
5 | import { css } from '@patternfly/react-styles';
|
6 | import { keyHandler, formatBreakpointMods } from '../../helpers/util';
|
7 | import { DropdownPosition, DropdownArrowContext, DropdownContext } from './dropdownConstants';
|
8 | export class DropdownMenu extends React.Component {
|
9 | constructor() {
|
10 | super(...arguments);
|
11 | this.refsCollection = [];
|
12 | this.componentWillUnmount = () => {
|
13 | document.removeEventListener('keydown', this.onKeyDown);
|
14 | };
|
15 | this.onKeyDown = (event) => {
|
16 | if (!this.props.isOpen ||
|
17 | !Array.from(document.activeElement.classList).find(className => DropdownMenu.validToggleClasses.concat(this.context.toggleClass).includes(className))) {
|
18 | return;
|
19 | }
|
20 | const refs = this.refsCollection;
|
21 | if (event.key === 'ArrowDown') {
|
22 | const firstFocusTargetCollection = refs.find(ref => ref && ref[0] && !ref[0].hasAttribute('disabled'));
|
23 | DropdownMenu.focusFirstRef(firstFocusTargetCollection);
|
24 | event.stopPropagation();
|
25 | }
|
26 | else if (event.key === 'ArrowUp') {
|
27 | const collectionLength = refs.length;
|
28 | const lastFocusTargetCollection = refs.slice(collectionLength - 1, collectionLength);
|
29 | const lastFocusTarget = lastFocusTargetCollection && lastFocusTargetCollection[0];
|
30 | DropdownMenu.focusFirstRef(lastFocusTarget);
|
31 | event.stopPropagation();
|
32 | }
|
33 | };
|
34 | this.childKeyHandler = (index, innerIndex, position, custom = false) => {
|
35 | keyHandler(index, innerIndex, position, this.refsCollection, this.props.isGrouped ? this.refsCollection : React.Children.toArray(this.props.children), custom);
|
36 | };
|
37 | this.sendRef = (index, nodes, isDisabled, isSeparator) => {
|
38 | this.refsCollection[index] = [];
|
39 | nodes.map((node, innerIndex) => {
|
40 | if (!node) {
|
41 | this.refsCollection[index][innerIndex] = null;
|
42 | }
|
43 | else if (!node.getAttribute) {
|
44 |
|
45 | this.refsCollection[index][innerIndex] = ReactDOM.findDOMNode(node);
|
46 | }
|
47 | else if (isSeparator) {
|
48 | this.refsCollection[index][innerIndex] = null;
|
49 | }
|
50 | else {
|
51 | this.refsCollection[index][innerIndex] = node;
|
52 | }
|
53 | });
|
54 | };
|
55 | }
|
56 | componentDidMount() {
|
57 | document.addEventListener('keydown', this.onKeyDown);
|
58 | const { autoFocus } = this.props;
|
59 | if (autoFocus) {
|
60 |
|
61 | const focusTargetCollection = this.refsCollection.find(ref => ref && ref[0] && !ref[0].hasAttribute('disabled'));
|
62 | const focusTarget = focusTargetCollection && focusTargetCollection[0];
|
63 | if (focusTarget && focusTarget.focus) {
|
64 | setTimeout(() => focusTarget.focus());
|
65 | }
|
66 | }
|
67 | }
|
68 | shouldComponentUpdate() {
|
69 |
|
70 | this.refsCollection = [];
|
71 | return true;
|
72 | }
|
73 | extendChildren() {
|
74 | const { children, isGrouped } = this.props;
|
75 | if (isGrouped) {
|
76 | let index = 0;
|
77 | return React.Children.map(children, groupedChildren => {
|
78 | const group = groupedChildren;
|
79 | const props = {};
|
80 | if (group.props && group.props.children) {
|
81 | if (Array.isArray(group.props.children)) {
|
82 | props.children = React.Children.map(group.props.children, option => React.cloneElement(option, {
|
83 | index: index++
|
84 | }));
|
85 | }
|
86 | else {
|
87 | props.children = React.cloneElement(group.props.children, {
|
88 | index: index++
|
89 | });
|
90 | }
|
91 | }
|
92 | return React.cloneElement(group, props);
|
93 | });
|
94 | }
|
95 | return React.Children.map(children, (child, index) => React.cloneElement(child, {
|
96 | index
|
97 | }));
|
98 | }
|
99 | render() {
|
100 | const _a = this.props, { className, isOpen, position, children, component, isGrouped, setMenuComponentRef,
|
101 |
|
102 | openedOnEnter, alignments } = _a, props = __rest(_a, ["className", "isOpen", "position", "children", "component", "isGrouped", "setMenuComponentRef", "openedOnEnter", "alignments"]);
|
103 | return (React.createElement(DropdownArrowContext.Provider, { value: {
|
104 | keyHandler: this.childKeyHandler,
|
105 | sendRef: this.sendRef
|
106 | } }, component === 'div' ? (React.createElement(DropdownContext.Consumer, null, ({ onSelect, menuClass }) => (React.createElement("div", { className: css(menuClass, position === DropdownPosition.right && styles.modifiers.alignRight, formatBreakpointMods(alignments, styles, 'align-'), className), hidden: !isOpen, onClick: event => onSelect && onSelect(event), ref: setMenuComponentRef }, children)))) : ((isGrouped && (React.createElement(DropdownContext.Consumer, null, ({ menuClass, menuComponent }) => {
|
107 | const MenuComponent = (menuComponent || 'div');
|
108 | return (React.createElement(MenuComponent, Object.assign({}, props, { className: css(menuClass, position === DropdownPosition.right && styles.modifiers.alignRight, formatBreakpointMods(alignments, styles, 'align-'), className), hidden: !isOpen, role: "menu", ref: setMenuComponentRef }), this.extendChildren()));
|
109 | }))) || (React.createElement(DropdownContext.Consumer, null, ({ menuClass, menuComponent }) => {
|
110 | const MenuComponent = (menuComponent || component);
|
111 | return (React.createElement(MenuComponent, Object.assign({}, props, { className: css(menuClass, position === DropdownPosition.right && styles.modifiers.alignRight, formatBreakpointMods(alignments, styles, 'align-'), className), hidden: !isOpen, role: "menu", ref: setMenuComponentRef }), this.extendChildren()));
|
112 | })))));
|
113 | }
|
114 | }
|
115 | DropdownMenu.displayName = 'DropdownMenu';
|
116 | DropdownMenu.defaultProps = {
|
117 | className: '',
|
118 | isOpen: true,
|
119 | openedOnEnter: false,
|
120 | autoFocus: true,
|
121 | position: DropdownPosition.left,
|
122 | component: 'ul',
|
123 | isGrouped: false,
|
124 | setMenuComponentRef: null
|
125 | };
|
126 | DropdownMenu.validToggleClasses = [styles.dropdownToggle, styles.dropdownToggleButton];
|
127 | DropdownMenu.focusFirstRef = (refCollection) => {
|
128 | if (refCollection && refCollection[0] && refCollection[0].focus) {
|
129 | setTimeout(() => refCollection[0].focus());
|
130 | }
|
131 | };
|
132 | DropdownMenu.contextType = DropdownContext;
|
133 |
|
\ | No newline at end of file |