@patreon/studio
Version:
Patreon Studio Design System
73 lines • 4.19 kB
JSX
'use client';
import cx from 'classnames';
import React, { memo } from 'react';
import { styled } from 'styled-components';
import { classNameForMarginBottom } from '~/styles/classNameForMarginBottom';
import { classNameForMarginLeft } from '~/styles/classNameForMarginLeft';
import { classNameForMarginRight } from '~/styles/classNameForMarginRight';
import { classNameForMarginTop } from '~/styles/classNameForMarginTop';
import { classNameForPaddingBottom } from '~/styles/classNameForPaddingBottom';
import { classNameForPaddingLeft } from '~/styles/classNameForPaddingLeft';
import { classNameForPaddingRight } from '~/styles/classNameForPaddingRight';
import { classNameForPaddingTop } from '~/styles/classNameForPaddingTop';
import { mergeResponsivePreferringLastValue, unwrapResponsive, wrapResponsive } from '~/utilities/opaque-responsive';
/**
* Wraps the responsive sides and merges them into a single responsive object
* which contains the top, bottom, left and right values.
*/
function wrapAndMergeResponsiveSides({ a, v, h, t, b, l, r }) {
const responsiveA = wrapResponsive(a);
const responsiveV = wrapResponsive(v);
const responsiveH = wrapResponsive(h);
const responsiveT = wrapResponsive(t);
const responsiveB = wrapResponsive(b);
const responsiveL = wrapResponsive(l);
const responsiveR = wrapResponsive(r);
// Cascade the responsive values to get the final responsive value
// for each side: start with all, then override with vertical/horizontal, then the specfic side
const responsiveTop = mergeResponsivePreferringLastValue([responsiveA, responsiveV, responsiveT]);
const responsiveBottom = mergeResponsivePreferringLastValue([responsiveA, responsiveV, responsiveB]);
const responsiveLeft = mergeResponsivePreferringLastValue([responsiveA, responsiveH, responsiveL]);
const responsiveRight = mergeResponsivePreferringLastValue([responsiveA, responsiveH, responsiveR]);
// unusually we need to use `unwrapResponsive` here because we are
// passing the responsive values to the `classNameFor` functions which
// expect a ValueOrResponsive value
return {
top: unwrapResponsive(responsiveTop),
bottom: unwrapResponsive(responsiveBottom),
left: unwrapResponsive(responsiveLeft),
right: unwrapResponsive(responsiveRight),
};
}
function getClassList({ p, pv, ph, pt, pb, pl, pr, m, mv, mh, mt, mb, ml, mr, className, }) {
const padding = wrapAndMergeResponsiveSides({ a: p, v: pv, h: ph, t: pt, b: pb, l: pl, r: pr });
const margin = wrapAndMergeResponsiveSides({ a: m, v: mv, h: mh, t: mt, b: mb, l: ml, r: mr });
return cx(classNameForPaddingTop({ paddingTop: padding.top }), classNameForPaddingBottom({ paddingBottom: padding.bottom }), classNameForPaddingLeft({ paddingLeft: padding.left }), classNameForPaddingRight({ paddingRight: padding.right }), classNameForMarginTop({ marginTop: margin.top }), classNameForMarginBottom({ marginBottom: margin.bottom }), classNameForMarginLeft({ marginLeft: margin.left }), classNameForMarginRight({ marginRight: margin.right }), className);
}
/**
* The spacer component is used to create wrapper divs with the specified
* margins and padding. Allowed values for margins and padding map directly to
* tokens.global.spaceX values.
*
* @example
* <Spacer m={tokens.global.space.x4} pt={tokens.global.space.x8} pb={tokens.global.space.x16}>
* ...
* </Spacer>
*/
export const Spacer = memo(function Spacer({ as = 'div', p, pv, ph, pt, pb, pl, pr, m, mv, mh, mt, mb, ml, mr, className, style, id, 'data-tag': dataTag, children, ...props // aria props
}) {
const Component = as;
const classList = getClassList({ p, pv, ph, pt, pb, pl, pr, m, mv, mh, mt, mb, ml, mr, className });
return (<Component className={classList} style={style} id={id} data-tag={dataTag} {...props}>
{children}
</Component>);
});
/** @deprecated use `Spacer` with `className` and css modules instead. */
export const SpacerWithCss = styled(Spacer).withConfig({
shouldForwardProp: (prop) => !['css'].includes(prop),
}) `
&& {
${({ css: userCss }) => userCss};
}
`;
//# sourceMappingURL=index.jsx.map