Unverified Commit 7dcbd894 authored by Tasso Evangelista's avatar Tasso Evangelista
Browse files

Rearrange Box internals

parent ba89a84d
......@@ -4,7 +4,7 @@ import React, { useCallback, useEffect, useState } from 'react';
import { appendClassName } from '../../../helpers/appendClassName';
import { useStyle } from '../../../hooks/useStyle';
import { BoxTransforms, useComposedBoxTransform } from '../transforms';
import { BoxTransforms, useComposedBoxTransform } from '../BoxTransforms';
function AnimatedVisibility({
children,
......
import PropTypes from 'prop-types';
import React, { useCallback } from 'react';
import { BoxTransforms, useComposedBoxTransform } from '../transforms';
import { BoxTransforms, useComposedBoxTransform } from '../BoxTransforms';
function FlexContainer({
inline = false,
......
......@@ -5,7 +5,7 @@ import React, { useRef, useCallback } from 'react';
import { appendClassName } from '../../../helpers/appendClassName';
import { useStyle } from '../../../hooks/useStyle';
import { BoxTransforms, useComposedBoxTransform } from '../transforms';
import { BoxTransforms, useComposedBoxTransform } from '../BoxTransforms';
const getTouchingEdges = (element) => ({
top: !element.scrollTop,
......
import { css } from '@rocket.chat/css-in-js';
import React, { createElement, forwardRef, memo } from 'react';
import { appendClassName } from '../../helpers/appendClassName';
import { prependClassName } from '../../helpers/prependClassName';
import { useStyle } from '../../hooks/useStyle';
import { useStyleSheet } from '../../hooks/useStyleSheet';
import { useStylingProps } from './stylingProps';
import { useBoxTransform, BoxTransforms } from './transforms';
export const useArrayLikeClassNameProp = (props) => {
const classNames = [].concat(props.className);
const cssFns = classNames.filter((value) => typeof value === 'function');
const stylesClassName = useStyle(
css`
${cssFns}
`,
props
);
const strings = classNames.filter((value) => typeof value === 'string');
props.className = strings.reduce(
(className, string) => appendClassName(className, string),
stylesClassName || ''
);
return props;
};
export const useBoxOnlyProps = (props) => {
Object.entries(props).forEach(([key, value]) => {
if (key.slice(0, 4) === 'rcx-') {
if (!value) {
delete props[key];
return;
}
const newClassName = value === true ? key : `${key}-${value}`;
props.className = prependClassName(props.className, newClassName);
delete props[key];
}
});
props.className = prependClassName(props.className, 'rcx-box rcx-box--full');
return props;
};
import { useBoxTransform, BoxTransforms } from './BoxTransforms';
import {
consumeBoxProps,
consumeCssPropertiesProps,
consumePostAliases,
consumePreAliases,
consumeRcxProps,
consumeSpecialStylingProps,
} from './props';
import { useArrayLikeClassNameProp } from './useArrayLikeClassNameProp';
export const Box = memo(
forwardRef(function Box({ is = 'div', children, animated, ...props }, ref) {
forwardRef(function Box({ is = 'div', children, ...props }, ref) {
useStyleSheet();
if (ref) {
props.ref = ref;
}
props = useArrayLikeClassNameProp(props);
const transformFn = useBoxTransform();
if (transformFn) {
props = transformFn(props);
}
props = useBoxOnlyProps(props);
props = useStylingProps(props);
props = consumeRcxProps(props);
props = consumePreAliases(props);
props = consumeSpecialStylingProps(props);
props = consumeCssPropertiesProps(props);
props = consumePostAliases(props);
props = consumeBoxProps(props);
props = useArrayLikeClassNameProp(props);
if (animated) {
props.className = prependClassName(props.className, 'rcx-box--animated');
if (ref) {
props.ref = ref;
}
const element = createElement(is, props, children);
if (transformFn) {
return <BoxTransforms.Provider children={element} />;
return <BoxTransforms.Provider children={element} value={undefined} />;
}
return element;
......@@ -81,10 +45,6 @@ export const Box = memo(
Box.displayName = 'Box';
Box.defaultProps = {
is: 'div',
};
export { default as AnimatedVisibility } from './AnimatedVisibility';
export { default as Flex } from './Flex';
export { default as Position, PositionAnimated } from './Position';
......
import { css } from '@rocket.chat/css-in-js';
import { appendClassName } from '../../helpers/appendClassName';
import { fromCamelToKebab } from '../../helpers/fromCamelToKebab';
import { prependClassName } from '../../helpers/prependClassName';
import {
borderWidth,
borderRadius,
color,
size,
inset,
margin,
padding,
fontFamily,
fontScale,
} from '../../styleTokens';
import { elevation } from '../../styles/runtime/elevation';
import * as fontScales from '../../styles/runtime/fontScales';
import { invisible } from '../../styles/runtime/invisible';
import * as sizes from '../../styles/runtime/sizes';
import { withRichContent } from '../../styles/runtime/withRichContent';
import { withTruncatedText } from '../../styles/runtime/withTruncatedText';
export const consumeRcxProps = (props) => {
for (const [key, value] of Object.entries(props)) {
if (key.slice(0, 4) !== 'rcx-') {
continue;
}
delete props[key];
if (!value) {
continue;
}
const newClassName = value === true ? key : `${key}-${value}`;
props.className = prependClassName(props.className, newClassName);
}
return props;
};
const preAliases = {
bg: 'backgroundColor',
w: 'width',
h: 'height',
m: 'margin',
mb: 'marginBlock',
mbs: 'marginBlockStart',
mbe: 'marginBlockEnd',
mi: 'marginInline',
mis: 'marginInlineStart',
mie: 'marginInlineEnd',
p: 'padding',
pb: 'paddingBlock',
pbs: 'paddingBlockStart',
pbe: 'paddingBlockEnd',
pi: 'paddingInline',
pis: 'paddingInlineStart',
pie: 'paddingInlineEnd',
};
export const consumePreAliases = (props) => {
for (const [alias, propName] of Object.entries(preAliases)) {
if (typeof props[alias] === 'undefined') {
continue;
}
if (typeof props[propName] !== 'undefined') {
delete props[alias];
continue;
}
props[propName] = props[alias];
delete props[alias];
}
return props;
};
const specialStylingProps = {
elevation,
invisible,
withRichContent,
withTruncatedText,
size: sizes.size,
minSize: sizes.minSize,
maxSize: sizes.maxSize,
fontScale: fontScales.fontScale,
};
export const consumeSpecialStylingProps = (props) => {
for (const [propName, fn] of Object.entries(specialStylingProps)) {
if (typeof props[propName] === 'undefined') {
continue;
}
props.className = appendClassName(props.className, fn(props[propName]));
delete props[propName];
}
return props;
};
const stringProp = (value) => {
if (typeof value === 'string') {
return value;
}
return undefined;
};
const numberOrStringProp = (value) => {
if (typeof value === 'number' || typeof value === 'string') {
return String(value);
}
return undefined;
};
const fontSizeProp = (value) => fontScale(value)?.fontSize ?? size(value);
const fontWeightProp = (value) => fontScale(value)?.fontWeight ?? value;
const lineHeightProp = (value) => fontScale(value)?.lineHeight ?? size(value);
const letterSpacingProp = (value) => fontScale(value)?.letterSpacing ?? value;
const cssPropertiesProps = {
border: stringProp,
borderBlock: stringProp,
borderBlockStart: stringProp,
borderBlockEnd: stringProp,
borderInline: stringProp,
borderInlineStart: stringProp,
borderInlineEnd: stringProp,
borderWidth,
borderBlockWidth: borderWidth,
borderBlockStartWidth: borderWidth,
borderBlockEndWidth: borderWidth,
borderInlineWidth: borderWidth,
borderInlineStartWidth: borderWidth,
borderInlineEndWidth: borderWidth,
borderStyle: stringProp,
borderBlockStyle: stringProp,
borderBlockStartStyle: stringProp,
borderBlockEndStyle: stringProp,
borderInlineStyle: stringProp,
borderInlineStartStyle: stringProp,
borderInlineEndStyle: stringProp,
borderColor: color,
borderBlockColor: color,
borderBlockStartColor: color,
borderBlockEndColor: color,
borderInlineColor: color,
borderInlineStartColor: color,
borderInlineEndColor: color,
borderRadius,
borderStartStartRadius: borderRadius,
borderStartEndRadius: borderRadius,
borderEndStartRadius: borderRadius,
borderEndEndRadius: borderRadius,
color,
backgroundColor: color,
opacity: numberOrStringProp,
alignItems: stringProp,
alignContent: stringProp,
justifyItems: stringProp,
justifyContent: stringProp,
flexWrap: stringProp,
flexDirection: stringProp,
flexGrow: numberOrStringProp,
flexShrink: numberOrStringProp,
flexBasis: stringProp,
justifySelf: stringProp,
alignSelf: stringProp,
order: numberOrStringProp,
width: size,
minWidth: size,
maxWidth: size,
height: size,
minHeight: size,
maxHeight: size,
display: stringProp,
verticalAlign: stringProp,
overflow: stringProp,
overflowX: stringProp,
overflowY: stringProp,
position: stringProp,
zIndex: numberOrStringProp,
inset,
insetBlock: inset,
insetBlockStart: inset,
insetBlockEnd: inset,
insetInline: inset,
insetInlineStart: inset,
insetInlineEnd: inset,
margin,
marginBlock: margin,
marginBlockStart: margin,
marginBlockEnd: margin,
marginInline: margin,
marginInlineStart: margin,
marginInlineEnd: margin,
padding,
paddingBlock: padding,
paddingBlockStart: padding,
paddingBlockEnd: padding,
paddingInline: padding,
paddingInlineStart: padding,
paddingInlineEnd: padding,
fontFamily,
fontSize: fontSizeProp,
fontStyle: stringProp,
fontWeight: fontWeightProp,
letterSpacing: letterSpacingProp,
lineHeight: lineHeightProp,
textAlign: stringProp,
textTransform: stringProp,
textDecorationLine: stringProp,
};
export const consumeCssPropertiesProps = (props) => {
for (const [propName, fn] of Object.entries(cssPropertiesProps)) {
if (typeof props[propName] === 'undefined') {
continue;
}
const cssProperty = fromCamelToKebab(propName);
const cssValue = fn(props[propName]);
const style = css`
${cssProperty}: ${cssValue} !important;
`;
props.className = appendClassName(props.className, style);
delete props[propName];
}
return props;
};
const postAliases = {
htmlSize: 'size',
};
export const consumePostAliases = (props) => {
for (const [alias, propName] of Object.entries(postAliases)) {
if (typeof props[alias] === 'undefined') {
continue;
}
if (typeof props[propName] !== 'undefined') {
delete props[alias];
continue;
}
props[propName] = props[alias];
delete props[alias];
}
return props;
};
export const consumeBoxProps = (props) => {
if (props.animated) {
props.className = prependClassName(props.className, 'rcx-box--animated');
delete props.animated;
}
props.className = prependClassName(props.className, 'rcx-box--full');
props.className = prependClassName(props.className, 'rcx-box');
return props;
};
import { css } from '@rocket.chat/css-in-js';
import { appendClassName } from '../../helpers/appendClassName';
import { fromCamelToKebab } from '../../helpers/fromCamelToKebab';
import { useStyle } from '../../hooks/useStyle';
import {
borderWidth,
borderRadius,
color,
size,
inset,
margin,
padding,
fontFamily,
fontScale,
} from '../../styleTokens';
import { elevation } from '../../styles/runtime/elevation';
import { invisible } from '../../styles/runtime/invisible';
import { withRichContent } from '../../styles/runtime/withRichContent';
import { withTruncatedText } from '../../styles/runtime/withTruncatedText';
const stringProp = {
toCSSValue: (value) => (typeof value === 'string' ? value : undefined),
};
const numberOrStringProp = {
toCSSValue: (value) => {
if (typeof value === 'number' || typeof value === 'string') {
return String(value);
}
},
};
const borderWidthProp = {
toCSSValue: borderWidth,
};
const borderRadiusProp = {
toCSSValue: borderRadius,
};
const colorProp = {
toCSSValue: color,
};
const sizeProp = {
toCSSValue: size,
};
const insetProp = {
toCSSValue: inset,
};
const marginProp = {
toCSSValue: margin,
};
const paddingProp = {
toCSSValue: padding,
};
const fontFamilyProp = {
toCSSValue: fontFamily,
};
const fontSizeProp = {
toCSSValue: (value) => fontScale(value)?.fontSize || size(value),
};
const fontWeightProp = {
toCSSValue: (value) => fontScale(value)?.fontWeight || value,
};
const lineHeightProp = {
toCSSValue: (value) => fontScale(value)?.lineHeight || size(value),
};
const letterSpacingProp = {
toCSSValue: (value) => fontScale(value)?.letterSpacing || value,
};
const aliasOf = (propName) => ({
aliasOf: propName,
});
const propDefs = {
border: stringProp,
borderBlock: stringProp,
borderBlockStart: stringProp,
borderBlockEnd: stringProp,
borderInline: stringProp,
borderInlineStart: stringProp,
borderInlineEnd: stringProp,
borderWidth: borderWidthProp,
borderBlockWidth: borderWidthProp,
borderBlockStartWidth: borderWidthProp,
borderBlockEndWidth: borderWidthProp,
borderInlineWidth: borderWidthProp,
borderInlineStartWidth: borderWidthProp,
borderInlineEndWidth: borderWidthProp,
borderStyle: stringProp,
borderBlockStyle: stringProp,
borderBlockStartStyle: stringProp,
borderBlockEndStyle: stringProp,
borderInlineStyle: stringProp,
borderInlineStartStyle: stringProp,
borderInlineEndStyle: stringProp,
borderColor: colorProp,
borderBlockColor: colorProp,
borderBlockStartColor: colorProp,
borderBlockEndColor: colorProp,
borderInlineColor: colorProp,
borderInlineStartColor: colorProp,
borderInlineEndColor: colorProp,
borderRadius: borderRadiusProp,
borderStartStartRadius: borderRadiusProp,
borderStartEndRadius: borderRadiusProp,
borderEndStartRadius: borderRadiusProp,
borderEndEndRadius: borderRadiusProp,
color: colorProp,
backgroundColor: colorProp,
bg: aliasOf('backgroundColor'),
opacity: numberOrStringProp,
alignItems: stringProp,
alignContent: stringProp,
justifyItems: stringProp,
justifyContent: stringProp,
flexWrap: stringProp,
flexDirection: stringProp,
flexGrow: numberOrStringProp,
flexShrink: numberOrStringProp,
flexBasis: stringProp,
justifySelf: stringProp,
alignSelf: stringProp,
order: numberOrStringProp,
w: aliasOf('width'),
width: sizeProp,
minWidth: sizeProp,
maxWidth: sizeProp,
h: aliasOf('height'),
height: sizeProp,
minHeight: sizeProp,
maxHeight: sizeProp,
display: stringProp,
verticalAlign: stringProp,
overflow: stringProp,
overflowX: stringProp,
overflowY: stringProp,
position: stringProp,
zIndex: numberOrStringProp,
inset: insetProp,
insetBlock: insetProp,
insetBlockStart: insetProp,
insetBlockEnd: insetProp,
insetInline: insetProp,
insetInlineStart: insetProp,
insetInlineEnd: insetProp,
m: aliasOf('margin'),
margin: marginProp,
mb: aliasOf('marginBlock'),
marginBlock: marginProp,
mbs: aliasOf('marginBlockStart'),
marginBlockStart: marginProp,
mbe: aliasOf('marginBlockEnd'),
marginBlockEnd: marginProp,