@native-mate/core 0.1.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/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/primitives/Icon/Icon.d.ts +4 -0
- package/dist/primitives/Icon/Icon.d.ts.map +1 -0
- package/dist/primitives/Icon/Icon.js +10 -0
- package/dist/primitives/Icon/Icon.js.map +1 -0
- package/dist/primitives/Icon/Icon.types.d.ts +8 -0
- package/dist/primitives/Icon/Icon.types.d.ts.map +1 -0
- package/dist/primitives/Icon/Icon.types.js +2 -0
- package/dist/primitives/Icon/Icon.types.js.map +1 -0
- package/dist/primitives/Separator/Separator.d.ts +4 -0
- package/dist/primitives/Separator/Separator.d.ts.map +1 -0
- package/dist/primitives/Separator/Separator.js +16 -0
- package/dist/primitives/Separator/Separator.js.map +1 -0
- package/dist/primitives/Separator/Separator.types.d.ts +6 -0
- package/dist/primitives/Separator/Separator.types.d.ts.map +1 -0
- package/dist/primitives/Separator/Separator.types.js +2 -0
- package/dist/primitives/Separator/Separator.types.js.map +1 -0
- package/dist/primitives/Spinner/Spinner.d.ts +4 -0
- package/dist/primitives/Spinner/Spinner.d.ts.map +1 -0
- package/dist/primitives/Spinner/Spinner.js +31 -0
- package/dist/primitives/Spinner/Spinner.js.map +1 -0
- package/dist/primitives/Spinner/Spinner.types.d.ts +5 -0
- package/dist/primitives/Spinner/Spinner.types.d.ts.map +1 -0
- package/dist/primitives/Spinner/Spinner.types.js +2 -0
- package/dist/primitives/Spinner/Spinner.types.js.map +1 -0
- package/dist/primitives/Text/Text.d.ts +4 -0
- package/dist/primitives/Text/Text.d.ts.map +1 -0
- package/dist/primitives/Text/Text.js +27 -0
- package/dist/primitives/Text/Text.js.map +1 -0
- package/dist/primitives/Text/Text.types.d.ts +14 -0
- package/dist/primitives/Text/Text.types.d.ts.map +1 -0
- package/dist/primitives/Text/Text.types.js +2 -0
- package/dist/primitives/Text/Text.types.js.map +1 -0
- package/dist/theme/ThemeContext.d.ts +4 -0
- package/dist/theme/ThemeContext.d.ts.map +1 -0
- package/dist/theme/ThemeContext.js +5 -0
- package/dist/theme/ThemeContext.js.map +1 -0
- package/dist/theme/ThemeProvider.d.ts +14 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +11 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/makeStyles.d.ts +6 -0
- package/dist/theme/makeStyles.d.ts.map +1 -0
- package/dist/theme/makeStyles.js +10 -0
- package/dist/theme/makeStyles.js.map +1 -0
- package/dist/theme/useTheme.d.ts +3 -0
- package/dist/theme/useTheme.d.ts.map +1 -0
- package/dist/theme/useTheme.js +6 -0
- package/dist/theme/useTheme.js.map +1 -0
- package/dist/tokens/index.d.ts +15 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +18 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/tokens/presets/midnight.d.ts +3 -0
- package/dist/tokens/presets/midnight.d.ts.map +1 -0
- package/dist/tokens/presets/midnight.js +23 -0
- package/dist/tokens/presets/midnight.js.map +1 -0
- package/dist/tokens/presets/rose.d.ts +3 -0
- package/dist/tokens/presets/rose.d.ts.map +1 -0
- package/dist/tokens/presets/rose.js +23 -0
- package/dist/tokens/presets/rose.js.map +1 -0
- package/dist/tokens/presets/slate.d.ts +3 -0
- package/dist/tokens/presets/slate.d.ts.map +1 -0
- package/dist/tokens/presets/slate.js +23 -0
- package/dist/tokens/presets/slate.js.map +1 -0
- package/dist/tokens/presets/zinc.d.ts +3 -0
- package/dist/tokens/presets/zinc.d.ts.map +1 -0
- package/dist/tokens/presets/zinc.js +36 -0
- package/dist/tokens/presets/zinc.js.map +1 -0
- package/dist/tokens/types.d.ts +109 -0
- package/dist/tokens/types.d.ts.map +1 -0
- package/dist/tokens/types.js +2 -0
- package/dist/tokens/types.js.map +1 -0
- package/dist/utils/platform.d.ts +17 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +19 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/useBreakpoint.d.ts +3 -0
- package/dist/utils/useBreakpoint.d.ts.map +1 -0
- package/dist/utils/useBreakpoint.js +10 -0
- package/dist/utils/useBreakpoint.js.map +1 -0
- package/package.json +31 -0
- package/src/__tests__/makeStyles.test.ts +56 -0
- package/src/__tests__/perf.test.ts +46 -0
- package/src/__tests__/platform.test.ts +34 -0
- package/src/__tests__/theme.test.ts +58 -0
- package/src/__tests__/tokens.test.ts +105 -0
- package/src/index.ts +27 -0
- package/src/primitives/Icon/Icon.tsx +11 -0
- package/src/primitives/Icon/Icon.types.ts +7 -0
- package/src/primitives/Separator/Separator.tsx +22 -0
- package/src/primitives/Separator/Separator.types.ts +6 -0
- package/src/primitives/Spinner/Spinner.tsx +50 -0
- package/src/primitives/Spinner/Spinner.types.ts +4 -0
- package/src/primitives/Text/Text.tsx +45 -0
- package/src/primitives/Text/Text.types.ts +15 -0
- package/src/theme/ThemeContext.ts +6 -0
- package/src/theme/ThemeProvider.tsx +27 -0
- package/src/theme/makeStyles.ts +15 -0
- package/src/theme/useTheme.ts +7 -0
- package/src/tokens/index.ts +29 -0
- package/src/tokens/presets/midnight.ts +24 -0
- package/src/tokens/presets/rose.ts +24 -0
- package/src/tokens/presets/slate.ts +24 -0
- package/src/tokens/presets/zinc.ts +37 -0
- package/src/tokens/types.ts +72 -0
- package/src/utils/platform.ts +20 -0
- package/src/utils/useBreakpoint.ts +10 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zinc.js","sourceRoot":"","sources":["../../../src/tokens/presets/zinc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export interface ColorToken {
|
|
2
|
+
light: string;
|
|
3
|
+
dark: string;
|
|
4
|
+
}
|
|
5
|
+
export interface TokenColors {
|
|
6
|
+
background: ColorToken;
|
|
7
|
+
surface: ColorToken;
|
|
8
|
+
surfaceRaised: ColorToken;
|
|
9
|
+
border: ColorToken;
|
|
10
|
+
primary: ColorToken;
|
|
11
|
+
onPrimary: ColorToken;
|
|
12
|
+
foreground: ColorToken;
|
|
13
|
+
onBackground: ColorToken;
|
|
14
|
+
onSurface: ColorToken;
|
|
15
|
+
muted: ColorToken;
|
|
16
|
+
destructive: ColorToken;
|
|
17
|
+
onDestructive: ColorToken;
|
|
18
|
+
success: ColorToken;
|
|
19
|
+
onSuccess: ColorToken;
|
|
20
|
+
warning: ColorToken;
|
|
21
|
+
onWarning: ColorToken;
|
|
22
|
+
}
|
|
23
|
+
export interface TokenSet {
|
|
24
|
+
colors: TokenColors;
|
|
25
|
+
spacing: {
|
|
26
|
+
xs: number;
|
|
27
|
+
sm: number;
|
|
28
|
+
md: number;
|
|
29
|
+
lg: number;
|
|
30
|
+
xl: number;
|
|
31
|
+
'2xl': number;
|
|
32
|
+
'3xl': number;
|
|
33
|
+
};
|
|
34
|
+
radius: {
|
|
35
|
+
sm: number;
|
|
36
|
+
md: number;
|
|
37
|
+
lg: number;
|
|
38
|
+
xl: number;
|
|
39
|
+
full: number;
|
|
40
|
+
};
|
|
41
|
+
typography: {
|
|
42
|
+
size: {
|
|
43
|
+
xs: number;
|
|
44
|
+
sm: number;
|
|
45
|
+
md: number;
|
|
46
|
+
lg: number;
|
|
47
|
+
xl: number;
|
|
48
|
+
'2xl': number;
|
|
49
|
+
'3xl': number;
|
|
50
|
+
};
|
|
51
|
+
weight: {
|
|
52
|
+
regular: string;
|
|
53
|
+
medium: string;
|
|
54
|
+
semibold: string;
|
|
55
|
+
bold: string;
|
|
56
|
+
};
|
|
57
|
+
lineHeight: {
|
|
58
|
+
tight: number;
|
|
59
|
+
normal: number;
|
|
60
|
+
relaxed: number;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
animation: {
|
|
64
|
+
speed: {
|
|
65
|
+
fast: number;
|
|
66
|
+
normal: number;
|
|
67
|
+
slow: number;
|
|
68
|
+
};
|
|
69
|
+
easing: {
|
|
70
|
+
standard: readonly [number, number, number, number];
|
|
71
|
+
decelerate: readonly [number, number, number, number];
|
|
72
|
+
spring: {
|
|
73
|
+
damping: number;
|
|
74
|
+
stiffness: number;
|
|
75
|
+
mass: number;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export type ResolvedColors = {
|
|
81
|
+
[K in keyof TokenColors]: string;
|
|
82
|
+
};
|
|
83
|
+
export interface ResolvedTheme {
|
|
84
|
+
colors: ResolvedColors;
|
|
85
|
+
spacing: TokenSet['spacing'];
|
|
86
|
+
radius: TokenSet['radius'];
|
|
87
|
+
typography: TokenSet['typography'];
|
|
88
|
+
animation: TokenSet['animation'];
|
|
89
|
+
colorScheme: 'light' | 'dark';
|
|
90
|
+
}
|
|
91
|
+
export type ThemePreset = 'zinc' | 'slate' | 'rose' | 'midnight';
|
|
92
|
+
export interface NativeMateTokenOverrides {
|
|
93
|
+
colors?: Partial<ResolvedColors>;
|
|
94
|
+
spacing?: Partial<TokenSet['spacing']>;
|
|
95
|
+
radius?: Partial<TokenSet['radius']>;
|
|
96
|
+
animation?: {
|
|
97
|
+
speed?: Partial<TokenSet['animation']['speed']>;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export interface NativeMateConfig {
|
|
101
|
+
theme: ThemePreset;
|
|
102
|
+
componentsDir: string;
|
|
103
|
+
registry: string;
|
|
104
|
+
tokens?: {
|
|
105
|
+
light?: NativeMateTokenOverrides;
|
|
106
|
+
dark?: NativeMateTokenOverrides;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tokens/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tokens/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function shadow(level?: 1 | 2 | 3 | 4): {
|
|
2
|
+
shadowColor: string;
|
|
3
|
+
shadowOpacity: number;
|
|
4
|
+
shadowRadius: number;
|
|
5
|
+
shadowOffset: {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
9
|
+
elevation?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
elevation: number;
|
|
12
|
+
shadowColor?: undefined;
|
|
13
|
+
shadowOpacity?: undefined;
|
|
14
|
+
shadowRadius?: undefined;
|
|
15
|
+
shadowOffset?: undefined;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/utils/platform.ts"],"names":[],"mappings":"AAEA,wBAAgB,MAAM,CAAC,KAAK,GAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAK;;;;;;;;;;;;;;;EAiB9C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
export function shadow(level = 1) {
|
|
3
|
+
const config = {
|
|
4
|
+
1: { opacity: 0.06, radius: 4, offsetY: 1, elevation: 2 },
|
|
5
|
+
2: { opacity: 0.10, radius: 8, offsetY: 2, elevation: 4 },
|
|
6
|
+
3: { opacity: 0.14, radius: 16, offsetY: 4, elevation: 8 },
|
|
7
|
+
4: { opacity: 0.18, radius: 24, offsetY: 8, elevation: 12 },
|
|
8
|
+
}[level];
|
|
9
|
+
if (Platform.OS === 'ios') {
|
|
10
|
+
return {
|
|
11
|
+
shadowColor: '#000',
|
|
12
|
+
shadowOpacity: config.opacity,
|
|
13
|
+
shadowRadius: config.radius,
|
|
14
|
+
shadowOffset: { width: 0, height: config.offsetY },
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return { elevation: config.elevation };
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/utils/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,MAAM,UAAU,MAAM,CAAC,QAAuB,CAAC;IAC7C,MAAM,MAAM,GAAG;QACb,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAG,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;QAC1D,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAG,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;QAC1D,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;QAC1D,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;KAC5D,CAAC,KAAK,CAAC,CAAA;IAER,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO;YACL,WAAW,EAAE,MAAM;YACnB,aAAa,EAAE,MAAM,CAAC,OAAO;YAC7B,YAAY,EAAE,MAAM,CAAC,MAAM;YAC3B,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE;SACnD,CAAA;IACH,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAA;AACxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBreakpoint.d.ts","sourceRoot":"","sources":["../../src/utils/useBreakpoint.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAE3C,wBAAgB,aAAa,IAAI,UAAU,CAK1C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useWindowDimensions } from 'react-native';
|
|
2
|
+
export function useBreakpoint() {
|
|
3
|
+
const { width } = useWindowDimensions();
|
|
4
|
+
if (width >= 1024)
|
|
5
|
+
return 'lg';
|
|
6
|
+
if (width >= 768)
|
|
7
|
+
return 'md';
|
|
8
|
+
return 'sm';
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=useBreakpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBreakpoint.js","sourceRoot":"","sources":["../../src/utils/useBreakpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAIlD,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,KAAK,EAAE,GAAG,mBAAmB,EAAE,CAAA;IACvC,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAA;IAC9B,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,IAAI,CAAA;IAC7B,OAAO,IAAI,CAAA;AACb,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@native-mate/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Token system, ThemeProvider, and primitive components for native-mate",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"files": ["dist", "src"],
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/native-mate/native-mate",
|
|
12
|
+
"directory": "packages/core"
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["react-native", "expo", "ui", "theme", "tokens", "native-mate"],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc --project tsconfig.json",
|
|
17
|
+
"test": "cd ../.. && npx vitest run --config vitest.config.ts packages/core",
|
|
18
|
+
"lint": "tsc --noEmit"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": ">=18.0.0",
|
|
22
|
+
"react-native": ">=0.73.0",
|
|
23
|
+
"react-native-reanimated": ">=3.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"react": "18.2.0",
|
|
27
|
+
"react-native": "0.73.6",
|
|
28
|
+
"react-native-reanimated": "^3.6.0",
|
|
29
|
+
"typescript": "^5.4.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { resolveTokens, zinc } from '../tokens'
|
|
3
|
+
import { makeStyles } from '../theme/makeStyles'
|
|
4
|
+
|
|
5
|
+
// makeStyles is a factory that returns a hook. We can't call hooks outside
|
|
6
|
+
// React, but we CAN verify the factory itself and the styles it produces.
|
|
7
|
+
|
|
8
|
+
describe('makeStyles', () => {
|
|
9
|
+
it('returns a function (hook)', () => {
|
|
10
|
+
const useStyles = makeStyles((theme) => ({
|
|
11
|
+
container: { backgroundColor: theme.colors.background },
|
|
12
|
+
}))
|
|
13
|
+
expect(typeof useStyles).toBe('function')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('factory receives a theme and returns style objects', () => {
|
|
17
|
+
const theme = resolveTokens(zinc, 'dark')
|
|
18
|
+
const factory = (t: typeof theme) => ({
|
|
19
|
+
box: { padding: t.spacing.md, borderRadius: t.radius.md },
|
|
20
|
+
})
|
|
21
|
+
const styles = factory(theme)
|
|
22
|
+
expect(styles.box.padding).toBe(12)
|
|
23
|
+
expect(styles.box.borderRadius).toBe(10)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('factory can access all token categories', () => {
|
|
27
|
+
const theme = resolveTokens(zinc, 'dark')
|
|
28
|
+
const factory = (t: typeof theme) => ({
|
|
29
|
+
text: {
|
|
30
|
+
color: t.colors.foreground,
|
|
31
|
+
fontSize: t.typography.size.md,
|
|
32
|
+
fontWeight: t.typography.weight.bold,
|
|
33
|
+
lineHeight: t.typography.lineHeight.normal,
|
|
34
|
+
},
|
|
35
|
+
animated: {
|
|
36
|
+
// animation tokens are accessible
|
|
37
|
+
opacity: t.animation.speed.fast > 0 ? 1 : 0,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
const styles = factory(theme)
|
|
41
|
+
expect(styles.text.color).toBe('#fafafa')
|
|
42
|
+
expect(styles.text.fontSize).toBe(15)
|
|
43
|
+
expect(styles.text.fontWeight).toBe('700')
|
|
44
|
+
expect(styles.animated.opacity).toBe(1)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('produces different styles for different presets', () => {
|
|
48
|
+
const darkTheme = resolveTokens(zinc, 'dark')
|
|
49
|
+
const lightTheme = resolveTokens(zinc, 'light')
|
|
50
|
+
const factory = (t: typeof darkTheme) => ({
|
|
51
|
+
bg: { backgroundColor: t.colors.background },
|
|
52
|
+
})
|
|
53
|
+
expect(factory(darkTheme).bg.backgroundColor).toBe('#070709')
|
|
54
|
+
expect(factory(lightTheme).bg.backgroundColor).toBe('#ffffff')
|
|
55
|
+
})
|
|
56
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { resolveTokens, zinc, slate, rose, midnight, presets } from '../tokens'
|
|
3
|
+
|
|
4
|
+
describe('performance', () => {
|
|
5
|
+
it('resolveTokens runs 10,000 times under 200ms', () => {
|
|
6
|
+
const start = performance.now()
|
|
7
|
+
for (let i = 0; i < 10_000; i++) {
|
|
8
|
+
resolveTokens(zinc, i % 2 === 0 ? 'dark' : 'light')
|
|
9
|
+
}
|
|
10
|
+
const elapsed = performance.now() - start
|
|
11
|
+
expect(elapsed).toBeLessThan(200)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
it('resolveTokens with overrides runs 10,000 times under 300ms', () => {
|
|
15
|
+
const overrides = { colors: { primary: '#6366f1' }, spacing: { lg: 20 } }
|
|
16
|
+
const start = performance.now()
|
|
17
|
+
for (let i = 0; i < 10_000; i++) {
|
|
18
|
+
resolveTokens(zinc, 'dark', overrides)
|
|
19
|
+
}
|
|
20
|
+
const elapsed = performance.now() - start
|
|
21
|
+
expect(elapsed).toBeLessThan(300)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('all 4 presets × 2 modes (80,000 calls) under 1s', () => {
|
|
25
|
+
const allPresets = [zinc, slate, rose, midnight]
|
|
26
|
+
const start = performance.now()
|
|
27
|
+
for (let i = 0; i < 10_000; i++) {
|
|
28
|
+
for (const preset of allPresets) {
|
|
29
|
+
resolveTokens(preset, 'dark')
|
|
30
|
+
resolveTokens(preset, 'light')
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const elapsed = performance.now() - start
|
|
34
|
+
expect(elapsed).toBeLessThan(1000)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('resolved theme object is consistently shaped', () => {
|
|
38
|
+
const theme = resolveTokens(zinc, 'dark')
|
|
39
|
+
const colorKeys = Object.keys(theme.colors)
|
|
40
|
+
// Verify across all presets
|
|
41
|
+
for (const preset of Object.values(presets)) {
|
|
42
|
+
const t = resolveTokens(preset, 'dark')
|
|
43
|
+
expect(Object.keys(t.colors).sort()).toEqual(colorKeys.sort())
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { Platform } from 'react-native'
|
|
3
|
+
import { shadow } from '../utils/platform'
|
|
4
|
+
|
|
5
|
+
describe('shadow()', () => {
|
|
6
|
+
it('returns elevation on Android', () => {
|
|
7
|
+
Object.defineProperty(Platform, 'OS', { get: () => 'android', configurable: true })
|
|
8
|
+
const s = shadow(2)
|
|
9
|
+
expect(s).toHaveProperty('elevation')
|
|
10
|
+
expect((s as { elevation: number }).elevation).toBe(4)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('returns shadowColor and shadowOffset on iOS', () => {
|
|
14
|
+
Object.defineProperty(Platform, 'OS', { get: () => 'ios', configurable: true })
|
|
15
|
+
const s = shadow(1)
|
|
16
|
+
expect(s).toHaveProperty('shadowColor')
|
|
17
|
+
expect(s).toHaveProperty('shadowOffset')
|
|
18
|
+
expect(s).toHaveProperty('shadowOpacity')
|
|
19
|
+
expect(s).toHaveProperty('shadowRadius')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('level 1 has lower shadow than level 4', () => {
|
|
23
|
+
Object.defineProperty(Platform, 'OS', { get: () => 'android', configurable: true })
|
|
24
|
+
const s1 = shadow(1) as { elevation: number }
|
|
25
|
+
const s4 = shadow(4) as { elevation: number }
|
|
26
|
+
expect(s4.elevation).toBeGreaterThan(s1.elevation)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('returns elevation object on non-ios (android fallback)', () => {
|
|
30
|
+
Object.defineProperty(Platform, 'OS', { get: () => 'android', configurable: true })
|
|
31
|
+
const s = shadow(3) as { elevation: number }
|
|
32
|
+
expect(s.elevation).toBe(8)
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { defaultTheme, ThemeContext } from '../theme/ThemeContext'
|
|
3
|
+
import { resolveTokens, zinc, presets } from '../tokens'
|
|
4
|
+
|
|
5
|
+
describe('ThemeContext', () => {
|
|
6
|
+
it('defaultTheme is zinc light', () => {
|
|
7
|
+
const expected = resolveTokens(zinc, 'light')
|
|
8
|
+
expect(defaultTheme.colorScheme).toBe('light')
|
|
9
|
+
expect(defaultTheme.colors.background).toBe(expected.colors.background)
|
|
10
|
+
expect(defaultTheme.colors.foreground).toBe(expected.colors.foreground)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('defaultTheme has all required token categories', () => {
|
|
14
|
+
expect(defaultTheme).toHaveProperty('colors')
|
|
15
|
+
expect(defaultTheme).toHaveProperty('spacing')
|
|
16
|
+
expect(defaultTheme).toHaveProperty('radius')
|
|
17
|
+
expect(defaultTheme).toHaveProperty('typography')
|
|
18
|
+
expect(defaultTheme).toHaveProperty('animation')
|
|
19
|
+
expect(defaultTheme).toHaveProperty('colorScheme')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('ThemeContext is a valid React context', () => {
|
|
23
|
+
expect(ThemeContext).toHaveProperty('Provider')
|
|
24
|
+
expect(ThemeContext).toHaveProperty('Consumer')
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe('ThemeProvider logic', () => {
|
|
29
|
+
it('forcedColorScheme dark resolves dark tokens', () => {
|
|
30
|
+
const theme = resolveTokens(presets.zinc, 'dark')
|
|
31
|
+
expect(theme.colorScheme).toBe('dark')
|
|
32
|
+
expect(theme.colors.background).toBe('#070709')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('forcedColorScheme light resolves light tokens', () => {
|
|
36
|
+
const theme = resolveTokens(presets.zinc, 'light')
|
|
37
|
+
expect(theme.colorScheme).toBe('light')
|
|
38
|
+
expect(theme.colors.background).toBe('#ffffff')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('each preset resolves to different primary colors', () => {
|
|
42
|
+
const themes = Object.entries(presets).map(([name, preset]) => ({
|
|
43
|
+
name,
|
|
44
|
+
primary: resolveTokens(preset, 'dark').colors.primary,
|
|
45
|
+
}))
|
|
46
|
+
const primaries = new Set(themes.map((t) => t.primary))
|
|
47
|
+
// At least 3 unique primaries across 4 presets (zinc and slate may share)
|
|
48
|
+
expect(primaries.size).toBeGreaterThanOrEqual(3)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('overrides are applied per-mode', () => {
|
|
52
|
+
const darkOverrides = { colors: { primary: '#ff0000' } }
|
|
53
|
+
const darkTheme = resolveTokens(presets.zinc, 'dark', darkOverrides)
|
|
54
|
+
const lightTheme = resolveTokens(presets.zinc, 'light')
|
|
55
|
+
expect(darkTheme.colors.primary).toBe('#ff0000')
|
|
56
|
+
expect(lightTheme.colors.primary).not.toBe('#ff0000')
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { resolveTokens, zinc, slate, rose, midnight, presets } from '../tokens'
|
|
3
|
+
|
|
4
|
+
describe('resolveTokens', () => {
|
|
5
|
+
it('resolves zinc dark mode correctly', () => {
|
|
6
|
+
const theme = resolveTokens(zinc, 'dark')
|
|
7
|
+
expect(theme.colors.background).toBe('#070709')
|
|
8
|
+
expect(theme.colors.foreground).toBe('#fafafa')
|
|
9
|
+
expect(theme.colorScheme).toBe('dark')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('resolves zinc light mode correctly', () => {
|
|
13
|
+
const theme = resolveTokens(zinc, 'light')
|
|
14
|
+
expect(theme.colors.background).toBe('#ffffff')
|
|
15
|
+
expect(theme.colors.foreground).toBe('#09090b')
|
|
16
|
+
expect(theme.colorScheme).toBe('light')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('returns non-color tokens unchanged', () => {
|
|
20
|
+
const theme = resolveTokens(zinc, 'dark')
|
|
21
|
+
expect(theme.spacing.lg).toBe(16)
|
|
22
|
+
expect(theme.spacing.xl).toBe(24)
|
|
23
|
+
expect(theme.radius.md).toBe(10)
|
|
24
|
+
expect(theme.typography.size.md).toBe(15)
|
|
25
|
+
expect(theme.typography.weight.bold).toBe('700')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('lineHeight values are absolute pixels, not multipliers', () => {
|
|
29
|
+
const theme = resolveTokens(zinc, 'dark')
|
|
30
|
+
expect(theme.typography.lineHeight.tight).toBe(18)
|
|
31
|
+
expect(theme.typography.lineHeight.normal).toBe(22)
|
|
32
|
+
expect(theme.typography.lineHeight.relaxed).toBe(28)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('applies color overrides', () => {
|
|
36
|
+
const theme = resolveTokens(zinc, 'dark', {
|
|
37
|
+
colors: { primary: '#6366f1' },
|
|
38
|
+
})
|
|
39
|
+
expect(theme.colors.primary).toBe('#6366f1')
|
|
40
|
+
expect(theme.colors.background).toBe('#070709') // unchanged
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('applies spacing overrides', () => {
|
|
44
|
+
const theme = resolveTokens(zinc, 'dark', {
|
|
45
|
+
spacing: { lg: 20 },
|
|
46
|
+
})
|
|
47
|
+
expect(theme.spacing.lg).toBe(20)
|
|
48
|
+
expect(theme.spacing.sm).toBe(8) // unchanged
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('applies radius overrides', () => {
|
|
52
|
+
const theme = resolveTokens(zinc, 'dark', {
|
|
53
|
+
radius: { md: 8 },
|
|
54
|
+
})
|
|
55
|
+
expect(theme.radius.md).toBe(8)
|
|
56
|
+
expect(theme.radius.full).toBe(9999) // unchanged
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('applies animation speed overrides', () => {
|
|
60
|
+
const theme = resolveTokens(zinc, 'dark', {
|
|
61
|
+
animation: { speed: { fast: 100 } },
|
|
62
|
+
})
|
|
63
|
+
expect(theme.animation.speed.fast).toBe(100)
|
|
64
|
+
expect(theme.animation.speed.normal).toBe(250) // unchanged
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('presets', () => {
|
|
69
|
+
it('exports all 4 presets', () => {
|
|
70
|
+
expect(presets).toHaveProperty('zinc')
|
|
71
|
+
expect(presets).toHaveProperty('slate')
|
|
72
|
+
expect(presets).toHaveProperty('rose')
|
|
73
|
+
expect(presets).toHaveProperty('midnight')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('slate dark background differs from zinc', () => {
|
|
77
|
+
const zincTheme = resolveTokens(zinc, 'dark')
|
|
78
|
+
const slateTheme = resolveTokens(slate, 'dark')
|
|
79
|
+
expect(slateTheme.colors.background).not.toBe(zincTheme.colors.background)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('rose primary differs from zinc primary in dark mode', () => {
|
|
83
|
+
const zincTheme = resolveTokens(zinc, 'dark')
|
|
84
|
+
const roseTheme = resolveTokens(rose, 'dark')
|
|
85
|
+
expect(roseTheme.colors.primary).not.toBe(zincTheme.colors.primary)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('all presets share same spacing, radius, and typography', () => {
|
|
89
|
+
const zincTheme = resolveTokens(zinc, 'dark')
|
|
90
|
+
const midnightTheme = resolveTokens(midnight, 'dark')
|
|
91
|
+
expect(midnightTheme.spacing).toEqual(zincTheme.spacing)
|
|
92
|
+
expect(midnightTheme.radius).toEqual(zincTheme.radius)
|
|
93
|
+
expect(midnightTheme.typography).toEqual(zincTheme.typography)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('every preset color token resolves to a hex string', () => {
|
|
97
|
+
for (const preset of Object.values(presets)) {
|
|
98
|
+
const theme = resolveTokens(preset, 'dark')
|
|
99
|
+
for (const [key, value] of Object.entries(theme.colors)) {
|
|
100
|
+
expect(typeof value).toBe('string')
|
|
101
|
+
expect(value.startsWith('#')).toBe(true)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
})
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Theme
|
|
2
|
+
export { ThemeProvider } from './theme/ThemeProvider'
|
|
3
|
+
export { useTheme } from './theme/useTheme'
|
|
4
|
+
export { makeStyles } from './theme/makeStyles'
|
|
5
|
+
|
|
6
|
+
// Tokens
|
|
7
|
+
export { presets, resolveTokens, zinc, slate, rose, midnight } from './tokens'
|
|
8
|
+
export type {
|
|
9
|
+
TokenSet, ResolvedTheme, ThemePreset,
|
|
10
|
+
NativeMateConfig, NativeMateTokenOverrides,
|
|
11
|
+
TokenColors, ColorToken, ResolvedColors,
|
|
12
|
+
} from './tokens/types'
|
|
13
|
+
|
|
14
|
+
// Primitives
|
|
15
|
+
export { Text } from './primitives/Text/Text'
|
|
16
|
+
export { Icon } from './primitives/Icon/Icon'
|
|
17
|
+
export { Spinner } from './primitives/Spinner/Spinner'
|
|
18
|
+
export { Separator } from './primitives/Separator/Separator'
|
|
19
|
+
export type { TextProps, TextVariant, TextSize, TextWeight } from './primitives/Text/Text.types'
|
|
20
|
+
export type { IconProps } from './primitives/Icon/Icon.types'
|
|
21
|
+
export type { SpinnerProps } from './primitives/Spinner/Spinner.types'
|
|
22
|
+
export type { SeparatorProps } from './primitives/Separator/Separator.types'
|
|
23
|
+
|
|
24
|
+
// Utils
|
|
25
|
+
export { shadow } from './utils/platform'
|
|
26
|
+
export { useBreakpoint } from './utils/useBreakpoint'
|
|
27
|
+
export type { Breakpoint } from './utils/useBreakpoint'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useTheme } from '../../theme/useTheme'
|
|
3
|
+
import type { IconProps } from './Icon.types'
|
|
4
|
+
|
|
5
|
+
const sizePx = { xs: 14, sm: 16, md: 20, lg: 24, xl: 32 }
|
|
6
|
+
|
|
7
|
+
export const Icon: React.FC<IconProps> = ({ as: IconComponent, name, size = 'md', color, ...rest }) => {
|
|
8
|
+
const theme = useTheme()
|
|
9
|
+
if (!IconComponent) return null
|
|
10
|
+
return <IconComponent name={name} size={sizePx[size]} color={color ?? theme.colors.foreground} {...rest} />
|
|
11
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { View } from 'react-native'
|
|
3
|
+
import { useTheme } from '../../theme/useTheme'
|
|
4
|
+
import type { SeparatorProps } from './Separator.types'
|
|
5
|
+
|
|
6
|
+
export const Separator: React.FC<SeparatorProps> = ({ orientation = 'horizontal', style }) => {
|
|
7
|
+
const theme = useTheme()
|
|
8
|
+
return (
|
|
9
|
+
<View
|
|
10
|
+
accessible={false}
|
|
11
|
+
style={[
|
|
12
|
+
{
|
|
13
|
+
backgroundColor: theme.colors.border,
|
|
14
|
+
...(orientation === 'horizontal'
|
|
15
|
+
? { height: 1, width: '100%' }
|
|
16
|
+
: { width: 1, height: '100%' }),
|
|
17
|
+
},
|
|
18
|
+
style,
|
|
19
|
+
]}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React, { useEffect } from 'react'
|
|
2
|
+
import { View } from 'react-native'
|
|
3
|
+
import Animated, {
|
|
4
|
+
useSharedValue,
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
withRepeat,
|
|
7
|
+
withTiming,
|
|
8
|
+
Easing,
|
|
9
|
+
} from 'react-native-reanimated'
|
|
10
|
+
import { useTheme } from '../../theme/useTheme'
|
|
11
|
+
import type { SpinnerProps } from './Spinner.types'
|
|
12
|
+
|
|
13
|
+
const sizes = { sm: 16, md: 24, lg: 32 }
|
|
14
|
+
|
|
15
|
+
export const Spinner: React.FC<SpinnerProps> = ({ size = 'md', color }) => {
|
|
16
|
+
const theme = useTheme()
|
|
17
|
+
const rotation = useSharedValue(0)
|
|
18
|
+
const px = sizes[size]
|
|
19
|
+
const spinnerColor = color ?? theme.colors.primary
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
rotation.value = withRepeat(
|
|
23
|
+
withTiming(360, { duration: 900, easing: Easing.linear }),
|
|
24
|
+
-1,
|
|
25
|
+
false,
|
|
26
|
+
)
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
30
|
+
transform: [{ rotate: `${rotation.value}deg` }],
|
|
31
|
+
}))
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<View style={{ width: px, height: px }}>
|
|
35
|
+
<Animated.View
|
|
36
|
+
style={[
|
|
37
|
+
animatedStyle,
|
|
38
|
+
{
|
|
39
|
+
width: px,
|
|
40
|
+
height: px,
|
|
41
|
+
borderRadius: px / 2,
|
|
42
|
+
borderWidth: 2,
|
|
43
|
+
borderColor: spinnerColor,
|
|
44
|
+
borderTopColor: 'transparent',
|
|
45
|
+
},
|
|
46
|
+
]}
|
|
47
|
+
/>
|
|
48
|
+
</View>
|
|
49
|
+
)
|
|
50
|
+
}
|