@pyreon/rocketstyle 0.11.0 → 0.11.2
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 +14 -12
- package/src/__tests__/attrs.test.ts +190 -0
- package/src/__tests__/chaining.test.ts +86 -0
- package/src/__tests__/collection.test.ts +35 -0
- package/src/__tests__/compose.test.ts +36 -0
- package/src/__tests__/context.test.ts +200 -0
- package/src/__tests__/createLocalProvider.test.ts +248 -0
- package/src/__tests__/dimensions.test.ts +183 -0
- package/src/__tests__/e2e-styler.test.ts +291 -0
- package/src/__tests__/hooks.test.ts +207 -0
- package/src/__tests__/isRocketComponent.test.ts +48 -0
- package/src/__tests__/misc.test.ts +204 -0
- package/src/__tests__/providerConsumer.test.ts +248 -0
- package/src/__tests__/rocketstyleIntegration.test.ts +615 -0
- package/src/__tests__/themeUtils.test.ts +463 -0
- package/src/cache/LocalThemeManager.ts +14 -0
- package/src/cache/index.ts +3 -0
- package/src/constants/booleanTags.ts +32 -0
- package/src/constants/defaultDimensions.ts +23 -0
- package/src/constants/index.ts +44 -0
- package/src/context/context.ts +51 -0
- package/src/context/createLocalProvider.ts +84 -0
- package/src/context/localContext.ts +37 -0
- package/src/hoc/index.ts +3 -0
- package/src/hoc/rocketstyleAttrsHoc.ts +63 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/usePseudoState.ts +79 -0
- package/src/hooks/useTheme.ts +36 -0
- package/src/index.ts +77 -0
- package/src/init.ts +93 -0
- package/src/isRocketComponent.ts +16 -0
- package/src/rocketstyle.ts +320 -0
- package/src/types/attrs.ts +13 -0
- package/src/types/config.ts +48 -0
- package/src/types/configuration.ts +69 -0
- package/src/types/dimensions.ts +106 -0
- package/src/types/hoc.ts +5 -0
- package/src/types/pseudo.ts +19 -0
- package/src/types/rocketComponent.ts +24 -0
- package/src/types/rocketstyle.ts +156 -0
- package/src/types/styles.ts +46 -0
- package/src/types/theme.ts +19 -0
- package/src/types/utils.ts +55 -0
- package/src/utils/attrs.ts +134 -0
- package/src/utils/chaining.ts +58 -0
- package/src/utils/collection.ts +9 -0
- package/src/utils/compose.ts +11 -0
- package/src/utils/dimensions.ts +126 -0
- package/src/utils/statics.ts +44 -0
- package/src/utils/styles.ts +18 -0
- package/src/utils/theme.ts +196 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { compose, config, hoistNonReactStatics, omit, pick, render } from "@pyreon/ui-core"
|
|
2
|
+
import { LocalThemeManager } from "./cache"
|
|
3
|
+
import { CONFIG_KEYS, PSEUDO_KEYS, PSEUDO_META_KEYS, STYLING_KEYS } from "./constants"
|
|
4
|
+
import createLocalProvider from "./context/createLocalProvider"
|
|
5
|
+
import { useLocalContext } from "./context/localContext"
|
|
6
|
+
import { rocketstyleAttrsHoc } from "./hoc"
|
|
7
|
+
import { useTheme } from "./hooks"
|
|
8
|
+
import type { Configuration, ExtendedConfiguration } from "./types/configuration"
|
|
9
|
+
import type { RocketComponent } from "./types/rocketComponent"
|
|
10
|
+
import type { InnerComponentProps, RocketStyleComponent } from "./types/rocketstyle"
|
|
11
|
+
import type { ComponentFn } from "./types/utils"
|
|
12
|
+
import { calculateChainOptions, calculateStylingAttrs, pickStyledAttrs } from "./utils/attrs"
|
|
13
|
+
import { chainOptions, chainOrOptions, chainReservedKeyOptions } from "./utils/chaining"
|
|
14
|
+
import { calculateHocsFuncs } from "./utils/compose"
|
|
15
|
+
import { getDimensionsMap } from "./utils/dimensions"
|
|
16
|
+
import { createStaticsChainingEnhancers, createStaticsEnhancers } from "./utils/statics"
|
|
17
|
+
import { calculateStyles } from "./utils/styles"
|
|
18
|
+
import { getDimensionThemes, getTheme, getThemeByMode, getThemeFromChain } from "./utils/theme"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Core rocketstyle component factory. Creates a fully-featured Pyreon component
|
|
22
|
+
* that integrates theme management (with light/dark mode support), multi-tier
|
|
23
|
+
* WeakMap caching, dimension-based styling props, pseudo-state detection, and
|
|
24
|
+
* chainable static methods (`.attrs()`, `.theme()`, `.styles()`, `.config()`, etc.).
|
|
25
|
+
*
|
|
26
|
+
* In Pyreon, components are plain functions that run once per mount.
|
|
27
|
+
* No forwardRef, useMemo, useState — ref flows as a normal prop.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// --------------------------------------------------------
|
|
31
|
+
// cloneAndEnhance
|
|
32
|
+
// --------------------------------------------------------
|
|
33
|
+
type CloneAndEnhance = (
|
|
34
|
+
defaultOpts: Configuration,
|
|
35
|
+
opts: Partial<ExtendedConfiguration>,
|
|
36
|
+
) => ReturnType<typeof rocketComponent>
|
|
37
|
+
|
|
38
|
+
/** Clones the current configuration and merges new options, returning a fresh rocketComponent. */
|
|
39
|
+
const cloneAndEnhance: CloneAndEnhance = (defaultOpts, opts) =>
|
|
40
|
+
rocketComponent({
|
|
41
|
+
...defaultOpts,
|
|
42
|
+
attrs: chainOptions(opts.attrs, defaultOpts.attrs),
|
|
43
|
+
filterAttrs: [...(defaultOpts.filterAttrs ?? []), ...(opts.filterAttrs ?? [])],
|
|
44
|
+
priorityAttrs: chainOptions(opts.priorityAttrs, defaultOpts.priorityAttrs),
|
|
45
|
+
statics: { ...defaultOpts.statics, ...opts.statics },
|
|
46
|
+
compose: { ...defaultOpts.compose, ...opts.compose },
|
|
47
|
+
...chainOrOptions(CONFIG_KEYS, opts, defaultOpts),
|
|
48
|
+
...chainReservedKeyOptions([...defaultOpts.dimensionKeys, ...STYLING_KEYS], opts, defaultOpts),
|
|
49
|
+
} as Parameters<typeof rocketComponent>[0])
|
|
50
|
+
|
|
51
|
+
// --------------------------------------------------------
|
|
52
|
+
// rocketComponent
|
|
53
|
+
// --------------------------------------------------------
|
|
54
|
+
// @ts-expect-error
|
|
55
|
+
const rocketComponent: RocketComponent = (options) => {
|
|
56
|
+
const { component, styles } = options
|
|
57
|
+
const { styled } = config
|
|
58
|
+
|
|
59
|
+
const _calculateStylingAttrs = calculateStylingAttrs({
|
|
60
|
+
multiKeys: options.multiKeys,
|
|
61
|
+
useBooleans: options.useBooleans,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const componentName = options.name ?? options.component.displayName ?? options.component.name
|
|
65
|
+
|
|
66
|
+
// Create styled component with all options.styles if available.
|
|
67
|
+
// boost: true doubles the class selector so rocketstyle wrapper styles
|
|
68
|
+
// always override inner library component styles.
|
|
69
|
+
const STYLED_COMPONENT =
|
|
70
|
+
(component.IS_ROCKETSTYLE ?? options.styled !== true)
|
|
71
|
+
? component
|
|
72
|
+
: styled(component, { boost: true })`
|
|
73
|
+
${calculateStyles(styles)};
|
|
74
|
+
`
|
|
75
|
+
|
|
76
|
+
// --------------------------------------------------------
|
|
77
|
+
// COMPONENT - Final component to be rendered
|
|
78
|
+
// --------------------------------------------------------
|
|
79
|
+
const RenderComponent: ComponentFn<any> = options.provider
|
|
80
|
+
? createLocalProvider(STYLED_COMPONENT)
|
|
81
|
+
: STYLED_COMPONENT
|
|
82
|
+
|
|
83
|
+
// --------------------------------------------------------
|
|
84
|
+
// THEME - Cached & Calculated theme(s)
|
|
85
|
+
// --------------------------------------------------------
|
|
86
|
+
const ThemeManager = new LocalThemeManager()
|
|
87
|
+
|
|
88
|
+
// --------------------------------------------------------
|
|
89
|
+
// COMPOSE - high-order components
|
|
90
|
+
// --------------------------------------------------------
|
|
91
|
+
const hocsFuncs = [rocketstyleAttrsHoc(options), ...calculateHocsFuncs(options.compose)]
|
|
92
|
+
|
|
93
|
+
// --------------------------------------------------------
|
|
94
|
+
// ENHANCED COMPONENT
|
|
95
|
+
// --------------------------------------------------------
|
|
96
|
+
// In Pyreon, components are plain functions — no forwardRef needed.
|
|
97
|
+
// Ref flows as a normal prop through the chain.
|
|
98
|
+
const EnhancedComponent: ComponentFn<InnerComponentProps> = (props) => {
|
|
99
|
+
// --------------------------------------------------
|
|
100
|
+
// hover - focus - pressed state passed via context from parent component
|
|
101
|
+
// --------------------------------------------------
|
|
102
|
+
const localCtx = useLocalContext(options.consumer)
|
|
103
|
+
|
|
104
|
+
// --------------------------------------------------
|
|
105
|
+
// general theme and theme mode dark / light passed in context
|
|
106
|
+
// --------------------------------------------------
|
|
107
|
+
const { theme, mode } = useTheme(options)
|
|
108
|
+
|
|
109
|
+
// --------------------------------------------------
|
|
110
|
+
// calculate themes for all defined styling dimensions
|
|
111
|
+
// --------------------------------------------------
|
|
112
|
+
|
|
113
|
+
// BASE / DEFAULT THEME Object (cached by theme identity)
|
|
114
|
+
const baseThemeHelper = ThemeManager.baseTheme
|
|
115
|
+
if (!baseThemeHelper.has(theme)) {
|
|
116
|
+
baseThemeHelper.set(theme, getThemeFromChain(options.theme, theme))
|
|
117
|
+
}
|
|
118
|
+
const baseTheme = baseThemeHelper.get(theme)
|
|
119
|
+
|
|
120
|
+
// DIMENSION(S) THEMES Object (cached by theme identity)
|
|
121
|
+
const dimHelper = ThemeManager.dimensionsThemes
|
|
122
|
+
if (!dimHelper.has(theme)) {
|
|
123
|
+
dimHelper.set(theme, getDimensionThemes(theme, options))
|
|
124
|
+
}
|
|
125
|
+
const themes = dimHelper.get(theme)
|
|
126
|
+
|
|
127
|
+
// BASE / DEFAULT MODE THEME Object (cached by mode + baseTheme)
|
|
128
|
+
const modeBaseHelper = ThemeManager.modeBaseTheme[mode]
|
|
129
|
+
if (!modeBaseHelper.has(baseTheme)) {
|
|
130
|
+
modeBaseHelper.set(baseTheme, getThemeByMode(baseTheme, mode))
|
|
131
|
+
}
|
|
132
|
+
const currentModeBaseTheme = modeBaseHelper.get(baseTheme)
|
|
133
|
+
|
|
134
|
+
// DIMENSION(S) MODE THEMES Object (cached by mode + themes)
|
|
135
|
+
const modeDimHelper = ThemeManager.modeDimensionTheme[mode]
|
|
136
|
+
if (!modeDimHelper.has(themes)) {
|
|
137
|
+
modeDimHelper.set(themes, getThemeByMode(themes, mode))
|
|
138
|
+
}
|
|
139
|
+
const currentModeThemes = modeDimHelper.get(themes)
|
|
140
|
+
|
|
141
|
+
// --------------------------------------------------
|
|
142
|
+
// dimension map & reserved prop names
|
|
143
|
+
// --------------------------------------------------
|
|
144
|
+
const { keysMap: dimensions, keywords: reservedPropNames } = getDimensionsMap({
|
|
145
|
+
themes,
|
|
146
|
+
useBooleans: options.useBooleans,
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
const RESERVED_STYLING_PROPS_KEYS = Object.keys(reservedPropNames)
|
|
150
|
+
|
|
151
|
+
// --------------------------------------------------
|
|
152
|
+
// get final props: merged styling from context + attrs + direct props
|
|
153
|
+
// --------------------------------------------------
|
|
154
|
+
const { pseudo, ...mergeProps } = {
|
|
155
|
+
...localCtx,
|
|
156
|
+
...props,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// --------------------------------------------------
|
|
160
|
+
// pseudo rocket state
|
|
161
|
+
// --------------------------------------------------
|
|
162
|
+
const pseudoRocketstate = {
|
|
163
|
+
...pseudo,
|
|
164
|
+
...pick(props, [...PSEUDO_KEYS, ...PSEUDO_META_KEYS]),
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// --------------------------------------------------
|
|
168
|
+
// rocketstate — active dimension values
|
|
169
|
+
// --------------------------------------------------
|
|
170
|
+
const rocketstate = _calculateStylingAttrs({
|
|
171
|
+
props: pickStyledAttrs(mergeProps, reservedPropNames),
|
|
172
|
+
dimensions,
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
const finalRocketstate = { ...rocketstate, pseudo: pseudoRocketstate }
|
|
176
|
+
|
|
177
|
+
// --------------------------------------------------
|
|
178
|
+
// rocketstyle — computed theme based on active dimensions
|
|
179
|
+
// --------------------------------------------------
|
|
180
|
+
const computedRocketstyle = getTheme({
|
|
181
|
+
rocketstate,
|
|
182
|
+
themes: currentModeThemes,
|
|
183
|
+
baseTheme: currentModeBaseTheme,
|
|
184
|
+
transformKeys: options.transformKeys,
|
|
185
|
+
appTheme: theme,
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// --------------------------------------------------
|
|
189
|
+
// final props passed to WrappedComponent
|
|
190
|
+
// --------------------------------------------------
|
|
191
|
+
const finalProps: Record<string, any> = {
|
|
192
|
+
...omit(mergeProps, [...RESERVED_STYLING_PROPS_KEYS, ...PSEUDO_KEYS, ...options.filterAttrs]),
|
|
193
|
+
...(options.passProps ? pick(mergeProps, options.passProps) : {}),
|
|
194
|
+
// ref flows as a normal prop in Pyreon
|
|
195
|
+
ref: props.ref,
|
|
196
|
+
$rocketstyle: computedRocketstyle,
|
|
197
|
+
$rocketstate: finalRocketstate,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// development debugging
|
|
201
|
+
if (process.env.NODE_ENV !== "production") {
|
|
202
|
+
finalProps["data-rocketstyle"] = componentName
|
|
203
|
+
|
|
204
|
+
if (options.DEBUG) {
|
|
205
|
+
const debugPayload = {
|
|
206
|
+
component: componentName,
|
|
207
|
+
rocketstate: finalRocketstate,
|
|
208
|
+
rocketstyle: computedRocketstyle,
|
|
209
|
+
dimensions,
|
|
210
|
+
mode,
|
|
211
|
+
reservedPropNames: RESERVED_STYLING_PROPS_KEYS,
|
|
212
|
+
filteredAttrs: options.filterAttrs,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// biome-ignore lint/suspicious/noConsole: debug logging controlled by DEBUG option
|
|
216
|
+
console.debug(`[rocketstyle] ${componentName} render:`, debugPayload)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return RenderComponent(finalProps)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ------------------------------------------------------
|
|
224
|
+
// Compose HOC chain and create final component
|
|
225
|
+
// ------------------------------------------------------
|
|
226
|
+
const FinalComponent: RocketStyleComponent = compose(...hocsFuncs)(EnhancedComponent)
|
|
227
|
+
FinalComponent.IS_ROCKETSTYLE = true
|
|
228
|
+
FinalComponent.displayName = componentName
|
|
229
|
+
|
|
230
|
+
hoistNonReactStatics(FinalComponent as Record<string, unknown>, options.component)
|
|
231
|
+
|
|
232
|
+
// ------------------------------------------------------
|
|
233
|
+
// enhance for chaining methods
|
|
234
|
+
// ------------------------------------------------------
|
|
235
|
+
createStaticsChainingEnhancers({
|
|
236
|
+
context: FinalComponent,
|
|
237
|
+
dimensionKeys: options.dimensionKeys,
|
|
238
|
+
func: cloneAndEnhance,
|
|
239
|
+
options,
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
FinalComponent.IS_ROCKETSTYLE = true
|
|
243
|
+
FinalComponent.displayName = componentName
|
|
244
|
+
FinalComponent.meta = {}
|
|
245
|
+
|
|
246
|
+
// ------------------------------------------------------
|
|
247
|
+
// enhance for statics
|
|
248
|
+
// ------------------------------------------------------
|
|
249
|
+
createStaticsEnhancers({
|
|
250
|
+
context: FinalComponent.meta,
|
|
251
|
+
options: options.statics,
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
// Also assign statics directly onto the component so they are
|
|
255
|
+
// discoverable via `"key" in Component` checks (e.g. _documentType).
|
|
256
|
+
createStaticsEnhancers({
|
|
257
|
+
context: FinalComponent,
|
|
258
|
+
options: options.statics,
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
Object.assign(FinalComponent, {
|
|
262
|
+
attrs: (attrs: any, { priority, filter }: any = {}) => {
|
|
263
|
+
const result: Record<string, any> = {}
|
|
264
|
+
|
|
265
|
+
if (filter) {
|
|
266
|
+
result.filterAttrs = filter
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (priority) {
|
|
270
|
+
result.priorityAttrs = attrs as ExtendedConfiguration["priorityAttrs"]
|
|
271
|
+
|
|
272
|
+
return cloneAndEnhance(options, result)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
result.attrs = attrs as ExtendedConfiguration["attrs"]
|
|
276
|
+
|
|
277
|
+
return cloneAndEnhance(options, result)
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
config: (opts: any = {}) => {
|
|
281
|
+
const result = pick(opts, CONFIG_KEYS) as ExtendedConfiguration
|
|
282
|
+
|
|
283
|
+
return cloneAndEnhance(options, result)
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
statics: (opts: any) => cloneAndEnhance(options, { statics: opts }),
|
|
287
|
+
|
|
288
|
+
getStaticDimensions: (theme: any) => {
|
|
289
|
+
const themes = getDimensionThemes(theme, options)
|
|
290
|
+
|
|
291
|
+
const { keysMap, keywords } = getDimensionsMap({
|
|
292
|
+
themes,
|
|
293
|
+
useBooleans: options.useBooleans,
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
dimensions: keysMap,
|
|
298
|
+
keywords,
|
|
299
|
+
useBooleans: options.useBooleans,
|
|
300
|
+
multiKeys: options.multiKeys,
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
getDefaultAttrs: (props: any, theme: any, mode: any) =>
|
|
305
|
+
calculateChainOptions(options.attrs)([
|
|
306
|
+
props,
|
|
307
|
+
theme,
|
|
308
|
+
{
|
|
309
|
+
render,
|
|
310
|
+
mode,
|
|
311
|
+
isDark: mode === "light",
|
|
312
|
+
isLight: mode === "dark",
|
|
313
|
+
},
|
|
314
|
+
]),
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
return FinalComponent
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export default rocketComponent
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { render } from "@pyreon/ui-core"
|
|
2
|
+
import type { ThemeModeKeys } from "./theme"
|
|
3
|
+
|
|
4
|
+
export type AttrsCb<A, T> = (
|
|
5
|
+
props: Partial<A>,
|
|
6
|
+
theme: T,
|
|
7
|
+
helpers: {
|
|
8
|
+
mode?: ThemeModeKeys
|
|
9
|
+
isDark?: boolean
|
|
10
|
+
isLight?: boolean
|
|
11
|
+
createElement: typeof render
|
|
12
|
+
},
|
|
13
|
+
) => Partial<A>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DimensionBooleanAttrs, Dimensions, ExtractDimensions, TDKP } from "./dimensions"
|
|
2
|
+
import type { PseudoState } from "./pseudo"
|
|
3
|
+
import type { ElementType, TObj } from "./utils"
|
|
4
|
+
|
|
5
|
+
// --------------------------------------------------------
|
|
6
|
+
// CONFIG
|
|
7
|
+
// --------------------------------------------------------
|
|
8
|
+
export type RocketComponentType = ElementType & {
|
|
9
|
+
IS_ROCKETSTYLE: true
|
|
10
|
+
$$rocketstyle: Record<string, unknown>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type RocketProviderState<T extends RocketComponentType | TObj | unknown = unknown> =
|
|
14
|
+
T extends RocketComponentType ? Partial<T["$$rocketstyle"]> & { pseudo: PseudoState } : T
|
|
15
|
+
|
|
16
|
+
export type ConsumerCtxCBValue<
|
|
17
|
+
T extends RocketComponentType,
|
|
18
|
+
D extends Dimensions,
|
|
19
|
+
DKP extends TDKP,
|
|
20
|
+
> = (
|
|
21
|
+
attrs: RocketProviderState<T>,
|
|
22
|
+
) => DKP extends TDKP ? Partial<ExtractDimensions<D, DKP> & { pseudo: PseudoState }> : TObj
|
|
23
|
+
|
|
24
|
+
export type ConsumerCtxCb<D extends Dimensions, DKP extends TDKP = TDKP> = <
|
|
25
|
+
T extends RocketComponentType,
|
|
26
|
+
>(
|
|
27
|
+
attrs: ConsumerCtxCBValue<T, D, DKP>,
|
|
28
|
+
) => ReturnType<ConsumerCtxCBValue<T, D, DKP>>
|
|
29
|
+
|
|
30
|
+
export type ConsumerCb<D extends Dimensions, DKP extends TDKP = TDKP> = (
|
|
31
|
+
ctx: ConsumerCtxCb<D, DKP>,
|
|
32
|
+
) => ReturnType<ConsumerCtxCb<D, DKP>>
|
|
33
|
+
|
|
34
|
+
export type ConfigAttrs<
|
|
35
|
+
C extends ElementType | unknown,
|
|
36
|
+
D extends Dimensions,
|
|
37
|
+
DKP extends TDKP,
|
|
38
|
+
UB extends boolean,
|
|
39
|
+
> = Partial<{
|
|
40
|
+
name: string
|
|
41
|
+
component: C
|
|
42
|
+
provider: boolean
|
|
43
|
+
consumer: ConsumerCb<D, DKP>
|
|
44
|
+
DEBUG: boolean
|
|
45
|
+
inversed: boolean
|
|
46
|
+
passProps: UB extends true ? keyof DimensionBooleanAttrs<D, DKP>[] : never
|
|
47
|
+
styled: boolean
|
|
48
|
+
}>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ConsumerCb } from "./config"
|
|
2
|
+
import type { Dimensions, MultiKeys } from "./dimensions"
|
|
3
|
+
import type { PseudoProps } from "./pseudo"
|
|
4
|
+
import type { StylesCbArray } from "./styles"
|
|
5
|
+
import type { ArrayOfKeys, ArrayOfValues, ElementType, TFn } from "./utils"
|
|
6
|
+
|
|
7
|
+
export type __ROCKETSTYLE__ = {
|
|
8
|
+
dimensions: Record<string, string>
|
|
9
|
+
reservedPropNames: Record<string, true>
|
|
10
|
+
baseTheme: Record<string, unknown>
|
|
11
|
+
themes: Record<string, unknown>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type OptionFunc = (...arg: unknown[]) => Record<string, unknown>
|
|
15
|
+
|
|
16
|
+
export type InitConfiguration<C, D> = {
|
|
17
|
+
name?: string | undefined
|
|
18
|
+
component: C
|
|
19
|
+
useBooleans: boolean
|
|
20
|
+
dimensions: D
|
|
21
|
+
dimensionKeys: ArrayOfKeys<D>
|
|
22
|
+
dimensionValues: ArrayOfValues<D>
|
|
23
|
+
multiKeys: MultiKeys
|
|
24
|
+
transformKeys: Partial<Record<string, true>>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type Configuration<
|
|
28
|
+
C = ElementType | unknown,
|
|
29
|
+
D extends Dimensions = Dimensions,
|
|
30
|
+
> = InitConfiguration<C, D> & {
|
|
31
|
+
provider?: boolean | undefined
|
|
32
|
+
consumer?: ConsumerCb<D> | undefined
|
|
33
|
+
DEBUG?: boolean | undefined
|
|
34
|
+
inversed?: boolean | undefined
|
|
35
|
+
passProps?: string[] | undefined
|
|
36
|
+
styled?: boolean | undefined
|
|
37
|
+
|
|
38
|
+
// array chaining options
|
|
39
|
+
attrs: OptionFunc[]
|
|
40
|
+
priorityAttrs: OptionFunc[]
|
|
41
|
+
filterAttrs: string[]
|
|
42
|
+
theme: OptionFunc[]
|
|
43
|
+
styles: StylesCbArray
|
|
44
|
+
compose: Record<string, TFn | null | undefined | false>
|
|
45
|
+
statics: Record<string, any>
|
|
46
|
+
} & Record<string, any>
|
|
47
|
+
|
|
48
|
+
export type ExtendedConfiguration<
|
|
49
|
+
C = ElementType | unknown,
|
|
50
|
+
D extends Dimensions = Dimensions,
|
|
51
|
+
> = InitConfiguration<C, D> & {
|
|
52
|
+
provider?: boolean | undefined
|
|
53
|
+
consumer?: ConsumerCb<D> | undefined
|
|
54
|
+
DEBUG?: boolean | undefined
|
|
55
|
+
inversed?: boolean | undefined
|
|
56
|
+
passProps?: string[] | undefined
|
|
57
|
+
styled?: boolean | undefined
|
|
58
|
+
|
|
59
|
+
// array chaining options
|
|
60
|
+
attrs: OptionFunc
|
|
61
|
+
priorityAttrs: OptionFunc
|
|
62
|
+
filterAttrs: string[]
|
|
63
|
+
theme: OptionFunc
|
|
64
|
+
styles: StylesCbArray
|
|
65
|
+
compose: Record<string, TFn | null | undefined | false>
|
|
66
|
+
statics: Record<string, any>
|
|
67
|
+
} & Record<string, any>
|
|
68
|
+
|
|
69
|
+
export type DefaultProps = Partial<PseudoProps>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { DefaultDimensions } from "../constants/defaultDimensions"
|
|
2
|
+
import type { Css } from "./styles"
|
|
3
|
+
import type { ThemeModeCallback } from "./theme"
|
|
4
|
+
import type { CallBackParam, NullableKeys, ReturnCbParam, Spread, TObj, ValueOf } from "./utils"
|
|
5
|
+
|
|
6
|
+
export type { DefaultDimensions }
|
|
7
|
+
|
|
8
|
+
export type ExtractNullableDimensionKeys<T> = {
|
|
9
|
+
[P in keyof T as T[P] extends false ? never : P]: T[P]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type ExtractDimensionKey<T extends DimensionValue> = T extends DimensionValueObj
|
|
13
|
+
? T["propName"]
|
|
14
|
+
: T
|
|
15
|
+
|
|
16
|
+
export type ExtractDimensionMulti<T extends DimensionValue> = T extends DimensionValueObj
|
|
17
|
+
? true
|
|
18
|
+
: false
|
|
19
|
+
|
|
20
|
+
export type ExtractDimensionAttrsKeys<D extends Dimensions> = {
|
|
21
|
+
[I in keyof D]: ExtractDimensionKey<D[I]>
|
|
22
|
+
}[keyof D]
|
|
23
|
+
|
|
24
|
+
export type DimensionValuePrimitive = string
|
|
25
|
+
export type DimensionValueObj = {
|
|
26
|
+
propName: string
|
|
27
|
+
multi?: boolean
|
|
28
|
+
/** When true, this dimension is evaluated last and its values receive the accumulated theme as argument. */
|
|
29
|
+
transform?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type DimensionValue = DimensionValuePrimitive | DimensionValueObj
|
|
33
|
+
export type Dimensions = Record<string, DimensionValue>
|
|
34
|
+
|
|
35
|
+
export type MultiKeys<T extends Dimensions = Dimensions> = Partial<
|
|
36
|
+
Record<ExtractDimensionKey<T[keyof T]>, true>
|
|
37
|
+
>
|
|
38
|
+
|
|
39
|
+
type DeepPartial<T> = {
|
|
40
|
+
[K in keyof T]?: T[K] extends (...args: any[]) => any
|
|
41
|
+
? T[K]
|
|
42
|
+
: NonNullable<T[K]> extends Record<string, any>
|
|
43
|
+
? DeepPartial<NonNullable<T[K]>> | Extract<T[K], null>
|
|
44
|
+
: T[K]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type DimensionResult<CT, T = any> = Record<
|
|
48
|
+
string,
|
|
49
|
+
| boolean
|
|
50
|
+
| null
|
|
51
|
+
| DeepPartial<CT>
|
|
52
|
+
| ((theme: CT, appTheme: T, mode: ThemeModeCallback, css: Css) => DeepPartial<CT>)
|
|
53
|
+
>
|
|
54
|
+
export type DimensionObj<CT, T = any> = DimensionResult<CT, T>
|
|
55
|
+
|
|
56
|
+
export type DimensionCb<T, CT> = (
|
|
57
|
+
theme: T,
|
|
58
|
+
mode: ThemeModeCallback,
|
|
59
|
+
css: Css,
|
|
60
|
+
) => DimensionResult<CT, T>
|
|
61
|
+
|
|
62
|
+
export type DimensionCallbackParam<T, CT> = DimensionObj<CT, T> | DimensionCb<T, CT>
|
|
63
|
+
|
|
64
|
+
export type DimensionReturn<P, A> = P extends TObj ? A & P : A
|
|
65
|
+
|
|
66
|
+
export type TDKP = Record<string, unknown>
|
|
67
|
+
|
|
68
|
+
export type DimensionProps<
|
|
69
|
+
K extends DimensionValue,
|
|
70
|
+
D extends Dimensions,
|
|
71
|
+
P extends CallBackParam,
|
|
72
|
+
DKP extends TDKP,
|
|
73
|
+
> = {
|
|
74
|
+
[I in ExtractDimensionKey<D[keyof D]>]: I extends ExtractDimensionKey<K>
|
|
75
|
+
? ExtractNullableDimensionKeys<Spread<[DKP[I], NullableKeys<ReturnCbParam<P>>]>>
|
|
76
|
+
: DKP[I]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type DimensionTypesHelper<D extends Dimensions, DKP extends TDKP> = {
|
|
80
|
+
[I in ExtractDimensionKey<D[keyof D]> & keyof DKP]: keyof DKP[I]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export type DimensionObjAttrs<D extends Dimensions, DKP extends TDKP> = {
|
|
84
|
+
[I in ExtractDimensionKey<D[keyof D]> & keyof DKP]: ExtractDimensionMulti<
|
|
85
|
+
D[I & keyof D]
|
|
86
|
+
> extends true
|
|
87
|
+
? Array<keyof DKP[I]>
|
|
88
|
+
: keyof DKP[I]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type DimensionBooleanAttrs<D extends Dimensions, DKP extends TDKP> = Partial<
|
|
92
|
+
Record<ValueOf<DimensionTypesHelper<D, DKP>>, boolean>
|
|
93
|
+
>
|
|
94
|
+
|
|
95
|
+
export type ExtractDimensionProps<
|
|
96
|
+
D extends Dimensions,
|
|
97
|
+
DKP extends TDKP,
|
|
98
|
+
UB extends boolean,
|
|
99
|
+
> = UB extends true
|
|
100
|
+
? Partial<ExtractNullableDimensionKeys<DimensionObjAttrs<D, DKP> & DimensionBooleanAttrs<D, DKP>>>
|
|
101
|
+
: Partial<ExtractNullableDimensionKeys<DimensionObjAttrs<D, DKP>>>
|
|
102
|
+
|
|
103
|
+
export type ExtractDimensions<
|
|
104
|
+
D extends Dimensions,
|
|
105
|
+
DKP extends TDKP,
|
|
106
|
+
> = ExtractNullableDimensionKeys<DimensionObjAttrs<D, DKP>>
|
package/src/types/hoc.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type PseudoActions = {
|
|
2
|
+
onMouseEnter: (e: MouseEvent) => void
|
|
3
|
+
onMouseLeave: (e: MouseEvent) => void
|
|
4
|
+
onMouseDown: (e: MouseEvent) => void
|
|
5
|
+
onMouseUp: (e: MouseEvent) => void
|
|
6
|
+
onFocus: (e: FocusEvent) => void
|
|
7
|
+
onBlur: (e: FocusEvent) => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type PseudoState = {
|
|
11
|
+
active: boolean
|
|
12
|
+
hover: boolean
|
|
13
|
+
focus: boolean
|
|
14
|
+
pressed: boolean
|
|
15
|
+
disabled: boolean
|
|
16
|
+
readOnly: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type PseudoProps = Partial<PseudoState & PseudoActions>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Configuration } from "./configuration"
|
|
2
|
+
import type { DefaultDimensions, Dimensions } from "./dimensions"
|
|
3
|
+
import type { RocketStyleComponent } from "./rocketstyle"
|
|
4
|
+
import type { ElementType, ExtractProps, TObj } from "./utils"
|
|
5
|
+
|
|
6
|
+
export type RocketComponent<
|
|
7
|
+
C extends ElementType = ElementType,
|
|
8
|
+
T extends TObj = {},
|
|
9
|
+
CSS extends TObj = {},
|
|
10
|
+
D extends Dimensions = DefaultDimensions,
|
|
11
|
+
UB extends boolean = boolean,
|
|
12
|
+
> = (props: Configuration<C, D>) => RocketStyleComponent<
|
|
13
|
+
// keep original component props + extract dimension props
|
|
14
|
+
ExtractProps<C>,
|
|
15
|
+
// set default extending props
|
|
16
|
+
{},
|
|
17
|
+
T,
|
|
18
|
+
CSS,
|
|
19
|
+
{},
|
|
20
|
+
{},
|
|
21
|
+
D,
|
|
22
|
+
UB,
|
|
23
|
+
{}
|
|
24
|
+
>
|