@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
438 lines (437 loc) • 20.8 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.getMessagesFromError = getMessagesFromError;
exports.states = void 0;
require("core-js/modules/web.dom-collections.iterator.js");
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _FieldBlockContext = _interopRequireDefault(require("./FieldBlockContext"));
var _Context = _interopRequireDefault(require("../DataContext/Context"));
var _components = require("../../../components");
var _elements = require("../../../elements");
var _componentHelper = require("../../../shared/component-helper");
var _useId = _interopRequireDefault(require("../../../shared/helpers/useId"));
var _HelpButtonInline = _interopRequireWildcard(require("../../../components/help-button/HelpButtonInline"));
var _SubmitIndicator = _interopRequireDefault(require("../Form/SubmitIndicator/SubmitIndicator"));
var _useSharedState = require("../../../shared/helpers/useSharedState");
var _useTranslation = _interopRequireDefault(require("../hooks/useTranslation"));
var _utils = require("../utils");
var _useIItemNo = require("../Iterate/ItemNo/useIItemNo");
var _br;
const _excluded = ["className", "forId", "layout", "layoutOptions", "composition", "label", "labelDescription", "labelDescriptionInline", "labelSuffix", "labelSrOnly", "help", "asFieldset", "required", "info", "warning", "error", "disableStatusSummary", "fieldState", "disabled", "width", "contentWidth", "labelHeight", "align", "labelSize", "contentClassName", "children"];
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
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 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; }
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); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
const states = exports.states = ['error', 'info', 'warning'];
function FieldBlock(props) {
var _props$id;
const dataContext = (0, _react.useContext)(_Context.default);
const fieldBlockContext = (0, _react.useContext)(_FieldBlockContext.default);
const nestedFieldBlockContext = !(fieldBlockContext !== null && fieldBlockContext !== void 0 && fieldBlockContext.disableStatusSummary) ? fieldBlockContext : null;
const id = (0, _useId.default)((_props$id = props.id) !== null && _props$id !== void 0 ? _props$id : props.forId);
const sharedData = (0, _useSharedState.createSharedState)('field-block-props-' + id);
const _Object$assign = Object.assign({}, sharedData.data, props),
{
className,
forId,
layout = 'vertical',
layoutOptions,
composition,
label: labelProp,
labelDescription,
labelDescriptionInline,
labelSuffix,
labelSrOnly,
help,
asFieldset,
required,
info,
warning,
error,
disableStatusSummary,
fieldState,
disabled,
width,
contentWidth,
labelHeight,
align,
labelSize,
contentClassName,
children
} = _Object$assign,
rest = _objectWithoutProperties(_Object$assign, _excluded);
const hasCustomWidth = /\d(rem)$/.test(String(width));
const hasCustomContentWidth = /\d(rem)$/.test(String(contentWidth));
const infoRef = (0, _react.useRef)();
const warningRef = (0, _react.useRef)();
const errorRef = (0, _react.useRef)();
const blockId = (0, _useId.default)(props.id);
const [salt, forceUpdate] = (0, _react.useReducer)(() => ({}), {});
const mountedFieldsRef = (0, _react.useRef)(new Map());
const fieldStateRef = (0, _react.useRef)(null);
const stateRecordRef = (0, _react.useRef)({});
const fieldStateIdsRef = (0, _react.useRef)(null);
const contentsRef = (0, _react.useRef)(null);
const hasInitiallyErrorPropRef = (0, _react.useRef)(Boolean(error));
const label = (0, _useIItemNo.useIterateItemNo)({
label: labelProp,
labelSuffix,
required
});
const setInternalRecord = (0, _react.useCallback)(props => {
const {
stateId,
identifier,
type
} = props;
if (!stateRecordRef.current[identifier]) {
stateRecordRef.current[identifier] = [];
}
fieldStateIdsRef.current = {
error: null,
warning: null,
info: null
};
const existingIndex = stateRecordRef.current[identifier].findIndex(item => {
return item.stateId === stateId && item.type === type;
});
if (existingIndex > -1) {
stateRecordRef.current[identifier][existingIndex] = _objectSpread(_objectSpread({}, stateRecordRef.current[identifier][existingIndex]), props);
} else {
stateRecordRef.current[identifier].push(props);
}
}, []);
const setBlockRecordNested = nestedFieldBlockContext === null || nestedFieldBlockContext === void 0 ? void 0 : nestedFieldBlockContext.setBlockRecord;
const setBlockRecord = (0, _react.useCallback)(props => {
if (setBlockRecordNested) {
setBlockRecordNested(props);
return;
}
setInternalRecord(props);
forceUpdate();
}, [setBlockRecordNested, setInternalRecord]);
const setFieldState = (0, _react.useCallback)((identifier, fieldState) => {
if (fieldState !== fieldStateRef.current) {
fieldStateRef.current = fieldState;
forceUpdate();
}
}, []);
const showFieldError = (0, _react.useCallback)((identifier, show) => {
if (nestedFieldBlockContext) {
nestedFieldBlockContext.showFieldError(identifier, show);
return;
}
if (stateRecordRef.current[identifier]) {
stateRecordRef.current[identifier] = stateRecordRef.current[identifier].map(item => {
if (item.showInitially) {
return item;
}
return _objectSpread(_objectSpread({}, item), {}, {
show
});
});
forceUpdate();
}
}, [nestedFieldBlockContext]);
const statusContent = (0, _react.useMemo)(() => {
if (typeof error !== 'undefined' || errorRef.current && !error) {
errorRef.current = error;
setInternalRecord({
identifier: blockId,
showInitially: hasInitiallyErrorPropRef.current,
type: 'error',
content: error
});
}
if (typeof warning !== 'undefined' || warningRef.current !== warning) {
warningRef.current = warning;
setInternalRecord({
identifier: blockId,
showInitially: true,
type: 'warning',
content: warning
});
}
if (typeof info !== 'undefined' || infoRef.current !== info) {
infoRef.current = info;
setInternalRecord({
identifier: blockId,
showInitially: true,
type: 'info',
content: info
});
}
const statesWithMessages = Object.entries(stateRecordRef.current).flatMap(_ref => {
let [identifier, states] = _ref;
return states.map(props => {
return _objectSpread({
identifier
}, props);
});
}).reduce((acc, cur) => {
const existing = acc.find(item => {
return item.type === cur.type;
});
const messages = getMessagesFromError(cur).map(message => {
return _objectSpread(_objectSpread({}, cur), {}, {
message
});
});
if (existing) {
existing.messages.push(...messages);
} else {
acc.push(_objectSpread(_objectSpread({}, cur), {}, {
content: undefined,
messages
}));
}
return acc;
}, []);
return states.reduce((acc, type) => {
const id = `${props.id || forId || blockId}-form-status--${type}`;
acc[type] = {
id,
label,
state: type === 'warning' ? 'warn' : type,
width_element: contentsRef,
no_animation: process.env.NODE_ENV === 'test' ? true : typeof globalThis !== 'undefined' ? globalThis.IS_TEST === true : false
};
const found = statesWithMessages.find(item => {
return item.type === type;
});
if (found !== null && found !== void 0 && found.messages) {
const messages = found.messages.map(msg => {
if (msg.type === 'error') {
if (!msg.showInitially && !msg.show) {
msg.message = null;
}
}
return msg;
}).filter(_ref2 => {
let {
message
} = _ref2;
return message;
}).reduce((acc, msg, i, arr) => {
const existingIndex = arr.findIndex(item => {
return (0, _componentHelper.convertJsxToString)(item.message) === (0, _componentHelper.convertJsxToString)(msg.message);
});
if (existingIndex === i) {
acc.push(msg);
}
return acc;
}, []);
if (messages.length > 0) {
acc[type] = _objectSpread(_objectSpread({}, acc[type]), {}, {
children: _react.default.createElement(CombineMessages, {
type: type,
messages: messages
})
});
fieldStateIdsRef.current[type] = id;
} else {
fieldStateIdsRef.current[type] = undefined;
}
}
return acc;
}, salt);
}, [error, warning, info, salt, setInternalRecord, blockId, props.id, forId, label]);
(0, _react.useEffect)(() => {
if (!nestedFieldBlockContext) {
showFieldError(blockId, Boolean(error));
}
}, [error, blockId, showFieldError, nestedFieldBlockContext]);
(0, _react.useEffect)(() => () => {
mountedFieldsRef.current = new Map();
stateRecordRef.current = {};
}, []);
const mainClasses = (0, _classnames.default)('dnb-forms-field-block', className, composition && `dnb-forms-field-block__composition dnb-forms-field-block__composition--${composition === true ? 'horizontal' : composition}`, width && `dnb-forms-field-block--width-${hasCustomWidth ? 'custom' : width}`, contentWidth && `dnb-forms-field-block--content-width-${hasCustomContentWidth ? 'custom' : contentWidth}`, labelHeight && `dnb-forms-field-block--label-height-${labelHeight}`);
const gridClasses = `dnb-forms-field-block__grid dnb-forms-field-block--layout-${layout}`;
const enableFieldset = useEnableFieldset({
label,
asFieldset,
children,
nestedFieldBlockContext
});
const labelProps = {
id: `${id}-label`,
className: 'dnb-forms-field-block__label',
element: enableFieldset ? 'legend' : 'label',
forId: enableFieldset ? undefined : forId,
srOnly: labelSrOnly,
space: 0,
size: labelSize,
disabled
};
const mainStyle = (0, _react.useMemo)(() => {
var _lO$minWidth, _lO$maxWidth;
const style = {};
if (hasCustomWidth) {
style['--dnb-forms-field-block-width'] = width;
}
if (hasCustomContentWidth) {
style['--dnb-forms-field-block-content-width'] = contentWidth;
}
const lO = layoutOptions || {};
const min = getFieldWidth((_lO$minWidth = lO.minWidth) !== null && _lO$minWidth !== void 0 ? _lO$minWidth : lO.width);
const max = getFieldWidth((_lO$maxWidth = lO.maxWidth) !== null && _lO$maxWidth !== void 0 ? _lO$maxWidth : lO.width);
if (typeof min === 'string') {
style['--dnb-forms-field-block-layout-width-min'] = min;
}
if (typeof max === 'string') {
style['--dnb-forms-field-block-layout-width-max'] = max;
}
return style;
}, [contentWidth, hasCustomContentWidth, hasCustomWidth, layoutOptions, width]);
if (dataContext !== null && dataContext !== void 0 && dataContext.prerenderFieldProps) {
return null;
}
const hasLabelDescription = isFragment(labelDescription) ? fragmentHasChildren(labelDescription) && !fragmentHasOnlyUndefinedChildren(labelDescription) : labelDescription;
const hasHelp = (help === null || help === void 0 ? void 0 : help.title) || (help === null || help === void 0 ? void 0 : help.content);
return _react.default.createElement(_FieldBlockContext.default.Provider, {
value: {
setBlockRecord,
setFieldState,
showFieldError,
hasErrorProp: Boolean(error),
fieldStateIdsRef,
mountedFieldsRef,
composition,
disableStatusSummary
}
}, _react.default.createElement(_components.Space, _extends({
element: enableFieldset ? 'fieldset' : 'div',
style: mainStyle,
className: mainClasses
}, rest), _react.default.createElement("div", {
className: gridClasses
}, (label || labelDescription || hasHelp) && _react.default.createElement(_components.FormLabel, labelProps, _react.default.createElement("span", null, label && _react.default.createElement("span", {
className: "dnb-forms-field-block__label__content"
}, label), hasHelp && _react.default.createElement(_HelpButtonInline.default, {
contentId: `${id}-help`,
help: help
}), hasLabelDescription && !labelDescriptionInline && (_br || (_br = _react.default.createElement("br", null))), hasLabelDescription && _react.default.createElement("span", {
className: "dnb-forms-field-block__label__description"
}, labelDescription))), hasHelp && _react.default.createElement(_HelpButtonInline.HelpButtonInlineContent, {
contentId: `${id}-help`,
className: "dnb-forms-field-block__help",
help: help,
breakout: layout === 'vertical' && !(nestedFieldBlockContext !== null && nestedFieldBlockContext !== void 0 && nestedFieldBlockContext.composition),
outset: layout !== 'horizontal'
}), _react.default.createElement("div", {
className: 'dnb-forms-field-block__status' + (contentWidth && contentWidth !== 'small' && contentWidth !== 'medium' && !(parseFloat(contentWidth) <= 11) ? ` dnb-forms-field-block__contents--width-${hasCustomContentWidth ? 'custom' : contentWidth}` : "")
}, _react.default.createElement(_components.FormStatus, statusContent === null || statusContent === void 0 ? void 0 : statusContent.error), _react.default.createElement(_components.FormStatus, statusContent === null || statusContent === void 0 ? void 0 : statusContent.warning), _react.default.createElement(_components.FormStatus, statusContent === null || statusContent === void 0 ? void 0 : statusContent.info)), _react.default.createElement("div", {
className: (0, _classnames.default)('dnb-forms-field-block__contents', contentClassName, contentWidth && `dnb-forms-field-block__contents--width-${hasCustomContentWidth ? 'custom' : contentWidth}`, align && `dnb-forms-field-block__contents--align-${align}`),
ref: contentsRef
}, children), _react.default.createElement(_SubmitIndicator.default, {
state: fieldState !== null && fieldState !== void 0 ? fieldState : fieldStateRef.current,
className: "dnb-forms-field-block__indicator dnb-forms-submit-indicator--inline-wrap"
}))));
}
function useEnableFieldset(_ref3) {
let {
label,
asFieldset,
children,
nestedFieldBlockContext
} = _ref3;
return (0, _react.useMemo)(() => {
if (asFieldset === false) {
return false;
}
let result = asFieldset;
if (label && !result && !nestedFieldBlockContext) {
let count = 0;
(0, _componentHelper.findElementInChildren)(children, child => {
var _child$props, _child$type;
if (child !== null && child !== void 0 && (_child$props = child.props) !== null && _child$props !== void 0 && _child$props.label || (child === null || child === void 0 ? void 0 : (_child$type = child.type) === null || _child$type === void 0 ? void 0 : _child$type['_formElement']) === true) {
count++;
}
if (count > 1) {
return result = true;
}
});
}
return Boolean(result);
}, [asFieldset, children, label, nestedFieldBlockContext]);
}
function CombineMessages(_ref4) {
let {
type,
messages
} = _ref4;
const translations = (0, _useTranslation.default)().Field;
if (messages.length === 1) {
return _react.default.createElement(_react.default.Fragment, null, messages[0].message);
}
return _react.default.createElement(_react.default.Fragment, null, type === 'error' ? translations.errorSummary : translations.stateSummary, _react.default.createElement(_elements.Ul, null, messages.map((_ref5, i) => {
let {
message
} = _ref5;
return _react.default.createElement(_elements.Li, {
key: i
}, message);
})));
}
function getMessage(error) {
if (error instanceof _utils.FormError) {
var _error$formattedMessa;
return (_error$formattedMessa = error.formattedMessage) !== null && _error$formattedMessa !== void 0 ? _error$formattedMessa : error.message;
}
return error.message;
}
function getMessagesFromError(item) {
const {
content
} = item;
if (content instanceof _utils.FormError && Array.isArray(content.errors)) {
return content.errors.map(content => {
return getMessage(content);
});
}
if (Array.isArray(content)) {
return content.map(content => {
return content instanceof _utils.FormError || content instanceof Error ? getMessage(content) : content;
});
}
if (content instanceof _utils.FormError || content instanceof Error) {
return [getMessage(content)];
}
return [(_react.default.isValidElement(content) ? content : content === null || content === void 0 ? void 0 : content.toString()) || content];
}
function isFragment(fragment) {
return _react.default.isValidElement(fragment) && fragment.type === _react.default.Fragment;
}
function fragmentHasChildren(fragment) {
return _react.default.isValidElement(fragment) && _react.default.Children.count(fragment.props.children) > 0;
}
function fragmentHasOnlyUndefinedChildren(fragment) {
const isUndefined = child => child === undefined;
return _react.default.isValidElement(fragment) && _react.default.Children.toArray(fragment.props.children).every(isUndefined);
}
FieldBlock._supportsSpacingProps = true;
var _default = exports.default = FieldBlock;
function getFieldWidth(width) {
switch (width) {
case 'small':
return 'var(--forms-field-width--small)';
case 'medium':
return 'var(--forms-field-width--medium)';
case 'large':
return 'var(--forms-field-width--large)';
}
return width;
}
//# sourceMappingURL=FieldBlock.js.map