@pyreon/rocketstyle 0.24.4 → 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.
- package/package.json +8 -10
- package/src/__tests__/attrs-overloads.test.ts +0 -97
- package/src/__tests__/attrs.test.ts +0 -190
- package/src/__tests__/cache-key-boolean-collision.test.ts +0 -54
- package/src/__tests__/chaining.test.ts +0 -86
- package/src/__tests__/collection.test.ts +0 -35
- package/src/__tests__/compose.test.ts +0 -36
- package/src/__tests__/context.test.ts +0 -200
- package/src/__tests__/createLocalProvider.test.ts +0 -280
- package/src/__tests__/dimensions.test.ts +0 -183
- package/src/__tests__/e2e-styler.test.ts +0 -299
- package/src/__tests__/hooks.test.ts +0 -178
- package/src/__tests__/isRocketComponent.test.ts +0 -48
- package/src/__tests__/memo-cap.test.ts +0 -174
- package/src/__tests__/minimal-theme.test.ts +0 -62
- package/src/__tests__/misc.test.ts +0 -204
- package/src/__tests__/native-marker.test.ts +0 -9
- package/src/__tests__/providerConsumer.test.ts +0 -183
- package/src/__tests__/reactive-props-preservation.test.ts +0 -195
- package/src/__tests__/rocketstyle.browser.test.tsx +0 -481
- package/src/__tests__/rocketstyleIntegration.test.ts +0 -711
- package/src/__tests__/theme-integration.test.tsx +0 -254
- package/src/__tests__/themeUtils.test.ts +0 -463
- package/src/cache/LocalThemeManager.ts +0 -14
- package/src/cache/index.ts +0 -3
- package/src/constants/booleanTags.ts +0 -32
- package/src/constants/defaultDimensions.ts +0 -23
- package/src/constants/index.ts +0 -59
- package/src/context/context.ts +0 -70
- package/src/context/createLocalProvider.ts +0 -97
- package/src/context/localContext.ts +0 -37
- package/src/env.d.ts +0 -6
- package/src/hoc/index.ts +0 -3
- package/src/hoc/rocketstyleAttrsHoc.ts +0 -76
- package/src/hooks/index.ts +0 -4
- package/src/hooks/usePseudoState.ts +0 -79
- package/src/hooks/useTheme.ts +0 -48
- package/src/index.ts +0 -95
- package/src/init.ts +0 -93
- package/src/isRocketComponent.ts +0 -16
- package/src/rocketstyle.ts +0 -640
- package/src/types/attrs.ts +0 -23
- package/src/types/config.ts +0 -48
- package/src/types/configuration.ts +0 -69
- package/src/types/dimensions.ts +0 -109
- package/src/types/hoc.ts +0 -5
- package/src/types/pseudo.ts +0 -19
- package/src/types/rocketComponent.ts +0 -24
- package/src/types/rocketstyle.ts +0 -220
- package/src/types/styles.ts +0 -61
- package/src/types/theme.ts +0 -18
- package/src/types/utils.ts +0 -98
- package/src/utils/attrs.ts +0 -181
- package/src/utils/chaining.ts +0 -58
- package/src/utils/collection.ts +0 -9
- package/src/utils/compose.ts +0 -11
- package/src/utils/dimensions.ts +0 -126
- package/src/utils/statics.ts +0 -44
- package/src/utils/styles.ts +0 -18
- 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
|
-
}
|
package/src/cache/index.ts
DELETED
|
@@ -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
|
package/src/constants/index.ts
DELETED
|
@@ -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
|
package/src/context/context.ts
DELETED
|
@@ -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
|