diff --git a/package.json b/package.json index bf38cc6014..2975e65669 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@docsearch/css": "^3.0.0", "@docsearch/react": "^3.0.0", "@emotion/jest": "^11.2.1", - "@emotion/react": "^11.1.5", + "@emotion/react": "^11.10.4", "@emotion/styled": "^11.10.4", "@hookform/resolvers": "^2.5.0", "@mapbox/rehype-prism": "^0.3.1", @@ -292,8 +292,8 @@ "kind-of": "^6.0.3" }, "peerDependencies": { - "@emotion/react": ">= 11.1.5 <= 11.9.3", - "@emotion/styled": ">= 11.1.5 <= 11.9.3", + "@emotion/react": ">= 11.10.4 <= 12", + "@emotion/styled": ">= 11.10.4 <= 12", "react": ">= 16.8.0 <= 18", "react-dom": ">= 16.8.0 <= 18", "react-is": ">= 16.8.0 <= 18" diff --git a/src/__tests__/__snapshots__/package.test.ts.snap b/src/__tests__/__snapshots__/package.test.ts.snap index 4697cf56a1..3baa1cebf8 100644 --- a/src/__tests__/__snapshots__/package.test.ts.snap +++ b/src/__tests__/__snapshots__/package.test.ts.snap @@ -31,8 +31,8 @@ Object { "module": "esm/index.js", "name": "newskit", "peerDependencies": Object { - "@emotion/react": ">= 11.1.5 <= 11.9.3", - "@emotion/styled": ">= 11.1.5 <= 11.9.3", + "@emotion/react": ">= 11.10.4 <= 12", + "@emotion/styled": ">= 11.10.4 <= 12", "react": ">= 16.8.0 <= 18", "react-dom": ">= 16.8.0 <= 18", "react-is": ">= 16.8.0 <= 18", diff --git a/src/block/__tests__/__snapshots__/block.test.tsx.snap b/src/block/__tests__/__snapshots__/block.test.tsx.snap index 3ab1dba818..13da59d02d 100644 --- a/src/block/__tests__/__snapshots__/block.test.tsx.snap +++ b/src/block/__tests__/__snapshots__/block.test.tsx.snap @@ -8,6 +8,19 @@ exports[`Block with no props renders an unstyled div 1`] = ` `; +exports[`Block with props renders GridLayout with container name and type 1`] = ` + + .emotion-0 { + container-type: inline-size; + container-name: test-container; +} + +
+ +`; + exports[`Block with props renders as span 1`] = ` ( ); StoryBreakpoint.storyName = 'Breakpoint'; +export const StoryContainerQueries = () => { + const QueryBlock = () => ( + 300px)', + value: 'space040', + }, + ], + }} + paddingBlock={{ + rules: [ + { + rule: '@container (width <= 300px)', + value: 'space010', + }, + { + rule: '@container (width > 300px)', + value: 'space040', + }, + ], + }} + > + This block changes padding depending on its container size + + ); + + return ( + + + + + + + + + + + + + ); +}; +StoryContainerQueries.storyName = 'Container Queries'; + export const StoryTransitions = () => ( { const fragment = renderToFragmentWithTheme(Block, props); expect(fragment).toMatchSnapshot(); }); + + test('renders GridLayout with container name and type', () => { + const props: BlockProps = { + containerName: 'test-container', + containerType: 'inline-size', + }; + + const fragment = renderToFragmentWithTheme(Block, props); + expect(fragment).toMatchSnapshot(); + }); }); }); diff --git a/src/block/block.tsx b/src/block/block.tsx index 03a639a304..221563eef6 100644 --- a/src/block/block.tsx +++ b/src/block/block.tsx @@ -6,12 +6,15 @@ import { MQ, getSpacingFromTheme, getStylePresetFromTheme, + ContainerQueryProps, } from '../utils/style'; import {getTransitionPresetFromTheme} from '../utils/style/transition-preset'; +import {containerProps} from '../utils/container-properties'; export interface BlockProps extends React.HTMLAttributes, - LogicalProps { + LogicalProps, + ContainerQueryProps { as?: keyof JSX.IntrinsicElements; stylePreset?: MQ; transitionPreset?: TransitionToken | TransitionToken[]; @@ -32,6 +35,7 @@ const StyledDiv = styled.div` ${({spaceStack}) => spaceStack && getSpacingFromTheme(spaceStack, undefined, 'marginBottom')} ${logicalProps()} + ${containerProps()} ${({transitionPreset}) => transitionPreset && getTransitionPresetFromTheme(transitionPreset)}; `; diff --git a/src/card-composable/__tests__/card-composable.stories.tsx b/src/card-composable/__tests__/card-composable.stories.tsx index cc9e83bfd2..22e05412b0 100644 --- a/src/card-composable/__tests__/card-composable.stories.tsx +++ b/src/card-composable/__tests__/card-composable.stories.tsx @@ -1,6 +1,7 @@ /* eslint-disable no-script-url */ import React from 'react'; import {Story as StoryType} from '@storybook/react'; +import {styled} from '../../utils'; import { CardComposable, @@ -38,6 +39,15 @@ import { stylePresets as stylePresetsTheSun, } from './the-sun-cards'; +const QueryContainerSmall = styled.div` + container-type: inline-size; + width: 300px; +`; +const QueryContainerLarge = styled.div` + container-type: inline-size; + width: 400px; +`; + const H = ({overrides, ...props}: Omit) => ( ( ); StoryLogicalProps.storyName = 'Logical props'; +export const StoryContainerQueries = () => { + const CardWithQueries = () => ( + 300px)', + value: 'space060', + }, + ], + }, + paddingInline: { + rules: [ + { + rule: '@container (width <= 300px)', + value: 'space020', + }, + { + rule: '@container (width > 300px)', + value: 'space060', + }, + ], + }, + }} + rowGap={areasGap} + containerType="inline-size" + > + + Flag + 300px)', + value: 'editorialHeadline040', + }, + ], + }, + }} + > + This headline's typographyPreset changes depending on its + container size + +

+ + + + + Tag + + + + ); + return ( + + + + + + + + + + + + + ); +}; +StoryContainerQueries.storyName = 'Container Queries'; + export const StoryOverrides = () => ( @@ -779,7 +874,6 @@ export const StoryOverrides = () => ( ); StoryOverrides.storyName = 'Styling overrides'; -// https://www.linkedin.com/search/results/content/?keywords=design&origin=FACETED_SEARCH&postedBy=%5B%22first%22%2C%22following%22%5D&sid=xxV&sortBy=%22relevance%22 export const ComplexStory = () => ( diff --git a/src/grid-layout/__tests__/__snapshots__/grid-layout.test.tsx.snap b/src/grid-layout/__tests__/__snapshots__/grid-layout.test.tsx.snap index d9335d5681..b57020d7a4 100644 --- a/src/grid-layout/__tests__/__snapshots__/grid-layout.test.tsx.snap +++ b/src/grid-layout/__tests__/__snapshots__/grid-layout.test.tsx.snap @@ -205,6 +205,22 @@ exports[`GridLayout renders GridLayout with colum/row prop 1`] = ` `; +exports[`GridLayout renders GridLayout with container name and type 1`] = ` + + .emotion-0 { + margin: 0; + padding: 0; + display: grid; + container-type: inline-size; + container-name: test-container; +} + +

+ +`; + exports[`GridLayout renders GridLayout with different areas for different breakpoints 1`] = ` .emotion-0 { diff --git a/src/grid-layout/__tests__/grid-layout.test.tsx b/src/grid-layout/__tests__/grid-layout.test.tsx index 7182c161cc..7540c485ad 100644 --- a/src/grid-layout/__tests__/grid-layout.test.tsx +++ b/src/grid-layout/__tests__/grid-layout.test.tsx @@ -64,6 +64,16 @@ describe('GridLayout', () => { expect(fragment).toMatchSnapshot(); }); + test('renders GridLayout with container name and type', () => { + const props: GridLayoutProps = { + containerName: 'test-container', + containerType: 'inline-size', + }; + + const fragment = renderToFragmentWithTheme(GridLayout, props); + expect(fragment).toMatchSnapshot(); + }); + test('renders GridLayout with different areas for different breakpoints', () => { const props: GridLayoutProps = { areas: { diff --git a/src/grid-layout/__tests__/stories/grid-layout.stories.tsx b/src/grid-layout/__tests__/stories/grid-layout.stories.tsx index 5bf58a815f..95fcc18196 100644 --- a/src/grid-layout/__tests__/stories/grid-layout.stories.tsx +++ b/src/grid-layout/__tests__/stories/grid-layout.stories.tsx @@ -9,6 +9,8 @@ import {Label} from '../../..'; import { StorybookHeading, StorybookSubHeading, + StorybookCase, + StorybookPage, } from '../../../test/storybook-comps'; const BigRedBlock = styled(Block)` @@ -163,6 +165,56 @@ export const StoryResponsiveExample = () => ( ); StoryResponsiveExample.storyName = 'responsive'; +export const StoryContainerQueryExample = () => { + const QueryGridLayout = () => ( + 200px)', + value: '1fr', + }, + ], + }} + columns={{ + rules: [ + { + rule: '@container (width <= 200px)', + value: '1fr', + }, + { + rule: '@container (width > 200px)', + value: '1fr 1fr', + }, + ], + }} + > + 1 + 2 + + ); + + return ( + + + + + + + + + + + + + ); +}; +StoryContainerQueryExample.storyName = 'Container Queries'; + export const StoryMinMaxRepeat = () => { const boxes = Array.from(Array(20)).map((_, i) => {i} box); return ( diff --git a/src/grid-layout/styled.ts b/src/grid-layout/styled.ts index 4f0e1613e1..ba7b2b2d6d 100644 --- a/src/grid-layout/styled.ts +++ b/src/grid-layout/styled.ts @@ -2,6 +2,7 @@ import {Theme} from '../theme'; import {logicalProps} from '../utils/logical-properties'; import {getResponsiveSize, handleResponsiveProp, styled} from '../utils/style'; import {GridLayoutProps} from './types'; +import {containerProps} from '../utils/container-properties'; const GRID_DEFAULT_PROPS = { rowGap: undefined, @@ -121,4 +122,5 @@ export const StyledGridLayout = styled.div` ${getResponsiveSize('minHeight', 'gridLayout', '', 'minHeight')}; ${getResponsiveSize('maxHeight', 'gridLayout', '', 'maxHeight')}; ${logicalProps('gridLayout')} + ${containerProps()} `; diff --git a/src/grid-layout/types.ts b/src/grid-layout/types.ts index e2db2035f0..e86f5c9cf6 100644 --- a/src/grid-layout/types.ts +++ b/src/grid-layout/types.ts @@ -1,5 +1,5 @@ import React from 'react'; -import {MQ} from '../utils/style'; +import {ContainerQueryProps, MQ, ResponsiveValue} from '../utils/style'; import {BlockProps} from '../block'; import {LogicalProps} from '../utils/logical-properties'; @@ -19,29 +19,29 @@ export type AreasMap = { export type GridLayoutRenderProps = (areas: AreasMap) => React.ReactNode; -export type GridLayoutProps = { - rowGap?: MQ; - columnGap?: MQ; - rows?: MQ; - columns?: MQ; - justifyContent?: MQ; - alignContent?: MQ; - justifyItems?: MQ; - alignItems?: MQ; - areas?: MQ; - inline?: MQ; - autoColumns?: MQ; - autoRows?: MQ; - autoFlow?: MQ; +export type GridLayoutProps = ContainerQueryProps & { + rowGap?: ResponsiveValue; + columnGap?: ResponsiveValue; + rows?: ResponsiveValue; + columns?: ResponsiveValue; + justifyContent?: ResponsiveValue; + alignContent?: ResponsiveValue; + justifyItems?: ResponsiveValue; + alignItems?: ResponsiveValue; + areas?: ResponsiveValue; + inline?: ResponsiveValue; + autoColumns?: ResponsiveValue; + autoRows?: ResponsiveValue; + autoFlow?: ResponsiveValue; children?: React.ReactNode | GridLayoutRenderProps; // eslint-disable-next-line @typescript-eslint/no-explicit-any as?: React.ElementType; overrides?: { - width?: MQ; - minWidth?: MQ; - maxWidth?: MQ; - height?: MQ; - minHeight?: MQ; - maxHeight?: MQ; + width?: ResponsiveValue; + minWidth?: ResponsiveValue; + maxWidth?: ResponsiveValue; + height?: ResponsiveValue; + minHeight?: ResponsiveValue; + maxHeight?: ResponsiveValue; } & LogicalProps; } & Omit, 'children'>; diff --git a/src/grid-layout/utils.ts b/src/grid-layout/utils.ts index eb53e801c3..d06c4b92da 100644 --- a/src/grid-layout/utils.ts +++ b/src/grid-layout/utils.ts @@ -1,4 +1,4 @@ -import {MQ} from '../utils/style'; +import {ResponsiveValue} from '../utils/style'; import {uniq} from '../utils/uniq'; export const capitalize = (s: string) => @@ -15,7 +15,7 @@ export const extractAreas = (areaString: string) => export const filterInvalidAreas = (areaName: string): boolean => areaName !== '.' && Boolean(areaName); -export const getAreasList = (areas: MQ): string[] => { +export const getAreasList = (areas: ResponsiveValue): string[] => { if (typeof areas === 'string') { return uniq(extractAreas(areas)); } diff --git a/src/headline/types.ts b/src/headline/types.ts index 5f6a798a6b..c7cd98630e 100644 --- a/src/headline/types.ts +++ b/src/headline/types.ts @@ -1,14 +1,14 @@ -import {MQ} from '../utils/style'; +import {ResponsiveValue} from '../utils/style'; import {LogicalProps} from '../utils/logical-properties'; export interface HeadlineOverrides extends LogicalProps { - typographyPreset?: MQ; + typographyPreset?: ResponsiveValue; kicker?: { - stylePreset?: MQ; - spaceInline?: MQ; + stylePreset?: ResponsiveValue; + spaceInline?: ResponsiveValue; }; heading?: { - stylePreset?: MQ; + stylePreset?: ResponsiveValue; }; } diff --git a/src/newskit-provider/__tests__/__snapshots__/newskitprovider.test.tsx.snap b/src/newskit-provider/__tests__/__snapshots__/newskitprovider.test.tsx.snap index 1760dc8bfe..171f832f55 100644 --- a/src/newskit-provider/__tests__/__snapshots__/newskitprovider.test.tsx.snap +++ b/src/newskit-provider/__tests__/__snapshots__/newskitprovider.test.tsx.snap @@ -149,15 +149,10 @@ exports[`NewsKitProvider renders (slowly) with css variables and theme cache mis --borderRadiusCircle: 50%; --borderRadiusPill: 20rem; --borderRadiusDefault: 8px; - -webkit---borderRadiusRounded010: 4px; --borderRadiusRounded010: 4px; - -webkit---borderRadiusRounded020: 8px; --borderRadiusRounded020: 8px; - -webkit---borderRadiusRounded030: 12px; --borderRadiusRounded030: 12px; - -webkit---borderRadiusRounded040: 16px; --borderRadiusRounded040: 16px; - -webkit---borderRadiusRounded050: 24px; --borderRadiusRounded050: 24px; --color-blue010: #ECF1FF; --color-blue020: #D5E0FC; @@ -639,15 +634,10 @@ exports[`NewsKitProvider renders (slowly) with css variables and theme cache mis --borderRadiusCircle: 50%; --borderRadiusPill: 20rem; --borderRadiusDefault: 8px; - -webkit---borderRadiusRounded010: 4px; --borderRadiusRounded010: 4px; - -webkit---borderRadiusRounded020: 8px; --borderRadiusRounded020: 8px; - -webkit---borderRadiusRounded030: 12px; --borderRadiusRounded030: 12px; - -webkit---borderRadiusRounded040: 16px; --borderRadiusRounded040: 16px; - -webkit---borderRadiusRounded050: 24px; --borderRadiusRounded050: 24px; --color-blue010: #ECF1FF; --color-blue020: #D5E0FC; diff --git a/src/text-block/__tests__/text-block.stories.tsx b/src/text-block/__tests__/text-block.stories.tsx index 05cb85be53..2b137e1bca 100644 --- a/src/text-block/__tests__/text-block.stories.tsx +++ b/src/text-block/__tests__/text-block.stories.tsx @@ -5,12 +5,20 @@ import {ThemeProvider, CreateThemeArgs} from '../../theme'; import {StorybookCase, StorybookPage} from '../../test/storybook-comps'; import {getColorCssFromTheme, styled} from '../../utils'; import {createCustomThemeWithBaseThemeSwitch} from '../../test/theme-select-object'; +import {Block} from '../../block'; const textBlockCustomThemeObject: CreateThemeArgs = { name: 'textblock-custom-theme', overrides: { stylePresets: { textBlockCustom: {base: {color: '{{colors.inkBrand010}}'}}, + blockContainerQueryWrapper: { + base: { + borderStyle: 'dashed', + borderWidth: '{{borders.borderWidth010}}', + borderColor: '{{colors.blue060}}', + }, + }, }, typographyPresets: { textBlockCustom: {fontFamily: '{{fonts.fontFamily020.fontFamily}}'}, @@ -71,6 +79,58 @@ export const StoryTextBlockLogicalProps = () => ( ); StoryTextBlockLogicalProps.storyName = 'Logical props'; +export const StoryTextBlockContainerQueries = () => { + const QueryTextBlock = () => ( + 300px)', + value: 'editorialParagraph030', + }, + ], + }} + stylePreset="inkContrast" + > + {BODY} + + ); + + return ( + + + + + + + + + + + + + ); +}; +StoryTextBlockContainerQueries.storyName = 'Container Queries'; + export const StoryTextBlockStylingOverrides = () => ( diff --git a/src/text-block/types.ts b/src/text-block/types.ts index a7fcc34afa..0e9c8d5b43 100644 --- a/src/text-block/types.ts +++ b/src/text-block/types.ts @@ -1,12 +1,12 @@ import React from 'react'; import {LogicalProps} from '../utils/logical-properties'; -import {MQ} from '../utils/style'; +import {ResponsiveValue} from '../utils/style'; export interface TextBlockProps extends React.HTMLAttributes, LogicalProps { - typographyPreset?: MQ; - stylePreset?: MQ; + typographyPreset?: ResponsiveValue; + stylePreset?: ResponsiveValue; noCrop?: boolean; as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'div' | 'span'; } diff --git a/src/theme/__tests__/__snapshots__/theme-provider.test.tsx.snap b/src/theme/__tests__/__snapshots__/theme-provider.test.tsx.snap index 7d3f2a136d..a39634d65a 100644 --- a/src/theme/__tests__/__snapshots__/theme-provider.test.tsx.snap +++ b/src/theme/__tests__/__snapshots__/theme-provider.test.tsx.snap @@ -12,15 +12,10 @@ exports[`ThemeProvider renders as css variables 1`] = ` --borderRadiusCircle: 50%; --borderRadiusPill: 20rem; --borderRadiusDefault: 8px; - -webkit---borderRadiusRounded010: 4px; --borderRadiusRounded010: 4px; - -webkit---borderRadiusRounded020: 8px; --borderRadiusRounded020: 8px; - -webkit---borderRadiusRounded030: 12px; --borderRadiusRounded030: 12px; - -webkit---borderRadiusRounded040: 16px; --borderRadiusRounded040: 16px; - -webkit---borderRadiusRounded050: 24px; --borderRadiusRounded050: 24px; --color-blue010: #ECF1FF; --color-blue020: #D5E0FC; @@ -371,15 +366,10 @@ exports[`ThemeProvider renders as css variables in nested providers 1`] = ` --borderRadiusCircle: 50%; --borderRadiusPill: 20rem; --borderRadiusDefault: 8px; - -webkit---borderRadiusRounded010: 4px; --borderRadiusRounded010: 4px; - -webkit---borderRadiusRounded020: 8px; --borderRadiusRounded020: 8px; - -webkit---borderRadiusRounded030: 12px; --borderRadiusRounded030: 12px; - -webkit---borderRadiusRounded040: 16px; --borderRadiusRounded040: 16px; - -webkit---borderRadiusRounded050: 24px; --borderRadiusRounded050: 24px; --color-blue010: #ECF1FF; --color-blue020: #D5E0FC; diff --git a/src/utils/__tests__/base.test.ts b/src/utils/__tests__/base.test.ts index 5d7b7ad669..68575d5e54 100644 --- a/src/utils/__tests__/base.test.ts +++ b/src/utils/__tests__/base.test.ts @@ -1,6 +1,9 @@ import {createTheme, compileTheme} from '../../theme'; -import {getSizingCssFromTheme} from '../style/getters'; -import {getXFromTheme} from '../style/base'; +import { + getSizingCssFromTheme, + getTypographyPresetFromTheme, +} from '../style/getters'; +import {getXFromTheme, getDefaultedValue} from '../style/base'; import { getResponsiveSize, getResponsiveSpace, @@ -58,7 +61,38 @@ describe('getXFromTheme', () => { '@media screen and (min-width: 768px)': {width: '12px'}, }); }); - + test('getXFromTheme with Container Query value', () => { + const result = getXFromTheme('sizing')('width', { + rules: [{rule: '@container (min-width: 300px)', value: '4px'}], + })({theme}); + expect(result).toEqual({ + '@container (min-width: 300px)': {width: '4px'}, + }); + }); + test('getXFromTheme – spacePreset with Container Query value', () => { + const result = getXFromTheme('spacePresets')('padding', { + rules: [{rule: '@container (min-width: 300px)', value: 'space010'}], + })({theme}); + expect(result).toEqual({ + '@container (min-width: 300px)': {padding: '4px'}, + }); + }); + test('getXFromTheme with CQ & MQ value', () => { + const result = getXFromTheme('sizing')('width', { + xs: 'sizing010', + sm: 'sizing020', + rules: [{rule: '@container (min-width: 300px)', value: '4px'}], + })({theme}); + expect(result).toEqual({ + '@media screen and (max-width: 479px)': { + width: '4px', + }, + '@media screen and (min-width: 480px)': { + width: '8px', + }, + '@container (min-width: 300px)': {width: '4px'}, + }); + }); test('getXFromTheme with non MQ and callback', () => { const cb = (value: string) => ({padding: `${value} 0`, width: value}); const result = getXFromTheme('sizing')(cb, 'sizing050')({theme}); diff --git a/src/utils/__tests__/container-properties.test.ts b/src/utils/__tests__/container-properties.test.ts new file mode 100644 index 0000000000..3fff50d29b --- /dev/null +++ b/src/utils/__tests__/container-properties.test.ts @@ -0,0 +1,35 @@ +import {containerProps} from '../container-properties'; // Import the module you want to test +import {ContainerQueryProps} from '../style'; + +describe('containerProps', () => { + test('returns a CSSObject with containerType and containerName', () => { + const props: ContainerQueryProps = { + containerType: 'inline-size', + containerName: 'containerName', + }; + const result = containerProps()(props); + expect(result).toEqual({ + containerType: 'inline-size', + containerName: 'containerName', + }); + }); + + test('returns an empty CSSObject when props is an empty object', () => { + const props = {}; + const result = containerProps()(props); + const expected = {}; + + expect(result).toEqual(expected); + }); + test('should return undefined values when props is undefined', () => { + const props = undefined; + + // @ts-ignore next-line + const result = containerProps()(props); + console.log(result); + expect(result).toEqual({ + containerType: undefined, + containerName: undefined, + }); + }); +}); diff --git a/src/utils/__tests__/responsive-props.test.ts b/src/utils/__tests__/responsive-props.test.ts index a32939303d..500defc5a3 100644 --- a/src/utils/__tests__/responsive-props.test.ts +++ b/src/utils/__tests__/responsive-props.test.ts @@ -2,7 +2,7 @@ import {handleResponsiveProp} from '../style/getters'; import {createTheme} from '../../theme'; describe('handleResponsiveProp', () => { - type DisplayObj = {display: string}; + type DisplayObj = {display: string | undefined}; const theme: any = createTheme({}); const handler = ({display}: DisplayObj) => ({display}); @@ -49,6 +49,27 @@ describe('handleResponsiveProp', () => { }); }); + it('using CQ rules value', () => { + const props = { + display: { + rules: [ + {rule: '@container (width < 200px)', value: 'inline'}, + {rule: '@container (width >= 200px)', value: 'block'}, + ], + }, + theme, + }; + const result = handleResponsiveProp({display: undefined}, handler)(props); + expect(result).toEqual({ + '@container (width < 200px)': { + display: 'inline', + }, + '@container (width >= 200px)': { + display: 'block', + }, + }); + }); + it('does not have XS value', () => { const props = { display: {sm: 'inline', md: 'block'}, diff --git a/src/utils/container-properties.ts b/src/utils/container-properties.ts new file mode 100644 index 0000000000..aa1515e4b0 --- /dev/null +++ b/src/utils/container-properties.ts @@ -0,0 +1,6 @@ +import {ContainerQueryProps, CSSObject} from './style'; + +export const containerProps = () => (props: ContainerQueryProps) => { + const {containerType, containerName} = props || {}; + return {containerType, containerName} as CSSObject; +}; diff --git a/src/utils/logical-properties.ts b/src/utils/logical-properties.ts index e8bcbadea6..ea482fa758 100644 --- a/src/utils/logical-properties.ts +++ b/src/utils/logical-properties.ts @@ -1,25 +1,30 @@ -import {CSSObject, getTypographyPreset, getXFromTheme, MQ} from './style'; +import { + CSSObject, + getTypographyPreset, + getXFromTheme, + ResponsiveValue, +} from './style'; import {ThemeProp} from './style-types'; import {deepMerge} from './deep-merge'; import {get} from './get'; import {filterObject, rejectObject} from './filter-object'; export interface LogicalMarginProps { - marginInlineStart?: MQ; - marginInlineEnd?: MQ; - marginInline?: MQ; - marginBlockStart?: MQ; - marginBlockEnd?: MQ; - marginBlock?: MQ; + marginInlineStart?: ResponsiveValue; + marginInlineEnd?: ResponsiveValue; + marginInline?: ResponsiveValue; + marginBlockStart?: ResponsiveValue; + marginBlockEnd?: ResponsiveValue; + marginBlock?: ResponsiveValue; } export interface LogicalPaddingProps { - paddingInlineStart?: MQ; - paddingInlineEnd?: MQ; - paddingInline?: MQ; - paddingBlockStart?: MQ; - paddingBlockEnd?: MQ; - paddingBlock?: MQ; + paddingInlineStart?: ResponsiveValue; + paddingInlineEnd?: ResponsiveValue; + paddingInline?: ResponsiveValue; + paddingBlockStart?: ResponsiveValue; + paddingBlockEnd?: ResponsiveValue; + paddingBlock?: ResponsiveValue; } export interface LogicalProps extends LogicalMarginProps, LogicalPaddingProps {} diff --git a/src/utils/responsive-helpers.ts b/src/utils/responsive-helpers.ts index 34a3361c78..195126039c 100644 --- a/src/utils/responsive-helpers.ts +++ b/src/utils/responsive-helpers.ts @@ -47,7 +47,8 @@ export const getMediaQueryFromTheme = ( export const isResponsive = ( prop: unknown, breakpoints: Breakpoints, -): prop is Record => +): prop is Record => !!prop && typeof prop === 'object' && - Object.keys(breakpoints).some(bp => prop && hasOwnProperty(prop, bp)); + (Object.keys(breakpoints).some(bp => prop && hasOwnProperty(prop, bp)) || + hasOwnProperty(prop, 'rules')); diff --git a/src/utils/style/base.ts b/src/utils/style/base.ts index fca9eb09df..c4bdf49581 100644 --- a/src/utils/style/base.ts +++ b/src/utils/style/base.ts @@ -3,7 +3,7 @@ import {isResponsive, getMediaQueryFromTheme} from '../responsive-helpers'; import {filterObject} from '../filter-object'; import {getToken} from '../get-token'; import {ThemeProp} from '../style-types'; -import {MQ} from './types'; +import {CSSQuery, MQ, ResponsiveValue} from './types'; import {isNonThemeValueAllowed, isValidUnit} from './utils'; import {CSSObject} from './emotion'; @@ -51,7 +51,7 @@ export const getValueFromTheme = ( export const getResponsiveValueFromTheme = ( themeKey: keyof Theme, ) => ( - defaultToken?: MQ, + defaultToken?: ResponsiveValue, customProp?: Exclude, ) => ({theme, ...props}: Props) => { const section = theme[themeKey] as Record; @@ -76,7 +76,7 @@ export const getResponsiveValueFromTheme = ( ([a], [b]) => mq.indexOf(a as BreakpointKeys) - mq.indexOf(b as BreakpointKeys), ) as any; // eslint-disable-line @typescript-eslint/no-explicit-any - const cssObject = presetKeys + const cssMediaQueryObject = presetKeys .filter( // Exclude invalid breakpoints and theme section keys ([breakpointKey, presetKey]) => @@ -114,7 +114,27 @@ export const getResponsiveValueFromTheme = ( return acc; }, {} as Record); - return Object.entries(cssObject); + const containerKeys = (propKeys.rules || []) as CSSQuery[]; + + const cssContainerQueryObject = + containerKeys && + containerKeys.reduce((acc, query) => { + const {rule, value} = query; + let preset = '' as Record[ThemeToken]; + const MQtokens = + typeof value === 'string' && (value as string).split(' '); + if (themeKey === 'spacePresets' && isMQTokenArray(MQtokens)) { + preset = mapTokensArray(MQtokens); + } else { + preset = + section[value] || + (canHaveNonThemeValue && isValidUnit(themeKey, value) && value); + } + acc[rule] = preset; + return acc; + }, {} as Record); + + return Object.entries({...cssMediaQueryObject, ...cssContainerQueryObject}); } const noMQtokens = @@ -142,7 +162,7 @@ export const getXFromTheme = (themeKey: keyof Theme) => < Props extends ThemeProp >( cssProperty: string | FromThemeCallback, - defaultToken: MQ, + defaultToken: ResponsiveValue, ) => (props: Props) => { const value = getResponsiveValueFromTheme(themeKey)(defaultToken)( props, diff --git a/src/utils/style/getters.ts b/src/utils/style/getters.ts index 3f110b381c..ad4d4ad59c 100644 --- a/src/utils/style/getters.ts +++ b/src/utils/style/getters.ts @@ -3,7 +3,7 @@ import {getFontSizing} from '../font-sizing'; import {BreakpointKeys, TypographyPreset} from '../../theme'; import {isFontConfigObject} from '../guards'; import {ThemeProp} from '../style-types'; -import {MQ, MQPartial} from './types'; +import {CSSQuery, CSSQueryRules, MQ, MQPartial, ResponsiveValue} from './types'; import { getResponsiveValueFromTheme, getValueFromTheme, @@ -15,7 +15,7 @@ import {textCrop} from '../text-crop'; import {getFontMetrics} from './helpers/getter-helper'; export const getTypographyPresetFromTheme = ( - defaultToken?: MQ, + defaultToken?: ResponsiveValue, customProp?: Exclude, options?: {withCrop: boolean}, ) => (props: Props) => { @@ -201,7 +201,6 @@ export const handleResponsiveProp = ( ) => string | CSSObject, ) => (props: Props): string | CSSObject => { const {breakpoints} = props.theme; - const propNames = Object.keys(propObject); // get only props that we will use @@ -210,7 +209,7 @@ export const handleResponsiveProp = ( return {...acc, [propName]: props[propName]}; } return acc; - }, {}) as {[Key in keyof T]: MQ}; + }, {}) as {[Key in keyof T]: ResponsiveValue}; const propsValues = Object.values(usedProps) as MQ[]; @@ -243,6 +242,7 @@ export const handleResponsiveProp = ( .flatMap( (propValue: MQ) => Object.keys(propValue) as BreakpointKeys[], ) + .filter((item: BreakpointKeys | 'rules') => item !== 'rules') .filter( (item: BreakpointKeys, index: number, ar: BreakpointKeys[]) => ar.indexOf(item) === index, @@ -308,30 +308,66 @@ export const handleResponsiveProp = ( ? commonMQKeys : ['xs', ...commonMQKeys]; - const cssObject = usedMQKeys.reduce((acc, mqKey, index) => { - const fromMqKey = mqKey; - const toMqKey = usedMQKeys[index + 1] ? usedMQKeys[index + 1] : undefined; + let cssMediaQueryObject = {}; + if (commonMQKeys.length > 0) { + cssMediaQueryObject = usedMQKeys.reduce((acc, mqKey, index) => { + const fromMqKey = mqKey; + const toMqKey = usedMQKeys[index + 1] ? usedMQKeys[index + 1] : undefined; - const mediaQuery = getMediaQueryFromTheme(fromMqKey, toMqKey)(props); - const values = propNames.reduce((valAcc, propName) => { - // TS needs checking if prop is part of the object otherwise throw error - /* istanbul ignore else */ - if (hasOwnProperty(filledPropValues, propName)) { - const mqValue = filledPropValues[propName as keyof T]; + const mediaQuery = getMediaQueryFromTheme(fromMqKey, toMqKey)(props); + const values = propNames.reduce((valAcc, propName) => { + // TS needs checking if prop is part of the object otherwise throw error /* istanbul ignore else */ - if (hasOwnProperty(mqValue, fromMqKey)) { - return { - ...valAcc, - [propName]: mqValue[fromMqKey], - }; + if (hasOwnProperty(filledPropValues, propName)) { + const mqValue = filledPropValues[propName as keyof T]; + /* istanbul ignore else */ + if (hasOwnProperty(mqValue, fromMqKey)) { + return { + ...valAcc, + [propName]: mqValue[fromMqKey], + }; + } } + /* istanbul ignore next */ + return valAcc; + }, {}) as {[Key in keyof T]: T[Key]}; + acc[mediaQuery] = propHandler(values, props, fromMqKey); + return acc; + }, {} as Record) as CSSObject; + } + + /* + If they've defined container queries using the 'rules' + */ + + const usedValues = Object.entries(usedProps).filter(usedProp => { + const propValue = usedProp[1]; + return ( + propValue && + typeof propValue === 'object' && + hasOwnProperty(propValue, 'rules') && + Array.isArray(propValue.rules) && + propValue.rules.length > 0 + ); + }) as [string, CSSQueryRules][]; + + const cssContainerQueryObject: Record< + CSSQuery['rule'], + string | CSSObject + > = usedValues.reduce( + (acc: Record['rule'], string | CSSObject>, prop) => { + const values = {} as {[Key in keyof T]: T[Key]}; + if (prop[1].rules) { + prop[1].rules.forEach(rule => { + const key = `${prop[0]}` as keyof T; + values[key] = rule.value; + acc[rule.rule] = propHandler(values, props, undefined); + }); } - /* istanbul ignore next */ - return valAcc; - }, {}) as {[Key in keyof T]: T[Key]}; - acc[mediaQuery] = propHandler(values, props, fromMqKey); - return acc; - }, {} as Record) as CSSObject; + return acc; + }, + {}, + ); - return cssObject; + return {...cssMediaQueryObject, ...cssContainerQueryObject}; }; diff --git a/src/utils/style/style-preset.ts b/src/utils/style/style-preset.ts index a514d7ed99..51f7d27d7e 100644 --- a/src/utils/style/style-preset.ts +++ b/src/utils/style/style-preset.ts @@ -9,7 +9,7 @@ import {filterObject, rejectObject} from '../filter-object'; import {ThemeProp} from '../style-types'; import {getDefaultedValue, getResponsiveValueFromTheme} from './base'; import {CSSObject} from './emotion'; -import {MQ} from './types'; +import {ResponsiveValue} from './types'; export interface GetStylePresetFromThemeOptions { nestedCssSelector?: string; @@ -241,7 +241,7 @@ const getStylePresetValueFromTheme = ( ); export const getStylePresetFromTheme = ( - defaultToken?: MQ, + defaultToken?: ResponsiveValue, customProp?: Exclude, options?: GetStylePresetFromThemeOptions, ) => (props: Props) => { diff --git a/src/utils/style/types.ts b/src/utils/style/types.ts index 805acd1a61..5ca7617637 100644 --- a/src/utils/style/types.ts +++ b/src/utils/style/types.ts @@ -7,3 +7,34 @@ export type MQPartial = Partial<{ }>; export type MQ = T | MQPartial; + +/* +Allows you define values at set breakpoints, or define custom media & container queries with the "rules" object +*/ +export type ResponsiveValue = MQ | CSSQueryRules; + +/* + @param rule - The media or container query definition + @param value - CSS value or token +*/ +export type CSSQuery = { + rule: `@media ${string}` | `@container ${string}`; + value: T; +}; + +export type CSSQueryRules = { + rules?: CSSQuery[]; +}; + +export type ContainerQueryProps = { + containerType?: + | `normal` + | `inline-size` + | `size` + | `inherit` + | `initial` + | `unset` + | `revert` + | `revert-layer`; + containerName?: string; +}; diff --git a/src/utils/style/utils.ts b/src/utils/style/utils.ts index f88d275760..df869f3835 100644 --- a/src/utils/style/utils.ts +++ b/src/utils/style/utils.ts @@ -32,6 +32,12 @@ export const CSSUnits = [ 'vmin', 'vmax', '%', + 'cqw', + 'cqh', + 'cqi', + 'cqb', + 'cqmin', + 'cqmax', ]; export const CSSColorNames = [ diff --git a/yarn.lock b/yarn.lock index b31f08d32b..eee6a654d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1308,13 +1308,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.7.2": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-jsx@^7.18.6", "@babel/plugin-syntax-jsx@^7.21.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz#f264ed7bf40ffc9ec239edabc17a50c4f5b6fea2" @@ -1322,6 +1315,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" @@ -2750,23 +2750,22 @@ "@babel/runtime" "^7.12.13" "@emotion-icons/emotion-icon" "4.0.0" -"@emotion/babel-plugin@^11.10.0": - version "11.10.2" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz#879db80ba622b3f6076917a1e6f648b1c7d008c7" - integrity sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA== +"@emotion/babel-plugin@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" + integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== dependencies: "@babel/helper-module-imports" "^7.16.7" - "@babel/plugin-syntax-jsx" "^7.17.12" "@babel/runtime" "^7.18.3" - "@emotion/hash" "^0.9.0" - "@emotion/memoize" "^0.8.0" - "@emotion/serialize" "^1.1.0" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/serialize" "^1.1.2" babel-plugin-macros "^3.1.0" convert-source-map "^1.5.0" escape-string-regexp "^4.0.0" find-root "^1.1.0" source-map "^0.5.7" - stylis "4.0.13" + stylis "4.2.0" "@emotion/babel-utils@^0.6.4": version "0.6.10" @@ -2780,16 +2779,16 @@ find-root "^1.1.0" source-map "^0.7.2" -"@emotion/cache@^11.6.0": - version "11.6.0" - resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.6.0.tgz" - integrity sha512-ElbsWY1KMwEowkv42vGo0UPuLgtPYfIs9BxxVrmvsaJVvktknsHYYlx5NQ5g6zLDcOTyamlDc7FkRg2TAcQDKQ== +"@emotion/cache@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== dependencies: - "@emotion/memoize" "^0.7.4" - "@emotion/sheet" "^1.1.0" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" - stylis "^4.0.10" + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" "@emotion/css-prettifier@^1.0.0": version "1.0.0" @@ -2804,10 +2803,10 @@ resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.6.tgz" integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ== -"@emotion/hash@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" - integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== +"@emotion/hash@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" + integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== "@emotion/is-prop-valid@^1.0.0": version "1.1.1" @@ -2816,13 +2815,20 @@ dependencies: "@emotion/memoize" "^0.7.4" -"@emotion/is-prop-valid@^1.1.0", "@emotion/is-prop-valid@^1.2.0": +"@emotion/is-prop-valid@^1.1.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg== dependencies: "@emotion/memoize" "^0.8.0" +"@emotion/is-prop-valid@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc" + integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw== + dependencies: + "@emotion/memoize" "^0.8.1" + "@emotion/jest@^11.2.1": version "11.6.0" resolved "https://registry.npmjs.org/@emotion/jest/-/jest-11.6.0.tgz" @@ -2849,17 +2855,23 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== -"@emotion/react@^11.1.5": - version "11.6.0" - resolved "https://registry.npmjs.org/@emotion/react/-/react-11.6.0.tgz" - integrity sha512-23MnRZFBN9+D1lHXC5pD6z4X9yhPxxtHr6f+iTGz6Fv6Rda0GdefPrsHL7otsEf+//7uqCdT5QtHeRxHCERzuw== +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== + +"@emotion/react@^11.10.4": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.0.tgz#408196b7ef8729d8ad08fc061b03b046d1460e02" + integrity sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw== dependencies: - "@babel/runtime" "^7.13.10" - "@emotion/cache" "^11.6.0" - "@emotion/serialize" "^1.0.2" - "@emotion/sheet" "^1.1.0" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.2" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" hoist-non-react-statics "^3.3.1" "@emotion/serialize@^0.9.1": @@ -2872,33 +2884,33 @@ "@emotion/unitless" "^0.6.7" "@emotion/utils" "^0.8.2" -"@emotion/serialize@^1.0.2", "@emotion/serialize@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.0.tgz#b1f97b1011b09346a40e9796c37a3397b4ea8ea8" - integrity sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA== +"@emotion/serialize@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.2.tgz#017a6e4c9b8a803bd576ff3d52a0ea6fa5a62b51" + integrity sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA== dependencies: - "@emotion/hash" "^0.9.0" - "@emotion/memoize" "^0.8.0" - "@emotion/unitless" "^0.8.0" - "@emotion/utils" "^1.2.0" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/unitless" "^0.8.1" + "@emotion/utils" "^1.2.1" csstype "^3.0.2" -"@emotion/sheet@^1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz" - integrity sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g== +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== "@emotion/styled@^11.10.4": - version "11.10.4" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.4.tgz#e93f84a4d54003c2acbde178c3f97b421fce1cd4" - integrity sha512-pRl4R8Ez3UXvOPfc2bzIoV8u9P97UedgHS4FPX594ntwEuAMA114wlaHvOK24HB48uqfXiGlYIZYCxVJ1R1ttQ== + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346" + integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.10.0" - "@emotion/is-prop-valid" "^1.2.0" - "@emotion/serialize" "^1.1.0" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" - "@emotion/utils" "^1.2.0" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/is-prop-valid" "^1.2.1" + "@emotion/serialize" "^1.1.2" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" "@emotion/stylis@^0.7.0": version "0.7.1" @@ -2920,30 +2932,30 @@ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@emotion/unitless@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" - integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== +"@emotion/unitless@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== -"@emotion/use-insertion-effect-with-fallbacks@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz#ffadaec35dbb7885bd54de3fa267ab2f860294df" - integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A== +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963" + integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== "@emotion/utils@^0.8.2": version "0.8.2" resolved "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz" integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw== -"@emotion/utils@^1.0.0", "@emotion/utils@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" - integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== -"@emotion/weak-memoize@^0.2.5": - version "0.2.5" - resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz" - integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== "@esbuild/android-arm64@0.16.3": version "0.16.3" @@ -21336,10 +21348,10 @@ stylis-rule-sheet@^0.0.10: resolved "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz" integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== -stylis@4.0.13: - version "4.0.13" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" - integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== stylis@^3.5.0: version "3.5.4"