wix-style-react
Version:
wix-style-react
370 lines • 12.4 kB
JavaScript
import { easingMap, timingMap, } from '../constants';
export const getPercentageValue = (percentage) => {
const percentRegex = /^((100)|(\d{1,2}(\.\d*)?))%$/g;
if (percentage.match(percentRegex)) {
const percentNumber = Number(percentage.split('%')[0]);
if (Number.isFinite(percentNumber)) {
return percentNumber / 100;
}
}
return 0;
};
const getFadeProps = (fade) => {
if (fade === true) {
return {
duration: 'medium01',
};
}
return fade;
};
const getMoveProps = (move) => {
if (move === true) {
return {
duration: 'medium01',
direction: 'bottomToTop',
distance: '10px',
};
}
return move;
};
const getToggleProps = (toggle) => {
if (toggle === true) {
return {
duration: 'medium01',
direction: 'bottomToTop',
};
}
return toggle;
};
const getScaleProps = (scale, isExiting) => {
if (scale === true) {
return {
duration: 'medium01',
direction: 'center',
scale: isExiting ? '0' : '1',
};
}
return { ...scale, scale: `${getPercentageValue(scale.scale)}` };
};
const getDefaultStyles = (props) => {
const easing = props.easing
? {
transitionTimingFunction: easingMap[props.easing],
}
: undefined;
const delay = props.delay
? {
transitionDelay: `${timingMap[props.delay]}ms`,
}
: undefined;
return {
...easing,
...delay,
};
};
const getFadeStyles = (fadeProps, isExiting) => {
const { duration } = fadeProps;
const defaultStyles = getDefaultStyles(fadeProps);
return {
[isExiting ? 'exiting' : 'entering']: {
opacity: 0,
transitionProperty: 'opacity',
transitionDuration: `${timingMap[duration]}ms`,
...(isExiting ? defaultStyles : {}),
},
[isExiting ? 'exited' : 'entered']: {
opacity: 1,
transitionProperty: 'opacity',
transitionDuration: `${timingMap[duration]}ms`,
...(!isExiting ? defaultStyles : {}),
},
};
};
export const getMoveStyles = (moveProps, isExiting) => {
const { direction, distance, duration } = moveProps;
const defaultStyles = getDefaultStyles(moveProps);
let transform = '';
switch (direction) {
case 'topToBottom':
transform = `translateY(${isExiting ? distance : `-${distance}`})`;
break;
case 'bottomToTop':
transform = `translateY(${isExiting ? `-${distance}` : distance})`;
break;
case 'leftToRight':
transform = `translateX(${isExiting ? distance : `-${distance}`})`;
break;
case 'rightToLeft':
transform = `translateX(${isExiting ? `-${distance}` : distance})`;
break;
default:
throw new Error('unsupported direction');
}
return {
[isExiting ? 'exiting' : 'entering']: {
transform,
transitionProperty: 'transform',
transitionDuration: `${timingMap[duration]}ms`,
...(isExiting ? defaultStyles : {}),
},
[isExiting ? 'exited' : 'entered']: {
transform: 'none',
transitionProperty: 'transform',
transitionDuration: `${timingMap[duration]}ms`,
...(!isExiting ? defaultStyles : {}),
},
};
};
const isDirectionVertical = (direction) => {
return direction === 'bottomToTop' || direction === 'topToBottom';
};
const getToggleStyles = (toggleProps, isExiting, height, width, oppositeProps) => {
const { direction, duration } = toggleProps;
const defaultStyles = getDefaultStyles(toggleProps);
const isVertical = isDirectionVertical(direction);
const transitionOrigin = isVertical ? 'bottom' : 'left';
const isOppositeVertical = oppositeProps?.direction && isDirectionVertical(oppositeProps?.direction);
const isOppositeOnAnotherAxis = isOppositeVertical !== undefined && isOppositeVertical !== isVertical;
const transitionOriginOutValue = oppositeProps?.direction === 'bottomToTop' ||
oppositeProps?.direction === 'leftToRight'
? '-100%'
: '100%';
const oppositeTransitionOrigin = isOppositeVertical ? 'bottom' : 'left';
let transitionOriginIn = '';
switch (direction) {
case 'topToBottom':
case 'rightToLeft':
transitionOriginIn = isExiting ? '-100%' : '100%';
break;
case 'bottomToTop':
case 'leftToRight':
transitionOriginIn = isExiting ? '100%' : '-100%';
break;
default:
throw new Error('unsupported direction');
}
const commonStyles = {
height: isVertical ? `${height}px` : '100%',
width: isVertical ? '100%' : `${width}px`,
position: 'relative',
overflow: 'hidden',
transitionProperty: 'bottom, left',
transitionDuration: `${timingMap[duration]}ms`,
};
const styles = {
in: {
...commonStyles,
[transitionOrigin]: transitionOriginIn,
...(isExiting ? defaultStyles : {}),
},
out: {
...commonStyles,
[transitionOrigin]: oppositeProps?.direction === direction ||
isOppositeVertical === isVertical
? transitionOriginOutValue
: '0%',
...(isOppositeOnAnotherAxis
? {
[oppositeTransitionOrigin]: transitionOriginOutValue,
}
: {}),
...(!isExiting ? defaultStyles : {}),
},
};
if (isExiting) {
return {
entered: {
...commonStyles,
[transitionOrigin]: '0%',
...(isOppositeOnAnotherAxis
? {
[oppositeTransitionOrigin]: '0%',
}
: {}),
...defaultStyles,
},
exiting: styles.in,
exited: styles.out,
};
}
return {
entering: styles.in,
entered: styles.out,
};
};
const getScaleStyles = (scaleProps, isExiting) => {
const { direction, scale, duration } = scaleProps;
const defaultStyles = getDefaultStyles(scaleProps);
let transformOrigin = '';
switch (direction) {
case 'bottom':
transformOrigin = '50% 100%';
break;
case 'bottomEnd':
transformOrigin = '100% 100%';
break;
case 'bottomStart':
transformOrigin = '0% 100%';
break;
case 'center':
transformOrigin = '50% 50%';
break;
case 'left':
transformOrigin = '0% 50%';
break;
case 'right':
transformOrigin = '100% 50%';
break;
case 'top':
transformOrigin = '50% 0%';
break;
case 'topEnd':
transformOrigin = '100% 0%';
break;
case 'topStart':
transformOrigin = '0% 0%';
break;
default:
throw new Error('unsupported direction');
}
return {
[isExiting ? 'exiting' : 'entering']: {
transform: 'scale(0, 0)',
transitionProperty: 'transform',
transitionDuration: `${timingMap[duration]}ms`,
transformOrigin,
...(isExiting ? defaultStyles : {}),
},
[isExiting ? 'exited' : 'entered']: {
transform: `scale(${scale}, ${scale})`,
transitionProperty: 'transform',
transitionDuration: `${timingMap[duration]}ms`,
transformOrigin,
...(!isExiting ? defaultStyles : {}),
},
};
};
const getToggleWrapperStyles = (expandProps, collapseProps, height, width) => {
if (expandProps?.direction === 'topToBottom' &&
collapseProps?.direction === 'bottomToTop') {
return {};
}
const commonStyles = { overflow: 'hidden', height, width };
return {
entering: commonStyles,
entered: commonStyles,
exiting: commonStyles,
exited: commonStyles,
};
};
const getMergedStyles = (target, source) => {
return {
entering: {
...target.entering,
...source.entering,
},
entered: {
...target.entered,
...source.entered,
},
exiting: {
...target.exiting,
...source.exiting,
},
exited: {
...target.exited,
...source.exited,
},
};
};
export const getTransitionStyles = ({ width, height }, enterAnimation, exitAnimation) => {
const transitionStyles = {
fade: {},
move: {},
scale: {},
toggle: {},
};
if (enterAnimation?.fadeIn) {
const props = getFadeProps(enterAnimation?.fadeIn);
const styles = getFadeStyles(props, false);
Object.assign(transitionStyles.fade, styles);
}
if (exitAnimation?.fadeOut) {
const props = getFadeProps(exitAnimation?.fadeOut);
const styles = getFadeStyles(props, true);
Object.assign(transitionStyles.fade, styles);
}
if (enterAnimation?.moveIn) {
const props = getMoveProps(enterAnimation?.moveIn);
const styles = getMoveStyles(props, false);
Object.assign(transitionStyles.move, styles);
}
if (exitAnimation?.moveOut) {
const props = getMoveProps(exitAnimation?.moveOut);
const styles = getMoveStyles(props, true);
Object.assign(transitionStyles.move, styles);
}
const expandProps = enterAnimation?.expand
? getToggleProps(enterAnimation?.expand)
: undefined;
const collapseProps = exitAnimation?.collapse
? getToggleProps(exitAnimation?.collapse)
: undefined;
if (expandProps) {
const styles = getToggleStyles(expandProps, false, height, width, collapseProps);
Object.assign(transitionStyles.toggle, styles);
}
if (collapseProps) {
const styles = getToggleStyles(collapseProps, true, height, width, expandProps);
Object.assign(transitionStyles.toggle, styles);
}
if (enterAnimation?.scaleUp) {
const props = getScaleProps(enterAnimation?.scaleUp);
const styles = getScaleStyles(props, false);
Object.assign(transitionStyles.scale, styles);
}
if (exitAnimation?.scaleDown) {
const props = getScaleProps(exitAnimation?.scaleDown, true);
const styles = getScaleStyles(props, true);
Object.assign(transitionStyles.scale, styles);
}
if (!!expandProps || !!collapseProps) {
const wrapperStyles = getToggleWrapperStyles(expandProps, collapseProps, height, width);
const mergedStyles = getMergedStyles(transitionStyles.scale, wrapperStyles);
Object.assign(transitionStyles.scale, mergedStyles);
}
return transitionStyles;
};
const getTiming = (type, animation) => {
if (!animation) {
return 0;
}
const entry = Object.entries(animation).find(([key]) => key === type);
if (entry) {
const [_, value] = entry;
if (typeof value !== 'boolean') {
const delay = value.delay ? timingMap[value.delay] : 0;
return timingMap[value.duration] + delay;
}
else if (value === true) {
// Setting default duration to medium01
return timingMap.medium01;
}
}
return 0;
};
export const getTimeout = (enterAnimation, exitAnimation) => {
const fadeEnter = getTiming('fadeIn', enterAnimation);
const fadeExit = getTiming('fadeOut', exitAnimation);
const moveEnter = getTiming('moveIn', enterAnimation);
const moveExit = getTiming('moveOut', exitAnimation);
const expand = getTiming('expand', enterAnimation);
const collapse = getTiming('collapse', exitAnimation);
const scaleUp = getTiming('scaleUp', enterAnimation);
const scaleDown = getTiming('scaleDown', exitAnimation);
return {
enter: Math.max(fadeEnter, moveEnter, expand, scaleUp),
exit: Math.max(fadeExit, moveExit, collapse, scaleDown),
};
};
//# sourceMappingURL=utils.js.map