@pyreon/rocketstyle 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 (60) hide show
  1. package/package.json +8 -10
  2. package/src/__tests__/attrs-overloads.test.ts +0 -97
  3. package/src/__tests__/attrs.test.ts +0 -190
  4. package/src/__tests__/cache-key-boolean-collision.test.ts +0 -54
  5. package/src/__tests__/chaining.test.ts +0 -86
  6. package/src/__tests__/collection.test.ts +0 -35
  7. package/src/__tests__/compose.test.ts +0 -36
  8. package/src/__tests__/context.test.ts +0 -200
  9. package/src/__tests__/createLocalProvider.test.ts +0 -280
  10. package/src/__tests__/dimensions.test.ts +0 -183
  11. package/src/__tests__/e2e-styler.test.ts +0 -299
  12. package/src/__tests__/hooks.test.ts +0 -178
  13. package/src/__tests__/isRocketComponent.test.ts +0 -48
  14. package/src/__tests__/memo-cap.test.ts +0 -174
  15. package/src/__tests__/minimal-theme.test.ts +0 -62
  16. package/src/__tests__/misc.test.ts +0 -204
  17. package/src/__tests__/native-marker.test.ts +0 -9
  18. package/src/__tests__/providerConsumer.test.ts +0 -183
  19. package/src/__tests__/reactive-props-preservation.test.ts +0 -195
  20. package/src/__tests__/rocketstyle.browser.test.tsx +0 -481
  21. package/src/__tests__/rocketstyleIntegration.test.ts +0 -711
  22. package/src/__tests__/theme-integration.test.tsx +0 -254
  23. package/src/__tests__/themeUtils.test.ts +0 -463
  24. package/src/cache/LocalThemeManager.ts +0 -14
  25. package/src/cache/index.ts +0 -3
  26. package/src/constants/booleanTags.ts +0 -32
  27. package/src/constants/defaultDimensions.ts +0 -23
  28. package/src/constants/index.ts +0 -59
  29. package/src/context/context.ts +0 -70
  30. package/src/context/createLocalProvider.ts +0 -97
  31. package/src/context/localContext.ts +0 -37
  32. package/src/env.d.ts +0 -6
  33. package/src/hoc/index.ts +0 -3
  34. package/src/hoc/rocketstyleAttrsHoc.ts +0 -76
  35. package/src/hooks/index.ts +0 -4
  36. package/src/hooks/usePseudoState.ts +0 -79
  37. package/src/hooks/useTheme.ts +0 -48
  38. package/src/index.ts +0 -95
  39. package/src/init.ts +0 -93
  40. package/src/isRocketComponent.ts +0 -16
  41. package/src/rocketstyle.ts +0 -640
  42. package/src/types/attrs.ts +0 -23
  43. package/src/types/config.ts +0 -48
  44. package/src/types/configuration.ts +0 -69
  45. package/src/types/dimensions.ts +0 -109
  46. package/src/types/hoc.ts +0 -5
  47. package/src/types/pseudo.ts +0 -19
  48. package/src/types/rocketComponent.ts +0 -24
  49. package/src/types/rocketstyle.ts +0 -220
  50. package/src/types/styles.ts +0 -61
  51. package/src/types/theme.ts +0 -18
  52. package/src/types/utils.ts +0 -98
  53. package/src/utils/attrs.ts +0 -181
  54. package/src/utils/chaining.ts +0 -58
  55. package/src/utils/collection.ts +0 -9
  56. package/src/utils/compose.ts +0 -11
  57. package/src/utils/dimensions.ts +0 -126
  58. package/src/utils/statics.ts +0 -44
  59. package/src/utils/styles.ts +0 -18
  60. package/src/utils/theme.ts +0 -211
@@ -1,463 +0,0 @@
1
- import {
2
- calculateChainOptions,
3
- getDimensionThemes,
4
- getTheme,
5
- getThemeByMode,
6
- getThemeFromChain,
7
- themeModeCallback,
8
- } from '../utils/theme'
9
-
10
- describe('themeModeCallback', () => {
11
- it('returns light value for light mode', () => {
12
- const cb = themeModeCallback('lightVal', 'darkVal')
13
- expect(cb('light')).toBe('lightVal')
14
- })
15
-
16
- it('returns light value when mode is falsy', () => {
17
- const cb = themeModeCallback('lightVal', 'darkVal')
18
- expect(cb(undefined as any)).toBe('lightVal')
19
- expect(cb('' as any)).toBe('lightVal')
20
- })
21
-
22
- it('returns dark value for dark mode', () => {
23
- const cb = themeModeCallback('lightVal', 'darkVal')
24
- expect(cb('dark')).toBe('darkVal')
25
- })
26
- })
27
-
28
- describe('getThemeFromChain', () => {
29
- it('returns empty for empty array', () => {
30
- expect(getThemeFromChain([], {})).toEqual({})
31
- })
32
-
33
- it('returns empty for null', () => {
34
- expect(getThemeFromChain(null, {})).toEqual({})
35
- })
36
-
37
- it('returns empty for undefined', () => {
38
- expect(getThemeFromChain(undefined, {})).toEqual({})
39
- })
40
-
41
- it('evaluates chain of callbacks and deep-merges results', () => {
42
- const fn1 = (_theme: any) => ({ color: 'blue' })
43
- const fn2 = (theme: any) => ({ bg: theme.primary })
44
- const result = getThemeFromChain([fn1, fn2], { primary: 'red' })
45
- expect(result).toEqual({ color: 'blue', bg: 'red' })
46
- })
47
-
48
- it('later callbacks override earlier ones', () => {
49
- const fn1 = () => ({ color: 'blue' })
50
- const fn2 = () => ({ color: 'red' })
51
- const result = getThemeFromChain([fn1, fn2], {})
52
- expect(result).toEqual({ color: 'red' })
53
- })
54
-
55
- it('passes themeModeCallback and config.css to each callback', () => {
56
- const fn = vi.fn(() => ({}))
57
- getThemeFromChain([fn], { rootSize: 16 })
58
- expect(fn).toHaveBeenCalledWith({ rootSize: 16 }, expect.any(Function), expect.anything())
59
- })
60
- })
61
-
62
- describe('getDimensionThemes', () => {
63
- it('returns empty for empty dimensions', () => {
64
- expect(getDimensionThemes({}, { dimensions: {} })).toEqual({})
65
- })
66
-
67
- it('returns empty when dimensions is falsy', () => {
68
- expect(getDimensionThemes({}, { dimensions: undefined })).toEqual({})
69
- })
70
-
71
- it('processes dimension theme chains', () => {
72
- const theme = { primaryColor: 'blue' }
73
- const options = {
74
- dimensions: { states: 'state' },
75
- states: [
76
- (t: any) => ({
77
- primary: { color: t.primaryColor },
78
- secondary: { color: 'green' },
79
- }),
80
- ],
81
- }
82
- const result = getDimensionThemes(theme, options)
83
- expect(result.state).toEqual({
84
- primary: { color: 'blue' },
85
- secondary: { color: 'green' },
86
- })
87
- })
88
-
89
- it('skips dimensions without callback arrays', () => {
90
- const options = {
91
- dimensions: { states: 'state', sizes: 'size' },
92
- states: [() => ({ primary: { color: 'red' } })],
93
- }
94
- const result = getDimensionThemes({}, options)
95
- expect(result.state).toEqual({ primary: { color: 'red' } })
96
- expect(result.size).toBeUndefined()
97
- })
98
-
99
- it('strips nullable values from results', () => {
100
- const options = {
101
- dimensions: { states: 'state' },
102
- states: [() => ({ primary: { color: 'red' }, secondary: null })],
103
- }
104
- const result = getDimensionThemes({}, options)
105
- expect(result.state.primary).toEqual({ color: 'red' })
106
- expect(result.state.secondary).toBeUndefined()
107
- })
108
-
109
- it('handles multi-key dimensions', () => {
110
- const options = {
111
- dimensions: { multiple: { propName: 'multiple', multi: true } },
112
- multiple: [() => ({ a: { weight: 'bold' } })],
113
- }
114
- const result = getDimensionThemes({}, options)
115
- expect(result.multiple).toEqual({ a: { weight: 'bold' } })
116
- })
117
-
118
- it('skips empty callback arrays', () => {
119
- const options = {
120
- dimensions: { states: 'state' },
121
- states: [],
122
- }
123
- const result = getDimensionThemes({}, options)
124
- expect(result.state).toBeUndefined()
125
- })
126
- })
127
-
128
- describe('calculateChainOptions (theme)', () => {
129
- it('returns empty for null', () => {
130
- expect(calculateChainOptions(null, [])).toEqual({})
131
- })
132
-
133
- it('returns empty for undefined', () => {
134
- expect(calculateChainOptions(undefined, [])).toEqual({})
135
- })
136
-
137
- it('returns empty for empty array', () => {
138
- expect(calculateChainOptions([], [])).toEqual({})
139
- })
140
-
141
- it('evaluates chain and deep-merges results', () => {
142
- const fn1 = () => ({ nested: { a: 1 } })
143
- const fn2 = () => ({ nested: { b: 2 } })
144
- const result = calculateChainOptions([fn1, fn2], [])
145
- expect(result).toEqual({ nested: { a: 1, b: 2 } })
146
- })
147
-
148
- it('passes args to each function', () => {
149
- const fn = vi.fn(() => ({}))
150
- calculateChainOptions([fn], ['arg1', 'arg2'])
151
- expect(fn).toHaveBeenCalledWith('arg1', 'arg2')
152
- })
153
- })
154
-
155
- describe('getTheme', () => {
156
- it('returns baseTheme when rocketstate has no matching dimension themes', () => {
157
- const result = getTheme({
158
- rocketstate: { state: 'unknown' },
159
- themes: { state: {} },
160
- baseTheme: { color: 'blue' },
161
- })
162
- expect(result.color).toBe('blue')
163
- })
164
-
165
- it('merges dimension theme into baseTheme', () => {
166
- const result = getTheme({
167
- rocketstate: { state: 'primary' },
168
- themes: { state: { primary: { color: 'red' } } },
169
- baseTheme: { color: 'blue', bg: 'white' },
170
- })
171
- expect(result.color).toBe('red')
172
- expect(result.bg).toBe('white')
173
- })
174
-
175
- it('handles array values for multi-key dimensions', () => {
176
- const result = getTheme({
177
- rocketstate: { multiple: ['a', 'b'] },
178
- themes: {
179
- multiple: { a: { weight: 'bold' }, b: { style: 'italic' } },
180
- },
181
- baseTheme: {},
182
- })
183
- expect(result.weight).toBe('bold')
184
- expect(result.style).toBe('italic')
185
- })
186
-
187
- it('later dimensions override earlier ones', () => {
188
- const result = getTheme({
189
- rocketstate: { state: 'primary', size: 'large' },
190
- themes: {
191
- state: { primary: { fontSize: 14 } },
192
- size: { large: { fontSize: 20 } },
193
- },
194
- baseTheme: {},
195
- })
196
- expect(result.fontSize).toBe(20)
197
- })
198
-
199
- it('does not mutate baseTheme', () => {
200
- const baseTheme = { color: 'blue' }
201
- getTheme({
202
- rocketstate: { state: 'primary' },
203
- themes: { state: { primary: { color: 'red' } } },
204
- baseTheme,
205
- })
206
- expect(baseTheme.color).toBe('blue')
207
- })
208
- })
209
-
210
- describe('getTheme with transform dimensions', () => {
211
- it('applies transform function values after all static dimensions', () => {
212
- const result = getTheme({
213
- rocketstate: { state: 'primary', modifier: 'outlined' },
214
- themes: {
215
- state: { primary: { backgroundColor: 'blue', color: 'white' } },
216
- modifier: {
217
- outlined: (theme: any) => ({
218
- color: theme.backgroundColor,
219
- backgroundColor: 'transparent',
220
- }),
221
- },
222
- },
223
- baseTheme: { border: 'none' },
224
- transformKeys: { modifier: true },
225
- })
226
- expect(result.color).toBe('blue')
227
- expect(result.backgroundColor).toBe('transparent')
228
- expect(result.border).toBe('none')
229
- })
230
-
231
- it('transform receives accumulated theme, appTheme, mode, and css', () => {
232
- const transformFn = vi.fn((theme: any) => ({ derived: theme.color }))
233
- const appTheme = { colors: { primary: 'blue' } }
234
- getTheme({
235
- rocketstate: { state: 'primary', modifier: 'test' },
236
- themes: {
237
- state: { primary: { color: 'red' } },
238
- modifier: { test: transformFn },
239
- },
240
- baseTheme: { bg: 'white' },
241
- transformKeys: { modifier: true },
242
- appTheme,
243
- })
244
- expect(transformFn).toHaveBeenCalledWith(
245
- expect.objectContaining({ bg: 'white', color: 'red' }),
246
- appTheme,
247
- expect.any(Function),
248
- expect.anything(),
249
- )
250
- })
251
-
252
- it('transform can use appTheme values', () => {
253
- const appTheme = { spacing: { lg: '2rem' } }
254
- const result = getTheme({
255
- rocketstate: { modifier: 'withSpacing' },
256
- themes: {
257
- modifier: {
258
- withSpacing: (_theme: any, app: any) => ({
259
- padding: app.spacing.lg,
260
- }),
261
- },
262
- },
263
- baseTheme: { color: 'red' },
264
- transformKeys: { modifier: true },
265
- appTheme,
266
- })
267
- expect(result.padding).toBe('2rem')
268
- expect(result.color).toBe('red')
269
- })
270
-
271
- it('supports multiple transform values (multi dimension)', () => {
272
- const result = getTheme({
273
- rocketstate: { modifier: ['outlined', 'rounded'] },
274
- themes: {
275
- modifier: {
276
- outlined: (theme: any) => ({
277
- color: theme.backgroundColor,
278
- backgroundColor: 'transparent',
279
- }),
280
- rounded: () => ({ borderRadius: '999px' }),
281
- },
282
- },
283
- baseTheme: { backgroundColor: 'blue', color: 'white' },
284
- transformKeys: { modifier: true },
285
- })
286
- expect(result.color).toBe('blue')
287
- expect(result.backgroundColor).toBe('transparent')
288
- expect(result.borderRadius).toBe('999px')
289
- })
290
-
291
- it('transforms compose — later transform sees earlier transform results', () => {
292
- const result = getTheme({
293
- rocketstate: { modifier: ['first', 'second'] },
294
- themes: {
295
- modifier: {
296
- first: () => ({ step: 'one' }),
297
- second: (theme: any) => ({ sawStep: theme.step }),
298
- },
299
- },
300
- baseTheme: {},
301
- transformKeys: { modifier: true },
302
- })
303
- expect(result.step).toBe('one')
304
- expect(result.sawStep).toBe('one')
305
- })
306
-
307
- it('works without transformKeys (backward compatible)', () => {
308
- const result = getTheme({
309
- rocketstate: { state: 'primary' },
310
- themes: { state: { primary: { color: 'red' } } },
311
- baseTheme: { bg: 'white' },
312
- })
313
- expect(result.color).toBe('red')
314
- expect(result.bg).toBe('white')
315
- })
316
-
317
- it('non-transform dimension treats function values as regular merge (not called as transform)', () => {
318
- const fn = vi.fn(() => ({ color: 'red' }))
319
- getTheme({
320
- rocketstate: { state: 'primary' },
321
- themes: { state: { primary: fn } },
322
- baseTheme: {},
323
- transformKeys: {},
324
- })
325
- expect(fn).not.toHaveBeenCalled()
326
- })
327
-
328
- it('transform dimension not in rocketstate is ignored', () => {
329
- const transformFn = vi.fn(() => ({ color: 'red' }))
330
- const result = getTheme({
331
- rocketstate: { state: 'primary' },
332
- themes: {
333
- state: { primary: { color: 'blue' } },
334
- modifier: { outlined: transformFn },
335
- },
336
- baseTheme: {},
337
- transformKeys: { modifier: true },
338
- })
339
- expect(transformFn).not.toHaveBeenCalled()
340
- expect(result.color).toBe('blue')
341
- })
342
-
343
- it('transform does not mutate baseTheme', () => {
344
- const baseTheme = { color: 'blue', bg: 'white' }
345
- getTheme({
346
- rocketstate: { modifier: 'flip' },
347
- themes: {
348
- modifier: {
349
- flip: (theme: any) => ({ color: theme.bg, bg: theme.color }),
350
- },
351
- },
352
- baseTheme,
353
- transformKeys: { modifier: true },
354
- })
355
- expect(baseTheme.color).toBe('blue')
356
- expect(baseTheme.bg).toBe('white')
357
- })
358
-
359
- it('transform with deep nested theme values', () => {
360
- const result = getTheme({
361
- rocketstate: { state: 'primary', modifier: 'outlined' },
362
- themes: {
363
- state: {
364
- primary: {
365
- backgroundColor: 'blue',
366
- color: 'white',
367
- hover: { backgroundColor: 'darkblue' },
368
- },
369
- },
370
- modifier: {
371
- outlined: (theme: any) => ({
372
- color: theme.backgroundColor,
373
- backgroundColor: 'transparent',
374
- hover: {
375
- backgroundColor: theme.backgroundColor,
376
- color: theme.color,
377
- },
378
- }),
379
- },
380
- },
381
- baseTheme: {},
382
- transformKeys: { modifier: true },
383
- })
384
- expect(result.color).toBe('blue')
385
- expect(result.backgroundColor).toBe('transparent')
386
- const hover = result.hover as Record<string, any>
387
- expect(hover.backgroundColor).toBe('blue')
388
- expect(hover.color).toBe('white')
389
- })
390
-
391
- it('appTheme defaults to empty object when not provided', () => {
392
- const transformFn = vi.fn(() => ({}))
393
- getTheme({
394
- rocketstate: { modifier: 'test' },
395
- themes: { modifier: { test: transformFn } },
396
- baseTheme: {},
397
- transformKeys: { modifier: true },
398
- })
399
- expect(transformFn).toHaveBeenCalledWith(
400
- expect.any(Object),
401
- {},
402
- expect.any(Function),
403
- expect.anything(),
404
- )
405
- })
406
-
407
- it('transform with mode callback produces light/dark values', () => {
408
- const result = getTheme({
409
- rocketstate: { modifier: 'themed' },
410
- themes: {
411
- modifier: {
412
- themed: (_theme: any, _app: any, mode: any) => ({
413
- shadow: mode('0 2px 4px rgba(0,0,0,0.1)', 'none'),
414
- }),
415
- },
416
- },
417
- baseTheme: {},
418
- transformKeys: { modifier: true },
419
- })
420
- expect(typeof result.shadow).toBe('function')
421
- })
422
- })
423
-
424
- describe('getThemeByMode', () => {
425
- it('returns scalar values as-is', () => {
426
- const result = getThemeByMode({ color: 'red', size: 16 }, 'light')
427
- expect(result).toEqual({ color: 'red', size: 16 })
428
- })
429
-
430
- it('recursively processes nested objects', () => {
431
- const result = getThemeByMode({ nested: { color: 'red' } }, 'light')
432
- expect(result).toEqual({ nested: { color: 'red' } })
433
- })
434
-
435
- it('resolves mode callbacks for light', () => {
436
- const cb = themeModeCallback('lightColor', 'darkColor')
437
- const result: any = getThemeByMode({ color: cb }, 'light')
438
- expect(result.color).toBe('lightColor')
439
- })
440
-
441
- it('resolves mode callbacks for dark', () => {
442
- const cb = themeModeCallback('lightColor', 'darkColor')
443
- const result: any = getThemeByMode({ color: cb }, 'dark')
444
- expect(result.color).toBe('darkColor')
445
- })
446
-
447
- it('resolves nested mode callbacks', () => {
448
- const cb = themeModeCallback('lightBg', 'darkBg')
449
- const result: any = getThemeByMode({ nested: { bg: cb } }, 'light')
450
- expect(result.nested.bg).toBe('lightBg')
451
- })
452
-
453
- it('handles mixed values and mode callbacks', () => {
454
- const cb = themeModeCallback('#fff', '#000')
455
- const result: any = getThemeByMode(
456
- { bg: cb, fontSize: 16, nested: { color: 'static' } },
457
- 'dark',
458
- )
459
- expect(result.bg).toBe('#000')
460
- expect(result.fontSize).toBe(16)
461
- expect(result.nested.color).toBe('static')
462
- })
463
- })
@@ -1,14 +0,0 @@
1
- /**
2
- * WeakMap-based multi-tier cache for computed theme objects.
3
- * Maintains separate caches for base themes, dimension themes,
4
- * and their light/dark mode variants to avoid recalculation on re-renders.
5
- */
6
- export default class ThemeManager {
7
- baseTheme = new WeakMap()
8
-
9
- dimensionsThemes = new WeakMap()
10
-
11
- modeBaseTheme = { light: new WeakMap(), dark: new WeakMap() }
12
-
13
- modeDimensionTheme = { light: new WeakMap(), dark: new WeakMap() }
14
- }
@@ -1,3 +0,0 @@
1
- import LocalThemeManager from './LocalThemeManager'
2
-
3
- export { LocalThemeManager }
@@ -1,32 +0,0 @@
1
- /**
2
- * List of standard HTML boolean attributes. Used to identify props
3
- * that are valid boolean DOM attributes and should not be filtered
4
- * out as unknown styling props.
5
- */
6
- export default [
7
- 'allowFullScreen',
8
- 'allowPaymentRequest',
9
- 'async',
10
- 'autoFocus',
11
- 'autoPlay',
12
- 'checked',
13
- 'controls',
14
- 'default',
15
- 'defer',
16
- 'disabled',
17
- 'formNoValidate',
18
- 'hidden',
19
- 'isMap',
20
- 'itemScope',
21
- 'loop',
22
- 'multiple',
23
- 'muted',
24
- 'noModule',
25
- 'noValidate',
26
- 'open',
27
- 'readOnly',
28
- 'required',
29
- 'reversed',
30
- 'selected',
31
- 'typeMustMatch',
32
- ]
@@ -1,23 +0,0 @@
1
- /**
2
- * Default dimension configuration for rocketstyle components.
3
- * Defines four built-in dimensions: `states`, `sizes`, `variants`,
4
- * and `multiple` (a multi-select dimension).
5
- */
6
- const DEFAULT_DIMENSIONS = {
7
- states: 'state',
8
- sizes: 'size',
9
- variants: 'variant',
10
- multiple: {
11
- propName: 'multiple',
12
- multi: true,
13
- },
14
- modifiers: {
15
- propName: 'modifier',
16
- multi: true,
17
- transform: true,
18
- },
19
- } as const
20
-
21
- export type DefaultDimensions = typeof DEFAULT_DIMENSIONS
22
-
23
- export default DEFAULT_DIMENSIONS
@@ -1,59 +0,0 @@
1
- // `import.meta.env.DEV` is provided by Vite/Rolldown at build time and
2
- // literal-replaced so prod bundles tree-shake the dev branch to zero bytes.
3
- // Typed through a narrowing interface so downstream packages don't need
4
- // `vite/client` in their tsconfigs to type-check this file transitively.
5
- /** Tree-shakeable dev-mode flag. `true` in dev, `false` (dead code eliminated) in prod. */
6
- export const __DEV__: boolean = process.env.NODE_ENV !== 'production'
7
-
8
- /** Default theme mode used when no mode is provided via context. */
9
- export const MODE_DEFAULT = 'light'
10
-
11
- /** Pseudo-state interaction keys tracked for styling (hover, active, focus, pressed). */
12
- export const PSEUDO_KEYS = ['hover', 'active', 'focus', 'pressed'] as const
13
-
14
- /** Meta pseudo-state keys representing non-interactive states (disabled, readOnly). */
15
- export const PSEUDO_META_KEYS = ['disabled', 'readOnly'] as const
16
-
17
- /**
18
- * Pre-merged interaction + meta keys. Hoisted from `rocketstyle.ts`'s
19
- * `rocketComponent` definition scope to module scope so the merged
20
- * 6-element array is allocated ONCE per process, not once per
21
- * rocketstyle definition. Ported from vitus-labs `00fdadc2`.
22
- */
23
- export const PSEUDO_AND_META_KEYS = [...PSEUDO_KEYS, ...PSEUDO_META_KEYS] as const
24
-
25
- /** Supported theme mode flags. */
26
- export const THEME_MODES = {
27
- light: true,
28
- dark: true,
29
- } as const
30
-
31
- /** Maps each theme mode to its inverse (light -> dark, dark -> light). */
32
- export const THEME_MODES_INVERSED = {
33
- dark: 'light',
34
- light: 'dark',
35
- } as const
36
-
37
- /** Reserved configuration keys accepted by the `.config()` chaining method. */
38
- export const CONFIG_KEYS = [
39
- 'provider',
40
- 'consumer',
41
- 'DEBUG',
42
- 'name',
43
- 'component',
44
- 'inversed',
45
- 'passProps',
46
- 'styled',
47
- ] as const
48
-
49
- /** Keys for theme and styles chaining methods. */
50
- export const STYLING_KEYS = ['theme', 'styles'] as const
51
- export const STATIC_KEYS = [...STYLING_KEYS, 'compose'] as const
52
-
53
- /** Union of all reserved keys that cannot be used as dimension names. */
54
- export const ALL_RESERVED_KEYS = [
55
- ...Object.keys(THEME_MODES),
56
- ...CONFIG_KEYS,
57
- ...STATIC_KEYS,
58
- 'attrs',
59
- ] as const
@@ -1,70 +0,0 @@
1
- import type { VNodeChild } from '@pyreon/core'
2
- import { nativeCompat, useContext } from '@pyreon/core'
3
- import { Provider as CoreProvider, context } from '@pyreon/ui-core'
4
- import { MODE_DEFAULT, THEME_MODES_INVERSED } from '../constants'
5
-
6
- // Both `rootSize` and `breakpoints` are OPTIONAL — the rest of the chain
7
- // handles their absence: `enrichTheme` defaults rootSize to 16,
8
- // `makeItResponsive` short-circuits to plain CSS when breakpoints are
9
- // empty, and `value()` defaults rootSize to 16 internally. Marking
10
- // either as required here over-constrained user themes downstream
11
- // (e.g. a minimal `{ colors: { primary: '#228be6' } }` theme passed
12
- // to the public Provider was a TS error even though it works at runtime).
13
- //
14
- // Shape matches `@pyreon/unistyle` `PyreonTheme` and the downstream
15
- // `@pyreon/ui-core` Provider's `Partial<...>`-wrapped theme — `?:` with
16
- // no explicit `| undefined` so the downstream Partial composition holds
17
- // under `exactOptionalPropertyTypes: true`.
18
- type Theme = {
19
- rootSize?: number
20
- breakpoints?: Record<string, number>
21
- } & Record<string, unknown>
22
-
23
- export type TProvider = {
24
- children: VNodeChild
25
- theme?: Theme | undefined
26
- mode?: 'light' | 'dark' | undefined
27
- inversed?: boolean | undefined
28
- provider?: ((props: Record<string, unknown>) => VNodeChild) | undefined
29
- }
30
-
31
- /**
32
- * Top-level theme and mode provider for rocketstyle components.
33
- * Reads the parent context, merges incoming props, and resolves
34
- * the active mode (with optional inversion for nested dark/light switching).
35
- *
36
- * In Pyreon, context is provided via provide() instead of React.Provider.
37
- */
38
- const Provider = ({ provider = CoreProvider, inversed, ...props }: TProvider): VNodeChild => {
39
- const getCtx = useContext(context)
40
- const ctx = getCtx()
41
-
42
- const merged = { ...ctx, ...props, provider } as unknown as TProvider & Record<string, unknown>
43
- const { theme, mode, provider: RocketstyleProvider, children } = merged
44
-
45
- let newMode = MODE_DEFAULT
46
-
47
- if (mode) {
48
- newMode = inversed ? THEME_MODES_INVERSED[mode] : mode
49
- }
50
-
51
- const FinalProvider = RocketstyleProvider ?? CoreProvider
52
- const result = FinalProvider({
53
- mode: newMode,
54
- isDark: newMode === 'dark',
55
- isLight: newMode === 'light',
56
- ...(theme !== undefined ? { theme } : {}),
57
- provider,
58
- children,
59
- })
60
-
61
- return result ?? null
62
- }
63
-
64
- // Mark as native — reads useContext() and delegates to CoreProvider, both
65
- // of which need Pyreon's setup frame.
66
- nativeCompat(Provider)
67
-
68
- export { context }
69
-
70
- export default Provider