@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
525 lines (524 loc) • 20.3 kB
JavaScript
"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