@spelyco/react-lib 1.2.0 → 1.3.0
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/README.md +4 -7
- package/dist/index.d.mts +176 -150
- package/dist/index.d.ts +176 -150
- package/dist/index.js +219 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +201 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -3
package/README.md
CHANGED
|
@@ -85,18 +85,15 @@ function Search() {
|
|
|
85
85
|
|
|
86
86
|
---
|
|
87
87
|
|
|
88
|
-
##
|
|
88
|
+
## Theme types
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
A pre-configured Mantine theme object with Spelyco defaults. Used internally by `SpelycoProvider`.
|
|
90
|
+
Framework-agnostic theme contract consumed by both `@spelyco/react` and `@spelyco/react-native`.
|
|
93
91
|
|
|
94
92
|
```ts
|
|
95
|
-
import {
|
|
96
|
-
// MantineTheme with defaultRadius: "md" and button defaults
|
|
93
|
+
import type { SpelycoTheme, SpelycoThemeOverride, ColorTuple } from "@spelyco/react-lib";
|
|
97
94
|
```
|
|
98
95
|
|
|
99
|
-
|
|
96
|
+
The runtime helpers that produce a theme live in the platform packages — `theme()` from `@spelyco/react` for web (Mantine), and `SpelycoProvider`'s defaults for React Native.
|
|
100
97
|
|
|
101
98
|
---
|
|
102
99
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,125 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import {
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 10-shade color tuple. Index 0 = lightest, 9 = darkest.
|
|
6
|
+
* Matches Mantine's color palette structure so palettes are portable across platforms.
|
|
7
|
+
*/
|
|
8
|
+
type ColorTuple = readonly [
|
|
9
|
+
string,
|
|
10
|
+
string,
|
|
11
|
+
string,
|
|
12
|
+
string,
|
|
13
|
+
string,
|
|
14
|
+
string,
|
|
15
|
+
string,
|
|
16
|
+
string,
|
|
17
|
+
string,
|
|
18
|
+
string
|
|
19
|
+
];
|
|
20
|
+
type SpelycoColorScheme = "light" | "dark" | "auto";
|
|
21
|
+
type SpelycoComputedColorScheme = "light" | "dark";
|
|
22
|
+
type SpelycoSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
23
|
+
type SpelycoRadiusKey = SpelycoSize | "pill";
|
|
24
|
+
type SpelycoColors = Record<string, ColorTuple>;
|
|
25
|
+
type SpelycoSpacing = Record<SpelycoSize, number>;
|
|
26
|
+
type SpelycoRadius = Record<SpelycoRadiusKey, number>;
|
|
27
|
+
type SpelycoFontSizes = Record<SpelycoSize, number>;
|
|
28
|
+
type SpelycoLineHeights = Record<SpelycoSize, number>;
|
|
29
|
+
type SpelycoShadows = Record<SpelycoSize, string>;
|
|
30
|
+
type SpelycoBreakpoints = Record<SpelycoSize, number>;
|
|
31
|
+
/**
|
|
32
|
+
* Which shade index of a color tuple becomes the "primary" color.
|
|
33
|
+
* Use a single number for both schemes, or an object to differ between light/dark.
|
|
34
|
+
*/
|
|
35
|
+
type SpelycoPrimaryShade = number | {
|
|
36
|
+
light: number;
|
|
37
|
+
dark: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Status/navigation bar config used by the RN provider via expo-system-ui and
|
|
41
|
+
* react-native-edge-to-edge. Web ignores this field.
|
|
42
|
+
*/
|
|
43
|
+
interface SpelycoSystemBars {
|
|
44
|
+
statusBarStyle: "light" | "dark" | "auto";
|
|
45
|
+
statusBarBackgroundColor?: string;
|
|
46
|
+
navigationBarColor?: string;
|
|
47
|
+
navigationBarStyle?: "light" | "dark";
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Per-component theme override. Keyed by component name (e.g. "Button").
|
|
51
|
+
* Generic over the component's props so `defaultProps` is typed.
|
|
52
|
+
*/
|
|
53
|
+
interface SpelycoComponentOverride<TProps = unknown> {
|
|
54
|
+
defaultProps?: Partial<TProps>;
|
|
55
|
+
}
|
|
56
|
+
type SpelycoComponents = Record<string, SpelycoComponentOverride>;
|
|
57
|
+
/**
|
|
58
|
+
* Fully resolved theme. Produced by `resolveTheme(override)` and consumed by
|
|
59
|
+
* components and the provider. All fields are required at this stage.
|
|
60
|
+
*/
|
|
61
|
+
interface SpelycoTheme {
|
|
62
|
+
colors: SpelycoColors;
|
|
63
|
+
primaryColor: string;
|
|
64
|
+
primaryShade: SpelycoPrimaryShade;
|
|
65
|
+
spacing: SpelycoSpacing;
|
|
66
|
+
radius: SpelycoRadius;
|
|
67
|
+
fontSizes: SpelycoFontSizes;
|
|
68
|
+
lineHeights: SpelycoLineHeights;
|
|
69
|
+
shadows: SpelycoShadows;
|
|
70
|
+
breakpoints: SpelycoBreakpoints;
|
|
71
|
+
fontFamily: string;
|
|
72
|
+
fontFamilyMono: string;
|
|
73
|
+
defaultRadius: SpelycoRadiusKey | number;
|
|
74
|
+
components: SpelycoComponents;
|
|
75
|
+
/** Only consumed by RN provider. Web ignores. */
|
|
76
|
+
systemBars?: {
|
|
77
|
+
light: SpelycoSystemBars;
|
|
78
|
+
dark: SpelycoSystemBars;
|
|
79
|
+
};
|
|
80
|
+
/** Free-form custom tokens. Consumers augment via module declaration. */
|
|
81
|
+
other: Record<string, unknown>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* What you pass to `<SpelycoProvider theme={...}>`. Every field is optional and
|
|
85
|
+
* gets deep-merged with the defaults.
|
|
86
|
+
*/
|
|
87
|
+
type SpelycoThemeOverride = Partial<SpelycoTheme>;
|
|
88
|
+
|
|
89
|
+
interface CreateComponentConfig<TProps extends object> {
|
|
90
|
+
/** Used as the key for `theme.components[name]` overrides. */
|
|
91
|
+
name: string;
|
|
92
|
+
defaultProps?: Partial<TProps>;
|
|
93
|
+
render: (props: TProps) => ReactElement | null;
|
|
94
|
+
}
|
|
95
|
+
interface SpelycoComponent<TProps extends object> {
|
|
96
|
+
(props: TProps): ReactElement | null;
|
|
97
|
+
displayName: string;
|
|
98
|
+
/**
|
|
99
|
+
* Helper for building a `theme.components[name]` override object — purely
|
|
100
|
+
* sugar, returns its argument with the right shape.
|
|
101
|
+
*/
|
|
102
|
+
extend: (override: SpelycoComponentOverride<TProps>) => SpelycoComponentOverride<TProps>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Wraps a render function into a Spelyco component that:
|
|
106
|
+
* - reads `theme.components[name].defaultProps` for runtime overrides
|
|
107
|
+
* - merges factory defaults → theme defaults → user props (later wins)
|
|
108
|
+
* - exposes `.extend()` so consumers can produce override objects
|
|
109
|
+
* - sets `displayName` to the provided `name`
|
|
110
|
+
*/
|
|
111
|
+
declare function createComponent<TProps extends object>(config: CreateComponentConfig<TProps>): SpelycoComponent<TProps>;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Merges three sources of props in precedence order (later wins):
|
|
115
|
+
* 1. factory defaults — declared inside `createComponent({ defaultProps })`
|
|
116
|
+
* 2. theme defaults — declared via `theme.components[name].defaultProps`
|
|
117
|
+
* 3. user props — passed at the call site
|
|
118
|
+
*
|
|
119
|
+
* `undefined` values in user props are skipped so partially-controlled inputs
|
|
120
|
+
* fall back to defaults instead of forcing `undefined`.
|
|
121
|
+
*/
|
|
122
|
+
declare function useProps<TProps extends object>(componentName: string, factoryDefaults: Partial<TProps> | undefined, props: TProps): TProps;
|
|
3
123
|
|
|
4
124
|
interface UseBooleanReturn {
|
|
5
125
|
value: boolean;
|
|
@@ -12,152 +132,58 @@ declare function useBoolean(initialValue?: boolean): UseBooleanReturn;
|
|
|
12
132
|
|
|
13
133
|
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
14
134
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
h4?: {
|
|
69
|
-
fontSize?: string | undefined;
|
|
70
|
-
fontWeight?: string | undefined;
|
|
71
|
-
lineHeight?: string | undefined;
|
|
72
|
-
} | undefined;
|
|
73
|
-
h5?: {
|
|
74
|
-
fontSize?: string | undefined;
|
|
75
|
-
fontWeight?: string | undefined;
|
|
76
|
-
lineHeight?: string | undefined;
|
|
77
|
-
} | undefined;
|
|
78
|
-
h6?: {
|
|
79
|
-
fontSize?: string | undefined;
|
|
80
|
-
fontWeight?: string | undefined;
|
|
81
|
-
lineHeight?: string | undefined;
|
|
82
|
-
} | undefined;
|
|
83
|
-
} | undefined;
|
|
84
|
-
} | undefined;
|
|
85
|
-
radius?: {
|
|
86
|
-
[x: string & {}]: string | undefined;
|
|
87
|
-
md?: string | undefined;
|
|
88
|
-
xs?: string | undefined;
|
|
89
|
-
sm?: string | undefined;
|
|
90
|
-
lg?: string | undefined;
|
|
91
|
-
xl?: string | undefined;
|
|
92
|
-
} | undefined;
|
|
93
|
-
defaultRadius?: _mantine_core.MantineRadius | undefined;
|
|
94
|
-
spacing?: {
|
|
95
|
-
[x: number]: string | undefined;
|
|
96
|
-
[x: string & {}]: string | undefined;
|
|
97
|
-
md?: string | undefined;
|
|
98
|
-
xs?: string | undefined;
|
|
99
|
-
sm?: string | undefined;
|
|
100
|
-
lg?: string | undefined;
|
|
101
|
-
xl?: string | undefined;
|
|
102
|
-
} | undefined;
|
|
103
|
-
fontSizes?: {
|
|
104
|
-
[x: string & {}]: string | undefined;
|
|
105
|
-
md?: string | undefined;
|
|
106
|
-
xs?: string | undefined;
|
|
107
|
-
sm?: string | undefined;
|
|
108
|
-
lg?: string | undefined;
|
|
109
|
-
xl?: string | undefined;
|
|
110
|
-
} | undefined;
|
|
111
|
-
lineHeights?: {
|
|
112
|
-
[x: string & {}]: string | undefined;
|
|
113
|
-
md?: string | undefined;
|
|
114
|
-
xs?: string | undefined;
|
|
115
|
-
sm?: string | undefined;
|
|
116
|
-
lg?: string | undefined;
|
|
117
|
-
xl?: string | undefined;
|
|
118
|
-
} | undefined;
|
|
119
|
-
fontWeights?: {
|
|
120
|
-
[x: string & {}]: string | undefined;
|
|
121
|
-
bold?: string | undefined;
|
|
122
|
-
regular?: string | undefined;
|
|
123
|
-
medium?: string | undefined;
|
|
124
|
-
} | undefined;
|
|
125
|
-
breakpoints?: {
|
|
126
|
-
[x: string & {}]: string | undefined;
|
|
127
|
-
md?: string | undefined;
|
|
128
|
-
xs?: string | undefined;
|
|
129
|
-
sm?: string | undefined;
|
|
130
|
-
lg?: string | undefined;
|
|
131
|
-
xl?: string | undefined;
|
|
132
|
-
} | undefined;
|
|
133
|
-
shadows?: {
|
|
134
|
-
[x: string & {}]: string | undefined;
|
|
135
|
-
md?: string | undefined;
|
|
136
|
-
xs?: string | undefined;
|
|
137
|
-
sm?: string | undefined;
|
|
138
|
-
lg?: string | undefined;
|
|
139
|
-
xl?: string | undefined;
|
|
140
|
-
} | undefined;
|
|
141
|
-
respectReducedMotion?: boolean | undefined;
|
|
142
|
-
cursorType?: "default" | "pointer" | undefined;
|
|
143
|
-
defaultGradient?: {
|
|
144
|
-
from?: string | undefined;
|
|
145
|
-
to?: string | undefined;
|
|
146
|
-
deg?: number | undefined;
|
|
147
|
-
} | undefined;
|
|
148
|
-
activeClassName?: string | undefined;
|
|
149
|
-
focusClassName?: string | undefined;
|
|
150
|
-
components?: {
|
|
151
|
-
[x: string]: {
|
|
152
|
-
classNames?: any;
|
|
153
|
-
styles?: any;
|
|
154
|
-
vars?: any;
|
|
155
|
-
defaultProps?: any;
|
|
156
|
-
} | undefined;
|
|
157
|
-
} | undefined;
|
|
158
|
-
other?: {
|
|
159
|
-
[x: string]: any;
|
|
160
|
-
} | undefined;
|
|
161
|
-
};
|
|
135
|
+
/**
|
|
136
|
+
* Wraps an array of 10 color strings into a typed `ColorTuple`. Throws if the
|
|
137
|
+
* array isn't exactly 10 items, which catches palette typos at boot time.
|
|
138
|
+
*
|
|
139
|
+
* For algorithmic shade generation from a single base color, prefer importing
|
|
140
|
+
* shades from a curated palette (e.g. Tailwind) — this lib intentionally ships
|
|
141
|
+
* without an HSL-based generator to keep the surface area small.
|
|
142
|
+
*/
|
|
143
|
+
declare function createColorTuple(shades: readonly string[]): ColorTuple;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Default palettes. Index 0 is the lightest, 9 is the darkest. Sourced from
|
|
147
|
+
* Tailwind's 50–900 ramps (the 950 step is dropped to keep the tuple length
|
|
148
|
+
* at 10).
|
|
149
|
+
*/
|
|
150
|
+
declare const DEFAULT_BRAND: ColorTuple;
|
|
151
|
+
declare const DEFAULT_NEUTRAL: ColorTuple;
|
|
152
|
+
declare const DEFAULT_RED: ColorTuple;
|
|
153
|
+
declare const DEFAULT_GREEN: ColorTuple;
|
|
154
|
+
declare const DEFAULT_COLORS: SpelycoColors;
|
|
155
|
+
declare const DEFAULT_SPACING: SpelycoSpacing;
|
|
156
|
+
declare const DEFAULT_RADIUS: SpelycoRadius;
|
|
157
|
+
declare const DEFAULT_FONT_SIZES: SpelycoFontSizes;
|
|
158
|
+
declare const DEFAULT_LINE_HEIGHTS: SpelycoLineHeights;
|
|
159
|
+
/**
|
|
160
|
+
* CSS box-shadow strings. RN consumers can map these to elevation locally.
|
|
161
|
+
*/
|
|
162
|
+
declare const DEFAULT_SHADOWS: SpelycoShadows;
|
|
163
|
+
/**
|
|
164
|
+
* `xs: 0` is intentional — Unistyles treats it as the always-active breakpoint.
|
|
165
|
+
*/
|
|
166
|
+
declare const DEFAULT_BREAKPOINTS: SpelycoBreakpoints;
|
|
167
|
+
declare const DEFAULT_SYSTEM_BARS_LIGHT: SpelycoSystemBars;
|
|
168
|
+
declare const DEFAULT_SYSTEM_BARS_DARK: SpelycoSystemBars;
|
|
169
|
+
/**
|
|
170
|
+
* Fully-resolved default theme. Override fields with `<SpelycoProvider theme>`.
|
|
171
|
+
*/
|
|
172
|
+
declare const DEFAULT_THEME: SpelycoTheme;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Merges a partial theme override with the default theme, returning a fully
|
|
176
|
+
* resolved `SpelycoTheme`. Color tuples and arrays are replaced wholesale;
|
|
177
|
+
* plain objects (spacing, components, etc.) are merged key-by-key.
|
|
178
|
+
*/
|
|
179
|
+
declare function resolveTheme(override?: SpelycoThemeOverride): SpelycoTheme;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Holds the resolved theme. Platform-specific providers (`SpelycoProvider` in
|
|
183
|
+
* the RN and web packages) write to this context after deep-merging user
|
|
184
|
+
* overrides with `DEFAULT_THEME`.
|
|
185
|
+
*/
|
|
186
|
+
declare const SpelycoThemeContext: react.Context<SpelycoTheme>;
|
|
187
|
+
declare function useSpelycoTheme(): SpelycoTheme;
|
|
162
188
|
|
|
163
|
-
export {
|
|
189
|
+
export { type ColorTuple, type CreateComponentConfig, DEFAULT_BRAND, DEFAULT_BREAKPOINTS, DEFAULT_COLORS, DEFAULT_FONT_SIZES, DEFAULT_GREEN, DEFAULT_LINE_HEIGHTS, DEFAULT_NEUTRAL, DEFAULT_RADIUS, DEFAULT_RED, DEFAULT_SHADOWS, DEFAULT_SPACING, DEFAULT_SYSTEM_BARS_DARK, DEFAULT_SYSTEM_BARS_LIGHT, DEFAULT_THEME, type SpelycoBreakpoints, type SpelycoColorScheme, type SpelycoColors, type SpelycoComponent, type SpelycoComponentOverride, type SpelycoComponents, type SpelycoComputedColorScheme, type SpelycoFontSizes, type SpelycoLineHeights, type SpelycoPrimaryShade, type SpelycoRadius, type SpelycoRadiusKey, type SpelycoShadows, type SpelycoSize, type SpelycoSpacing, type SpelycoSystemBars, type SpelycoTheme, SpelycoThemeContext, type SpelycoThemeOverride, createColorTuple, createComponent, resolveTheme, useBoolean, useDebounce, useProps, useSpelycoTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,125 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import {
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 10-shade color tuple. Index 0 = lightest, 9 = darkest.
|
|
6
|
+
* Matches Mantine's color palette structure so palettes are portable across platforms.
|
|
7
|
+
*/
|
|
8
|
+
type ColorTuple = readonly [
|
|
9
|
+
string,
|
|
10
|
+
string,
|
|
11
|
+
string,
|
|
12
|
+
string,
|
|
13
|
+
string,
|
|
14
|
+
string,
|
|
15
|
+
string,
|
|
16
|
+
string,
|
|
17
|
+
string,
|
|
18
|
+
string
|
|
19
|
+
];
|
|
20
|
+
type SpelycoColorScheme = "light" | "dark" | "auto";
|
|
21
|
+
type SpelycoComputedColorScheme = "light" | "dark";
|
|
22
|
+
type SpelycoSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
23
|
+
type SpelycoRadiusKey = SpelycoSize | "pill";
|
|
24
|
+
type SpelycoColors = Record<string, ColorTuple>;
|
|
25
|
+
type SpelycoSpacing = Record<SpelycoSize, number>;
|
|
26
|
+
type SpelycoRadius = Record<SpelycoRadiusKey, number>;
|
|
27
|
+
type SpelycoFontSizes = Record<SpelycoSize, number>;
|
|
28
|
+
type SpelycoLineHeights = Record<SpelycoSize, number>;
|
|
29
|
+
type SpelycoShadows = Record<SpelycoSize, string>;
|
|
30
|
+
type SpelycoBreakpoints = Record<SpelycoSize, number>;
|
|
31
|
+
/**
|
|
32
|
+
* Which shade index of a color tuple becomes the "primary" color.
|
|
33
|
+
* Use a single number for both schemes, or an object to differ between light/dark.
|
|
34
|
+
*/
|
|
35
|
+
type SpelycoPrimaryShade = number | {
|
|
36
|
+
light: number;
|
|
37
|
+
dark: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Status/navigation bar config used by the RN provider via expo-system-ui and
|
|
41
|
+
* react-native-edge-to-edge. Web ignores this field.
|
|
42
|
+
*/
|
|
43
|
+
interface SpelycoSystemBars {
|
|
44
|
+
statusBarStyle: "light" | "dark" | "auto";
|
|
45
|
+
statusBarBackgroundColor?: string;
|
|
46
|
+
navigationBarColor?: string;
|
|
47
|
+
navigationBarStyle?: "light" | "dark";
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Per-component theme override. Keyed by component name (e.g. "Button").
|
|
51
|
+
* Generic over the component's props so `defaultProps` is typed.
|
|
52
|
+
*/
|
|
53
|
+
interface SpelycoComponentOverride<TProps = unknown> {
|
|
54
|
+
defaultProps?: Partial<TProps>;
|
|
55
|
+
}
|
|
56
|
+
type SpelycoComponents = Record<string, SpelycoComponentOverride>;
|
|
57
|
+
/**
|
|
58
|
+
* Fully resolved theme. Produced by `resolveTheme(override)` and consumed by
|
|
59
|
+
* components and the provider. All fields are required at this stage.
|
|
60
|
+
*/
|
|
61
|
+
interface SpelycoTheme {
|
|
62
|
+
colors: SpelycoColors;
|
|
63
|
+
primaryColor: string;
|
|
64
|
+
primaryShade: SpelycoPrimaryShade;
|
|
65
|
+
spacing: SpelycoSpacing;
|
|
66
|
+
radius: SpelycoRadius;
|
|
67
|
+
fontSizes: SpelycoFontSizes;
|
|
68
|
+
lineHeights: SpelycoLineHeights;
|
|
69
|
+
shadows: SpelycoShadows;
|
|
70
|
+
breakpoints: SpelycoBreakpoints;
|
|
71
|
+
fontFamily: string;
|
|
72
|
+
fontFamilyMono: string;
|
|
73
|
+
defaultRadius: SpelycoRadiusKey | number;
|
|
74
|
+
components: SpelycoComponents;
|
|
75
|
+
/** Only consumed by RN provider. Web ignores. */
|
|
76
|
+
systemBars?: {
|
|
77
|
+
light: SpelycoSystemBars;
|
|
78
|
+
dark: SpelycoSystemBars;
|
|
79
|
+
};
|
|
80
|
+
/** Free-form custom tokens. Consumers augment via module declaration. */
|
|
81
|
+
other: Record<string, unknown>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* What you pass to `<SpelycoProvider theme={...}>`. Every field is optional and
|
|
85
|
+
* gets deep-merged with the defaults.
|
|
86
|
+
*/
|
|
87
|
+
type SpelycoThemeOverride = Partial<SpelycoTheme>;
|
|
88
|
+
|
|
89
|
+
interface CreateComponentConfig<TProps extends object> {
|
|
90
|
+
/** Used as the key for `theme.components[name]` overrides. */
|
|
91
|
+
name: string;
|
|
92
|
+
defaultProps?: Partial<TProps>;
|
|
93
|
+
render: (props: TProps) => ReactElement | null;
|
|
94
|
+
}
|
|
95
|
+
interface SpelycoComponent<TProps extends object> {
|
|
96
|
+
(props: TProps): ReactElement | null;
|
|
97
|
+
displayName: string;
|
|
98
|
+
/**
|
|
99
|
+
* Helper for building a `theme.components[name]` override object — purely
|
|
100
|
+
* sugar, returns its argument with the right shape.
|
|
101
|
+
*/
|
|
102
|
+
extend: (override: SpelycoComponentOverride<TProps>) => SpelycoComponentOverride<TProps>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Wraps a render function into a Spelyco component that:
|
|
106
|
+
* - reads `theme.components[name].defaultProps` for runtime overrides
|
|
107
|
+
* - merges factory defaults → theme defaults → user props (later wins)
|
|
108
|
+
* - exposes `.extend()` so consumers can produce override objects
|
|
109
|
+
* - sets `displayName` to the provided `name`
|
|
110
|
+
*/
|
|
111
|
+
declare function createComponent<TProps extends object>(config: CreateComponentConfig<TProps>): SpelycoComponent<TProps>;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Merges three sources of props in precedence order (later wins):
|
|
115
|
+
* 1. factory defaults — declared inside `createComponent({ defaultProps })`
|
|
116
|
+
* 2. theme defaults — declared via `theme.components[name].defaultProps`
|
|
117
|
+
* 3. user props — passed at the call site
|
|
118
|
+
*
|
|
119
|
+
* `undefined` values in user props are skipped so partially-controlled inputs
|
|
120
|
+
* fall back to defaults instead of forcing `undefined`.
|
|
121
|
+
*/
|
|
122
|
+
declare function useProps<TProps extends object>(componentName: string, factoryDefaults: Partial<TProps> | undefined, props: TProps): TProps;
|
|
3
123
|
|
|
4
124
|
interface UseBooleanReturn {
|
|
5
125
|
value: boolean;
|
|
@@ -12,152 +132,58 @@ declare function useBoolean(initialValue?: boolean): UseBooleanReturn;
|
|
|
12
132
|
|
|
13
133
|
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
14
134
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
h4?: {
|
|
69
|
-
fontSize?: string | undefined;
|
|
70
|
-
fontWeight?: string | undefined;
|
|
71
|
-
lineHeight?: string | undefined;
|
|
72
|
-
} | undefined;
|
|
73
|
-
h5?: {
|
|
74
|
-
fontSize?: string | undefined;
|
|
75
|
-
fontWeight?: string | undefined;
|
|
76
|
-
lineHeight?: string | undefined;
|
|
77
|
-
} | undefined;
|
|
78
|
-
h6?: {
|
|
79
|
-
fontSize?: string | undefined;
|
|
80
|
-
fontWeight?: string | undefined;
|
|
81
|
-
lineHeight?: string | undefined;
|
|
82
|
-
} | undefined;
|
|
83
|
-
} | undefined;
|
|
84
|
-
} | undefined;
|
|
85
|
-
radius?: {
|
|
86
|
-
[x: string & {}]: string | undefined;
|
|
87
|
-
md?: string | undefined;
|
|
88
|
-
xs?: string | undefined;
|
|
89
|
-
sm?: string | undefined;
|
|
90
|
-
lg?: string | undefined;
|
|
91
|
-
xl?: string | undefined;
|
|
92
|
-
} | undefined;
|
|
93
|
-
defaultRadius?: _mantine_core.MantineRadius | undefined;
|
|
94
|
-
spacing?: {
|
|
95
|
-
[x: number]: string | undefined;
|
|
96
|
-
[x: string & {}]: string | undefined;
|
|
97
|
-
md?: string | undefined;
|
|
98
|
-
xs?: string | undefined;
|
|
99
|
-
sm?: string | undefined;
|
|
100
|
-
lg?: string | undefined;
|
|
101
|
-
xl?: string | undefined;
|
|
102
|
-
} | undefined;
|
|
103
|
-
fontSizes?: {
|
|
104
|
-
[x: string & {}]: string | undefined;
|
|
105
|
-
md?: string | undefined;
|
|
106
|
-
xs?: string | undefined;
|
|
107
|
-
sm?: string | undefined;
|
|
108
|
-
lg?: string | undefined;
|
|
109
|
-
xl?: string | undefined;
|
|
110
|
-
} | undefined;
|
|
111
|
-
lineHeights?: {
|
|
112
|
-
[x: string & {}]: string | undefined;
|
|
113
|
-
md?: string | undefined;
|
|
114
|
-
xs?: string | undefined;
|
|
115
|
-
sm?: string | undefined;
|
|
116
|
-
lg?: string | undefined;
|
|
117
|
-
xl?: string | undefined;
|
|
118
|
-
} | undefined;
|
|
119
|
-
fontWeights?: {
|
|
120
|
-
[x: string & {}]: string | undefined;
|
|
121
|
-
bold?: string | undefined;
|
|
122
|
-
regular?: string | undefined;
|
|
123
|
-
medium?: string | undefined;
|
|
124
|
-
} | undefined;
|
|
125
|
-
breakpoints?: {
|
|
126
|
-
[x: string & {}]: string | undefined;
|
|
127
|
-
md?: string | undefined;
|
|
128
|
-
xs?: string | undefined;
|
|
129
|
-
sm?: string | undefined;
|
|
130
|
-
lg?: string | undefined;
|
|
131
|
-
xl?: string | undefined;
|
|
132
|
-
} | undefined;
|
|
133
|
-
shadows?: {
|
|
134
|
-
[x: string & {}]: string | undefined;
|
|
135
|
-
md?: string | undefined;
|
|
136
|
-
xs?: string | undefined;
|
|
137
|
-
sm?: string | undefined;
|
|
138
|
-
lg?: string | undefined;
|
|
139
|
-
xl?: string | undefined;
|
|
140
|
-
} | undefined;
|
|
141
|
-
respectReducedMotion?: boolean | undefined;
|
|
142
|
-
cursorType?: "default" | "pointer" | undefined;
|
|
143
|
-
defaultGradient?: {
|
|
144
|
-
from?: string | undefined;
|
|
145
|
-
to?: string | undefined;
|
|
146
|
-
deg?: number | undefined;
|
|
147
|
-
} | undefined;
|
|
148
|
-
activeClassName?: string | undefined;
|
|
149
|
-
focusClassName?: string | undefined;
|
|
150
|
-
components?: {
|
|
151
|
-
[x: string]: {
|
|
152
|
-
classNames?: any;
|
|
153
|
-
styles?: any;
|
|
154
|
-
vars?: any;
|
|
155
|
-
defaultProps?: any;
|
|
156
|
-
} | undefined;
|
|
157
|
-
} | undefined;
|
|
158
|
-
other?: {
|
|
159
|
-
[x: string]: any;
|
|
160
|
-
} | undefined;
|
|
161
|
-
};
|
|
135
|
+
/**
|
|
136
|
+
* Wraps an array of 10 color strings into a typed `ColorTuple`. Throws if the
|
|
137
|
+
* array isn't exactly 10 items, which catches palette typos at boot time.
|
|
138
|
+
*
|
|
139
|
+
* For algorithmic shade generation from a single base color, prefer importing
|
|
140
|
+
* shades from a curated palette (e.g. Tailwind) — this lib intentionally ships
|
|
141
|
+
* without an HSL-based generator to keep the surface area small.
|
|
142
|
+
*/
|
|
143
|
+
declare function createColorTuple(shades: readonly string[]): ColorTuple;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Default palettes. Index 0 is the lightest, 9 is the darkest. Sourced from
|
|
147
|
+
* Tailwind's 50–900 ramps (the 950 step is dropped to keep the tuple length
|
|
148
|
+
* at 10).
|
|
149
|
+
*/
|
|
150
|
+
declare const DEFAULT_BRAND: ColorTuple;
|
|
151
|
+
declare const DEFAULT_NEUTRAL: ColorTuple;
|
|
152
|
+
declare const DEFAULT_RED: ColorTuple;
|
|
153
|
+
declare const DEFAULT_GREEN: ColorTuple;
|
|
154
|
+
declare const DEFAULT_COLORS: SpelycoColors;
|
|
155
|
+
declare const DEFAULT_SPACING: SpelycoSpacing;
|
|
156
|
+
declare const DEFAULT_RADIUS: SpelycoRadius;
|
|
157
|
+
declare const DEFAULT_FONT_SIZES: SpelycoFontSizes;
|
|
158
|
+
declare const DEFAULT_LINE_HEIGHTS: SpelycoLineHeights;
|
|
159
|
+
/**
|
|
160
|
+
* CSS box-shadow strings. RN consumers can map these to elevation locally.
|
|
161
|
+
*/
|
|
162
|
+
declare const DEFAULT_SHADOWS: SpelycoShadows;
|
|
163
|
+
/**
|
|
164
|
+
* `xs: 0` is intentional — Unistyles treats it as the always-active breakpoint.
|
|
165
|
+
*/
|
|
166
|
+
declare const DEFAULT_BREAKPOINTS: SpelycoBreakpoints;
|
|
167
|
+
declare const DEFAULT_SYSTEM_BARS_LIGHT: SpelycoSystemBars;
|
|
168
|
+
declare const DEFAULT_SYSTEM_BARS_DARK: SpelycoSystemBars;
|
|
169
|
+
/**
|
|
170
|
+
* Fully-resolved default theme. Override fields with `<SpelycoProvider theme>`.
|
|
171
|
+
*/
|
|
172
|
+
declare const DEFAULT_THEME: SpelycoTheme;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Merges a partial theme override with the default theme, returning a fully
|
|
176
|
+
* resolved `SpelycoTheme`. Color tuples and arrays are replaced wholesale;
|
|
177
|
+
* plain objects (spacing, components, etc.) are merged key-by-key.
|
|
178
|
+
*/
|
|
179
|
+
declare function resolveTheme(override?: SpelycoThemeOverride): SpelycoTheme;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Holds the resolved theme. Platform-specific providers (`SpelycoProvider` in
|
|
183
|
+
* the RN and web packages) write to this context after deep-merging user
|
|
184
|
+
* overrides with `DEFAULT_THEME`.
|
|
185
|
+
*/
|
|
186
|
+
declare const SpelycoThemeContext: react.Context<SpelycoTheme>;
|
|
187
|
+
declare function useSpelycoTheme(): SpelycoTheme;
|
|
162
188
|
|
|
163
|
-
export {
|
|
189
|
+
export { type ColorTuple, type CreateComponentConfig, DEFAULT_BRAND, DEFAULT_BREAKPOINTS, DEFAULT_COLORS, DEFAULT_FONT_SIZES, DEFAULT_GREEN, DEFAULT_LINE_HEIGHTS, DEFAULT_NEUTRAL, DEFAULT_RADIUS, DEFAULT_RED, DEFAULT_SHADOWS, DEFAULT_SPACING, DEFAULT_SYSTEM_BARS_DARK, DEFAULT_SYSTEM_BARS_LIGHT, DEFAULT_THEME, type SpelycoBreakpoints, type SpelycoColorScheme, type SpelycoColors, type SpelycoComponent, type SpelycoComponentOverride, type SpelycoComponents, type SpelycoComputedColorScheme, type SpelycoFontSizes, type SpelycoLineHeights, type SpelycoPrimaryShade, type SpelycoRadius, type SpelycoRadiusKey, type SpelycoShadows, type SpelycoSize, type SpelycoSpacing, type SpelycoSystemBars, type SpelycoTheme, SpelycoThemeContext, type SpelycoThemeOverride, createColorTuple, createComponent, resolveTheme, useBoolean, useDebounce, useProps, useSpelycoTheme };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,183 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
|
-
var core = require('@mantine/core');
|
|
5
4
|
|
|
6
|
-
// src/
|
|
5
|
+
// src/theme/ThemeContext.ts
|
|
6
|
+
|
|
7
|
+
// src/theme/createColorTuple.ts
|
|
8
|
+
function createColorTuple(shades) {
|
|
9
|
+
if (shades.length !== 10) {
|
|
10
|
+
throw new Error(`createColorTuple expects exactly 10 shades, got ${shades.length}`);
|
|
11
|
+
}
|
|
12
|
+
return shades;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/theme/defaults.ts
|
|
16
|
+
var DEFAULT_BRAND = createColorTuple([
|
|
17
|
+
"#eef2ff",
|
|
18
|
+
"#e0e7ff",
|
|
19
|
+
"#c7d2fe",
|
|
20
|
+
"#a5b4fc",
|
|
21
|
+
"#818cf8",
|
|
22
|
+
"#6366f1",
|
|
23
|
+
"#4f46e5",
|
|
24
|
+
"#4338ca",
|
|
25
|
+
"#3730a3",
|
|
26
|
+
"#312e81"
|
|
27
|
+
]);
|
|
28
|
+
var DEFAULT_NEUTRAL = createColorTuple([
|
|
29
|
+
"#fafafa",
|
|
30
|
+
"#f4f4f5",
|
|
31
|
+
"#e4e4e7",
|
|
32
|
+
"#d4d4d8",
|
|
33
|
+
"#a1a1aa",
|
|
34
|
+
"#71717a",
|
|
35
|
+
"#52525b",
|
|
36
|
+
"#3f3f46",
|
|
37
|
+
"#27272a",
|
|
38
|
+
"#18181b"
|
|
39
|
+
]);
|
|
40
|
+
var DEFAULT_RED = createColorTuple([
|
|
41
|
+
"#fef2f2",
|
|
42
|
+
"#fee2e2",
|
|
43
|
+
"#fecaca",
|
|
44
|
+
"#fca5a5",
|
|
45
|
+
"#f87171",
|
|
46
|
+
"#ef4444",
|
|
47
|
+
"#dc2626",
|
|
48
|
+
"#b91c1c",
|
|
49
|
+
"#991b1b",
|
|
50
|
+
"#7f1d1d"
|
|
51
|
+
]);
|
|
52
|
+
var DEFAULT_GREEN = createColorTuple([
|
|
53
|
+
"#ecfdf5",
|
|
54
|
+
"#d1fae5",
|
|
55
|
+
"#a7f3d0",
|
|
56
|
+
"#6ee7b7",
|
|
57
|
+
"#34d399",
|
|
58
|
+
"#10b981",
|
|
59
|
+
"#059669",
|
|
60
|
+
"#047857",
|
|
61
|
+
"#065f46",
|
|
62
|
+
"#064e3b"
|
|
63
|
+
]);
|
|
64
|
+
var DEFAULT_COLORS = {
|
|
65
|
+
brand: DEFAULT_BRAND,
|
|
66
|
+
neutral: DEFAULT_NEUTRAL,
|
|
67
|
+
red: DEFAULT_RED,
|
|
68
|
+
green: DEFAULT_GREEN
|
|
69
|
+
};
|
|
70
|
+
var DEFAULT_SPACING = {
|
|
71
|
+
xs: 4,
|
|
72
|
+
sm: 8,
|
|
73
|
+
md: 12,
|
|
74
|
+
lg: 16,
|
|
75
|
+
xl: 24
|
|
76
|
+
};
|
|
77
|
+
var DEFAULT_RADIUS = {
|
|
78
|
+
xs: 2,
|
|
79
|
+
sm: 4,
|
|
80
|
+
md: 8,
|
|
81
|
+
lg: 12,
|
|
82
|
+
xl: 16,
|
|
83
|
+
pill: 9999
|
|
84
|
+
};
|
|
85
|
+
var DEFAULT_FONT_SIZES = {
|
|
86
|
+
xs: 12,
|
|
87
|
+
sm: 14,
|
|
88
|
+
md: 16,
|
|
89
|
+
lg: 18,
|
|
90
|
+
xl: 20
|
|
91
|
+
};
|
|
92
|
+
var DEFAULT_LINE_HEIGHTS = {
|
|
93
|
+
xs: 1.4,
|
|
94
|
+
sm: 1.45,
|
|
95
|
+
md: 1.55,
|
|
96
|
+
lg: 1.6,
|
|
97
|
+
xl: 1.65
|
|
98
|
+
};
|
|
99
|
+
var DEFAULT_SHADOWS = {
|
|
100
|
+
xs: "0 1px 2px rgba(0, 0, 0, 0.05)",
|
|
101
|
+
sm: "0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04)",
|
|
102
|
+
md: "0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.04)",
|
|
103
|
+
lg: "0 10px 15px rgba(0, 0, 0, 0.08), 0 4px 6px rgba(0, 0, 0, 0.04)",
|
|
104
|
+
xl: "0 20px 25px rgba(0, 0, 0, 0.08), 0 10px 10px rgba(0, 0, 0, 0.03)"
|
|
105
|
+
};
|
|
106
|
+
var DEFAULT_BREAKPOINTS = {
|
|
107
|
+
xs: 0,
|
|
108
|
+
sm: 360,
|
|
109
|
+
md: 768,
|
|
110
|
+
lg: 1024,
|
|
111
|
+
xl: 1280
|
|
112
|
+
};
|
|
113
|
+
var DEFAULT_SYSTEM_BARS_LIGHT = {
|
|
114
|
+
statusBarStyle: "dark",
|
|
115
|
+
statusBarBackgroundColor: "#ffffff",
|
|
116
|
+
navigationBarColor: "#ffffff",
|
|
117
|
+
navigationBarStyle: "dark"
|
|
118
|
+
};
|
|
119
|
+
var DEFAULT_SYSTEM_BARS_DARK = {
|
|
120
|
+
statusBarStyle: "light",
|
|
121
|
+
statusBarBackgroundColor: "#0b0b0f",
|
|
122
|
+
navigationBarColor: "#0b0b0f",
|
|
123
|
+
navigationBarStyle: "light"
|
|
124
|
+
};
|
|
125
|
+
var DEFAULT_THEME = {
|
|
126
|
+
colors: DEFAULT_COLORS,
|
|
127
|
+
primaryColor: "brand",
|
|
128
|
+
primaryShade: { light: 6, dark: 4 },
|
|
129
|
+
spacing: DEFAULT_SPACING,
|
|
130
|
+
radius: DEFAULT_RADIUS,
|
|
131
|
+
fontSizes: DEFAULT_FONT_SIZES,
|
|
132
|
+
lineHeights: DEFAULT_LINE_HEIGHTS,
|
|
133
|
+
shadows: DEFAULT_SHADOWS,
|
|
134
|
+
breakpoints: DEFAULT_BREAKPOINTS,
|
|
135
|
+
fontFamily: "System",
|
|
136
|
+
fontFamilyMono: "Menlo, monospace",
|
|
137
|
+
defaultRadius: "md",
|
|
138
|
+
components: {},
|
|
139
|
+
systemBars: {
|
|
140
|
+
light: DEFAULT_SYSTEM_BARS_LIGHT,
|
|
141
|
+
dark: DEFAULT_SYSTEM_BARS_DARK
|
|
142
|
+
},
|
|
143
|
+
other: {}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// src/theme/ThemeContext.ts
|
|
147
|
+
var SpelycoThemeContext = react.createContext(DEFAULT_THEME);
|
|
148
|
+
function useSpelycoTheme() {
|
|
149
|
+
return react.useContext(SpelycoThemeContext);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/factory/useProps.ts
|
|
153
|
+
function useProps(componentName, factoryDefaults, props) {
|
|
154
|
+
const theme = useSpelycoTheme();
|
|
155
|
+
const themeOverride = theme.components[componentName];
|
|
156
|
+
const themeDefaults = themeOverride?.defaultProps;
|
|
157
|
+
const merged = {
|
|
158
|
+
...factoryDefaults,
|
|
159
|
+
...themeDefaults
|
|
160
|
+
};
|
|
161
|
+
const propsRecord = props;
|
|
162
|
+
for (const key in propsRecord) {
|
|
163
|
+
if (propsRecord[key] !== void 0) {
|
|
164
|
+
merged[key] = propsRecord[key];
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return merged;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/factory/createComponent.ts
|
|
171
|
+
function createComponent(config) {
|
|
172
|
+
const { name, defaultProps, render } = config;
|
|
173
|
+
const Component = ((props) => {
|
|
174
|
+
const merged = useProps(name, defaultProps, props);
|
|
175
|
+
return render(merged);
|
|
176
|
+
});
|
|
177
|
+
Component.displayName = name;
|
|
178
|
+
Component.extend = (override) => override;
|
|
179
|
+
return Component;
|
|
180
|
+
}
|
|
7
181
|
function useBoolean(initialValue = false) {
|
|
8
182
|
const [value, setValue] = react.useState(initialValue);
|
|
9
183
|
const setTrue = react.useCallback(() => setValue(true), []);
|
|
@@ -19,31 +193,52 @@ function useDebounce(value, delay = 300) {
|
|
|
19
193
|
}, [value, delay]);
|
|
20
194
|
return debouncedValue;
|
|
21
195
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
NavLink: core.NavLink.extend({
|
|
37
|
-
defaultProps: {
|
|
38
|
-
color: "gray",
|
|
39
|
-
variant: "light"
|
|
40
|
-
}
|
|
41
|
-
})
|
|
196
|
+
|
|
197
|
+
// src/theme/resolveTheme.ts
|
|
198
|
+
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
199
|
+
function deepMerge(base, override) {
|
|
200
|
+
const result = { ...base };
|
|
201
|
+
for (const key of Object.keys(override)) {
|
|
202
|
+
const overrideValue = override[key];
|
|
203
|
+
if (overrideValue === void 0) continue;
|
|
204
|
+
const baseValue = base[key];
|
|
205
|
+
if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
|
|
206
|
+
result[key] = deepMerge(baseValue, overrideValue);
|
|
207
|
+
} else {
|
|
208
|
+
result[key] = overrideValue;
|
|
209
|
+
}
|
|
42
210
|
}
|
|
43
|
-
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
function resolveTheme(override) {
|
|
214
|
+
if (!override) return DEFAULT_THEME;
|
|
215
|
+
return deepMerge(
|
|
216
|
+
DEFAULT_THEME,
|
|
217
|
+
override
|
|
218
|
+
);
|
|
219
|
+
}
|
|
44
220
|
|
|
45
|
-
exports.
|
|
221
|
+
exports.DEFAULT_BRAND = DEFAULT_BRAND;
|
|
222
|
+
exports.DEFAULT_BREAKPOINTS = DEFAULT_BREAKPOINTS;
|
|
223
|
+
exports.DEFAULT_COLORS = DEFAULT_COLORS;
|
|
224
|
+
exports.DEFAULT_FONT_SIZES = DEFAULT_FONT_SIZES;
|
|
225
|
+
exports.DEFAULT_GREEN = DEFAULT_GREEN;
|
|
226
|
+
exports.DEFAULT_LINE_HEIGHTS = DEFAULT_LINE_HEIGHTS;
|
|
227
|
+
exports.DEFAULT_NEUTRAL = DEFAULT_NEUTRAL;
|
|
228
|
+
exports.DEFAULT_RADIUS = DEFAULT_RADIUS;
|
|
229
|
+
exports.DEFAULT_RED = DEFAULT_RED;
|
|
230
|
+
exports.DEFAULT_SHADOWS = DEFAULT_SHADOWS;
|
|
231
|
+
exports.DEFAULT_SPACING = DEFAULT_SPACING;
|
|
232
|
+
exports.DEFAULT_SYSTEM_BARS_DARK = DEFAULT_SYSTEM_BARS_DARK;
|
|
233
|
+
exports.DEFAULT_SYSTEM_BARS_LIGHT = DEFAULT_SYSTEM_BARS_LIGHT;
|
|
234
|
+
exports.DEFAULT_THEME = DEFAULT_THEME;
|
|
235
|
+
exports.SpelycoThemeContext = SpelycoThemeContext;
|
|
236
|
+
exports.createColorTuple = createColorTuple;
|
|
237
|
+
exports.createComponent = createComponent;
|
|
238
|
+
exports.resolveTheme = resolveTheme;
|
|
46
239
|
exports.useBoolean = useBoolean;
|
|
47
240
|
exports.useDebounce = useDebounce;
|
|
241
|
+
exports.useProps = useProps;
|
|
242
|
+
exports.useSpelycoTheme = useSpelycoTheme;
|
|
48
243
|
//# sourceMappingURL=index.js.map
|
|
49
244
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useBoolean.ts","../src/hooks/useDebounce.ts","../src/utils/theme.ts"],"names":["useState","useCallback","useEffect","createTheme","Button","ActionIcon","NavLink"],"mappings":";;;;;;AAUO,SAAS,UAAA,CAAW,eAAe,KAAA,EAAyB;AACjE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAS,YAAY,CAAA;AAE/C,EAAA,MAAM,UAAUC,iBAAA,CAAY,MAAM,SAAS,IAAI,CAAA,EAAG,EAAE,CAAA;AACpD,EAAA,MAAM,WAAWA,iBAAA,CAAY,MAAM,SAAS,KAAK,CAAA,EAAG,EAAE,CAAA;AACtD,EAAA,MAAM,MAAA,GAASA,iBAAA,CAAY,MAAM,QAAA,CAAS,CAAC,MAAM,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA;AAExD,EAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAU,QAAQ,QAAA,EAAS;AACtD;AChBO,SAAS,WAAA,CAAe,KAAA,EAAU,KAAA,GAAQ,GAAA,EAAQ;AACvD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAID,eAAY,KAAK,CAAA;AAE7D,EAAAE,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,iBAAA,CAAkB,KAAK,GAAG,KAAK,CAAA;AAC9D,IAAA,OAAO,MAAM,aAAa,KAAK,CAAA;AAAA,EACjC,CAAA,EAAG,CAAC,KAAA,EAAO,KAAK,CAAC,CAAA;AAEjB,EAAA,OAAO,cAAA;AACT;ACTO,IAAM,KAAA,GAAQ,CAAC,YAAA,KACpBC,gBAAA,CAAY;AAAA,EACV,cAAc,YAAA,IAAgB,MAAA;AAAA,EAC9B,aAAA,EAAe,IAAA;AAAA,EACf,UAAA,EAAY;AAAA,IACV,MAAA,EAAQC,YAAO,MAAA,CAAO;AAAA,MACpB,YAAA,EAAc;AAAA,QACZ,OAAA,EAAS;AAAA;AACX,KACD,CAAA;AAAA,IACD,UAAA,EAAYC,gBAAW,MAAA,CAAO;AAAA,MAC5B,YAAA,EAAc;AAAA,QACZ,OAAA,EAAS;AAAA;AACX,KACD,CAAA;AAAA,IACD,OAAA,EAASC,aAAQ,MAAA,CAAO;AAAA,MACtB,YAAA,EAAc;AAAA,QACZ,KAAA,EAAO,MAAA;AAAA,QACP,OAAA,EAAS;AAAA;AACX,KACD;AAAA;AAEL,CAAC","file":"index.js","sourcesContent":["import { useCallback, useState } from \"react\";\n\nexport interface UseBooleanReturn {\n value: boolean;\n setTrue: () => void;\n setFalse: () => void;\n toggle: () => void;\n setValue: (value: boolean) => void;\n}\n\nexport function useBoolean(initialValue = false): UseBooleanReturn {\n const [value, setValue] = useState(initialValue);\n\n const setTrue = useCallback(() => setValue(true), []);\n const setFalse = useCallback(() => setValue(false), []);\n const toggle = useCallback(() => setValue((v) => !v), []);\n\n return { value, setTrue, setFalse, toggle, setValue };\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebounce<T>(value: T, delay = 300): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n const timer = setTimeout(() => setDebouncedValue(value), delay);\n return () => clearTimeout(timer);\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { ActionIcon, Button, createTheme, type MantineColor, NavLink } from \"@mantine/core\";\n\nexport const theme = (primaryColor?: MantineColor) =>\n createTheme({\n primaryColor: primaryColor ?? \"dark\",\n defaultRadius: \"md\",\n components: {\n Button: Button.extend({\n defaultProps: {\n variant: \"default\",\n },\n }),\n ActionIcon: ActionIcon.extend({\n defaultProps: {\n variant: \"transparent\",\n },\n }),\n NavLink: NavLink.extend({\n defaultProps: {\n color: \"gray\",\n variant: \"light\",\n },\n }),\n },\n });\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/theme/createColorTuple.ts","../src/theme/defaults.ts","../src/theme/ThemeContext.ts","../src/factory/useProps.ts","../src/factory/createComponent.ts","../src/hooks/useBoolean.ts","../src/hooks/useDebounce.ts","../src/theme/resolveTheme.ts"],"names":["createContext","useContext","useState","useCallback","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import type { ColorTuple } from \"./types\";\n\n/**\n * Wraps an array of 10 color strings into a typed `ColorTuple`. Throws if the\n * array isn't exactly 10 items, which catches palette typos at boot time.\n *\n * For algorithmic shade generation from a single base color, prefer importing\n * shades from a curated palette (e.g. Tailwind) — this lib intentionally ships\n * without an HSL-based generator to keep the surface area small.\n */\nexport function createColorTuple(shades: readonly string[]): ColorTuple {\n if (shades.length !== 10) {\n throw new Error(`createColorTuple expects exactly 10 shades, got ${shades.length}`);\n }\n return shades as unknown as ColorTuple;\n}\n","import { createColorTuple } from \"./createColorTuple\";\nimport type {\n ColorTuple,\n SpelycoBreakpoints,\n SpelycoColors,\n SpelycoFontSizes,\n SpelycoLineHeights,\n SpelycoRadius,\n SpelycoShadows,\n SpelycoSpacing,\n SpelycoSystemBars,\n SpelycoTheme,\n} from \"./types\";\n\n/**\n * Default palettes. Index 0 is the lightest, 9 is the darkest. Sourced from\n * Tailwind's 50–900 ramps (the 950 step is dropped to keep the tuple length\n * at 10).\n */\nexport const DEFAULT_BRAND: ColorTuple = createColorTuple([\n \"#eef2ff\",\n \"#e0e7ff\",\n \"#c7d2fe\",\n \"#a5b4fc\",\n \"#818cf8\",\n \"#6366f1\",\n \"#4f46e5\",\n \"#4338ca\",\n \"#3730a3\",\n \"#312e81\",\n]);\n\nexport const DEFAULT_NEUTRAL: ColorTuple = createColorTuple([\n \"#fafafa\",\n \"#f4f4f5\",\n \"#e4e4e7\",\n \"#d4d4d8\",\n \"#a1a1aa\",\n \"#71717a\",\n \"#52525b\",\n \"#3f3f46\",\n \"#27272a\",\n \"#18181b\",\n]);\n\nexport const DEFAULT_RED: ColorTuple = createColorTuple([\n \"#fef2f2\",\n \"#fee2e2\",\n \"#fecaca\",\n \"#fca5a5\",\n \"#f87171\",\n \"#ef4444\",\n \"#dc2626\",\n \"#b91c1c\",\n \"#991b1b\",\n \"#7f1d1d\",\n]);\n\nexport const DEFAULT_GREEN: ColorTuple = createColorTuple([\n \"#ecfdf5\",\n \"#d1fae5\",\n \"#a7f3d0\",\n \"#6ee7b7\",\n \"#34d399\",\n \"#10b981\",\n \"#059669\",\n \"#047857\",\n \"#065f46\",\n \"#064e3b\",\n]);\n\nexport const DEFAULT_COLORS: SpelycoColors = {\n brand: DEFAULT_BRAND,\n neutral: DEFAULT_NEUTRAL,\n red: DEFAULT_RED,\n green: DEFAULT_GREEN,\n};\n\nexport const DEFAULT_SPACING: SpelycoSpacing = {\n xs: 4,\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n};\n\nexport const DEFAULT_RADIUS: SpelycoRadius = {\n xs: 2,\n sm: 4,\n md: 8,\n lg: 12,\n xl: 16,\n pill: 9999,\n};\n\nexport const DEFAULT_FONT_SIZES: SpelycoFontSizes = {\n xs: 12,\n sm: 14,\n md: 16,\n lg: 18,\n xl: 20,\n};\n\nexport const DEFAULT_LINE_HEIGHTS: SpelycoLineHeights = {\n xs: 1.4,\n sm: 1.45,\n md: 1.55,\n lg: 1.6,\n xl: 1.65,\n};\n\n/**\n * CSS box-shadow strings. RN consumers can map these to elevation locally.\n */\nexport const DEFAULT_SHADOWS: SpelycoShadows = {\n xs: \"0 1px 2px rgba(0, 0, 0, 0.05)\",\n sm: \"0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04)\",\n md: \"0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.04)\",\n lg: \"0 10px 15px rgba(0, 0, 0, 0.08), 0 4px 6px rgba(0, 0, 0, 0.04)\",\n xl: \"0 20px 25px rgba(0, 0, 0, 0.08), 0 10px 10px rgba(0, 0, 0, 0.03)\",\n};\n\n/**\n * `xs: 0` is intentional — Unistyles treats it as the always-active breakpoint.\n */\nexport const DEFAULT_BREAKPOINTS: SpelycoBreakpoints = {\n xs: 0,\n sm: 360,\n md: 768,\n lg: 1024,\n xl: 1280,\n};\n\nexport const DEFAULT_SYSTEM_BARS_LIGHT: SpelycoSystemBars = {\n statusBarStyle: \"dark\",\n statusBarBackgroundColor: \"#ffffff\",\n navigationBarColor: \"#ffffff\",\n navigationBarStyle: \"dark\",\n};\n\nexport const DEFAULT_SYSTEM_BARS_DARK: SpelycoSystemBars = {\n statusBarStyle: \"light\",\n statusBarBackgroundColor: \"#0b0b0f\",\n navigationBarColor: \"#0b0b0f\",\n navigationBarStyle: \"light\",\n};\n\n/**\n * Fully-resolved default theme. Override fields with `<SpelycoProvider theme>`.\n */\nexport const DEFAULT_THEME: SpelycoTheme = {\n colors: DEFAULT_COLORS,\n primaryColor: \"brand\",\n primaryShade: { light: 6, dark: 4 },\n\n spacing: DEFAULT_SPACING,\n radius: DEFAULT_RADIUS,\n fontSizes: DEFAULT_FONT_SIZES,\n lineHeights: DEFAULT_LINE_HEIGHTS,\n shadows: DEFAULT_SHADOWS,\n breakpoints: DEFAULT_BREAKPOINTS,\n\n fontFamily: \"System\",\n fontFamilyMono: \"Menlo, monospace\",\n\n defaultRadius: \"md\",\n\n components: {},\n\n systemBars: {\n light: DEFAULT_SYSTEM_BARS_LIGHT,\n dark: DEFAULT_SYSTEM_BARS_DARK,\n },\n\n other: {},\n};\n","import { createContext, useContext } from \"react\";\nimport { DEFAULT_THEME } from \"./defaults\";\nimport type { SpelycoTheme } from \"./types\";\n\n/**\n * Holds the resolved theme. Platform-specific providers (`SpelycoProvider` in\n * the RN and web packages) write to this context after deep-merging user\n * overrides with `DEFAULT_THEME`.\n */\nexport const SpelycoThemeContext = createContext<SpelycoTheme>(DEFAULT_THEME);\n\nexport function useSpelycoTheme(): SpelycoTheme {\n return useContext(SpelycoThemeContext);\n}\n","import { useSpelycoTheme } from \"../theme/ThemeContext\";\nimport type { SpelycoComponentOverride } from \"../theme/types\";\n\n/**\n * Merges three sources of props in precedence order (later wins):\n * 1. factory defaults — declared inside `createComponent({ defaultProps })`\n * 2. theme defaults — declared via `theme.components[name].defaultProps`\n * 3. user props — passed at the call site\n *\n * `undefined` values in user props are skipped so partially-controlled inputs\n * fall back to defaults instead of forcing `undefined`.\n */\nexport function useProps<TProps extends object>(\n componentName: string,\n factoryDefaults: Partial<TProps> | undefined,\n props: TProps\n): TProps {\n const theme = useSpelycoTheme();\n const themeOverride = theme.components[componentName] as\n | SpelycoComponentOverride<TProps>\n | undefined;\n const themeDefaults = themeOverride?.defaultProps;\n\n const merged: Record<string, unknown> = {\n ...factoryDefaults,\n ...themeDefaults,\n };\n\n const propsRecord = props as Record<string, unknown>;\n for (const key in propsRecord) {\n if (propsRecord[key] !== undefined) {\n merged[key] = propsRecord[key];\n }\n }\n\n return merged as TProps;\n}\n","import type { ReactElement } from \"react\";\nimport type { SpelycoComponentOverride } from \"../theme/types\";\nimport { useProps } from \"./useProps\";\n\nexport interface CreateComponentConfig<TProps extends object> {\n /** Used as the key for `theme.components[name]` overrides. */\n name: string;\n defaultProps?: Partial<TProps>;\n render: (props: TProps) => ReactElement | null;\n}\n\nexport interface SpelycoComponent<TProps extends object> {\n (props: TProps): ReactElement | null;\n displayName: string;\n /**\n * Helper for building a `theme.components[name]` override object — purely\n * sugar, returns its argument with the right shape.\n */\n extend: (override: SpelycoComponentOverride<TProps>) => SpelycoComponentOverride<TProps>;\n}\n\n/**\n * Wraps a render function into a Spelyco component that:\n * - reads `theme.components[name].defaultProps` for runtime overrides\n * - merges factory defaults → theme defaults → user props (later wins)\n * - exposes `.extend()` so consumers can produce override objects\n * - sets `displayName` to the provided `name`\n */\nexport function createComponent<TProps extends object>(\n config: CreateComponentConfig<TProps>\n): SpelycoComponent<TProps> {\n const { name, defaultProps, render } = config;\n\n const Component = ((props: TProps) => {\n const merged = useProps<TProps>(name, defaultProps, props);\n return render(merged);\n }) as SpelycoComponent<TProps>;\n\n Component.displayName = name;\n Component.extend = (override) => override;\n\n return Component;\n}\n","import { useCallback, useState } from \"react\";\n\nexport interface UseBooleanReturn {\n value: boolean;\n setTrue: () => void;\n setFalse: () => void;\n toggle: () => void;\n setValue: (value: boolean) => void;\n}\n\nexport function useBoolean(initialValue = false): UseBooleanReturn {\n const [value, setValue] = useState(initialValue);\n\n const setTrue = useCallback(() => setValue(true), []);\n const setFalse = useCallback(() => setValue(false), []);\n const toggle = useCallback(() => setValue((v) => !v), []);\n\n return { value, setTrue, setFalse, toggle, setValue };\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebounce<T>(value: T, delay = 300): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n const timer = setTimeout(() => setDebouncedValue(value), delay);\n return () => clearTimeout(timer);\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { DEFAULT_THEME } from \"./defaults\";\nimport type { SpelycoTheme, SpelycoThemeOverride } from \"./types\";\n\ntype PlainObject = Record<string, unknown>;\n\nconst isPlainObject = (value: unknown): value is PlainObject =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nfunction deepMerge(base: PlainObject, override: PlainObject): PlainObject {\n const result: PlainObject = { ...base };\n for (const key of Object.keys(override)) {\n const overrideValue = override[key];\n if (overrideValue === undefined) continue;\n\n const baseValue = base[key];\n if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {\n result[key] = deepMerge(baseValue, overrideValue);\n } else {\n result[key] = overrideValue;\n }\n }\n return result;\n}\n\n/**\n * Merges a partial theme override with the default theme, returning a fully\n * resolved `SpelycoTheme`. Color tuples and arrays are replaced wholesale;\n * plain objects (spacing, components, etc.) are merged key-by-key.\n */\nexport function resolveTheme(override?: SpelycoThemeOverride): SpelycoTheme {\n if (!override) return DEFAULT_THEME;\n return deepMerge(\n DEFAULT_THEME as unknown as PlainObject,\n override as unknown as PlainObject\n ) as unknown as SpelycoTheme;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,181 @@
|
|
|
1
|
-
import { useState, useCallback, useEffect } from 'react';
|
|
2
|
-
import { createTheme, NavLink, ActionIcon, Button } from '@mantine/core';
|
|
1
|
+
import { createContext, useContext, useState, useCallback, useEffect } from 'react';
|
|
3
2
|
|
|
4
|
-
// src/
|
|
3
|
+
// src/theme/ThemeContext.ts
|
|
4
|
+
|
|
5
|
+
// src/theme/createColorTuple.ts
|
|
6
|
+
function createColorTuple(shades) {
|
|
7
|
+
if (shades.length !== 10) {
|
|
8
|
+
throw new Error(`createColorTuple expects exactly 10 shades, got ${shades.length}`);
|
|
9
|
+
}
|
|
10
|
+
return shades;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/theme/defaults.ts
|
|
14
|
+
var DEFAULT_BRAND = createColorTuple([
|
|
15
|
+
"#eef2ff",
|
|
16
|
+
"#e0e7ff",
|
|
17
|
+
"#c7d2fe",
|
|
18
|
+
"#a5b4fc",
|
|
19
|
+
"#818cf8",
|
|
20
|
+
"#6366f1",
|
|
21
|
+
"#4f46e5",
|
|
22
|
+
"#4338ca",
|
|
23
|
+
"#3730a3",
|
|
24
|
+
"#312e81"
|
|
25
|
+
]);
|
|
26
|
+
var DEFAULT_NEUTRAL = createColorTuple([
|
|
27
|
+
"#fafafa",
|
|
28
|
+
"#f4f4f5",
|
|
29
|
+
"#e4e4e7",
|
|
30
|
+
"#d4d4d8",
|
|
31
|
+
"#a1a1aa",
|
|
32
|
+
"#71717a",
|
|
33
|
+
"#52525b",
|
|
34
|
+
"#3f3f46",
|
|
35
|
+
"#27272a",
|
|
36
|
+
"#18181b"
|
|
37
|
+
]);
|
|
38
|
+
var DEFAULT_RED = createColorTuple([
|
|
39
|
+
"#fef2f2",
|
|
40
|
+
"#fee2e2",
|
|
41
|
+
"#fecaca",
|
|
42
|
+
"#fca5a5",
|
|
43
|
+
"#f87171",
|
|
44
|
+
"#ef4444",
|
|
45
|
+
"#dc2626",
|
|
46
|
+
"#b91c1c",
|
|
47
|
+
"#991b1b",
|
|
48
|
+
"#7f1d1d"
|
|
49
|
+
]);
|
|
50
|
+
var DEFAULT_GREEN = createColorTuple([
|
|
51
|
+
"#ecfdf5",
|
|
52
|
+
"#d1fae5",
|
|
53
|
+
"#a7f3d0",
|
|
54
|
+
"#6ee7b7",
|
|
55
|
+
"#34d399",
|
|
56
|
+
"#10b981",
|
|
57
|
+
"#059669",
|
|
58
|
+
"#047857",
|
|
59
|
+
"#065f46",
|
|
60
|
+
"#064e3b"
|
|
61
|
+
]);
|
|
62
|
+
var DEFAULT_COLORS = {
|
|
63
|
+
brand: DEFAULT_BRAND,
|
|
64
|
+
neutral: DEFAULT_NEUTRAL,
|
|
65
|
+
red: DEFAULT_RED,
|
|
66
|
+
green: DEFAULT_GREEN
|
|
67
|
+
};
|
|
68
|
+
var DEFAULT_SPACING = {
|
|
69
|
+
xs: 4,
|
|
70
|
+
sm: 8,
|
|
71
|
+
md: 12,
|
|
72
|
+
lg: 16,
|
|
73
|
+
xl: 24
|
|
74
|
+
};
|
|
75
|
+
var DEFAULT_RADIUS = {
|
|
76
|
+
xs: 2,
|
|
77
|
+
sm: 4,
|
|
78
|
+
md: 8,
|
|
79
|
+
lg: 12,
|
|
80
|
+
xl: 16,
|
|
81
|
+
pill: 9999
|
|
82
|
+
};
|
|
83
|
+
var DEFAULT_FONT_SIZES = {
|
|
84
|
+
xs: 12,
|
|
85
|
+
sm: 14,
|
|
86
|
+
md: 16,
|
|
87
|
+
lg: 18,
|
|
88
|
+
xl: 20
|
|
89
|
+
};
|
|
90
|
+
var DEFAULT_LINE_HEIGHTS = {
|
|
91
|
+
xs: 1.4,
|
|
92
|
+
sm: 1.45,
|
|
93
|
+
md: 1.55,
|
|
94
|
+
lg: 1.6,
|
|
95
|
+
xl: 1.65
|
|
96
|
+
};
|
|
97
|
+
var DEFAULT_SHADOWS = {
|
|
98
|
+
xs: "0 1px 2px rgba(0, 0, 0, 0.05)",
|
|
99
|
+
sm: "0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04)",
|
|
100
|
+
md: "0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.04)",
|
|
101
|
+
lg: "0 10px 15px rgba(0, 0, 0, 0.08), 0 4px 6px rgba(0, 0, 0, 0.04)",
|
|
102
|
+
xl: "0 20px 25px rgba(0, 0, 0, 0.08), 0 10px 10px rgba(0, 0, 0, 0.03)"
|
|
103
|
+
};
|
|
104
|
+
var DEFAULT_BREAKPOINTS = {
|
|
105
|
+
xs: 0,
|
|
106
|
+
sm: 360,
|
|
107
|
+
md: 768,
|
|
108
|
+
lg: 1024,
|
|
109
|
+
xl: 1280
|
|
110
|
+
};
|
|
111
|
+
var DEFAULT_SYSTEM_BARS_LIGHT = {
|
|
112
|
+
statusBarStyle: "dark",
|
|
113
|
+
statusBarBackgroundColor: "#ffffff",
|
|
114
|
+
navigationBarColor: "#ffffff",
|
|
115
|
+
navigationBarStyle: "dark"
|
|
116
|
+
};
|
|
117
|
+
var DEFAULT_SYSTEM_BARS_DARK = {
|
|
118
|
+
statusBarStyle: "light",
|
|
119
|
+
statusBarBackgroundColor: "#0b0b0f",
|
|
120
|
+
navigationBarColor: "#0b0b0f",
|
|
121
|
+
navigationBarStyle: "light"
|
|
122
|
+
};
|
|
123
|
+
var DEFAULT_THEME = {
|
|
124
|
+
colors: DEFAULT_COLORS,
|
|
125
|
+
primaryColor: "brand",
|
|
126
|
+
primaryShade: { light: 6, dark: 4 },
|
|
127
|
+
spacing: DEFAULT_SPACING,
|
|
128
|
+
radius: DEFAULT_RADIUS,
|
|
129
|
+
fontSizes: DEFAULT_FONT_SIZES,
|
|
130
|
+
lineHeights: DEFAULT_LINE_HEIGHTS,
|
|
131
|
+
shadows: DEFAULT_SHADOWS,
|
|
132
|
+
breakpoints: DEFAULT_BREAKPOINTS,
|
|
133
|
+
fontFamily: "System",
|
|
134
|
+
fontFamilyMono: "Menlo, monospace",
|
|
135
|
+
defaultRadius: "md",
|
|
136
|
+
components: {},
|
|
137
|
+
systemBars: {
|
|
138
|
+
light: DEFAULT_SYSTEM_BARS_LIGHT,
|
|
139
|
+
dark: DEFAULT_SYSTEM_BARS_DARK
|
|
140
|
+
},
|
|
141
|
+
other: {}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// src/theme/ThemeContext.ts
|
|
145
|
+
var SpelycoThemeContext = createContext(DEFAULT_THEME);
|
|
146
|
+
function useSpelycoTheme() {
|
|
147
|
+
return useContext(SpelycoThemeContext);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/factory/useProps.ts
|
|
151
|
+
function useProps(componentName, factoryDefaults, props) {
|
|
152
|
+
const theme = useSpelycoTheme();
|
|
153
|
+
const themeOverride = theme.components[componentName];
|
|
154
|
+
const themeDefaults = themeOverride?.defaultProps;
|
|
155
|
+
const merged = {
|
|
156
|
+
...factoryDefaults,
|
|
157
|
+
...themeDefaults
|
|
158
|
+
};
|
|
159
|
+
const propsRecord = props;
|
|
160
|
+
for (const key in propsRecord) {
|
|
161
|
+
if (propsRecord[key] !== void 0) {
|
|
162
|
+
merged[key] = propsRecord[key];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return merged;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// src/factory/createComponent.ts
|
|
169
|
+
function createComponent(config) {
|
|
170
|
+
const { name, defaultProps, render } = config;
|
|
171
|
+
const Component = ((props) => {
|
|
172
|
+
const merged = useProps(name, defaultProps, props);
|
|
173
|
+
return render(merged);
|
|
174
|
+
});
|
|
175
|
+
Component.displayName = name;
|
|
176
|
+
Component.extend = (override) => override;
|
|
177
|
+
return Component;
|
|
178
|
+
}
|
|
5
179
|
function useBoolean(initialValue = false) {
|
|
6
180
|
const [value, setValue] = useState(initialValue);
|
|
7
181
|
const setTrue = useCallback(() => setValue(true), []);
|
|
@@ -17,29 +191,31 @@ function useDebounce(value, delay = 300) {
|
|
|
17
191
|
}, [value, delay]);
|
|
18
192
|
return debouncedValue;
|
|
19
193
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
NavLink: NavLink.extend({
|
|
35
|
-
defaultProps: {
|
|
36
|
-
color: "gray",
|
|
37
|
-
variant: "light"
|
|
38
|
-
}
|
|
39
|
-
})
|
|
194
|
+
|
|
195
|
+
// src/theme/resolveTheme.ts
|
|
196
|
+
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
197
|
+
function deepMerge(base, override) {
|
|
198
|
+
const result = { ...base };
|
|
199
|
+
for (const key of Object.keys(override)) {
|
|
200
|
+
const overrideValue = override[key];
|
|
201
|
+
if (overrideValue === void 0) continue;
|
|
202
|
+
const baseValue = base[key];
|
|
203
|
+
if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
|
|
204
|
+
result[key] = deepMerge(baseValue, overrideValue);
|
|
205
|
+
} else {
|
|
206
|
+
result[key] = overrideValue;
|
|
207
|
+
}
|
|
40
208
|
}
|
|
41
|
-
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
function resolveTheme(override) {
|
|
212
|
+
if (!override) return DEFAULT_THEME;
|
|
213
|
+
return deepMerge(
|
|
214
|
+
DEFAULT_THEME,
|
|
215
|
+
override
|
|
216
|
+
);
|
|
217
|
+
}
|
|
42
218
|
|
|
43
|
-
export {
|
|
219
|
+
export { DEFAULT_BRAND, DEFAULT_BREAKPOINTS, DEFAULT_COLORS, DEFAULT_FONT_SIZES, DEFAULT_GREEN, DEFAULT_LINE_HEIGHTS, DEFAULT_NEUTRAL, DEFAULT_RADIUS, DEFAULT_RED, DEFAULT_SHADOWS, DEFAULT_SPACING, DEFAULT_SYSTEM_BARS_DARK, DEFAULT_SYSTEM_BARS_LIGHT, DEFAULT_THEME, SpelycoThemeContext, createColorTuple, createComponent, resolveTheme, useBoolean, useDebounce, useProps, useSpelycoTheme };
|
|
44
220
|
//# sourceMappingURL=index.mjs.map
|
|
45
221
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useBoolean.ts","../src/hooks/useDebounce.ts","../src/utils/theme.ts"],"names":["useState"],"mappings":";;;;AAUO,SAAS,UAAA,CAAW,eAAe,KAAA,EAAyB;AACjE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,YAAY,CAAA;AAE/C,EAAA,MAAM,UAAU,WAAA,CAAY,MAAM,SAAS,IAAI,CAAA,EAAG,EAAE,CAAA;AACpD,EAAA,MAAM,WAAW,WAAA,CAAY,MAAM,SAAS,KAAK,CAAA,EAAG,EAAE,CAAA;AACtD,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,MAAM,QAAA,CAAS,CAAC,MAAM,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA;AAExD,EAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAU,QAAQ,QAAA,EAAS;AACtD;AChBO,SAAS,WAAA,CAAe,KAAA,EAAU,KAAA,GAAQ,GAAA,EAAQ;AACvD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,SAAY,KAAK,CAAA;AAE7D,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,iBAAA,CAAkB,KAAK,GAAG,KAAK,CAAA;AAC9D,IAAA,OAAO,MAAM,aAAa,KAAK,CAAA;AAAA,EACjC,CAAA,EAAG,CAAC,KAAA,EAAO,KAAK,CAAC,CAAA;AAEjB,EAAA,OAAO,cAAA;AACT;ACTO,IAAM,KAAA,GAAQ,CAAC,YAAA,KACpB,WAAA,CAAY;AAAA,EACV,cAAc,YAAA,IAAgB,MAAA;AAAA,EAC9B,aAAA,EAAe,IAAA;AAAA,EACf,UAAA,EAAY;AAAA,IACV,MAAA,EAAQ,OAAO,MAAA,CAAO;AAAA,MACpB,YAAA,EAAc;AAAA,QACZ,OAAA,EAAS;AAAA;AACX,KACD,CAAA;AAAA,IACD,UAAA,EAAY,WAAW,MAAA,CAAO;AAAA,MAC5B,YAAA,EAAc;AAAA,QACZ,OAAA,EAAS;AAAA;AACX,KACD,CAAA;AAAA,IACD,OAAA,EAAS,QAAQ,MAAA,CAAO;AAAA,MACtB,YAAA,EAAc;AAAA,QACZ,KAAA,EAAO,MAAA;AAAA,QACP,OAAA,EAAS;AAAA;AACX,KACD;AAAA;AAEL,CAAC","file":"index.mjs","sourcesContent":["import { useCallback, useState } from \"react\";\n\nexport interface UseBooleanReturn {\n value: boolean;\n setTrue: () => void;\n setFalse: () => void;\n toggle: () => void;\n setValue: (value: boolean) => void;\n}\n\nexport function useBoolean(initialValue = false): UseBooleanReturn {\n const [value, setValue] = useState(initialValue);\n\n const setTrue = useCallback(() => setValue(true), []);\n const setFalse = useCallback(() => setValue(false), []);\n const toggle = useCallback(() => setValue((v) => !v), []);\n\n return { value, setTrue, setFalse, toggle, setValue };\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebounce<T>(value: T, delay = 300): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n const timer = setTimeout(() => setDebouncedValue(value), delay);\n return () => clearTimeout(timer);\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { ActionIcon, Button, createTheme, type MantineColor, NavLink } from \"@mantine/core\";\n\nexport const theme = (primaryColor?: MantineColor) =>\n createTheme({\n primaryColor: primaryColor ?? \"dark\",\n defaultRadius: \"md\",\n components: {\n Button: Button.extend({\n defaultProps: {\n variant: \"default\",\n },\n }),\n ActionIcon: ActionIcon.extend({\n defaultProps: {\n variant: \"transparent\",\n },\n }),\n NavLink: NavLink.extend({\n defaultProps: {\n color: \"gray\",\n variant: \"light\",\n },\n }),\n },\n });\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/theme/createColorTuple.ts","../src/theme/defaults.ts","../src/theme/ThemeContext.ts","../src/factory/useProps.ts","../src/factory/createComponent.ts","../src/hooks/useBoolean.ts","../src/hooks/useDebounce.ts","../src/theme/resolveTheme.ts"],"names":["useState"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { ColorTuple } from \"./types\";\n\n/**\n * Wraps an array of 10 color strings into a typed `ColorTuple`. Throws if the\n * array isn't exactly 10 items, which catches palette typos at boot time.\n *\n * For algorithmic shade generation from a single base color, prefer importing\n * shades from a curated palette (e.g. Tailwind) — this lib intentionally ships\n * without an HSL-based generator to keep the surface area small.\n */\nexport function createColorTuple(shades: readonly string[]): ColorTuple {\n if (shades.length !== 10) {\n throw new Error(`createColorTuple expects exactly 10 shades, got ${shades.length}`);\n }\n return shades as unknown as ColorTuple;\n}\n","import { createColorTuple } from \"./createColorTuple\";\nimport type {\n ColorTuple,\n SpelycoBreakpoints,\n SpelycoColors,\n SpelycoFontSizes,\n SpelycoLineHeights,\n SpelycoRadius,\n SpelycoShadows,\n SpelycoSpacing,\n SpelycoSystemBars,\n SpelycoTheme,\n} from \"./types\";\n\n/**\n * Default palettes. Index 0 is the lightest, 9 is the darkest. Sourced from\n * Tailwind's 50–900 ramps (the 950 step is dropped to keep the tuple length\n * at 10).\n */\nexport const DEFAULT_BRAND: ColorTuple = createColorTuple([\n \"#eef2ff\",\n \"#e0e7ff\",\n \"#c7d2fe\",\n \"#a5b4fc\",\n \"#818cf8\",\n \"#6366f1\",\n \"#4f46e5\",\n \"#4338ca\",\n \"#3730a3\",\n \"#312e81\",\n]);\n\nexport const DEFAULT_NEUTRAL: ColorTuple = createColorTuple([\n \"#fafafa\",\n \"#f4f4f5\",\n \"#e4e4e7\",\n \"#d4d4d8\",\n \"#a1a1aa\",\n \"#71717a\",\n \"#52525b\",\n \"#3f3f46\",\n \"#27272a\",\n \"#18181b\",\n]);\n\nexport const DEFAULT_RED: ColorTuple = createColorTuple([\n \"#fef2f2\",\n \"#fee2e2\",\n \"#fecaca\",\n \"#fca5a5\",\n \"#f87171\",\n \"#ef4444\",\n \"#dc2626\",\n \"#b91c1c\",\n \"#991b1b\",\n \"#7f1d1d\",\n]);\n\nexport const DEFAULT_GREEN: ColorTuple = createColorTuple([\n \"#ecfdf5\",\n \"#d1fae5\",\n \"#a7f3d0\",\n \"#6ee7b7\",\n \"#34d399\",\n \"#10b981\",\n \"#059669\",\n \"#047857\",\n \"#065f46\",\n \"#064e3b\",\n]);\n\nexport const DEFAULT_COLORS: SpelycoColors = {\n brand: DEFAULT_BRAND,\n neutral: DEFAULT_NEUTRAL,\n red: DEFAULT_RED,\n green: DEFAULT_GREEN,\n};\n\nexport const DEFAULT_SPACING: SpelycoSpacing = {\n xs: 4,\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n};\n\nexport const DEFAULT_RADIUS: SpelycoRadius = {\n xs: 2,\n sm: 4,\n md: 8,\n lg: 12,\n xl: 16,\n pill: 9999,\n};\n\nexport const DEFAULT_FONT_SIZES: SpelycoFontSizes = {\n xs: 12,\n sm: 14,\n md: 16,\n lg: 18,\n xl: 20,\n};\n\nexport const DEFAULT_LINE_HEIGHTS: SpelycoLineHeights = {\n xs: 1.4,\n sm: 1.45,\n md: 1.55,\n lg: 1.6,\n xl: 1.65,\n};\n\n/**\n * CSS box-shadow strings. RN consumers can map these to elevation locally.\n */\nexport const DEFAULT_SHADOWS: SpelycoShadows = {\n xs: \"0 1px 2px rgba(0, 0, 0, 0.05)\",\n sm: \"0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04)\",\n md: \"0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.04)\",\n lg: \"0 10px 15px rgba(0, 0, 0, 0.08), 0 4px 6px rgba(0, 0, 0, 0.04)\",\n xl: \"0 20px 25px rgba(0, 0, 0, 0.08), 0 10px 10px rgba(0, 0, 0, 0.03)\",\n};\n\n/**\n * `xs: 0` is intentional — Unistyles treats it as the always-active breakpoint.\n */\nexport const DEFAULT_BREAKPOINTS: SpelycoBreakpoints = {\n xs: 0,\n sm: 360,\n md: 768,\n lg: 1024,\n xl: 1280,\n};\n\nexport const DEFAULT_SYSTEM_BARS_LIGHT: SpelycoSystemBars = {\n statusBarStyle: \"dark\",\n statusBarBackgroundColor: \"#ffffff\",\n navigationBarColor: \"#ffffff\",\n navigationBarStyle: \"dark\",\n};\n\nexport const DEFAULT_SYSTEM_BARS_DARK: SpelycoSystemBars = {\n statusBarStyle: \"light\",\n statusBarBackgroundColor: \"#0b0b0f\",\n navigationBarColor: \"#0b0b0f\",\n navigationBarStyle: \"light\",\n};\n\n/**\n * Fully-resolved default theme. Override fields with `<SpelycoProvider theme>`.\n */\nexport const DEFAULT_THEME: SpelycoTheme = {\n colors: DEFAULT_COLORS,\n primaryColor: \"brand\",\n primaryShade: { light: 6, dark: 4 },\n\n spacing: DEFAULT_SPACING,\n radius: DEFAULT_RADIUS,\n fontSizes: DEFAULT_FONT_SIZES,\n lineHeights: DEFAULT_LINE_HEIGHTS,\n shadows: DEFAULT_SHADOWS,\n breakpoints: DEFAULT_BREAKPOINTS,\n\n fontFamily: \"System\",\n fontFamilyMono: \"Menlo, monospace\",\n\n defaultRadius: \"md\",\n\n components: {},\n\n systemBars: {\n light: DEFAULT_SYSTEM_BARS_LIGHT,\n dark: DEFAULT_SYSTEM_BARS_DARK,\n },\n\n other: {},\n};\n","import { createContext, useContext } from \"react\";\nimport { DEFAULT_THEME } from \"./defaults\";\nimport type { SpelycoTheme } from \"./types\";\n\n/**\n * Holds the resolved theme. Platform-specific providers (`SpelycoProvider` in\n * the RN and web packages) write to this context after deep-merging user\n * overrides with `DEFAULT_THEME`.\n */\nexport const SpelycoThemeContext = createContext<SpelycoTheme>(DEFAULT_THEME);\n\nexport function useSpelycoTheme(): SpelycoTheme {\n return useContext(SpelycoThemeContext);\n}\n","import { useSpelycoTheme } from \"../theme/ThemeContext\";\nimport type { SpelycoComponentOverride } from \"../theme/types\";\n\n/**\n * Merges three sources of props in precedence order (later wins):\n * 1. factory defaults — declared inside `createComponent({ defaultProps })`\n * 2. theme defaults — declared via `theme.components[name].defaultProps`\n * 3. user props — passed at the call site\n *\n * `undefined` values in user props are skipped so partially-controlled inputs\n * fall back to defaults instead of forcing `undefined`.\n */\nexport function useProps<TProps extends object>(\n componentName: string,\n factoryDefaults: Partial<TProps> | undefined,\n props: TProps\n): TProps {\n const theme = useSpelycoTheme();\n const themeOverride = theme.components[componentName] as\n | SpelycoComponentOverride<TProps>\n | undefined;\n const themeDefaults = themeOverride?.defaultProps;\n\n const merged: Record<string, unknown> = {\n ...factoryDefaults,\n ...themeDefaults,\n };\n\n const propsRecord = props as Record<string, unknown>;\n for (const key in propsRecord) {\n if (propsRecord[key] !== undefined) {\n merged[key] = propsRecord[key];\n }\n }\n\n return merged as TProps;\n}\n","import type { ReactElement } from \"react\";\nimport type { SpelycoComponentOverride } from \"../theme/types\";\nimport { useProps } from \"./useProps\";\n\nexport interface CreateComponentConfig<TProps extends object> {\n /** Used as the key for `theme.components[name]` overrides. */\n name: string;\n defaultProps?: Partial<TProps>;\n render: (props: TProps) => ReactElement | null;\n}\n\nexport interface SpelycoComponent<TProps extends object> {\n (props: TProps): ReactElement | null;\n displayName: string;\n /**\n * Helper for building a `theme.components[name]` override object — purely\n * sugar, returns its argument with the right shape.\n */\n extend: (override: SpelycoComponentOverride<TProps>) => SpelycoComponentOverride<TProps>;\n}\n\n/**\n * Wraps a render function into a Spelyco component that:\n * - reads `theme.components[name].defaultProps` for runtime overrides\n * - merges factory defaults → theme defaults → user props (later wins)\n * - exposes `.extend()` so consumers can produce override objects\n * - sets `displayName` to the provided `name`\n */\nexport function createComponent<TProps extends object>(\n config: CreateComponentConfig<TProps>\n): SpelycoComponent<TProps> {\n const { name, defaultProps, render } = config;\n\n const Component = ((props: TProps) => {\n const merged = useProps<TProps>(name, defaultProps, props);\n return render(merged);\n }) as SpelycoComponent<TProps>;\n\n Component.displayName = name;\n Component.extend = (override) => override;\n\n return Component;\n}\n","import { useCallback, useState } from \"react\";\n\nexport interface UseBooleanReturn {\n value: boolean;\n setTrue: () => void;\n setFalse: () => void;\n toggle: () => void;\n setValue: (value: boolean) => void;\n}\n\nexport function useBoolean(initialValue = false): UseBooleanReturn {\n const [value, setValue] = useState(initialValue);\n\n const setTrue = useCallback(() => setValue(true), []);\n const setFalse = useCallback(() => setValue(false), []);\n const toggle = useCallback(() => setValue((v) => !v), []);\n\n return { value, setTrue, setFalse, toggle, setValue };\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebounce<T>(value: T, delay = 300): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n useEffect(() => {\n const timer = setTimeout(() => setDebouncedValue(value), delay);\n return () => clearTimeout(timer);\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { DEFAULT_THEME } from \"./defaults\";\nimport type { SpelycoTheme, SpelycoThemeOverride } from \"./types\";\n\ntype PlainObject = Record<string, unknown>;\n\nconst isPlainObject = (value: unknown): value is PlainObject =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nfunction deepMerge(base: PlainObject, override: PlainObject): PlainObject {\n const result: PlainObject = { ...base };\n for (const key of Object.keys(override)) {\n const overrideValue = override[key];\n if (overrideValue === undefined) continue;\n\n const baseValue = base[key];\n if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {\n result[key] = deepMerge(baseValue, overrideValue);\n } else {\n result[key] = overrideValue;\n }\n }\n return result;\n}\n\n/**\n * Merges a partial theme override with the default theme, returning a fully\n * resolved `SpelycoTheme`. Color tuples and arrays are replaced wholesale;\n * plain objects (spacing, components, etc.) are merged key-by-key.\n */\nexport function resolveTheme(override?: SpelycoThemeOverride): SpelycoTheme {\n if (!override) return DEFAULT_THEME;\n return deepMerge(\n DEFAULT_THEME as unknown as PlainObject,\n override as unknown as PlainObject\n ) as unknown as SpelycoTheme;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spelyco/react-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Shared React hooks and utilities for Spelyco UI packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -32,11 +32,9 @@
|
|
|
32
32
|
"clean": "rm -rf dist"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@mantine/core": ">=9",
|
|
36
35
|
"react": ">=18"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
39
|
-
"@mantine/core": "^9.0.1",
|
|
40
38
|
"@spelyco/tsconfig": "*",
|
|
41
39
|
"@testing-library/react": "^16.1.0",
|
|
42
40
|
"@types/react": "^19.2.14",
|