@newtonedev/components 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.
Files changed (111) hide show
  1. package/README.md +506 -0
  2. package/dist/Button/Button.d.ts +23 -0
  3. package/dist/Button/Button.d.ts.map +1 -0
  4. package/dist/Button/Button.styles.d.ts +39 -0
  5. package/dist/Button/Button.styles.d.ts.map +1 -0
  6. package/dist/Button/Button.types.d.ts +42 -0
  7. package/dist/Button/Button.types.d.ts.map +1 -0
  8. package/dist/Button/index.d.ts +3 -0
  9. package/dist/Button/index.d.ts.map +1 -0
  10. package/dist/Card/Card.d.ts +4 -0
  11. package/dist/Card/Card.d.ts.map +1 -0
  12. package/dist/Card/Card.styles.d.ts +12 -0
  13. package/dist/Card/Card.styles.d.ts.map +1 -0
  14. package/dist/Card/Card.types.d.ts +9 -0
  15. package/dist/Card/Card.types.d.ts.map +1 -0
  16. package/dist/Card/index.d.ts +3 -0
  17. package/dist/Card/index.d.ts.map +1 -0
  18. package/dist/HueSlider/HueSlider.d.ts +14 -0
  19. package/dist/HueSlider/HueSlider.d.ts.map +1 -0
  20. package/dist/HueSlider/HueSlider.styles.d.ts +28 -0
  21. package/dist/HueSlider/HueSlider.styles.d.ts.map +1 -0
  22. package/dist/HueSlider/HueSlider.types.d.ts +12 -0
  23. package/dist/HueSlider/HueSlider.types.d.ts.map +1 -0
  24. package/dist/HueSlider/index.d.ts +3 -0
  25. package/dist/HueSlider/index.d.ts.map +1 -0
  26. package/dist/Select/Select.d.ts +11 -0
  27. package/dist/Select/Select.d.ts.map +1 -0
  28. package/dist/Select/Select.styles.d.ts +23 -0
  29. package/dist/Select/Select.styles.d.ts.map +1 -0
  30. package/dist/Select/Select.types.d.ts +14 -0
  31. package/dist/Select/Select.types.d.ts.map +1 -0
  32. package/dist/Select/index.d.ts +3 -0
  33. package/dist/Select/index.d.ts.map +1 -0
  34. package/dist/Slider/Slider.d.ts +4 -0
  35. package/dist/Slider/Slider.d.ts.map +1 -0
  36. package/dist/Slider/Slider.styles.d.ts +27 -0
  37. package/dist/Slider/Slider.styles.d.ts.map +1 -0
  38. package/dist/Slider/Slider.types.d.ts +13 -0
  39. package/dist/Slider/Slider.types.d.ts.map +1 -0
  40. package/dist/Slider/index.d.ts +3 -0
  41. package/dist/Slider/index.d.ts.map +1 -0
  42. package/dist/TextInput/TextInput.d.ts +4 -0
  43. package/dist/TextInput/TextInput.d.ts.map +1 -0
  44. package/dist/TextInput/TextInput.styles.d.ts +23 -0
  45. package/dist/TextInput/TextInput.styles.d.ts.map +1 -0
  46. package/dist/TextInput/TextInput.types.d.ts +7 -0
  47. package/dist/TextInput/TextInput.types.d.ts.map +1 -0
  48. package/dist/TextInput/index.d.ts +3 -0
  49. package/dist/TextInput/index.d.ts.map +1 -0
  50. package/dist/Toggle/Toggle.d.ts +4 -0
  51. package/dist/Toggle/Toggle.d.ts.map +1 -0
  52. package/dist/Toggle/Toggle.styles.d.ts +30 -0
  53. package/dist/Toggle/Toggle.styles.d.ts.map +1 -0
  54. package/dist/Toggle/Toggle.types.d.ts +9 -0
  55. package/dist/Toggle/Toggle.types.d.ts.map +1 -0
  56. package/dist/Toggle/index.d.ts +3 -0
  57. package/dist/Toggle/index.d.ts.map +1 -0
  58. package/dist/index.cjs +736 -0
  59. package/dist/index.cjs.map +1 -0
  60. package/dist/index.d.ts +22 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +719 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/theme/NewtoneProvider.d.ts +33 -0
  65. package/dist/theme/NewtoneProvider.d.ts.map +1 -0
  66. package/dist/theme/defaults.d.ts +7 -0
  67. package/dist/theme/defaults.d.ts.map +1 -0
  68. package/dist/theme/types.d.ts +56 -0
  69. package/dist/theme/types.d.ts.map +1 -0
  70. package/dist/tokens/computeTokens.d.ts +30 -0
  71. package/dist/tokens/computeTokens.d.ts.map +1 -0
  72. package/dist/tokens/types.d.ts +31 -0
  73. package/dist/tokens/types.d.ts.map +1 -0
  74. package/dist/tokens/useTokens.d.ts +26 -0
  75. package/dist/tokens/useTokens.d.ts.map +1 -0
  76. package/package.json +57 -0
  77. package/src/Button/Button.styles.ts +100 -0
  78. package/src/Button/Button.tsx +67 -0
  79. package/src/Button/Button.types.ts +49 -0
  80. package/src/Button/index.ts +2 -0
  81. package/src/Card/Card.styles.ts +16 -0
  82. package/src/Card/Card.tsx +25 -0
  83. package/src/Card/Card.types.ts +9 -0
  84. package/src/Card/index.ts +2 -0
  85. package/src/HueSlider/HueSlider.styles.ts +77 -0
  86. package/src/HueSlider/HueSlider.tsx +70 -0
  87. package/src/HueSlider/HueSlider.types.ts +12 -0
  88. package/src/HueSlider/index.ts +2 -0
  89. package/src/Select/Select.styles.ts +29 -0
  90. package/src/Select/Select.tsx +60 -0
  91. package/src/Select/Select.types.ts +15 -0
  92. package/src/Select/index.ts +2 -0
  93. package/src/Slider/Slider.styles.ts +45 -0
  94. package/src/Slider/Slider.tsx +57 -0
  95. package/src/Slider/Slider.types.ts +13 -0
  96. package/src/Slider/index.ts +2 -0
  97. package/src/TextInput/TextInput.styles.ts +29 -0
  98. package/src/TextInput/TextInput.tsx +32 -0
  99. package/src/TextInput/TextInput.types.ts +7 -0
  100. package/src/TextInput/index.ts +2 -0
  101. package/src/Toggle/Toggle.styles.ts +45 -0
  102. package/src/Toggle/Toggle.tsx +42 -0
  103. package/src/Toggle/Toggle.types.ts +9 -0
  104. package/src/Toggle/index.ts +2 -0
  105. package/src/index.ts +49 -0
  106. package/src/theme/NewtoneProvider.tsx +65 -0
  107. package/src/theme/defaults.ts +42 -0
  108. package/src/theme/types.ts +62 -0
  109. package/src/tokens/computeTokens.ts +217 -0
  110. package/src/tokens/types.ts +31 -0
  111. package/src/tokens/useTokens.ts +42 -0
@@ -0,0 +1,65 @@
1
+ import React, { createContext, useState, useMemo, useContext } from 'react';
2
+ import type { NewtoneThemeConfig, NewtoneThemeContext, ColorMode, ThemeName } from './types';
3
+ import { DEFAULT_THEME_CONFIG } from './defaults';
4
+
5
+ const ThemeContext = createContext<NewtoneThemeContext | null>(null);
6
+
7
+ export interface NewtoneProviderProps {
8
+ readonly config?: NewtoneThemeConfig;
9
+ readonly initialMode?: ColorMode;
10
+ readonly initialTheme?: ThemeName;
11
+ readonly children: React.ReactNode;
12
+ }
13
+
14
+ /**
15
+ * NewtoneProvider - Provides theme context to all Newtone components
16
+ *
17
+ * Wrap your app with this provider to enable theme and mode switching.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <NewtoneProvider initialMode="light" initialTheme="neutral">
22
+ * <App />
23
+ * </NewtoneProvider>
24
+ * ```
25
+ */
26
+ export function NewtoneProvider({
27
+ config = DEFAULT_THEME_CONFIG,
28
+ initialMode = 'light',
29
+ initialTheme = 'neutral',
30
+ children,
31
+ }: NewtoneProviderProps) {
32
+ const [mode, setMode] = useState<ColorMode>(initialMode);
33
+ const [theme, setTheme] = useState<ThemeName>(initialTheme);
34
+
35
+ const value = useMemo(
36
+ () => ({
37
+ config,
38
+ mode,
39
+ theme,
40
+ setMode,
41
+ setTheme,
42
+ }),
43
+ [config, mode, theme]
44
+ );
45
+
46
+ return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
47
+ }
48
+
49
+ /**
50
+ * useNewtoneTheme - Hook to access theme context
51
+ *
52
+ * Must be used within a NewtoneProvider.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * const { mode, theme, setMode, setTheme } = useNewtoneTheme();
57
+ * ```
58
+ */
59
+ export function useNewtoneTheme(): NewtoneThemeContext {
60
+ const context = useContext(ThemeContext);
61
+ if (!context) {
62
+ throw new Error('useNewtoneTheme must be used within NewtoneProvider');
63
+ }
64
+ return context;
65
+ }
@@ -0,0 +1,42 @@
1
+ import type { NewtoneThemeConfig } from './types';
2
+ import {
3
+ DEFAULT_NEUTRAL_HUE,
4
+ DEFAULT_NEUTRAL_SATURATION,
5
+ DEFAULT_ACCENT_HUE,
6
+ DEFAULT_ACCENT_SATURATION,
7
+ DEFAULT_SUCCESS_HUE,
8
+ DEFAULT_SUCCESS_SATURATION,
9
+ DEFAULT_WARNING_HUE,
10
+ DEFAULT_WARNING_SATURATION,
11
+ DEFAULT_ERROR_HUE,
12
+ DEFAULT_ERROR_SATURATION,
13
+ } from 'newtone';
14
+
15
+ /**
16
+ * Default theme configuration matching playground defaults.
17
+ * Palettes: [0] Neutral, [1] Accent, [2] Success, [3] Warning, [4] Error
18
+ */
19
+ export const DEFAULT_THEME_CONFIG: NewtoneThemeConfig = {
20
+ colorSystem: {
21
+ dynamicRange: {
22
+ lightest: 1,
23
+ darkest: 1,
24
+ },
25
+ palettes: [
26
+ { hue: DEFAULT_NEUTRAL_HUE, saturation: DEFAULT_NEUTRAL_SATURATION },
27
+ { hue: DEFAULT_ACCENT_HUE, saturation: DEFAULT_ACCENT_SATURATION },
28
+ { hue: DEFAULT_SUCCESS_HUE, saturation: DEFAULT_SUCCESS_SATURATION },
29
+ { hue: DEFAULT_WARNING_HUE, saturation: DEFAULT_WARNING_SATURATION },
30
+ { hue: DEFAULT_ERROR_HUE, saturation: DEFAULT_ERROR_SATURATION },
31
+ ],
32
+ },
33
+ themes: {
34
+ neutral: { paletteIndex: 0, lightModeNv: 0.95, darkModeNv: 0.1 },
35
+ primary: { paletteIndex: 1, lightModeNv: 0.95, darkModeNv: 0.1 },
36
+ secondary: { paletteIndex: 1, lightModeNv: 0.85, darkModeNv: 0.15 },
37
+ strong: { paletteIndex: 0, lightModeNv: 0.1, darkModeNv: 0.95 },
38
+ },
39
+ elevation: {
40
+ offsets: [-0.02, 0, 0.04], // [sunken, default, elevated]
41
+ },
42
+ };
@@ -0,0 +1,62 @@
1
+ import type { DynamicRange, PaletteConfig } from 'newtone';
2
+
3
+ /**
4
+ * Color mode: light or dark
5
+ */
6
+ export type ColorMode = 'light' | 'dark';
7
+
8
+ /**
9
+ * Theme names for different UI contexts
10
+ */
11
+ export type ThemeName = 'neutral' | 'primary' | 'secondary' | 'strong';
12
+
13
+ /**
14
+ * Elevation levels for surfaces
15
+ * 0 = sunken, 1 = default, 2 = elevated
16
+ */
17
+ export type ElevationLevel = 0 | 1 | 2;
18
+
19
+ /**
20
+ * Theme mapping: which palette and normalizedValue to use for backgrounds/text
21
+ * Based on playground theme preview logic
22
+ */
23
+ export interface ThemeMapping {
24
+ readonly paletteIndex: number; // Index into ColorSystemConfig.palettes
25
+ readonly lightModeNv: number; // normalizedValue for light mode background
26
+ readonly darkModeNv: number; // normalizedValue for dark mode background
27
+ }
28
+
29
+ /**
30
+ * Complete color system configuration
31
+ */
32
+ export interface ColorSystemConfig {
33
+ readonly dynamicRange: DynamicRange;
34
+ readonly palettes: ReadonlyArray<PaletteConfig>;
35
+ }
36
+
37
+ /**
38
+ * Newtone theme configuration
39
+ */
40
+ export interface NewtoneThemeConfig {
41
+ readonly colorSystem: ColorSystemConfig;
42
+ readonly themes: {
43
+ readonly neutral: ThemeMapping;
44
+ readonly primary: ThemeMapping;
45
+ readonly secondary: ThemeMapping;
46
+ readonly strong: ThemeMapping;
47
+ };
48
+ readonly elevation: {
49
+ readonly offsets: readonly [number, number, number]; // NV offsets for [sunken, default, elevated]
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Current theme context state
55
+ */
56
+ export interface NewtoneThemeContext {
57
+ readonly config: NewtoneThemeConfig;
58
+ readonly mode: ColorMode;
59
+ readonly theme: ThemeName;
60
+ readonly setMode: (mode: ColorMode) => void;
61
+ readonly setTheme: (theme: ThemeName) => void;
62
+ }
@@ -0,0 +1,217 @@
1
+ import { getColor, getColorByContrast } from 'newtone';
2
+ import type { ColorSystemConfig, ColorMode, ThemeMapping, ElevationLevel } from '../theme/types';
3
+ import type { ResolvedTokens } from './types';
4
+
5
+ /**
6
+ * Compute design tokens for a specific mode/theme/elevation combination.
7
+ *
8
+ * This function calls the Newtone engine to generate all necessary color tokens
9
+ * based on the current theme context. All colors are computed on-demand using
10
+ * the pure functions from the engine.
11
+ *
12
+ * @param config - Complete color system configuration (dynamic range + palettes)
13
+ * @param mode - Current color mode ('light' or 'dark')
14
+ * @param themeMapping - Theme configuration (which palette and NV to use)
15
+ * @param elevation - Elevation level (0=sunken, 1=default, 2=elevated)
16
+ * @param elevationOffsets - NV offsets for each elevation level
17
+ * @returns Resolved design tokens with all necessary colors
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const tokens = computeTokens(
22
+ * config.colorSystem,
23
+ * 'light',
24
+ * config.themes.neutral,
25
+ * 1,
26
+ * config.elevation.offsets
27
+ * );
28
+ * console.log(tokens.background.srgb); // { r: 0.95, g: 0.95, b: 0.95 }
29
+ * ```
30
+ */
31
+ export function computeTokens(
32
+ config: ColorSystemConfig,
33
+ mode: ColorMode,
34
+ themeMapping: ThemeMapping,
35
+ elevation: ElevationLevel,
36
+ elevationOffsets: readonly [number, number, number]
37
+ ): ResolvedTokens {
38
+ const { dynamicRange, palettes } = config;
39
+ const palette = palettes[themeMapping.paletteIndex];
40
+
41
+ if (!palette) {
42
+ throw new Error(`Palette at index ${themeMapping.paletteIndex} not found`);
43
+ }
44
+
45
+ // Determine base NV for this mode + elevation
46
+ const baseNv = mode === 'light' ? themeMapping.lightModeNv : themeMapping.darkModeNv;
47
+ const elevationOffset = elevationOffsets[elevation];
48
+ const backgroundNv = Math.max(0, Math.min(1, baseNv + elevationOffset));
49
+
50
+ // Derive effective text mode from actual background lightness.
51
+ // This handles inverted themes (e.g., strong: dark bg in light mode)
52
+ // where the mode flag doesn't match the background's visual lightness.
53
+ const effectiveTextMode: ColorMode = backgroundNv >= 0.5 ? 'light' : 'dark';
54
+
55
+ // Compute background colors for current elevation
56
+ const background = getColor(
57
+ palette.hue,
58
+ palette.saturation,
59
+ dynamicRange,
60
+ backgroundNv,
61
+ palette.desaturation,
62
+ palette.paletteHueGrading
63
+ );
64
+
65
+ // Compute elevated surface (always at elevation 2 offset)
66
+ const elevatedNv = Math.max(0, Math.min(1, baseNv + elevationOffsets[2]));
67
+ const backgroundElevated = getColor(
68
+ palette.hue,
69
+ palette.saturation,
70
+ dynamicRange,
71
+ elevatedNv,
72
+ palette.desaturation,
73
+ palette.paletteHueGrading
74
+ );
75
+
76
+ // Compute sunken surface (always at elevation 0 offset)
77
+ const sunkenNv = Math.max(0, Math.min(1, baseNv + elevationOffsets[0]));
78
+ const backgroundSunken = getColor(
79
+ palette.hue,
80
+ palette.saturation,
81
+ dynamicRange,
82
+ sunkenNv,
83
+ palette.desaturation,
84
+ palette.paletteHueGrading
85
+ );
86
+
87
+ // Compute text colors with WCAG contrast requirements
88
+ // Primary text: WCAG AA (4.5:1 for body text)
89
+ const textPrimary = getColorByContrast(
90
+ palette.hue,
91
+ palette.saturation,
92
+ dynamicRange,
93
+ 4.5,
94
+ effectiveTextMode,
95
+ palette.desaturation,
96
+ palette.paletteHueGrading
97
+ );
98
+
99
+ // Secondary text: Lower contrast (3.0:1 for captions)
100
+ const textSecondary = getColorByContrast(
101
+ palette.hue,
102
+ palette.saturation,
103
+ dynamicRange,
104
+ 3.0,
105
+ effectiveTextMode,
106
+ palette.desaturation,
107
+ palette.paletteHueGrading
108
+ );
109
+
110
+ // Interactive colors: Use accent palette (index 1)
111
+ const accentPalette = palettes[1];
112
+
113
+ if (!accentPalette) {
114
+ throw new Error('Accent palette (index 1) not found');
115
+ }
116
+
117
+ // Interactive base: WCAG AA contrast against current background
118
+ const interactive = getColorByContrast(
119
+ accentPalette.hue,
120
+ accentPalette.saturation,
121
+ dynamicRange,
122
+ 4.5,
123
+ effectiveTextMode,
124
+ accentPalette.desaturation,
125
+ accentPalette.paletteHueGrading
126
+ );
127
+
128
+ // Hover/active states: Shift NV slightly from interactive base
129
+ // In light mode (light bg), go darker; in dark mode (dark bg), go lighter
130
+ const interactiveNv = effectiveTextMode === 'light' ? 0.3 : 0.7;
131
+
132
+ const interactiveHover = getColor(
133
+ accentPalette.hue,
134
+ accentPalette.saturation,
135
+ dynamicRange,
136
+ interactiveNv + (effectiveTextMode === 'light' ? -0.05 : 0.05),
137
+ accentPalette.desaturation,
138
+ accentPalette.paletteHueGrading
139
+ );
140
+
141
+ const interactiveActive = getColor(
142
+ accentPalette.hue,
143
+ accentPalette.saturation,
144
+ dynamicRange,
145
+ interactiveNv + (effectiveTextMode === 'light' ? -0.1 : 0.1),
146
+ accentPalette.desaturation,
147
+ accentPalette.paletteHueGrading
148
+ );
149
+
150
+ // Border: Subtle contrast from background
151
+ const borderNv = effectiveTextMode === 'light' ? backgroundNv - 0.1 : backgroundNv + 0.1;
152
+ const border = getColor(
153
+ palette.hue,
154
+ palette.saturation,
155
+ dynamicRange,
156
+ Math.max(0, Math.min(1, borderNv)),
157
+ palette.desaturation,
158
+ palette.paletteHueGrading
159
+ );
160
+
161
+ // Semantic status colors: success (palette 2), warning (palette 3), error (palette 4)
162
+ // Each computed at WCAG AA contrast against the mode background, same as interactive
163
+ const successPalette = palettes[2];
164
+ const warningPalette = palettes[3];
165
+ const errorPalette = palettes[4];
166
+
167
+ const success = successPalette
168
+ ? getColorByContrast(
169
+ successPalette.hue,
170
+ successPalette.saturation,
171
+ dynamicRange,
172
+ 4.5,
173
+ effectiveTextMode,
174
+ successPalette.desaturation,
175
+ successPalette.paletteHueGrading
176
+ )
177
+ : interactive; // Fallback to interactive if palette missing
178
+
179
+ const warning = warningPalette
180
+ ? getColorByContrast(
181
+ warningPalette.hue,
182
+ warningPalette.saturation,
183
+ dynamicRange,
184
+ 4.5,
185
+ effectiveTextMode,
186
+ warningPalette.desaturation,
187
+ warningPalette.paletteHueGrading
188
+ )
189
+ : interactive;
190
+
191
+ const error = errorPalette
192
+ ? getColorByContrast(
193
+ errorPalette.hue,
194
+ errorPalette.saturation,
195
+ dynamicRange,
196
+ 4.5,
197
+ effectiveTextMode,
198
+ errorPalette.desaturation,
199
+ errorPalette.paletteHueGrading
200
+ )
201
+ : interactive;
202
+
203
+ return {
204
+ background,
205
+ backgroundElevated,
206
+ backgroundSunken,
207
+ textPrimary,
208
+ textSecondary,
209
+ interactive,
210
+ interactiveHover,
211
+ interactiveActive,
212
+ border,
213
+ success,
214
+ warning,
215
+ error,
216
+ };
217
+ }
@@ -0,0 +1,31 @@
1
+ import type { ColorResult } from 'newtone';
2
+
3
+ /**
4
+ * Resolved design tokens for a specific mode/theme/elevation combination
5
+ */
6
+ export interface ResolvedTokens {
7
+ /** Background color for the current surface */
8
+ readonly background: ColorResult;
9
+ /** Background color for elevated surfaces (cards, modals) */
10
+ readonly backgroundElevated: ColorResult;
11
+ /** Background color for sunken surfaces (input fields, wells) */
12
+ readonly backgroundSunken: ColorResult;
13
+ /** Primary text color (high contrast for body text) */
14
+ readonly textPrimary: ColorResult;
15
+ /** Secondary text color (lower contrast for captions, labels) */
16
+ readonly textSecondary: ColorResult;
17
+ /** Interactive element color (buttons, links) */
18
+ readonly interactive: ColorResult;
19
+ /** Interactive element hover state */
20
+ readonly interactiveHover: ColorResult;
21
+ /** Interactive element active/pressed state */
22
+ readonly interactiveActive: ColorResult;
23
+ /** Border color for subtle separators */
24
+ readonly border: ColorResult;
25
+ /** Success state color (from success palette, index 2) */
26
+ readonly success: ColorResult;
27
+ /** Warning state color (from warning palette, index 3) */
28
+ readonly warning: ColorResult;
29
+ /** Error/destructive state color (from error palette, index 4) */
30
+ readonly error: ColorResult;
31
+ }
@@ -0,0 +1,42 @@
1
+ import { useMemo } from 'react';
2
+ import { useNewtoneTheme } from '../theme/NewtoneProvider';
3
+ import { computeTokens } from './computeTokens';
4
+ import type { ElevationLevel } from '../theme/types';
5
+ import type { ResolvedTokens } from './types';
6
+
7
+ /**
8
+ * Hook to compute design tokens for the current theme/mode/elevation.
9
+ *
10
+ * This hook automatically recomputes tokens when the theme configuration,
11
+ * mode, theme name, or elevation changes. Results are memoized to avoid
12
+ * unnecessary computation.
13
+ *
14
+ * @param elevation - Elevation level (0=sunken, 1=default, 2=elevated)
15
+ * @returns Resolved design tokens with all necessary colors
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * function Button() {
20
+ * const tokens = useTokens(1); // Default elevation
21
+ * return (
22
+ * <button style={{ backgroundColor: srgbToHex(tokens.interactive.srgb) }}>
23
+ * Click me
24
+ * </button>
25
+ * );
26
+ * }
27
+ * ```
28
+ */
29
+ export function useTokens(elevation: ElevationLevel = 1): ResolvedTokens {
30
+ const { config, mode, theme } = useNewtoneTheme();
31
+
32
+ return useMemo(() => {
33
+ const themeMapping = config.themes[theme];
34
+ return computeTokens(
35
+ config.colorSystem,
36
+ mode,
37
+ themeMapping,
38
+ elevation,
39
+ config.elevation.offsets
40
+ );
41
+ }, [config, mode, theme, elevation]);
42
+ }