next-style 1.1.4 → 1.1.5
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 +205 -172
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -2
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -1,56 +1,46 @@
|
|
|
1
|
-
#
|
|
1
|
+
# NextStyle
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A lightweight **runtime CSS-in-JS engine** for React with deterministic class names, nested pseudo selectors, media queries, global styles, keyframes, and font-face support.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
style isolation with zero global leakage between pages or routes.
|
|
7
|
-
|
|
8
|
-
The library is framework-agnostic at its core and does not depend on React internally.
|
|
5
|
+
Designed for **page-scoped and component-scoped usage** without build-time tooling.
|
|
9
6
|
|
|
10
7
|
---
|
|
11
8
|
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
- Styles are scoped to a **single page or component**
|
|
15
|
-
- No global singleton style registry
|
|
16
|
-
- No cross-page or cross-route CSS leakage
|
|
17
|
-
- Each page owns its own styles
|
|
18
|
-
- Explicit style injection via a `<style>` tag
|
|
19
|
-
- No implicit DOM side effects
|
|
9
|
+
## Package Information
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
11
|
+
- **Name:** next-style
|
|
12
|
+
- **Version:** 1.1.5
|
|
13
|
+
- **License:** MIT
|
|
14
|
+
- **Author:** kingslimes
|
|
15
|
+
https://github.com/kingslimes
|
|
16
|
+
- **Repository:**
|
|
17
|
+
https://github.com/kingslimes/next-style
|
|
18
|
+
- **Issue Tracker:**
|
|
19
|
+
https://github.com/kingslimes/next-style/issues
|
|
24
20
|
|
|
25
21
|
---
|
|
26
22
|
|
|
27
23
|
## Features
|
|
28
24
|
|
|
29
|
-
- Object-based styling
|
|
30
|
-
- Deterministic
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
25
|
+
- Object-based styling (TypeScript friendly)
|
|
26
|
+
- Deterministic class names (same style → same class)
|
|
27
|
+
- Pseudo selectors (`:hover`, `:focus`, `:active`)
|
|
28
|
+
- Responsive media queries (`sm` → `xxl`)
|
|
29
|
+
- Global styles
|
|
34
30
|
- `@keyframes` support
|
|
35
31
|
- `@font-face` support
|
|
36
|
-
- PostCSS + Autoprefixer
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
32
|
+
- Built-in PostCSS + Autoprefixer
|
|
33
|
+
- Zero DOM dependency
|
|
34
|
+
- Tree-shakeable (`sideEffects: false`)
|
|
35
|
+
- Copy–paste friendly API
|
|
40
36
|
|
|
41
37
|
---
|
|
42
38
|
|
|
43
39
|
## Installation
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```sh
|
|
41
|
+
``` bash
|
|
48
42
|
npm install next-style
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
### Bun
|
|
52
|
-
|
|
53
|
-
```sh
|
|
43
|
+
# or
|
|
54
44
|
bun add next-style
|
|
55
45
|
```
|
|
56
46
|
|
|
@@ -58,243 +48,286 @@ bun add next-style
|
|
|
58
48
|
|
|
59
49
|
## Peer Dependencies
|
|
60
50
|
|
|
61
|
-
|
|
51
|
+
NextStyle relies on the following peer dependencies:
|
|
52
|
+
|
|
53
|
+
``` txt
|
|
54
|
+
react >= 18
|
|
55
|
+
postcss ^8
|
|
56
|
+
autoprefixer ^10
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Make sure they are installed in your project.
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
- **PostCSS** and **Autoprefixer** are bundled and used internally by Next.js
|
|
61
|
+
---
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
- Custom React setups
|
|
68
|
-
- Bun + React
|
|
69
|
-
- Vite or other non-Next runtimes
|
|
63
|
+
## Recommended Usage Pattern (Scoped)
|
|
70
64
|
|
|
71
|
-
|
|
65
|
+
The **recommended and official pattern** is to scope styles per page or per component using destructuring.
|
|
72
66
|
|
|
73
|
-
```
|
|
74
|
-
|
|
67
|
+
``` ts
|
|
68
|
+
const { css, StyleProvider } = new NextStyle("home")
|
|
75
69
|
```
|
|
76
70
|
|
|
77
|
-
|
|
71
|
+
Why this works well:
|
|
72
|
+
- Clear scope ownership
|
|
73
|
+
- No global side effects
|
|
74
|
+
- Easy to copy and reuse
|
|
75
|
+
- Matches React’s mental model
|
|
78
76
|
|
|
79
|
-
|
|
77
|
+
---
|
|
80
78
|
|
|
81
|
-
|
|
82
|
-
You may optionally provide a **custom prefix** to control generated class names.
|
|
79
|
+
## Basic Example (Page Scoped)
|
|
83
80
|
|
|
84
|
-
```
|
|
81
|
+
``` tsx
|
|
85
82
|
import { NextStyle } from "next-style"
|
|
86
83
|
|
|
87
|
-
export default function
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
export default function HomePage() {
|
|
85
|
+
const { css, StyleProvider } = new NextStyle("home")
|
|
86
|
+
|
|
87
|
+
const title = css({
|
|
88
|
+
fontSize: "32px",
|
|
89
|
+
fontWeight: 700,
|
|
90
|
+
marginBottom: "16px"
|
|
94
91
|
})
|
|
92
|
+
|
|
93
|
+
const button = css({
|
|
94
|
+
padding: "10px 20px",
|
|
95
|
+
borderRadius: "8px",
|
|
96
|
+
backgroundColor: "#2563eb",
|
|
97
|
+
color: "#fff",
|
|
98
|
+
|
|
99
|
+
_hover: {
|
|
100
|
+
backgroundColor: "#1d4ed8"
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
95
104
|
return (
|
|
96
105
|
<>
|
|
97
|
-
<
|
|
98
|
-
<
|
|
106
|
+
<StyleProvider />
|
|
107
|
+
<h1 className={title}>Home</h1>
|
|
108
|
+
<button className={button}>Click me</button>
|
|
99
109
|
</>
|
|
100
110
|
)
|
|
101
111
|
}
|
|
102
112
|
```
|
|
103
113
|
|
|
104
|
-
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Styling API
|
|
105
117
|
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
### `css(style): string`
|
|
119
|
+
|
|
120
|
+
Creates a class name from a style object.
|
|
121
|
+
|
|
122
|
+
``` ts
|
|
123
|
+
const className = css({
|
|
124
|
+
color: "red",
|
|
125
|
+
fontSize: "16px"
|
|
126
|
+
})
|
|
108
127
|
```
|
|
109
128
|
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
- Prefixes help identify styles per page or component
|
|
114
|
-
- Each page or component should create its own `NextStyle` instance
|
|
129
|
+
- Automatically converts camelCase → kebab-case
|
|
130
|
+
- Deduplicates styles using hashing
|
|
131
|
+
- Returns a stable class name
|
|
115
132
|
|
|
116
133
|
---
|
|
117
134
|
|
|
118
135
|
## Pseudo Selectors
|
|
119
136
|
|
|
120
|
-
|
|
137
|
+
Supported pseudo keys:
|
|
138
|
+
|
|
139
|
+
| Key | CSS Output |
|
|
140
|
+
|----|-----------|
|
|
141
|
+
| `_hover` | `:hover` |
|
|
142
|
+
| `_focus` | `:focus` |
|
|
143
|
+
| `_active` | `:active` |
|
|
121
144
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
145
|
+
Example:
|
|
146
|
+
|
|
147
|
+
``` ts
|
|
148
|
+
css({
|
|
149
|
+
color: "black",
|
|
126
150
|
_hover: {
|
|
127
|
-
|
|
128
|
-
},
|
|
129
|
-
_active: {
|
|
130
|
-
transform: "scale(0.98)"
|
|
151
|
+
color: "red"
|
|
131
152
|
}
|
|
132
153
|
})
|
|
133
154
|
```
|
|
134
155
|
|
|
135
|
-
Supported pseudo selectors:
|
|
136
|
-
- `_hover`
|
|
137
|
-
- `_focus`
|
|
138
|
-
- `_active`
|
|
139
|
-
|
|
140
156
|
---
|
|
141
157
|
|
|
142
|
-
## Responsive
|
|
158
|
+
## Responsive Media Queries
|
|
143
159
|
|
|
144
160
|
Built-in breakpoints:
|
|
145
161
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
| Key | Media Query |
|
|
163
|
+
|----|-------------|
|
|
164
|
+
| `_sm` | `(min-width: 640px)` |
|
|
165
|
+
| `_md` | `(min-width: 768px)` |
|
|
166
|
+
| `_lg` | `(min-width: 1024px)` |
|
|
167
|
+
| `_xl` | `(min-width: 1280px)` |
|
|
168
|
+
| `_xxl` | `(min-width: 1536px)` |
|
|
169
|
+
|
|
170
|
+
Example:
|
|
171
|
+
|
|
172
|
+
``` ts
|
|
173
|
+
css({
|
|
174
|
+
fontSize: "14px",
|
|
158
175
|
_lg: {
|
|
159
|
-
|
|
176
|
+
fontSize: "18px"
|
|
160
177
|
}
|
|
161
178
|
})
|
|
162
179
|
```
|
|
163
180
|
|
|
164
|
-
Media queries can be nested and
|
|
181
|
+
Media queries can be nested and merged automatically.
|
|
165
182
|
|
|
166
183
|
---
|
|
167
184
|
|
|
168
|
-
## Global Styles
|
|
185
|
+
## Global Styles
|
|
169
186
|
|
|
170
|
-
|
|
187
|
+
### `global(selector, style)`
|
|
171
188
|
|
|
172
|
-
|
|
173
|
-
|
|
189
|
+
Apply styles globally without generating a class.
|
|
190
|
+
|
|
191
|
+
``` ts
|
|
192
|
+
const { global, StyleProvider } = new NextStyle("global")
|
|
193
|
+
|
|
194
|
+
global("body", {
|
|
174
195
|
margin: 0,
|
|
175
|
-
fontFamily: "
|
|
196
|
+
fontFamily: "system-ui"
|
|
176
197
|
})
|
|
177
|
-
```
|
|
178
198
|
|
|
179
|
-
|
|
199
|
+
global("a", {
|
|
200
|
+
color: "inherit",
|
|
201
|
+
_hover: {
|
|
202
|
+
textDecoration: "underline"
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
```
|
|
180
206
|
|
|
181
207
|
---
|
|
182
208
|
|
|
183
|
-
##
|
|
209
|
+
## Animations
|
|
184
210
|
|
|
185
|
-
|
|
211
|
+
### `keyframes(frames): string`
|
|
186
212
|
|
|
187
|
-
|
|
188
|
-
|
|
213
|
+
Creates a `@keyframes` rule and returns its name.
|
|
214
|
+
|
|
215
|
+
``` ts
|
|
216
|
+
const fadeIn = keyframes({
|
|
189
217
|
from: { opacity: 0 },
|
|
190
218
|
to: { opacity: 1 }
|
|
191
219
|
})
|
|
192
|
-
```
|
|
193
220
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
```ts
|
|
197
|
-
const modal = ns.css({
|
|
198
|
-
animation: `${ fadeIn } 0.3s ease-out`
|
|
221
|
+
css({
|
|
222
|
+
animation: `${fadeIn} 300ms ease-in`
|
|
199
223
|
})
|
|
200
224
|
```
|
|
201
225
|
|
|
202
|
-
Keyframes are scoped to the current `NextStyle` instance.
|
|
203
|
-
|
|
204
226
|
---
|
|
205
227
|
|
|
206
|
-
##
|
|
228
|
+
## Fonts
|
|
207
229
|
|
|
208
|
-
|
|
230
|
+
### `fontFace(font)`
|
|
209
231
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
232
|
+
Registers a `@font-face` rule.
|
|
233
|
+
|
|
234
|
+
``` ts
|
|
235
|
+
fontFace({
|
|
236
|
+
fontFamily: "MyFont",
|
|
237
|
+
src: "url(/fonts/myfont.woff2)",
|
|
214
238
|
fontWeight: 400,
|
|
215
239
|
fontStyle: "normal",
|
|
216
240
|
fontDisplay: "swap"
|
|
217
241
|
})
|
|
218
242
|
```
|
|
219
243
|
|
|
220
|
-
Font-face rules are injected only for the current page or component.
|
|
221
|
-
|
|
222
244
|
---
|
|
223
245
|
|
|
224
|
-
##
|
|
246
|
+
## Rendering Styles
|
|
225
247
|
|
|
226
|
-
|
|
227
|
-
- Object keys are sorted before hashing
|
|
228
|
-
- Semantically identical styles always produce the same class name
|
|
229
|
-
- Prevents unnecessary class regeneration
|
|
248
|
+
### `<StyleProvider />`
|
|
230
249
|
|
|
231
|
-
|
|
250
|
+
Injects all generated CSS into a `<style>` tag.
|
|
232
251
|
|
|
233
|
-
|
|
252
|
+
``` tsx
|
|
253
|
+
<>
|
|
254
|
+
<StyleProvider />
|
|
255
|
+
<App />
|
|
256
|
+
</>
|
|
257
|
+
```
|
|
234
258
|
|
|
235
|
-
|
|
259
|
+
- Returns `null` if no styles exist
|
|
260
|
+
- Should be rendered **once per scope**
|
|
236
261
|
|
|
237
|
-
|
|
238
|
-
- No JSX is exported from the library
|
|
239
|
-
- No React runtime is required
|
|
240
|
-
- No side effects occur during render
|
|
262
|
+
---
|
|
241
263
|
|
|
242
|
-
|
|
264
|
+
### `toTextCss(): string | null`
|
|
243
265
|
|
|
244
|
-
|
|
245
|
-
<style>{ ns.StyleText }</style>
|
|
246
|
-
```
|
|
266
|
+
Returns all generated CSS as a string.
|
|
247
267
|
|
|
248
|
-
|
|
268
|
+
Useful for:
|
|
269
|
+
- Server-side rendering (SSR)
|
|
270
|
+
- Manual injection
|
|
271
|
+
- Debugging
|
|
249
272
|
|
|
250
|
-
|
|
273
|
+
``` ts
|
|
274
|
+
const cssText = toTextCss()
|
|
275
|
+
```
|
|
251
276
|
|
|
252
|
-
|
|
277
|
+
---
|
|
253
278
|
|
|
254
|
-
|
|
255
|
-
- PostCSS and Autoprefixer results are cached
|
|
256
|
-
- Only one `<style>` tag is required per page or component
|
|
257
|
-
- No global runtime mutations
|
|
279
|
+
## Component Scoped Example
|
|
258
280
|
|
|
259
|
-
|
|
260
|
-
- Next.js App Router
|
|
261
|
-
- Page-level isolation
|
|
262
|
-
- Component-driven design systems
|
|
281
|
+
Reusable, self-contained component.
|
|
263
282
|
|
|
264
|
-
|
|
283
|
+
``` tsx
|
|
284
|
+
import { NextStyle } from "next-style"
|
|
265
285
|
|
|
266
|
-
|
|
286
|
+
export function Card({ title, children }) {
|
|
287
|
+
const { css, StyleProvider } = new NextStyle("card")
|
|
267
288
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
289
|
+
const root = css({
|
|
290
|
+
padding: "16px",
|
|
291
|
+
borderRadius: "12px",
|
|
292
|
+
backgroundColor: "#fff",
|
|
293
|
+
boxShadow: "0 10px 25px rgba(0,0,0,.1)"
|
|
294
|
+
})
|
|
272
295
|
|
|
273
|
-
|
|
296
|
+
const heading = css({
|
|
297
|
+
fontSize: "18px",
|
|
298
|
+
fontWeight: 600,
|
|
299
|
+
marginBottom: "8px"
|
|
300
|
+
})
|
|
274
301
|
|
|
275
|
-
|
|
302
|
+
return (
|
|
303
|
+
<>
|
|
304
|
+
<StyleProvider />
|
|
305
|
+
<div className={root}>
|
|
306
|
+
<div className={heading}>{title}</div>
|
|
307
|
+
{children}
|
|
308
|
+
</div>
|
|
309
|
+
</>
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
```
|
|
276
313
|
|
|
277
|
-
|
|
278
|
-
- Version: `1.1.2`
|
|
279
|
-
- License: MIT
|
|
280
|
-
- Module type: ESM
|
|
281
|
-
- Side effects: false
|
|
314
|
+
---
|
|
282
315
|
|
|
283
|
-
|
|
284
|
-
https://github.com/kingslimes/next-style
|
|
316
|
+
## Best Practices
|
|
285
317
|
|
|
286
|
-
|
|
287
|
-
|
|
318
|
+
- Create **one NextStyle instance per page or component**
|
|
319
|
+
- Do **not** share instances globally
|
|
320
|
+
- Render `StyleProvider` only once per scope
|
|
321
|
+
- Use meaningful prefixes (`home`, `card`, `profile`)
|
|
288
322
|
|
|
289
323
|
---
|
|
290
324
|
|
|
291
|
-
##
|
|
325
|
+
## Design Intentions
|
|
292
326
|
|
|
293
|
-
-
|
|
294
|
-
-
|
|
295
|
-
-
|
|
296
|
-
-
|
|
297
|
-
- Dev-time warnings for incorrect usage
|
|
327
|
+
- No descendant selectors (`& > div`)
|
|
328
|
+
- No arbitrary selector nesting
|
|
329
|
+
- Predictable output over expressiveness
|
|
330
|
+
- Optimized for runtime and SSR safety
|
|
298
331
|
|
|
299
332
|
---
|
|
300
333
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Properties } from "csstype";
|
|
2
|
+
import type { DetailedReactHTMLElement } from "react";
|
|
2
3
|
export type NextStyleProperties = {
|
|
3
4
|
[K in keyof Properties<string | number>]?: Properties<string | number>[K];
|
|
4
5
|
} & {
|
|
@@ -31,6 +32,9 @@ export declare class NextStyle {
|
|
|
31
32
|
global: (selector: string, style: NextStyleProperties) => void;
|
|
32
33
|
keyframes: (frames: KeyframesObject) => string;
|
|
33
34
|
fontFace: (font: FontFaceObject) => void;
|
|
34
|
-
|
|
35
|
+
toTextCss: () => string | null;
|
|
36
|
+
StyleProvider: () => DetailedReactHTMLElement<{
|
|
37
|
+
children: string;
|
|
38
|
+
}, HTMLStyleElement> | null;
|
|
35
39
|
}
|
|
36
40
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import postcss from"postcss";import autoprefixer from"autoprefixer";var processor=postcss([autoprefixer({overrideBrowserslist:[">0.2%","not dead","not op_mini all"]})]),postcssCache=new Map;function postcssTransform(cssText){let cached=postcssCache.get(cssText);if(cached)return cached;let result=processor.process(cssText,{from:void 0}).css;return postcssCache.set(cssText,result),result}function stableStringify(value){if(value==null||typeof value!=="object")return JSON.stringify(value);if(Array.isArray(value))return`[${value.map(stableStringify).join(",")}]`;return`{${Object.keys(value).sort().map((k)=>`"${k}":${stableStringify(value[k])}`).join(",")}}`}function createHashName(seed){let hash=BigInt("0xcbf29ce484222325"),prime=BigInt("0x100000001b3");for(let i=0;i<seed.length;i++)hash^=BigInt(seed.charCodeAt(i)),hash*=prime,hash&=BigInt("0xffffffffffffffff");return hash.toString(36).slice(0,9)}function toKebabCase(prop){return prop.replace(/[A-Z]/g,(m)=>`-${m.toLowerCase()}`)}var MEDIA_MAP={_sm:"(min-width:640px)",_md:"(min-width:768px)",_lg:"(min-width:1024px)",_xl:"(min-width:1280px)",_xxl:"(min-width:1536px)"};function mergeMedia(parent,current){if(!parent)return current;if(!current)return parent;return`${parent} and ${current}`}function serializeNested(style,ctx){let css="",base="";for(let key in style){let value=style[key];if(value==null||typeof value==="object"||key.startsWith("_"))continue;base+=`${toKebabCase(key)}:${value};`}if(base){let rule=`${ctx.selector}{${base}}`;css+=ctx.media?`@media ${ctx.media}{${rule}}`:rule}for(let pseudo of["_hover","_focus","_active"]){let value=style[pseudo];if(!value)continue;css+=serializeNested(value,{selector:`${ctx.selector}:${pseudo.slice(1)}`,media:ctx.media})}for(let key in MEDIA_MAP){let mediaKey=key,value=style[mediaKey];if(!value)continue;css+=serializeNested(value,{selector:ctx.selector,media:mergeMedia(ctx.media,MEDIA_MAP[mediaKey])})}return css}class NextStyle{prefix;rules=new Map;constructor(prefix="next"){this.prefix=prefix}css=(style)=>{let seed=stableStringify(style),hash=createHashName(seed),className=`${this.prefix}_${hash}`,key=`class:${className}`;if(!this.rules.has(key)){let raw=serializeNested(style,{selector:`.${className}`}),cssText=postcssTransform(raw);this.rules.set(key,cssText)}return className};global=(selector,style)=>{let key=`global:${selector}`;if(!this.rules.has(key)){let raw=serializeNested(style,{selector}),cssText=postcssTransform(raw);this.rules.set(key,cssText)}};keyframes=(frames)=>{let seed=stableStringify(frames),hash=createHashName(seed),name=`${this.prefix}_${hash}`,key=`@keyframes:${name}`;if(!this.rules.has(key)){let body="";for(let step in frames){let props="",frame=frames[step];for(let prop in frame)props+=`${toKebabCase(prop)}:${frame[prop]};`;body+=`${step}{${props}}`}let cssText=postcssTransform(`@keyframes ${name}{${body}}`);this.rules.set(key,cssText)}return name};fontFace=(font)=>{let seed=stableStringify(font),key=`@font-face:${createHashName(seed)}`;if(!this.rules.has(key)){let body="";for(let prop in font)body+=`${toKebabCase(prop)}:${font[prop]};`;let cssText=postcssTransform(`@font-face{${body}}`);this.rules.set(key,cssText)}};
|
|
2
|
-
`;return cssText}
|
|
1
|
+
import postcss from"postcss";import{createElement}from"react";import autoprefixer from"autoprefixer";var processor=postcss([autoprefixer({overrideBrowserslist:[">0.2%","not dead","not op_mini all"]})]),postcssCache=new Map;function postcssTransform(cssText){let cached=postcssCache.get(cssText);if(cached)return cached;let result=processor.process(cssText,{from:void 0}).css;return postcssCache.set(cssText,result),result}function stableStringify(value){if(value==null||typeof value!=="object")return JSON.stringify(value);if(Array.isArray(value))return`[${value.map(stableStringify).join(",")}]`;return`{${Object.keys(value).sort().map((k)=>`"${k}":${stableStringify(value[k])}`).join(",")}}`}function createHashName(seed){let hash=BigInt("0xcbf29ce484222325"),prime=BigInt("0x100000001b3");for(let i=0;i<seed.length;i++)hash^=BigInt(seed.charCodeAt(i)),hash*=prime,hash&=BigInt("0xffffffffffffffff");return hash.toString(36).slice(0,9)}function toKebabCase(prop){return prop.replace(/[A-Z]/g,(m)=>`-${m.toLowerCase()}`)}var MEDIA_MAP={_sm:"(min-width:640px)",_md:"(min-width:768px)",_lg:"(min-width:1024px)",_xl:"(min-width:1280px)",_xxl:"(min-width:1536px)"};function mergeMedia(parent,current){if(!parent)return current;if(!current)return parent;return`${parent} and ${current}`}function serializeNested(style,ctx){let css="",base="";for(let key in style){let value=style[key];if(value==null||typeof value==="object"||key.startsWith("_"))continue;base+=`${toKebabCase(key)}:${value};`}if(base){let rule=`${ctx.selector}{${base}}`;css+=ctx.media?`@media ${ctx.media}{${rule}}`:rule}for(let pseudo of["_hover","_focus","_active"]){let value=style[pseudo];if(!value)continue;css+=serializeNested(value,{selector:`${ctx.selector}:${pseudo.slice(1)}`,media:ctx.media})}for(let key in MEDIA_MAP){let mediaKey=key,value=style[mediaKey];if(!value)continue;css+=serializeNested(value,{selector:ctx.selector,media:mergeMedia(ctx.media,MEDIA_MAP[mediaKey])})}return css}class NextStyle{prefix;rules=new Map;constructor(prefix="next"){this.prefix=prefix}css=(style)=>{let seed=stableStringify(style),hash=createHashName(seed),className=`${this.prefix}_${hash}`,key=`class:${className}`;if(!this.rules.has(key)){let raw=serializeNested(style,{selector:`.${className}`}),cssText=postcssTransform(raw);this.rules.set(key,cssText)}return className};global=(selector,style)=>{let key=`global:${selector}`;if(!this.rules.has(key)){let raw=serializeNested(style,{selector}),cssText=postcssTransform(raw);this.rules.set(key,cssText)}};keyframes=(frames)=>{let seed=stableStringify(frames),hash=createHashName(seed),name=`${this.prefix}_${hash}`,key=`@keyframes:${name}`;if(!this.rules.has(key)){let body="";for(let step in frames){let props="",frame=frames[step];for(let prop in frame)props+=`${toKebabCase(prop)}:${frame[prop]};`;body+=`${step}{${props}}`}let cssText=postcssTransform(`@keyframes ${name}{${body}}`);this.rules.set(key,cssText)}return name};fontFace=(font)=>{let seed=stableStringify(font),key=`@font-face:${createHashName(seed)}`;if(!this.rules.has(key)){let body="";for(let prop in font)body+=`${toKebabCase(prop)}:${font[prop]};`;let cssText=postcssTransform(`@font-face{${body}}`);this.rules.set(key,cssText)}};toTextCss=()=>{if(this.rules.size===0)return null;let cssText="";for(let rule of this.rules.values())cssText+=rule+`
|
|
2
|
+
`;return cssText};StyleProvider=()=>{if(this.rules.size===0)return null;let cssText="";for(let rule of this.rules.values())cssText+=rule+`
|
|
3
|
+
`;return createElement("style",{children:cssText})}}export{NextStyle};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-style",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Lightweight runtime CSS-in-JS engine with nested pseudo selectors, media queries, global styles, keyframes, and font-face support.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "kingslimes",
|
|
@@ -52,15 +52,13 @@
|
|
|
52
52
|
"font-face"
|
|
53
53
|
],
|
|
54
54
|
"peerDependencies": {
|
|
55
|
+
"react": ">=18",
|
|
55
56
|
"postcss": "^8",
|
|
56
57
|
"autoprefixer": "^10"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"csstype": "latest"
|
|
60
61
|
},
|
|
61
|
-
"engines": {
|
|
62
|
-
"node": ">=18"
|
|
63
|
-
},
|
|
64
62
|
"publishConfig": {
|
|
65
63
|
"access": "public"
|
|
66
64
|
}
|