@pyreon/styler 0.24.5 → 0.24.6

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.
Files changed (47) hide show
  1. package/package.json +5 -7
  2. package/src/ThemeProvider.ts +0 -65
  3. package/src/__tests__/ThemeProvider.test.ts +0 -67
  4. package/src/__tests__/benchmark.bench.ts +0 -200
  5. package/src/__tests__/composition-chain.test.ts +0 -537
  6. package/src/__tests__/css.test.ts +0 -70
  7. package/src/__tests__/dev-gate-treeshake.test.ts +0 -85
  8. package/src/__tests__/forward.test.ts +0 -282
  9. package/src/__tests__/globalStyle.test.ts +0 -72
  10. package/src/__tests__/hash.test.ts +0 -70
  11. package/src/__tests__/hybrid-injection.test.ts +0 -225
  12. package/src/__tests__/index.ts +0 -14
  13. package/src/__tests__/inject-rules.browser.test.ts +0 -40
  14. package/src/__tests__/insertion-effect.test.ts +0 -119
  15. package/src/__tests__/integration-dom.test.ts +0 -58
  16. package/src/__tests__/integration.test.ts +0 -179
  17. package/src/__tests__/keyframes.test.ts +0 -68
  18. package/src/__tests__/memory-growth.test.ts +0 -220
  19. package/src/__tests__/native-marker.test.ts +0 -9
  20. package/src/__tests__/p3-features.test.ts +0 -316
  21. package/src/__tests__/resolve-cache.test.ts +0 -94
  22. package/src/__tests__/resolve.test.ts +0 -308
  23. package/src/__tests__/shared.test.ts +0 -133
  24. package/src/__tests__/sheet-advanced.test.ts +0 -659
  25. package/src/__tests__/sheet-split-atrules.test.ts +0 -410
  26. package/src/__tests__/sheet.test.ts +0 -250
  27. package/src/__tests__/static-styler-resolve-cost.test.ts +0 -160
  28. package/src/__tests__/styled-reactive.test.ts +0 -74
  29. package/src/__tests__/styled-ssr.test.ts +0 -75
  30. package/src/__tests__/styled.test.ts +0 -511
  31. package/src/__tests__/styler.browser.test.tsx +0 -194
  32. package/src/__tests__/theme.test.ts +0 -33
  33. package/src/__tests__/useCSS.test.ts +0 -172
  34. package/src/css.ts +0 -13
  35. package/src/env.d.ts +0 -6
  36. package/src/forward.ts +0 -308
  37. package/src/globalStyle.ts +0 -53
  38. package/src/hash.ts +0 -28
  39. package/src/index.ts +0 -15
  40. package/src/keyframes.ts +0 -36
  41. package/src/manifest.ts +0 -332
  42. package/src/resolve.ts +0 -225
  43. package/src/shared.ts +0 -22
  44. package/src/sheet.ts +0 -635
  45. package/src/styled.tsx +0 -503
  46. package/src/tests/manifest-snapshot.test.ts +0 -51
  47. package/src/useCSS.ts +0 -20
@@ -1,33 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { ThemeContext, useTheme } from '../ThemeProvider'
3
-
4
- describe('ThemeContext', () => {
5
- it('is a Context object', () => {
6
- expect(ThemeContext).toBeDefined()
7
- expect(ThemeContext.id).toBeDefined()
8
- })
9
-
10
- it('has an id property for context identification', () => {
11
- expect(typeof ThemeContext.id).toBe('symbol')
12
- })
13
- })
14
-
15
- describe('useTheme', () => {
16
- it('is a function', () => {
17
- expect(typeof useTheme).toBe('function')
18
- })
19
-
20
- it('returns the default theme (empty object) when called outside a provider', () => {
21
- const theme = useTheme()
22
- expect(theme).toEqual({})
23
- })
24
-
25
- it('can be called with a type parameter', () => {
26
- interface MyTheme {
27
- primary: string
28
- spacing: number
29
- }
30
- const theme = useTheme<MyTheme>()
31
- expect(theme).toBeDefined()
32
- })
33
- })
@@ -1,172 +0,0 @@
1
- import { afterEach, describe, expect, it } from 'vitest'
2
- import { css } from '../css'
3
- import { sheet } from '../sheet'
4
- import { useCSS } from '../useCSS'
5
-
6
- describe('useCSS', () => {
7
- afterEach(() => {
8
- sheet.clearAll()
9
- })
10
-
11
- describe('basic usage', () => {
12
- it('returns a className string for static CSS', () => {
13
- const template = css`
14
- display: flex;
15
- `
16
- const result = useCSS(template)
17
- expect(typeof result).toBe('string')
18
- expect(result).toMatch(/^pyr-[0-9a-z]+$/)
19
- })
20
-
21
- it('returns different classNames for different CSS', () => {
22
- const template1 = css`
23
- display: flex;
24
- `
25
- const template2 = css`
26
- display: block;
27
- `
28
-
29
- const r1 = useCSS(template1)
30
- const r2 = useCSS(template2)
31
-
32
- expect(r1).toMatch(/^pyr-/)
33
- expect(r2).toMatch(/^pyr-/)
34
- expect(r1).not.toBe(r2)
35
- })
36
-
37
- it('returns empty string for empty CSS', () => {
38
- const template = css``
39
- const result = useCSS(template)
40
- expect(result).toBe('')
41
- })
42
-
43
- it('returns empty string for whitespace-only CSS', () => {
44
- const template = css``
45
- const result = useCSS(template)
46
- expect(result).toBe('')
47
- })
48
- })
49
-
50
- describe('dynamic values', () => {
51
- it('works with static interpolation values', () => {
52
- const color = 'red'
53
- const template = css`
54
- color: ${color};
55
- `
56
- const result = useCSS(template)
57
- expect(result).toMatch(/^pyr-[0-9a-z]+$/)
58
- })
59
-
60
- it('works with function interpolations resolved via props', () => {
61
- const template = css`
62
- color: ${(p: any) => p.color};
63
- `
64
- const result = useCSS(template, { color: 'blue' })
65
- expect(result).toMatch(/^pyr-[0-9a-z]+$/)
66
- })
67
-
68
- it('different prop values produce different classNames', () => {
69
- const template = css`
70
- color: ${(p: any) => p.color};
71
- `
72
-
73
- const r1 = useCSS(template, { color: 'red' })
74
- const r2 = useCSS(template, { color: 'green' })
75
-
76
- expect(r1).not.toBe(r2)
77
- })
78
- })
79
-
80
- describe('caching', () => {
81
- it('same CSS returns same className on repeated calls', () => {
82
- const template = css`
83
- display: flex;
84
- `
85
- const cls1 = useCSS(template)
86
- const cls2 = useCSS(template)
87
- expect(cls1).toBe(cls2)
88
- })
89
-
90
- it('same dynamic CSS with same props returns same className', () => {
91
- const template = css`
92
- color: ${(p: any) => p.color};
93
- `
94
- const cls1 = useCSS(template, { color: 'red' })
95
- const cls2 = useCSS(template, { color: 'red' })
96
- expect(cls1).toBe(cls2)
97
- })
98
- })
99
-
100
- describe('cache hit path', () => {
101
- it('reuses cached className with identical resolved CSS', () => {
102
- const template = css`
103
- color: ${(p: any) => p.color};
104
- `
105
- const cls1 = useCSS(template, { color: 'red' })
106
- const cls2 = useCSS(template, { color: 'red' })
107
- expect(cls1).toBe(cls2)
108
- expect(cls1).toMatch(/^pyr-/)
109
- })
110
-
111
- it('updates className when resolved CSS changes', () => {
112
- const template = css`
113
- color: ${(p: any) => p.color};
114
- `
115
- const cls1 = useCSS(template, { color: 'red' })
116
- const cls2 = useCSS(template, { color: 'blue' })
117
- expect(cls1).not.toBe(cls2)
118
- })
119
- })
120
-
121
- describe('boost parameter', () => {
122
- it('does not throw when boost is true', () => {
123
- const template = css`
124
- display: flex;
125
- `
126
- const result = useCSS(template, undefined, true)
127
- expect(result).toMatch(/^pyr-[0-9a-z]+$/)
128
- })
129
-
130
- it('does not throw when boost is false', () => {
131
- const template = css`
132
- display: flex;
133
- `
134
- const result = useCSS(template, undefined, false)
135
- expect(result).toMatch(/^pyr-[0-9a-z]+$/)
136
- })
137
- })
138
-
139
- describe('without theme and without props', () => {
140
- it('uses empty object when no props and no theme', () => {
141
- const template = css`
142
- display: flex;
143
- `
144
- const result = useCSS(template)
145
- expect(result).toMatch(/^pyr-[0-9a-z]+$/)
146
- })
147
-
148
- it('handles dynamic template without theme or props', () => {
149
- const template = css`
150
- color: ${(p: any) => p.color ?? 'red'};
151
- `
152
- const result = useCSS(template, undefined)
153
- expect(result).toMatch(/^pyr-/)
154
- })
155
- })
156
-
157
- describe('empty CSS from dynamic resolution', () => {
158
- it('returns empty className when dynamic CSS resolves to empty', () => {
159
- const template = css`
160
- ${(p: any) => (p.color ? `color: ${p.color};` : '')}
161
- `
162
-
163
- // First call: non-empty CSS
164
- const cls1 = useCSS(template, { color: 'red' })
165
- expect(cls1).toMatch(/^pyr-/)
166
-
167
- // Second call: empty CSS
168
- const cls2 = useCSS(template, { color: undefined })
169
- expect(cls2).toBe('')
170
- })
171
- })
172
- })
package/src/css.ts DELETED
@@ -1,13 +0,0 @@
1
- import { CSSResult, type Interpolation } from './resolve'
2
-
3
- /**
4
- * Tagged template function for CSS. Captures the template strings and
5
- * interpolation values as a lazy CSSResult — resolution is deferred
6
- * until a styled component renders.
7
- *
8
- * Works as both a tagged template (`css\`...\``) and a regular function
9
- * call (`css(...args)`) since tagged templates are syntactic sugar for
10
- * function calls with (TemplateStringsArray, ...values).
11
- */
12
- export const css = (strings: TemplateStringsArray, ...values: Interpolation[]): CSSResult =>
13
- new CSSResult(strings, values)
package/src/env.d.ts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * Minimal process type — just enough for `process.env.NODE_ENV` checks.
3
- * Avoids requiring @types/node in consumers that import pyreon source
4
- * via the `"bun"` export condition.
5
- */
6
- declare var process: { env: { NODE_ENV?: string } }
package/src/forward.ts DELETED
@@ -1,308 +0,0 @@
1
- /**
2
- * HTML prop filtering. Prevents unknown props from being forwarded to DOM
3
- * elements (which causes warnings). Props starting with `$` are
4
- * transient (styling-only) and are always filtered out.
5
- */
6
-
7
- // Common HTML attributes, event handlers, and ARIA/data attributes.
8
- //
9
- // Using a plain object with `key in HTML_PROPS` instead of `Set.has(key)`:
10
- // V8 inlines `in` checks via hidden-class lookups (the object has a fixed
11
- // shape at module load and never changes), which is meaningfully faster
12
- // than going through the Set protocol on hot prop-filter paths. Measured
13
- // upstream (vitus-labs `be471b19`): +19% on the 5-lookup mix benchmark
14
- // (4 hits + 1 miss).
15
- const HTML_PROPS_LIST = [
16
- // Core props
17
- 'className',
18
- 'class',
19
- 'dangerouslySetInnerHTML',
20
- 'htmlFor',
21
- 'id',
22
- 'key',
23
- 'ref',
24
- 'style',
25
- 'tabIndex',
26
- 'role',
27
- // Event handlers
28
- 'onAbort',
29
- 'onAnimationEnd',
30
- 'onAnimationIteration',
31
- 'onAnimationStart',
32
- 'onBlur',
33
- 'onChange',
34
- 'onClick',
35
- 'onCompositionEnd',
36
- 'onCompositionStart',
37
- 'onCompositionUpdate',
38
- 'onContextMenu',
39
- 'onCopy',
40
- 'onCut',
41
- 'onDoubleClick',
42
- 'onDrag',
43
- 'onDragEnd',
44
- 'onDragEnter',
45
- 'onDragLeave',
46
- 'onDragOver',
47
- 'onDragStart',
48
- 'onDrop',
49
- 'onError',
50
- 'onFocus',
51
- 'onInput',
52
- 'onKeyDown',
53
- 'onKeyPress',
54
- 'onKeyUp',
55
- 'onLoad',
56
- 'onMouseDown',
57
- 'onMouseEnter',
58
- 'onMouseLeave',
59
- 'onMouseMove',
60
- 'onMouseOut',
61
- 'onMouseOver',
62
- 'onMouseUp',
63
- 'onPaste',
64
- 'onPointerCancel',
65
- 'onPointerDown',
66
- 'onPointerEnter',
67
- 'onPointerLeave',
68
- 'onPointerMove',
69
- 'onPointerOut',
70
- 'onPointerOver',
71
- 'onPointerUp',
72
- 'onScroll',
73
- 'onSelect',
74
- 'onSubmit',
75
- 'onTouchCancel',
76
- 'onTouchEnd',
77
- 'onTouchMove',
78
- 'onTouchStart',
79
- 'onTransitionEnd',
80
- 'onWheel',
81
- // HTML attributes
82
- 'accept',
83
- 'acceptCharset',
84
- 'accessKey',
85
- 'action',
86
- 'allow',
87
- 'allowFullScreen',
88
- 'alt',
89
- 'as',
90
- 'async',
91
- 'autoCapitalize',
92
- 'autoComplete',
93
- 'autoCorrect',
94
- 'autoFocus',
95
- 'autoPlay',
96
- 'capture',
97
- 'cellPadding',
98
- 'cellSpacing',
99
- 'charSet',
100
- 'checked',
101
- 'cite',
102
- 'cols',
103
- 'colSpan',
104
- 'content',
105
- 'contentEditable',
106
- 'controls',
107
- 'controlsList',
108
- 'coords',
109
- 'crossOrigin',
110
- 'dateTime',
111
- 'decoding',
112
- 'default',
113
- 'defaultChecked',
114
- 'defaultValue',
115
- 'defer',
116
- 'dir',
117
- 'disabled',
118
- 'disablePictureInPicture',
119
- 'disableRemotePlayback',
120
- 'download',
121
- 'draggable',
122
- 'encType',
123
- 'enterKeyHint',
124
- 'fetchPriority',
125
- 'form',
126
- 'formAction',
127
- 'formEncType',
128
- 'formMethod',
129
- 'formNoValidate',
130
- 'formTarget',
131
- 'frameBorder',
132
- 'headers',
133
- 'height',
134
- 'hidden',
135
- 'high',
136
- 'href',
137
- 'hrefLang',
138
- 'httpEquiv',
139
- 'inputMode',
140
- 'integrity',
141
- 'is',
142
- 'label',
143
- 'lang',
144
- 'list',
145
- 'loading',
146
- 'loop',
147
- 'low',
148
- 'max',
149
- 'maxLength',
150
- 'media',
151
- 'method',
152
- 'min',
153
- 'minLength',
154
- 'multiple',
155
- 'muted',
156
- 'name',
157
- 'noModule',
158
- 'noValidate',
159
- 'nonce',
160
- 'open',
161
- 'optimum',
162
- 'pattern',
163
- 'placeholder',
164
- 'playsInline',
165
- 'poster',
166
- 'preload',
167
- 'readOnly',
168
- 'referrerPolicy',
169
- 'rel',
170
- 'required',
171
- 'reversed',
172
- 'rows',
173
- 'rowSpan',
174
- 'sandbox',
175
- 'scope',
176
- 'scoped',
177
- 'scrolling',
178
- 'selected',
179
- 'shape',
180
- 'size',
181
- 'sizes',
182
- 'slot',
183
- 'span',
184
- 'spellCheck',
185
- 'src',
186
- 'srcDoc',
187
- 'srcLang',
188
- 'srcSet',
189
- 'start',
190
- 'step',
191
- 'summary',
192
- 'target',
193
- 'title',
194
- 'translate',
195
- 'type',
196
- 'useMap',
197
- 'value',
198
- 'width',
199
- 'wrap',
200
- ] as const
201
-
202
- // Build the lookup object once at module load. `null`-prototype keeps the
203
- // object's hidden class lean and means `in` checks don't accidentally pick
204
- // up `Object.prototype` keys.
205
- const HTML_PROPS: Record<string, true> = Object.create(null)
206
- for (const k of HTML_PROPS_LIST) HTML_PROPS[k] = true
207
-
208
- /**
209
- * Filters props for HTML elements. Keeps valid HTML attrs, data-*, aria-*.
210
- * Rejects unknown props and $-prefixed transient props.
211
- */
212
- export const filterProps = (props: Record<string, unknown>): Record<string, unknown> => {
213
- const filtered: Record<string, unknown> = {}
214
-
215
- for (const key in props) {
216
- // Skip transient props ($-prefixed) — used for styling-only props
217
- if (key.charCodeAt(0) === 36) continue // '$'
218
-
219
- // Skip `as` prop — handled separately by styled
220
- if (key === 'as') continue
221
-
222
- // Keep data-* and aria-* attributes
223
- if (key.startsWith('data-') || key.startsWith('aria-')) {
224
- filtered[key] = props[key]
225
- continue
226
- }
227
-
228
- // Keep known HTML props — `in` against the null-prototype lookup
229
- // object beats `Set.has` on the hot DOM-filter path.
230
- if (key in HTML_PROPS) {
231
- filtered[key] = props[key]
232
- }
233
- }
234
-
235
- return filtered
236
- }
237
-
238
- /**
239
- * Build final props for a styled component in a single pass.
240
- * Combines className merging, ref injection, and prop filtering into one
241
- * allocation and one iteration.
242
- *
243
- * Copies own property DESCRIPTORS rather than values for forwarded
244
- * props — getter-shaped reactive props (compiler-emitted `_rp(() =>
245
- * signal())` converted to getters by `makeReactiveProps`) survive the
246
- * copy with their reactive subscription intact. A bare `result[key] =
247
- * rawProps[key]` fires the getter at setup time and stores a static
248
- * value, breaking signal-driven reactivity for any consumer that reads
249
- * `props.x` in a reactive scope downstream.
250
- */
251
- export const buildProps = (
252
- rawProps: Record<string, any>,
253
- generatedCls: string,
254
- isDOM: boolean,
255
- customFilter?: (prop: string) => boolean,
256
- ): Record<string, any> => {
257
- const result: Record<string, any> = {}
258
-
259
- // Merge generated + user className. Reading `rawProps.class` /
260
- // `.className` synchronously is fine — `class` is consumed at this
261
- // boundary (merged with the generated class), never forwarded
262
- // reactively. The string we write is consumed by the DOM at apply
263
- // time, not stored as a getter.
264
- const userCls = rawProps.class || rawProps.className
265
- if (generatedCls) {
266
- result.class = userCls ? `${generatedCls} ${userCls}` : generatedCls
267
- } else if (userCls) {
268
- result.class = userCls
269
- }
270
-
271
- // Helper: copy a prop's OWN descriptor (preserves getters) into result.
272
- // Falls back to a no-op if the source has no own descriptor for the key.
273
- const copyDescriptor = (key: string): void => {
274
- const d = Object.getOwnPropertyDescriptor(rawProps, key)
275
- if (d) Object.defineProperty(result, key, d)
276
- }
277
-
278
- // Component target — forward all props except as/className/class and $-prefixed
279
- if (!isDOM) {
280
- for (const key in rawProps) {
281
- if (key === 'as' || key === 'className' || key === 'class') continue
282
- if (key.charCodeAt(0) === 36) continue // $-prefixed transient
283
- copyDescriptor(key)
284
- }
285
- return result
286
- }
287
-
288
- // DOM element with custom shouldForwardProp
289
- if (customFilter) {
290
- for (const key in rawProps) {
291
- if (key === 'as' || key === 'className' || key === 'class') continue
292
- if (customFilter(key)) copyDescriptor(key)
293
- }
294
- return result
295
- }
296
-
297
- // DOM element with default filtering
298
- for (const key in rawProps) {
299
- if (key === 'as' || key === 'className' || key === 'class') continue
300
- if (key.charCodeAt(0) === 36) continue // $-prefixed transient
301
- if (key.startsWith('data-') || key.startsWith('aria-')) {
302
- copyDescriptor(key)
303
- continue
304
- }
305
- if (key in HTML_PROPS) copyDescriptor(key)
306
- }
307
- return result
308
- }
@@ -1,53 +0,0 @@
1
- /**
2
- * createGlobalStyle() — tagged template function that injects global CSS
3
- * rules (not scoped to a class name). Returns a component function that
4
- * injects styles when called and supports dynamic interpolations via
5
- * props/theme.
6
- *
7
- * Usage:
8
- * const GlobalStyle = createGlobalStyle`
9
- * body { margin: 0; font-family: ${({ theme }) => theme.font}; }
10
- * *, *::before, *::after { box-sizing: border-box; }
11
- * `
12
- */
13
- import type { ComponentFn } from '@pyreon/core'
14
- import { type Interpolation, normalizeCSS, resolve } from './resolve'
15
- import { isDynamic } from './shared'
16
- import { sheet } from './sheet'
17
- import { useTheme } from './ThemeProvider'
18
-
19
- export const createGlobalStyle = (
20
- strings: TemplateStringsArray,
21
- ...values: Interpolation[]
22
- ): ComponentFn => {
23
- const hasDynamicValues = values.some(isDynamic)
24
-
25
- // STATIC FAST PATH: compute once at creation time
26
- if (!hasDynamicValues) {
27
- const cssText = normalizeCSS(resolve(strings, values, {}))
28
-
29
- // Inject into sheet immediately. `normalizeCSS` already strips
30
- // leading/trailing whitespace, so a length check is equivalent to the
31
- // prior `.trim()` (no O(n) whitespace scan, no string allocation).
32
- // Ported from vitus-labs `be471b19`.
33
- if (cssText.length > 0) sheet.insertGlobal(cssText)
34
-
35
- const StaticGlobal: ComponentFn = () => null
36
- return StaticGlobal
37
- }
38
-
39
- // DYNAMIC PATH: resolve on every render with theme/props
40
- const DynamicGlobal: ComponentFn = (props: Record<string, any>) => {
41
- const theme = useTheme()
42
- const allProps = { ...props, theme }
43
- const cssText = normalizeCSS(resolve(strings, values, allProps))
44
-
45
- // Length check — `normalizeCSS` already trims. Ported from
46
- // vitus-labs `be471b19`.
47
- if (cssText.length > 0) sheet.insertGlobal(cssText)
48
-
49
- return null
50
- }
51
-
52
- return DynamicGlobal
53
- }
package/src/hash.ts DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * Fast FNV-1a non-cryptographic hash. Returns base-36 string for compact class names.
3
- *
4
- * 32-bit hash space → ~4.3 billion unique values. Collision probability is
5
- * negligible for typical applications (< 10,000 unique CSS rules).
6
- */
7
-
8
- /** FNV-1a offset basis — starting state for streaming hash. */
9
- export const HASH_INIT = 2166136261
10
-
11
- const FNV_PRIME = 16777619
12
-
13
- /** Feed a string segment into the running hash state.
14
- * Streaming: hashUpdate(hashUpdate(HASH_INIT, 'ab'), 'cd') === hash('abcd').
15
- */
16
- export const hashUpdate = (init: number, str: string): number => {
17
- let h = init
18
- for (let i = 0; i < str.length; i++) {
19
- h = Math.imul(h ^ str.charCodeAt(i), FNV_PRIME)
20
- }
21
- return h
22
- }
23
-
24
- /** Finalize a hash state into a base-36 class name suffix. */
25
- export const hashFinalize = (h: number): string => (h >>> 0).toString(36)
26
-
27
- /** Hash a complete string in one shot. Returns base-36 string. */
28
- export const hash = (str: string): string => hashFinalize(hashUpdate(HASH_INIT, str))
package/src/index.ts DELETED
@@ -1,15 +0,0 @@
1
- export { css } from './css'
2
- export { buildProps, filterProps } from './forward'
3
- export { createGlobalStyle } from './globalStyle'
4
- export { HASH_INIT, hash, hashFinalize, hashUpdate } from './hash'
5
- export { keyframes } from './keyframes'
6
- export type { CSSResult, Interpolation } from './resolve'
7
- export { clearNormCache, normalizeCSS, resolve, resolveValue } from './resolve'
8
- export { isDynamic } from './shared'
9
- export type { StyleSheetOptions } from './sheet'
10
- export { createSheet, StyleSheet, sheet } from './sheet'
11
- export type { StyledFunction, StyledOptions } from './styled'
12
- export { styled } from './styled'
13
- export type { DefaultTheme } from './ThemeProvider'
14
- export { ThemeContext, ThemeProvider, useTheme, useThemeAccessor } from './ThemeProvider'
15
- export { useCSS } from './useCSS'
package/src/keyframes.ts DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * keyframes() tagged template function. Creates a CSS @keyframes rule,
3
- * injects it into the stylesheet, and returns the generated animation name.
4
- *
5
- * Usage:
6
- * const fadeIn = keyframes`
7
- * from { opacity: 0; }
8
- * to { opacity: 1; }
9
- * `
10
- * // fadeIn === "pyr-kf-abc123" (deterministic, hash-based)
11
- */
12
- import { hash } from './hash'
13
- import { type Interpolation, normalizeCSS, resolve } from './resolve'
14
- import { sheet } from './sheet'
15
-
16
- class KeyframesResult {
17
- readonly name: string
18
-
19
- constructor(strings: TemplateStringsArray, values: Interpolation[]) {
20
- const body = normalizeCSS(resolve(strings, values, {}))
21
- const h = hash(body)
22
- this.name = `pyr-kf-${h}`
23
-
24
- sheet.insertKeyframes(this.name, body)
25
- }
26
-
27
- /** Returns the animation name when used in string context. */
28
- toString(): string {
29
- return this.name
30
- }
31
- }
32
-
33
- export const keyframes = (
34
- strings: TemplateStringsArray,
35
- ...values: Interpolation[]
36
- ): KeyframesResult => new KeyframesResult(strings, values)