simplestyle-js 5.5.0 → 5.5.1-alpha.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 CHANGED
@@ -172,27 +172,27 @@ const { classes } = createStyles('my-component', vars => ({
172
172
 
173
173
  ### Next.js
174
174
 
175
- Create your style registry and scoped CSS functions, then use the official Next.js integration here and wrap the `SimpleStyleProvider` around your `layout` file.
175
+ Create your scoped CSS functions using the per-request Next.js registry, then wrap the `SimpleStyleProvider` around your `layout` file. This ensures styles are collected during server rendering and injected into the `<head />` during streaming.
176
176
 
177
177
  ```typescript
178
178
  // src/styleRegistry.ts
179
179
 
180
180
  import { makeCssFuncs, setSeed } from "simplestyle-js";
181
- import { SimpleStyleRegistry } from "simplestyle-js/simpleStyleRegistry";
181
+ import { getSimpleStyleRegistry } from "simplestyle-js/next";
182
182
 
183
183
  // ensures deterministic creation of CSS classnames
184
184
  setSeed(11223344);
185
185
 
186
- export const StyleRegistry = new SimpleStyleRegistry();
187
-
188
- export const { createStyles, imports, keyframes, rawStyles } = makeCssFuncs({ registry: StyleRegistry });
186
+ export const { createStyles, imports, keyframes, rawStyles } = makeCssFuncs(() => ({
187
+ registry: getSimpleStyleRegistry(),
188
+ }));
189
189
  ```
190
190
 
191
191
  ```tsx
192
192
  // src/app/layout.tsx
193
193
  import type { Metadata } from "next";
194
194
  import { SimpleStyleProvider } from "simplestyle-js/next";
195
- import { createStyles, StyleRegistry } from "./styleRegistry";
195
+ import { createStyles } from "./styleRegistry";
196
196
 
197
197
  // start writing CSS!
198
198
  const { classes } = createStyles('RootLayoutStyles', () => ({
@@ -210,7 +210,7 @@ export default function RootLayout({
210
210
  return (
211
211
  <html lang="en">
212
212
  <body className={classes.rootLayout}>
213
- <SimpleStyleProvider registry={StyleRegistry}>
213
+ <SimpleStyleProvider>
214
214
  {children}
215
215
  </SimpleStyleProvider>
216
216
  </body>
@@ -221,6 +221,8 @@ export default function RootLayout({
221
221
 
222
222
  Check out this [Code Sandbox w/Next.js integration to see how it works](https://codesandbox.io/p/devbox/t3smf4).
223
223
 
224
+ If you're building a component library that needs to work in Next.js with SSR, use the same `getSimpleStyleRegistry()` callback inside that library's `makeCssFuncs` call so it participates in the app's per-request registry. On the client, `getSimpleStyleRegistry()` returns `null`, so styles fall back to runtime injection.
225
+
224
226
 
225
227
  ### Astro
226
228
 
@@ -28,6 +28,7 @@ _export(exports, {
28
28
  const _deepmerge = /*#__PURE__*/ _interop_require_default(require("deepmerge"));
29
29
  const _generateClassName = require("./generateClassName.cjs");
30
30
  const _plugins = require("./plugins.cjs");
31
+ const _styleCache = require("./styleCache.cjs");
31
32
  function _interop_require_default(obj) {
32
33
  return obj && obj.__esModule ? obj : {
33
34
  default: obj
@@ -186,6 +187,7 @@ function imports(ruleId, rulesFnc, optionsOrCallback) {
186
187
  } else if (coerced.flush) {
187
188
  flushSheetContents(importRuleId, sheetBuffer, options);
188
189
  }
190
+ (0, _styleCache.setCachedRule)(importRuleId, sheetBuffer);
189
191
  return {
190
192
  registry: options?.registry
191
193
  };
@@ -202,6 +204,7 @@ function rawStyles(ruleId, rulesFnc, optionsOrCallback) {
202
204
  } else if (coerced.flush) {
203
205
  flushSheetContents(rawStylesId, mergedContents, options);
204
206
  }
207
+ (0, _styleCache.setCachedRule)(rawStylesId, mergedContents);
205
208
  return {
206
209
  registry: options?.registry,
207
210
  stylesheet: mergedContents
@@ -219,6 +222,7 @@ function keyframes(ruleId, framesFnc, optionsOrCallback) {
219
222
  } else if (coerced.flush) {
220
223
  flushSheetContents(keyframeId, stylesheet);
221
224
  }
225
+ (0, _styleCache.setCachedRule)(keyframeId, stylesheet);
222
226
  return {
223
227
  keyframe: keyframeId,
224
228
  registry: options?.registry,
@@ -232,6 +236,7 @@ function createStyles(ruleId, rulesFnc, optionsOrCallback) {
232
236
  const { classes: out, sheetBuffer: sheetContents, mediaQueriesBuffer: mediaQueriesContents } = execCreateStyles(ruleId, rules, coerced, null);
233
237
  const mergedContents = `${sheetContents}${mediaQueriesContents}`;
234
238
  const replacedSheetContents = replaceBackReferences(out, mergedContents);
239
+ (0, _styleCache.setCachedRule)(ruleId, replacedSheetContents);
235
240
  let sheet = null;
236
241
  const updateSheet = (updatedRulesFnc)=>{
237
242
  if (options?.flush || options?.registry || !options?.flush) {
@@ -245,6 +250,7 @@ function createStyles(ruleId, rulesFnc, optionsOrCallback) {
245
250
  else if (options?.registry) {
246
251
  options.registry.add(ruleId, updatedReplacedSheetContents);
247
252
  }
253
+ (0, _styleCache.setCachedRule)(ruleId, updatedReplacedSheetContents);
248
254
  return {
249
255
  classes: updatedOut,
250
256
  stylesheet: updatedSheetContents
@@ -1,3 +1,4 @@
1
+ // @ts-expect-error - this is a tsc error in this project because it's not a full next.js app
1
2
  "use strict";
2
3
  Object.defineProperty(exports, "__esModule", {
3
4
  value: true
@@ -9,14 +10,21 @@ Object.defineProperty(exports, "SimpleStyleProvider", {
9
10
  }
10
11
  });
11
12
  const _jsxruntime = require("react/jsx-runtime");
13
+ const _navigation = require("next/navigation");
14
+ const _registry = require("./registry.cjs");
12
15
  function SimpleStyleProvider({ children, registry }) {
13
- return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
14
- children: [
15
- registry.getRulesById().map(([ruleId, css])=>/*#__PURE__*/ (0, _jsxruntime.jsx)("style", {
16
+ const activeRegistry = registry ?? (0, _registry.getSimpleStyleRegistry)();
17
+ (0, _navigation.useServerInsertedHTML)(()=>{
18
+ const rules = (0, _registry.getPendingRules)(activeRegistry);
19
+ if (!rules.length) return null;
20
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
21
+ children: rules.map(([ruleId, css])=>/*#__PURE__*/ (0, _jsxruntime.jsx)("style", {
16
22
  id: ruleId,
17
23
  children: css
18
- }, ruleId)),
19
- children
20
- ]
24
+ }, ruleId))
25
+ });
26
+ });
27
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
28
+ children: children
21
29
  });
22
30
  }
@@ -7,5 +7,5 @@ import type { SimpleStyleRegistry } from '../simpleStyleRegistry.js';
7
7
  * that leverage React server components
8
8
  */
9
9
  export declare function SimpleStyleProvider({ children, registry, }: PropsWithChildren & {
10
- registry: SimpleStyleRegistry;
10
+ registry?: SimpleStyleRegistry | null;
11
11
  }): import("react/jsx-runtime").JSX.Element;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
+ _export_star(require("./registry.cjs"), exports);
5
6
  _export_star(require("./SimpleStyleProvider.cjs"), exports);
6
7
  function _export_star(from, to) {
7
8
  Object.keys(from).forEach(function(k) {
@@ -1 +1,2 @@
1
+ export * from './registry.js';
1
2
  export * from './SimpleStyleProvider.js';
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get getPendingRules () {
13
+ return getPendingRules;
14
+ },
15
+ get getSimpleStyleRegistry () {
16
+ return getSimpleStyleRegistry;
17
+ }
18
+ });
19
+ const _react = require("react");
20
+ const _simpleStyleRegistry = require("../simpleStyleRegistry.cjs");
21
+ const _styleCache = require("../styleCache.cjs");
22
+ const getServerRegistry = (0, _react.cache)(()=>{
23
+ const registry = new _simpleStyleRegistry.SimpleStyleRegistry();
24
+ for (const [ruleId, css] of (0, _styleCache.getCachedRules)()){
25
+ registry.add(ruleId, css);
26
+ }
27
+ return registry;
28
+ });
29
+ function getSimpleStyleRegistry() {
30
+ if (typeof window !== 'undefined') return null;
31
+ return getServerRegistry();
32
+ }
33
+ const getEmittedRuleIds = (0, _react.cache)(()=>new Set());
34
+ function getPendingRules(registry) {
35
+ const emitted = getEmittedRuleIds();
36
+ const rules = new Map((0, _styleCache.getCachedRules)());
37
+ if (registry) {
38
+ for (const [ruleId, css] of registry.getRulesById()){
39
+ rules.set(ruleId, css);
40
+ }
41
+ }
42
+ const pending = [];
43
+ for (const [ruleId, css] of rules){
44
+ if (emitted.has(ruleId)) continue;
45
+ emitted.add(ruleId);
46
+ pending.push([
47
+ ruleId,
48
+ css
49
+ ]);
50
+ }
51
+ return pending;
52
+ }
@@ -0,0 +1,3 @@
1
+ import { SimpleStyleRegistry } from '../simpleStyleRegistry.js';
2
+ export declare function getSimpleStyleRegistry(): SimpleStyleRegistry | null;
3
+ export declare function getPendingRules(registry?: SimpleStyleRegistry | null): [string, string][];
@@ -47,6 +47,11 @@ ${contents}`, '');
47
47
  ];
48
48
  }
49
49
  /**
50
+ * clears all accumulated rules from the registry
51
+ */ clear() {
52
+ this.sheets.clear();
53
+ }
54
+ /**
50
55
  * unique ID for this registry, based on the time when it was created
51
56
  */ get id() {
52
57
  return this._id;
@@ -26,6 +26,10 @@ export declare class SimpleStyleRegistry {
26
26
  * won't work during local development
27
27
  */
28
28
  getRulesById(): [string, string][];
29
+ /**
30
+ * clears all accumulated rules from the registry
31
+ */
32
+ clear(): void;
29
33
  /**
30
34
  * unique ID for this registry, based on the time when it was created
31
35
  */
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get getCachedRules () {
13
+ return getCachedRules;
14
+ },
15
+ get setCachedRule () {
16
+ return setCachedRule;
17
+ }
18
+ });
19
+ const styleCache = new Map();
20
+ function setCachedRule(ruleId, css) {
21
+ styleCache.set(ruleId, css);
22
+ }
23
+ function getCachedRules() {
24
+ return [
25
+ ...styleCache.entries()
26
+ ];
27
+ }
@@ -0,0 +1,2 @@
1
+ export declare function setCachedRule(ruleId: string, css: string): void;
2
+ export declare function getCachedRules(): [string, string][];
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-deprecated */ import merge from 'deepmerge';
2
2
  import { generateClassName } from './generateClassName.mjs';
3
3
  import { getPosthooks } from './plugins.mjs';
4
+ import { setCachedRule } from './styleCache.mjs';
4
5
  function extractOptions(optionsOrCallback) {
5
6
  return typeof optionsOrCallback === 'function' ? optionsOrCallback() : optionsOrCallback;
6
7
  }
@@ -154,6 +155,7 @@ export function imports(ruleId, rulesFnc, optionsOrCallback) {
154
155
  } else if (coerced.flush) {
155
156
  flushSheetContents(importRuleId, sheetBuffer, options);
156
157
  }
158
+ setCachedRule(importRuleId, sheetBuffer);
157
159
  return {
158
160
  registry: options?.registry
159
161
  };
@@ -170,6 +172,7 @@ export function rawStyles(ruleId, rulesFnc, optionsOrCallback) {
170
172
  } else if (coerced.flush) {
171
173
  flushSheetContents(rawStylesId, mergedContents, options);
172
174
  }
175
+ setCachedRule(rawStylesId, mergedContents);
173
176
  return {
174
177
  registry: options?.registry,
175
178
  stylesheet: mergedContents
@@ -187,6 +190,7 @@ export function keyframes(ruleId, framesFnc, optionsOrCallback) {
187
190
  } else if (coerced.flush) {
188
191
  flushSheetContents(keyframeId, stylesheet);
189
192
  }
193
+ setCachedRule(keyframeId, stylesheet);
190
194
  return {
191
195
  keyframe: keyframeId,
192
196
  registry: options?.registry,
@@ -200,6 +204,7 @@ export function createStyles(ruleId, rulesFnc, optionsOrCallback) {
200
204
  const { classes: out, sheetBuffer: sheetContents, mediaQueriesBuffer: mediaQueriesContents } = execCreateStyles(ruleId, rules, coerced, null);
201
205
  const mergedContents = `${sheetContents}${mediaQueriesContents}`;
202
206
  const replacedSheetContents = replaceBackReferences(out, mergedContents);
207
+ setCachedRule(ruleId, replacedSheetContents);
203
208
  let sheet = null;
204
209
  const updateSheet = (updatedRulesFnc)=>{
205
210
  if (options?.flush || options?.registry || !options?.flush) {
@@ -213,6 +218,7 @@ export function createStyles(ruleId, rulesFnc, optionsOrCallback) {
213
218
  else if (options?.registry) {
214
219
  options.registry.add(ruleId, updatedReplacedSheetContents);
215
220
  }
221
+ setCachedRule(ruleId, updatedReplacedSheetContents);
216
222
  return {
217
223
  classes: updatedOut,
218
224
  stylesheet: updatedSheetContents
@@ -7,5 +7,5 @@ import type { SimpleStyleRegistry } from '../simpleStyleRegistry.js';
7
7
  * that leverage React server components
8
8
  */
9
9
  export declare function SimpleStyleProvider({ children, registry, }: PropsWithChildren & {
10
- registry: SimpleStyleRegistry;
10
+ registry?: SimpleStyleRegistry | null;
11
11
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,17 +1,25 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // @ts-expect-error - this is a tsc error in this project because it's not a full next.js app
3
+ import { useServerInsertedHTML } from 'next/navigation';
4
+ import { getPendingRules, getSimpleStyleRegistry } from './registry.mjs';
2
5
  /**
3
6
  * Accumulates all CSS rules and writes
4
7
  * them to your layout.
5
8
  * Use this for Next.js or other Next.js-like frameworks
6
9
  * that leverage React server components
7
10
  */ export function SimpleStyleProvider({ children, registry }) {
8
- return /*#__PURE__*/ _jsxs(_Fragment, {
9
- children: [
10
- registry.getRulesById().map(([ruleId, css])=>/*#__PURE__*/ _jsx("style", {
11
+ const activeRegistry = registry ?? getSimpleStyleRegistry();
12
+ useServerInsertedHTML(()=>{
13
+ const rules = getPendingRules(activeRegistry);
14
+ if (!rules.length) return null;
15
+ return /*#__PURE__*/ _jsx(_Fragment, {
16
+ children: rules.map(([ruleId, css])=>/*#__PURE__*/ _jsx("style", {
11
17
  id: ruleId,
12
18
  children: css
13
- }, ruleId)),
14
- children
15
- ]
19
+ }, ruleId))
20
+ });
21
+ });
22
+ return /*#__PURE__*/ _jsx(_Fragment, {
23
+ children: children
16
24
  });
17
25
  }
@@ -1 +1,2 @@
1
+ export * from './registry.js';
1
2
  export * from './SimpleStyleProvider.js';
@@ -1 +1,2 @@
1
+ export * from './registry.mjs';
1
2
  export * from './SimpleStyleProvider.mjs';
@@ -0,0 +1,3 @@
1
+ import { SimpleStyleRegistry } from '../simpleStyleRegistry.js';
2
+ export declare function getSimpleStyleRegistry(): SimpleStyleRegistry | null;
3
+ export declare function getPendingRules(registry?: SimpleStyleRegistry | null): [string, string][];
@@ -0,0 +1,34 @@
1
+ import { cache } from 'react';
2
+ import { SimpleStyleRegistry } from '../simpleStyleRegistry.mjs';
3
+ import { getCachedRules } from '../styleCache.mjs';
4
+ const getServerRegistry = cache(()=>{
5
+ const registry = new SimpleStyleRegistry();
6
+ for (const [ruleId, css] of getCachedRules()){
7
+ registry.add(ruleId, css);
8
+ }
9
+ return registry;
10
+ });
11
+ export function getSimpleStyleRegistry() {
12
+ if (typeof window !== 'undefined') return null;
13
+ return getServerRegistry();
14
+ }
15
+ const getEmittedRuleIds = cache(()=>new Set());
16
+ export function getPendingRules(registry) {
17
+ const emitted = getEmittedRuleIds();
18
+ const rules = new Map(getCachedRules());
19
+ if (registry) {
20
+ for (const [ruleId, css] of registry.getRulesById()){
21
+ rules.set(ruleId, css);
22
+ }
23
+ }
24
+ const pending = [];
25
+ for (const [ruleId, css] of rules){
26
+ if (emitted.has(ruleId)) continue;
27
+ emitted.add(ruleId);
28
+ pending.push([
29
+ ruleId,
30
+ css
31
+ ]);
32
+ }
33
+ return pending;
34
+ }
@@ -26,6 +26,10 @@ export declare class SimpleStyleRegistry {
26
26
  * won't work during local development
27
27
  */
28
28
  getRulesById(): [string, string][];
29
+ /**
30
+ * clears all accumulated rules from the registry
31
+ */
32
+ clear(): void;
29
33
  /**
30
34
  * unique ID for this registry, based on the time when it was created
31
35
  */
@@ -42,6 +42,11 @@ ${contents}`, '');
42
42
  ];
43
43
  }
44
44
  /**
45
+ * clears all accumulated rules from the registry
46
+ */ clear() {
47
+ this.sheets.clear();
48
+ }
49
+ /**
45
50
  * unique ID for this registry, based on the time when it was created
46
51
  */ get id() {
47
52
  return this._id;
@@ -0,0 +1,2 @@
1
+ export declare function setCachedRule(ruleId: string, css: string): void;
2
+ export declare function getCachedRules(): [string, string][];
@@ -0,0 +1,9 @@
1
+ const styleCache = new Map();
2
+ export function setCachedRule(ruleId, css) {
3
+ styleCache.set(ruleId, css);
4
+ }
5
+ export function getCachedRules() {
6
+ return [
7
+ ...styleCache.entries()
8
+ ];
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simplestyle-js",
3
- "version": "5.5.0",
3
+ "version": "5.5.1-alpha.0",
4
4
  "description": "An incredibly straightforward and simple CSS-in-JS solution with zero runtime dependencies, and out-of-the-box TypeScript support",
5
5
  "type": "module",
6
6
  "repository": {
@@ -130,6 +130,16 @@
130
130
  "default": "./dist/esm/next/index.mjs"
131
131
  }
132
132
  },
133
+ "./next/registry": {
134
+ "require": {
135
+ "types": "./dist/cjs/next/registry.d.ts",
136
+ "default": "./dist/cjs/next/registry.cjs"
137
+ },
138
+ "import": {
139
+ "types": "./dist/esm/next/registry.d.ts",
140
+ "default": "./dist/esm/next/registry.mjs"
141
+ }
142
+ },
133
143
  "./numToAlpha": {
134
144
  "require": {
135
145
  "types": "./dist/cjs/numToAlpha.d.ts",
@@ -160,6 +170,16 @@
160
170
  "default": "./dist/esm/simpleStyleRegistry.mjs"
161
171
  }
162
172
  },
173
+ "./styleCache": {
174
+ "require": {
175
+ "types": "./dist/cjs/styleCache.d.ts",
176
+ "default": "./dist/cjs/styleCache.cjs"
177
+ },
178
+ "import": {
179
+ "types": "./dist/esm/styleCache.d.ts",
180
+ "default": "./dist/esm/styleCache.mjs"
181
+ }
182
+ },
163
183
  "./types": {
164
184
  "require": {
165
185
  "types": "./dist/cjs/types.d.ts",