simplestyle-js 5.5.1-alpha.2 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -306
- package/compiler/cli.js +207 -0
- package/compiler/collector.js +50 -0
- package/compiler/dependencyGraph.js +217 -0
- package/compiler/empty.js +1 -0
- package/compiler/getCommonRootPath.js +44 -0
- package/compiler/interceptor.js +42 -0
- package/compiler/mock.js +107 -0
- package/compiler/register.js +24 -0
- package/dist/browser/index.d.ts +5 -0
- package/dist/browser/index.mjs +4 -0
- package/dist/makeStyles/createImports.d.ts +4 -0
- package/dist/makeStyles/createImports.mjs +25 -0
- package/dist/makeStyles/createKeyframes.d.ts +6 -0
- package/dist/makeStyles/createKeyframes.mjs +20 -0
- package/dist/makeStyles/createRawStyles.d.ts +4 -0
- package/dist/makeStyles/createRawStyles.mjs +18 -0
- package/dist/makeStyles/createSheet.d.ts +4 -0
- package/dist/makeStyles/createSheet.mjs +22 -0
- package/dist/makeStyles/createStyles.d.ts +9 -0
- package/dist/makeStyles/createStyles.mjs +54 -0
- package/dist/makeStyles/execCreateStyles.d.ts +6 -0
- package/dist/makeStyles/execCreateStyles.mjs +66 -0
- package/dist/makeStyles/flushSheetContents.d.ts +2 -0
- package/dist/makeStyles/flushSheetContents.mjs +20 -0
- package/dist/makeStyles/generateClassName.d.ts +13 -0
- package/dist/makeStyles/generateClassName.mjs +24 -0
- package/dist/makeStyles/makeCssFuncsBrowser.d.ts +29 -0
- package/dist/makeStyles/makeCssFuncsBrowser.mjs +64 -0
- package/dist/makeStyles/types.d.ts +27 -0
- package/dist/makeStyles/types.mjs +1 -0
- package/dist/makeStyles/utils.d.ts +5 -0
- package/dist/makeStyles/utils.mjs +13 -0
- package/dist/{cjs/simpleStyleRegistry.d.ts → simpleStyleRegistry.d.ts} +0 -4
- package/dist/{esm/simpleStyleRegistry.mjs → simpleStyleRegistry.mjs} +0 -5
- package/dist/ssr/index.d.ts +6 -0
- package/dist/ssr/index.mjs +4 -0
- package/dist/ssr/makeCssFuncsSSR.d.ts +31 -0
- package/dist/ssr/makeCssFuncsSSR.mjs +59 -0
- package/dist/types.d.ts +4 -0
- package/package.json +51 -166
- package/dist/cjs/astro/SimpleStyleProvider.astro +0 -16
- package/dist/cjs/createStyles.cjs +0 -274
- package/dist/cjs/createStyles.d.ts +0 -51
- package/dist/cjs/generateClassName.cjs +0 -62
- package/dist/cjs/generateClassName.d.ts +0 -3
- package/dist/cjs/index.cjs +0 -90
- package/dist/cjs/index.d.ts +0 -8
- package/dist/cjs/makeStyles.cjs +0 -55
- package/dist/cjs/makeStyles.d.ts +0 -42
- package/dist/cjs/next/SimpleStyleProvider.cjs +0 -31
- package/dist/cjs/next/SimpleStyleProvider.d.ts +0 -11
- package/dist/cjs/next/index.cjs +0 -19
- package/dist/cjs/next/index.d.ts +0 -2
- package/dist/cjs/next/registry.cjs +0 -52
- package/dist/cjs/next/registry.d.ts +0 -3
- package/dist/cjs/numToAlpha.cjs +0 -14
- package/dist/cjs/numToAlpha.d.ts +0 -1
- package/dist/cjs/package.json +0 -1
- package/dist/cjs/plugins.cjs +0 -25
- package/dist/cjs/simpleStyleRegistry.cjs +0 -59
- package/dist/cjs/styleCache.cjs +0 -27
- package/dist/cjs/styleCache.d.ts +0 -2
- package/dist/cjs/types.cjs +0 -4
- package/dist/cjs/types.d.ts +0 -9
- package/dist/cjs/util/deepEqual.cjs +0 -27
- package/dist/cjs/util/deepEqual.d.ts +0 -1
- package/dist/cjs/util/index.cjs +0 -18
- package/dist/cjs/util/index.d.ts +0 -1
- package/dist/esm/astro/SimpleStyleProvider.astro +0 -16
- package/dist/esm/createStyles.d.ts +0 -51
- package/dist/esm/createStyles.mjs +0 -242
- package/dist/esm/generateClassName.d.ts +0 -3
- package/dist/esm/generateClassName.mjs +0 -36
- package/dist/esm/index.d.ts +0 -8
- package/dist/esm/index.mjs +0 -6
- package/dist/esm/makeStyles.d.ts +0 -42
- package/dist/esm/makeStyles.mjs +0 -51
- package/dist/esm/next/SimpleStyleProvider.d.ts +0 -11
- package/dist/esm/next/SimpleStyleProvider.mjs +0 -27
- package/dist/esm/next/index.d.ts +0 -2
- package/dist/esm/next/index.mjs +0 -2
- package/dist/esm/next/registry.d.ts +0 -3
- package/dist/esm/next/registry.mjs +0 -34
- package/dist/esm/numToAlpha.d.ts +0 -1
- package/dist/esm/numToAlpha.mjs +0 -4
- package/dist/esm/plugins.d.ts +0 -3
- package/dist/esm/simpleStyleRegistry.d.ts +0 -37
- package/dist/esm/styleCache.d.ts +0 -2
- package/dist/esm/styleCache.mjs +0 -9
- package/dist/esm/types.d.ts +0 -9
- package/dist/esm/util/deepEqual.d.ts +0 -1
- package/dist/esm/util/deepEqual.mjs +0 -17
- package/dist/esm/util/index.d.ts +0 -1
- package/dist/esm/util/index.mjs +0 -1
- /package/dist/{esm/package.json → package.json} +0 -0
- /package/dist/{cjs/plugins.d.ts → plugins.d.ts} +0 -0
- /package/dist/{esm/plugins.mjs → plugins.mjs} +0 -0
- /package/dist/{esm/types.mjs → types.mjs} +0 -0
package/README.md
CHANGED
|
@@ -2,26 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
An ultra-tiny, neat, easy-to-use CSS-in-JS library with SSR support,
|
|
4
4
|
tiny bundle size and only *one runtime dependency*.
|
|
5
|
+
Framework agnostic by design — works with React, Vue, Svelte, Next.js, Astro, or no framework at all.
|
|
5
6
|
|
|
6
7
|
`6.48kB` / `2.69kB gzip` ([courtesy of bundlejs.com](https://bundlejs.com/?q=simplestyle-js))
|
|
7
8
|
|
|
8
|
-
# Simplestyle-js Reference
|
|
9
|
-
|
|
10
|
-
A concise guide to the core `simplestyle-js` APIs, how they fit together, and how to use them in browser and server-rendered apps (including Next.js).
|
|
11
|
-
|
|
12
9
|
## Table of Contents
|
|
13
10
|
- [Install](#install)
|
|
14
|
-
- [Quick Start](#quick-start)
|
|
11
|
+
- [Quick Start (Browser)](#quick-start-browser)
|
|
12
|
+
- [SSR / Static Extraction (Framework-Agnostic)](#ssr--static-extraction-framework-agnostic)
|
|
15
13
|
- [API Reference](#api-reference)
|
|
16
14
|
- [Patterns and Tips](#patterns-and-tips)
|
|
17
|
-
- [Creating reusable variables and / or design system-like tokens](#reusable-variables)
|
|
18
|
-
- [SSR](#ssr)
|
|
19
|
-
- [Next.js](#nextjs)
|
|
20
|
-
- [Astro](#astro)
|
|
21
|
-
- [SSR steps for most SSR / SSG frameworks](#ssr-steps-for-most-ssr--ssg-frameworks)
|
|
22
|
-
- [1. Set your seed, create a SimpleStyleRegistry and your style functions](#1-set-your-seed-create-a-simplestyleregistry-and-your-style-functions)
|
|
23
|
-
- [2. Render the generated styles in your HTML](#2-render-the-generated-styles-in-your-html)
|
|
24
|
-
- [3. Create your styles and have fun!](#3-create-your-styles-and-have-fun)
|
|
25
15
|
- [Creating a simplestyle-js plugin](#creating-a-simplestyle-js-plugin)
|
|
26
16
|
- [Plugin Example (Autoprefixer)](#plugin-example-autoprefixer)
|
|
27
17
|
- [License](#license)
|
|
@@ -50,367 +40,239 @@ pnpm add simplestyle-js
|
|
|
50
40
|
yarn add simplestyle-js
|
|
51
41
|
```
|
|
52
42
|
|
|
53
|
-
## Quick Start
|
|
43
|
+
## Quick Start (Runtime styles in the Browser)
|
|
44
|
+
|
|
45
|
+
Use the browser entrypoint for runtime CSS injection. This variant creates `<style />` tags in the browser and is the most traditional CSS‑in‑JS experience.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { makeCssFuncs } from 'simplestyle-js/browser';
|
|
49
|
+
|
|
50
|
+
const { createStyles, createKeyframes, createRawStyles } = makeCssFuncs();
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
const { keyframe } = createKeyframes('Pulse', () => ({
|
|
53
|
+
'0%': { opacity: 0.6, transform: 'scale(0.98)' },
|
|
54
|
+
'100%': { opacity: 1, transform: 'scale(1)' },
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
createRawStyles('GlobalReset', () => ({
|
|
58
|
+
'*, *::before, *::after': { boxSizing: 'border-box' },
|
|
59
|
+
body: { margin: 0, fontFamily: 'system-ui, sans-serif' },
|
|
60
|
+
}));
|
|
57
61
|
|
|
58
62
|
const { classes } = createStyles('Button', () => ({
|
|
59
63
|
root: {
|
|
60
|
-
'&:hover': { backgroundColor: '#2d6cdf' },
|
|
61
|
-
'@media (max-width: 768px)': { padding: '10px 12px' },
|
|
62
64
|
backgroundColor: '#1f4aa8',
|
|
63
65
|
borderRadius: 6,
|
|
64
66
|
color: '#fff',
|
|
65
67
|
padding: '12px 16px',
|
|
68
|
+
animation: `${keyframe} 900ms ease-in-out infinite alternate`,
|
|
69
|
+
'&:hover': { backgroundColor: '#2d6cdf' },
|
|
70
|
+
'@media (max-width: 768px)': { padding: '10px 12px' },
|
|
66
71
|
},
|
|
67
72
|
}));
|
|
68
73
|
|
|
69
74
|
document.querySelector('button')?.classList.add(classes.root);
|
|
70
|
-
|
|
71
|
-
// or, in a React / JSX-like component
|
|
72
|
-
const Button = (props) => <button {...props} className={classes.root}>Awesome button</button>
|
|
73
75
|
```
|
|
74
76
|
|
|
75
|
-
Rules support nested selectors via `&`, media queries, and `$className` back
|
|
76
|
-
|
|
77
|
-
## API Reference
|
|
77
|
+
Rules support nested selectors via `&`, media queries, and `$className` back‑references to other generated classes.
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
- Builds a set of class names and CSS from a rules object. Returns `{ classes, stylesheet, updateSheet }`.
|
|
81
|
-
- `options.flush` (default `true`): injects a `<style>` tag into `document.head`.
|
|
82
|
-
- `options.insertBefore` / `insertAfter`: choose where the `<style>` tag is placed when flushing.
|
|
83
|
-
- `options.registry`: provide a `SimpleStyleRegistry` instance to **collect** CSS instead of touching the DOM (ideal for SSR).
|
|
84
|
-
- `updateSheet(updatedRules)` merges rules and updates the existing sheet (works when `flush` is `true` or a `registry` is provided). Returns `{ classes, stylesheet } | null`.
|
|
85
|
-
- Example:
|
|
86
|
-
```ts
|
|
87
|
-
const { classes, stylesheet } = createStyles('Nav', () => ({
|
|
88
|
-
wrapper: { display: 'flex', gap: 12 },
|
|
89
|
-
link: {
|
|
90
|
-
'&:hover': { textDecoration: 'underline' },
|
|
91
|
-
},
|
|
92
|
-
'@media (max-width: 600px)': {
|
|
93
|
-
wrapper: { flexDirection: 'column' },
|
|
94
|
-
},
|
|
95
|
-
}), { flush: false }); // do not write to the DOM automatically
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
- `imports(ruleId, importRulesFnc, options?)`
|
|
99
|
-
- Allow you to define one or more `@import()` rules for importing or referencing external stylesheets. **Note**: These imports will not be transformed or attempted to have their contents imported.
|
|
100
|
-
|
|
101
|
-
- `keyframes(ruleId, framesFnc, options?)`
|
|
102
|
-
- Generates a unique animation name and accompanying `@keyframes` CSS.
|
|
103
|
-
- Returns `{ keyframe: string; stylesheet: string; }`. Respects `flush` and `insertBefore/After` options.
|
|
104
|
-
|
|
105
|
-
- `rawStyles(ruleId, rulesFnc, options?)`
|
|
106
|
-
- Writes rules without generating new class names. Keys must already be selectors (e.g., `html`, `body *`, `.app`).
|
|
107
|
-
- Good for global resets or theme primitives. Respects `flush` and `registry`.
|
|
108
|
-
|
|
109
|
-
- `makeCssFuncs({ registry?, variables? })`
|
|
110
|
-
- Returns `createStyles`, `keyframes` and `rawStyles` functions for you to use that are bound to an optional `SimpleStyleRegistry` and an optional `variables` object.
|
|
111
|
-
- Use this variant if you want to bind all of the CSS functions to a set of styling tokens / variables that you want accessible and available wherever you write your CSS, complete with IDE intellisense.
|
|
112
|
-
- Use this as a convenience if you don't want to manually wire up each CSS function (listed below) to your registry.
|
|
113
|
-
|
|
114
|
-
- `makeCreateStyles(registry)`
|
|
115
|
-
- Convenience wrapper that returns a `createStyles` instance pre-bound to a `SimpleStyleRegistry`. Use this when you want every call to accumulate in a registry (especially useful for SSR / Server-side rendering).
|
|
116
|
-
|
|
117
|
-
- `makeRawStyles(registry)`
|
|
118
|
-
- Returns a `rawStyles` helper preconfigured with the provided registry; calls will auto-add to that registry instead of touching the DOM (same motivation as `makeCreateStyles` for SSR motivations).
|
|
119
|
-
|
|
120
|
-
- `makeKeyframes(registry)`
|
|
121
|
-
- Returns a `keyframes` helper preconfigured with the provided registry; calls will auto-add to that registry instead of touching the DOM (same motivation as `makeCreateStyles` for SSR motivations).
|
|
122
|
-
|
|
123
|
-
- `setSeed(seed: number | null)`
|
|
124
|
-
- Controls the deterministic suffix used for generated class names. Setting the same seed in server and client renders keeps class names stable for hydration. Pass `null` to reset to `Date.now()`.
|
|
125
|
-
|
|
126
|
-
- `registerPosthook(fn: (sheet: string) => string)`
|
|
127
|
-
- Adds a transform that runs after CSS strings are generated but before they are flushed or stored. Use for autoprefixing, minification, or custom transforms. Hooks run in registration order.
|
|
128
|
-
|
|
129
|
-
- Types
|
|
130
|
-
- `SimpleStyleRules`: `{ [selectorOrKey: string]: Properties | SimpleStyleRules }` (recursive rule tree).
|
|
131
|
-
- `CreateStylesOptions`: shape of the options described above.
|
|
132
|
-
- `PosthookPlugin`: signature for `registerPosthook`.
|
|
79
|
+
## SSR / Static Extraction (Framework‑Agnostic)
|
|
133
80
|
|
|
134
|
-
|
|
81
|
+
The SSR workflow requires usage of the built in `ssjs` CLI tool.
|
|
82
|
+
This works by scanning your source files and generating a single `.css` file, containing all of the collected styles.
|
|
83
|
+
Your source code remains untouched and does not require any transformation or transpilation.
|
|
84
|
+
To leverage this, you **must** use the SSR entrypoint and place all styles in files named with the following format:
|
|
135
85
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- **Media queries**: Top-level `@media` keys contain further rule objects.
|
|
140
|
-
- **DOM placement**: `insertBefore` and `insertAfter` let you control the exact placement for where `<style />` tags will be rendered (does not apply to SSR / Server-side rendering).br
|
|
141
|
-
- **Updating styles**: `updateSheet` merges the new rules and updates the existing `<style>` tag (or registry entry, if you're not letting `simplestyle-js` flush to the DOM automatically for you). It also returns `{ classes, stylesheet }` so you can re-use class names if needed.
|
|
86
|
+
```
|
|
87
|
+
*.styles.{js|cjs|mjs|ts|mts|cts|jsx|tsx}
|
|
88
|
+
```
|
|
142
89
|
|
|
143
|
-
|
|
90
|
+
Run the `ssjs` CLI to compile a single CSS file. This works with **Next.js, Astro, or any framework** (SSR or SSG) because the output is just plain CSS.
|
|
144
91
|
|
|
145
|
-
|
|
146
|
-
To do this, you would use the same API that's used to bind to a specific sheet registry, but specify the `variables` option:
|
|
92
|
+
### 1) Write styles in `*.styles.*` files
|
|
147
93
|
|
|
148
|
-
```
|
|
149
|
-
|
|
94
|
+
```ts
|
|
95
|
+
// src/components/button.styles.ts
|
|
96
|
+
import { makeCssFuncs } from 'simplestyle-js/ssr';
|
|
150
97
|
|
|
98
|
+
const { createStyles } = makeCssFuncs();
|
|
151
99
|
|
|
152
|
-
export const {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
const { classes } = createStyles('my-component', vars => ({
|
|
162
|
-
card: {
|
|
163
|
-
// use all of your variables here.
|
|
164
|
-
// your IDE should provide code assistance to you
|
|
165
|
-
// to inform you of what variables are available
|
|
166
|
-
backgroundColor: vars.background.secondary,
|
|
100
|
+
export const { classes } = createStyles('Button', () => ({
|
|
101
|
+
root: {
|
|
102
|
+
backgroundColor: '#1f4aa8',
|
|
103
|
+
borderRadius: 6,
|
|
104
|
+
color: '#fff',
|
|
105
|
+
padding: '12px 16px',
|
|
106
|
+
'&:hover': { backgroundColor: '#2d6cdf' },
|
|
167
107
|
},
|
|
168
108
|
}));
|
|
169
109
|
```
|
|
170
110
|
|
|
171
|
-
|
|
111
|
+
```tsx
|
|
112
|
+
// src/components/Button.tsx
|
|
113
|
+
import { classes } from './button.styles';
|
|
172
114
|
|
|
173
|
-
|
|
115
|
+
export function Button() {
|
|
116
|
+
return <button className={classes.root}>Click me</button>;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
174
119
|
|
|
175
|
-
|
|
120
|
+
### 2) Compile with `ssjs`
|
|
176
121
|
|
|
177
|
-
|
|
178
|
-
|
|
122
|
+
Define **accurate `--entrypoints`** CLI flags for your code so the compiler can follow your import graph and discover all of your styles.
|
|
123
|
+
The resulting CSS is written in the same order as your source code / import tree.
|
|
179
124
|
|
|
180
|
-
|
|
181
|
-
|
|
125
|
+
```bash
|
|
126
|
+
bun ssjs --entrypoints src/app.tsx src/pages/**/*.tsx --outfile public/my-styles.css
|
|
127
|
+
```
|
|
128
|
+
```bash
|
|
129
|
+
npx ssjs --entrypoints src/app.tsx src/pages/**/*.tsx --outfile public/my-styles.css
|
|
130
|
+
```
|
|
131
|
+
```bash
|
|
132
|
+
pnpm ssjs --entrypoints src/app.tsx src/pages/**/*.tsx --outfile public/my-styles.css
|
|
133
|
+
```
|
|
134
|
+
```bash
|
|
135
|
+
yarn ssjs --entrypoints src/app.tsx src/pages/**/*.tsx --outfile public/my-styles.css
|
|
136
|
+
```
|
|
182
137
|
|
|
183
|
-
|
|
184
|
-
setSeed(11223344);
|
|
138
|
+
Optional watch mode:
|
|
185
139
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}));
|
|
140
|
+
```bash
|
|
141
|
+
npx ssjs --entrypoints src/app.tsx src/pages/**/*.tsx --outfile public/my-styles.css --watch
|
|
189
142
|
```
|
|
190
143
|
|
|
191
|
-
|
|
192
|
-
// src/app/layout.tsx
|
|
193
|
-
import type { Metadata } from "next";
|
|
194
|
-
import { SimpleStyleProvider } from "simplestyle-js/next";
|
|
195
|
-
import { createStyles } from "./styleRegistry";
|
|
196
|
-
|
|
197
|
-
// start writing CSS!
|
|
198
|
-
const { classes } = createStyles('RootLayoutStyles', () => ({
|
|
199
|
-
rootLayout: {
|
|
200
|
-
backgroundColor: 'pink',
|
|
201
|
-
padding: '1rem',
|
|
202
|
-
},
|
|
203
|
-
}));
|
|
144
|
+
### 3) Include the generated CSS
|
|
204
145
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return (
|
|
211
|
-
<html lang="en">
|
|
212
|
-
<body className={classes.rootLayout}>
|
|
213
|
-
<SimpleStyleProvider>
|
|
214
|
-
{children}
|
|
215
|
-
</SimpleStyleProvider>
|
|
216
|
-
</body>
|
|
217
|
-
</html>
|
|
218
|
-
);
|
|
219
|
-
}
|
|
146
|
+
The output file is plain CSS. Include it the same way you would any stylesheet:
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<!-- SSR/SSG: add to your HTML head -->
|
|
150
|
+
<link rel="stylesheet" href="/my-styles.css" />
|
|
220
151
|
```
|
|
221
152
|
|
|
222
|
-
|
|
153
|
+
Or import it via your framework’s entry:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
// e.g. Next.js or Astro entry files, or any UI application that uses a bundler
|
|
157
|
+
import '../public/my-styles.css';
|
|
158
|
+
```
|
|
223
159
|
|
|
224
|
-
|
|
160
|
+
## API Reference
|
|
225
161
|
|
|
162
|
+
**Important:** always call `makeCssFuncs()` from the correct entrypoint:
|
|
226
163
|
|
|
227
|
-
|
|
164
|
+
- Browser runtime: `import { makeCssFuncs } from 'simplestyle-js/browser'`
|
|
165
|
+
- SSR: `import { makeCssFuncs } from 'simplestyle-js/ssr'`
|
|
228
166
|
|
|
229
|
-
|
|
230
|
-
The overall developer experience is similar to Next.js, but requires a pinch more boilerplate.
|
|
167
|
+
### `makeCssFuncs({ variables? }?)`
|
|
231
168
|
|
|
232
|
-
|
|
233
|
-
// src/styleRegistry.ts
|
|
169
|
+
Creates the CSS helpers and optionally binds your design tokens for typed access.
|
|
234
170
|
|
|
235
|
-
|
|
171
|
+
```ts
|
|
172
|
+
import { makeCssFuncs } from 'simplestyle-js/browser'; // or import the SSR variant from 'simplestyle-js/ssr';
|
|
236
173
|
|
|
237
|
-
|
|
238
|
-
|
|
174
|
+
const { createStyles } = makeCssFuncs({
|
|
175
|
+
variables: {
|
|
176
|
+
colors: { brand: '#1f4aa8' },
|
|
177
|
+
},
|
|
178
|
+
});
|
|
239
179
|
|
|
240
|
-
|
|
180
|
+
const { classes } = createStyles('Card', (vars) => ({
|
|
181
|
+
root: { backgroundColor: vars.colors.brand },
|
|
182
|
+
}));
|
|
241
183
|
```
|
|
242
184
|
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
import { SimpleStyleRegistry } from "simplestyle-js";
|
|
246
|
-
import SimpleStyleProvider from "simplestyle-js/astro/SimpleStyleProvider";
|
|
247
|
-
|
|
248
|
-
import {
|
|
249
|
-
createStyles,
|
|
250
|
-
keyframes,
|
|
251
|
-
rawStyles,
|
|
252
|
-
} from "../styleRegistry";
|
|
185
|
+
### `createStyles(ruleId, rulesFn, options?)`
|
|
253
186
|
|
|
254
|
-
|
|
187
|
+
Builds class names + CSS.
|
|
188
|
+
Returns `{ classes, stylesheet, updateSheet }`.
|
|
189
|
+
Use the returned `classes` directly in your component code / HTML.
|
|
255
190
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
padding: 0,
|
|
264
|
-
},
|
|
265
|
-
}), {
|
|
266
|
-
// provide the registry used for this `.astro` file here
|
|
267
|
-
registry,
|
|
268
|
-
});
|
|
191
|
+
```ts
|
|
192
|
+
const { classes } = createStyles('Nav', () => ({
|
|
193
|
+
wrapper: { display: 'flex', gap: 12 },
|
|
194
|
+
link: { '&:hover': { textDecoration: 'underline' } },
|
|
195
|
+
'@media (max-width: 600px)': { wrapper: { flexDirection: 'column' } },
|
|
196
|
+
}));
|
|
197
|
+
```
|
|
269
198
|
|
|
270
|
-
|
|
271
|
-
const { keyframe } = keyframes("HomePage", () => ({
|
|
272
|
-
"0%": {
|
|
273
|
-
backgroundColor: "#cc2222cc",
|
|
274
|
-
},
|
|
275
|
-
"33%": {
|
|
276
|
-
backgroundColor: "#22cc22cc",
|
|
277
|
-
},
|
|
278
|
-
"66%": {
|
|
279
|
-
backgroundColor: "#2222cccc",
|
|
280
|
-
},
|
|
281
|
-
"100%": {
|
|
282
|
-
backgroundColor: "#cc2222cc",
|
|
283
|
-
},
|
|
284
|
-
}), {
|
|
285
|
-
// provide the registry used for this `.astro` file here
|
|
286
|
-
registry,
|
|
287
|
-
});
|
|
199
|
+
Back‑reference example (use `$otherRule` to reference another generated class):
|
|
288
200
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
margin: "0 auto",
|
|
298
|
-
width: "90vw",
|
|
299
|
-
},
|
|
300
|
-
content: {
|
|
301
|
-
backgroundColor: "#00000033",
|
|
302
|
-
borderRadius: "4px",
|
|
303
|
-
color: "white",
|
|
304
|
-
padding: "1rem",
|
|
201
|
+
```ts
|
|
202
|
+
const { classes } = createStyles('Card', () => ({
|
|
203
|
+
title: { fontWeight: 700, marginBottom: 8 },
|
|
204
|
+
root: {
|
|
205
|
+
padding: 16,
|
|
206
|
+
borderRadius: 8,
|
|
207
|
+
backgroundColor: '#f6f7fb',
|
|
208
|
+
'& $title': { color: '#1f4aa8' },
|
|
305
209
|
},
|
|
306
|
-
})
|
|
307
|
-
// provide the registry used for this `.astro` file here
|
|
308
|
-
registry,
|
|
309
|
-
});
|
|
310
|
-
---
|
|
311
|
-
<!-- wrap your astro content here with the provider and give it the registry you created in your front matter -->
|
|
312
|
-
<SimpleStyleProvider registry={registry}>
|
|
313
|
-
<div class={classes.background}>
|
|
314
|
-
<div class={classes.content}>
|
|
315
|
-
<h1>Astro</h1>
|
|
316
|
-
<p>
|
|
317
|
-
Checkout the CSS class and animation applied to the body, which is
|
|
318
|
-
making my colors changes.
|
|
319
|
-
</p>
|
|
320
|
-
<p>Feel free to edit me and I'll hot reload!</p>
|
|
321
|
-
</div>
|
|
322
|
-
</div>
|
|
323
|
-
</SimpleStyleProvider>
|
|
210
|
+
}));
|
|
324
211
|
```
|
|
325
212
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
**General SSR Concepts**
|
|
213
|
+
### `createKeyframes(ruleId, framesFn, options?)`
|
|
329
214
|
|
|
330
|
-
|
|
331
|
-
The core APIs needed to make this work are:
|
|
215
|
+
Generates a unique animation name and `@keyframes` CSS. Returns `{ keyframe, stylesheet }`.
|
|
332
216
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
217
|
+
```ts
|
|
218
|
+
const { keyframe } = createKeyframes('FadeIn', () => ({
|
|
219
|
+
'0%': { opacity: 0, transform: 'translateY(6px)' },
|
|
220
|
+
'100%': { opacity: 1, transform: 'translateY(0px)' },
|
|
221
|
+
}));
|
|
336
222
|
|
|
337
|
-
|
|
223
|
+
const { classes } = createStyles('Notice', () => ({
|
|
224
|
+
root: {
|
|
225
|
+
animation: `${keyframe} 320ms ease-out`,
|
|
226
|
+
},
|
|
227
|
+
}));
|
|
228
|
+
```
|
|
338
229
|
|
|
339
|
-
|
|
230
|
+
### `createRawStyles(ruleId, rulesFn, options?)`
|
|
340
231
|
|
|
341
|
-
|
|
342
|
-
For demonstration purposes, we'll locate this at our `src/` root, and name it `styleLib.js`
|
|
232
|
+
Writes rules without generating class names. Keys must be selectors (`html`, `body *`, `.app`).
|
|
343
233
|
|
|
344
|
-
```
|
|
345
|
-
|
|
234
|
+
```ts
|
|
235
|
+
createRawStyles('GlobalReset', () => ({
|
|
236
|
+
'*, *::before, *::after': { boxSizing: 'border-box' },
|
|
237
|
+
'html, body': {
|
|
238
|
+
margin: 0,
|
|
239
|
+
padding: 0,
|
|
240
|
+
fontFamily: 'system-ui, sans-serif',
|
|
241
|
+
lineHeight: 1.4,
|
|
242
|
+
backgroundColor: '#fff',
|
|
243
|
+
color: '#111',
|
|
244
|
+
},
|
|
245
|
+
img: { maxWidth: '100%', display: 'block' },
|
|
246
|
+
button: { font: 'inherit' },
|
|
247
|
+
}));
|
|
248
|
+
```
|
|
346
249
|
|
|
347
|
-
|
|
348
|
-
// between the client and the server.
|
|
349
|
-
// the number you use is arbitrary.
|
|
350
|
-
// set it higher to have most characters injected in your generated class names
|
|
351
|
-
setSeed(1);
|
|
250
|
+
### `createImports(ruleId, rulesFn, options?)`
|
|
352
251
|
|
|
353
|
-
|
|
354
|
-
export const StyleRegistry = new SimpleStyleRegistry();
|
|
252
|
+
Creates `@import` rules. The array items must already be valid `@import` strings.
|
|
355
253
|
|
|
356
|
-
|
|
357
|
-
|
|
254
|
+
```ts
|
|
255
|
+
createImports('Imports', () => [
|
|
256
|
+
'@import "https://unpkg.com/normalize.css/normalize.css"',
|
|
257
|
+
]);
|
|
358
258
|
```
|
|
359
259
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
**Note**: If you use Next.js, you would do this in your `layout.jsx` or `layout.tsx` file.
|
|
363
|
-
Additionally, if you're not using React or any other JSX-inspired framework, you can use
|
|
364
|
-
`StyleRegistry.getHTML()` to return an HTML string with all of the `<style />` tags you need,
|
|
365
|
-
or `StyleRegistry.getCSS()` to just return a single, concatenated CSS string.
|
|
366
|
-
|
|
367
|
-
```jsx
|
|
368
|
-
import { StyleRegistry } from '../styleLib.js';
|
|
369
|
-
|
|
370
|
-
export default function Layout({ children }) {
|
|
371
|
-
return (
|
|
372
|
-
<body lang="en">
|
|
373
|
-
{/* render your <style /> tags and set the IDs on them */}
|
|
374
|
-
{StyleRegistry.getRulesById().map(([id, css]) => (
|
|
375
|
-
<style id={id} key={id}>
|
|
376
|
-
{css}
|
|
377
|
-
</style>
|
|
378
|
-
))}
|
|
379
|
-
{children}
|
|
380
|
-
</body>
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
```
|
|
260
|
+
### `registerPosthook(fn: (sheet: string) => string)`
|
|
384
261
|
|
|
385
|
-
|
|
262
|
+
Registers a transform that runs after CSS strings are generated, but before they’re flushed or written.
|
|
386
263
|
|
|
387
|
-
|
|
388
|
-
import { createStyles } from '../styleLib.js';
|
|
264
|
+
### Types
|
|
389
265
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
backgroundColor: 'purple',
|
|
394
|
-
fontSize: '2rem',
|
|
395
|
-
padding: '2rem',
|
|
266
|
+
- `SimpleStyleRules`: `{ [selectorOrKey: string]: Properties | SimpleStyleRules }`
|
|
267
|
+
- `CreateStylesOptions`: options for flushing/placement in the browser runtime.
|
|
268
|
+
- `PosthookPlugin`: signature for `registerPosthook`.
|
|
396
269
|
|
|
397
|
-
|
|
398
|
-
fontStyle: 'italic',
|
|
399
|
-
fontWeight: 'bold',
|
|
400
|
-
textDecoration: 'underline',
|
|
401
|
-
},
|
|
402
|
-
},
|
|
403
|
-
}));
|
|
270
|
+
## Patterns and Tips
|
|
404
271
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
This is super <span>cool.</span>
|
|
410
|
-
</div>
|
|
411
|
-
);
|
|
412
|
-
}
|
|
413
|
-
```
|
|
272
|
+
- **Nested selectors**: `&` is replaced with the parent selector. Comma‑separated selectors are supported (e.g., `'&:hover, &:focus'`).
|
|
273
|
+
- **Back‑references**: Use `$otherRule` to reference another generated class in the same `createStyles` call (the referenced rule should appear earlier in the object).
|
|
274
|
+
- **Media queries**: Top‑level `@media` keys contain further rule objects.
|
|
275
|
+
- **Updating styles**: `updateSheet` merges new rules and updates the existing `<style>` tag (browser) or returns an updated sheet string (SSR extraction).
|
|
414
276
|
|
|
415
277
|
## Creating a simplestyle-js plugin
|
|
416
278
|
|
|
@@ -421,12 +283,13 @@ Do this if you want to integrate with `postcss`, `autoprefixer`, or any other CS
|
|
|
421
283
|
```ts
|
|
422
284
|
import autoprefixer from 'autoprefixer';
|
|
423
285
|
import postcss from 'postcss';
|
|
424
|
-
import { registerPosthook } from 'simplestyle-js';
|
|
286
|
+
import { registerPosthook } from 'simplestyle-js/browser';
|
|
425
287
|
|
|
426
288
|
registerPosthook(css => postcss([autoprefixer]).process(css, { from: undefined }).css);
|
|
427
289
|
```
|
|
428
290
|
|
|
429
|
-
Any future `createStyles`, `
|
|
291
|
+
Any future `createStyles`, `createRawStyles`, or `createKeyframes` calls will run through the posthook chain.
|
|
292
|
+
You can use the same API from `simplestyle-js/ssr` if you want the transform applied to extracted CSS as well.
|
|
430
293
|
|
|
431
294
|
## License
|
|
432
295
|
[MIT](https://en.wikipedia.org/wiki/MIT_License)
|