@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.
Files changed (51) hide show
  1. package/package.json +14 -12
  2. package/src/__tests__/attrs.test.ts +190 -0
  3. package/src/__tests__/chaining.test.ts +86 -0
  4. package/src/__tests__/collection.test.ts +35 -0
  5. package/src/__tests__/compose.test.ts +36 -0
  6. package/src/__tests__/context.test.ts +200 -0
  7. package/src/__tests__/createLocalProvider.test.ts +248 -0
  8. package/src/__tests__/dimensions.test.ts +183 -0
  9. package/src/__tests__/e2e-styler.test.ts +291 -0
  10. package/src/__tests__/hooks.test.ts +207 -0
  11. package/src/__tests__/isRocketComponent.test.ts +48 -0
  12. package/src/__tests__/misc.test.ts +204 -0
  13. package/src/__tests__/providerConsumer.test.ts +248 -0
  14. package/src/__tests__/rocketstyleIntegration.test.ts +615 -0
  15. package/src/__tests__/themeUtils.test.ts +463 -0
  16. package/src/cache/LocalThemeManager.ts +14 -0
  17. package/src/cache/index.ts +3 -0
  18. package/src/constants/booleanTags.ts +32 -0
  19. package/src/constants/defaultDimensions.ts +23 -0
  20. package/src/constants/index.ts +44 -0
  21. package/src/context/context.ts +51 -0
  22. package/src/context/createLocalProvider.ts +84 -0
  23. package/src/context/localContext.ts +37 -0
  24. package/src/hoc/index.ts +3 -0
  25. package/src/hoc/rocketstyleAttrsHoc.ts +63 -0
  26. package/src/hooks/index.ts +4 -0
  27. package/src/hooks/usePseudoState.ts +79 -0
  28. package/src/hooks/useTheme.ts +36 -0
  29. package/src/index.ts +77 -0
  30. package/src/init.ts +93 -0
  31. package/src/isRocketComponent.ts +16 -0
  32. package/src/rocketstyle.ts +320 -0
  33. package/src/types/attrs.ts +13 -0
  34. package/src/types/config.ts +48 -0
  35. package/src/types/configuration.ts +69 -0
  36. package/src/types/dimensions.ts +106 -0
  37. package/src/types/hoc.ts +5 -0
  38. package/src/types/pseudo.ts +19 -0
  39. package/src/types/rocketComponent.ts +24 -0
  40. package/src/types/rocketstyle.ts +156 -0
  41. package/src/types/styles.ts +46 -0
  42. package/src/types/theme.ts +19 -0
  43. package/src/types/utils.ts +55 -0
  44. package/src/utils/attrs.ts +134 -0
  45. package/src/utils/chaining.ts +58 -0
  46. package/src/utils/collection.ts +9 -0
  47. package/src/utils/compose.ts +11 -0
  48. package/src/utils/dimensions.ts +126 -0
  49. package/src/utils/statics.ts +44 -0
  50. package/src/utils/styles.ts +18 -0
  51. 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>>
@@ -0,0 +1,5 @@
1
+ import type { ElementType } from "./utils"
2
+
3
+ export type GenericHoc = (component: ElementType) => ElementType
4
+
5
+ export type ComposeParam = Record<string, GenericHoc | null | undefined | false>
@@ -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
+ >