@newtonedev/components 0.1.0 → 0.1.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/dist/AppShell/AppShell.d.ts +4 -0
- package/dist/AppShell/AppShell.d.ts.map +1 -0
- package/dist/AppShell/AppShell.styles.d.ts +16 -0
- package/dist/AppShell/AppShell.styles.d.ts.map +1 -0
- package/dist/AppShell/AppShell.types.d.ts +8 -0
- package/dist/AppShell/AppShell.types.d.ts.map +1 -0
- package/dist/AppShell/index.d.ts +3 -0
- package/dist/AppShell/index.d.ts.map +1 -0
- package/dist/Button/Button.d.ts +9 -4
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.styles.d.ts +33 -26
- package/dist/Button/Button.styles.d.ts.map +1 -1
- package/dist/Button/Button.types.d.ts +17 -2
- package/dist/Button/Button.types.d.ts.map +1 -1
- package/dist/ColorScaleSlider/ColorScaleSlider.d.ts +13 -0
- package/dist/ColorScaleSlider/ColorScaleSlider.d.ts.map +1 -0
- package/dist/ColorScaleSlider/ColorScaleSlider.styles.d.ts +54 -0
- package/dist/ColorScaleSlider/ColorScaleSlider.styles.d.ts.map +1 -0
- package/dist/ColorScaleSlider/ColorScaleSlider.types.d.ts +25 -0
- package/dist/ColorScaleSlider/ColorScaleSlider.types.d.ts.map +1 -0
- package/dist/ColorScaleSlider/index.d.ts +3 -0
- package/dist/ColorScaleSlider/index.d.ts.map +1 -0
- package/dist/Frame/Frame.d.ts +48 -0
- package/dist/Frame/Frame.d.ts.map +1 -0
- package/dist/Frame/Frame.styles.d.ts +39 -0
- package/dist/Frame/Frame.styles.d.ts.map +1 -0
- package/dist/Frame/Frame.types.d.ts +115 -0
- package/dist/Frame/Frame.types.d.ts.map +1 -0
- package/dist/Frame/Frame.utils.d.ts +39 -0
- package/dist/Frame/Frame.utils.d.ts.map +1 -0
- package/dist/Frame/index.d.ts +4 -0
- package/dist/Frame/index.d.ts.map +1 -0
- package/dist/HueSlider/HueSlider.d.ts +1 -1
- package/dist/HueSlider/HueSlider.d.ts.map +1 -1
- package/dist/HueSlider/HueSlider.styles.d.ts +47 -5
- package/dist/HueSlider/HueSlider.styles.d.ts.map +1 -1
- package/dist/HueSlider/HueSlider.types.d.ts +1 -0
- package/dist/HueSlider/HueSlider.types.d.ts.map +1 -1
- package/dist/Icon/Icon.d.ts +36 -0
- package/dist/Icon/Icon.d.ts.map +1 -0
- package/dist/Navbar/Navbar.d.ts +4 -0
- package/dist/Navbar/Navbar.d.ts.map +1 -0
- package/dist/Navbar/Navbar.styles.d.ts +31 -0
- package/dist/Navbar/Navbar.styles.d.ts.map +1 -0
- package/dist/Navbar/Navbar.types.d.ts +14 -0
- package/dist/Navbar/Navbar.types.d.ts.map +1 -0
- package/dist/Navbar/index.d.ts +3 -0
- package/dist/Navbar/index.d.ts.map +1 -0
- package/dist/Popover/Popover.d.ts +4 -0
- package/dist/Popover/Popover.d.ts.map +1 -0
- package/dist/Popover/Popover.styles.d.ts +9 -0
- package/dist/Popover/Popover.styles.d.ts.map +1 -0
- package/dist/Popover/Popover.types.d.ts +37 -0
- package/dist/Popover/Popover.types.d.ts.map +1 -0
- package/dist/Popover/index.d.ts +4 -0
- package/dist/Popover/index.d.ts.map +1 -0
- package/dist/Popover/usePopover.d.ts +3 -0
- package/dist/Popover/usePopover.d.ts.map +1 -0
- package/dist/Select/Select.d.ts +1 -8
- package/dist/Select/Select.d.ts.map +1 -1
- package/dist/Select/Select.styles.d.ts +32 -5
- package/dist/Select/Select.styles.d.ts.map +1 -1
- package/dist/Select/Select.types.d.ts +25 -1
- package/dist/Select/Select.types.d.ts.map +1 -1
- package/dist/Select/SelectOption.d.ts +13 -0
- package/dist/Select/SelectOption.d.ts.map +1 -0
- package/dist/Select/useSelect.d.ts +15 -0
- package/dist/Select/useSelect.d.ts.map +1 -0
- package/dist/Sidebar/Sidebar.d.ts +4 -0
- package/dist/Sidebar/Sidebar.d.ts.map +1 -0
- package/dist/Sidebar/Sidebar.styles.d.ts +31 -0
- package/dist/Sidebar/Sidebar.styles.d.ts.map +1 -0
- package/dist/Sidebar/Sidebar.types.d.ts +14 -0
- package/dist/Sidebar/Sidebar.types.d.ts.map +1 -0
- package/dist/Sidebar/index.d.ts +3 -0
- package/dist/Sidebar/index.d.ts.map +1 -0
- package/dist/Slider/Slider.d.ts +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.styles.d.ts +48 -8
- package/dist/Slider/Slider.styles.d.ts.map +1 -1
- package/dist/Slider/Slider.types.d.ts +1 -0
- package/dist/Slider/Slider.types.d.ts.map +1 -1
- package/dist/TextInput/TextInput.styles.d.ts +3 -1
- package/dist/TextInput/TextInput.styles.d.ts.map +1 -1
- package/dist/Toggle/Toggle.styles.d.ts +2 -1
- package/dist/Toggle/Toggle.styles.d.ts.map +1 -1
- package/dist/fonts/GoogleFontLoader.d.ts +19 -0
- package/dist/fonts/GoogleFontLoader.d.ts.map +1 -0
- package/dist/fonts/IconFontLoader.d.ts +13 -0
- package/dist/fonts/IconFontLoader.d.ts.map +1 -0
- package/dist/fonts/buildGoogleFontsUrl.d.ts +17 -0
- package/dist/fonts/buildGoogleFontsUrl.d.ts.map +1 -0
- package/dist/fonts/googleFonts.d.ts +20 -0
- package/dist/fonts/googleFonts.d.ts.map +1 -0
- package/dist/index.cjs +2303 -205
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +27 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2279 -200
- package/dist/index.js.map +1 -1
- package/dist/registry/codegen.d.ts +11 -0
- package/dist/registry/codegen.d.ts.map +1 -0
- package/dist/registry/index.d.ts +4 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/registry.d.ts +7 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/types.d.ts +32 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/theme/FrameContext.d.ts +24 -0
- package/dist/theme/FrameContext.d.ts.map +1 -0
- package/dist/theme/NewtoneProvider.d.ts.map +1 -1
- package/dist/theme/defaults.d.ts.map +1 -1
- package/dist/theme/types.d.ts +64 -1
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/tokens/computeTokens.d.ts +55 -3
- package/dist/tokens/computeTokens.d.ts.map +1 -1
- package/dist/tokens/types.d.ts +52 -0
- package/dist/tokens/types.d.ts.map +1 -1
- package/dist/tokens/useTokens.d.ts +12 -9
- package/dist/tokens/useTokens.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/AppShell/AppShell.styles.ts +20 -0
- package/src/AppShell/AppShell.tsx +17 -0
- package/src/AppShell/AppShell.types.ts +8 -0
- package/src/AppShell/index.ts +2 -0
- package/src/Button/Button.styles.ts +74 -41
- package/src/Button/Button.tsx +36 -17
- package/src/Button/Button.types.ts +20 -2
- package/src/Card/Card.styles.ts +2 -2
- package/src/ColorScaleSlider/ColorScaleSlider.styles.ts +60 -0
- package/src/ColorScaleSlider/ColorScaleSlider.tsx +156 -0
- package/src/ColorScaleSlider/ColorScaleSlider.types.ts +25 -0
- package/src/ColorScaleSlider/index.ts +2 -0
- package/src/Frame/Frame.styles.ts +213 -0
- package/src/Frame/Frame.tsx +242 -0
- package/src/Frame/Frame.types.ts +181 -0
- package/src/Frame/Frame.utils.ts +189 -0
- package/src/Frame/index.ts +21 -0
- package/src/HueSlider/HueSlider.styles.ts +58 -39
- package/src/HueSlider/HueSlider.tsx +97 -25
- package/src/HueSlider/HueSlider.types.ts +1 -0
- package/src/Icon/Icon.tsx +76 -0
- package/src/Navbar/Navbar.styles.ts +37 -0
- package/src/Navbar/Navbar.tsx +32 -0
- package/src/Navbar/Navbar.types.ts +14 -0
- package/src/Navbar/index.ts +2 -0
- package/src/Popover/Popover.styles.ts +39 -0
- package/src/Popover/Popover.tsx +103 -0
- package/src/Popover/Popover.types.ts +40 -0
- package/src/Popover/index.ts +3 -0
- package/src/Popover/usePopover.ts +26 -0
- package/src/Select/Select.styles.ts +49 -10
- package/src/Select/Select.tsx +127 -36
- package/src/Select/Select.types.ts +30 -1
- package/src/Select/SelectOption.tsx +104 -0
- package/src/Select/useSelect.ts +129 -0
- package/src/Sidebar/Sidebar.styles.ts +37 -0
- package/src/Sidebar/Sidebar.tsx +27 -0
- package/src/Sidebar/Sidebar.types.ts +14 -0
- package/src/Sidebar/index.ts +2 -0
- package/src/Slider/Slider.styles.ts +53 -25
- package/src/Slider/Slider.tsx +89 -24
- package/src/Slider/Slider.types.ts +1 -0
- package/src/TextInput/TextInput.styles.ts +9 -7
- package/src/Toggle/Toggle.styles.ts +4 -3
- package/src/fonts/GoogleFontLoader.tsx +63 -0
- package/src/fonts/IconFontLoader.tsx +49 -0
- package/src/fonts/buildGoogleFontsUrl.ts +31 -0
- package/src/fonts/googleFonts.ts +87 -0
- package/src/index.ts +70 -2
- package/src/registry/codegen.ts +132 -0
- package/src/registry/index.ts +17 -0
- package/src/registry/registry.ts +402 -0
- package/src/registry/types.ts +35 -0
- package/src/theme/FrameContext.tsx +29 -0
- package/src/theme/NewtoneProvider.tsx +9 -1
- package/src/theme/defaults.ts +51 -0
- package/src/theme/types.ts +66 -1
- package/src/tokens/computeTokens.ts +103 -46
- package/src/tokens/types.ts +52 -0
- package/src/tokens/useTokens.ts +30 -15
package/src/theme/types.ts
CHANGED
|
@@ -5,17 +5,34 @@ import type { DynamicRange, PaletteConfig } from 'newtone';
|
|
|
5
5
|
*/
|
|
6
6
|
export type ColorMode = 'light' | 'dark';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Font configuration for a single font slot
|
|
10
|
+
*/
|
|
11
|
+
export interface FontConfig {
|
|
12
|
+
readonly type: 'system' | 'google' | 'custom';
|
|
13
|
+
readonly family: string; // 'ui-monospace' | 'Roboto' | custom name
|
|
14
|
+
readonly customUrl?: string; // Supabase Storage URL for custom fonts
|
|
15
|
+
readonly fallback: string; // CSS fallback stack
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
/**
|
|
9
19
|
* Theme names for different UI contexts
|
|
10
20
|
*/
|
|
11
21
|
export type ThemeName = 'neutral' | 'primary' | 'secondary' | 'strong';
|
|
12
22
|
|
|
13
23
|
/**
|
|
14
|
-
* Elevation levels for surfaces
|
|
24
|
+
* Elevation levels for surfaces (internal)
|
|
15
25
|
* 0 = sunken, 1 = default, 2 = elevated
|
|
16
26
|
*/
|
|
17
27
|
export type ElevationLevel = 0 | 1 | 2;
|
|
18
28
|
|
|
29
|
+
/**
|
|
30
|
+
* User-facing elevation for Frame component
|
|
31
|
+
* -2 = deeply sunken (inset shadow), -1 = sunken, 0 = default,
|
|
32
|
+
* 1 = elevated, 2 = prominently elevated (drop shadow)
|
|
33
|
+
*/
|
|
34
|
+
export type FrameElevation = -2 | -1 | 0 | 1 | 2;
|
|
35
|
+
|
|
19
36
|
/**
|
|
20
37
|
* Theme mapping: which palette and normalizedValue to use for backgrounds/text
|
|
21
38
|
* Based on playground theme preview logic
|
|
@@ -48,6 +65,54 @@ export interface NewtoneThemeConfig {
|
|
|
48
65
|
readonly elevation: {
|
|
49
66
|
readonly offsets: readonly [number, number, number]; // NV offsets for [sunken, default, elevated]
|
|
50
67
|
};
|
|
68
|
+
readonly spacing: {
|
|
69
|
+
readonly xs: number; // 4 * multiplier
|
|
70
|
+
readonly sm: number; // 8 * multiplier
|
|
71
|
+
readonly md: number; // 12 * multiplier
|
|
72
|
+
readonly lg: number; // 16 * multiplier
|
|
73
|
+
readonly xl: number; // 24 * multiplier
|
|
74
|
+
readonly xxl: number; // 32 * multiplier
|
|
75
|
+
};
|
|
76
|
+
readonly radius: {
|
|
77
|
+
readonly none: number; // 0
|
|
78
|
+
readonly sm: number; // 4 * multiplier
|
|
79
|
+
readonly md: number; // 6 * multiplier
|
|
80
|
+
readonly lg: number; // 8 * multiplier
|
|
81
|
+
readonly xl: number; // 12 * multiplier
|
|
82
|
+
readonly pill: 999; // Fixed large value
|
|
83
|
+
};
|
|
84
|
+
readonly typography: {
|
|
85
|
+
readonly fonts: {
|
|
86
|
+
readonly mono: FontConfig;
|
|
87
|
+
readonly display: FontConfig;
|
|
88
|
+
readonly default: FontConfig;
|
|
89
|
+
};
|
|
90
|
+
readonly scale: {
|
|
91
|
+
readonly xs: number; // baseSize / ratio^2
|
|
92
|
+
readonly sm: number; // baseSize / ratio
|
|
93
|
+
readonly base: number; // baseSize
|
|
94
|
+
readonly md: number; // baseSize * ratio
|
|
95
|
+
readonly lg: number; // baseSize * ratio^2
|
|
96
|
+
readonly xl: number; // baseSize * ratio^3
|
|
97
|
+
readonly xxl: number; // baseSize * ratio^4
|
|
98
|
+
};
|
|
99
|
+
readonly lineHeight: {
|
|
100
|
+
readonly tight: number; // 1.25
|
|
101
|
+
readonly normal: number; // 1.5
|
|
102
|
+
readonly relaxed: number; // 1.75
|
|
103
|
+
};
|
|
104
|
+
readonly fontWeight: {
|
|
105
|
+
readonly regular: number; // 400
|
|
106
|
+
readonly medium: number; // 500
|
|
107
|
+
readonly semibold: number; // 600
|
|
108
|
+
readonly bold: number; // 700
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
readonly icons: {
|
|
112
|
+
readonly variant: 'outlined' | 'rounded' | 'sharp';
|
|
113
|
+
readonly weight: 100 | 200 | 300 | 400 | 500 | 600 | 700;
|
|
114
|
+
readonly autoGrade: boolean; // true = mode-aware grade (light=-25, dark=200)
|
|
115
|
+
};
|
|
51
116
|
}
|
|
52
117
|
|
|
53
118
|
/**
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { getColor, getColorByContrast } from 'newtone';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PaletteConfig } from 'newtone';
|
|
3
|
+
import type { ColorSystemConfig, ColorMode, ThemeMapping, ElevationLevel, FontConfig } from '../theme/types';
|
|
3
4
|
import type { ResolvedTokens } from './types';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Convert FontConfig to CSS font-family string
|
|
8
|
+
*/
|
|
9
|
+
function fontConfigToFamily(font: FontConfig): string {
|
|
10
|
+
const family = font.family.includes(' ') ? `"${font.family}"` : font.family;
|
|
11
|
+
return `${family}, ${font.fallback}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
5
14
|
/**
|
|
6
15
|
* Compute design tokens for a specific mode/theme/elevation combination.
|
|
7
16
|
*
|
|
@@ -14,6 +23,10 @@ import type { ResolvedTokens } from './types';
|
|
|
14
23
|
* @param themeMapping - Theme configuration (which palette and NV to use)
|
|
15
24
|
* @param elevation - Elevation level (0=sunken, 1=default, 2=elevated)
|
|
16
25
|
* @param elevationOffsets - NV offsets for each elevation level
|
|
26
|
+
* @param spacing - Spacing scale for paddings, gaps, and margins
|
|
27
|
+
* @param radius - Border radius scale for component roundness
|
|
28
|
+
* @param typography - Typography configuration with fonts and scales
|
|
29
|
+
* @param icons - Icon configuration with variant, weight, and auto-grade setting
|
|
17
30
|
* @returns Resolved design tokens with all necessary colors
|
|
18
31
|
*
|
|
19
32
|
* @example
|
|
@@ -23,7 +36,11 @@ import type { ResolvedTokens } from './types';
|
|
|
23
36
|
* 'light',
|
|
24
37
|
* config.themes.neutral,
|
|
25
38
|
* 1,
|
|
26
|
-
* config.elevation.offsets
|
|
39
|
+
* config.elevation.offsets,
|
|
40
|
+
* config.spacing,
|
|
41
|
+
* config.radius,
|
|
42
|
+
* config.typography,
|
|
43
|
+
* config.icons
|
|
27
44
|
* );
|
|
28
45
|
* console.log(tokens.background.srgb); // { r: 0.95, g: 0.95, b: 0.95 }
|
|
29
46
|
* ```
|
|
@@ -33,7 +50,20 @@ export function computeTokens(
|
|
|
33
50
|
mode: ColorMode,
|
|
34
51
|
themeMapping: ThemeMapping,
|
|
35
52
|
elevation: ElevationLevel,
|
|
36
|
-
elevationOffsets: readonly [number, number, number]
|
|
53
|
+
elevationOffsets: readonly [number, number, number],
|
|
54
|
+
spacing: { readonly xs: number; readonly sm: number; readonly md: number; readonly lg: number; readonly xl: number; readonly xxl: number },
|
|
55
|
+
radius: { readonly none: number; readonly sm: number; readonly md: number; readonly lg: number; readonly xl: number; readonly pill: 999 },
|
|
56
|
+
typography: {
|
|
57
|
+
readonly fonts: { readonly mono: FontConfig; readonly display: FontConfig; readonly default: FontConfig };
|
|
58
|
+
readonly scale: { readonly xs: number; readonly sm: number; readonly base: number; readonly md: number; readonly lg: number; readonly xl: number; readonly xxl: number };
|
|
59
|
+
readonly lineHeight: { readonly tight: number; readonly normal: number; readonly relaxed: number };
|
|
60
|
+
readonly fontWeight: { readonly regular: number; readonly medium: number; readonly semibold: number; readonly bold: number };
|
|
61
|
+
},
|
|
62
|
+
icons: {
|
|
63
|
+
readonly variant: 'outlined' | 'rounded' | 'sharp';
|
|
64
|
+
readonly weight: 100 | 200 | 300 | 400 | 500 | 600 | 700;
|
|
65
|
+
readonly autoGrade: boolean;
|
|
66
|
+
}
|
|
37
67
|
): ResolvedTokens {
|
|
38
68
|
const { dynamicRange, palettes } = config;
|
|
39
69
|
const palette = palettes[themeMapping.paletteIndex];
|
|
@@ -84,7 +114,7 @@ export function computeTokens(
|
|
|
84
114
|
palette.paletteHueGrading
|
|
85
115
|
);
|
|
86
116
|
|
|
87
|
-
// Compute text colors with WCAG contrast
|
|
117
|
+
// Compute text colors with WCAG contrast against actual background
|
|
88
118
|
// Primary text: WCAG AA (4.5:1 for body text)
|
|
89
119
|
const textPrimary = getColorByContrast(
|
|
90
120
|
palette.hue,
|
|
@@ -93,7 +123,8 @@ export function computeTokens(
|
|
|
93
123
|
4.5,
|
|
94
124
|
effectiveTextMode,
|
|
95
125
|
palette.desaturation,
|
|
96
|
-
palette.paletteHueGrading
|
|
126
|
+
palette.paletteHueGrading,
|
|
127
|
+
background,
|
|
97
128
|
);
|
|
98
129
|
|
|
99
130
|
// Secondary text: Lower contrast (3.0:1 for captions)
|
|
@@ -104,7 +135,8 @@ export function computeTokens(
|
|
|
104
135
|
3.0,
|
|
105
136
|
effectiveTextMode,
|
|
106
137
|
palette.desaturation,
|
|
107
|
-
palette.paletteHueGrading
|
|
138
|
+
palette.paletteHueGrading,
|
|
139
|
+
background,
|
|
108
140
|
);
|
|
109
141
|
|
|
110
142
|
// Interactive colors: Use accent palette (index 1)
|
|
@@ -114,20 +146,35 @@ export function computeTokens(
|
|
|
114
146
|
throw new Error('Accent palette (index 1) not found');
|
|
115
147
|
}
|
|
116
148
|
|
|
117
|
-
//
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
149
|
+
// Resolve per-mode key color: light mode uses keyNormalizedValue, dark uses keyNormalizedValueDark
|
|
150
|
+
const resolveKeyNv = (p: PaletteConfig): number | undefined =>
|
|
151
|
+
mode === 'dark' ? p.keyNormalizedValueDark : p.keyNormalizedValue;
|
|
152
|
+
|
|
153
|
+
// Interactive base: use user-chosen key color or auto WCAG AA contrast
|
|
154
|
+
const accentKeyNv = resolveKeyNv(accentPalette);
|
|
155
|
+
const interactive = accentKeyNv !== undefined
|
|
156
|
+
? getColor(
|
|
157
|
+
accentPalette.hue,
|
|
158
|
+
accentPalette.saturation,
|
|
159
|
+
dynamicRange,
|
|
160
|
+
accentKeyNv,
|
|
161
|
+
accentPalette.desaturation,
|
|
162
|
+
accentPalette.paletteHueGrading
|
|
163
|
+
)
|
|
164
|
+
: getColorByContrast(
|
|
165
|
+
accentPalette.hue,
|
|
166
|
+
accentPalette.saturation,
|
|
167
|
+
dynamicRange,
|
|
168
|
+
4.5,
|
|
169
|
+
effectiveTextMode,
|
|
170
|
+
accentPalette.desaturation,
|
|
171
|
+
accentPalette.paletteHueGrading,
|
|
172
|
+
background,
|
|
173
|
+
);
|
|
127
174
|
|
|
128
175
|
// Hover/active states: Shift NV slightly from interactive base
|
|
129
176
|
// In light mode (light bg), go darker; in dark mode (dark bg), go lighter
|
|
130
|
-
const interactiveNv = effectiveTextMode === 'light' ? 0.3 : 0.7;
|
|
177
|
+
const interactiveNv = accentKeyNv ?? (effectiveTextMode === 'light' ? 0.3 : 0.7);
|
|
131
178
|
|
|
132
179
|
const interactiveHover = getColor(
|
|
133
180
|
accentPalette.hue,
|
|
@@ -159,45 +206,36 @@ export function computeTokens(
|
|
|
159
206
|
);
|
|
160
207
|
|
|
161
208
|
// Semantic status colors: success (palette 2), warning (palette 3), error (palette 4)
|
|
162
|
-
// Each computed at WCAG AA contrast against
|
|
209
|
+
// Each computed at WCAG AA contrast against actual background
|
|
163
210
|
const successPalette = palettes[2];
|
|
164
211
|
const warningPalette = palettes[3];
|
|
165
212
|
const errorPalette = palettes[4];
|
|
166
213
|
|
|
214
|
+
const successKeyNv = successPalette ? resolveKeyNv(successPalette) : undefined;
|
|
167
215
|
const success = successPalette
|
|
168
|
-
?
|
|
169
|
-
successPalette.hue,
|
|
170
|
-
|
|
171
|
-
dynamicRange,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
successPalette.desaturation,
|
|
175
|
-
successPalette.paletteHueGrading
|
|
176
|
-
)
|
|
177
|
-
: interactive; // Fallback to interactive if palette missing
|
|
216
|
+
? (successKeyNv !== undefined
|
|
217
|
+
? getColor(successPalette.hue, successPalette.saturation, dynamicRange,
|
|
218
|
+
successKeyNv, successPalette.desaturation, successPalette.paletteHueGrading)
|
|
219
|
+
: getColorByContrast(successPalette.hue, successPalette.saturation, dynamicRange,
|
|
220
|
+
4.5, effectiveTextMode, successPalette.desaturation, successPalette.paletteHueGrading, background))
|
|
221
|
+
: interactive;
|
|
178
222
|
|
|
223
|
+
const warningKeyNv = warningPalette ? resolveKeyNv(warningPalette) : undefined;
|
|
179
224
|
const warning = warningPalette
|
|
180
|
-
?
|
|
181
|
-
warningPalette.hue,
|
|
182
|
-
|
|
183
|
-
dynamicRange,
|
|
184
|
-
|
|
185
|
-
effectiveTextMode,
|
|
186
|
-
warningPalette.desaturation,
|
|
187
|
-
warningPalette.paletteHueGrading
|
|
188
|
-
)
|
|
225
|
+
? (warningKeyNv !== undefined
|
|
226
|
+
? getColor(warningPalette.hue, warningPalette.saturation, dynamicRange,
|
|
227
|
+
warningKeyNv, warningPalette.desaturation, warningPalette.paletteHueGrading)
|
|
228
|
+
: getColorByContrast(warningPalette.hue, warningPalette.saturation, dynamicRange,
|
|
229
|
+
4.5, effectiveTextMode, warningPalette.desaturation, warningPalette.paletteHueGrading, background))
|
|
189
230
|
: interactive;
|
|
190
231
|
|
|
232
|
+
const errorKeyNv = errorPalette ? resolveKeyNv(errorPalette) : undefined;
|
|
191
233
|
const error = errorPalette
|
|
192
|
-
?
|
|
193
|
-
errorPalette.hue,
|
|
194
|
-
|
|
195
|
-
dynamicRange,
|
|
196
|
-
|
|
197
|
-
effectiveTextMode,
|
|
198
|
-
errorPalette.desaturation,
|
|
199
|
-
errorPalette.paletteHueGrading
|
|
200
|
-
)
|
|
234
|
+
? (errorKeyNv !== undefined
|
|
235
|
+
? getColor(errorPalette.hue, errorPalette.saturation, dynamicRange,
|
|
236
|
+
errorKeyNv, errorPalette.desaturation, errorPalette.paletteHueGrading)
|
|
237
|
+
: getColorByContrast(errorPalette.hue, errorPalette.saturation, dynamicRange,
|
|
238
|
+
4.5, effectiveTextMode, errorPalette.desaturation, errorPalette.paletteHueGrading, background))
|
|
201
239
|
: interactive;
|
|
202
240
|
|
|
203
241
|
return {
|
|
@@ -213,5 +251,24 @@ export function computeTokens(
|
|
|
213
251
|
success,
|
|
214
252
|
warning,
|
|
215
253
|
error,
|
|
254
|
+
spacing,
|
|
255
|
+
radius,
|
|
256
|
+
typography: {
|
|
257
|
+
fonts: {
|
|
258
|
+
mono: fontConfigToFamily(typography.fonts.mono),
|
|
259
|
+
display: fontConfigToFamily(typography.fonts.display),
|
|
260
|
+
default: fontConfigToFamily(typography.fonts.default),
|
|
261
|
+
},
|
|
262
|
+
size: typography.scale,
|
|
263
|
+
lineHeight: typography.lineHeight,
|
|
264
|
+
weight: typography.fontWeight,
|
|
265
|
+
},
|
|
266
|
+
icons: {
|
|
267
|
+
variant: icons.variant,
|
|
268
|
+
weight: icons.weight,
|
|
269
|
+
grade: icons.autoGrade
|
|
270
|
+
? (mode === 'light' ? -25 : 200)
|
|
271
|
+
: 0,
|
|
272
|
+
},
|
|
216
273
|
};
|
|
217
274
|
}
|
package/src/tokens/types.ts
CHANGED
|
@@ -28,4 +28,56 @@ export interface ResolvedTokens {
|
|
|
28
28
|
readonly warning: ColorResult;
|
|
29
29
|
/** Error/destructive state color (from error palette, index 4) */
|
|
30
30
|
readonly error: ColorResult;
|
|
31
|
+
/** Spacing tokens for paddings, gaps, and margins */
|
|
32
|
+
readonly spacing: {
|
|
33
|
+
readonly xs: number;
|
|
34
|
+
readonly sm: number;
|
|
35
|
+
readonly md: number;
|
|
36
|
+
readonly lg: number;
|
|
37
|
+
readonly xl: number;
|
|
38
|
+
readonly xxl: number;
|
|
39
|
+
};
|
|
40
|
+
/** Border radius tokens for component roundness */
|
|
41
|
+
readonly radius: {
|
|
42
|
+
readonly none: number;
|
|
43
|
+
readonly sm: number;
|
|
44
|
+
readonly md: number;
|
|
45
|
+
readonly lg: number;
|
|
46
|
+
readonly xl: number;
|
|
47
|
+
readonly pill: 999;
|
|
48
|
+
};
|
|
49
|
+
/** Typography tokens for fonts, sizes, line heights, and weights */
|
|
50
|
+
readonly typography: {
|
|
51
|
+
readonly fonts: {
|
|
52
|
+
readonly mono: string; // CSS font-family string
|
|
53
|
+
readonly display: string; // CSS font-family string
|
|
54
|
+
readonly default: string; // CSS font-family string
|
|
55
|
+
};
|
|
56
|
+
readonly size: {
|
|
57
|
+
readonly xs: number;
|
|
58
|
+
readonly sm: number;
|
|
59
|
+
readonly base: number;
|
|
60
|
+
readonly md: number;
|
|
61
|
+
readonly lg: number;
|
|
62
|
+
readonly xl: number;
|
|
63
|
+
readonly xxl: number;
|
|
64
|
+
};
|
|
65
|
+
readonly lineHeight: {
|
|
66
|
+
readonly tight: number;
|
|
67
|
+
readonly normal: number;
|
|
68
|
+
readonly relaxed: number;
|
|
69
|
+
};
|
|
70
|
+
readonly weight: {
|
|
71
|
+
readonly regular: number;
|
|
72
|
+
readonly medium: number;
|
|
73
|
+
readonly semibold: number;
|
|
74
|
+
readonly bold: number;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
/** Icon tokens for Material Symbols configuration */
|
|
78
|
+
readonly icons: {
|
|
79
|
+
readonly variant: 'outlined' | 'rounded' | 'sharp';
|
|
80
|
+
readonly weight: 100 | 200 | 300 | 400 | 500 | 600 | 700;
|
|
81
|
+
readonly grade: -25 | 0 | 200; // Mode-aware: light=-25, dark=200
|
|
82
|
+
};
|
|
31
83
|
}
|
package/src/tokens/useTokens.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { useNewtoneTheme } from '../theme/NewtoneProvider';
|
|
3
|
+
import { useFrameContext } from '../theme/FrameContext';
|
|
3
4
|
import { computeTokens } from './computeTokens';
|
|
4
5
|
import type { ElevationLevel } from '../theme/types';
|
|
5
6
|
import type { ResolvedTokens } from './types';
|
|
@@ -7,36 +8,50 @@ import type { ResolvedTokens } from './types';
|
|
|
7
8
|
/**
|
|
8
9
|
* Hook to compute design tokens for the current theme/mode/elevation.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Resolution order:
|
|
12
|
+
* 1. Explicit elevation parameter takes highest priority
|
|
13
|
+
* 2. FrameContext values (from nearest parent Frame) are used when elevation is omitted
|
|
14
|
+
* 3. Falls back to NewtoneProvider theme + elevation 1
|
|
13
15
|
*
|
|
14
|
-
*
|
|
16
|
+
* Theme always reads from FrameContext if present, falling back to NewtoneProvider.
|
|
17
|
+
*
|
|
18
|
+
* @param elevation - Elevation level (0=sunken, 1=default, 2=elevated).
|
|
19
|
+
* When omitted, reads from FrameContext or defaults to 1.
|
|
15
20
|
* @returns Resolved design tokens with all necessary colors
|
|
16
21
|
*
|
|
17
22
|
* @example
|
|
18
23
|
* ```tsx
|
|
19
|
-
*
|
|
20
|
-
*
|
|
24
|
+
* // Inside a <Frame theme="primary" elevation={1}>:
|
|
25
|
+
* function MyComponent() {
|
|
26
|
+
* const tokens = useTokens(); // Gets primary theme, elevation 2 (mapped from Frame's 1)
|
|
21
27
|
* return (
|
|
22
|
-
* <
|
|
23
|
-
* Click me
|
|
24
|
-
* </button>
|
|
28
|
+
* <View style={{ backgroundColor: srgbToHex(tokens.background.srgb) }} />
|
|
25
29
|
* );
|
|
26
30
|
* }
|
|
27
31
|
* ```
|
|
28
32
|
*/
|
|
29
|
-
export function useTokens(elevation
|
|
30
|
-
const { config, mode, theme } = useNewtoneTheme();
|
|
33
|
+
export function useTokens(elevation?: ElevationLevel): ResolvedTokens {
|
|
34
|
+
const { config, mode, theme: providerTheme } = useNewtoneTheme();
|
|
35
|
+
const frameCtx = useFrameContext();
|
|
36
|
+
|
|
37
|
+
// Resolve theme: FrameContext overrides provider
|
|
38
|
+
const resolvedTheme = frameCtx?.theme ?? providerTheme;
|
|
39
|
+
|
|
40
|
+
// Resolve elevation: explicit param > FrameContext > default 1
|
|
41
|
+
const resolvedElevation: ElevationLevel = elevation ?? frameCtx?.elevation ?? 1;
|
|
31
42
|
|
|
32
43
|
return useMemo(() => {
|
|
33
|
-
const themeMapping = config.themes[
|
|
44
|
+
const themeMapping = config.themes[resolvedTheme];
|
|
34
45
|
return computeTokens(
|
|
35
46
|
config.colorSystem,
|
|
36
47
|
mode,
|
|
37
48
|
themeMapping,
|
|
38
|
-
|
|
39
|
-
config.elevation.offsets
|
|
49
|
+
resolvedElevation,
|
|
50
|
+
config.elevation.offsets,
|
|
51
|
+
config.spacing,
|
|
52
|
+
config.radius,
|
|
53
|
+
config.typography,
|
|
54
|
+
config.icons
|
|
40
55
|
);
|
|
41
|
-
}, [config, mode,
|
|
56
|
+
}, [config, mode, resolvedTheme, resolvedElevation]);
|
|
42
57
|
}
|