UNPKG

panda-plugin-crv

Version:

A Panda CSS plugin for responsive variants

138 lines (114 loc) 7.09 kB
import{ts as v}from"ts-morph";var k=` 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; };`,P=` /** * 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>>; `;var d=(t,e)=>`${t}_${e}`,T=t=>` const crvBreakpoints = [${t.map(e=>`'${e}'`).join(", ")}]; 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; ${k} `,S=t=>`/* eslint-disable */ import type { SystemStyleObject } from '../types/system-types'; type CrvBreakpoints = ${t.map(e=>`'${e}'`).join(" | ")}; /** * 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; ${P} `;var $=t=>t.replace(/^\s+|\s+$|\s+(?=\s)/g,""),j=t=>{let{writer:e,key:i,value:n,bp:r}=t;e.write(`${i}: {`);for(let s of n.getProperties()){if(!s.isKind(v.SyntaxKind.PropertyAssignment))continue;let o=s.getInitializer()?.getText()??"";r?(e.write(`${s.getName()}: {`),e.write(`'${r}':`),e.write(`${$(o)},`),e.write("},")):e.write(`${$(s.getText())},`)}e.write("},")},C=(t,e,i,n="crv")=>{let{breakpoints:r,debug:s}=e,o=i.getDescendantsOfKind(v.SyntaxKind.CallExpression).filter(c=>c.getExpression().getText()===n);if(o.length){for(let c of o){let f=c.getArguments()[0],p=c.getArguments()[1],a=f?.getText()??"";f&&f.isKind(v.SyntaxKind.StringLiteral)&&(a=f.getLiteralValue()),!(!p||!p.isKind(v.SyntaxKind.ObjectLiteralExpression))&&(c.replaceWithText(l=>{l.write("{"),j({writer:l,key:a,value:p});for(let g of r)j({writer:l,key:d(a,g),value:p,bp:g});l.write("}")}),s?.("plugin:crv",`crv: '${a}': ${t.filePath.split("/").at(-1)}`))}return i.getText()}};import{ts as u}from"ts-morph";var x=t=>t.replace(/^\s+|\s+$|\s+(?=\s)/g,""),A=t=>{let{writer:e,variants:i,value:n,bp:r,isLast:s}=t;e.write("{");for(let o of i){if(!o.isKind(u.SyntaxKind.PropertyAssignment))continue;let c=o.getInitializer()?.getText()??"";r?(e.write(`${d(o.getName(),r)}: `),e.write(`${x(c)},`)):e.write(`${x(o.getText())},`)}e.write("css: {"),r&&e.write(`'${r}': {`);for(let o of n.getProperties())e.write(`${x(o.getText())},`);r&&e.write("}},"),r||e.write("},"),e.write(s?"}":"},")},K=(t,e,i,n="ccv")=>{let{breakpoints:r,debug:s}=e,o=i.getDescendantsOfKind(u.SyntaxKind.SpreadElement).filter(c=>c.getExpression()?.getText().startsWith(n));if(o.length){for(let c of o){let f=c.getExpressionIfKind(u.SyntaxKind.CallExpression);if(!f)continue;let p=f.getArguments().at(0);if(!p||!p.isKind(u.SyntaxKind.ObjectLiteralExpression))continue;let a=p.getProperties(),l,g=a.filter(m=>m.isKind(u.SyntaxKind.PropertyAssignment)?m.getName()!=="css":!1);for(let m of a)m.isKind(u.SyntaxKind.PropertyAssignment)&&m.getName()==="css"&&(l=m.getInitializer());if(!l||!l.isKind(u.SyntaxKind.ObjectLiteralExpression))continue;let w=c.replaceWithText(m=>{A({writer:m,variants:g,value:l});for(let[E,O]of r.entries())A({writer:m,variants:g,value:l,bp:O,isLast:E===r.length-1})});s?.("plugin:crv",`ccv: '${w.getText()}': ${t.filePath.split("/").at(-1)}`)}return i.getText()}};var y=["crv","ccv"],L=t=>{let e={};for(let i of t.getImportDeclarations())if(!(!i.getText().includes(y[0])&&!i.getText().includes(y[1])))for(let n of i.getNamedImports())for(let r of y)(n.getText()===r||n.getText().startsWith(`${r} as`))&&(e[r]=n.getAliasNode()?.getText()??r);return e},B=(t,e)=>{let{project:i}=e,n,r=i.createSourceFile("__crv-parser.tsx",t.content,{overwrite:!0}),s=L(r);if(s.crv&&(n=C(t,e,r,s.crv)),s.ccv&&(n=K(t,e,r,s.ccv)??n),!!n)return r.getText()};var F=(t,e)=>{let i=t.artifacts.find(a=>a.id==="css-fn"),n=t.artifacts.find(a=>a.id==="css-index"),r=n?.files.find(a=>a.file.match(/^index\.(mjs|js)/)),s=n?.files.find(a=>a.file.includes("index.d.")),o=r?.file.split(".").at(-1),c=s?.file.split(".").at(-1);if(!i||!r||!s)return t.artifacts;let f={file:`crv.${o}`,code:T(e.breakpoints)},p={file:`crv.d.${c}`,code:S(e.breakpoints)};return i.files.push(f,p),r.code+=` export * from './crv.${o}';`,s.code+=` export * from './crv';`,e.debug&&e.debug("plugin:crv","codegen complete"),t.artifacts};import{IndentationText as h,Project as V,ts as b}from"ts-morph";var R=()=>({project:new V({compilerOptions:{jsx:b.JsxEmit.React,jsxFactory:"React.createElement",jsxFragmentFactory:"React.Fragment",module:b.ModuleKind.ESNext,target:b.ScriptTarget.ESNext,noUnusedParameters:!1,noEmit:!0,useVirtualFileSystem:!0,allowJs:!0},skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0,skipLoadingLibFiles:!0,manipulationSettings:{indentationText:h.TwoSpaces}}),breakpoints:[]});var le=()=>{let t=R();return{name:"panda-plugin-crv",hooks:{"context:created":e=>{t.debug=e.logger?.debug,t.breakpoints=Object.keys(e.ctx.config.theme?.breakpoints??{})},"parser:before":e=>B(e,t),"codegen:prepare":e=>F(e,t)}}};export{le as pluginResponsiveVariants};