Skip to content

Commit

Permalink
MVP Core
Browse files Browse the repository at this point in the history
  • Loading branch information
Brijesh Bittu committed Dec 4, 2024
1 parent 56ace5a commit 3cc6195
Show file tree
Hide file tree
Showing 20 changed files with 324 additions and 26 deletions.
4 changes: 1 addition & 3 deletions packages/eslint-plugin-material-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
"@typescript-eslint/experimental-utils": "^5.62.0",
"@typescript-eslint/parser": "^7.5.0"
},
"scripts": {
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/eslint-plugin-material-ui/**/*.test.js' --timeout 3000"
},
"scripts": {},
"license": "MIT"
}
5 changes: 5 additions & 0 deletions packages/pigment-css-core/exports/keyframes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Object.defineProperty(exports, '__esModule', {
value: true,
});

exports.default = require('../build/processors/keyframes').KeyframesProcessor;
5 changes: 0 additions & 5 deletions packages/pigment-css-core/src/globalCss.d.ts

This file was deleted.

10 changes: 0 additions & 10 deletions packages/pigment-css-core/src/globalCss.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/pigment-css-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ export * from '@pigment-css/theme';
export * from './base';
export { default as css } from './css';
export { default as keyframes } from './keyframes';
export { default as globalCss } from './globalCss';
161 changes: 161 additions & 0 deletions packages/pigment-css-core/src/processors/keyframes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import type { Expression } from '@babel/types';
import type {
CallParam,
TemplateParam,
Params,
TailProcessorParams,
ValueCache,
} from '@wyw-in-js/processor-utils';
import { type Replacements, type Rules, ValueType } from '@wyw-in-js/shared';
import { BaseProcessor, validateParams } from '@wyw-in-js/processor-utils';
import { PigmentConfig, serializeStyles, processStyle } from '@pigment-css/shared';

export type Primitive = string | number | boolean | null | undefined;

export type TemplateCallback = (params: Record<string, unknown> | undefined) => string | number;

export class KeyframesProcessor extends BaseProcessor {
callParam: CallParam | TemplateParam;

constructor(params: Params, ...args: TailProcessorParams) {
super([params[0]], ...args);
if (params.length < 2) {
throw BaseProcessor.SKIP;
}
validateParams(
params,
['callee', ['call', 'template']],
`Invalid use of ${this.tagSource.imported} tag.`,
);

const [, callParams] = params;
if (callParams[0] === 'call') {
this.dependencies.push(callParams[1]);
} else if (callParams[0] === 'template') {
callParams[1].forEach((element) => {
if ('kind' in element && element.kind !== ValueType.CONST) {
this.dependencies.push(element);
}
});
}
this.callParam = callParams;
}

build(values: ValueCache) {
if (this.artifacts.length > 0) {
throw new Error(`MUI: "${this.tagSource.imported}" is already built`);
}

const [callType] = this.callParam;

if (callType === 'template') {
this.handleTemplate(this.callParam, values);
} else {
this.handleCall(this.callParam, values);
}
}

private handleTemplate([, callArgs]: TemplateParam, values: ValueCache) {
const templateStrs: string[] = [];
// @ts-ignore @TODO - Fix this. No idea how to initialize a Tagged String array.
templateStrs.raw = [];
const templateExpressions: Primitive[] = [];
const { themeArgs } = this.options as PigmentConfig;

callArgs.forEach((item) => {
if ('kind' in item) {
switch (item.kind) {
case ValueType.FUNCTION: {
const value = values.get(item.ex.name) as TemplateCallback;
templateExpressions.push(value(themeArgs));
break;
}
case ValueType.CONST:
templateExpressions.push(item.value);
break;
case ValueType.LAZY: {
const evaluatedValue = values.get(item.ex.name);
if (typeof evaluatedValue === 'function') {
templateExpressions.push(evaluatedValue(themeArgs));
} else {
templateExpressions.push(evaluatedValue as Primitive);
}
break;
}
default:
break;
}
} else if (item.type === 'TemplateElement') {
templateStrs.push(item.value.cooked as string);
// @ts-ignore
templateStrs.raw.push(item.value.raw);
}
});
this.generateArtifacts(templateStrs, ...templateExpressions);
}

generateArtifacts(styleObjOrTagged: string[], ...args: Primitive[]) {
const { styles } = serializeStyles(
args.length > 0 ? [styleObjOrTagged, ...args] : [styleObjOrTagged],
);
const cssText = `@keyframes {${styles}}`;

const rules: Rules = {
[this.asSelector]: {
className: this.className,
cssText,
displayName: this.displayName,
start: this.location?.start ?? null,
},
};
const sourceMapReplacements: Replacements = [
{
length: cssText.length,
original: {
start: {
column: this.location?.start.column ?? 0,
line: this.location?.start.line ?? 0,
},
end: {
column: this.location?.end.column ?? 0,
line: this.location?.end.line ?? 0,
},
},
},
];
this.artifacts.push(['css', [rules, sourceMapReplacements]]);
}

private handleCall([, callArg]: CallParam, values: ValueCache) {
if (callArg.kind === ValueType.LAZY || callArg.kind === ValueType.FUNCTION) {
const value = values.get(callArg.ex.name);
const { themeArgs } = this.options as PigmentConfig;
const styleObj = typeof value === 'function' ? value(themeArgs) : value;
if (styleObj) {
let count = 0;
// Won't actually be used since keyframes call doesn't allow function values
const getVariableName = () => {
count += 1;
return `${this.className}-${count}`;
};
this.generateArtifacts(processStyle(styleObj, { getVariableName }).result);
}
}
}

doEvaltimeReplacement() {
this.replacer(this.value, false);
}

doRuntimeReplacement() {
this.doEvaltimeReplacement();
}

get asSelector() {
return this.className;
}

get value(): Expression {
return this.astService.stringLiteral(this.className);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { keyframes } from '@pigment-css/core';

const green = 'green';

const gradientKeyframe = keyframes(({ theme }) => ({
'0%': {
background: theme.palette.primary.main,
},
'50%': {
background: green,
},
'100%': {
background: theme.palette.secondary.main,
},
}));

const gradientKeyframe2 = keyframes`
0% {
background: ${({ theme }) => theme.palette.primary.main};
}
50% {
background: ${green};
}
100% {
background: ${({ theme }) => theme.palette.secondary.main};
}
`;

// simulate CssBaseline transpiled by Next.js
export const styles = (theme) => ({
'0%': {
background: theme.palette.primary.main,
},
'50%': {
background: green,
},
'100%': {
background: theme.palette.secondary.main,
},
});
const gradientKeyframe3 = keyframes((_c = ({ theme }) => styles(theme)));
var _c;

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const green = 'green';
const gradientKeyframe = 'g5g95nd';
const gradientKeyframe2 = 'gt2fuab';

// simulate CssBaseline transpiled by Next.js
export const styles = (theme) => ({
'0%': {
background: theme.palette.primary.main,
},
'50%': {
background: green,
},
'100%': {
background: theme.palette.secondary.main,
},
});
const gradientKeyframe3 = 'g1611ti3';
var _c;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { keyframes } from '@pigment-css/core';

const rotateKeyframe = keyframes({
from: {
transform: 'rotate(360deg)',
},
to: {
transform: 'rotate(0deg)',
},
});

const rotateKeyframe2 = keyframes`
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
`;

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const rotateKeyframe = 'rrtfw11';
const rotateKeyframe2 = 'rw2yxe7';
36 changes: 36 additions & 0 deletions packages/pigment-css-core/tests/keyframes/keyframes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import path from 'node:path';
import { runTransformation, expect } from '../testUtils';

describe('Pigment CSS - keyframes', () => {
it('basics', async () => {
const { output, fixture } = await runTransformation(
path.join(__dirname, 'fixtures/keyframes.input.js'),
);

expect(output.js).to.equal(fixture.js);
expect(output.css).to.equal(fixture.css);
});

it('should transform correctly with theme', async () => {
const { output, fixture } = await runTransformation(
path.join(__dirname, 'fixtures/keyframes-theme.input.js'),
{
themeArgs: {
theme: {
palette: {
primary: {
main: 'red',
},
secondary: {
main: 'blue',
},
},
},
},
},
);

expect(output.js).to.equal(fixture.js);
expect(output.css).to.equal(fixture.css);
});
});
2 changes: 1 addition & 1 deletion packages/pigment-css-core/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Options, defineConfig } from 'tsup';
import config from '../../tsup.config';

const processors = ['css'];
const processors = ['css', 'keyframes'];

const baseConfig: Options = {
...(config as Options),
Expand Down
3 changes: 2 additions & 1 deletion packages/pigment-css-shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"module": "build/index.mjs",
"types": "build/index.d.ts",
"author": "MUI Team",
"description": "Node utilities to be used internally across Pigment CSS libraries.",
"description": "Node utilities to be used internally across Pigment CSS libraries.",
"repository": {
"type": "git",
"url": "git+https://github.com/mui/pigment-css.git",
Expand Down Expand Up @@ -52,6 +52,7 @@
"access": "public"
},
"files": [
"src",
"build",
"package.json",
"LICENSE"
Expand Down
7 changes: 5 additions & 2 deletions packages/pigment-css-shared/src/utils/processStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ function transformProbableCssVar(value: string): string {
});
}

function processStyle<T extends object>(t: T, options: ProcessStyleOptions): ProcessStyleReturn<T> {
export function processStyle<T extends object>(
t: T,
options: ProcessStyleOptions,
): ProcessStyleReturn<T> {
const result: Record<string, string | number | object> = {};
let variables: ProcessStyleReturn<T>['variables'] = {};

Expand All @@ -100,7 +103,7 @@ function processStyle<T extends object>(t: T, options: ProcessStyleOptions): Pro
} else if (typeof value === 'function') {
const variableRaw = getCSSVar(cssesc(options.getVariableName()));
variables[variableRaw] = [value, isUnitLess(newKey) ? 1 : 0];
result[newKey] = getCSSVar(variableRaw, true);
result[newKey] = `var(${variableRaw})`;
}
});
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('processStyle', () => {
expect(res).to.deep.equal({
result: {
'---hello': 'world',
'--hello-1': 'world',
'--hello1': 'world',
'.cls1': {
border: '1px solid var(--palette-primary-main) var(---hello)',
color: 'var(--var-1)',
Expand Down
Loading

0 comments on commit 3cc6195

Please sign in to comment.