diff --git a/config/rollup/create-package-config.ts b/config/rollup/create-package-config.ts index a407bcf4..25e07fb4 100644 --- a/config/rollup/create-package-config.ts +++ b/config/rollup/create-package-config.ts @@ -39,6 +39,14 @@ export default async function createPackageConfig(config: PkgConfigInput): Promi minify: config.format === 'umd', sourceMap: false, tsconfig: path.resolve(process.cwd(), 'tsconfig.json'), + optimizeDeps: { + esbuildOptions: { + define: { + global: 'globalThis', + }, + }, + include: [], + }, }), json(), alias({ entries: aliasEntries }), diff --git a/packages/co-design-core/src/components/ContainerQuery/ContainerQuery.style.ts b/packages/co-design-core/src/components/ContainerQuery/ContainerQuery.style.ts new file mode 100644 index 00000000..b504adf6 --- /dev/null +++ b/packages/co-design-core/src/components/ContainerQuery/ContainerQuery.style.ts @@ -0,0 +1,39 @@ +import { createStyles, CoBreakpoints, CSSObject } from '@co-design/styles'; + +interface ContainerQueryStyles { + smallerThan?: CoBreakpoints | number; + largerThan?: CoBreakpoints | number; + style?: CSSObject; + containerName?: string; + query: string; +} + +export default createStyles((theme, { smallerThan, largerThan, query, style, containerName }: ContainerQueryStyles) => { + const containerQuery: CSSObject = {}; + const minWidth = theme.fn.size({ size: largerThan, sizes: theme.breakpoints }) + 1; + const maxWidth = theme.fn.size({ size: smallerThan, sizes: theme.breakpoints }); + + if (largerThan && smallerThan) { + containerQuery[`@container ${containerName ? containerName + ' ' : ''}(min-width: ${minWidth}px) and (max-width: ${maxWidth}px)`] = style; + } else { + if (largerThan) { + containerQuery[ + `@container ${containerName ? containerName + ' ' : ''}(min-width: ${theme.fn.size({ size: largerThan, sizes: theme.breakpoints }) + 1}px)` + ] = style; + } + + if (smallerThan) { + containerQuery[ + `@container ${containerName ? containerName + ' ' : ''}(max-width: ${theme.fn.size({ size: smallerThan, sizes: theme.breakpoints })}px)` + ] = style; + } + } + + if (query) { + containerQuery[`@container ${containerName ? containerName + ' ' : ''}${query}`] = style; + } + + return { + containerQuery, + }; +}); diff --git a/packages/co-design-core/src/components/ContainerQuery/ContainerQuery.tsx b/packages/co-design-core/src/components/ContainerQuery/ContainerQuery.tsx new file mode 100644 index 00000000..fa93c27a --- /dev/null +++ b/packages/co-design-core/src/components/ContainerQuery/ContainerQuery.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { CoBreakpoints, CSSObject } from '@co-design/styles'; +import useStyles from './ContainerQuery.style'; + +export interface ContainerQueryProps { + /** ContainerQuery 컴포넌트는 오직 하나의 자식만 가질 수 있습니다. */ + children: React.ReactElement; + + /** 속성 값보다 작은 경우 자식 요소에 className과 style이 적용됩니다. */ + smallerThan?: CoBreakpoints | number; + + /** 속성 값보다 큰 경우 자식 요소에 className과 style이 적용됩니다. */ + largerThan?: CoBreakpoints | number; + + /** ContainerQuery를 raw string으로 적용합니다. */ + query?: string; + + /** 자식 요소에 적용되는 className 입니다. */ + className?: string; + + /** 자식 요소에 적용되는 style 입니다. */ + style?: CSSObject; + + /** 지정 컨테이너의 이름을 설정할 때 사용합니다. */ + containerName?: string; +} + +export function ContainerQuery({ children, smallerThan, largerThan, query, className, style, containerName }: ContainerQueryProps) { + const { classes, cx } = useStyles({ smallerThan, largerThan, query, style, containerName }, { name: 'ContainerQuery' }); + const child = React.Children.only(children) as React.ReactElement; + return React.cloneElement(child, { + className: cx(classes.containerQuery, child.props?.className, className), + }); +} + +ContainerQuery.displayName = '@co-design/core/ContainerQuery'; diff --git a/packages/co-design-core/src/components/ContainerQuery/index.ts b/packages/co-design-core/src/components/ContainerQuery/index.ts new file mode 100644 index 00000000..ca04093f --- /dev/null +++ b/packages/co-design-core/src/components/ContainerQuery/index.ts @@ -0,0 +1,2 @@ +export { ContainerQuery } from './ContainerQuery'; +export type { ContainerQueryProps } from './ContainerQuery'; diff --git a/packages/co-design-core/src/components/ContainerQuery/stories/ContainerQuery.stories.tsx b/packages/co-design-core/src/components/ContainerQuery/stories/ContainerQuery.stories.tsx new file mode 100644 index 00000000..da162566 --- /dev/null +++ b/packages/co-design-core/src/components/ContainerQuery/stories/ContainerQuery.stories.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { ContainerQuery } from '../ContainerQuery'; +import { View } from '../../View'; +import { Stack } from '../../Stack'; + +export default { + title: '@co-design/core/ContainerQuery', + component: ContainerQuery, +}; + +export const Default = () => { + const highlight = { color: 'blue' }; + return ( + + + largerThan 900 + + + largerThan 1000 + + + smallerThan 1000 + + + ); +}; diff --git a/packages/co-design-core/src/components/index.ts b/packages/co-design-core/src/components/index.ts index e40caade..ec1ed079 100644 --- a/packages/co-design-core/src/components/index.ts +++ b/packages/co-design-core/src/components/index.ts @@ -11,6 +11,7 @@ export * from './Center'; export * from './Checkbox'; export * from './Chips'; export * from './Container'; +export * from './ContainerQuery'; export * from './Divider'; export * from './Drawer'; export * from './EquallyGrid';