UNPKG

panda-plugin-crv

Version:

A Panda CSS plugin for responsive variants

259 lines (225 loc) 6.44 kB
import { codegen } from '../codegen'; import { context } from './fixtures'; describe('codegen', () => { it('generates crv runtime code', () => { const result = codegen( { artifacts: [ { id: 'css-fn', files: [], }, { id: 'css-index', files: [ { file: 'index.mjs', code: '// ...panda code' }, { file: 'index.d.ts', code: '// ...panda code' }, ], }, ], changed: [], }, context, ); expect(result).toMatchInlineSnapshot(` [ { "files": [ { "code": " const crvBreakpoints = ['sm', 'md', '2lg']; const makeKey = (name, bp) => { return \`\${name}_\${bp}\`; } const injectBreakpoint = (styles, breakpoint) => { return Object.fromEntries( Object.entries(styles).map(([key, css]) => [[key], { [breakpoint]: css }]), ); }; export const crv = (name, styles) => { if (!name) return; const variants = { [name]: styles, }; for (const bp of crvBreakpoints) { variants[makeKey(name, bp)] = injectBreakpoint(styles, bp); } return variants; }; export const splitResponsiveVariant = (name, value) => { if (typeof value !== 'object') { return { [name]: value }; } const { base, ...rest } = value; let variants = { [name]: base }; for (const bp of crvBreakpoints) { if (!(bp in rest)) continue; variants[makeKey(name, bp)] = rest[bp]; } return variants; }; export const splitCrv = splitResponsiveVariant; const groupByBreakpoint = (variants) => { const result = {}; for (const bp of crvBreakpoints) { let renamed = {}; for (const [key, value] of Object.entries(variants)) { renamed[makeKey(key, bp)] = value; } result[bp] = renamed; } return Object.entries(result); }; export const ccv = (args) => { const { css, ...variants } = args; if (!variants || !css) return []; const compoundVariants = [{ ...variants, css }]; for (const [bp, keys] of groupByBreakpoint(variants)) { compoundVariants.push({ ...keys, css: { [bp]: css } }); } return compoundVariants; }; ", "file": "crv.mjs", }, { "code": "/* eslint-disable */ import type { SystemStyleObject } from '../types/system-types'; type CrvBreakpoints = 'sm' | 'md' | '2lg'; /** * Create responsive variants * * @example * cva({ * variants: { * ...crv('prop', { * variant1: { color: 'red' }, * variant2: { color: 'blue' } * }) * }) */ export declare const crv: <T extends string, P extends Record<any, SystemStyleObject>>( name: T, styles: P ) => Record<\`\${T}_\${CrvBreakpoints}\` | T, P>; /** * Splits responsive objects into \`crv\` variants */ type SplitResponsiveVariant = <T extends string>( name: T, value: any ) => Record<\`\${T}_\${CrvBreakpoints}\` | T, any>; export declare const splitCrv: SplitResponsiveVariant; export declare const splitResponsiveVariant: SplitResponsiveVariant; export type ResponsiveVariant<T> = Partial<Record<'base' | CrvBreakpoints, T>> | T; /** * Create compound variants * * @example * variants: { * crv({ * variants: { * ...crv('prop', { * variant1: { color: 'red' }, * variant2: { color: 'blue' } * }) * }) * }, * compoundVariants: [ * ...ccv({ * variant1: 'red', * variant2: 'blue', * css: { * bg: 'green' * } * }) * ] */ export declare const ccv: <T extends Record<any, any> & { css: SystemStyleObject }>( args: T, ) => Array<{ css: T['css'] } & Record<keyof T, any>>; ", "file": "crv.d.ts", }, ], "id": "css-fn", }, { "files": [ { "code": "// ...panda code export * from './crv.mjs';", "file": "index.mjs", }, { "code": "// ...panda code export * from './crv';", "file": "index.d.ts", }, ], "id": "css-index", }, ] `); }); it('generates crv runtime code with outExtension set to "js"', () => { const result = codegen( { artifacts: [ { id: 'css-fn', files: [], }, { id: 'css-index', files: [ { file: 'index.js', code: '' }, { file: 'index.d.ts', code: '' }, ], }, ], changed: [], }, context, ) as any[]; expect(result.at(0).files[0].file).toEqual('crv.js'); expect(result.at(0).files[1].file).toEqual('crv.d.ts'); expect(result.at(1).files[0].code).includes('./crv.js'); expect(result.at(1).files[1].code).includes('./crv'); }); it('generates crv runtime code with outExtension set to "mjs" and force type extension', () => { const result = codegen( { artifacts: [ { id: 'css-fn', files: [], }, { id: 'css-index', files: [ { file: 'index.mjs', code: '' }, { file: 'index.d.mts', code: '' }, ], }, ], changed: [], }, context, ) as any[]; expect(result.at(0).files[0].file).toEqual('crv.mjs'); expect(result.at(0).files[1].file).toEqual('crv.d.mts'); expect(result.at(1).files[0].code).includes('./crv.mjs'); expect(result.at(1).files[1].code).includes('./crv'); }); it('skips if artifacts dont exist', () => { const result = codegen( { artifacts: [], changed: [], }, context, ); expect(result).toEqual([]); }); });