'use strict'; var react = require('react'); var styledComponents = require('styled-components'); var edsTokens = require('@equinor/eds-tokens'); const useOutsideClick = (el, callback) => { react.useEffect(() => { const handleClick = e => { if (el && !el.contains(e.target)) { callback(e); } }; document.addEventListener('click', handleClick); return () => { document.removeEventListener('click', handleClick); }; }, [el, callback]); }; const useGlobalKeyPress = (targetKey, callback) => { react.useEffect(() => { const handleGlobalKeyPress = e => { const { key } = e; switch (key) { case targetKey: callback(e); break; } }; document.addEventListener('keydown', handleGlobalKeyPress, true); return () => { document.removeEventListener('keydown', handleGlobalKeyPress, true); }; }, [targetKey, callback]); }; const useId = (idOverride, type) => { const [defaultId, setDefaultId] = react.useState(idOverride); const id = idOverride || defaultId; react.useEffect(() => { if (defaultId == null) { setDefaultId(`eds-${type ? type + `-` : ''}${Math.round(Math.random() * 1e5)}`); } }, [defaultId, type]); return id; }; const useIsMounted = () => { const [isMounted, setIsMounted] = react.useState(null); react.useEffect(() => { setIsMounted(true); return () => setIsMounted(false); }, []); return isMounted; }; const useAutoResize = (targetEl, maxHeight) => { react.useEffect(() => { const handleResize = () => { targetEl.style.height = 'auto'; const { scrollHeight, clientHeight } = targetEl; let newHeight = clientHeight; if (maxHeight > newHeight) { newHeight = Math.min(maxHeight, Math.max(scrollHeight, newHeight)); if (scrollHeight > maxHeight) { targetEl.style.overflow = 'auto'; } else { targetEl.style.overflow = 'hidden'; } if (newHeight > clientHeight) { targetEl.style.height = `${newHeight}px`; } } }; if (targetEl && maxHeight) { handleResize(); targetEl.addEventListener('keyup', handleResize, true); } return () => { targetEl?.removeEventListener('keyup', handleResize, true); }; }, [targetEl, maxHeight]); }; var _placeholder = { '@@functional/placeholder': true }; function _isPlaceholder(a) { return a === _placeholder; } /** * Optimized internal one-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry1(fn) { return function f1(a) { if (arguments.length === 0 || _isPlaceholder(a)) { return f1; } else { return fn.apply(this, arguments); } }; } /** * Optimized internal two-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry2(fn) { return function f2(a, b) { switch (arguments.length) { case 0: return f2; case 1: return _isPlaceholder(a) ? f2 : _curry1(function (_b) { return fn(a, _b); }); default: return _isPlaceholder(a) && _isPlaceholder(b) ? f2 : _isPlaceholder(a) ? _curry1(function (_a) { return fn(_a, b); }) : _isPlaceholder(b) ? _curry1(function (_b) { return fn(a, _b); }) : fn(a, b); } }; } /** * Optimized internal three-arity curry function. * * @private * @category Function * @param {Function} fn The function to curry. * @return {Function} The curried function. */ function _curry3(fn) { return function f3(a, b, c) { switch (arguments.length) { case 0: return f3; case 1: return _isPlaceholder(a) ? f3 : _curry2(function (_b, _c) { return fn(a, _b, _c); }); case 2: return _isPlaceholder(a) && _isPlaceholder(b) ? f3 : _isPlaceholder(a) ? _curry2(function (_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) ? _curry2(function (_b, _c) { return fn(a, _b, _c); }) : _curry1(function (_c) { return fn(a, b, _c); }); default: return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c) ? f3 : _isPlaceholder(a) && _isPlaceholder(b) ? _curry2(function (_a, _b) { return fn(_a, _b, c); }) : _isPlaceholder(a) && _isPlaceholder(c) ? _curry2(function (_a, _c) { return fn(_a, b, _c); }) : _isPlaceholder(b) && _isPlaceholder(c) ? _curry2(function (_b, _c) { return fn(a, _b, _c); }) : _isPlaceholder(a) ? _curry1(function (_a) { return fn(_a, b, c); }) : _isPlaceholder(b) ? _curry1(function (_b) { return fn(a, _b, c); }) : _isPlaceholder(c) ? _curry1(function (_c) { return fn(a, b, _c); }) : fn(a, b, c); } }; } function _has(prop, obj) { return Object.prototype.hasOwnProperty.call(obj, prop); } function _isObject(x) { return Object.prototype.toString.call(x) === '[object Object]'; } /** * Creates a new object with the own properties of the two provided objects. If * a key exists in both objects, the provided function is applied to the key * and the values associated with the key in each object, with the result being * used as the value associated with the key in the returned object. * * @func * @memberOf R * @since v0.19.0 * @category Object * @sig ((String, a, a) -> a) -> {a} -> {a} -> {a} * @param {Function} fn * @param {Object} l * @param {Object} r * @return {Object} * @see R.mergeDeepWithKey, R.merge, R.mergeWith * @example * * let concatValues = (k, l, r) => k == 'values' ? R.concat(l, r) : r * R.mergeWithKey(concatValues, * { a: true, thing: 'foo', values: [10, 20] }, * { b: true, thing: 'bar', values: [15, 35] }); * //=> { a: true, b: true, thing: 'bar', values: [10, 20, 15, 35] } * @symb R.mergeWithKey(f, { x: 1, y: 2 }, { y: 5, z: 3 }) = { x: 1, y: f('y', 2, 5), z: 3 } */ var mergeWithKey = /*#__PURE__*/_curry3(function mergeWithKey(fn, l, r) { var result = {}; var k; l = l || {}; r = r || {}; for (k in l) { if (_has(k, l)) { result[k] = _has(k, r) ? fn(k, l[k], r[k]) : l[k]; } } for (k in r) { if (_has(k, r) && !_has(k, result)) { result[k] = r[k]; } } return result; }); /** * Creates a new object with the own properties of the two provided objects. * If a key exists in both objects: * - and both associated values are also objects then the values will be * recursively merged. * - otherwise the provided function is applied to the key and associated values * using the resulting value as the new value associated with the key. * If a key only exists in one object, the value will be associated with the key * of the resulting object. * * @func * @memberOf R * @since v0.24.0 * @category Object * @sig ((String, a, a) -> a) -> {a} -> {a} -> {a} * @param {Function} fn * @param {Object} lObj * @param {Object} rObj * @return {Object} * @see R.mergeWithKey, R.mergeDeepWith * @example * * let concatValues = (k, l, r) => k == 'values' ? R.concat(l, r) : r * R.mergeDeepWithKey(concatValues, * { a: true, c: { thing: 'foo', values: [10, 20] }}, * { b: true, c: { thing: 'bar', values: [15, 35] }}); * //=> { a: true, b: true, c: { thing: 'bar', values: [10, 20, 15, 35] }} */ var mergeDeepWithKey = /*#__PURE__*/_curry3(function mergeDeepWithKey(fn, lObj, rObj) { return mergeWithKey(function (k, lVal, rVal) { if (_isObject(lVal) && _isObject(rVal)) { return mergeDeepWithKey(fn, lVal, rVal); } else { return fn(k, lVal, rVal); } }, lObj, rObj); }); /** * Creates a new object with the own properties of the first object merged with * the own properties of the second object. If a key exists in both objects: * - and both values are objects, the two values will be recursively merged * - otherwise the value from the second object will be used. * * @func * @memberOf R * @since v0.24.0 * @category Object * @sig {a} -> {a} -> {a} * @param {Object} lObj * @param {Object} rObj * @return {Object} * @see R.merge, R.mergeDeepLeft, R.mergeDeepWith, R.mergeDeepWithKey * @example * * R.mergeDeepRight({ name: 'fred', age: 10, contact: { email: 'moo@example.com' }}, * { age: 40, contact: { email: 'baa@example.com' }}); * //=> { name: 'fred', age: 40, contact: { email: 'baa@example.com' }} */ var mergeDeepRight = /*#__PURE__*/_curry2(function mergeDeepRight(lObj, rObj) { return mergeDeepWithKey(function (k, lVal, rVal) { return rVal; }, lObj, rObj); }); const useToken = (options, token) => react.useCallback(() => { const { density } = options; if (density === 'compact') { return mergeDeepRight(token, token.modes.compact); } return token; }, [options, token]); const useHideBodyScroll = active => { const originalStyles = react.useRef(); react.useEffect(() => { if (typeof document === 'undefined') return; const html = document.documentElement; const { body } = document; if (active) { const scrollBarWidth = window.innerWidth - html.clientWidth; const bodyPaddingRight = parseInt(window.getComputedStyle(body).getPropertyValue('padding-right')) || 0; const oldStyle = { overflow: body.style.overflow, paddingRight: body.style.paddingRight }; originalStyles.current = oldStyle; body.style.overflow = 'hidden'; body.style.paddingRight = `${bodyPaddingRight + scrollBarWidth}px`; } else if (originalStyles.current) { body.style.overflow = originalStyles.current.overflow; body.style.paddingRight = originalStyles.current.paddingRight; } const originalState = originalStyles.current; return () => { body.style.overflow = originalState?.overflow; body.style.paddingRight = originalState?.paddingRight; }; }, [active]); }; const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? react.useLayoutEffect : react.useEffect; const useIsInDialog = el => { const [inDialog, setInDialog] = react.useState(null); react.useEffect(() => { if (el && inDialog === null) { setInDialog(!!el.closest('dialog')); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [el]); return inDialog; }; const shorthand = token => { if (!token) { return undefined; } const { width = '', style = '', color = '' } = token; if (!width) { return null; } return `${width} ${style} ${color}`; }; const bordersTemplate = border => { if (!border) { return styledComponents.css({}); } switch (border.type) { case 'border': return styledComponents.css({ border: shorthand(border), borderRadius: border.radius }); case 'bordergroup': return styledComponents.css({ borderBottom: shorthand(border.bottom), borderTop: shorthand(border.top), borderLeft: shorthand(border.left), borderRight: shorthand(border.right), borderBottomLeftRadius: border?.left?.radius, borderTopLeftRadius: border?.left?.radius, borderBottomRightRadius: border?.right?.radius, borderTopRightRadius: border?.right?.radius }); default: return styledComponents.css({}); } }; const { colors: { interactive: { focus: { rgba: focusColor } } } } = edsTokens.tokens; const outlineTemplate = outline => { const { color = focusColor, style = 'dashed', width = '2px', offset = '0px', type } = outline; const outline_ = { color, style, width, offset, type }; return styledComponents.css({ outline: shorthand(outline_), outlineOffset: outline_.offset }); }; const typographyTemplate = (typography, link) => { if (!typography) { return ''; } let base = ` margin: 0; color: ${typography.color}; font-family: ${typography.fontFamily}; font-size: ${typography.fontSize}; font-weight: ${typography.fontWeight}; line-height: ${typography.lineHeight}; `; if (typography.fontStyle) { base += `\nfont-style: ${typography.fontStyle};`; } if (typography.letterSpacing) { base += `\nletter-spacing: ${typography.letterSpacing};`; } if (typography.textTransform) { base += `\ntext-transform: ${typography.textTransform};`; } if (typography.textDecoration) { base += `\ntext-decoration: ${typography.textDecoration};`; } if (typography.textAlign) { base += `\ntext-align: ${typography.textAlign};`; } if (typography.fontFeature) { base += `\nfont-feature-settings: ${typography.fontFeature};`; } if (link) { base += `\ncursor: pointer;`; } return base; }; const spacingsTemplate = ({ left, right, top, bottom }) => styledComponents.css({ paddingLeft: left, paddingTop: top, paddingRight: right, paddingBottom: bottom }); const boxshadowTemplate = border => styledComponents.css({ boxShadow: `inset 0 -${border.width} 0 0 ${border.color};` }); const joinHandlers = (handler1, handler2) => { const callback = event => { handler1 && handler1(event); handler2 && handler2(event); }; return callback; }; const mergeRefs = (...refs) => { return element => refs.forEach(ref => { if (typeof ref === 'function') { ref(element); } else if (ref && typeof ref === 'object') { ref.current = element; } }); }; // Workaround // React ignores 'dispathEvent' on input/textarea, see https://github.com/facebook/react/issues/10135 const setReactInputValue = (input, value) => { const previousValue = input.value; input.value = value; const tracker = input._valueTracker; if (typeof tracker !== 'undefined') { tracker.setValue(previousValue); } //'change' instead of 'input', see https://github.com/facebook/react/issues/11488#issuecomment-381590324 input.dispatchEvent(new Event('change', { bubbles: true })); }; const trimSpaces = text => text.replace(/ /g, ''); /** Simpler version `typographyTemplate` that does not set `color` and `margin` */ const typographyMixin = typography => { const { fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, fontFeature, textDecoration, textTransform, fontStyle } = typography; return { fontFeatureSettings: fontFeature, fontFamily, fontSize, fontWeight, letterSpacing, lineHeight, textDecoration, textTransform: textTransform, fontStyle }; }; exports.bordersTemplate = bordersTemplate; exports.boxshadowTemplate = boxshadowTemplate; exports.joinHandlers = joinHandlers; exports.mergeRefs = mergeRefs; exports.outlineTemplate = outlineTemplate; exports.setReactInputValue = setReactInputValue; exports.spacingsTemplate = spacingsTemplate; exports.trimSpaces = trimSpaces; exports.typographyMixin = typographyMixin; exports.typographyTemplate = typographyTemplate; exports.useAutoResize = useAutoResize; exports.useGlobalKeyPress = useGlobalKeyPress; exports.useHideBodyScroll = useHideBodyScroll; exports.useId = useId; exports.useIsInDialog = useIsInDialog; exports.useIsMounted = useIsMounted; exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect; exports.useOutsideClick = useOutsideClick; exports.useToken = useToken;