UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

495 lines (494 loc) 20.6 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _classnames = _interopRequireDefault(require("classnames")); var _Context = _interopRequireDefault(require("../../shared/Context.js")); var _componentHelper = require("../../shared/component-helper.js"); var _HeightAnimation = _interopRequireDefault(require("../height-animation/HeightAnimation.js")); var _SkeletonHelper = require("../skeleton/SkeletonHelper.js"); var _SpacingHelper = require("../space/SpacingHelper.js"); var _Hr2 = _interopRequireDefault(require("../../elements/hr/Hr.js")); var _GlobalStatusController = _interopRequireWildcard(require("./GlobalStatusController.js")); var _GlobalStatusProvider = _interopRequireDefault(require("./GlobalStatusProvider.js")); var _Icon = _interopRequireDefault(require("../icon/Icon.js")); var _FormStatus = require("../form-status/FormStatus.js"); var _Section = _interopRequireDefault(require("../section/Section.js")); var _Button = _interopRequireDefault(require("../button/Button.js")); var _Hr; 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 }; } 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 _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); } class GlobalStatus extends _react.default.PureComponent { static getIcon({ state, icon, icon_size }) { if (typeof icon === 'string') { let IconToLoad = icon; switch (state) { case 'info': case 'information': case 'success': IconToLoad = _FormStatus.InfoIcon; break; case 'warning': case 'warn': IconToLoad = _FormStatus.WarnIcon; break; case 'error': default: IconToLoad = _FormStatus.ErrorIcon; } icon = _react.default.createElement(_Icon.default, { icon: _react.default.createElement(IconToLoad, { state: state }), size: icon_size, inheritColor: false }); } return icon; } static getDerivedStateFromProps(props, state) { if (state._items !== props.items) { state.globalStatus = _GlobalStatusProvider.default.combineMessages([state.globalStatus, props]); } state._items = props.items; return state; } constructor(props) { super(props); _defineProperty(this, "state", { globalStatus: null, isActive: false }); _defineProperty(this, "isPassive", () => { return this.props.show !== 'auto' && (0, _componentHelper.isTrue)(this.props.show) === false; }); _defineProperty(this, "setVisible", () => { if (this.isPassive()) { return; } this.setState({ isActive: true }); }); _defineProperty(this, "setHidden", () => { this.setState({ isActive: false }); }); _defineProperty(this, "onKeyDownHandler", e => { switch ((0, _componentHelper.keycode)(e)) { case 'escape': case 'esc': e.preventDefault(); this.closeHandler(); break; } }); _defineProperty(this, "closeHandler", () => { this.provider.add({ status_id: 'internal-close', show: false }); if (this.initialActiveElement) { try { this.initialActiveElement.focus(); this.initialActiveElement = null; } catch (e) { (0, _componentHelper.warn)(e); } } (0, _componentHelper.dispatchCustomElementEvent)(this._globalStatus, 'on_hide', this._globalStatus); }); _defineProperty(this, "gotoItem", (event, item) => { event.persist(); const keyCode = (0, _componentHelper.keycode)(event); if (item.item_id && typeof document !== 'undefined' && typeof window !== 'undefined' && keyCode === 'space' || keyCode === 'enter' || typeof keyCode === 'undefined') { event.preventDefault(); try { const element = document.getElementById(item.item_id); if (!element) { return; } isElementVisible(element, elem => { try { elem.addEventListener('blur', e => { if (e.target.classList) { e.target.removeAttribute('tabindex'); } }); elem.classList.add('dnb-no-focus'); elem.setAttribute('tabindex', '-1'); elem.focus({ preventScroll: true }); } catch (e) { (0, _componentHelper.warn)(e); } }); if (typeof element.scrollIntoView === 'function') { element.scrollIntoView({ block: 'center', behavior: 'smooth' }); } } catch (e) { (0, _componentHelper.warn)(e); } } }); _defineProperty(this, "itemsRenderHandler", ({ status_anchor_text, lang }) => (item, i) => { const text = item !== null && item !== void 0 && item.text ? item.text : typeof item === 'string' ? item : null; if (!text) { return null; } const id = item.id || item.item_id ? `${item.item_id}-${i}` : (0, _componentHelper.makeUniqueId)(); let anchorText = status_anchor_text; if (_react.default.isValidElement(item.status_anchor_label)) { anchorText = _react.default.createElement(_react.default.Fragment, null, typeof status_anchor_text === 'string' ? status_anchor_text.replace('%s', '').trim() : status_anchor_text, ' ', item.status_anchor_label); } else { anchorText = String(item.status_anchor_text || status_anchor_text).replace('%s', item.status_anchor_label || '').replace(/[: ]$/g, ''); } const useAutolink = item.item_id && (0, _componentHelper.isTrue)(item.status_anchor_url); return _react.default.createElement("li", { key: i }, _react.default.createElement("p", { id: id, className: "dnb-p" }, text), item && (useAutolink || item.status_anchor_url) && _react.default.createElement("a", { className: "dnb-anchor", "aria-describedby": id, lang: lang, href: useAutolink ? `#${item.item_id}` : item.status_anchor_url, onClick: e => this.gotoItem(e, item), onKeyDown: e => this.gotoItem(e, item) }, anchorText)); }); _defineProperty(this, "onAnimationStart", state => { this.setState({ isAnimating: true }); switch (state) { case 'opening': this.scrollToStatus(); } }); _defineProperty(this, "onAnimationEnd", state => { switch (state) { case 'opened': this.setFocus(); (0, _componentHelper.dispatchCustomElementEvent)(this._globalStatus, 'on_open', this._globalStatus); break; case 'adjusted': if (!(0, _componentHelper.isTrue)(this.props.omit_set_focus_on_update)) { this.setFocus(); } (0, _componentHelper.dispatchCustomElementEvent)(this._globalStatus, 'on_adjust', this._globalStatus); break; case 'closed': (0, _componentHelper.dispatchCustomElementEvent)(this._globalStatus, 'on_close', this._globalStatus); break; } }); _defineProperty(this, "onOpen", isOpened => { if (isOpened) { (0, _componentHelper.dispatchCustomElementEvent)(this._globalStatus, 'on_show', this._globalStatus); } }); this._wrapperRef = _react.default.createRef(); this.provider = _GlobalStatusProvider.default.create(props.id); this.state.globalStatus = this._globalStatus = this.provider.init(props); if ((0, _componentHelper.isTrue)(props.show)) { this.state.isActive = true; } this.provider.onUpdate(globalStatus => { if (globalStatus.on_close) { this._globalStatus = globalStatus; } this.setState({ globalStatus }); if ((0, _componentHelper.isTrue)(this.props.autoclose) && this._hadContent && !this.hasContent(globalStatus) && !(0, _componentHelper.isTrue)(this.props.show) || typeof globalStatus.show !== 'undefined' && !(0, _componentHelper.isTrue)(globalStatus.show)) { this.setHidden(); } else if ((0, _componentHelper.isTrue)(this.props.show) || typeof globalStatus.show !== 'undefined' && (0, _componentHelper.isTrue)(globalStatus.show)) { this._hadContent = this.hasContent(globalStatus); this.setVisible(); } }); this.initialActiveElement = null; } componentWillUnmount() { clearTimeout(this._scrollToStatusTimeout); this.provider.empty(); } componentDidUpdate(prevProps) { if (prevProps !== this.props) { const globalStatus = (0, _componentHelper.extendPropsWithContextInClassComponent)(this.props, GlobalStatus.defaultProps, this.context.globalStatus); this.setState({ globalStatus }); } if (prevProps.show !== this.props.show) { if ((0, _componentHelper.isTrue)(this.props.show)) { this.setVisible(); } else { this.setHidden(); } } } hasContent(globalStatus) { var _globalStatus$items; return Boolean(((_globalStatus$items = globalStatus.items) === null || _globalStatus$items === void 0 ? void 0 : _globalStatus$items.length) > 0 || globalStatus.text); } correctStatus(state) { switch (state) { case 'information': state = 'info'; break; } return state; } setFocus() { if (typeof document !== 'undefined' && document.activeElement !== this._wrapperRef.current) { this.initialActiveElement = document.activeElement; } if (this._wrapperRef.current && !(0, _componentHelper.isTrue)(this.props.omit_set_focus)) { this._wrapperRef.current.focus({ preventScroll: true }); } } async scrollToStatus(isDone = null) { if (typeof window === 'undefined' || (0, _componentHelper.isTrue)(this.state.globalStatus.autoscroll) === false) { return; } try { const element = this._wrapperRef.current; this._scrollToStatusTimeout = isElementVisible(element, isDone); if (element && typeof element.scrollIntoView === 'function') { await wait(1); element.scrollIntoView({ block: 'center', behavior: 'smooth' }); } else { const top = element.offsetTop; if (window.scrollTo) { window.scrollTo({ top, behavior: 'smooth' }); } else { window.scrollTop = top; } } } catch (e) { (0, _componentHelper.warn)('GlobalStatus: Could not scroll into view!', e); } } render() { var _this$context; const { isActive } = this.state; const fallbackProps = (0, _componentHelper.extendPropsWithContextInClassComponent)(this.props, GlobalStatus.defaultProps, this.context.getTranslation(this.props).GlobalStatus); const props = (0, _componentHelper.extendPropsWithContextInClassComponent)(_GlobalStatusProvider.default.combineMessages([this.context.globalStatus, this.state.globalStatus]), GlobalStatus.defaultProps, fallbackProps); const lang = this.context.locale; const { title, default_title, state: rawState, className, no_animation, hide_close_button, close_text, status_anchor_text, skeleton, id, item, items, autoclose, show, delay, autoscroll, text, icon, icon_size, children, ...attributes } = props; const wrapperParams = { id, key: 'global-status', className: (0, _classnames.default)("dnb-global-status__wrapper dnb-no-focus", (0, _SkeletonHelper.createSkeletonClass)('font', skeleton, this.context), (0, _SpacingHelper.createSpacingClasses)(props), className), 'aria-live': isActive ? 'assertive' : 'off', onKeyDown: this.onKeyDownHandler, tabIndex: '-1' }; const state = this.correctStatus(rawState); const iconToRender = GlobalStatus.getIcon({ state, icon: icon || fallbackProps.icon, icon_size: icon_size || fallbackProps.icon_size, theme: ((_this$context = this.context) === null || _this$context === void 0 || (_this$context = _this$context.theme) === null || _this$context === void 0 ? void 0 : _this$context.name) || 'ui' }); const titleToRender = title || fallbackProps.title || fallbackProps.default_title; const noAnimation = (0, _componentHelper.isTrue)(no_animation); const itemsToRender = props.items || []; const contentToRender = props.text || props.children; const params = { className: `dnb-global-status dnb-global-status--${state}`, ...attributes }; (0, _SkeletonHelper.skeletonDOMAttributes)(params, skeleton, this.context); (0, _componentHelper.validateDOMAttributes)(this.props, params); const renderedItems = itemsToRender.length > 0 && _react.default.createElement("ul", { className: "dnb-ul" }, itemsToRender.map(this.itemsRenderHandler({ status_anchor_text, lang }))); const hasContent = renderedItems || contentToRender; const renderedContent = _react.default.createElement(_react.default.Fragment, null, title !== false && _react.default.createElement(_react.default.Fragment, null, _react.default.createElement("div", { className: "dnb-global-status__title", role: titleToRender !== null && titleToRender !== void 0 && titleToRender.type ? undefined : 'paragraph', lang: lang }, _react.default.createElement("span", { className: "dnb-global-status__icon" }, iconToRender), titleToRender, !(0, _componentHelper.isTrue)(hide_close_button) && _react.default.createElement(_Button.default, { text: close_text, title: close_text, variant: state === 'success' ? 'secondary' : 'tertiary', className: "dnb-global-status__close-button", icon: "close", on_click: this.closeHandler, size: "medium", icon_position: "left" })), hasContent && _react.default.createElement("div", { className: "dnb-global-status__message" }, _react.default.createElement("div", { className: 'dnb-global-status__message__content' + (!renderedItems ? " dnb-space__bottom--small" : "") }, typeof contentToRender === 'string' ? _react.default.createElement("p", { className: "dnb-p" }, contentToRender) : contentToRender, renderedItems)), _Hr || (_Hr = _react.default.createElement(_Hr2.default, { breakout: true })))); return _react.default.createElement("div", _extends({}, wrapperParams, { ref: this._wrapperRef }), _react.default.createElement("section", params, _react.default.createElement(_HeightAnimation.default, { className: "dnb-global-status__shell", duration: 800, delay: delay, open: isActive, animate: !noAnimation, onAnimationEnd: this.onAnimationEnd, onAnimationStart: this.onAnimationStart, onOpen: this.onOpen }, _react.default.createElement(_Section.default, { element: "div", variant: state, className: "dnb-global-status__content" }, renderedContent)))); } } exports.default = GlobalStatus; _defineProperty(GlobalStatus, "contextType", _Context.default); _defineProperty(GlobalStatus, "defaultProps", { id: 'main', status_id: 'status-main', title: null, default_title: null, text: null, items: [], icon: 'error', icon_size: 'medium', state: 'error', show: 'auto', autoscroll: true, autoclose: true, no_animation: false, close_text: 'Lukk', hide_close_button: false, omit_set_focus: false, omit_set_focus_on_update: true, delay: null, status_anchor_text: null, skeleton: null, className: null, children: null, on_adjust: null, on_open: null, on_show: null, on_close: null, on_hide: null }); process.env.NODE_ENV !== "production" ? GlobalStatus.propTypes = { id: _propTypes.default.string, status_id: _propTypes.default.string, title: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.bool]), default_title: _propTypes.default.string, text: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), items: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.array]), icon: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), icon_size: _propTypes.default.string, state: _propTypes.default.oneOf(['error', 'info', 'warning', 'success']), show: _propTypes.default.oneOf(['auto', true, false, 'true', 'false']), autoscroll: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), autoclose: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), no_animation: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), delay: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), close_text: _propTypes.default.node, hide_close_button: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), omit_set_focus: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), omit_set_focus_on_update: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), status_anchor_text: _propTypes.default.node, skeleton: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.bool]), ..._SpacingHelper.spacingPropTypes, className: _propTypes.default.string, children: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.node]), on_adjust: _propTypes.default.func, on_open: _propTypes.default.func, on_show: _propTypes.default.func, on_close: _propTypes.default.func, on_hide: _propTypes.default.func } : void 0; GlobalStatus.create = (...args) => new _GlobalStatusController.GlobalStatusInterceptor(...args); GlobalStatus.Update = GlobalStatus.create; GlobalStatus.Add = _GlobalStatusController.default; GlobalStatus.Remove = _GlobalStatusController.default.Remove; const isElementVisible = (elem, callback, delayFallback = 1e3) => { if (typeof IntersectionObserver !== 'undefined') { const intersectionObserver = new IntersectionObserver(entries => { const [entry] = entries; if (entry.isIntersecting) { intersectionObserver.unobserve(elem); if (typeof callback === 'function') { callback(elem); } } }); intersectionObserver.observe(elem); } else { if (typeof callback === 'function') { return setTimeout(() => callback(elem), delayFallback); } } return null; }; const wait = duration => new Promise(r => setTimeout(r, duration)); GlobalStatus._supportsSpacingProps = true; //# sourceMappingURL=GlobalStatus.js.map