@draftbit/theme 50.5.3 → 50.5.4-27aeb2.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 +1 -0
- 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 +14 -10
- package/lib/typescript/src/Provider.js.map +1 -1
- package/lib/typescript/src/createTheme.js +25 -3
- package/lib/typescript/src/createTheme.js.map +1 -1
- package/lib/typescript/src/createThemeValuesProxy.js +23 -19
- package/lib/typescript/src/createThemeValuesProxy.js.map +1 -1
- package/lib/typescript/src/types.d.ts +30 -2
- package/lib/typescript/src/validators.d.ts +3 -1
- package/lib/typescript/src/validators.js +81 -42
- 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 +14 -10
- package/src/Provider.js.map +1 -1
- package/src/Provider.tsx +20 -40
- package/src/createTheme.js +25 -3
- package/src/createTheme.js.map +1 -1
- package/src/createTheme.ts +30 -2
- package/src/createThemeValuesProxy.js +23 -19
- package/src/createThemeValuesProxy.js.map +1 -1
- package/src/createThemeValuesProxy.ts +32 -23
- package/src/types.ts +33 -2
- package/src/validators.js +81 -42
- package/src/validators.js.map +1 -1
- package/src/validators.ts +103 -46
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ThemeValues, Breakpoints } from "./types";
|
|
2
|
-
import { Platform } from "react-native";
|
|
3
|
-
import {
|
|
2
|
+
import { Platform, TextStyle } from "react-native";
|
|
3
|
+
import { asThemeValuesObject } from "./validators";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Creates a proxy for theme value objects to select a value whenever
|
|
@@ -23,16 +23,18 @@ export default function createThemeValuesProxy(
|
|
|
23
23
|
get: (
|
|
24
24
|
target: ThemeValues,
|
|
25
25
|
key: string
|
|
26
|
-
): string | number | ThemeValues | undefined => {
|
|
26
|
+
): string | number | ThemeValues | TextStyle | undefined => {
|
|
27
27
|
const currentValue = target[key];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
|
|
29
|
+
const valueAsThemeValues = asThemeValuesObject(currentValue);
|
|
30
|
+
|
|
31
|
+
if (valueAsThemeValues) {
|
|
31
32
|
const platformKeys = ["ios", "android", "web", "macos", "windows"];
|
|
32
33
|
const breakpointKeys = Object.keys(breakpoints);
|
|
33
34
|
const lightDarkKeys = ["light", "dark"];
|
|
35
|
+
|
|
34
36
|
const keysType = getKeysType(
|
|
35
|
-
|
|
37
|
+
valueAsThemeValues,
|
|
36
38
|
platformKeys,
|
|
37
39
|
breakpointKeys,
|
|
38
40
|
lightDarkKeys
|
|
@@ -40,7 +42,7 @@ export default function createThemeValuesProxy(
|
|
|
40
42
|
|
|
41
43
|
if (keysType === "default") {
|
|
42
44
|
return createThemeValuesProxy(
|
|
43
|
-
|
|
45
|
+
valueAsThemeValues,
|
|
44
46
|
breakpoints,
|
|
45
47
|
deviceWidth,
|
|
46
48
|
devicePlatform,
|
|
@@ -48,7 +50,7 @@ export default function createThemeValuesProxy(
|
|
|
48
50
|
);
|
|
49
51
|
} else if (keysType === "platform") {
|
|
50
52
|
return getPlatformValue(
|
|
51
|
-
|
|
53
|
+
valueAsThemeValues,
|
|
52
54
|
breakpoints,
|
|
53
55
|
deviceWidth,
|
|
54
56
|
devicePlatform,
|
|
@@ -56,7 +58,7 @@ export default function createThemeValuesProxy(
|
|
|
56
58
|
);
|
|
57
59
|
} else if (keysType === "breakpoint") {
|
|
58
60
|
return getBreakpointValue(
|
|
59
|
-
|
|
61
|
+
valueAsThemeValues,
|
|
60
62
|
breakpoints,
|
|
61
63
|
deviceWidth,
|
|
62
64
|
devicePlatform,
|
|
@@ -64,7 +66,7 @@ export default function createThemeValuesProxy(
|
|
|
64
66
|
);
|
|
65
67
|
} else if (keysType === "lightDark") {
|
|
66
68
|
return getLightDarkValue(
|
|
67
|
-
|
|
69
|
+
valueAsThemeValues,
|
|
68
70
|
breakpoints,
|
|
69
71
|
deviceWidth,
|
|
70
72
|
devicePlatform,
|
|
@@ -73,6 +75,8 @@ export default function createThemeValuesProxy(
|
|
|
73
75
|
} else {
|
|
74
76
|
return undefined;
|
|
75
77
|
}
|
|
78
|
+
} else {
|
|
79
|
+
return currentValue;
|
|
76
80
|
}
|
|
77
81
|
},
|
|
78
82
|
set: () => {
|
|
@@ -147,16 +151,18 @@ function getPlatformValue(
|
|
|
147
151
|
currentLightDarkSelection: "light" | "dark"
|
|
148
152
|
) {
|
|
149
153
|
const currentPlatformValue = value[devicePlatform] ?? value.default;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
154
|
+
const valueAsThemeValues = asThemeValuesObject(currentPlatformValue);
|
|
155
|
+
|
|
156
|
+
if (valueAsThemeValues) {
|
|
153
157
|
return createThemeValuesProxy(
|
|
154
|
-
|
|
158
|
+
valueAsThemeValues,
|
|
155
159
|
breakpoints,
|
|
156
160
|
deviceWidth,
|
|
157
161
|
devicePlatform,
|
|
158
162
|
currentLightDarkSelection
|
|
159
163
|
);
|
|
164
|
+
} else {
|
|
165
|
+
return currentPlatformValue;
|
|
160
166
|
}
|
|
161
167
|
}
|
|
162
168
|
|
|
@@ -178,16 +184,18 @@ function getBreakpointValue(
|
|
|
178
184
|
}
|
|
179
185
|
}
|
|
180
186
|
const currentBreakpointValue = value[currentBreakpointKey] ?? value.default;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
187
|
+
const valueAsThemeValues = asThemeValuesObject(currentBreakpointValue);
|
|
188
|
+
|
|
189
|
+
if (valueAsThemeValues) {
|
|
184
190
|
return createThemeValuesProxy(
|
|
185
|
-
|
|
191
|
+
valueAsThemeValues,
|
|
186
192
|
breakpoints,
|
|
187
193
|
deviceWidth,
|
|
188
194
|
devicePlatform,
|
|
189
195
|
currentLightDarkSelection
|
|
190
196
|
);
|
|
197
|
+
} else {
|
|
198
|
+
return currentBreakpointValue;
|
|
191
199
|
}
|
|
192
200
|
}
|
|
193
201
|
|
|
@@ -200,16 +208,17 @@ function getLightDarkValue(
|
|
|
200
208
|
) {
|
|
201
209
|
const currentLightDarkValue =
|
|
202
210
|
value[currentLightDarkSelection] ?? value.default;
|
|
211
|
+
const valueAsThemeValues = asThemeValuesObject(currentLightDarkValue);
|
|
203
212
|
|
|
204
|
-
if (
|
|
205
|
-
return currentLightDarkValue;
|
|
206
|
-
} else {
|
|
213
|
+
if (valueAsThemeValues) {
|
|
207
214
|
return createThemeValuesProxy(
|
|
208
|
-
|
|
215
|
+
valueAsThemeValues,
|
|
209
216
|
breakpoints,
|
|
210
217
|
deviceWidth,
|
|
211
218
|
devicePlatform,
|
|
212
219
|
currentLightDarkSelection
|
|
213
220
|
);
|
|
221
|
+
} else {
|
|
222
|
+
return currentLightDarkValue;
|
|
214
223
|
}
|
|
215
224
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { TextStyle } from "react-native";
|
|
2
|
+
|
|
1
3
|
export type ThemeValues = {
|
|
2
|
-
[key: string]: string | number | ThemeValues;
|
|
4
|
+
[key: string]: string | number | TextStyle | ThemeValues;
|
|
3
5
|
};
|
|
4
6
|
|
|
5
7
|
export type Theme = {
|
|
@@ -11,7 +13,21 @@ export type Theme = {
|
|
|
11
13
|
foreground?: ThemeValues;
|
|
12
14
|
border?: ThemeValues;
|
|
13
15
|
};
|
|
14
|
-
typography: {
|
|
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
|
+
};
|
|
15
31
|
};
|
|
16
32
|
|
|
17
33
|
export type ValidatedTheme = Theme & {
|
|
@@ -26,6 +42,21 @@ export type ReadTheme = Theme & {
|
|
|
26
42
|
foreground?: any;
|
|
27
43
|
border?: any;
|
|
28
44
|
};
|
|
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
|
+
};
|
|
29
60
|
};
|
|
30
61
|
|
|
31
62
|
export type ColorPaletteValues = {
|
package/src/validators.js
CHANGED
|
@@ -1,52 +1,91 @@
|
|
|
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
|
+
});
|
|
1
63
|
export function validatePalettes(palettes) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
}
|
|
64
|
+
const result = PaletteSchema.safeParse(palettes);
|
|
65
|
+
if (!result.success) {
|
|
66
|
+
throw new Error("Invalid palettes object: " + result.error.message);
|
|
14
67
|
}
|
|
15
68
|
}
|
|
16
69
|
export function validateBreakpoints(breakpoints) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
if (typeof value !== "number") {
|
|
22
|
-
throw new Error(`Invalid breakpoint value, ${value} is not a number`);
|
|
23
|
-
}
|
|
70
|
+
const result = BreakpointSchema.safeParse(breakpoints);
|
|
71
|
+
if (!result.success) {
|
|
72
|
+
throw new Error("Invalid breakpoints object: " + result.error.message);
|
|
24
73
|
}
|
|
25
74
|
}
|
|
26
75
|
export function validateTheme(theme) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
}
|
|
76
|
+
const result = ThemeSchema.safeParse(theme);
|
|
77
|
+
if (!result.success) {
|
|
78
|
+
throw new Error("Invalid theme object: " + result.error.message);
|
|
45
79
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
80
|
+
}
|
|
81
|
+
export function isTextStyleObject(value) {
|
|
82
|
+
return TextStyleSchema.safeParse(value).success;
|
|
83
|
+
}
|
|
84
|
+
export function asThemeValuesObject(value) {
|
|
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;
|
|
51
90
|
}
|
|
52
91
|
//# 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,MAAM,
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["validators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,aAAa,GAA6B,CAAC,CAAC,MAAM,CACtD,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CACjC,CAAC;AAEF,MAAM,gBAAgB,GAA2B,CAAC,CAAC,MAAM,CACvD,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,MAAM,EAAE,CACX,CAAC;AAEF,MAAM,eAAe,GAAyB,CAAC,CAAC,KAAK,CAAC;IACpD,CAAC,CAAC,MAAM,CAAC;QACP,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;KACrB,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;KACvB,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC;YACjB,QAAQ;YACR,MAAM;YACN,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;SACN,CAAC;KACH,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;KACxC,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;KAC1B,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;KACvB,CAAC;CACH,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAA2B,CAAC,CAAC,MAAM,CACxD,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CACV,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC,CACtE,CACF,CAAC;AAEF,MAAM,4BAA4B,GAChC,CAAC,CAAC,KAAK,CAAC,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEhD,MAAM,WAAW,GAAqB,CAAC,CAAC,MAAM,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,EAAE;QACtC,IAAI,EAAE,iBAAiB,CAAC,QAAQ,EAAE;QAClC,UAAU,EAAE,iBAAiB,CAAC,QAAQ,EAAE;QACxC,UAAU,EAAE,iBAAiB,CAAC,QAAQ,EAAE;QACxC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,EAAE;KACrC,CAAC;IACF,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAC9C,KAAK,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAC9C,MAAM,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAC/C,OAAO,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAChD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAClD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAClD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAClD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAClD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAClD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAClD,QAAQ,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QACjD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;QAClD,SAAS,EAAE,4BAA4B,CAAC,QAAQ,EAAE;KACnD,CAAC;CACH,CAAC,CAAC;AAEH,MAAM,UAAU,gBAAgB,CAAC,QAAuB;IACtD,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;QACnB,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;KACrE;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,WAAwB;IAC1D,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;QACnB,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;KACxE;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAY;IACxC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;QACnB,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;KAClE;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAU;IAC1C,OAAO,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAU;IAC5C,8FAA8F;IAC9F,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE;QAC5B,OAAO,IAAI,CAAC;KACb;IAED,OAAO,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnE,CAAC"}
|
package/src/validators.ts
CHANGED
|
@@ -1,59 +1,116 @@
|
|
|
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
|
+
});
|
|
2
83
|
|
|
3
84
|
export function validatePalettes(palettes: ColorPalettes) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
}
|
|
85
|
+
const result = PaletteSchema.safeParse(palettes);
|
|
86
|
+
if (!result.success) {
|
|
87
|
+
throw new Error("Invalid palettes object: " + result.error.message);
|
|
20
88
|
}
|
|
21
89
|
}
|
|
22
90
|
|
|
23
91
|
export function validateBreakpoints(breakpoints: Breakpoints) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
if (typeof value !== "number") {
|
|
29
|
-
throw new Error(`Invalid breakpoint value, ${value} is not a number`);
|
|
30
|
-
}
|
|
92
|
+
const result = BreakpointSchema.safeParse(breakpoints);
|
|
93
|
+
if (!result.success) {
|
|
94
|
+
throw new Error("Invalid breakpoints object: " + result.error.message);
|
|
31
95
|
}
|
|
32
96
|
}
|
|
33
97
|
|
|
34
98
|
export function validateTheme(theme: Theme) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
}
|
|
99
|
+
const result = ThemeSchema.safeParse(theme);
|
|
100
|
+
if (!result.success) {
|
|
101
|
+
throw new Error("Invalid theme object: " + result.error.message);
|
|
53
102
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function isTextStyleObject(value: any): boolean {
|
|
106
|
+
return TextStyleSchema.safeParse(value).success;
|
|
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;
|
|
59
116
|
}
|