UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

490 lines (489 loc) 22.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _classnames = _interopRequireDefault(require("classnames")); var _componentHelper = require("../../shared/component-helper.js"); var _AlignmentHelper2 = _interopRequireDefault(require("../../shared/AlignmentHelper.js")); var _SpacingHelper = require("../space/SpacingHelper.js"); var _filterValidProps = require("../../shared/helpers/filterValidProps.js"); var _Suffix = _interopRequireDefault(require("../../shared/helpers/Suffix.js")); var _IconPrimary = _interopRequireDefault(require("../icon-primary/IconPrimary.js")); var _FormLabel = _interopRequireDefault(require("../form-label/FormLabel.js")); var _FormStatus = _interopRequireDefault(require("../form-status/FormStatus.js")); var _Button = _interopRequireWildcard(require("../button/Button.js")); var _DrawerList = _interopRequireDefault(require("../../fragments/drawer-list/DrawerList.js")); var _DrawerListContext = _interopRequireDefault(require("../../fragments/drawer-list/DrawerListContext.js")); var _DrawerListProvider = _interopRequireDefault(require("../../fragments/drawer-list/DrawerListProvider.js")); var _DrawerListHelpers = require("../../fragments/drawer-list/DrawerListHelpers.js"); var _AlignmentHelper; 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); } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } class Dropdown extends _react.default.PureComponent { render() { const id = this.props.id || (0, _componentHelper.makeUniqueId)(); const { more_menu, action_menu, prevent_selection, children, data } = this.props; return _react.default.createElement(_DrawerListProvider.default, _extends({}, this.props, { id: id, data: data || children, opened: false, tagName: "dnb-dropdown", ignore_events: false, prevent_selection: (0, _componentHelper.isTrue)(more_menu) || (0, _componentHelper.isTrue)(action_menu) || (0, _componentHelper.isTrue)(prevent_selection) }), _react.default.createElement(DropdownInstance, _extends({}, this.props, { id: id }))); } } exports.default = Dropdown; _defineProperty(Dropdown, "defaultProps", { id: null, title: 'Option Menu', variant: 'secondary', icon: null, icon_size: null, icon_position: null, triangle_position: null, label: null, label_direction: null, label_sr_only: null, status: null, status_state: 'error', status_props: null, status_no_animation: null, globalStatus: null, innerRef: null, buttonRef: null, suffix: null, scrollable: true, focusable: false, max_height: null, direction: 'auto', skip_portal: null, portal_class: null, no_animation: false, no_scroll_animation: false, prevent_selection: false, more_menu: false, action_menu: false, independent_width: false, size: 'default', align_dropdown: null, trigger_element: null, data: null, default_value: null, value: 'initval', open_on_focus: false, prevent_close: false, keep_open: false, opened: false, disabled: null, stretch: null, skeleton: null, className: null, children: null, on_show: null, on_hide: null, on_change: null, on_select: null, on_state_update: null }); process.env.NODE_ENV !== "production" ? Dropdown.propTypes = { ..._SpacingHelper.spacingPropTypes, ..._DrawerListHelpers.drawerListPropTypes, ..._DrawerListHelpers.drawerListProviderPropTypes, id: _propTypes.default.string, title: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]), variant: _Button.buttonVariantPropType.variant, icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node, _propTypes.default.func]), icon_size: _propTypes.default.string, icon_position: _propTypes.default.oneOf(['left', 'right']), triangle_position: _propTypes.default.oneOf(['left', 'right']), label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), label_direction: _propTypes.default.oneOf(['horizontal', 'vertical']), label_sr_only: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), status: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool, _propTypes.default.func, _propTypes.default.node]), status_state: _propTypes.default.string, status_props: _propTypes.default.object, status_no_animation: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), innerRef: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.func]), buttonRef: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.func]), globalStatus: _propTypes.default.shape({ id: _propTypes.default.string, message: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]) }), suffix: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), scrollable: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), focusable: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), direction: _propTypes.default.oneOf(['auto', 'top', 'bottom']), max_height: _propTypes.default.number, skip_portal: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), portal_class: _propTypes.default.string, no_animation: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), no_scroll_animation: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), prevent_selection: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), more_menu: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), action_menu: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), independent_width: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), size: _propTypes.default.oneOf(['default', 'small', 'medium', 'large']), align_dropdown: _propTypes.default.oneOf(['left', 'right']), trigger_element: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node]), data: _propTypes.default.oneOfType([_propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node, _propTypes.default.object]), _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]), _propTypes.default.shape({ selectedKey: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), selected_key: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), selected_value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]), content: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node, _propTypes.default.arrayOf(_propTypes.default.string)]) })]))]), default_value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), open_on_focus: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), prevent_close: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), keep_open: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), opened: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), disabled: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), stretch: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), skeleton: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), className: _propTypes.default.string, children: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node, _propTypes.default.object, _propTypes.default.array]), on_show: _propTypes.default.func, on_hide: _propTypes.default.func, on_change: _propTypes.default.func, on_select: _propTypes.default.func, on_state_update: _propTypes.default.func } : void 0; class DropdownInstance extends _react.default.PureComponent { constructor(props) { super(props); _defineProperty(this, "setVisible", () => { this.context.drawerList.setWrapperElement(this._refWrapper.current).setVisible(); }); _defineProperty(this, "setHidden", (...args) => { this.context.drawerList.setHidden(...args); }); _defineProperty(this, "onFocusHandler", () => { if ((0, _componentHelper.isTrue)(this.props.open_on_focus)) { this.setVisible(); } }); _defineProperty(this, "onBlurHandler", () => { if ((0, _componentHelper.isTrue)(this.props.open_on_focus)) { this.setHidden(); } }); _defineProperty(this, "onClickHandler", () => { if ((0, _componentHelper.isTrue)(this.props.disabled)) { return; } if (!this.context.drawerList.hidden && this.context.drawerList.isOpen) { this.setHidden(); } else { this.setVisible(); } }); _defineProperty(this, "onTriggerKeyDownHandler", e => { switch ((0, _componentHelper.keycode)(e)) { case 'enter': case 'space': e.preventDefault(); this.setVisible(); break; case 'up': case 'down': e.preventDefault(); this.setVisible(); break; case 'escape': case 'esc': this.setHidden(); break; case 'home': case 'end': case 'page down': case 'page up': e.preventDefault(); break; } }); _defineProperty(this, "onHideHandler", (args = {}) => { const attributes = this.attributes || {}; const res = (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_hide', { ...args, attributes }); if (res !== false) { this.setFocus(args); } return res; }); _defineProperty(this, "setFocus", args => { clearTimeout(this._focusTimeout); this._focusTimeout = setTimeout(() => { try { const element = this._refButton.current; if (element && typeof element.focus === 'function') { if (args.preventHideFocus !== true) { element.focus({ preventScroll: true }); } (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_hide_focus', { element }); } } catch (e) {} }, 1); }); _defineProperty(this, "onSelectHandler", args => { if (parseFloat(args.active_item) > -1) { const attributes = this.attributes || {}; (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_select', { ...args, attributes }); } }); _defineProperty(this, "onChangeHandler", args => { const attributes = this.attributes || {}; (0, _componentHelper.dispatchCustomElementEvent)(this, 'on_change', { ...args, attributes }); }); this.attributes = {}; this.state = this.state || {}; this._ref = props.innerRef || _react.default.createRef(); this._refWrapper = _react.default.createRef(); this._refButton = props.buttonRef || _react.default.createRef(); } componentDidMount() { if ((0, _componentHelper.isTrue)(this.props.opened)) { this.setVisible(); } } componentWillUnmount() { clearTimeout(this._focusTimeout); } getTitle(title = null) { const { data } = this.context.drawerList; if (data && data.length > 0) { const currentOptionData = (0, _DrawerListHelpers.getCurrentData)(this.context.drawerList.selected_item, data); if (currentOptionData) { title = currentOptionData.selected_value || (0, _DrawerListHelpers.parseContentTitle)(currentOptionData); } } return title; } render() { var _this$context, _this$context2, _this$context3; const props = (0, _componentHelper.extendPropsWithContextInClassComponent)(this.props, Dropdown.defaultProps, { skeleton: (_this$context = this.context) === null || _this$context === void 0 ? void 0 : _this$context.skeleton }, this.context.getTranslation(this.props).Dropdown, (0, _filterValidProps.pickFormElementProps)((_this$context2 = this.context) === null || _this$context2 === void 0 ? void 0 : _this$context2.FormRow), (0, _filterValidProps.pickFormElementProps)((_this$context3 = this.context) === null || _this$context3 === void 0 ? void 0 : _this$context3.formElement), this.context.Dropdown); const { label, label_direction, label_sr_only, icon_size, size, fixed_position, enable_body_lock, status, status_state, status_props, status_no_animation, globalStatus, suffix, scrollable, focusable, keep_open, prevent_close, no_animation, no_scroll_animation, triangle_position, skip_portal, portal_class, trigger_element: CustomTrigger, more_menu, action_menu, independent_width, prevent_selection, max_height, default_value, className, disabled, stretch, skeleton, variant, title: _title, icon: _icon, align_dropdown: _align_dropdown, icon_position: _icon_position, data: _data, children: _children, direction: _direction, id: _id, opened: _opened, value: _value, buttonRef, innerRef, ...attributes } = props; let { icon, icon_position, align_dropdown } = props; const handleAsMenu = (0, _componentHelper.isTrue)(action_menu) || (0, _componentHelper.isTrue)(more_menu) || (0, _componentHelper.isTrue)(prevent_selection); const title = this.getTitle(_title); const isPopupMenu = (0, _componentHelper.isTrue)(more_menu) || !title; if (isPopupMenu) { icon = icon || ((0, _componentHelper.isTrue)(more_menu) ? 'more' : 'chevron_down'); } if (isPopupMenu || (0, _componentHelper.isTrue)(action_menu)) { if (icon_position !== 'right' && align_dropdown !== 'right') { icon_position = 'left'; align_dropdown = 'left'; } } if ((0, _componentHelper.isTrue)(independent_width) && icon_position !== 'left' && !align_dropdown) { align_dropdown = 'right'; } const { id, selected_item, direction, opened } = this.context.drawerList; const showStatus = (0, _componentHelper.getStatusState)(status); Object.assign(this.context.drawerList.attributes, (0, _componentHelper.validateDOMAttributes)(null, attributes)); const mainParams = { className: (0, _classnames.default)(`dnb-dropdown dnb-dropdown--${direction} dnb-dropdown--icon-position-${icon_position || 'right'} dnb-dropdown--${align_dropdown || 'right'} dnb-form-component`, ((0, _componentHelper.isTrue)(independent_width) || (0, _componentHelper.isTrue)(action_menu)) && 'dnb-dropdown--independent-width', (0, _SpacingHelper.createSpacingClasses)(props), className, opened && 'dnb-dropdown--opened', label_direction && `dnb-dropdown--${label_direction}`, isPopupMenu && 'dnb-dropdown--is-popup', (0, _componentHelper.isTrue)(action_menu) && `dnb-dropdown--action-menu`, size && `dnb-dropdown--${size}`, (0, _componentHelper.isTrue)(stretch) && `dnb-dropdown--stretch`, status && `dnb-dropdown__status--${status_state}`, showStatus && 'dnb-dropdown__form-status') }; const triggerParams = { className: 'dnb-dropdown__trigger' + (opened ? " dnb-button--active" : ""), id, disabled, 'aria-haspopup': handleAsMenu ? true : 'listbox', 'aria-expanded': opened, ...attributes, onFocus: this.onFocusHandler, onBlur: this.onBlurHandler, onClick: this.onClickHandler, onKeyDown: this.onTriggerKeyDownHandler }; if (opened) { triggerParams['aria-controls'] = `${id}-ul`; } if (showStatus || suffix) { triggerParams['aria-describedby'] = (0, _componentHelper.combineDescribedBy)(triggerParams, showStatus ? id + '-status' : null, suffix ? id + '-suffix' : null); } if (label) { triggerParams['aria-labelledby'] = (0, _componentHelper.combineLabelledBy)(triggerParams, id + '-label', id); } (0, _componentHelper.validateDOMAttributes)(null, mainParams); (0, _componentHelper.validateDOMAttributes)(this.props, triggerParams); this.attributes = (0, _componentHelper.validateDOMAttributes)(null, attributes); return _react.default.createElement("span", _extends({ ref: this._ref }, mainParams), label && _react.default.createElement(_FormLabel.default, { id: id + '-label', forId: id, text: label, labelDirection: label_direction, srOnly: label_sr_only, disabled: disabled, skeleton: skeleton, onClick: this.onClickHandler }), _react.default.createElement("span", { className: "dnb-dropdown__inner", ref: this._refWrapper }, _AlignmentHelper || (_AlignmentHelper = _react.default.createElement(_AlignmentHelper2.default, null)), _react.default.createElement(_FormStatus.default, _extends({ show: showStatus, id: id + '-form-status', globalStatus: globalStatus, label: label, text_id: id + '-status', text: status, state: status_state, no_animation: status_no_animation, skeleton: skeleton }, status_props)), _react.default.createElement("span", { className: "dnb-dropdown__row" }, _react.default.createElement("span", { className: "dnb-dropdown__shell" }, CustomTrigger ? _react.default.createElement(CustomTrigger, triggerParams) : _react.default.createElement(_Button.default, _extends({ variant: variant, icon: false, size: size === 'default' ? 'medium' : size, innerRef: this._refButton, custom_content: _react.default.createElement(_react.default.Fragment, null, !isPopupMenu && _react.default.createElement("span", { className: "dnb-dropdown__text dnb-button__text" }, _react.default.createElement("span", { className: "dnb-dropdown__text__inner" }, title)), _react.default.createElement("span", { "aria-hidden": true, className: 'dnb-dropdown__icon' + (parseFloat(selected_item) === 0 ? " dnb-dropdown__icon--first" : "") }, icon !== false && _react.default.createElement(_IconPrimary.default, { icon: icon || 'chevron_down', size: icon_size || (size === 'large' ? 'medium' : 'default') }))), role: "combobox", title: (0, _componentHelper.convertJsxToString)(title) || undefined }, triggerParams)), _react.default.createElement(_DrawerList.default, { id: id, role: handleAsMenu ? 'menu' : 'listbox', portal_class: portal_class, list_class: 'dnb-dropdown__list' + (variant === 'tertiary' ? " dnb-dropdown__list--tertiary" : ""), value: selected_item, default_value: default_value, scrollable: scrollable, focusable: focusable, no_animation: no_animation, no_scroll_animation: no_scroll_animation, skip_portal: skip_portal, prevent_selection: handleAsMenu, action_menu: action_menu, triangle_position: triangle_position || icon_position || 'right', keep_open: keep_open, prevent_close: prevent_close, independent_width: (0, _componentHelper.isTrue)(independent_width) || isPopupMenu || action_menu, is_popup: isPopupMenu || action_menu, align_drawer: align_dropdown || 'left', fixed_position: fixed_position, enable_body_lock: enable_body_lock, disabled: disabled, max_height: max_height, direction: direction, size: size, on_change: this.onChangeHandler, on_select: this.onSelectHandler, on_hide: this.onHideHandler })), suffix && _react.default.createElement(_Suffix.default, { className: "dnb-dropdown__suffix", id: id + '-suffix', context: props, onClick: this.setHidden }, suffix)))); } } _defineProperty(DropdownInstance, "defaultProps", Dropdown.defaultProps); _defineProperty(DropdownInstance, "contextType", _DrawerListContext.default); process.env.NODE_ENV !== "production" ? DropdownInstance.propTypes = Dropdown.propTypes : void 0; Dropdown.HorizontalItem = _DrawerList.default.HorizontalItem; Dropdown._formElement = true; Dropdown._supportsSpacingProps = true; //# sourceMappingURL=Dropdown.js.map