@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,84 @@
|
|
|
1
|
+
import { provide } from "@pyreon/core"
|
|
2
|
+
import { signal } from "@pyreon/reactivity"
|
|
3
|
+
import type { PseudoProps } from "../types/pseudo"
|
|
4
|
+
import type { ComponentFn } from "../types/utils"
|
|
5
|
+
import { localContext } from "./localContext"
|
|
6
|
+
|
|
7
|
+
type Props = PseudoProps & Record<string, any>
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Higher-order component that wraps a component with a LocalProvider,
|
|
11
|
+
* detecting pseudo-states (hover, focus, pressed) via mouse/focus events
|
|
12
|
+
* and broadcasting them through local context to child rocketstyle components.
|
|
13
|
+
*
|
|
14
|
+
* In Pyreon, context is provided via provide(), and state is managed
|
|
15
|
+
* with signals instead of useState.
|
|
16
|
+
*/
|
|
17
|
+
const createLocalProvider = (WrappedComponent: ComponentFn<any>) => {
|
|
18
|
+
const HOCComponent: ComponentFn<Props> = ({
|
|
19
|
+
onMouseEnter,
|
|
20
|
+
onMouseLeave,
|
|
21
|
+
onMouseUp,
|
|
22
|
+
onMouseDown,
|
|
23
|
+
onFocus,
|
|
24
|
+
onBlur,
|
|
25
|
+
$rocketstate,
|
|
26
|
+
...props
|
|
27
|
+
}) => {
|
|
28
|
+
const hover = signal(false)
|
|
29
|
+
const focus = signal(false)
|
|
30
|
+
const pressed = signal(false)
|
|
31
|
+
|
|
32
|
+
const pseudoState = () => ({
|
|
33
|
+
hover: hover(),
|
|
34
|
+
focus: focus(),
|
|
35
|
+
pressed: pressed(),
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const events = {
|
|
39
|
+
onMouseEnter: (e: MouseEvent) => {
|
|
40
|
+
hover.set(true)
|
|
41
|
+
if (onMouseEnter) onMouseEnter(e)
|
|
42
|
+
},
|
|
43
|
+
onMouseLeave: (e: MouseEvent) => {
|
|
44
|
+
hover.set(false)
|
|
45
|
+
pressed.set(false)
|
|
46
|
+
if (onMouseLeave) onMouseLeave(e)
|
|
47
|
+
},
|
|
48
|
+
onMouseDown: (e: MouseEvent) => {
|
|
49
|
+
pressed.set(true)
|
|
50
|
+
if (onMouseDown) onMouseDown(e)
|
|
51
|
+
},
|
|
52
|
+
onMouseUp: (e: MouseEvent) => {
|
|
53
|
+
pressed.set(false)
|
|
54
|
+
if (onMouseUp) onMouseUp(e)
|
|
55
|
+
},
|
|
56
|
+
onFocus: (e: FocusEvent) => {
|
|
57
|
+
focus.set(true)
|
|
58
|
+
if (onFocus) onFocus(e)
|
|
59
|
+
},
|
|
60
|
+
onBlur: (e: FocusEvent) => {
|
|
61
|
+
focus.set(false)
|
|
62
|
+
if (onBlur) onBlur(e)
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const updatedState = {
|
|
67
|
+
...$rocketstate,
|
|
68
|
+
pseudo: { ...$rocketstate?.pseudo, ...pseudoState() },
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Provide local context for child rocketstyle components
|
|
72
|
+
provide(localContext, updatedState)
|
|
73
|
+
|
|
74
|
+
return WrappedComponent({
|
|
75
|
+
...props,
|
|
76
|
+
...events,
|
|
77
|
+
$rocketstate: updatedState,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return HOCComponent
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default createLocalProvider
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createContext, useContext } from "@pyreon/core"
|
|
2
|
+
import type { PseudoState } from "../types/pseudo"
|
|
3
|
+
|
|
4
|
+
type LocalContext = Partial<
|
|
5
|
+
{
|
|
6
|
+
pseudo: PseudoState
|
|
7
|
+
} & Record<string, string>
|
|
8
|
+
>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Local context for propagating pseudo-state (hover, focus, pressed)
|
|
12
|
+
* and additional styling attributes from a parent provider component
|
|
13
|
+
* to its rocketstyle children.
|
|
14
|
+
*/
|
|
15
|
+
const localContext = createContext<LocalContext>({})
|
|
16
|
+
|
|
17
|
+
const EMPTY_CTX = { pseudo: {} } as LocalContext
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Retrieves the local pseudo-state context. When a consumer callback
|
|
21
|
+
* is provided, it transforms the raw context; otherwise returns defaults.
|
|
22
|
+
*
|
|
23
|
+
* In Pyreon, components are plain functions that run once — no useMemo needed.
|
|
24
|
+
*/
|
|
25
|
+
type UseLocalContext = (consumer: any) => LocalContext
|
|
26
|
+
export const useLocalContext: UseLocalContext = (consumer) => {
|
|
27
|
+
const ctx = useContext(localContext)
|
|
28
|
+
|
|
29
|
+
if (!consumer) return EMPTY_CTX
|
|
30
|
+
|
|
31
|
+
const result = consumer((callback: any) => callback(ctx))
|
|
32
|
+
return { pseudo: {}, ...result }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { localContext }
|
|
36
|
+
|
|
37
|
+
export default localContext
|
package/src/hoc/index.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { render } from "@pyreon/ui-core"
|
|
2
|
+
import { useTheme } from "../hooks"
|
|
3
|
+
import type { Configuration } from "../types/configuration"
|
|
4
|
+
import type { ComponentFn } from "../types/utils"
|
|
5
|
+
import { calculateChainOptions, removeUndefinedProps } from "../utils/attrs"
|
|
6
|
+
|
|
7
|
+
export type RocketStyleHOC = ({
|
|
8
|
+
inversed,
|
|
9
|
+
attrs,
|
|
10
|
+
priorityAttrs,
|
|
11
|
+
}: Pick<Configuration, "inversed" | "attrs" | "priorityAttrs">) => (
|
|
12
|
+
WrappedComponent: ComponentFn<any>,
|
|
13
|
+
) => ComponentFn<any>
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* HOC that resolves the `.attrs()` chain before the inner component renders.
|
|
17
|
+
* Evaluates both regular and priority attrs callbacks with the current theme
|
|
18
|
+
* and mode, then merges the results with explicit props (priority attrs
|
|
19
|
+
* are applied first, regular attrs can be overridden by direct props).
|
|
20
|
+
*
|
|
21
|
+
* In Pyreon, there is no forwardRef — ref flows as a normal prop.
|
|
22
|
+
* Components are plain functions.
|
|
23
|
+
*/
|
|
24
|
+
const rocketStyleHOC: RocketStyleHOC = ({ inversed, attrs, priorityAttrs }) => {
|
|
25
|
+
const calculateAttrs = calculateChainOptions(attrs)
|
|
26
|
+
const calculatePriorityAttrs = calculateChainOptions(priorityAttrs)
|
|
27
|
+
|
|
28
|
+
const Enhanced = (WrappedComponent: ComponentFn<any>) => {
|
|
29
|
+
const HOCComponent: ComponentFn<any> = (props) => {
|
|
30
|
+
const { theme, mode, isDark, isLight } = useTheme({
|
|
31
|
+
inversed,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const callbackParams = [theme, { render, mode, isDark, isLight }]
|
|
35
|
+
|
|
36
|
+
// Remove undefined props not to override potential default props
|
|
37
|
+
const filteredProps = removeUndefinedProps(props)
|
|
38
|
+
|
|
39
|
+
const prioritizedAttrs = calculatePriorityAttrs([filteredProps, ...callbackParams])
|
|
40
|
+
|
|
41
|
+
const finalAttrs = calculateAttrs([
|
|
42
|
+
{
|
|
43
|
+
...prioritizedAttrs,
|
|
44
|
+
...filteredProps,
|
|
45
|
+
},
|
|
46
|
+
...callbackParams,
|
|
47
|
+
])
|
|
48
|
+
|
|
49
|
+
const finalProps = {
|
|
50
|
+
...prioritizedAttrs,
|
|
51
|
+
...finalAttrs,
|
|
52
|
+
...filteredProps,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return WrappedComponent(finalProps)
|
|
56
|
+
}
|
|
57
|
+
return HOCComponent
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return Enhanced
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default rocketStyleHOC
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { signal } from "@pyreon/reactivity"
|
|
2
|
+
import type { PseudoActions, PseudoState } from "../types/pseudo"
|
|
3
|
+
|
|
4
|
+
type UsePseudoState = ({
|
|
5
|
+
onMouseEnter,
|
|
6
|
+
onMouseLeave,
|
|
7
|
+
onMouseDown,
|
|
8
|
+
onMouseUp,
|
|
9
|
+
onFocus,
|
|
10
|
+
onBlur,
|
|
11
|
+
}: Partial<PseudoActions>) => {
|
|
12
|
+
state: Pick<PseudoState, "hover" | "focus" | "pressed">
|
|
13
|
+
events: PseudoActions
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Tracks hover, focus, and pressed pseudo-states via mouse and focus
|
|
18
|
+
* event handlers. Returns the current state flags and wrapped event
|
|
19
|
+
* callbacks that preserve any user-provided handlers.
|
|
20
|
+
*
|
|
21
|
+
* In Pyreon, uses signals instead of useState. Components are plain
|
|
22
|
+
* functions that run once — no useCallback/useMemo needed.
|
|
23
|
+
*/
|
|
24
|
+
const usePseudoState: UsePseudoState = ({
|
|
25
|
+
onBlur,
|
|
26
|
+
onFocus,
|
|
27
|
+
onMouseDown,
|
|
28
|
+
onMouseEnter,
|
|
29
|
+
onMouseLeave,
|
|
30
|
+
onMouseUp,
|
|
31
|
+
}) => {
|
|
32
|
+
const hover = signal(false)
|
|
33
|
+
const focus = signal(false)
|
|
34
|
+
const pressed = signal(false)
|
|
35
|
+
|
|
36
|
+
const state = {
|
|
37
|
+
get hover() {
|
|
38
|
+
return hover()
|
|
39
|
+
},
|
|
40
|
+
get focus() {
|
|
41
|
+
return focus()
|
|
42
|
+
},
|
|
43
|
+
get pressed() {
|
|
44
|
+
return pressed()
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const events: PseudoActions = {
|
|
49
|
+
onMouseEnter: (e) => {
|
|
50
|
+
hover.set(true)
|
|
51
|
+
if (onMouseEnter) onMouseEnter(e)
|
|
52
|
+
},
|
|
53
|
+
onMouseLeave: (e) => {
|
|
54
|
+
hover.set(false)
|
|
55
|
+
pressed.set(false)
|
|
56
|
+
if (onMouseLeave) onMouseLeave(e)
|
|
57
|
+
},
|
|
58
|
+
onMouseDown: (e) => {
|
|
59
|
+
pressed.set(true)
|
|
60
|
+
if (onMouseDown) onMouseDown(e)
|
|
61
|
+
},
|
|
62
|
+
onMouseUp: (e) => {
|
|
63
|
+
pressed.set(false)
|
|
64
|
+
if (onMouseUp) onMouseUp(e)
|
|
65
|
+
},
|
|
66
|
+
onFocus: (e) => {
|
|
67
|
+
focus.set(true)
|
|
68
|
+
if (onFocus) onFocus(e)
|
|
69
|
+
},
|
|
70
|
+
onBlur: (e) => {
|
|
71
|
+
focus.set(false)
|
|
72
|
+
if (onBlur) onBlur(e)
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return { state, events }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export default usePseudoState
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useContext } from "@pyreon/core"
|
|
2
|
+
import { THEME_MODES_INVERSED } from "../constants"
|
|
3
|
+
import { context } from "../context/context"
|
|
4
|
+
import type { ThemeModeKeys } from "../types/theme"
|
|
5
|
+
|
|
6
|
+
type Context = {
|
|
7
|
+
theme: Record<string, unknown>
|
|
8
|
+
mode: ThemeModeKeys
|
|
9
|
+
isDark: boolean
|
|
10
|
+
isLight: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type UseThemeAttrs = ({ inversed }: { inversed?: boolean | undefined }) => Context
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves the current theme object and resolved mode from context.
|
|
17
|
+
* Supports mode inversion so nested components can flip between
|
|
18
|
+
* light and dark without a new provider.
|
|
19
|
+
*
|
|
20
|
+
* In Pyreon, components run once — no useMemo needed.
|
|
21
|
+
*/
|
|
22
|
+
const useThemeAttrs: UseThemeAttrs = ({ inversed }) => {
|
|
23
|
+
const {
|
|
24
|
+
theme = {},
|
|
25
|
+
mode: ctxMode = "light",
|
|
26
|
+
isDark: ctxDark,
|
|
27
|
+
} = useContext<Context>(context) || {}
|
|
28
|
+
|
|
29
|
+
const mode = inversed ? THEME_MODES_INVERSED[ctxMode] : ctxMode
|
|
30
|
+
const isDark = inversed ? !ctxDark : ctxDark
|
|
31
|
+
const isLight = !isDark
|
|
32
|
+
|
|
33
|
+
return { theme, mode, isDark, isLight }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default useThemeAttrs
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { TProvider } from "./context/context"
|
|
2
|
+
import Provider, { context } from "./context/context"
|
|
3
|
+
import type { Rocketstyle } from "./init"
|
|
4
|
+
import rocketstyle from "./init"
|
|
5
|
+
import type { IsRocketComponent } from "./isRocketComponent"
|
|
6
|
+
import isRocketComponent from "./isRocketComponent"
|
|
7
|
+
import type { AttrsCb } from "./types/attrs"
|
|
8
|
+
import type {
|
|
9
|
+
ConfigAttrs,
|
|
10
|
+
ConsumerCb,
|
|
11
|
+
ConsumerCtxCBValue,
|
|
12
|
+
ConsumerCtxCb,
|
|
13
|
+
RocketComponentType,
|
|
14
|
+
RocketProviderState,
|
|
15
|
+
} from "./types/config"
|
|
16
|
+
import type { DefaultProps } from "./types/configuration"
|
|
17
|
+
import type {
|
|
18
|
+
DimensionCallbackParam,
|
|
19
|
+
DimensionProps,
|
|
20
|
+
Dimensions,
|
|
21
|
+
DimensionValue,
|
|
22
|
+
ExtractDimensionProps,
|
|
23
|
+
ExtractDimensions,
|
|
24
|
+
TDKP,
|
|
25
|
+
} from "./types/dimensions"
|
|
26
|
+
import type { ComposeParam, GenericHoc } from "./types/hoc"
|
|
27
|
+
import type { IRocketStyleComponent, RocketStyleComponent } from "./types/rocketstyle"
|
|
28
|
+
import type { RocketStyleInterpolationProps, StylesCb, StylesDefault } from "./types/styles"
|
|
29
|
+
import type {
|
|
30
|
+
ThemeCb,
|
|
31
|
+
ThemeDefault,
|
|
32
|
+
ThemeMode,
|
|
33
|
+
ThemeModeCallback,
|
|
34
|
+
ThemeModeKeys,
|
|
35
|
+
} from "./types/theme"
|
|
36
|
+
import type { ComponentFn, ElementType, ExtractProps, MergeTypes, TObj } from "./types/utils"
|
|
37
|
+
|
|
38
|
+
export type {
|
|
39
|
+
AttrsCb,
|
|
40
|
+
ComponentFn,
|
|
41
|
+
ComposeParam,
|
|
42
|
+
ConfigAttrs,
|
|
43
|
+
ConsumerCb,
|
|
44
|
+
ConsumerCtxCBValue,
|
|
45
|
+
ConsumerCtxCb,
|
|
46
|
+
DefaultProps,
|
|
47
|
+
DimensionCallbackParam,
|
|
48
|
+
DimensionProps,
|
|
49
|
+
Dimensions,
|
|
50
|
+
DimensionValue,
|
|
51
|
+
ElementType,
|
|
52
|
+
ExtractDimensionProps,
|
|
53
|
+
ExtractDimensions,
|
|
54
|
+
ExtractProps,
|
|
55
|
+
GenericHoc,
|
|
56
|
+
IRocketStyleComponent,
|
|
57
|
+
IsRocketComponent,
|
|
58
|
+
MergeTypes,
|
|
59
|
+
RocketComponentType,
|
|
60
|
+
RocketProviderState,
|
|
61
|
+
RocketStyleComponent,
|
|
62
|
+
RocketStyleInterpolationProps,
|
|
63
|
+
Rocketstyle,
|
|
64
|
+
StylesCb,
|
|
65
|
+
StylesDefault,
|
|
66
|
+
TDKP,
|
|
67
|
+
ThemeCb,
|
|
68
|
+
ThemeDefault,
|
|
69
|
+
ThemeMode,
|
|
70
|
+
ThemeModeCallback,
|
|
71
|
+
ThemeModeKeys,
|
|
72
|
+
TObj,
|
|
73
|
+
TProvider,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { context, isRocketComponent, Provider, rocketstyle }
|
|
77
|
+
export default rocketstyle
|
package/src/init.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { isEmpty } from "@pyreon/ui-core"
|
|
2
|
+
import { ALL_RESERVED_KEYS } from "./constants"
|
|
3
|
+
import defaultDimensions from "./constants/defaultDimensions"
|
|
4
|
+
import rocketComponent from "./rocketstyle"
|
|
5
|
+
import type { DefaultDimensions, Dimensions } from "./types/dimensions"
|
|
6
|
+
import type { RocketComponent } from "./types/rocketComponent"
|
|
7
|
+
import type { ElementType } from "./types/utils"
|
|
8
|
+
import {
|
|
9
|
+
getDimensionsValues,
|
|
10
|
+
getKeys,
|
|
11
|
+
getMultipleDimensions,
|
|
12
|
+
getTransformDimensions,
|
|
13
|
+
} from "./utils/dimensions"
|
|
14
|
+
|
|
15
|
+
export type Rocketstyle = <
|
|
16
|
+
const D extends Dimensions = DefaultDimensions,
|
|
17
|
+
UB extends boolean = true,
|
|
18
|
+
>({
|
|
19
|
+
dimensions,
|
|
20
|
+
useBooleans,
|
|
21
|
+
}?: {
|
|
22
|
+
dimensions?: D
|
|
23
|
+
useBooleans?: UB
|
|
24
|
+
}) => <C extends ElementType>({
|
|
25
|
+
name,
|
|
26
|
+
component,
|
|
27
|
+
}: {
|
|
28
|
+
name: string
|
|
29
|
+
component: C
|
|
30
|
+
}) => ReturnType<RocketComponent<C, {}, {}, D, UB>>
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Factory initializer for rocketstyle components. Validates dimension
|
|
34
|
+
* configurations against reserved keys, then delegates to the core
|
|
35
|
+
* `rocketComponent` builder with pre-computed dimension metadata.
|
|
36
|
+
*/
|
|
37
|
+
type InitErrors = Partial<{
|
|
38
|
+
component: string
|
|
39
|
+
name: string
|
|
40
|
+
dimensions: string
|
|
41
|
+
invalidDimensions: string
|
|
42
|
+
}>
|
|
43
|
+
|
|
44
|
+
const validateInit = (name: string, component: unknown, dimensions: Dimensions) => {
|
|
45
|
+
const errors: InitErrors = {}
|
|
46
|
+
|
|
47
|
+
if (!component) {
|
|
48
|
+
errors.component = "Parameter `component` is missing in params!"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!name) {
|
|
52
|
+
errors.name = "Parameter `name` is missing in params!"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (isEmpty(dimensions)) {
|
|
56
|
+
errors.dimensions = "Parameter `dimensions` is missing in params!"
|
|
57
|
+
} else {
|
|
58
|
+
const definedDimensions = getKeys(dimensions)
|
|
59
|
+
const invalidDimension = ALL_RESERVED_KEYS.some((item) =>
|
|
60
|
+
definedDimensions.some((d) => d === item),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if (invalidDimension) {
|
|
64
|
+
errors.invalidDimensions = `Some of your \`dimensions\` is invalid and uses reserved static keys which are
|
|
65
|
+
${defaultDimensions.toString()}`
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!isEmpty(errors)) {
|
|
70
|
+
throw Error(JSON.stringify(errors))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const rocketstyle = (({ dimensions = defaultDimensions, useBooleans = true } = {}) =>
|
|
75
|
+
({ name, component }: { name: string; component: any }) => {
|
|
76
|
+
if (process.env.NODE_ENV !== "production") {
|
|
77
|
+
validateInit(name, component, dimensions)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return (rocketComponent as any)({
|
|
81
|
+
name,
|
|
82
|
+
component,
|
|
83
|
+
useBooleans,
|
|
84
|
+
dimensions,
|
|
85
|
+
dimensionKeys: getKeys(dimensions),
|
|
86
|
+
dimensionValues: getDimensionsValues(dimensions),
|
|
87
|
+
multiKeys: getMultipleDimensions(dimensions),
|
|
88
|
+
transformKeys: getTransformDimensions(dimensions),
|
|
89
|
+
styled: true,
|
|
90
|
+
})
|
|
91
|
+
}) as unknown as Rocketstyle
|
|
92
|
+
|
|
93
|
+
export default rocketstyle
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type IsRocketComponent = <T>(component: T) => boolean
|
|
2
|
+
|
|
3
|
+
/** Runtime type guard — checks if a component was created by `rocketstyle()`. */
|
|
4
|
+
const isRocketComponent: IsRocketComponent = (component) => {
|
|
5
|
+
if (
|
|
6
|
+
component &&
|
|
7
|
+
(typeof component === "object" || typeof component === "function") &&
|
|
8
|
+
Object.hasOwn(component as object, "IS_ROCKETSTYLE")
|
|
9
|
+
) {
|
|
10
|
+
return true
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default isRocketComponent
|