Skip to content

Commit

Permalink
Add defaultVariants support in runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
Brijesh Bittu committed Feb 1, 2025
1 parent 6b83625 commit d727ea8
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 7 deletions.
35 changes: 28 additions & 7 deletions packages/pigment-css-core/src/runtime/css.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* This module is not supposed to be imported by users.
*/
type Props = Record<string, string | number>;
type Props = Record<string, string | number | boolean>;

export type VariantInfo = {
$$cls: string;
Expand All @@ -11,36 +11,57 @@ export type VariantInfo = {
export type ClassInfo = {
classes: string;
variants?: VariantInfo[];
defaultVariants?: Props;
};

function isVariantMatching(props: Props, variantProps: Props) {
function isVariantMatching(props: Props, variantProps: Props, defaultVariants: Props = {}) {
// eslint-disable-next-line no-restricted-syntax
for (const key in variantProps) {
if (!variantProps.hasOwnProperty(key)) {
continue;
}
if (variantProps[key] !== props[key]) {
const propValue = props[key] ?? defaultVariants[key];
// eslint-disable-next-line eqeqeq
if (variantProps[key] != propValue) {
return false;
}
}
return true;
}

export function css({ classes, variants = [] }: ClassInfo) {
return (props?: Props) => {
export function css({ classes, variants = [], defaultVariants = {} }: ClassInfo) {
let baseClasses = classes;

if (variants.length > 0) {
const newClasses = [];
for (let i = 0; i < variants.length; i += 1) {
const variant = variants[i];
if (isVariantMatching(defaultVariants, variant.props)) {
newClasses.push(variant.$$cls);
}
}
if (newClasses.length > 0) {
baseClasses = `${baseClasses} ${newClasses.join(' ')}`;
}
}
function cssWithProps(props?: Props) {
if (!props || !variants.length) {
return classes;
return baseClasses;
}

const newClasses = [];
for (let i = 0; i < variants.length; i += 1) {
const variant = variants[i];
if (isVariantMatching(props, variant.props)) {
if (isVariantMatching(props, variant.props, defaultVariants)) {
newClasses.push(variant.$$cls);
}
}
if (!newClasses.length) {
return classes;
}
return `${classes} ${newClasses.join(' ')}`;
}
cssWithProps.toString = function toString() {
return baseClasses;
};
}
30 changes: 30 additions & 0 deletions packages/pigment-css-core/tests/css/css-runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,34 @@ describe('css - runtime', () => {
'hello world c-secondary-s-medium',
);
});

it('should consider defaultVariants when returning classes', () => {
const cssFn = css({
classes: 'hello world',
variants: [
{
props: { color: 'primary' },
$$cls: 'c-primary',
},
{
props: { size: 'medium' },
$$cls: 's-medium',
},
{
props: { color: 'secondary', size: 'medium' },
$$cls: 'c-secondary-s-medium',
},
],
defaultVariants: {
color: 'primary',
size: 'medium',
},
});
expect(cssFn.toString()).to.equal('hello world c-primary s-medium');
expect(cssFn({})).to.equal('hello world c-primary s-medium');
expect(cssFn({ color: 'secondary' })).to.equal('hello world s-medium c-secondary-s-medium');
expect(cssFn({ color: 'tertiary', size: 'medium' })).to.equal('hello world s-medium');
expect(cssFn({ size: 'large' })).to.equal('hello world c-primary');
expect(cssFn({ size: 'large', color: 'tertiary' })).to.equal('hello world');
});
});

0 comments on commit d727ea8

Please sign in to comment.