simplestyle-js 3.4.2-alpha.3 → 4.0.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
@@ -1,278 +1,233 @@
1
- # simplestyle-js [![Build Status](https://travis-ci.org/benduran/simplestyle.svg?branch=master)](https://travis-ci.org/benduran/simplestyle) [![Coverage Status](https://coveralls.io/repos/github/benduran/simplestyle/badge.svg?branch=master)](https://coveralls.io/github/benduran/simplestyle?branch=master)
2
- A super simple CSS-in-JS solution with friendly TypeScript support and a small file size
3
-
4
- ## Bundle Size
5
- - `~5.5kB` minified
6
- - `~2.2kB` gzipped
7
- - Courtesy of [Bundle Phobia](https://bundlephobia.com/result?p=simplestyle-js)
8
-
9
- ## Installation
10
- `npm install simplestyle-js --save`
1
+ # Simplestyle-js Reference
2
+
3
+ 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).
4
+
5
+ ## Table of Contents
6
+ - [Install](#install)
7
+ - [Quick Start](#quick-start)
8
+ - [API Reference (from `src/index.ts`)](#api-reference-from-srcindexts)
9
+ - [Patterns and Tips](#patterns-and-tips)
10
+ - [SSR](#ssr)
11
+ - [SSR steps for most SSR / SSG frameworks (including Next.js)](#ssr-steps-for-most-ssr--ssg-frameworks)
12
+ - [1. Set your seed, create a SimpleStyleRegistry and your style functions](#1-set-your-seed-create-a-simplestyleregistry-and-your-style-functions)
13
+ - [2. Render the generated styles in your HTML](#2-render-the-generated-styles-in-your-html)
14
+ - [3. Create your styles and have fun!](#3-create-your-styles-and-have-fun)
15
+ - [Creating a simplestyle-js plugin](#creating-a-simplestyle-js-plugin)
16
+ - [Plugin Example (Autoprefixer)](#plugin-example-autoprefixer)
17
+ - [License](#license)
18
+
19
+ ## Install
20
+
21
+ **bun**
22
+ ```
23
+ bun add simplestyle-js
24
+ ```
11
25
 
12
- ## Live Demo using VanillaJS
13
- [Codesandbox VanillaJS Demo](https://codesandbox.io/s/gracious-browser-9hxg3r?file=/src/index.js)
26
+ **npm**
27
+ ```
28
+ npm install simplestyle-js --save
29
+ ```
14
30
 
15
- ## Live Demo using the provided React Hooks
16
- [Codesandbox React Hooks Demo](https://codesandbox.io/s/nice-franklin-485wi?file=/src/App.tsx)
31
+ **pnpm**
17
32
 
18
- ## Basic Usage
19
- ```javascript
20
- import { createStyles } from 'simplestyle-js';
21
- const { classes } = createStyles({
22
- myButton: {
23
- '&:hover': {
24
- backgroundColor: 'red',
25
- },
26
- '&:active, &:focus': {
27
- borderColor: 'blue',
28
- },
29
- backgroundColor: 'black',
30
- border: '1px solid',
31
- boxSizing: 'border-box',
32
- color: 'white',
33
- },
34
- });
35
- const btn = document.createElement('button');
36
- btn.classList.add(classes.myButton);
37
- document.body.appendChild(btn);
33
+ ```
34
+ pnpm add simplestyle-js
35
+ ```
38
36
 
39
- // Or React / JSX style component
37
+ **yarn**
40
38
 
41
- const Button = (props) => <button {...props} className={classes.myButton}>Awesome button</button>
39
+ ```
40
+ yarn add simplestyle-js
42
41
  ```
43
42
 
44
- ## Advanced Usage
43
+ ## Quick Start
45
44
 
46
- `simplestyle-js` provides four APIs out of the box: `createStyles`, `keyframes` and `rawStyles` and `setSeed`.
45
+ ```tsx
46
+ import createStyles from 'simplestyle-js';
47
47
 
48
- ```javascript
49
- import { createStyles, rawStyles } from 'simplestyle-js';
50
-
51
- // Allows setting global, top-level styles.
52
- // This is useful for setting your application's overall font family, font size, box-sizing, etc
53
- rawStyles({
54
- html: {
55
- fontFamily: 'Arial, Helvetica, sans-serif',
56
- fontSize: '16px',
57
- },
58
- 'body *': {
59
- boxSizing: 'border-box',
60
- },
61
- a: {
62
- '&:hover': {
63
- color: 'red',
64
- textDecoration: 'none',
65
- },
48
+ const { classes } = createStyles('Button', {
49
+ root: {
50
+ '&:hover': { backgroundColor: '#2d6cdf' },
51
+ '@media (max-width: 768px)': { padding: '10px 12px' },
52
+ backgroundColor: '#1f4aa8',
53
+ borderRadius: 6,
54
+ color: '#fff',
55
+ padding: '12px 16px',
66
56
  },
67
57
  });
68
58
 
69
- // Generates a unique animation name and valid keyframes.
70
- // You can then use this animation name in your CSS-in-JS styles
71
- // in place of where you'd normally place an animation name
72
- const [animationName] = keyframes({
73
- '0%': {
74
- borderColor: 'red',
75
- },
76
- '50%': {
77
- borderColor: 'blue',
78
- },
79
- '100%': {
80
- borderColor: 'red',
81
- },
82
- });
59
+ document.querySelector('button')?.classList.add(classes.root);
83
60
 
84
- const { classes } = createStyles({
85
- myButton: {
86
- '&:hover': {
87
- backgroundColor: 'red',
88
- },
89
- '&:active, &:focus': {
90
- borderColor: 'blue',
91
- },
92
- // use the generated animation name from the `keyframes` call above
93
- animation: `${animationName} 1s linear infinite`,
94
- backgroundColor: 'transparent',
95
- border: '1px solid',
96
- color: 'white',
97
- },
98
- header: {
99
- // Media queries work great with simplestyle-js!
100
- '@media (max-width: 960px)': {
101
- '& > $myButton': {
102
- padding: '12px', // special padding for header button on mobile
61
+ // or, in a React / JSX-like component
62
+ const Button = (props) => <button {...props} className={classes.root}>Awesome button</button>
63
+ ```
64
+
65
+ Rules support nested selectors via `&`, media queries, and `$className` back-references to other generated classes.
66
+
67
+ ## API Reference (from `src/index.ts`)
68
+
69
+ - `createStyles(ruleId, rules, options?)`
70
+ - Builds a set of class names and CSS from a rules object. Returns `{ classes, stylesheet, updateSheet }`.
71
+ - `options.flush` (default `true`): injects a `<style>` tag into `document.head`.
72
+ - `options.insertBefore` / `insertAfter`: choose where the `<style>` tag is placed when flushing.
73
+ - `options.registry`: provide a `SimpleStyleRegistry` instance to **collect** CSS instead of touching the DOM (ideal for SSR).
74
+ - `updateSheet(updatedRules)` merges rules and updates the existing sheet (works when `flush` is `true` or a `registry` is provided). Returns `{ classes, stylesheet } | null`.
75
+ - Example:
76
+ ```ts
77
+ const { classes, stylesheet } = createStyles('Nav', {
78
+ wrapper: { display: 'flex', gap: 12 },
79
+ link: {
80
+ '&:hover': { textDecoration: 'underline' },
103
81
  },
104
- height: '50px', // target smaller height on mobile devices
105
- },
106
- '& > $myButton': {
107
- padding: '4px 8px',
108
- },
109
- height: '100px',
110
- left: 0,
111
- position: 'fixed',
112
- right: 0,
113
- top: 0,
114
- },
115
- }); // A new <style /> tag will appear in the header immediately after calling this function
82
+ '@media (max-width: 600px)': {
83
+ wrapper: { flexDirection: 'column' },
84
+ },
85
+ }, { flush: false }); // do not write to the DOM automatically
86
+ ```
116
87
 
117
- const myHeader = document.createElement('header');
118
- myHeader.classList.add(classes.header); // Will have a generated CSS classname in the format of '.header<unique_identifier>' ex .header_umdoaudnaoqwu
88
+ - `keyframes(ruleId, frames, options?)`
89
+ - Generates a unique animation name and accompanying `@keyframes` CSS.
90
+ - Returns `[animationName, stylesheet]`. Respects `flush` and `insertBefore/After` options.
119
91
 
120
- // if you want Simplestyle to always generate the same CSS class names, you can set
121
- // your own initial seed. Assuming your modules are imported in the same order and
122
- // execute their calls to createStyles() in the same order, the library will reliably generate
123
- // the same classNames across successive calls.
124
- // This is useful if you're going to be generating your stylesheets on the server
125
- // and then rehydrating
92
+ - `rawStyles(ruleId, rules, options?)`
93
+ - Writes rules without generating new class names. Keys must already be selectors (e.g., `html`, `body *`, `.app`).
94
+ - Good for global resets or theme primitives. Respects `flush` and `registry`.
126
95
 
127
- import { createStyles, setSeed } from 'simplestyle-js';
96
+ - `makeCreateStyles(registry)`
97
+ - 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).
128
98
 
129
- setSeed(4567);
99
+ - `makeRawStyles(registry)` *(from `simplestyle-js/createStyles`)*
100
+ - 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).
130
101
 
131
- const { classes } = createStyles({
132
- someRule: {
133
- backgroundColor: 'red,
134
- },
135
- });
102
+ - `makeKeyframes(registry)` *(from `simplestyle-js/createStyles`)*
103
+ - 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).
136
104
 
137
- // you can also update an existing stylesheet by adding or removing styles. Only applies when "flush" is set to true (it is true by default)
138
- const { classes, styles, updateSheet } = createStyles({
139
- myRule: {
140
- height: '400px,
141
- },
142
- });
143
- const { classes: updatedClasses } = updateSheet({
144
- anotherRule: {
145
- textTransform: 'uppercase',
146
- },
147
- myRule: {
148
- height: '200px',
149
- },
150
- }); // will update replace the existing sheet's contents and you can use the updatedClassnames here
105
+ - `setSeed(seed: number | null)`
106
+ - 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()`.
151
107
 
152
- ```
108
+ - `registerPosthook(fn: (sheet: string) => string)`
109
+ - 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.
153
110
 
154
- ```javascript
155
- import { createStyles } from 'simplestyle-js';
111
+ - Types
112
+ - `SimpleStyleRules`: `{ [selectorOrKey: string]: Properties | SimpleStyleRules }` (recursive rule tree).
113
+ - `CreateStylesOptions`: shape of the options described above.
114
+ - `PosthookPlugin`: signature for `registerPosthook`.
156
115
 
157
- const { classes, stylesheet } = createStyles({
158
- nav: {
159
- backgroundColor: '#ccaa00',
160
- width: '24em',
161
- },
162
- }, { flush: false }); // prevents immediate flushing of the <style /> tag to the DOM
163
- const { classes: moreClasses, stylesheet: moreSheetContents } = createStyles({
164
- navButtons: {
165
- padding: '.5em',
166
- },
167
- }, { flush: false }); // prevents immediate flushing of the <style /> tag to the DOM
116
+ ## Patterns and Tips
168
117
 
169
- const styleTag = document.createElement('style');
170
- styleTag.innerHTML = `${stylesheet}${moreSheetContents}`;
171
- ```
118
+ - **Nested selectors**: `&` is replaced with the parent selector. Comma-separated selectors are supported (e.g., `'&:hover, &:focus'`).
119
+ - **Back-references**: Use `$otherRule` to reference another generated class in the same `createStyles` call.
120
+ - **NOTE:** The `$otherRule` needs to have been declared above where you're trying to use it in a descendant selector.
121
+ - **Media queries**: Top-level `@media` keys contain further rule objects.
122
+ - **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
123
+ - **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.
172
124
 
173
- ```javascript
174
- /**
175
- * By default, simple style will insert the <style /> tags
176
- * it creates in the document <head />. You can change this
177
- * by providing either an "insertBefore" or "insertAfter"
178
- * DOM node.
179
- */
180
-
181
- const someElement = document.getElementById('some-element');
182
-
183
- const { classes, stylesheet } = createStyles({
184
- nav: {
185
- backgroundColor: '#ccaa00',
186
- width: '24em',
187
- },
188
- }, { insertBefore: someElement }); // <style /> will be inserted into the DOM *before* someElement
125
+ ## SSR
189
126
 
190
- const anotherElement = document.getElementById('another-element`);
191
- const { classes: moreClasses, stylesheet: moreSheetContents } = createStyles({
192
- navButtons: {
193
- padding: '.5em',
194
- },
195
- }, { insertAfter: anotherElement }); // <style /> will be insert into the DOM *after* anotherElement
127
+ `simplestyle-js` is intentionally unopinionated, especially when it comes to deep integrations with various frameworks. This also applies to SSR / Server-side rendering.
128
+ The core APIs needed to make this work are:
196
129
 
197
- const styleTag = document.createElement('style');
198
- styleTag.innerHTML = `${stylesheet}${moreSheetContents}`;
130
+ - `new SimpleStyleRegistry()` - creates a new StyleSheet registry where all of your styles will be accumulated
131
+ - `setSeed(number)` - ensures that classNames are deterministically computed and will be the same on the server and when they're rehydrated on the client
132
+ - `makeCreateStyle(registry)` - returns a `createStyles()` function that is locked to your StyleSheet registry
133
+ - `makeKeyframes(registry)` - returns a `keyframes()` function that is locaked to your StyleSheet registry
199
134
 
200
- ```
135
+ ### SSR steps for most SSR / SSG frameworks (including Next.js)
136
+
137
+ #### 1. Set your seed, create a SimpleStyleRegistry and your style functions
201
138
 
202
- ## React Hook
203
- `simplestyle-js` also ships with a React hook that you can import, if you'd prefer working with hooks
139
+ **Note**: This file can be located anywhere in your repository.
140
+ For demonstration purposes, we'll locate this at our `src/` root, and name it `styleLib.js`
204
141
 
205
142
  ```javascript
206
- import React from 'react';
207
- import { useCreateStyles } from 'simplestyle-js/react';
208
-
209
-
210
- const MyComponent = () => {
211
- // You can dynamically update the rules object passed into useCreateStyles.
212
- // This is great for programmatically changing styles, colors, etc, based
213
- // on some user input
214
- const classes = useCreateStyles({
215
- app: {
216
- backgroundColor: 'purple',
217
- fontSize: '16px',
218
- },
219
- button: {
220
- padding: '1em',
221
- },
222
- });
143
+ import { makeCreateStyles, makeKeyframes, makeRawStyles, setSeed } from "simplestyle-js";
144
+ import { SimpleStyleRegistry } from "simplestyle-js/simpleStyleRegistry";
145
+
146
+ // set the className generation seed to ensure classNames are computed consistently
147
+ // between the client and the server.
148
+ // the number you use is arbitrary.
149
+ // set it higher to have most characters injected in your generated class names
150
+ setSeed(1);
151
+
152
+ // create the registry to hold all of the styles on the server
153
+ export const StyleRegistry = new SimpleStyleRegistry();
154
+
155
+ // export the style functions that will be locked to your registry
156
+ export const createStyles = makeCreateStyles(StyleRegistry);
157
+ export const keyframes = makeKeyframes(StyleRegistry);
158
+ export const rawStyles = makeRawStyles(StyleRegistry);
159
+ ```
160
+
161
+ #### 2. Render the generated styles in your HTML
223
162
 
163
+ **Note**: If you use Next.js, you would do this in your `layout.jsx` or `layout.tsx` file.
164
+ Additionally, if you're not using React or any other JSX-inspired framework, you can use
165
+ `StyleRegistry.getHTML()` to return an HTML string with all of the `<style />` tags you need,
166
+ or `StyleRegistry.getCSS()` to just return a single, concatenated CSS string.
167
+
168
+ ```jsx
169
+ import { StyleRegistry } from '../styleLib.js';
170
+
171
+ export default function Layout({ children }) {
224
172
  return (
225
- <div className={classes.app}>
226
- <button className={classes.button}>Click Me</button>
227
- </div>
173
+ <body lang="en">
174
+ {/* render your <style /> tags and set the IDs on them */}
175
+ {StyleRegistry.getRulesById().map(([id, css]) => (
176
+ <style id={id} key={id}>
177
+ {css}
178
+ </style>
179
+ ))}
180
+ {children}
181
+ </body>
228
182
  );
229
- };
183
+ }
230
184
  ```
231
185
 
232
- ## Authoring Plugins
233
- A recent update has removed the need for a "prehook" plugin (see previous [documentation](https://github.com/benduran/simplestyle/blob/276aac7fd8b64c6cbfced152249aac7024351092/README.md#prehook-plugin-example-poor-mans-autoprefixer) for historical purposes).
234
- There is a single type of plugin:
235
- - `posthook`
236
- - Called on all style rule objects *after* the CSS string has been generated, but before it has been written to the DOM in a `<style />` tag
237
- - When creating a plugin, for improved SEO, it is **highly recommended** that you prefix the plugin package name with `simplestyle-js-plugin-*`.
238
- - See the official `postcss` Simplestyle plugin as an example: [simplestyle-js-plugin-postcss](https://www.npmjs.com/package/simplestyle-js-plugin-postcss)
186
+ #### 3. Create your styles and have fun!
239
187
 
240
- ### Posthook Plugin Example *Full Autoprefixer and PostCSS integration*
241
- ```javascript
242
- import autoprefixer from 'autoprefixer';
243
- import postcss from 'postcss';
244
- import { createStyles, registerPostHook } from 'simplestyle-js';
188
+ ```jsx
189
+ import { createStyles } from '../styleLib.js';
245
190
 
246
- const posthookVendorPrefix = sheetContents => postcss([autoprefixer()]).process(s.getStyles()).css;
247
- registerPostHook(posthookVendorPrefix);
248
- const styles = createStyles({
249
- postHookRoot: {
250
- userSelect: 'none',
191
+ // create your styles
192
+ const { classes } = createStyles({
193
+ awesome: {
194
+ backgroundColor: 'purple',
195
+ fontSize: '2rem',
196
+ padding: '2rem',
197
+
198
+ '& > span': {
199
+ fontStyle: 'italic',
200
+ fontWeight: 'bold',
201
+ textDecoration: 'underline',
202
+ },
251
203
  },
252
204
  });
253
- const div = document.createElement('div');
254
- div.classList.add(styles.posthookRoot); // This div will have all vendor prefixed CSS properties based on how PostCSS and Autoprefixer transform the CSS
255
- document.body.appendChild(div);
256
-
257
- // Or in a React / JSX-style component
258
205
 
259
- const MyComponent = () => <div className={styles.postHookRoot}>Some stuff here</div>
206
+ export function MyCoolComponent() {
207
+ // use your styles here!
208
+ return (
209
+ <div className={classes.awesome}>
210
+ This is super <span>cool.</span>
211
+ </div>
212
+ );
213
+ }
260
214
  ```
261
- ### Plugin API
262
- SimpleStyle does one thing out of the box well, and that's providing an intuitive way for you to write your CSS-in-JS in ways that are very similar to popular CSS Preprocessors like LESS, SASS, Stylus, among others. If you need to provide additional functionality that's not offered in the core library, `simplestyle-js` provides easy ways to tie into lifecycle hooks in the style rendering process if you need to stub out additional behavior. This allows you to create and chain an infinite number of plugins, based on your needs.
263
215
 
264
- In order to use a plugin, you need to **register** each plugin you'd like to use *before* you issue any calls to `createStyles`. Plugins will be executed in the order in which they were registered. The methods available for you to register plugins are as follows:
216
+ ## Creating a simplestyle-js plugin
217
+
218
+ Do this if you want to integrate with `postcss`, `autoprefixer`, or any other CSS transformation utility you desire.
265
219
 
266
- - `registerPostHook(postHookFnc)`
267
- - `postHookFnc` is a function that accepts one parameter, which is the string contents of the sheet that should eventually be written to the DOM. This function should return a string, after you've done any desired transformations to the sheetContents.
220
+ ### Plugin Example (Autoprefixer)
268
221
 
269
- ## What this library isn't
270
- This library isn't trying to make grandiose assumptions about how your styles should be rendered. Its goal is to simply provide a typed way of
271
- easily creating reusable styles close to your JavaScript / TypeScript components. It is a super compact, small file size way of creating CSS in JS and assumes that you're wise enough to know
272
- whether you've made a styling mistake (wrong property, wrong unit, invalid rule format, etc).
222
+ ```ts
223
+ import autoprefixer from 'autoprefixer';
224
+ import postcss from 'postcss';
225
+ import { registerPosthook } from 'simplestyle-js';
226
+
227
+ registerPosthook(css => postcss([autoprefixer]).process(css, { from: undefined }).css);
228
+ ```
273
229
 
274
- There are, currently, **no plans** for creating an SSR-variant of this library, as it would be in-confict of the goal of SimpleStyle, which is to be an easy and lightweight way to use CSS-in-JS.
275
- If you need SSR rendering in a CSS-in-JS engine, consider using [Emotion](https://emotion.sh/docs/introduction), instead.
230
+ Any future `createStyles`, `rawStyles`, or `keyframes` calls will run through the posthook chain.
276
231
 
277
232
  ## License
278
233
  [MIT](https://en.wikipedia.org/wiki/MIT_License)
@@ -15,8 +15,14 @@ _export(exports, {
15
15
  get keyframes () {
16
16
  return keyframes;
17
17
  },
18
- get makeCreateStyle () {
19
- return makeCreateStyle;
18
+ get makeCreateStyles () {
19
+ return makeCreateStyles;
20
+ },
21
+ get makeKeyframes () {
22
+ return makeKeyframes;
23
+ },
24
+ get makeRawStyles () {
25
+ return makeRawStyles;
20
26
  },
21
27
  get rawStyles () {
22
28
  return rawStyles;
@@ -151,6 +157,13 @@ function rawStyles(ruleId, rules, options) {
151
157
  if (coerced.flush) flushSheetContents(ruleId, mergedContents, options);
152
158
  return mergedContents;
153
159
  }
160
+ function makeRawStyles(registry) {
161
+ return function wrappedRawStyles(ruleId, rules) {
162
+ return rawStyles(ruleId, rules, {
163
+ registry
164
+ });
165
+ };
166
+ }
154
167
  function keyframes(ruleId, frames, options) {
155
168
  const coerced = coerceCreateStylesOptions(options);
156
169
  const keyframeName = (0, _generateClassName.generateClassName)(`${ruleId}_keyframes_`);
@@ -162,7 +175,14 @@ function keyframes(ruleId, frames, options) {
162
175
  sheetContents
163
176
  ];
164
177
  }
165
- function makeCreateStyle(registry) {
178
+ function makeKeyframes(registry) {
179
+ return function wrappedCreateKeyframes(ruleId, rules) {
180
+ return keyframes(ruleId, rules, {
181
+ registry
182
+ });
183
+ };
184
+ }
185
+ function makeCreateStyles(registry) {
166
186
  return function wrappedCreateStyles(ruleId, rules) {
167
187
  return createStyles(ruleId, rules, {
168
188
  registry
@@ -175,9 +195,8 @@ function createStyles(ruleId, rules, options) {
175
195
  const mergedContents = `${sheetContents}${mediaQueriesContents}`;
176
196
  const replacedSheetContents = replaceBackReferences(out, mergedContents);
177
197
  let sheet = null;
178
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
179
198
  const updateSheet = (updatedRules)=>{
180
- if ((options?.flush || options?.registry) && sheet || !options?.flush) {
199
+ if (options?.flush || options?.registry || !options?.flush) {
181
200
  // We prefer the first set, and then we shallow merge
182
201
  const { classes: updatedOut, sheetBuffer: updatedSheetContents, mediaQueriesBuffer: updatedMediaQueriesContents } = execCreateStyles(ruleId, (0, _deepmerge.default)(rules, updatedRules), {
183
202
  flush: false
@@ -185,6 +204,9 @@ function createStyles(ruleId, rules, options) {
185
204
  const updatedMergedContents = `${updatedSheetContents}${updatedMediaQueriesContents}`;
186
205
  const updatedReplacedSheetContents = replaceBackReferences(out, updatedMergedContents);
187
206
  if (sheet) sheet.innerHTML = updatedReplacedSheetContents;
207
+ else if (options?.registry) {
208
+ options.registry.add(ruleId, updatedReplacedSheetContents);
209
+ }
188
210
  return {
189
211
  classes: updatedOut,
190
212
  stylesheet: updatedSheetContents
@@ -26,12 +26,14 @@ export type CreateStylesOptions = Partial<{
26
26
  */
27
27
  registry?: SimpleStyleRegistry;
28
28
  }>;
29
- export declare function rawStyles<T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T, options?: Partial<CreateStylesOptions>): string;
29
+ export declare function rawStyles<T extends SimpleStyleRules>(ruleId: string, rules: T, options?: Partial<CreateStylesOptions>): string;
30
+ export declare function makeRawStyles(registry: SimpleStyleRegistry): <T extends SimpleStyleRules>(ruleId: string, rules: T) => string;
30
31
  export declare function keyframes<T extends Record<string, Properties>>(ruleId: string, frames: T, options?: CreateStylesOptions): [string, string];
31
- export declare function makeCreateStyle(registry: SimpleStyleRegistry): <T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T) => {
32
+ export declare function makeKeyframes(registry: SimpleStyleRegistry): <T extends Record<string, Properties>>(ruleId: string, rules: T) => [string, string];
33
+ export declare function makeCreateStyles(registry: SimpleStyleRegistry): <T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T) => {
32
34
  classes: O;
33
35
  stylesheet: string;
34
- updateSheet: <T2 extends SimpleStyleRules, K2 extends keyof T2, O2 extends Record<K2, string>>(updatedRules: Partial<T2>) => {
36
+ updateSheet: <T2 extends SimpleStyleRules>(updatedRules: Partial<T2>) => {
35
37
  classes: Record<string | number | keyof T2, string>;
36
38
  stylesheet: string;
37
39
  } | null;
@@ -39,7 +41,7 @@ export declare function makeCreateStyle(registry: SimpleStyleRegistry): <T exten
39
41
  export default function createStyles<T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T, options?: Partial<CreateStylesOptions>): {
40
42
  classes: O;
41
43
  stylesheet: string;
42
- updateSheet: <T2 extends SimpleStyleRules, K2 extends keyof T2, O2 extends Record<K2, string>>(updatedRules: Partial<T2>) => {
44
+ updateSheet: <T2 extends SimpleStyleRules>(updatedRules: Partial<T2>) => {
43
45
  classes: Record<string | number | keyof T2, string>;
44
46
  stylesheet: string;
45
47
  } | null;
@@ -15,8 +15,14 @@ _export(exports, {
15
15
  get keyframes () {
16
16
  return _createStyles.keyframes;
17
17
  },
18
- get makeCreateStyle () {
19
- return _createStyles.makeCreateStyle;
18
+ get makeCreateStyles () {
19
+ return _createStyles.makeCreateStyles;
20
+ },
21
+ get makeKeyframes () {
22
+ return _createStyles.makeKeyframes;
23
+ },
24
+ get makeRawStyles () {
25
+ return _createStyles.makeRawStyles;
20
26
  },
21
27
  get rawStyles () {
22
28
  return _createStyles.rawStyles;
@@ -1,5 +1,5 @@
1
1
  export type { CreateStylesArgs, CreateStylesOptions } from './createStyles.js';
2
- export { default as createStyles, keyframes, makeCreateStyle, rawStyles } from './createStyles.js';
2
+ export { default as createStyles, keyframes, makeCreateStyles, makeKeyframes, makeRawStyles, rawStyles, } from './createStyles.js';
3
3
  export { setSeed } from './generateClassName.js';
4
4
  export type { PosthookPlugin } from './plugins.js';
5
5
  export { registerPosthook } from './plugins.js';
@@ -33,4 +33,16 @@ ${contents}`, '');
33
33
  return this.sheets.entries().reduce((prev, [ruleId, contents])=>`${prev}
34
34
  <style id="${ruleId}">${contents}</style>`, '');
35
35
  }
36
+ /**
37
+ * returns an array of tuples, [string, string][]
38
+ * where the first item in the tuple is the ID for the style rule
39
+ * and the second item is the actual CSS.
40
+ * Use this if you need to fully-control how you're rendering
41
+ * style tags BUT BE SURE TO USE THE ID or else HMR
42
+ * won't work during local development
43
+ */ getRulesById() {
44
+ return [
45
+ ...this.sheets.entries()
46
+ ];
47
+ }
36
48
  }
@@ -16,4 +16,13 @@ export declare class SimpleStyleRegistry {
16
16
  * mapped to their internal ruleset IDs
17
17
  */
18
18
  getHTML(): string;
19
+ /**
20
+ * returns an array of tuples, [string, string][]
21
+ * where the first item in the tuple is the ID for the style rule
22
+ * and the second item is the actual CSS.
23
+ * Use this if you need to fully-control how you're rendering
24
+ * style tags BUT BE SURE TO USE THE ID or else HMR
25
+ * won't work during local development
26
+ */
27
+ getRulesById(): [string, string][];
19
28
  }
@@ -26,12 +26,14 @@ export type CreateStylesOptions = Partial<{
26
26
  */
27
27
  registry?: SimpleStyleRegistry;
28
28
  }>;
29
- export declare function rawStyles<T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T, options?: Partial<CreateStylesOptions>): string;
29
+ export declare function rawStyles<T extends SimpleStyleRules>(ruleId: string, rules: T, options?: Partial<CreateStylesOptions>): string;
30
+ export declare function makeRawStyles(registry: SimpleStyleRegistry): <T extends SimpleStyleRules>(ruleId: string, rules: T) => string;
30
31
  export declare function keyframes<T extends Record<string, Properties>>(ruleId: string, frames: T, options?: CreateStylesOptions): [string, string];
31
- export declare function makeCreateStyle(registry: SimpleStyleRegistry): <T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T) => {
32
+ export declare function makeKeyframes(registry: SimpleStyleRegistry): <T extends Record<string, Properties>>(ruleId: string, rules: T) => [string, string];
33
+ export declare function makeCreateStyles(registry: SimpleStyleRegistry): <T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T) => {
32
34
  classes: O;
33
35
  stylesheet: string;
34
- updateSheet: <T2 extends SimpleStyleRules, K2 extends keyof T2, O2 extends Record<K2, string>>(updatedRules: Partial<T2>) => {
36
+ updateSheet: <T2 extends SimpleStyleRules>(updatedRules: Partial<T2>) => {
35
37
  classes: Record<string | number | keyof T2, string>;
36
38
  stylesheet: string;
37
39
  } | null;
@@ -39,7 +41,7 @@ export declare function makeCreateStyle(registry: SimpleStyleRegistry): <T exten
39
41
  export default function createStyles<T extends SimpleStyleRules, K extends keyof T, O extends Record<K, string>>(ruleId: string, rules: T, options?: Partial<CreateStylesOptions>): {
40
42
  classes: O;
41
43
  stylesheet: string;
42
- updateSheet: <T2 extends SimpleStyleRules, K2 extends keyof T2, O2 extends Record<K2, string>>(updatedRules: Partial<T2>) => {
44
+ updateSheet: <T2 extends SimpleStyleRules>(updatedRules: Partial<T2>) => {
43
45
  classes: Record<string | number | keyof T2, string>;
44
46
  stylesheet: string;
45
47
  } | null;
@@ -115,7 +115,6 @@ function coerceCreateStylesOptions(options) {
115
115
  flush: options && typeof options.flush === 'boolean' ? options.flush : true
116
116
  };
117
117
  }
118
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
119
118
  export function rawStyles(ruleId, rules, options) {
120
119
  const coerced = coerceCreateStylesOptions(options);
121
120
  const { sheetBuffer: sheetContents, mediaQueriesBuffer: mediaQueriesContents } = execCreateStyles(ruleId, rules, coerced, null, true);
@@ -123,6 +122,13 @@ export function rawStyles(ruleId, rules, options) {
123
122
  if (coerced.flush) flushSheetContents(ruleId, mergedContents, options);
124
123
  return mergedContents;
125
124
  }
125
+ export function makeRawStyles(registry) {
126
+ return function wrappedRawStyles(ruleId, rules) {
127
+ return rawStyles(ruleId, rules, {
128
+ registry
129
+ });
130
+ };
131
+ }
126
132
  export function keyframes(ruleId, frames, options) {
127
133
  const coerced = coerceCreateStylesOptions(options);
128
134
  const keyframeName = generateClassName(`${ruleId}_keyframes_`);
@@ -134,7 +140,14 @@ export function keyframes(ruleId, frames, options) {
134
140
  sheetContents
135
141
  ];
136
142
  }
137
- export function makeCreateStyle(registry) {
143
+ export function makeKeyframes(registry) {
144
+ return function wrappedCreateKeyframes(ruleId, rules) {
145
+ return keyframes(ruleId, rules, {
146
+ registry
147
+ });
148
+ };
149
+ }
150
+ export function makeCreateStyles(registry) {
138
151
  return function wrappedCreateStyles(ruleId, rules) {
139
152
  return createStyles(ruleId, rules, {
140
153
  registry
@@ -147,9 +160,8 @@ export default function createStyles(ruleId, rules, options) {
147
160
  const mergedContents = `${sheetContents}${mediaQueriesContents}`;
148
161
  const replacedSheetContents = replaceBackReferences(out, mergedContents);
149
162
  let sheet = null;
150
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
151
163
  const updateSheet = (updatedRules)=>{
152
- if ((options?.flush || options?.registry) && sheet || !options?.flush) {
164
+ if (options?.flush || options?.registry || !options?.flush) {
153
165
  // We prefer the first set, and then we shallow merge
154
166
  const { classes: updatedOut, sheetBuffer: updatedSheetContents, mediaQueriesBuffer: updatedMediaQueriesContents } = execCreateStyles(ruleId, merge(rules, updatedRules), {
155
167
  flush: false
@@ -157,6 +169,9 @@ export default function createStyles(ruleId, rules, options) {
157
169
  const updatedMergedContents = `${updatedSheetContents}${updatedMediaQueriesContents}`;
158
170
  const updatedReplacedSheetContents = replaceBackReferences(out, updatedMergedContents);
159
171
  if (sheet) sheet.innerHTML = updatedReplacedSheetContents;
172
+ else if (options?.registry) {
173
+ options.registry.add(ruleId, updatedReplacedSheetContents);
174
+ }
160
175
  return {
161
176
  classes: updatedOut,
162
177
  stylesheet: updatedSheetContents
@@ -1,5 +1,5 @@
1
1
  export type { CreateStylesArgs, CreateStylesOptions } from './createStyles.js';
2
- export { default as createStyles, keyframes, makeCreateStyle, rawStyles } from './createStyles.js';
2
+ export { default as createStyles, keyframes, makeCreateStyles, makeKeyframes, makeRawStyles, rawStyles, } from './createStyles.js';
3
3
  export { setSeed } from './generateClassName.js';
4
4
  export type { PosthookPlugin } from './plugins.js';
5
5
  export { registerPosthook } from './plugins.js';
@@ -1,3 +1,3 @@
1
- export { default as createStyles, keyframes, makeCreateStyle, rawStyles } from './createStyles.mjs';
1
+ export { default as createStyles, keyframes, makeCreateStyles, makeKeyframes, makeRawStyles, rawStyles } from './createStyles.mjs';
2
2
  export { setSeed } from './generateClassName.mjs';
3
3
  export { registerPosthook } from './plugins.mjs';
@@ -16,4 +16,13 @@ export declare class SimpleStyleRegistry {
16
16
  * mapped to their internal ruleset IDs
17
17
  */
18
18
  getHTML(): string;
19
+ /**
20
+ * returns an array of tuples, [string, string][]
21
+ * where the first item in the tuple is the ID for the style rule
22
+ * and the second item is the actual CSS.
23
+ * Use this if you need to fully-control how you're rendering
24
+ * style tags BUT BE SURE TO USE THE ID or else HMR
25
+ * won't work during local development
26
+ */
27
+ getRulesById(): [string, string][];
19
28
  }
@@ -28,4 +28,16 @@ ${contents}`, '');
28
28
  return this.sheets.entries().reduce((prev, [ruleId, contents])=>`${prev}
29
29
  <style id="${ruleId}">${contents}</style>`, '');
30
30
  }
31
+ /**
32
+ * returns an array of tuples, [string, string][]
33
+ * where the first item in the tuple is the ID for the style rule
34
+ * and the second item is the actual CSS.
35
+ * Use this if you need to fully-control how you're rendering
36
+ * style tags BUT BE SURE TO USE THE ID or else HMR
37
+ * won't work during local development
38
+ */ getRulesById() {
39
+ return [
40
+ ...this.sheets.entries()
41
+ ];
42
+ }
31
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simplestyle-js",
3
- "version": "3.4.2-alpha.3",
3
+ "version": "4.0.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": {