@draftbit/theme 50.6.2-4142fd.2 → 50.6.2-8430ca.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/lib/commonjs/DefaultTheme.js +1 -1
- package/lib/commonjs/Provider.js +1 -1
- package/lib/commonjs/createTheme.js +1 -1
- package/lib/commonjs/createThemeValuesProxy.js +1 -1
- package/lib/commonjs/types.js +0 -1
- package/lib/commonjs/validators.js +1 -1
- package/lib/typescript/src/DefaultTheme.js +38 -38
- package/lib/typescript/src/DefaultTheme.js.map +1 -1
- package/lib/typescript/src/Provider.js +11 -29
- package/lib/typescript/src/Provider.js.map +1 -1
- package/lib/typescript/src/createTheme.d.ts +0 -12
- package/lib/typescript/src/createTheme.js +1 -13
- package/lib/typescript/src/createTheme.js.map +1 -1
- package/lib/typescript/src/createThemeValuesProxy.d.ts +1 -9
- package/lib/typescript/src/createThemeValuesProxy.js +26 -48
- package/lib/typescript/src/createThemeValuesProxy.js.map +1 -1
- package/lib/typescript/src/types.d.ts +2 -30
- package/lib/typescript/src/validators.d.ts +1 -3
- package/lib/typescript/src/validators.js +42 -81
- package/lib/typescript/src/validators.js.map +1 -1
- package/lib/typescript/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/DefaultTheme.js +38 -38
- package/src/DefaultTheme.js.map +1 -1
- package/src/DefaultTheme.ts +38 -38
- package/src/Provider.js +11 -29
- package/src/Provider.js.map +1 -1
- package/src/Provider.tsx +41 -29
- package/src/createTheme.js +1 -13
- package/src/createTheme.js.map +1 -1
- package/src/createTheme.ts +1 -14
- package/src/createThemeValuesProxy.js +26 -48
- package/src/createThemeValuesProxy.js.map +1 -1
- package/src/createThemeValuesProxy.ts +95 -75
- package/src/types.ts +2 -33
- package/src/validators.js +42 -81
- package/src/validators.js.map +1 -1
- package/src/validators.ts +46 -103
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { ThemeValues, Breakpoints } from "./types";
|
|
2
|
-
import { Platform
|
|
2
|
+
import { Platform } from "react-native";
|
|
3
3
|
import { isObject } from "lodash";
|
|
4
4
|
|
|
5
|
-
interface CreateThemeValuesProxyInput {
|
|
6
|
-
value: ThemeValues | undefined;
|
|
7
|
-
breakpoints: Breakpoints;
|
|
8
|
-
deviceWidth: number;
|
|
9
|
-
devicePlatform: typeof Platform.OS;
|
|
10
|
-
currentLightDarkSelection: "light" | "dark";
|
|
11
|
-
}
|
|
12
|
-
|
|
13
5
|
/**
|
|
14
6
|
* Creates a proxy for theme value objects to select a value whenever
|
|
15
7
|
* multiple values are provided for different platforms, breakpoints, and/or light/dark modes
|
|
@@ -17,13 +9,13 @@ interface CreateThemeValuesProxyInput {
|
|
|
17
9
|
* Ex: {color: {ios: "blue", android: "red"}}
|
|
18
10
|
* -> theme.color returns "blue" when the platform is ios and "red" when android
|
|
19
11
|
*/
|
|
20
|
-
export default function createThemeValuesProxy(
|
|
21
|
-
value,
|
|
22
|
-
breakpoints,
|
|
23
|
-
deviceWidth,
|
|
24
|
-
devicePlatform,
|
|
25
|
-
currentLightDarkSelection
|
|
26
|
-
|
|
12
|
+
export default function createThemeValuesProxy(
|
|
13
|
+
value: ThemeValues | undefined,
|
|
14
|
+
breakpoints: Breakpoints,
|
|
15
|
+
deviceWidth: number,
|
|
16
|
+
devicePlatform: typeof Platform.OS,
|
|
17
|
+
currentLightDarkSelection: "light" | "dark"
|
|
18
|
+
): any /* return type 'any' to allow arbitrary object references (object.example.another.there) */ {
|
|
27
19
|
if (value === undefined || value === null) {
|
|
28
20
|
return undefined;
|
|
29
21
|
}
|
|
@@ -31,46 +23,56 @@ export default function createThemeValuesProxy({
|
|
|
31
23
|
get: (
|
|
32
24
|
target: ThemeValues,
|
|
33
25
|
key: string
|
|
34
|
-
): string | number | ThemeValues |
|
|
26
|
+
): string | number | ThemeValues | undefined => {
|
|
35
27
|
const currentValue = target[key];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
: undefined;
|
|
40
|
-
|
|
41
|
-
if (valueAsThemeValues) {
|
|
28
|
+
if (!isObject(currentValue)) {
|
|
29
|
+
return currentValue;
|
|
30
|
+
} else {
|
|
42
31
|
const platformKeys = ["ios", "android", "web", "macos", "windows"];
|
|
43
32
|
const breakpointKeys = Object.keys(breakpoints);
|
|
44
33
|
const lightDarkKeys = ["light", "dark"];
|
|
45
|
-
|
|
46
34
|
const keysType = getKeysType(
|
|
47
|
-
|
|
35
|
+
currentValue,
|
|
48
36
|
platformKeys,
|
|
49
37
|
breakpointKeys,
|
|
50
38
|
lightDarkKeys
|
|
51
39
|
);
|
|
52
40
|
|
|
53
|
-
const input: CreateThemeValuesProxyInput = {
|
|
54
|
-
value: valueAsThemeValues,
|
|
55
|
-
breakpoints,
|
|
56
|
-
deviceWidth,
|
|
57
|
-
devicePlatform,
|
|
58
|
-
currentLightDarkSelection,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
41
|
if (keysType === "default") {
|
|
62
|
-
return createThemeValuesProxy(
|
|
42
|
+
return createThemeValuesProxy(
|
|
43
|
+
currentValue,
|
|
44
|
+
breakpoints,
|
|
45
|
+
deviceWidth,
|
|
46
|
+
devicePlatform,
|
|
47
|
+
currentLightDarkSelection
|
|
48
|
+
);
|
|
63
49
|
} else if (keysType === "platform") {
|
|
64
|
-
return getPlatformValue(
|
|
50
|
+
return getPlatformValue(
|
|
51
|
+
currentValue,
|
|
52
|
+
breakpoints,
|
|
53
|
+
deviceWidth,
|
|
54
|
+
devicePlatform,
|
|
55
|
+
currentLightDarkSelection
|
|
56
|
+
);
|
|
65
57
|
} else if (keysType === "breakpoint") {
|
|
66
|
-
return getBreakpointValue(
|
|
58
|
+
return getBreakpointValue(
|
|
59
|
+
currentValue,
|
|
60
|
+
breakpoints,
|
|
61
|
+
deviceWidth,
|
|
62
|
+
devicePlatform,
|
|
63
|
+
currentLightDarkSelection
|
|
64
|
+
);
|
|
67
65
|
} else if (keysType === "lightDark") {
|
|
68
|
-
return getLightDarkValue(
|
|
66
|
+
return getLightDarkValue(
|
|
67
|
+
currentValue,
|
|
68
|
+
breakpoints,
|
|
69
|
+
deviceWidth,
|
|
70
|
+
devicePlatform,
|
|
71
|
+
currentLightDarkSelection
|
|
72
|
+
);
|
|
69
73
|
} else {
|
|
70
74
|
return undefined;
|
|
71
75
|
}
|
|
72
|
-
} else {
|
|
73
|
-
return currentValue;
|
|
74
76
|
}
|
|
75
77
|
},
|
|
76
78
|
set: () => {
|
|
@@ -137,27 +139,37 @@ function allFalse(a: boolean, b: boolean, c: boolean, d: boolean) {
|
|
|
137
139
|
return [a, b, c, d].filter((x) => x).length === 0;
|
|
138
140
|
}
|
|
139
141
|
|
|
140
|
-
function getPlatformValue(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
return createThemeValuesProxy({ ...input, value: valueAsThemeValues });
|
|
150
|
-
} else {
|
|
142
|
+
function getPlatformValue(
|
|
143
|
+
value: ThemeValues,
|
|
144
|
+
breakpoints: Breakpoints,
|
|
145
|
+
deviceWidth: number,
|
|
146
|
+
devicePlatform: typeof Platform.OS,
|
|
147
|
+
currentLightDarkSelection: "light" | "dark"
|
|
148
|
+
) {
|
|
149
|
+
const currentPlatformValue = value[devicePlatform] ?? value.default;
|
|
150
|
+
if (!isObject(currentPlatformValue)) {
|
|
151
151
|
return currentPlatformValue;
|
|
152
|
+
} else {
|
|
153
|
+
return createThemeValuesProxy(
|
|
154
|
+
currentPlatformValue,
|
|
155
|
+
breakpoints,
|
|
156
|
+
deviceWidth,
|
|
157
|
+
devicePlatform,
|
|
158
|
+
currentLightDarkSelection
|
|
159
|
+
);
|
|
152
160
|
}
|
|
153
161
|
}
|
|
154
162
|
|
|
155
|
-
function getBreakpointValue(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
function getBreakpointValue(
|
|
164
|
+
value: ThemeValues,
|
|
165
|
+
breakpoints: Breakpoints,
|
|
166
|
+
deviceWidth: number,
|
|
167
|
+
devicePlatform: typeof Platform.OS,
|
|
168
|
+
currentLightDarkSelection: "light" | "dark"
|
|
169
|
+
) {
|
|
170
|
+
const keysToBreakpointValue: [string, number][] = Object.keys(value).map(
|
|
171
|
+
(key) => [key, breakpoints[key]]
|
|
172
|
+
);
|
|
161
173
|
const orderedBreakpoints = keysToBreakpointValue.sort(([_, val]) => val);
|
|
162
174
|
let currentBreakpointKey = "";
|
|
163
175
|
for (const [breakpointKey, breakpointValue] of orderedBreakpoints) {
|
|
@@ -165,31 +177,39 @@ function getBreakpointValue(input: CreateThemeValuesProxyInput) {
|
|
|
165
177
|
currentBreakpointKey = breakpointKey;
|
|
166
178
|
}
|
|
167
179
|
}
|
|
168
|
-
const currentBreakpointValue =
|
|
169
|
-
|
|
170
|
-
const valueAsThemeValues = isObject(currentBreakpointKey)
|
|
171
|
-
? (currentBreakpointKey as ThemeValues)
|
|
172
|
-
: undefined;
|
|
173
|
-
|
|
174
|
-
if (valueAsThemeValues) {
|
|
175
|
-
return createThemeValuesProxy({ ...input, value: valueAsThemeValues });
|
|
176
|
-
} else {
|
|
180
|
+
const currentBreakpointValue = value[currentBreakpointKey] ?? value.default;
|
|
181
|
+
if (!isObject(currentBreakpointValue)) {
|
|
177
182
|
return currentBreakpointValue;
|
|
183
|
+
} else {
|
|
184
|
+
return createThemeValuesProxy(
|
|
185
|
+
currentBreakpointValue,
|
|
186
|
+
breakpoints,
|
|
187
|
+
deviceWidth,
|
|
188
|
+
devicePlatform,
|
|
189
|
+
currentLightDarkSelection
|
|
190
|
+
);
|
|
178
191
|
}
|
|
179
192
|
}
|
|
180
193
|
|
|
181
|
-
function getLightDarkValue(
|
|
182
|
-
|
|
183
|
-
|
|
194
|
+
function getLightDarkValue(
|
|
195
|
+
value: ThemeValues,
|
|
196
|
+
breakpoints: Breakpoints,
|
|
197
|
+
deviceWidth: number,
|
|
198
|
+
devicePlatform: typeof Platform.OS,
|
|
199
|
+
currentLightDarkSelection: "light" | "dark"
|
|
200
|
+
) {
|
|
184
201
|
const currentLightDarkValue =
|
|
185
|
-
value
|
|
186
|
-
const valueAsThemeValues = isObject(currentLightDarkSelection)
|
|
187
|
-
? (currentLightDarkSelection as ThemeValues)
|
|
188
|
-
: undefined;
|
|
202
|
+
value[currentLightDarkSelection] ?? value.default;
|
|
189
203
|
|
|
190
|
-
if (
|
|
191
|
-
return createThemeValuesProxy({ ...input, value: valueAsThemeValues });
|
|
192
|
-
} else {
|
|
204
|
+
if (!isObject(currentLightDarkValue)) {
|
|
193
205
|
return currentLightDarkValue;
|
|
206
|
+
} else {
|
|
207
|
+
return createThemeValuesProxy(
|
|
208
|
+
currentLightDarkValue,
|
|
209
|
+
breakpoints,
|
|
210
|
+
deviceWidth,
|
|
211
|
+
devicePlatform,
|
|
212
|
+
currentLightDarkSelection
|
|
213
|
+
);
|
|
194
214
|
}
|
|
195
215
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { TextStyle } from "react-native";
|
|
2
|
-
|
|
3
1
|
export type ThemeValues = {
|
|
4
|
-
[key: string]: string | number |
|
|
2
|
+
[key: string]: string | number | ThemeValues;
|
|
5
3
|
};
|
|
6
4
|
|
|
7
5
|
export type Theme = {
|
|
@@ -13,21 +11,7 @@ export type Theme = {
|
|
|
13
11
|
foreground?: ThemeValues;
|
|
14
12
|
border?: ThemeValues;
|
|
15
13
|
};
|
|
16
|
-
typography: {
|
|
17
|
-
body1?: ThemeValues | TextStyle;
|
|
18
|
-
body2?: ThemeValues | TextStyle;
|
|
19
|
-
button?: ThemeValues | TextStyle;
|
|
20
|
-
caption?: ThemeValues | TextStyle;
|
|
21
|
-
headline1?: ThemeValues | TextStyle;
|
|
22
|
-
headline2?: ThemeValues | TextStyle;
|
|
23
|
-
headline3?: ThemeValues | TextStyle;
|
|
24
|
-
headline4?: ThemeValues | TextStyle;
|
|
25
|
-
headline5?: ThemeValues | TextStyle;
|
|
26
|
-
headline6?: ThemeValues | TextStyle;
|
|
27
|
-
overline?: ThemeValues | TextStyle;
|
|
28
|
-
subtitle1?: ThemeValues | TextStyle;
|
|
29
|
-
subtitle2?: ThemeValues | TextStyle;
|
|
30
|
-
};
|
|
14
|
+
typography: { [key: string]: any }; //TODO: Update theme to support typography. Left as 'any' for legacy support until updated and migrated
|
|
31
15
|
};
|
|
32
16
|
|
|
33
17
|
export type ValidatedTheme = Theme & {
|
|
@@ -42,21 +26,6 @@ export type ReadTheme = Theme & {
|
|
|
42
26
|
foreground?: any;
|
|
43
27
|
border?: any;
|
|
44
28
|
};
|
|
45
|
-
typography: {
|
|
46
|
-
body1?: any;
|
|
47
|
-
body2?: any;
|
|
48
|
-
button?: any;
|
|
49
|
-
caption?: any;
|
|
50
|
-
headline1?: any;
|
|
51
|
-
headline2?: any;
|
|
52
|
-
headline3?: any;
|
|
53
|
-
headline4?: any;
|
|
54
|
-
headline5?: any;
|
|
55
|
-
headline6?: any;
|
|
56
|
-
overline?: any;
|
|
57
|
-
subtitle1?: any;
|
|
58
|
-
subtitle2?: any;
|
|
59
|
-
};
|
|
60
29
|
};
|
|
61
30
|
|
|
62
31
|
export type ColorPaletteValues = {
|
package/src/validators.js
CHANGED
|
@@ -1,91 +1,52 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
const PaletteSchema = z.record(z.string(), z.record(z.string(), z.string()));
|
|
3
|
-
const BreakpointSchema = z.record(z.string(), z.number());
|
|
4
|
-
const TextStyleSchema = z.union([
|
|
5
|
-
z.object({
|
|
6
|
-
fontSize: z.number(),
|
|
7
|
-
}),
|
|
8
|
-
z.object({
|
|
9
|
-
fontFamily: z.string(),
|
|
10
|
-
}),
|
|
11
|
-
z.object({
|
|
12
|
-
fontWeight: z.enum([
|
|
13
|
-
"normal",
|
|
14
|
-
"bold",
|
|
15
|
-
"100",
|
|
16
|
-
"200",
|
|
17
|
-
"300",
|
|
18
|
-
"400",
|
|
19
|
-
"500",
|
|
20
|
-
"600",
|
|
21
|
-
"700",
|
|
22
|
-
"800",
|
|
23
|
-
"900",
|
|
24
|
-
]),
|
|
25
|
-
}),
|
|
26
|
-
z.object({
|
|
27
|
-
fontStyle: z.enum(["normal", "italic"]),
|
|
28
|
-
}),
|
|
29
|
-
z.object({
|
|
30
|
-
letterSpacing: z.number(),
|
|
31
|
-
}),
|
|
32
|
-
z.object({
|
|
33
|
-
lineHeight: z.number(),
|
|
34
|
-
}),
|
|
35
|
-
]);
|
|
36
|
-
const ThemeValuesSchema = z.record(z.string(), z.lazy(() => z.union([z.string(), z.number(), TextStyleSchema, ThemeValuesSchema])));
|
|
37
|
-
const TextStyleOrThemeValuesSchema = z.union([TextStyleSchema, ThemeValuesSchema]);
|
|
38
|
-
const ThemeSchema = z.object({
|
|
39
|
-
name: z.string(),
|
|
40
|
-
colors: z.object({
|
|
41
|
-
branding: ThemeValuesSchema.optional(),
|
|
42
|
-
text: ThemeValuesSchema.optional(),
|
|
43
|
-
background: ThemeValuesSchema.optional(),
|
|
44
|
-
foreground: ThemeValuesSchema.optional(),
|
|
45
|
-
border: ThemeValuesSchema.optional(),
|
|
46
|
-
}),
|
|
47
|
-
typography: z.object({
|
|
48
|
-
body1: TextStyleOrThemeValuesSchema.optional(),
|
|
49
|
-
body2: TextStyleOrThemeValuesSchema.optional(),
|
|
50
|
-
button: TextStyleOrThemeValuesSchema.optional(),
|
|
51
|
-
caption: TextStyleOrThemeValuesSchema.optional(),
|
|
52
|
-
headline1: TextStyleOrThemeValuesSchema.optional(),
|
|
53
|
-
headline2: TextStyleOrThemeValuesSchema.optional(),
|
|
54
|
-
headline3: TextStyleOrThemeValuesSchema.optional(),
|
|
55
|
-
headline4: TextStyleOrThemeValuesSchema.optional(),
|
|
56
|
-
headline5: TextStyleOrThemeValuesSchema.optional(),
|
|
57
|
-
headline6: TextStyleOrThemeValuesSchema.optional(),
|
|
58
|
-
overline: TextStyleOrThemeValuesSchema.optional(),
|
|
59
|
-
subtitle1: TextStyleOrThemeValuesSchema.optional(),
|
|
60
|
-
subtitle2: TextStyleOrThemeValuesSchema.optional(),
|
|
61
|
-
}),
|
|
62
|
-
});
|
|
63
1
|
export function validatePalettes(palettes) {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
2
|
+
for (const key of Object.keys(palettes)) {
|
|
3
|
+
if (typeof key !== "string") {
|
|
4
|
+
throw new Error(`Invalid palettes object, ${key} is not a string`);
|
|
5
|
+
}
|
|
6
|
+
for (const [innerKey, value] of Object.entries(palettes[key])) {
|
|
7
|
+
if (typeof innerKey !== "string") {
|
|
8
|
+
throw new Error(`Invalid palette color key, ${innerKey} is not a string`);
|
|
9
|
+
}
|
|
10
|
+
if (typeof value !== "string") {
|
|
11
|
+
throw new Error(`Invalid palette color value, ${value} is not a string`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
67
14
|
}
|
|
68
15
|
}
|
|
69
16
|
export function validateBreakpoints(breakpoints) {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
17
|
+
for (const [key, value] of Object.entries(breakpoints)) {
|
|
18
|
+
if (typeof key !== "string") {
|
|
19
|
+
throw new Error(`Invalid breakpoint key, ${key} is not a string`);
|
|
20
|
+
}
|
|
21
|
+
if (typeof value !== "number") {
|
|
22
|
+
throw new Error(`Invalid breakpoint value, ${value} is not a number`);
|
|
23
|
+
}
|
|
73
24
|
}
|
|
74
25
|
}
|
|
75
26
|
export function validateTheme(theme) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
27
|
+
function validateThemeValues(themeValue) {
|
|
28
|
+
if (themeValue === undefined || themeValue === null) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const [key, value] of Object.entries(themeValue)) {
|
|
32
|
+
if (typeof key !== "string") {
|
|
33
|
+
throw new Error(`Invalid theme key, ${key} is not a string`);
|
|
34
|
+
}
|
|
35
|
+
if (value === undefined || value === null) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
else if (typeof value === "object") {
|
|
39
|
+
validateThemeValues(value);
|
|
40
|
+
}
|
|
41
|
+
else if (typeof value !== "string" && typeof value !== "number") {
|
|
42
|
+
throw new Error(`Invalid theme value, ${value} is not a string, number, or object`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
79
45
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// Text style matches the shape of ThemeValues, but we don't want to treat it as a ThemeValues
|
|
86
|
-
if (isTextStyleObject(value)) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
return ThemeValuesSchema.safeParse(value).success ? value : null;
|
|
46
|
+
validateThemeValues(theme.colors.branding);
|
|
47
|
+
validateThemeValues(theme.colors.text);
|
|
48
|
+
validateThemeValues(theme.colors.foreground);
|
|
49
|
+
validateThemeValues(theme.colors.background);
|
|
50
|
+
validateThemeValues(theme.colors.border);
|
|
90
51
|
}
|
|
91
52
|
//# sourceMappingURL=validators.js.map
|
package/src/validators.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.js","sourceRoot":"","sources":["validators.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["validators.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,QAAuB;IACtD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,kBAAkB,CAAC,CAAC;SACpE;QACD,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE;YAC7D,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;gBAChC,MAAM,IAAI,KAAK,CACb,8BAA8B,QAAQ,kBAAkB,CACzD,CAAC;aACH;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAC7B,MAAM,IAAI,KAAK,CACb,gCAAgC,KAAK,kBAAkB,CACxD,CAAC;aACH;SACF;KACF;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,WAAwB;IAC1D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;QACtD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,kBAAkB,CAAC,CAAC;SACnE;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,kBAAkB,CAAC,CAAC;SACvE;KACF;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAY;IACxC,SAAS,mBAAmB,CAAC,UAAwB;QACnD,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,IAAI,EAAE;YACnD,OAAO;SACR;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YACrD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;gBAC3B,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,kBAAkB,CAAC,CAAC;aAC9D;YACD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE;gBACzC,SAAS;aACV;iBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBACpC,mBAAmB,CAAC,KAAK,CAAC,CAAC;aAC5B;iBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBACjE,MAAM,IAAI,KAAK,CACb,wBAAwB,KAAK,qCAAqC,CACnE,CAAC;aACH;SACF;IACH,CAAC;IACD,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3C,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvC,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7C,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7C,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC"}
|
package/src/validators.ts
CHANGED
|
@@ -1,116 +1,59 @@
|
|
|
1
1
|
import { ColorPalettes, Breakpoints, Theme, ThemeValues } from "./types";
|
|
2
|
-
import { TextStyle } from "react-native";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
|
|
5
|
-
const PaletteSchema: z.ZodType<ColorPalettes> = z.record(
|
|
6
|
-
z.string(),
|
|
7
|
-
z.record(z.string(), z.string())
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
const BreakpointSchema: z.ZodType<Breakpoints> = z.record(
|
|
11
|
-
z.string(),
|
|
12
|
-
z.number()
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
const TextStyleSchema: z.ZodType<TextStyle> = z.union([
|
|
16
|
-
z.object({
|
|
17
|
-
fontSize: z.number(),
|
|
18
|
-
}),
|
|
19
|
-
z.object({
|
|
20
|
-
fontFamily: z.string(),
|
|
21
|
-
}),
|
|
22
|
-
z.object({
|
|
23
|
-
fontWeight: z.enum([
|
|
24
|
-
"normal",
|
|
25
|
-
"bold",
|
|
26
|
-
"100",
|
|
27
|
-
"200",
|
|
28
|
-
"300",
|
|
29
|
-
"400",
|
|
30
|
-
"500",
|
|
31
|
-
"600",
|
|
32
|
-
"700",
|
|
33
|
-
"800",
|
|
34
|
-
"900",
|
|
35
|
-
]),
|
|
36
|
-
}),
|
|
37
|
-
z.object({
|
|
38
|
-
fontStyle: z.enum(["normal", "italic"]),
|
|
39
|
-
}),
|
|
40
|
-
z.object({
|
|
41
|
-
letterSpacing: z.number(),
|
|
42
|
-
}),
|
|
43
|
-
z.object({
|
|
44
|
-
lineHeight: z.number(),
|
|
45
|
-
}),
|
|
46
|
-
]);
|
|
47
|
-
|
|
48
|
-
const ThemeValuesSchema: z.ZodType<ThemeValues> = z.record(
|
|
49
|
-
z.string(),
|
|
50
|
-
z.lazy(() =>
|
|
51
|
-
z.union([z.string(), z.number(), TextStyleSchema, ThemeValuesSchema])
|
|
52
|
-
)
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
const TextStyleOrThemeValuesSchema: z.ZodType<ThemeValues | TextStyle> =
|
|
56
|
-
z.union([TextStyleSchema, ThemeValuesSchema]);
|
|
57
|
-
|
|
58
|
-
const ThemeSchema: z.ZodType<Theme> = z.object({
|
|
59
|
-
name: z.string(),
|
|
60
|
-
colors: z.object({
|
|
61
|
-
branding: ThemeValuesSchema.optional(),
|
|
62
|
-
text: ThemeValuesSchema.optional(),
|
|
63
|
-
background: ThemeValuesSchema.optional(),
|
|
64
|
-
foreground: ThemeValuesSchema.optional(),
|
|
65
|
-
border: ThemeValuesSchema.optional(),
|
|
66
|
-
}),
|
|
67
|
-
typography: z.object({
|
|
68
|
-
body1: TextStyleOrThemeValuesSchema.optional(),
|
|
69
|
-
body2: TextStyleOrThemeValuesSchema.optional(),
|
|
70
|
-
button: TextStyleOrThemeValuesSchema.optional(),
|
|
71
|
-
caption: TextStyleOrThemeValuesSchema.optional(),
|
|
72
|
-
headline1: TextStyleOrThemeValuesSchema.optional(),
|
|
73
|
-
headline2: TextStyleOrThemeValuesSchema.optional(),
|
|
74
|
-
headline3: TextStyleOrThemeValuesSchema.optional(),
|
|
75
|
-
headline4: TextStyleOrThemeValuesSchema.optional(),
|
|
76
|
-
headline5: TextStyleOrThemeValuesSchema.optional(),
|
|
77
|
-
headline6: TextStyleOrThemeValuesSchema.optional(),
|
|
78
|
-
overline: TextStyleOrThemeValuesSchema.optional(),
|
|
79
|
-
subtitle1: TextStyleOrThemeValuesSchema.optional(),
|
|
80
|
-
subtitle2: TextStyleOrThemeValuesSchema.optional(),
|
|
81
|
-
}),
|
|
82
|
-
});
|
|
83
2
|
|
|
84
3
|
export function validatePalettes(palettes: ColorPalettes) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
4
|
+
for (const key of Object.keys(palettes)) {
|
|
5
|
+
if (typeof key !== "string") {
|
|
6
|
+
throw new Error(`Invalid palettes object, ${key} is not a string`);
|
|
7
|
+
}
|
|
8
|
+
for (const [innerKey, value] of Object.entries(palettes[key])) {
|
|
9
|
+
if (typeof innerKey !== "string") {
|
|
10
|
+
throw new Error(
|
|
11
|
+
`Invalid palette color key, ${innerKey} is not a string`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
if (typeof value !== "string") {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Invalid palette color value, ${value} is not a string`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
88
20
|
}
|
|
89
21
|
}
|
|
90
22
|
|
|
91
23
|
export function validateBreakpoints(breakpoints: Breakpoints) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
24
|
+
for (const [key, value] of Object.entries(breakpoints)) {
|
|
25
|
+
if (typeof key !== "string") {
|
|
26
|
+
throw new Error(`Invalid breakpoint key, ${key} is not a string`);
|
|
27
|
+
}
|
|
28
|
+
if (typeof value !== "number") {
|
|
29
|
+
throw new Error(`Invalid breakpoint value, ${value} is not a number`);
|
|
30
|
+
}
|
|
95
31
|
}
|
|
96
32
|
}
|
|
97
33
|
|
|
98
34
|
export function validateTheme(theme: Theme) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
35
|
+
function validateThemeValues(themeValue?: ThemeValues) {
|
|
36
|
+
if (themeValue === undefined || themeValue === null) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
for (const [key, value] of Object.entries(themeValue)) {
|
|
40
|
+
if (typeof key !== "string") {
|
|
41
|
+
throw new Error(`Invalid theme key, ${key} is not a string`);
|
|
42
|
+
}
|
|
43
|
+
if (value === undefined || value === null) {
|
|
44
|
+
continue;
|
|
45
|
+
} else if (typeof value === "object") {
|
|
46
|
+
validateThemeValues(value);
|
|
47
|
+
} else if (typeof value !== "string" && typeof value !== "number") {
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Invalid theme value, ${value} is not a string, number, or object`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
102
53
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
export function asThemeValuesObject(value: any): ThemeValues | null {
|
|
110
|
-
// Text style matches the shape of ThemeValues, but we don't want to treat it as a ThemeValues
|
|
111
|
-
if (isTextStyleObject(value)) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return ThemeValuesSchema.safeParse(value).success ? value : null;
|
|
54
|
+
validateThemeValues(theme.colors.branding);
|
|
55
|
+
validateThemeValues(theme.colors.text);
|
|
56
|
+
validateThemeValues(theme.colors.foreground);
|
|
57
|
+
validateThemeValues(theme.colors.background);
|
|
58
|
+
validateThemeValues(theme.colors.border);
|
|
116
59
|
}
|