UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

431 lines 13.2 kB
import _pushInstanceProperty from "core-js-pure/stable/instance/push.js"; import clsx from 'clsx'; import { warn } from "../../shared/component-helper.js"; export const spacingDefaultProps = { space: null, innerSpace: null, top: null, right: null, bottom: null, left: null }; export const spacePatterns = { 'xx-small': 0.25, 'x-small': 0.5, small: 1, medium: 1.5, large: 2, 'x-large': 3, 'xx-large': 3.5, 'xx-large-x2': 7 }; globalThis.CALC_CACHE = {}; export const calc = (...types) => { const hash = types.join('|'); if (globalThis.CALC_CACHE[hash]) { return globalThis.CALC_CACHE[hash]; } const result = []; types.forEach(rawTypes => { createTypeModifiers(rawTypes).forEach(type => { _pushInstanceProperty(result).call(result, `var(--spacing-${type})`); }); }); return result.length ? globalThis.CALC_CACHE[hash] = `calc(${result.join(' + ')})` : null; }; export const createSpacingProperties = props => { if (props !== null && props !== void 0 && props.innerSpace) { return computeProperties(props.innerSpace); } return {}; }; export const createMarginProperties = props => { return computeMarginProperties(props); }; function mergeSpacing(spaceValue, individualProps) { const { top, right, bottom, left } = individualProps; if (spaceValue === undefined || spaceValue === null) { const result = {}; if (typeof top !== 'undefined') { result.top = top; } if (typeof right !== 'undefined') { result.right = right; } if (typeof bottom !== 'undefined') { result.bottom = bottom; } if (typeof left !== 'undefined') { result.left = left; } return result; } const base = transformToAll(spaceValue); const result = { ...base }; if (typeof top !== 'undefined') { result.top = top; } if (typeof right !== 'undefined') { result.right = right; } if (typeof bottom !== 'undefined') { result.bottom = bottom; } if (typeof left !== 'undefined') { result.left = left; } return result; } function computeMarginProperties(props) { const { space, top, right, bottom, left } = props; const individualProps = { top, right, bottom, left }; const hasMedia = hasMediaSize(space); let mediaSpace; if (hasMedia) { const spaceMedia = space; mediaSpace = { small: mergeSpacing(spaceMedia.small, individualProps), medium: mergeSpacing(spaceMedia.medium, individualProps), large: mergeSpacing(spaceMedia.large, individualProps) }; } else { return {}; } const result = {}; for (const size in mediaSpace) { const value = mediaSpace[size]; if (!value || typeof value === 'object' && !hasSize(value)) { continue; } const props = transformToAll(value); for (const key in props) { if (isValidInnerSpaceProp(key)) { const cur = props[key]; const name = `--margin-${key[0]}-${size[0]}`; if (String(cur) === '0' || String(cur) === 'false') { result[name] = '0'; } else if (cur) { const typeModifiers = createTypeModifiers(cur); const sum = sumTypes(typeModifiers); if (sum > 0) { result[name] = `${sum}rem`; } } } } } return result; } function hasMediaSize(media) { const keys = media ? Object.keys(media) : []; return keys.includes('small') || keys.includes('medium') || keys.includes('large'); } function hasSize(space) { const keys = Object.keys(space); return keys.includes('top') || keys.includes('right') || keys.includes('bottom') || keys.includes('left') || keys.includes('inline') || keys.includes('block'); } function computeProperties(space) { if (!hasMediaSize(space)) { space = { small: space, medium: space, large: space }; } const result = {}; for (const size in space) { var _space; const value = (_space = space) === null || _space === void 0 ? void 0 : _space[size]; const props = transformToAll(value); for (const key in props) { if (isValidInnerSpaceProp(key)) { const cur = props[key]; const name = `--padding-${key[0]}-${size[0]}`; if (String(cur) === '0' || String(cur) === 'false') { result[name] = '0'; } else if (cur) { const typeModifiers = createTypeModifiers(cur); const sum = sumTypes(typeModifiers); result[name] = `${sum}rem`; } } } } return result; } function transformToAll(value) { let result = value; if (!hasSize(value)) { result = { top: value, right: value, bottom: value, left: value }; } return expandInnerSpaceShorthand(result); } function expandInnerSpaceShorthand(space) { const result = { ...space }; if (typeof result.inline !== 'undefined') { var _result$left, _result$right; result.left = (_result$left = result.left) !== null && _result$left !== void 0 ? _result$left : result.inline; result.right = (_result$right = result.right) !== null && _result$right !== void 0 ? _result$right : result.inline; } if (typeof result.block !== 'undefined') { var _result$top, _result$bottom; result.top = (_result$top = result.top) !== null && _result$top !== void 0 ? _result$top : result.block; result.bottom = (_result$bottom = result.bottom) !== null && _result$bottom !== void 0 ? _result$bottom : result.block; } return result; } function isValidInnerSpaceProp(propName) { return ['top', 'right', 'bottom', 'left'].includes(propName); } const collectSpacingClasses = (props, elementName = null) => { const p = { ...props }; if (typeof p.space !== 'undefined') { if (typeof p.space === 'string' || typeof p.space === 'number' || typeof p.space === 'boolean' && p.space) { var _p$left, _p$bottom, _p$right, _p$top; p.left = (_p$left = p.left) !== null && _p$left !== void 0 ? _p$left : p.space; p.bottom = (_p$bottom = p.bottom) !== null && _p$bottom !== void 0 ? _p$bottom : p.space; p.right = (_p$right = p.right) !== null && _p$right !== void 0 ? _p$right : p.space; p.top = (_p$top = p.top) !== null && _p$top !== void 0 ? _p$top : p.space; } if (typeof p.space === 'object') { if (hasMediaSize(p.space)) { const smallValue = p.space['small']; if (smallValue) { if (typeof smallValue === 'string' || typeof smallValue === 'number' || typeof smallValue === 'boolean' && smallValue) { var _p$left2, _p$bottom2, _p$right2, _p$top2; p.left = (_p$left2 = p.left) !== null && _p$left2 !== void 0 ? _p$left2 : smallValue; p.bottom = (_p$bottom2 = p.bottom) !== null && _p$bottom2 !== void 0 ? _p$bottom2 : smallValue; p.right = (_p$right2 = p.right) !== null && _p$right2 !== void 0 ? _p$right2 : smallValue; p.top = (_p$top2 = p.top) !== null && _p$top2 !== void 0 ? _p$top2 : smallValue; } else if (typeof smallValue === 'object') { const expandedSmallValue = expandInnerSpaceShorthand(smallValue); for (const i in expandedSmallValue) { if (!p[i] && isValidSpaceProp(i)) { p[i] = expandedSmallValue[i]; } } } } } else { const expandedSpace = expandInnerSpaceShorthand(p.space); for (const i in expandedSpace) { if (!p[i] && isValidSpaceProp(i)) { p[i] = expandedSpace[i]; } } } } delete p.space; } return Object.entries(p).reduce((acc, [direction, cur]) => { if (isValidSpaceProp(direction) && direction !== 'innerSpace') { if (String(cur) === '0' || String(cur) === 'false') { _pushInstanceProperty(acc).call(acc, `dnb-space__${direction}--zero`); } else if (cur) { const typeModifiers = createTypeModifiers(cur); const sum = sumTypes(typeModifiers); if (sum > 10) { warn(`Spacing of more than 10rem is not supported! You used ${sum} / (${typeModifiers.join(',')})`); } else { const nearestTypes = findNearestTypes(sum, true); acc = [...acc, ...nearestTypes.map(type => `dnb-space__${direction}--${type}`)]; } } } else if (direction === 'noCollapse') { _pushInstanceProperty(acc).call(acc, 'dnb-space--no-collapse'); if (elementName && isInline(elementName)) { _pushInstanceProperty(acc).call(acc, 'dnb-space--inline'); } } return acc; }, []); }; export const createSpacing = (props, elementName = null) => { const className = collectSpacingClasses(props, elementName); const innerStyle = createSpacingProperties(props); const marginStyle = createMarginProperties(props); const style = { ...marginStyle, ...innerStyle }; const hasStyle = Object.keys(style).length > 0; return { className, style: hasStyle ? style : undefined }; }; export const applySpacing = (props, target, elementName = null) => { const classes = collectSpacingClasses(props, elementName); const innerStyle = createSpacingProperties(props); const marginStyle = createMarginProperties(props); const style = { ...marginStyle, ...innerStyle }; const hasClasses = classes.length > 0; const hasStyle = Object.keys(style).length > 0; const hasSpacingKeyOnTarget = spacingKeys.some(key => key in target); if (!hasClasses && !hasStyle && !hasSpacingKeyOnTarget) { return target; } const result = { ...target }; for (const key of spacingKeys) { if (key in result) { delete result[key]; } } if (hasClasses) { result.className = clsx(target.className, ...classes); } if (hasStyle) { result.style = { ...target.style, ...style }; } return result; }; const spacingKeys = ['space', 'innerSpace', 'top', 'right', 'bottom', 'left', 'noCollapse']; export const translateSpace = type => { if (/-x2$/.test(String(type))) { return spacePatterns[String(type).replace(/-x2$/, '')] * 2; } return spacePatterns[String(type)] || 0; }; export const splitTypes = types => { if (typeof types === 'string') { const test = types.split(/ /g); return clean(test); } else if (typeof types === 'boolean') { return [types ? 'small' : 0]; } else if (typeof types === 'number') { return [types]; } return clean(types) || null; function clean(t) { return t === null || t === void 0 ? void 0 : t.filter(r => r && String(r).length > 0); } }; export const sumTypes = types => splitTypes(types).map(type => translateSpace(type)).reduce((acc, cur) => { if (cur > 0) { acc += cur; } else if (cur < 0) { acc -= cur; } return acc; }, 0); export const createTypeModifiers = types => { return (splitTypes(types) || []).reduce((acc, type) => { if (type) { const firstLetter = String(type)[0]; if (parseFloat(firstLetter) > -1) { let num = parseFloat(String(type)); if (num >= 8 && /[0-9]px/.test(String(type))) { num = num / 16; } const foundType = findType(num); if (foundType) { type = foundType; } else { findNearestTypes(num).forEach(type => { if (type) { _pushInstanceProperty(acc).call(acc, type); } }); } } if (!(parseFloat(String(type)) > 0)) { _pushInstanceProperty(acc).call(acc, type); } } return acc; }, []); }; export const findType = num => { const found = findTypeAll(num); if (found) { return found[0]; } return null; }; export const findTypeAll = num => { const listOfSpacePatterns = Object.entries(spacePatterns); const found = listOfSpacePatterns.find(([k, v]) => k && v === num) || null; return found; }; export const findNearestTypes = (num, multiply = false) => { let res = []; const near = Object.entries(spacePatterns).reverse().filter(k => multiply ? true : !k[0].includes('-x')).find(([k, v]) => k && num >= v); const nearNum = near && near[1] || num; const types = findTypeAll(nearNum); if (types) { const nearType = types[0]; _pushInstanceProperty(res).call(res, nearType); const leftOver = num - parseFloat(String(types[1])); const foundMoreTypes = findNearestTypes(leftOver, multiply); foundMoreTypes.forEach(type => { const index = res.indexOf(type); if (index !== -1) { res[index] = multiply ? `${type}-x2` : type; } }); res = [...res, ...foundMoreTypes]; } return res; }; export const isValidSpaceProp = propName => propName && ['top', 'right', 'bottom', 'left', 'space', 'innerSpace'].includes(propName); export const removeSpaceProps = props => { const { space, innerSpace, top, bottom, left, right, ...restProps } = props; return restProps; }; export const isInline = elementName => { switch (elementName) { case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': case 'p': return true; } return false; }; //# sourceMappingURL=SpacingUtils.js.map