UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

300 lines 11.9 kB
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import _extends from "@babel/runtime/helpers/esm/extends"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; var _em, _em2; const _excluded = ["value", "title", "children", "error", "help", "size"]; import "core-js/modules/web.dom-collections.iterator.js"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import React, { useMemo, useCallback } from 'react'; import classnames from 'classnames'; import { convertJsxToString, makeUniqueId } from '../../../../shared/component-helper'; import { ToggleButton, Dropdown, Radio, Autocomplete, HelpButton } from '../../../../components'; import OptionField from '../Option'; import { useFieldProps } from '../../hooks'; import { checkForError } from '../../hooks/useFieldProps'; import { pickSpacingProps } from '../../../../components/flex/utils'; import FieldBlock from '../../FieldBlock'; import { convertCamelCaseProps } from '../../../../shared/helpers/withCamelCaseProps'; import useDataValue from '../../hooks/useDataValue'; function Selection(props) { var _props$autocompletePr; const clearValue = useMemo(() => `clear-option-${makeUniqueId()}`, []); const { id, className, variant = 'dropdown', layout = 'vertical', optionsLayout = 'vertical', placeholder, value, info, warning, error, hasError, disabled, size, emptyValue, width = 'large', htmlAttributes, setHasFocus, handleChange, setDisplayValue, transformSelection, data, dataPath, children, additionalArgs, autocompleteProps, dropdownProps } = useFieldProps(props); const { getValueByPath } = useDataValue(); let dataList = data; if (dataPath) { dataList = getValueByPath(dataPath); } const handleDrawerListChange = useCallback(_ref => { var _data$selectedKey; let { data, value } = _ref; const selectedKey = (_data$selectedKey = data === null || data === void 0 ? void 0 : data.selectedKey) !== null && _data$selectedKey !== void 0 ? _data$selectedKey : value; handleChange === null || handleChange === void 0 ? void 0 : handleChange(!selectedKey || selectedKey === clearValue ? emptyValue : selectedKey, { data }); }, [handleChange, emptyValue, clearValue]); const onChangeHandler = useCallback(_ref2 => { let { value } = _ref2; handleChange === null || handleChange === void 0 ? void 0 : handleChange(value === undefined ? emptyValue : value); }, [handleChange, emptyValue]); const handleShow = useCallback(_ref3 => { let { data } = _ref3; setHasFocus(true, data === null || data === void 0 ? void 0 : data.selectedKey); }, [setHasFocus]); const handleHide = useCallback(_ref4 => { let { data } = _ref4; setHasFocus(false, data === null || data === void 0 ? void 0 : data.selectedKey); }, [setHasFocus]); const cn = classnames(`dnb-forms-field-selection dnb-forms-field-selection__variant--${variant} dnb-forms-field-selection--layout-${layout} dnb-forms-field-selection--options-layout--${optionsLayout}`, className); const fieldBlockProps = _objectSpread({ forId: id, className: cn, disableStatusSummary: true }, pickSpacingProps(props)); const onType = props === null || props === void 0 ? void 0 : (_props$autocompletePr = props.autocompleteProps) === null || _props$autocompletePr === void 0 ? void 0 : _props$autocompletePr.onType; const onTypeAutocompleteHandler = useCallback(event => { const { value } = event; if (typeof onType === 'function') { onType(value === undefined ? emptyValue : value, _objectSpread(_objectSpread({}, event), additionalArgs)); } }, [additionalArgs, emptyValue, onType]); switch (variant) { case 'radio': case 'button': { const Component = variant === 'radio' ? Radio : ToggleButton; const items = renderRadioItems({ id, value, variant, info, warning, htmlAttributes, children, dataList, hasError, iterateOverItems: _ref5 => { let { value: v, label } = _ref5; if (v === value) { setDisplayValue(label); } } }); const additionalFieldBlockProps = { asFieldset: React.Children.count(items) > 1 }; if (!size) { additionalFieldBlockProps.labelHeight = 'small'; } return React.createElement(FieldBlock, _extends({}, fieldBlockProps, additionalFieldBlockProps), React.createElement(Component.Group, { size: size, className: cn, layout_direction: optionsLayout === 'horizontal' ? 'row' : 'column', disabled: disabled, on_change: onChangeHandler, value: String(value !== null && value !== void 0 ? value : '') || undefined }, items)); } case 'autocomplete': case 'dropdown': { var _data$find; const data = renderDropdownItems(dataList, transformSelection).concat(makeOptions(children, transformSelection)).filter(Boolean); const displayValue = (_data$find = data.find(item => item.selectedKey === value)) === null || _data$find === void 0 ? void 0 : _data$find.content; setDisplayValue(displayValue); const sharedProps = _objectSpread(_objectSpread({ id, list_class: 'dnb-forms-field-selection__list', portal_class: 'dnb-forms-field-selection__portal', title: placeholder, value: String(value !== null && value !== void 0 ? value : ''), status: (hasError || checkForError([error, info, warning])) && 'error', disabled }, htmlAttributes), {}, { data, size, on_change: handleDrawerListChange, on_show: handleShow, on_hide: handleHide, stretch: true }); const specificFieldBlockProps = { width }; if (layout === 'horizontal') { specificFieldBlockProps.width = undefined; specificFieldBlockProps.contentWidth = width; } return React.createElement(FieldBlock, _extends({}, fieldBlockProps, specificFieldBlockProps), variant === 'autocomplete' ? React.createElement(Autocomplete, _extends({}, sharedProps, autocompleteProps ? convertCamelCaseProps(Object.freeze(autocompleteProps)) : null, { value: autocompleteProps !== null && autocompleteProps !== void 0 && autocompleteProps.preventSelection ? undefined : value, on_type: onTypeAutocompleteHandler, data: !props.data && !props.dataPath && (autocompleteProps === null || autocompleteProps === void 0 ? void 0 : autocompleteProps.mode) === 'async' ? undefined : data })) : React.createElement(Dropdown, _extends({}, sharedProps, dropdownProps ? convertCamelCaseProps(dropdownProps) : null))); } } } function renderRadioItems(_ref6) { let { id, value: valueProp, variant, info, warning, htmlAttributes, children, dataList, hasError, iterateOverItems } = _ref6; const optionsCount = React.Children.count(children) + ((dataList === null || dataList === void 0 ? void 0 : dataList.length) || 0); const createOption = (props, i) => { const { value, title, children, error, help, size } = props, rest = _objectWithoutProperties(props, _excluded); const label = title !== null && title !== void 0 ? title : children; const suffix = help ? React.createElement(HelpButton, { size: "small", title: convertJsxToString(help.title) }, help.content) : undefined; iterateOverItems === null || iterateOverItems === void 0 ? void 0 : iterateOverItems({ value, label }); const Component = variant === 'radio' ? Radio : ToggleButton; return React.createElement(Component, _extends({ id: optionsCount === 1 ? id : undefined, key: `option-${i}-${id}`, label: variant === 'radio' ? label : undefined, text: variant === 'button' ? label : undefined, value: String(value !== null && value !== void 0 ? value : valueProp) || undefined, status: (hasError || checkForError([error, info, warning])) && 'error', suffix: suffix, size: size }, htmlAttributes, rest)); }; return [...(dataList || []).map((props, i) => { return createOption(props, i); }), ...(mapOptions(children, { createOption }) || [])].filter(Boolean); } export function mapOptions(children, _ref7) { let { createOption } = _ref7; return React.Children.map(children, (child, i) => { if (React.isValidElement(child)) { if (child.type === OptionField) { return createOption(child.props, i); } if (child.props.children) { const nestedChildren = mapOptions(child.props.children, { createOption }); return React.cloneElement(child, child.props, nestedChildren); } } return child; }); } export function makeOptions(children, transformSelection) { return React.Children.map(children, child => { var _child, _child$props, _child$props$children; if (((_child = child) === null || _child === void 0 ? void 0 : (_child$props = _child['props']) === null || _child$props === void 0 ? void 0 : (_child$props$children = _child$props.children) === null || _child$props$children === void 0 ? void 0 : _child$props$children.type) === OptionField) { child = child['props'].children; } if (React.isValidElement(child) && child.type === OptionField) { var _ref8, _props$title, _props$value; const props = child.props; const title = (_ref8 = (_props$title = props.title) !== null && _props$title !== void 0 ? _props$title : props.children) !== null && _ref8 !== void 0 ? _ref8 : _em || (_em = React.createElement("em", null, "Untitled")); const content = props.text ? [title, props.text] : title; const selected_value = transformSelection ? transformSelection(props) : undefined; const selectedKey = String((_props$value = props.value) !== null && _props$value !== void 0 ? _props$value : ''); const disabled = props.disabled; const style = props.style; return { selectedKey, selected_value, content, disabled, style }; } if (child) { return { content: child }; } }); } function renderDropdownItems(data, transformSelection) { return (data === null || data === void 0 ? void 0 : data.map(props => { const { value, title, text, disabled, style } = props; return { selectedKey: value, content: (text ? [title, text] : title) || _em2 || (_em2 = React.createElement("em", null, "Untitled")), selected_value: transformSelection ? transformSelection(props) : undefined, disabled, style }; })) || []; } Selection._supportsSpacingProps = true; export default Selection; //# sourceMappingURL=Selection.js.map