Skip to content

Commit

Permalink
Add Sprinkles (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattcompiles committed Apr 28, 2021
1 parent 2d98bcc commit 58e4f8a
Show file tree
Hide file tree
Showing 24 changed files with 1,949 additions and 18 deletions.
6 changes: 6 additions & 0 deletions .changeset/lovely-tigers-applaud.md
@@ -0,0 +1,6 @@
---
'@vanilla-extract/esbuild-plugin': minor
'@vanilla-extract/webpack-plugin': minor
---

Support exporting functions from `.css.ts` files via recipes
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -3,6 +3,8 @@ dist
tsconfig.tsbuildinfo
yarn-error.log
packages/**/README.md
!packages/sprinkles/README.md


.yarn/*
!.yarn/patches
Expand Down
12 changes: 8 additions & 4 deletions README.md
Expand Up @@ -76,6 +76,10 @@ document.write(`

---

Want to work at a higher level while maximising style re-use? Check out 🍨 [Sprinkles](https://github.com/seek-oss/vanilla-extract/tree/master/packages/sprinkles), our official zero-runtime atomic CSS framework, built on top of vanilla-extract.

---

- [Setup](#setup)
- [webpack](#webpack)
- [esbuild](#esbuild)
Expand Down Expand Up @@ -115,7 +119,7 @@ There are currently a few integrations to choose from.
1. Install the dependencies.

```bash
$ yarn add --dev @vanilla-extract/css @vanilla-extract/babel-plugin @vanilla-extract/webpack-plugin
$ npm install @vanilla-extract/css @vanilla-extract/babel-plugin @vanilla-extract/webpack-plugin
```

2. Add the [Babel](https://babeljs.io) plugin.
Expand Down Expand Up @@ -171,7 +175,7 @@ module.exports = {
1. Install the dependencies.

```bash
$ yarn add --dev @vanilla-extract/css @vanilla-extract/esbuild-plugin
$ npm install @vanilla-extract/css @vanilla-extract/esbuild-plugin
```

2. Add the [esbuild](https://esbuild.github.io/) plugin to your build script.
Expand Down Expand Up @@ -620,7 +624,7 @@ export const green = composeStyles(base, style({
We also provide a lightweight standalone package to support dynamic runtime theming.

```bash
$ yarn add --dev @vanilla-extract/dynamic
$ npm install @vanilla-extract/dynamic
```

### createInlineTheme
Expand Down Expand Up @@ -681,7 +685,7 @@ We also provide a standalone package of optional utility functions to make it ea
> 💡 This package can be used with any CSS-in-JS library.
```bash
$ yarn add --dev @vanilla-extract/css-utils
$ npm install @vanilla-extract/css-utils
```

### calc
Expand Down
12 changes: 12 additions & 0 deletions fixtures/sprinkles/package.json
@@ -0,0 +1,12 @@
{
"name": "@fixtures/sprinkles",
"version": "0.0.0",
"main": "src/index.ts",
"sideEffects": true,
"author": "SEEK",
"private": true,
"dependencies": {
"@vanilla-extract/css": "0.3.2",
"@vanilla-extract/sprinkles": "0.1.0"
}
}
18 changes: 18 additions & 0 deletions fixtures/sprinkles/src/index.ts
@@ -0,0 +1,18 @@
import { atoms } from './styles.css';
import testNodes from '../test-nodes.json';

function render() {
document.body.innerHTML = `
<div id="${testNodes.root}" class="${atoms({
display: 'block',
paddingTop: {
mobile: 'small',
desktop: 'medium',
},
})}">
Sprinkles
</div>
`;
}

render();
28 changes: 28 additions & 0 deletions fixtures/sprinkles/src/styles.css.ts
@@ -0,0 +1,28 @@
import { createAtomicStyles, createAtomsFn } from '@vanilla-extract/sprinkles';

export const atoms = createAtomsFn(
createAtomicStyles({
defaultCondition: 'mobile',
conditions: {
mobile: {},
tablet: {
'@media': 'screen and (min-width: 768px)',
},
desktop: {
'@media': 'screen and (min-width: 1024px)',
},
darkDesktop: {
'@supports': 'not (display: grid)',
'@media': 'screen and (min-width: 1024px)',
selector: '[data-dark-mode] &',
},
},
properties: {
display: ['flex', 'none', 'block'],
paddingTop: {
small: '10px',
medium: '20px',
},
},
}),
);
3 changes: 3 additions & 0 deletions fixtures/sprinkles/test-nodes.json
@@ -0,0 +1,3 @@
{
"root": "root"
}
45 changes: 41 additions & 4 deletions packages/esbuild-plugin/src/index.ts
Expand Up @@ -11,6 +11,10 @@ import { build as esbuild, Plugin } from 'esbuild';
import evalCode from 'eval';
import { stringify } from 'javascript-stringify';
import isPlainObject from 'lodash/isPlainObject';
import crypto from 'crypto';

const hash = (value: string) =>
crypto.createHash('md5').update(value).digest('hex');

const vanillaCssNamespace = 'vanilla-extract-css-ns';

Expand Down Expand Up @@ -192,7 +196,7 @@ export function vanillaExtractPlugin({
};
}

const stringifyExports = (value: any) =>
const stringifyExports = (recipeImports: Set<string>, value: any): any =>
stringify(
value,
(value, _indent, next) => {
Expand All @@ -208,6 +212,37 @@ const stringifyExports = (value: any) =>
return next(value);
}

if (valueType === 'function' && value.__recipe__) {
const { importPath, importName, args } = value.__recipe__;

if (
typeof importPath !== 'string' ||
typeof importName !== 'string' ||
!Array.isArray(args)
) {
throw new Error('Invalid recipe');
}

try {
const hashedImportName = `_${hash(`${importName}${importPath}`).slice(
0,
5,
)}`;

recipeImports.add(
`import { ${importName} as ${hashedImportName} } from '${importPath}';`,
);

return `${hashedImportName}(${args
.map((arg) => stringifyExports(recipeImports, arg))
.join(',')})`;
} catch (err) {
console.error(err);

throw new Error('Invalid recipe.');
}
}

throw new Error(dedent`
Invalid exports.
Expand All @@ -230,13 +265,15 @@ const serializeVanillaModule = (
return `import '${request}';`;
});

const recipeImports = new Set<string>();

const moduleExports = Object.keys(exports).map((key) =>
key === 'default'
? `export default ${stringifyExports(exports[key])};`
: `export var ${key} = ${stringifyExports(exports[key])};`,
? `export default ${stringifyExports(recipeImports, exports[key])};`
: `export var ${key} = ${stringifyExports(recipeImports, exports[key])};`,
);

const outputCode = [...cssImports, ...moduleExports];
const outputCode = [...cssImports, ...recipeImports, ...moduleExports];

return outputCode.join('\n');
};

0 comments on commit 58e4f8a

Please sign in to comment.