Skip to content

Commit

Permalink
fix: ccv generates the right variant keys with breakpoints, adds tests (
Browse files Browse the repository at this point in the history
#22)

* fix: fix ccv generating the right variant keys

* fix: fix a test
  • Loading branch information
jonambas authored Apr 26, 2024
1 parent 632c1fc commit f132616
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 12 deletions.
2 changes: 1 addition & 1 deletion apps/vite-react/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion apps/vite-react/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
ccv,
css,
cva,
cx,
ct,
splitResponsiveVariant,
ResponsiveVariant,
Expand Down
10 changes: 10 additions & 0 deletions e2e/parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ test.describe('parser', () => {
'rgb(0, 0, 0)',
);

await expect(page.getByText('Responsive compound variants')).toHaveCSS(
'border-radius',
'10px',
);

page.setViewportSize({ width: 300, height: 1024 });

await expect(page.getByText('Responsive compound variants')).toHaveCSS(
Expand All @@ -100,5 +105,10 @@ test.describe('parser', () => {
'color',
'rgb(0, 0, 0)',
);

await expect(page.getByText('Responsive compound variants')).toHaveCSS(
'border-radius',
'3px',
);
});
});
254 changes: 247 additions & 7 deletions src/__tests__/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const makeParser = (content: string) => {
);
};

describe('parsers', () => {
describe('crv parser', () => {
it('parses', () => {
const res = makeParser(`
import foo from 'bar';
Expand All @@ -25,9 +25,6 @@ describe('parsers', () => {
positive: { bg: "green.200" }
}),
},
compoundVariants: [
...ccv({ tone: 'negative', size: 'sm' }, { bg: 'amber.400' }),
]
});
`);

Expand All @@ -40,9 +37,6 @@ describe('parsers', () => {
variants: {
...{tone: {negative: { bg: "red.200" },positive: { bg: "green.200" },},tone_sm: {negative: {'sm':{ bg: "red.200" },},positive: {'sm':{ bg: "green.200" },},},tone_md: {negative: {'md':{ bg: "red.200" },},positive: {'md':{ bg: "green.200" },},},tone_2lg: {negative: {'2lg':{ bg: "red.200" },},positive: {'2lg':{ bg: "green.200" },},},},
},
compoundVariants: [
{tone: 'negative',size: 'sm',css: {bg: 'amber.400',},{tone: 'negative',size: 'sm',css: {'sm': {bg: 'amber.400',}},},{tone: 'negative',size: 'sm',css: {'md': {bg: 'amber.400',}},},{tone: 'negative',size: 'sm',css: {'2lg': {bg: 'amber.400',}},},
]
});
"
`,
Expand Down Expand Up @@ -273,3 +267,249 @@ describe('parsers', () => {
`);
});
});

describe('ccv parser', () => {
it('parses', () => {
const res = makeParser(`
import foo from 'bar';
import { css, cva, ccv } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv({
variant1: 'red',
variant2: 'blue'
}, { bg: 'green' }),
],
});
`);

expect(res).toMatchInlineSnapshot(`
"import foo from 'bar';
import { css, cva, ccv } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
{variant1: 'red',variant2: 'blue',css: {bg: 'green',},{variant1_sm: 'red',variant2_sm: 'blue',css: {'sm': {bg: 'green',}},},{variant1_md: 'red',variant2_md: 'blue',css: {'md': {bg: 'green',}},},{variant1_2lg: 'red',variant2_2lg: 'blue',css: {'2lg': {bg: 'green',}},},
],
});
"
`);
});

it('parses with an import alias', () => {
const res = makeParser(`
import { css, ccv as alias, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...alias({
variant1: 'red',
variant2: 'blue'
}, { bg: 'green' }),
],
});
`);

expect(res).toMatchInlineSnapshot(`
"import { css, ccv as alias, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
{variant1: 'red',variant2: 'blue',css: {bg: 'green',},{variant1_sm: 'red',variant2_sm: 'blue',css: {'sm': {bg: 'green',}},},{variant1_md: 'red',variant2_md: 'blue',css: {'md': {bg: 'green',}},},{variant1_2lg: 'red',variant2_2lg: 'blue',css: {'2lg': {bg: 'green',}},},
],
});
"
`);
});

it('parses without style object', () => {
const res = makeParser(`
import { css, crv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv({
variant1: 'red',
variant2: 'blue'
}),
],
});
`);

expect(res).toBeUndefined();
});

it('skips without crv imports or expressions', () => {
expect(makeParser(`ccv({}, {})`)).toBeUndefined();

expect(
makeParser(`import { ccv } from '@/styled-system/css`),
).toBeUndefined();
});

it('skips without crv return value', () => {
expect(
makeParser(`
import { ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv(),
],
});
`),
).toMatchInlineSnapshot(`
"import { ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv(),
],
});
"
`);
});

it('parses nested objects', () => {
const res = makeParser(`
import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv({
variant1: 'red',
variant2: 'blue'
}, {
foo: { bar: { baz: '#fff' }}
}),
],
});
`);

expect(res).toMatchInlineSnapshot(`
"import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
{variant1: 'red',variant2: 'blue',css: {foo: { bar: { baz: '#fff' }},},{variant1_sm: 'red',variant2_sm: 'blue',css: {'sm': {foo: { bar: { baz: '#fff' }},}},},{variant1_md: 'red',variant2_md: 'blue',css: {'md': {foo: { bar: { baz: '#fff' }},}},},{variant1_2lg: 'red',variant2_2lg: 'blue',css: {'2lg': {foo: { bar: { baz: '#fff' }},}},},
],
});
"
`);
});

it('parses different quote styles', () => {
const res = makeParser(`
import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv({
variant1: 'red',
variant2: 'blue'
}, {
foo: { '& > *': { "3baz": \`\${'#fff'}\`}}
}),
],
});
`);

expect(res).toMatchInlineSnapshot(`
"import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
{variant1: 'red',variant2: 'blue',css: {foo: { '& > *': { "3baz": \`\${'#fff'}\`}},},{variant1_sm: 'red',variant2_sm: 'blue',css: {'sm': {foo: { '& > *': { "3baz": \`\${'#fff'}\`}},}},},{variant1_md: 'red',variant2_md: 'blue',css: {'md': {foo: { '& > *': { "3baz": \`\${'#fff'}\`}},}},},{variant1_2lg: 'red',variant2_2lg: 'blue',css: {'2lg': {foo: { '& > *': { "3baz": \`\${'#fff'}\`}},}},},
],
});
"
`);
});

it('parses booleans', () => {
const res = makeParser(`
import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv({
variant1: true,
variant2: false
}, {
foo: { bar: { srOnly: false }}
}),
],
});
`);

expect(res).toMatchInlineSnapshot(
`
"import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
{variant1: true,variant2: false,css: {foo: { bar: { srOnly: false }},},{variant1_sm: true,variant2_sm: false,css: {'sm': {foo: { bar: { srOnly: false }},}},},{variant1_md: true,variant2_md: false,css: {'md': {foo: { bar: { srOnly: false }},}},},{variant1_2lg: true,variant2_2lg: false,css: {'2lg': {foo: { bar: { srOnly: false }},}},},
],
});
"
`,
);
});

it('parses numbers', () => {
const res = makeParser(`
import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv({
variant1: 1,
variant2: 0
}, {
foo: { opacity: 0.5 }
}),
],
});
`);

expect(res).toMatchInlineSnapshot(`
"import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
{variant1: 1,variant2: 0,css: {foo: { opacity: 0.5 },},{variant1_sm: 1,variant2_sm: 0,css: {'sm': {foo: { opacity: 0.5 },}},},{variant1_md: 1,variant2_md: 0,css: {'md': {foo: { opacity: 0.5 },}},},{variant1_2lg: 1,variant2_2lg: 0,css: {'2lg': {foo: { opacity: 0.5 },}},},
],
});
"
`);
});

it('parses funcs', () => {
const res = makeParser(`
import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
...ccv({
variant1: 1,
variant2: 0
}, {
foo: { opacity: get('test'), bg: \`\${get('test')}\` }
}),
],
});
`);

expect(res).toMatchInlineSnapshot(`
"import { css, ccv, cva } from '@/styled-system/css';
const styles = cva({
compoundVariants: [
{variant1: 1,variant2: 0,css: {foo: { opacity: get('test'), bg: \`\${get('test')}\` },},{variant1_sm: 1,variant2_sm: 0,css: {'sm': {foo: { opacity: get('test'), bg: \`\${get('test')}\` },}},},{variant1_md: 1,variant2_md: 0,css: {'md': {foo: { opacity: get('test'), bg: \`\${get('test')}\` },}},},{variant1_2lg: 1,variant2_2lg: 0,css: {'2lg': {foo: { opacity: get('test'), bg: \`\${get('test')}\` },}},},
],
});
"
`);
});
});
11 changes: 8 additions & 3 deletions src/ccvParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ts,
} from 'ts-morph';
import type { PluginContext } from './types';
import { makeKey } from './crv';

const clean = (str: string) => str.replace(/^\s+|\s+$|\s+(?=\s)/g, '');

Expand All @@ -23,10 +24,14 @@ export const writeObject = (args: WriterArgs) => {
writer.write('{');

for (const property of variants.getProperties()) {
if (!property.isKind(ts.SyntaxKind.PropertyAssignment)) {
continue;
if (!property.isKind(ts.SyntaxKind.PropertyAssignment)) continue;
const initializer = property.getInitializer()?.getText() ?? '';
if (bp) {
writer.write(`${makeKey(property.getName(), bp)}: `);
writer.write(`${clean(initializer)},`);
} else {
writer.write(`${clean(property.getText())},`);
}
writer.write(`${property.getText()},`);
}
writer.write('css: {');

Expand Down

0 comments on commit f132616

Please sign in to comment.