@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
431 lines • 13.2 kB
JavaScript
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