From 99be6f15bbe6e03af770fe036126b0e7b8e7b79d Mon Sep 17 00:00:00 2001 From: Alexandre Stahmer <47224540+astahmer@users.noreply.github.com> Date: Sat, 4 May 2024 19:18:05 +0200 Subject: [PATCH] fix: css.raw typings (#2561) --- .changeset/violet-birds-tie.md | 6 + .../__tests__/generate-css-fn.test.ts | 24 +- packages/generator/src/artifacts/js/css-fn.ts | 12 +- packages/studio/styled-system/css/css.d.ts | 12 +- sandbox/codegen/__tests__/css.test.ts | 240 ++++++++++++++++++ .../__tests__/scenarios/strict.test.ts | 185 ++++++++++++++ 6 files changed, 463 insertions(+), 16 deletions(-) create mode 100644 .changeset/violet-birds-tie.md diff --git a/.changeset/violet-birds-tie.md b/.changeset/violet-birds-tie.md new file mode 100644 index 000000000..3ed698e49 --- /dev/null +++ b/.changeset/violet-birds-tie.md @@ -0,0 +1,6 @@ +--- +'@pandacss/generator': patch +--- + +Fix `css.raw` typings after recent ([0.39.0](https://github.com/chakra-ui/panda/discussions/2560)) changes allowing +arrays of `SystemStyleObject` diff --git a/packages/generator/__tests__/generate-css-fn.test.ts b/packages/generator/__tests__/generate-css-fn.test.ts index c3f7ff3d5..8e870dcb0 100644 --- a/packages/generator/__tests__/generate-css-fn.test.ts +++ b/packages/generator/__tests__/generate-css-fn.test.ts @@ -10,16 +10,20 @@ describe('generate css-fn', () => { type Styles = SystemStyleObject | undefined | null | false + interface CssRawFunction { + (styles: Styles): SystemStyleObject + (styles: Styles[]): SystemStyleObject + (...styles: Array): SystemStyleObject + (styles: Styles): SystemStyleObject + } + interface CssFunction { (styles: Styles): string (styles: Styles[]): string (...styles: Array): string (styles: Styles): string - raw: (styles: Styles) => string - raw: (styles: Styles[]) => string - raw: (...styles: Array) => string - raw: (styles: Styles) => string + raw: CssRawFunction } export declare const css: CssFunction;", @@ -96,16 +100,20 @@ describe('generate css-fn', () => { type Styles = SystemStyleObject | undefined | null | false + interface CssRawFunction { + (styles: Styles): SystemStyleObject + (styles: Styles[]): SystemStyleObject + (...styles: Array): SystemStyleObject + (styles: Styles): SystemStyleObject + } + interface CssFunction { (styles: Styles): string (styles: Styles[]): string (...styles: Array): string (styles: Styles): string - raw: (styles: Styles) => string - raw: (styles: Styles[]) => string - raw: (...styles: Array) => string - raw: (styles: Styles) => string + raw: CssRawFunction } export declare const css: CssFunction;", diff --git a/packages/generator/src/artifacts/js/css-fn.ts b/packages/generator/src/artifacts/js/css-fn.ts index de0052c51..010bf6a21 100644 --- a/packages/generator/src/artifacts/js/css-fn.ts +++ b/packages/generator/src/artifacts/js/css-fn.ts @@ -12,16 +12,20 @@ export function generateCssFn(ctx: Context) { type Styles = SystemStyleObject | undefined | null | false + interface CssRawFunction { + (styles: Styles): SystemStyleObject + (styles: Styles[]): SystemStyleObject + (...styles: Array): SystemStyleObject + (styles: Styles): SystemStyleObject + } + interface CssFunction { (styles: Styles): string (styles: Styles[]): string (...styles: Array): string (styles: Styles): string - raw: (styles: Styles) => string - raw: (styles: Styles[]) => string - raw: (...styles: Array) => string - raw: (styles: Styles) => string + raw: CssRawFunction } export declare const css: CssFunction; diff --git a/packages/studio/styled-system/css/css.d.ts b/packages/studio/styled-system/css/css.d.ts index 175f97471..496da4193 100644 --- a/packages/studio/styled-system/css/css.d.ts +++ b/packages/studio/styled-system/css/css.d.ts @@ -3,16 +3,20 @@ import type { SystemStyleObject } from '../types/index'; type Styles = SystemStyleObject | undefined | null | false +interface CssRawFunction { + (styles: Styles): SystemStyleObject + (styles: Styles[]): SystemStyleObject + (...styles: Array): SystemStyleObject + (styles: Styles): SystemStyleObject +} + interface CssFunction { (styles: Styles): string (styles: Styles[]): string (...styles: Array): string (styles: Styles): string - raw: (styles: Styles) => string - raw: (styles: Styles[]) => string - raw: (...styles: Array) => string - raw: (styles: Styles) => string + raw: CssRawFunction } export declare const css: CssFunction; \ No newline at end of file diff --git a/sandbox/codegen/__tests__/css.test.ts b/sandbox/codegen/__tests__/css.test.ts index bf8b0de2c..9928f01b6 100644 --- a/sandbox/codegen/__tests__/css.test.ts +++ b/sandbox/codegen/__tests__/css.test.ts @@ -123,3 +123,243 @@ describe('css', () => { expect(className).toMatchInlineSnapshot(`"fs_12px bg_red.600"`) }) }) + +describe('css.raw', () => { + test('native CSS prop and value', () => { + const styles = css.raw({ display: 'flex' }) + + expect(styles).toMatchInlineSnapshot(` + { + "display": "flex", + } + `) + }) + + test('token value', () => { + const styles = css.raw({ color: 'blue.300' }) + + expect(styles).toMatchInlineSnapshot(` + { + "color": "blue.300", + } + `) + }) + + test('utility prop', () => { + const styles = css.raw({ srOnly: true }) + + expect(styles).toMatchInlineSnapshot(` + { + "srOnly": true, + } + `) + }) + + test('shorthand prop', () => { + const styles = css.raw({ bg: 'red' }) + + expect(styles).toMatchInlineSnapshot(` + { + "bg": "red", + } + `) + }) + + test('object condition prop', () => { + const styles = css.raw({ bg: { _hover: 'yellow.100' } }) + + expect(styles).toMatchInlineSnapshot(` + { + "bg": { + "_hover": "yellow.100", + }, + } + `) + }) + + test('condition prop', () => { + const styles = css.raw({ _hover: { bg: 'yellow.200' } }) + + expect(styles).toMatchInlineSnapshot(` + { + "_hover": { + "bg": "yellow.200", + }, + } + `) + }) + + test('nested condition prop', () => { + const styles = css.raw({ _hover: { _dark: { bg: 'pink' } } }) + + expect(styles).toMatchInlineSnapshot(` + { + "_hover": { + "_dark": { + "bg": "pink", + }, + }, + } + `) + }) + + test('arbitrary value', () => { + const styles = css.raw({ color: '#fff' }) + + expect(styles).toMatchInlineSnapshot(` + { + "color": "#fff", + } + `) + }) + + test('arbitrary selector', () => { + const styles = css.raw({ ['&:data-panda']: { display: 'flex' } }) + + expect(styles).toMatchInlineSnapshot(` + { + "&:data-panda": { + "display": "flex", + }, + } + `) + }) + + test('responsive condition', () => { + const styles = css.raw({ sm: { bg: 'purple' } }) + + expect(styles).toMatchInlineSnapshot(` + { + "sm": { + "bg": "purple", + }, + } + `) + }) + + test('responsive array syntax prop', () => { + const styles = css.raw({ bg: ['cyan.100', 'cyan.200', null, undefined, 'cyan.300'] }) + + expect(styles).toMatchInlineSnapshot(` + { + "bg": [ + "cyan.100", + "cyan.200", + null, + undefined, + "cyan.300", + ], + } + `) + }) + + test('using inline token helper - in value', () => { + const styles = css.raw({ border: '1px solid token(colors.blue.400)' }) + + expect(styles).toMatchInlineSnapshot(` + { + "border": "1px solid token(colors.blue.400)", + } + `) + }) + + test('using inline token helper - in condition', () => { + const styles = css.raw({ '@media screen and (min-width: token(sizes.4xl))': { bg: 'blue.500' } }) + + expect(styles).toMatchInlineSnapshot(` + { + "@media screen and (min-width: token(sizes.4xl))": { + "bg": "blue.500", + }, + } + `) + }) + + test('nested condition prop with array syntax', () => { + const styles = css.raw({ _hover: { _dark: { bg: ['pink.100', 'pink.200'] } } }) + + expect(styles).toMatchInlineSnapshot(` + { + "_hover": { + "_dark": { + "bg": [ + "pink.100", + "pink.200", + ], + }, + }, + } + `) + }) + + test('same prop', () => { + const styles = css.raw({ bgColor: 'red.100', backgroundColor: 'red.200' }) + + expect(styles).toMatchInlineSnapshot(` + { + "backgroundColor": "red.200", + "bgColor": "red.100", + } + `) + + const styles2 = css.raw({ backgroundColor: 'red.300', bgColor: 'red.400' }) + + expect(styles2).toMatchInlineSnapshot(` + { + "backgroundColor": "red.300", + "bgColor": "red.400", + } + `) + }) + + test('merging styles', () => { + const styles = css.raw({ fontSize: 'sm', bgColor: 'red.500' }, { backgroundColor: 'red.600' }) + + expect(styles).toMatchInlineSnapshot(` + { + "backgroundColor": "red.600", + "fontSize": "sm", + } + `) + }) + + test('merging styles with nested conditions', () => { + const styles = css.raw({ fontSize: 'sm', _hover: { color: 'green.100' } }, { _hover: { color: 'green.200' } }) + + expect(styles).toMatchInlineSnapshot(` + { + "_hover": { + "color": "green.200", + }, + "fontSize": "sm", + } + `) + }) + + test('merging styles with object condition prop', () => { + const styles = css.raw({ fontSize: 'md' }, { fontSize: { base: 'lg', sm: 'xs' } }) + + expect(styles).toMatchInlineSnapshot(` + { + "fontSize": { + "base": "lg", + "sm": "xs", + }, + } + `) + }) + + test('merging styles with array item', () => { + const styles = css.raw({ fontSize: 'sm', bgColor: 'red.500' }, [ + { backgroundColor: 'red.600' }, + { fontSize: '12px' }, + ]) + + expect(styles).toMatchInlineSnapshot(` + { + "backgroundColor": "red.600", + "fontSize": "12px", + } + `) + }) +}) diff --git a/sandbox/codegen/__tests__/scenarios/strict.test.ts b/sandbox/codegen/__tests__/scenarios/strict.test.ts index cbda8bc36..863db50b7 100644 --- a/sandbox/codegen/__tests__/scenarios/strict.test.ts +++ b/sandbox/codegen/__tests__/scenarios/strict.test.ts @@ -185,3 +185,188 @@ describe('css', () => { assertType(css({ _hover: { _dark: { bg: ['pink.100', 'pink.200'] } } })) }) }) + +describe('css.raw', () => { + test('native CSS prop and value', () => { + assertType(css.raw({ display: 'flex' })) + + // @ts-expect-error expected from strictPropertyValues: true + assertType(css.raw({ display: 'abc' })) + assertType(css.raw({ content: 'abc' })) + assertType(css.raw({ willChange: 'abc' })) + + assertType(css.raw({ pos: 'absolute' })) + + // @ts-expect-error expected from strictPropertyValues: true + assertType(css.raw({ position: 'absolute123' })) + // @ts-expect-error expected from strictPropertyValues: true + assertType(css.raw({ pos: 'absolute123' })) + // @ts-expect-error expected from strictTokens: true + assertType(css.raw({ flex: '0 1' })) + }) + + test('token value', () => { + assertType(css.raw({ color: 'blue.300' })) + }) + + test('css var', () => { + assertType(css.raw({ color: 'var(--button-color)' })) + assertType(css.raw({ display: 'var(--button-color)' })) + }) + + test('utility prop', () => { + assertType( + css.raw({ + srOnly: true, + }), + ) + }) + + test('shorthand prop', () => { + assertType( + css.raw({ + // @ts-expect-error expected from strictTokens: true + backgroundColor: 'red', + // @ts-expect-error expected from strictTokens: true + bg: 'red', + }), + ) + }) + + test('object condition prop', () => { + assertType(css.raw({ bg: { _hover: 'yellow.100' } })) + }) + + test('condition prop', () => { + assertType(css.raw({ _hover: { bg: 'yellow.200' } })) + }) + + test('nested condition prop', () => { + assertType( + css.raw({ + _hover: { + _dark: { + // @ts-expect-error expected from strictTokens: true + bg: 'pink', + }, + }, + }), + ) + }) + + test('arbitrary value', () => { + assertType( + css.raw({ + // @ts-expect-error expected from strictTokens: true + color: '#fff', + }), + ) + }) + + test('arbitrary value escape hatch', () => { + assertType( + css.raw({ + color: '[#fff]', + fontSize: '[123px]', + }), + ) + }) + + test('arbitrary value escape hatch with conditionals', () => { + assertType( + css.raw({ + color: '[#fff]', + fontSize: '[123px]', + bgColor: '[#fff!]', + borderColor: '[#fff !important]', + _hover: { + color: '[#fff]', + fontSize: '[123px]', + bgColor: '[#fff!]', + borderColor: '[#fff !important]', + }, + backgroundColor: { + _dark: '[#3B00B9]', + _hover: '[#3B00B9!]', + _focus: '[#3B00B9 !important]', + }, + }), + ) + }) + + test('arbitrary selector', () => { + assertType(css.raw({ ['&:data-panda']: { display: 'flex' } })) + }) + + test('important', () => { + assertType( + css.raw({ + fontSize: '2xl !important', + p: '4 !important', + // @ts-expect-error expected from strictTokens: true + bgColor: '#fff!', + // @ts-expect-error expected from strictTokens: true + borderColor: '#fff !important', + _hover: { + fontSize: '2xl !important', + p: '4 !important', + // @ts-expect-error expected from strictTokens: true + + bgColor: '#fff!', + // @ts-expect-error expected from strictTokens: true + borderColor: '#fff !important', + }, + // @ts-expect-error expected from strictTokens: true + backgroundColor: { + _disabled: '2xl!', + _active: '4 !important', + _hover: '#3B00B9!', + _focus: '#3B00B9 !important', + }, + }), + ) + }) + + test('responsive condition', () => { + assertType( + css.raw({ + sm: { + // @ts-expect-error expected from strictTokens: true + bg: 'purple', + }, + }), + ) + }) + + test('responsive array syntax prop', () => { + assertType( + css.raw({ + bg: [ + 'cyan.100', + 'cyan.200', + null, + // @ts-expect-error expected from strictTokens: true + undefined, + 'cyan.300', + ], + }), + ) + }) + + test('using inline token helper - in value', () => { + assertType( + css.raw({ + // @ts-expect-error expected from strictTokens: true + border: '1px solid token(colors.blue.400)', + }), + ) + }) + + test('using inline token helper - in condition', () => { + assertType(css.raw({ '@media screen and (min-width: token(sizes.4xl))': { bg: 'blue.500' } })) + }) + + test('nested condition prop with array syntax', () => { + assertType(css.raw({ _hover: { _dark: { bg: ['pink.100', 'pink.200'] } } })) + }) +})