@draftbit/theme 50.5.4-27aeb2.2 → 50.5.4-e9e0de.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 +10 -14
- package/lib/typescript/src/Provider.js.map +1 -1
- package/lib/typescript/src/createTheme.js +3 -25
- package/lib/typescript/src/createTheme.js.map +1 -1
- package/lib/typescript/src/createThemeValuesProxy.js +19 -23
- 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 +5 -5
- package/src/DefaultTheme.js +38 -38
- package/src/DefaultTheme.js.map +1 -1
- package/src/DefaultTheme.ts +38 -38
- package/src/Provider.js +10 -14
- package/src/Provider.js.map +1 -1
- package/src/Provider.tsx +40 -20
- package/src/createTheme.js +3 -25
- package/src/createTheme.js.map +1 -1
- package/src/createTheme.ts +2 -30
- package/src/createThemeValuesProxy.js +19 -23
- package/src/createThemeValuesProxy.js.map +1 -1
- package/src/createThemeValuesProxy.ts +23 -32
- 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,6 +1,6 @@
|
|
|
1
1
|
import { ThemeValues, Breakpoints } from "./types";
|
|
2
|
-
import { Platform
|
|
3
|
-
import {
|
|
2
|
+
import { Platform } from "react-native";
|
|
3
|
+
import { isObject } from "lodash";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Creates a proxy for theme value objects to select a value whenever
|
|
@@ -23,18 +23,16 @@ export default function createThemeValuesProxy(
|
|
|
23
23
|
get: (
|
|
24
24
|
target: ThemeValues,
|
|
25
25
|
key: string
|
|
26
|
-
): string | number | ThemeValues |
|
|
26
|
+
): string | number | ThemeValues | undefined => {
|
|
27
27
|
const currentValue = target[key];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (valueAsThemeValues) {
|
|
28
|
+
if (!isObject(currentValue)) {
|
|
29
|
+
return currentValue;
|
|
30
|
+
} else {
|
|
32
31
|
const platformKeys = ["ios", "android", "web", "macos", "windows"];
|
|
33
32
|
const breakpointKeys = Object.keys(breakpoints);
|
|
34
33
|
const lightDarkKeys = ["light", "dark"];
|
|
35
|
-
|
|
36
34
|
const keysType = getKeysType(
|
|
37
|
-
|
|
35
|
+
currentValue,
|
|
38
36
|
platformKeys,
|
|
39
37
|
breakpointKeys,
|
|
40
38
|
lightDarkKeys
|
|
@@ -42,7 +40,7 @@ export default function createThemeValuesProxy(
|
|
|
42
40
|
|
|
43
41
|
if (keysType === "default") {
|
|
44
42
|
return createThemeValuesProxy(
|
|
45
|
-
|
|
43
|
+
currentValue,
|
|
46
44
|
breakpoints,
|
|
47
45
|
deviceWidth,
|
|
48
46
|
devicePlatform,
|
|
@@ -50,7 +48,7 @@ export default function createThemeValuesProxy(
|
|
|
50
48
|
);
|
|
51
49
|
} else if (keysType === "platform") {
|
|
52
50
|
return getPlatformValue(
|
|
53
|
-
|
|
51
|
+
currentValue,
|
|
54
52
|
breakpoints,
|
|
55
53
|
deviceWidth,
|
|
56
54
|
devicePlatform,
|
|
@@ -58,7 +56,7 @@ export default function createThemeValuesProxy(
|
|
|
58
56
|
);
|
|
59
57
|
} else if (keysType === "breakpoint") {
|
|
60
58
|
return getBreakpointValue(
|
|
61
|
-
|
|
59
|
+
currentValue,
|
|
62
60
|
breakpoints,
|
|
63
61
|
deviceWidth,
|
|
64
62
|
devicePlatform,
|
|
@@ -66,7 +64,7 @@ export default function createThemeValuesProxy(
|
|
|
66
64
|
);
|
|
67
65
|
} else if (keysType === "lightDark") {
|
|
68
66
|
return getLightDarkValue(
|
|
69
|
-
|
|
67
|
+
currentValue,
|
|
70
68
|
breakpoints,
|
|
71
69
|
deviceWidth,
|
|
72
70
|
devicePlatform,
|
|
@@ -75,8 +73,6 @@ export default function createThemeValuesProxy(
|
|
|
75
73
|
} else {
|
|
76
74
|
return undefined;
|
|
77
75
|
}
|
|
78
|
-
} else {
|
|
79
|
-
return currentValue;
|
|
80
76
|
}
|
|
81
77
|
},
|
|
82
78
|
set: () => {
|
|
@@ -151,18 +147,16 @@ function getPlatformValue(
|
|
|
151
147
|
currentLightDarkSelection: "light" | "dark"
|
|
152
148
|
) {
|
|
153
149
|
const currentPlatformValue = value[devicePlatform] ?? value.default;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
if (!isObject(currentPlatformValue)) {
|
|
151
|
+
return currentPlatformValue;
|
|
152
|
+
} else {
|
|
157
153
|
return createThemeValuesProxy(
|
|
158
|
-
|
|
154
|
+
currentPlatformValue,
|
|
159
155
|
breakpoints,
|
|
160
156
|
deviceWidth,
|
|
161
157
|
devicePlatform,
|
|
162
158
|
currentLightDarkSelection
|
|
163
159
|
);
|
|
164
|
-
} else {
|
|
165
|
-
return currentPlatformValue;
|
|
166
160
|
}
|
|
167
161
|
}
|
|
168
162
|
|
|
@@ -184,18 +178,16 @@ function getBreakpointValue(
|
|
|
184
178
|
}
|
|
185
179
|
}
|
|
186
180
|
const currentBreakpointValue = value[currentBreakpointKey] ?? value.default;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
181
|
+
if (!isObject(currentBreakpointValue)) {
|
|
182
|
+
return currentBreakpointValue;
|
|
183
|
+
} else {
|
|
190
184
|
return createThemeValuesProxy(
|
|
191
|
-
|
|
185
|
+
currentBreakpointValue,
|
|
192
186
|
breakpoints,
|
|
193
187
|
deviceWidth,
|
|
194
188
|
devicePlatform,
|
|
195
189
|
currentLightDarkSelection
|
|
196
190
|
);
|
|
197
|
-
} else {
|
|
198
|
-
return currentBreakpointValue;
|
|
199
191
|
}
|
|
200
192
|
}
|
|
201
193
|
|
|
@@ -208,17 +200,16 @@ function getLightDarkValue(
|
|
|
208
200
|
) {
|
|
209
201
|
const currentLightDarkValue =
|
|
210
202
|
value[currentLightDarkSelection] ?? value.default;
|
|
211
|
-
const valueAsThemeValues = asThemeValuesObject(currentLightDarkValue);
|
|
212
203
|
|
|
213
|
-
if (
|
|
204
|
+
if (!isObject(currentLightDarkValue)) {
|
|
205
|
+
return currentLightDarkValue;
|
|
206
|
+
} else {
|
|
214
207
|
return createThemeValuesProxy(
|
|
215
|
-
|
|
208
|
+
currentLightDarkValue,
|
|
216
209
|
breakpoints,
|
|
217
210
|
deviceWidth,
|
|
218
211
|
devicePlatform,
|
|
219
212
|
currentLightDarkSelection
|
|
220
213
|
);
|
|
221
|
-
} else {
|
|
222
|
-
return currentLightDarkValue;
|
|
223
214
|
}
|
|
224
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
|
}
|