@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
492 lines (491 loc) • 17.3 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _withComponentMarkers = _interopRequireDefault(require("../../shared/helpers/withComponentMarkers.js"));
var _react = _interopRequireWildcard(require("react"));
var _clsx = _interopRequireDefault(require("clsx"));
var _componentHelper = require("../../shared/component-helper.js");
var _extendPropsWithContext = require("../../shared/helpers/extendPropsWithContext.js");
var _useMountEffect = _interopRequireDefault(require("../../shared/helpers/useMountEffect.js"));
var _useIsomorphicLayoutEffect = require("../../shared/helpers/useIsomorphicLayoutEffect.js");
var _useId = _interopRequireDefault(require("../../shared/helpers/useId.js"));
var _AlignmentHelper2 = _interopRequireDefault(require("../../shared/AlignmentHelper.js"));
var _SpacingUtils = require("../space/SpacingUtils.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 = _interopRequireDefault(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 _jsxRuntime = require("react/jsx-runtime");
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 }; }
const dropdownDefaultProps = {
id: null,
title: 'Option Menu',
variant: 'secondary',
icon: null,
iconSize: null,
iconPosition: null,
arrowPosition: null,
label: null,
labelDirection: 'vertical',
labelSrOnly: null,
status: null,
statusState: 'error',
statusProps: null,
statusNoAnimation: null,
globalStatus: null,
ref: null,
buttonRef: null,
suffix: null,
scrollable: true,
focusable: false,
maxHeight: null,
direction: 'auto',
skipPortal: null,
portalClass: null,
noAnimation: false,
noScrollAnimation: false,
preventSelection: false,
independentWidth: false,
size: 'default',
align: null,
triggerElement: null,
data: null,
defaultValue: null,
value: 'initval',
openOnFocus: false,
preventClose: false,
keepOpen: false,
open: false,
disabled: null,
stretch: null,
skeleton: null,
className: null,
children: null,
onOpen: null,
onClose: null,
onChange: null,
onSelect: null
};
const DropdownInstance = _react.default.memo(function DropdownInstance({
externalRef,
externalButtonRef,
...ownProps
}) {
const context = (0, _react.useContext)(_DrawerListContext.default);
const elRef = (0, _react.useRef)(null);
const wrapperRef = (0, _react.useRef)(null);
const buttonRef = (0, _react.useRef)(null);
const focusTimeoutRef = (0, _react.useRef)(null);
const attributesRef = (0, _react.useRef)({});
const setRootRef = (0, _react.useCallback)(el => {
elRef.current = el;
if (typeof externalRef === 'function') {
externalRef(el);
} else if (externalRef) {
externalRef.current = el;
}
}, [externalRef]);
const setButtonRef = (0, _react.useCallback)(el => {
buttonRef.current = el;
if (typeof externalButtonRef === 'function') {
externalButtonRef(el);
} else if (externalButtonRef) {
externalButtonRef.current = el;
}
}, [externalButtonRef]);
const propsWithDefaults = {
...dropdownDefaultProps,
...(0, _componentHelper.removeUndefinedProps)({
...ownProps
})
};
const propsWithDefaultsRef = (0, _react.useRef)(propsWithDefaults);
propsWithDefaultsRef.current = propsWithDefaults;
(0, _useIsomorphicLayoutEffect.useIsomorphicLayoutEffect)(() => {
if (propsWithDefaults.open) {
context.drawerList.setWrapperElement(wrapperRef.current).setVisible();
}
}, []);
(0, _useMountEffect.default)(() => {
return () => {
if (focusTimeoutRef.current) {
clearTimeout(focusTimeoutRef.current);
}
};
});
const setVisible = (0, _react.useCallback)(() => {
context.drawerList.setWrapperElement(wrapperRef.current).setVisible();
}, [context.drawerList]);
const setHidden = (0, _react.useCallback)((...args) => {
context.drawerList.setHidden(...args);
}, [context.drawerList]);
const setFocus = (0, _react.useCallback)(args => {
if (focusTimeoutRef.current) {
clearTimeout(focusTimeoutRef.current);
}
focusTimeoutRef.current = setTimeout(() => {
try {
const element = buttonRef.current;
if (element && typeof element.focus === 'function') {
if (args.preventHideFocus !== true) {
element.focus({
preventScroll: true
});
}
(0, _componentHelper.dispatchCustomElementEvent)({
props: propsWithDefaultsRef.current
}, 'onCloseFocus', {
element
});
}
} catch (e) {}
}, 1);
}, []);
const onFocusHandler = (0, _react.useCallback)(() => {
if (propsWithDefaults.openOnFocus) {
setVisible();
}
}, [propsWithDefaults.openOnFocus, setVisible]);
const onBlurHandler = (0, _react.useCallback)(() => {
if (propsWithDefaults.openOnFocus) {
setHidden();
}
}, [propsWithDefaults.openOnFocus, setHidden]);
const onClickHandler = (0, _react.useCallback)(() => {
if (propsWithDefaults.disabled) {
return;
}
if (!context.drawerList.hidden && context.drawerList.isOpen) {
setHidden();
} else {
setVisible();
}
}, [propsWithDefaults.disabled, context.drawerList.hidden, context.drawerList.isOpen, setHidden, setVisible]);
const onTriggerKeyDownHandler = (0, _react.useCallback)(e => {
switch (e.key) {
case 'Enter':
case ' ':
e.preventDefault();
setVisible();
break;
case 'ArrowUp':
case 'ArrowDown':
e.preventDefault();
setVisible();
break;
case 'Escape':
setHidden();
break;
case 'Home':
case 'End':
case 'PageDown':
case 'PageUp':
e.preventDefault();
break;
}
}, [setVisible, setHidden]);
const onCloseHandler = (0, _react.useCallback)((args = {}) => {
const attributes = attributesRef.current || {};
const res = (0, _componentHelper.dispatchCustomElementEvent)({
props: propsWithDefaultsRef.current
}, 'onClose', {
...args,
attributes
});
if (res !== false) {
setFocus(args);
}
return res;
}, [setFocus]);
const onSelectHandler = (0, _react.useCallback)(args => {
if (parseFloat(args.activeItem) > -1) {
const attributes = attributesRef.current || {};
(0, _componentHelper.dispatchCustomElementEvent)({
props: propsWithDefaultsRef.current
}, 'onSelect', {
...args,
attributes
});
}
}, []);
const onChangeHandler = (0, _react.useCallback)(args => {
const attributes = attributesRef.current || {};
(0, _componentHelper.dispatchCustomElementEvent)({
props: propsWithDefaultsRef.current
}, 'onChange', {
...args,
attributes
});
}, []);
const getTitle = (title = null) => {
const {
data
} = context.drawerList;
if (data && data.length > 0) {
const currentOptionData = (0, _DrawerListHelpers.getCurrentData)(context.drawerList.selectedItem, data);
if (currentOptionData) {
title = currentOptionData.selectedValue || (0, _DrawerListHelpers.parseContentTitle)(currentOptionData);
}
}
return title;
};
const props = (0, _extendPropsWithContext.extendPropsWithContext)(propsWithDefaults, dropdownDefaultProps, {
skeleton: context === null || context === void 0 ? void 0 : context.skeleton
}, context.getTranslation(propsWithDefaults).Dropdown, (0, _filterValidProps.pickFormElementProps)(context === null || context === void 0 ? void 0 : context.formElement), context.Dropdown);
const {
label,
labelDirection,
labelSrOnly,
iconSize,
size,
fixedPosition,
enableBodyLock,
status,
statusState,
statusProps,
statusNoAnimation,
globalStatus,
suffix,
scrollable,
focusable,
keepOpen,
preventClose,
noAnimation,
noScrollAnimation,
arrowPosition,
skipPortal,
portalClass,
triggerElement: CustomTrigger,
independentWidth,
preventSelection,
maxHeight,
defaultValue,
className,
disabled,
stretch,
skeleton,
variant,
title: _title,
icon: _icon,
align: _align,
iconPosition: _iconPosition,
openOnFocus: _openOnFocus,
data: _data,
children: _children,
direction: _direction,
id: _id,
open: _open,
value: _value,
pageOffset: _pageOffset,
observerElement: _observerElement,
enableBodyLock: _enableBodyLock,
listClass: _listClass,
buttonRef: _buttonRef,
ref: _ref,
onOpen: _onOpen,
onClose: _onClose,
onFocus: _onFocus,
onChange: _onChange,
onSelect: _onSelect,
onOpenFocus: _onOpenFocus,
onCloseFocus: _onCloseFocus,
externalRef: _externalRef,
externalButtonRef: _externalButtonRef,
...attributes
} = props;
let {
icon,
iconPosition,
align
} = props;
const handleAsMenu = preventSelection;
const title = getTitle(_title);
const isPopupMenu = !title;
if (isPopupMenu) {
icon = icon || 'chevron_down';
}
if (isPopupMenu) {
if (iconPosition !== 'right' && align !== 'right') {
iconPosition = 'left';
align = 'left';
}
}
if (independentWidth && iconPosition !== 'left' && !align) {
align = 'right';
}
const {
id,
selectedItem,
direction,
open
} = context.drawerList;
const showStatus = (0, _componentHelper.getStatusState)(status);
Object.assign(context.drawerList.attributes, (0, _componentHelper.validateDOMAttributes)(null, attributes));
const mainParams = (0, _SpacingUtils.applySpacing)(props, {
className: (0, _clsx.default)(`dnb-dropdown dnb-dropdown--${direction} dnb-dropdown--icon-position-${iconPosition || 'right'} dnb-dropdown--${align || 'right'} dnb-form-component`, className, open && 'dnb-dropdown--open', labelDirection && `dnb-dropdown--${labelDirection}`, isPopupMenu && 'dnb-dropdown--is-popup', independentWidth && 'dnb-dropdown--independent-width', size && `dnb-dropdown--${size}`, stretch && `dnb-dropdown--stretch`, status && `dnb-dropdown__status--${statusState}`, showStatus && 'dnb-dropdown__form-status')
});
const triggerParams = {
className: 'dnb-dropdown__trigger',
id,
disabled,
'aria-haspopup': handleAsMenu ? true : 'listbox',
'aria-expanded': open,
...attributes,
onFocus: onFocusHandler,
onBlur: onBlurHandler,
onClick: onClickHandler,
onKeyDown: onTriggerKeyDownHandler
};
if (open) {
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)(ownProps, triggerParams);
attributesRef.current = (0, _componentHelper.validateDOMAttributes)(null, attributes);
return (0, _jsxRuntime.jsxs)("span", {
ref: setRootRef,
...mainParams,
children: [label && (0, _jsxRuntime.jsx)(_FormLabel.default, {
id: id + '-label',
forId: id,
text: label,
labelDirection: labelDirection,
srOnly: labelSrOnly,
disabled: disabled,
skeleton: skeleton,
onClick: onClickHandler
}), (0, _jsxRuntime.jsxs)("span", {
className: "dnb-dropdown__inner",
ref: wrapperRef,
children: [_AlignmentHelper || (_AlignmentHelper = (0, _jsxRuntime.jsx)(_AlignmentHelper2.default, {})), (0, _jsxRuntime.jsx)(_FormStatus.default, {
show: showStatus,
id: id + '-form-status',
globalStatus: globalStatus,
label: label,
textId: id + '-status',
text: status,
state: statusState,
noAnimation: statusNoAnimation,
skeleton: skeleton,
...statusProps
}), (0, _jsxRuntime.jsxs)("span", {
className: "dnb-dropdown__row",
children: [(0, _jsxRuntime.jsxs)("span", {
className: "dnb-dropdown__shell",
children: [CustomTrigger ? (_react.default.createElement(CustomTrigger, triggerParams)) : (0, _jsxRuntime.jsx)(_Button.default, {
variant: variant,
status: status ? statusState : null,
statusState: statusState,
icon: false,
size: size === 'default' ? 'medium' : size,
ref: setButtonRef,
customContent: (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [!isPopupMenu && (0, _jsxRuntime.jsx)("span", {
className: "dnb-dropdown__text dnb-button__text",
children: (0, _jsxRuntime.jsx)("span", {
className: "dnb-dropdown__text__inner",
children: title
})
}), (0, _jsxRuntime.jsx)("span", {
"aria-hidden": true,
className: 'dnb-dropdown__icon' + (parseFloat(String(selectedItem)) === 0 ? " dnb-dropdown__icon--first" : ""),
children: icon !== false && (0, _jsxRuntime.jsx)(_IconPrimary.default, {
icon: icon || 'chevron_down',
size: iconSize || (size === 'large' ? 'medium' : 'default')
})
})]
}),
role: "combobox",
title: (0, _componentHelper.convertJsxToString)(title) || undefined,
...triggerParams
}), (0, _jsxRuntime.jsx)(_DrawerList.default, {
id: id,
role: handleAsMenu ? 'menu' : 'listbox',
portalClass: portalClass,
listClass: 'dnb-dropdown__list' + (variant === 'tertiary' ? " dnb-dropdown__list--tertiary" : ""),
value: selectedItem,
defaultValue: defaultValue,
scrollable: scrollable,
focusable: focusable,
noAnimation: noAnimation,
noScrollAnimation: noScrollAnimation,
skipPortal: skipPortal,
preventSelection: handleAsMenu,
arrowPosition: arrowPosition || iconPosition || 'right',
keepOpen: keepOpen,
preventClose: preventClose,
independentWidth: independentWidth || isPopupMenu,
isPopup: isPopupMenu,
alignDrawer: align || 'left',
fixedPosition: fixedPosition,
enableBodyLock: enableBodyLock,
disabled: disabled,
maxHeight: maxHeight,
direction: direction,
size: size,
onChange: onChangeHandler,
onSelect: onSelectHandler,
onClose: onCloseHandler
})]
}), suffix && (0, _jsxRuntime.jsx)(_Suffix.default, {
className: "dnb-dropdown__suffix",
id: id + '-suffix',
context: props,
onClick: setHidden,
children: suffix
})]
})]
})]
});
});
function Dropdown({
ref,
buttonRef,
...props
}) {
const id = (0, _useId.default)(props.id);
const {
preventSelection,
children,
data
} = props;
return (0, _jsxRuntime.jsx)(_DrawerListProvider.default, {
...props,
id: id,
data: data || children,
open: false,
tagName: "dnb-dropdown",
ignoreEvents: false,
preventSelection: preventSelection,
children: (0, _jsxRuntime.jsx)(DropdownInstance, {
...props,
id: id,
externalRef: ref,
externalButtonRef: buttonRef
})
});
}
Dropdown.HorizontalItem = _DrawerList.default.HorizontalItem;
(0, _withComponentMarkers.default)(Dropdown, {
_formElement: true,
_supportsSpacingProps: true
});
var _default = exports.default = Dropdown;
//# sourceMappingURL=Dropdown.js.map