UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

525 lines (524 loc) 20.3 kB
"use client"; import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; const _excluded = ["title", "state", "size", "variant", "className", "stretch", "shellSpace", "text_id", "show", "no_animation", "label", "status_id", "globalStatus", "id", "text", "icon", "icon_size", "skeleton", "children", "role"]; import "core-js/modules/es.string.replace.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 from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { useTheme, Context } from '../../shared'; import { isTrue, makeUniqueId, validateDOMAttributes, processChildren, extendPropsWithContextInClassComponent } from '../../shared/component-helper'; import HeightAnimation from '../height-animation/HeightAnimation'; import { spacingPropTypes, createSpacingClasses } from '../space/SpacingHelper'; import Icon from '../icon/Icon'; import GlobalStatusProvider from '../global-status/GlobalStatusProvider'; import { skeletonDOMAttributes, createSkeletonClass } from '../skeleton/SkeletonHelper'; import { pickFormElementProps } from '../../shared/helpers/filterValidProps'; import ui from '../../style/themes/theme-ui/properties'; import sbanken from '../../style/themes/theme-sbanken/properties'; const properties = { ui, sbanken }; export default class FormStatus extends React.PureComponent { static getContent(props) { if (props.text) { if (isTrue(props.text)) { return null; } return props.text; } return processChildren(props); } static correctStatus(state) { switch (state) { case 'information': state = 'info'; break; case 'warning': state = 'warn'; break; } return state; } static getIcon(_ref) { let { state, icon, icon_size } = _ref; if (typeof icon !== 'string') { return icon; } let IconToLoad = icon; switch (FormStatus.correctStatus(state)) { case 'info': case 'success': IconToLoad = InfoIcon; break; case 'warn': IconToLoad = WarnIcon; break; case 'marketing': IconToLoad = MarketingIcon; break; case 'error': default: IconToLoad = ErrorIcon; } return React.createElement(Icon, { icon: React.createElement(IconToLoad, { title: null, state: state }), size: icon_size, inheritColor: false }); } static getDerivedStateFromProps(props, state) { if (state._id !== props.id && props.id) { state.id = props.id; } state._id = props.id; return state; } constructor(props, context) { var _props$globalStatus, _context$FormStatus, _context$FormStatus$g, _context$FormRow, _context$FormRow$glob, _context$formElement, _context$formElement$; super(props); _defineProperty(this, "state", { id: null }); _defineProperty(this, "init", () => { if (this._isMounted) { this._globalStatus.isReady(); this.updateWidth(); this.fillCache(); } }); _defineProperty(this, "updateWidth", () => { if (this._ref.current) { const { width_element, width_selector } = this.props; setMaxWidthToElement({ element: this._ref.current, widthElement: width_element && width_element.current, widthSelector: width_selector }); } }); this.state.id = props.id || makeUniqueId(); this._globalStatus = GlobalStatusProvider.init((props === null || props === void 0 ? void 0 : (_props$globalStatus = props.globalStatus) === null || _props$globalStatus === void 0 ? void 0 : _props$globalStatus.id) || (context === null || context === void 0 ? void 0 : (_context$FormStatus = context.FormStatus) === null || _context$FormStatus === void 0 ? void 0 : (_context$FormStatus$g = _context$FormStatus.globalStatus) === null || _context$FormStatus$g === void 0 ? void 0 : _context$FormStatus$g.id) || (context === null || context === void 0 ? void 0 : (_context$FormRow = context.FormRow) === null || _context$FormRow === void 0 ? void 0 : (_context$FormRow$glob = _context$FormRow.globalStatus) === null || _context$FormRow$glob === void 0 ? void 0 : _context$FormRow$glob.id) || (context === null || context === void 0 ? void 0 : (_context$formElement = context.formElement) === null || _context$formElement === void 0 ? void 0 : (_context$formElement$ = _context$formElement.globalStatus) === null || _context$formElement$ === void 0 ? void 0 : _context$formElement$.id) || 'main', provider => { if (this.props.state === 'error' && this.isReadyToGetVisible()) { const { state, text, children, globalStatus, label } = this.getProps(context); provider.add(_objectSpread({ state, status_id: this.getStatusId(), item: { item_id: this.state.id, text: (globalStatus === null || globalStatus === void 0 ? void 0 : globalStatus.message) || text || children, status_anchor_label: label, status_anchor_url: true } }, globalStatus)); } }); this._ref = React.createRef(); } componentDidMount() { this._isMounted = true; if (document.readyState === 'complete') { this.init(); } else if (typeof window !== 'undefined') { window.addEventListener('load', this.init); } if (typeof window !== 'undefined') { window.addEventListener('resize', this.updateWidth); } } fillCache() { const shouldAnimate = this.shouldAnimate(); const content = shouldAnimate && FormStatus.getContent(this.props); if (content && content !== this.contentCache) { this.contentCache = content; } const state = shouldAnimate && FormStatus.correctStatus(this.props.state); if (state) { this.stateCache = state; } } componentWillUnmount() { this._isMounted = false; const status_id = this.getStatusId(); this._globalStatus.remove(status_id); if (typeof window !== 'undefined') { window.removeEventListener('load', this.init); window.removeEventListener('resize', this.updateWidth); } } componentDidUpdate(prevProps) { var _prevProps$globalStat; const { state, show, text, globalStatus, children, label } = this.getProps(); if (prevProps.text !== text || prevProps.children !== children || prevProps.show !== show || ((_prevProps$globalStat = prevProps.globalStatus) === null || _prevProps$globalStat === void 0 ? void 0 : _prevProps$globalStat.show) !== (globalStatus === null || globalStatus === void 0 ? void 0 : globalStatus.show) || prevProps.state !== state) { this.fillCache(); if (state === 'error') { const status_id = this.getStatusId(); if (isTrue(show)) { this._globalStatus.update(status_id, _objectSpread({ state, status_id, item: { item_id: this.state.id, text: (globalStatus === null || globalStatus === void 0 ? void 0 : globalStatus.message) || text || children, status_anchor_label: label, status_anchor_url: true } }, globalStatus), { preventRestack: true }); } else if (!FormStatus.getContent(this.props)) { const status_id = this.getStatusId(); this._globalStatus.remove(status_id); } } if (this.isReadyToGetVisible()) { this.updateWidth(); } } } getProps() { let context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.context; return extendPropsWithContextInClassComponent(this.props, FormStatus.defaultProps, { skeleton: context === null || context === void 0 ? void 0 : context.skeleton }, pickFormElementProps(context === null || context === void 0 ? void 0 : context.FormRow), pickFormElementProps(context === null || context === void 0 ? void 0 : context.formElement), context === null || context === void 0 ? void 0 : context.FormStatus); } getStatusId() { return `${this.state.id}-gs`; } shouldAnimate() { return this.props.no_animation === false; } isReadyToGetVisible() { let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; return isTrue(props.show) && FormStatus.getContent(props) ? true : false; } render() { const props = this.getProps(); const { title, state: rawState, size, variant, className, stretch, shellSpace, text_id, show, no_animation, label, status_id, globalStatus, id, text, icon, icon_size, skeleton, children, role } = props, rest = _objectWithoutProperties(props, _excluded); const state = FormStatus.correctStatus(rawState) || this.stateCache; const iconToRender = FormStatus.getIcon({ state, icon, icon_size }); const contentToRender = FormStatus.getContent(this.props); const hasStringContent = typeof contentToRender === 'string' && contentToRender.length > 0; const params = _objectSpread({ className: classnames(`dnb-form-status dnb-form-status__size--${size}`, createSpacingClasses(props), className, state && `dnb-form-status--${state}`, variant && `dnb-form-status__variant--${variant}`, stretch && 'dnb-form-status--stretch', hasStringContent && 'dnb-form-status--has-content'), id: !String(id).startsWith('null') ? this.state.id : null, title, role }, rest); if (!role) { switch (state) { case 'info': params.role = 'status'; break; default: params.role = 'alert'; } } const textParams = { className: classnames('dnb-form-status__text', createSkeletonClass('font', skeleton, this.context)), id: !String(text_id).startsWith('null') ? text_id : null }; const shellParams = { className: classnames('dnb-form-status__shell', createSpacingClasses({ space: shellSpace })) }; skeletonDOMAttributes(params, skeleton, this.context); validateDOMAttributes(this.props, params); validateDOMAttributes(null, textParams); return React.createElement(HeightAnimation, _extends({ element: "span", open: this.isReadyToGetVisible(), animate: this.shouldAnimate(), duration: 600 }, params, { innerRef: this._ref }), React.createElement("span", shellParams, iconToRender, React.createElement("span", textParams, contentToRender || this.contentCache))); } } _defineProperty(FormStatus, "contextType", Context); _defineProperty(FormStatus, "defaultProps", { id: null, title: null, show: true, text: null, globalStatus: null, label: null, icon: 'error', icon_size: 'medium', size: 'default', variant: null, state: 'error', attributes: null, text_id: null, width_selector: null, width_element: null, no_animation: null, skeleton: null, stretch: null, role: null, className: null, children: null }); process.env.NODE_ENV !== "production" ? FormStatus.propTypes = _objectSpread(_objectSpread({ id: PropTypes.string, title: PropTypes.string, show: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), text: PropTypes.oneOfType([PropTypes.string, PropTypes.bool, PropTypes.func, PropTypes.node]), label: PropTypes.node, icon: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.node]), icon_size: PropTypes.string, state: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.oneOf(['error', 'warn', 'info', 'marketing'])]), variant: PropTypes.oneOf(['flat', 'outlined']), size: PropTypes.oneOf(['default', 'large']), globalStatus: PropTypes.shape({ id: PropTypes.string, message: PropTypes.oneOfType([PropTypes.string, PropTypes.node]) }), attributes: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), text_id: PropTypes.string, width_selector: PropTypes.string, width_element: PropTypes.object, no_animation: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), skeleton: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), stretch: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), role: PropTypes.string }, spacingPropTypes), {}, { className: PropTypes.string, children: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.node]) }) : void 0; export const ErrorIcon = props => { var _useTheme; const { title = 'error' } = props || {}; const isSbankenTheme = ((_useTheme = useTheme()) === null || _useTheme === void 0 ? void 0 : _useTheme.name) === 'sbanken'; const fill = isSbankenTheme ? properties.sbanken['--sb-color-magenta'] : properties.ui['--color-fire-red']; const line = isSbankenTheme ? properties.sbanken['--sb-color-magenta-light-2'] : properties.ui['--color-white']; return React.createElement("svg", _extends({ width: "24", height: "24", viewBox: "0 0 24 24", fill: "none" }, props), React.createElement("title", null, title), React.createElement("path", { d: "M23.625 17.864A3.547 3.547 0 0120.45 23H3.548a3.546 3.546 0 01-3.172-5.136l8.45-14.902a3.548 3.548 0 016.347 0l8.452 14.902z", fill: fill }), React.createElement("path", { d: "M12 16.286a1.286 1.286 0 100 2.572 1.286 1.286 0 000-2.572z", fill: line }), React.createElement("path", { d: "M12 13.818v-5", stroke: line, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })); }; process.env.NODE_ENV !== "production" ? ErrorIcon.propTypes = { title: PropTypes.string } : void 0; export const WarnIcon = props => { var _useTheme2; const { title = 'error' } = props || {}; const isSbankenTheme = ((_useTheme2 = useTheme()) === null || _useTheme2 === void 0 ? void 0 : _useTheme2.name) === 'sbanken'; const fill = isSbankenTheme ? properties.sbanken['--sb-color-yellow-dark'] : properties.ui['--color-accent-yellow']; const line = isSbankenTheme ? properties.sbanken['--sb-color-black'] : properties.ui['--color-black-80']; return React.createElement("svg", _extends({ width: "24", height: "24", viewBox: "0 0 24 24", fill: "none" }, props), React.createElement("title", null, title), React.createElement("path", { d: "M23.625 17.864A3.547 3.547 0 0120.45 23H3.548a3.546 3.546 0 01-3.172-5.136l8.45-14.902a3.548 3.548 0 016.347 0l8.452 14.902z", fill: fill }), React.createElement("path", { d: "M12 16.286a1.286 1.286 0 100 2.572 1.286 1.286 0 000-2.572z", fill: line }), React.createElement("path", { d: "M12 13.818v-5", stroke: line, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })); }; process.env.NODE_ENV !== "production" ? WarnIcon.propTypes = { title: PropTypes.string } : void 0; export const InfoIcon = props => { var _useTheme3; const { title = 'info' } = props || {}; const isSbankenTheme = ((_useTheme3 = useTheme()) === null || _useTheme3 === void 0 ? void 0 : _useTheme3.name) === 'sbanken'; let fill = isSbankenTheme ? properties.sbanken['--sb-color-green-dark-2'] : properties.ui['--color-sea-green']; if (props && (props === null || props === void 0 ? void 0 : props.state) === 'success') { fill = isSbankenTheme ? properties.sbanken['--sb-color-green-dark-3'] : properties.ui['--color-summer-green']; } const line = isSbankenTheme ? properties.sbanken['--sb-color-green-light-2'] : properties.ui['--color-white']; return React.createElement("svg", _extends({ width: "24", height: "24", viewBox: "0 0 24 24", fill: "none" }, props), React.createElement("title", null, title), React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M11.268 0a11.25 11.25 0 105.566 21.017l6.112 2.91a.75.75 0 001-1l-2.911-6.112A11.234 11.234 0 0011.268 0z", fill: fill }), React.createElement("circle", { cx: "11", cy: "6.5", r: ".5", fill: "#fff", stroke: line }), React.createElement("path", { d: "M13.75 16H13a1.5 1.5 0 01-1.5-1.5v-3.75a.75.75 0 00-.75-.75H10", stroke: line, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })); }; process.env.NODE_ENV !== "production" ? InfoIcon.propTypes = { title: PropTypes.string } : void 0; export const MarketingIcon = props => { var _useTheme4; const { title = 'marketing' } = props || {}; const isSbankenTheme = ((_useTheme4 = useTheme()) === null || _useTheme4 === void 0 ? void 0 : _useTheme4.name) === 'sbanken'; const fill = isSbankenTheme ? properties.sbanken['--sb-color-violet-light'] : properties.ui['--color-black-80']; return React.createElement("svg", _extends({ width: "24", height: "24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, props), React.createElement("title", null, title), React.createElement("path", { d: "M6 15.25H4.5c-2.042 0-3.75-1.707-3.75-3.75S2.458 7.75 4.5 7.75H6v7.5ZM7.5 15.25c4.801 0 8.846 1.897 12.75 4.5V3.25c-3.904 2.603-7.949 4.5-12.75 4.5v7.5ZM23.25 10a.75.75 0 0 0-1.5 0h1.5Zm-1.5 3a.75.75 0 0 0 1.5 0h-1.5ZM8.483 21.043a.75.75 0 1 0 1.034-1.086l-1.034 1.086ZM21.75 10v3h1.5v-3h-1.5ZM6 15.25a8.058 8.058 0 0 0 2.483 5.793l1.034-1.086A6.559 6.559 0 0 1 7.5 15.25H6Z", fill: fill })); }; process.env.NODE_ENV !== "production" ? MarketingIcon.propTypes = { title: PropTypes.string } : void 0; export function setMaxWidthToElement(_ref2) { let { element, id = null, widthElement = null, widthSelector = null } = _ref2; if (!(element && typeof window !== 'undefined')) { return; } try { var _id; if (!id && !widthSelector) { id = element.getAttribute('id'); } widthSelector = widthSelector || ((_id = id) === null || _id === void 0 ? void 0 : _id.replace('-form-status', '')) || id; let width = sumElementWidth({ widthElement, widthSelector }); if (width > 40) { const maxWidth = 30 * 16; if (width < maxWidth) { width = maxWidth; } const remWidth = `${width / 16}rem`; const style = window.getComputedStyle(element); const hasCustomWidth = element.style.maxWidth ? false : style.minWidth !== '' && style.minWidth !== 'auto' || style.maxWidth !== '' && style.maxWidth !== 'none'; if (!hasCustomWidth) { element.style.maxWidth = remWidth; } } } catch (e) {} } function sumElementWidth(_ref3) { let { widthElement, widthSelector } = _ref3; let width = 0; if (typeof document === 'undefined') { return width; } try { const ids = widthElement ? [widthElement] : widthSelector.split(/, |,/g); width = ids.reduce((acc, cur) => { const elem = typeof cur === 'string' ? cur[0] === '.' ? document.querySelector(cur) : document.getElementById(cur) : cur; let width = elem && elem.offsetWidth || window.getComputedStyle(elem).width; if (/em|rem/.test(width)) { width = parseFloat(width) * 16; } if (width > 0) { if (acc > 0) { acc += 16; } acc += width; } return acc; }, width); } catch (e) {} return width; } FormStatus._supportsSpacingProps = true; //# sourceMappingURL=FormStatus.js.map