@talend/react-bootstrap
Version:
Bootstrap 3 components built with React
310 lines (307 loc) • 10.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _classnames = _interopRequireDefault(require("classnames"));
var _activeElement = _interopRequireDefault(require("dom-helpers/activeElement"));
var _contains = _interopRequireDefault(require("dom-helpers/query/contains"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _all = _interopRequireDefault(require("prop-types-extra/lib/all"));
var _elementType = _interopRequireDefault(require("prop-types-extra/lib/elementType"));
var _isRequiredForA11y = _interopRequireDefault(require("prop-types-extra/lib/isRequiredForA11y"));
var _uncontrollable = require("uncontrollable");
var _warning = _interopRequireDefault(require("warning"));
var _ButtonGroup = _interopRequireDefault(require("./ButtonGroup"));
var _DropdownMenu = _interopRequireDefault(require("./DropdownMenu"));
var _DropdownToggle = _interopRequireDefault(require("./DropdownToggle"));
var _bootstrapUtils = require("./utils/bootstrapUtils");
var _createChainedFunction = _interopRequireDefault(require("./utils/createChainedFunction"));
var _PropTypes = require("./utils/PropTypes");
var _ValidComponentChildren = _interopRequireDefault(require("./utils/ValidComponentChildren"));
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const TOGGLE_ROLE = _DropdownToggle.default.defaultProps.bsRole;
const MENU_ROLE = _DropdownMenu.default.defaultProps.bsRole;
const propTypes = {
/**
* The menu will open above the dropdown button, instead of below it.
*/
dropup: _propTypes.default.bool,
/**
* An html id attribute, necessary for assistive technologies, such as screen readers.
* @type {string|number}
* @required
*/
id: (0, _isRequiredForA11y.default)(_propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number])),
componentClass: _elementType.default,
/**
* The children of a Dropdown may be a `<Dropdown.Toggle>` or a `<Dropdown.Menu>`.
* @type {node}
*/
children: (0, _all.default)((0, _PropTypes.requiredRoles)(TOGGLE_ROLE, MENU_ROLE), (0, _PropTypes.exclusiveRoles)(MENU_ROLE)),
/**
* Whether or not component is disabled.
*/
disabled: _propTypes.default.bool,
/**
* Align the menu to the right side of the Dropdown toggle
*/
pullRight: _propTypes.default.bool,
/**
* Whether or not the Dropdown is visible.
*
* @controllable onToggle
*/
open: _propTypes.default.bool,
defaultOpen: _propTypes.default.bool,
/**
* A callback fired when the Dropdown wishes to change visibility. Called with the requested
* `open` value, the DOM event, and the source that fired it: `'click'`,`'keydown'`,`'rootClose'`, or `'select'`.
*
* ```js
* function(Boolean isOpen, Object event, { String source }) {}
* ```
* @controllable open
*/
onToggle: _propTypes.default.func,
/**
* A callback fired when a menu item is selected.
*
* ```js
* (eventKey: any, event: Object) => any
* ```
*/
onSelect: _propTypes.default.func,
/**
* If `'menuitem'`, causes the dropdown to behave like a menu item rather than
* a menu button.
*/
role: _propTypes.default.string,
/**
* Which event when fired outside the component will cause it to be closed
*
* *Note: For custom dropdown components, you will have to pass the
* `rootCloseEvent` to `<RootCloseWrapper>` in your custom dropdown menu
* component ([similarly to how it is implemented in `<Dropdown.Menu>`](https://github.com/react-bootstrap/react-bootstrap/blob/v0.31.5/src/DropdownMenu.js#L115-L119)).*
*/
rootCloseEvent: _propTypes.default.oneOf(['click', 'mousedown']),
/**
* @private
*/
onMouseEnter: _propTypes.default.func,
/**
* @private
*/
onMouseLeave: _propTypes.default.func
};
const defaultProps = {
componentClass: _ButtonGroup.default
};
class Dropdown extends _react.default.Component {
constructor(props, context) {
super(props, context);
this.handleClick = this.handleClick.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleClose = this.handleClose.bind(this);
this._focusInDropdown = false;
this.lastOpenEventType = null;
}
componentDidMount() {
this.focusNextOnOpen();
}
componentDidUpdate(prevProps) {
const {
open
} = this.props;
const prevOpen = prevProps.open;
if (open && !prevOpen) {
this.focusNextOnOpen();
}
if (!open && prevOpen) {
this._focusInDropdown = (0, _contains.default)(_reactDom.default.findDOMNode(this.menu), (0, _activeElement.default)(document));
// if focus hasn't already moved from the menu let's return it
// to the toggle
if (this._focusInDropdown) {
this._focusInDropdown = false;
this.focus();
}
}
}
focus() {
const toggle = _reactDom.default.findDOMNode(this.toggle);
if (toggle && toggle.focus) {
toggle.focus();
}
}
focusNextOnOpen() {
const menu = this.menu;
if (!menu || !menu.focusNext) {
return;
}
if (this.lastOpenEventType === 'keydown' || this.props.role === 'menuitem') {
menu.focusNext();
}
}
handleClick(event) {
if (this.props.disabled) {
return;
}
this.toggleOpen(event, {
source: 'click'
});
}
handleClose(event, eventDetails) {
if (!this.props.open) {
return;
}
this.toggleOpen(event, eventDetails);
}
handleKeyDown(event) {
if (this.props.disabled) {
return;
}
switch (event.key) {
case 'Down':
case 'ArrowDown':
if (!this.props.open) {
this.toggleOpen(event, {
source: 'keydown'
});
} else if (this.menu.focusNext) {
this.menu.focusNext();
}
event.preventDefault();
break;
case 'Esc':
case 'Escape':
case 'Tab':
this.handleClose(event, {
source: 'keydown'
});
break;
default:
}
}
toggleOpen(event, eventDetails) {
let open = !this.props.open;
if (open) {
this.lastOpenEventType = eventDetails.source;
}
if (this.props.onToggle) {
this.props.onToggle(open, event, eventDetails);
}
}
renderMenu(child, {
id,
onSelect,
rootCloseEvent,
...props
}) {
let ref = c => {
this.menu = c;
};
if (typeof child.ref === 'string') {
(0, _warning.default)(false, 'String refs are not supported on `<Dropdown.Menu>` components. ' + 'To apply a ref to the component use the callback signature:\n\n ' + 'https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute');
} else {
ref = (0, _createChainedFunction.default)(child.ref, ref);
}
return /*#__PURE__*/(0, _react.cloneElement)(child, {
...props,
ref,
labelledBy: id,
bsClass: (0, _bootstrapUtils.prefix)(props, 'menu'),
onClose: (0, _createChainedFunction.default)(child.props.onClose, this.handleClose),
onSelect: (0, _createChainedFunction.default)(child.props.onSelect, onSelect, (key, event) => this.handleClose(event, {
source: 'select'
})),
rootCloseEvent
});
}
renderToggle(child, props) {
let ref = c => {
this.toggle = c;
};
if (typeof child.ref === 'string') {
(0, _warning.default)(false, 'String refs are not supported on `<Dropdown.Toggle>` components. ' + 'To apply a ref to the component use the callback signature:\n\n ' + 'https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute');
} else {
ref = (0, _createChainedFunction.default)(child.ref, ref);
}
return /*#__PURE__*/(0, _react.cloneElement)(child, {
...props,
ref,
bsClass: (0, _bootstrapUtils.prefix)(props, 'toggle'),
onClick: (0, _createChainedFunction.default)(child.props.onClick, this.handleClick),
onKeyDown: (0, _createChainedFunction.default)(child.props.onKeyDown, this.handleKeyDown)
});
}
render() {
const {
componentClass: Component,
id,
dropup,
disabled,
pullRight,
open,
onSelect,
role,
bsClass,
className,
rootCloseEvent,
children,
...props
} = this.props;
delete props.onToggle;
const classes = {
[bsClass]: true,
open,
disabled
};
if (dropup) {
classes[bsClass] = false;
classes.dropup = true;
}
// This intentionally forwards bsSize and bsStyle (if set) to the
// underlying component, to allow it to render size and style variants.
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, {
...props,
className: (0, _classnames.default)(className, classes),
children: _ValidComponentChildren.default.map(children, child => {
switch (child.props.bsRole) {
case TOGGLE_ROLE:
return this.renderToggle(child, {
id,
disabled,
open,
role,
bsClass
});
case MENU_ROLE:
return this.renderMenu(child, {
id,
open,
pullRight,
bsClass,
onSelect,
rootCloseEvent
});
default:
return child;
}
})
});
}
}
Dropdown.propTypes = propTypes;
Dropdown.defaultProps = defaultProps;
(0, _bootstrapUtils.bsClass)('dropdown', Dropdown);
const UncontrolledDropdown = (0, _uncontrollable.uncontrollable)(Dropdown, {
open: 'onToggle'
});
UncontrolledDropdown.Toggle = _DropdownToggle.default;
UncontrolledDropdown.Menu = _DropdownMenu.default;
var _default = exports.default = UncontrolledDropdown;
//# sourceMappingURL=Dropdown.js.map