UNPKG

@patreon/studio

Version:

Patreon Studio Design System

114 lines 5.74 kB
'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 { unwrapResponsive, mergeResponsivePreferringLastValue, wrapResponsive, } from '../../utilities/opaque-responsive'; import { safeResponsiveClassNameFor } from '../../utilities/responsive-style'; import { useIncrementLogger } from '../IncrementLogger'; /** * 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, incrementLogger, }) { 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(safeResponsiveClassNameFor({ classNameFn: classNameForPaddingTop, props: { paddingTop: padding.top }, incrementLogger, incrementName: 'studio.spacer.responsive_error.padding_top', }), safeResponsiveClassNameFor({ classNameFn: classNameForPaddingBottom, props: { paddingBottom: padding.bottom }, incrementLogger, incrementName: 'studio.spacer.responsive_error.padding_bottom', }), safeResponsiveClassNameFor({ classNameFn: classNameForPaddingLeft, props: { paddingLeft: padding.left }, incrementLogger, incrementName: 'studio.spacer.responsive_error.padding_left', }), safeResponsiveClassNameFor({ classNameFn: classNameForPaddingRight, props: { paddingRight: padding.right }, incrementLogger, incrementName: 'studio.spacer.responsive_error.padding_right', }), safeResponsiveClassNameFor({ classNameFn: classNameForMarginTop, props: { marginTop: margin.top }, incrementLogger, incrementName: 'studio.spacer.responsive_error.margin_top', }), safeResponsiveClassNameFor({ classNameFn: classNameForMarginBottom, props: { marginBottom: margin.bottom }, incrementLogger, incrementName: 'studio.spacer.responsive_error.margin_bottom', }), safeResponsiveClassNameFor({ classNameFn: classNameForMarginLeft, props: { marginLeft: margin.left }, incrementLogger, incrementName: 'studio.spacer.responsive_error.margin_left', }), safeResponsiveClassNameFor({ classNameFn: classNameForMarginRight, props: { marginRight: margin.right }, incrementLogger, incrementName: 'studio.spacer.responsive_error.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 { incrementLoggerOnce: incrementLogger } = useIncrementLogger(); const classList = getClassList({ p, pv, ph, pt, pb, pl, pr, m, mv, mh, mt, mb, ml, mr, className, incrementLogger }); 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) ` && { ${({ css: userCss }) => userCss}; } `; //# sourceMappingURL=index.jsx.map