@newtonedev/components 0.1.11 → 0.1.13

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 (150) hide show
  1. package/dist/_COMPONENT_TEMPLATE/ComponentName.styles.d.ts +3 -2
  2. package/dist/_COMPONENT_TEMPLATE/ComponentName.styles.d.ts.map +1 -1
  3. package/dist/_COMPONENT_TEMPLATE/ComponentName.types.d.ts +1 -1
  4. package/dist/_COMPONENT_TEMPLATE/ComponentName.types.d.ts.map +1 -1
  5. package/dist/composites/actions/Button/Button.styles.d.ts +1 -1
  6. package/dist/composites/actions/Button/Button.styles.d.ts.map +1 -1
  7. package/dist/composites/form-controls/Select/Select.d.ts.map +1 -1
  8. package/dist/composites/form-controls/Select/Select.styles.d.ts +2 -2
  9. package/dist/composites/form-controls/Select/Select.styles.d.ts.map +1 -1
  10. package/dist/composites/form-controls/Select/SelectOption.d.ts.map +1 -1
  11. package/dist/composites/form-controls/TextInput/TextInput.d.ts.map +1 -1
  12. package/dist/composites/form-controls/TextInput/TextInput.styles.d.ts +2 -2
  13. package/dist/composites/form-controls/TextInput/TextInput.styles.d.ts.map +1 -1
  14. package/dist/composites/form-controls/Toggle/Toggle.styles.d.ts +2 -2
  15. package/dist/composites/form-controls/Toggle/Toggle.styles.d.ts.map +1 -1
  16. package/dist/composites/layout/AppShell/AppShell.styles.d.ts +2 -2
  17. package/dist/composites/layout/AppShell/AppShell.styles.d.ts.map +1 -1
  18. package/dist/composites/layout/Card/Card.styles.d.ts +2 -2
  19. package/dist/composites/layout/Card/Card.styles.d.ts.map +1 -1
  20. package/dist/composites/layout/Card/Card.types.d.ts +1 -1
  21. package/dist/composites/layout/Card/Card.types.d.ts.map +1 -1
  22. package/dist/composites/layout/Navbar/Navbar.styles.d.ts +3 -2
  23. package/dist/composites/layout/Navbar/Navbar.styles.d.ts.map +1 -1
  24. package/dist/composites/layout/Sidebar/Sidebar.styles.d.ts +3 -2
  25. package/dist/composites/layout/Sidebar/Sidebar.styles.d.ts.map +1 -1
  26. package/dist/composites/overlays/Popover/Popover.styles.d.ts +2 -2
  27. package/dist/composites/overlays/Popover/Popover.styles.d.ts.map +1 -1
  28. package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.d.ts +1 -1
  29. package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.d.ts.map +1 -1
  30. package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.d.ts +2 -2
  31. package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.d.ts.map +1 -1
  32. package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.types.d.ts +2 -0
  33. package/dist/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.types.d.ts.map +1 -1
  34. package/dist/composites/range-inputs/HueSlider/HueSlider.d.ts +3 -4
  35. package/dist/composites/range-inputs/HueSlider/HueSlider.d.ts.map +1 -1
  36. package/dist/composites/range-inputs/HueSlider/HueSlider.styles.d.ts +4 -4
  37. package/dist/composites/range-inputs/HueSlider/HueSlider.styles.d.ts.map +1 -1
  38. package/dist/composites/range-inputs/Slider/Slider.d.ts.map +1 -1
  39. package/dist/composites/range-inputs/Slider/Slider.styles.d.ts +2 -2
  40. package/dist/composites/range-inputs/Slider/Slider.styles.d.ts.map +1 -1
  41. package/dist/index.cjs +1245 -1824
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.d.ts +12 -24
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1096 -1737
  46. package/dist/index.js.map +1 -1
  47. package/dist/primitives/Frame/Frame.d.ts.map +1 -1
  48. package/dist/primitives/Frame/Frame.styles.d.ts +3 -2
  49. package/dist/primitives/Frame/Frame.styles.d.ts.map +1 -1
  50. package/dist/primitives/Frame/Frame.types.d.ts +1 -1
  51. package/dist/primitives/Frame/Frame.types.d.ts.map +1 -1
  52. package/dist/primitives/Frame/Frame.utils.d.ts +1 -1
  53. package/dist/primitives/Frame/Frame.utils.d.ts.map +1 -1
  54. package/dist/primitives/Icon/Icon.d.ts.map +1 -1
  55. package/dist/primitives/Text/Text.d.ts +1 -1
  56. package/dist/primitives/Text/Text.d.ts.map +1 -1
  57. package/dist/primitives/Text/Text.types.d.ts +1 -1
  58. package/dist/primitives/Text/Text.types.d.ts.map +1 -1
  59. package/dist/primitives/Wrapper/Wrapper.styles.d.ts +1 -1
  60. package/dist/primitives/Wrapper/Wrapper.styles.d.ts.map +1 -1
  61. package/package.json +3 -2
  62. package/src/_COMPONENT_TEMPLATE/ComponentName.styles.ts +4 -4
  63. package/src/_COMPONENT_TEMPLATE/ComponentName.tsx +2 -2
  64. package/src/_COMPONENT_TEMPLATE/ComponentName.types.ts +1 -1
  65. package/src/composites/actions/Button/Button.styles.ts +37 -36
  66. package/src/composites/actions/Button/Button.tsx +1 -1
  67. package/src/composites/form-controls/Select/Select.styles.ts +8 -8
  68. package/src/composites/form-controls/Select/Select.tsx +4 -5
  69. package/src/composites/form-controls/Select/SelectOption.tsx +7 -8
  70. package/src/composites/form-controls/TextInput/TextInput.styles.ts +7 -8
  71. package/src/composites/form-controls/TextInput/TextInput.tsx +3 -4
  72. package/src/composites/form-controls/Toggle/Toggle.styles.ts +6 -6
  73. package/src/composites/form-controls/Toggle/Toggle.tsx +2 -2
  74. package/src/composites/layout/AppShell/AppShell.styles.ts +3 -4
  75. package/src/composites/layout/AppShell/AppShell.tsx +2 -2
  76. package/src/composites/layout/Card/Card.styles.ts +4 -5
  77. package/src/composites/layout/Card/Card.tsx +2 -2
  78. package/src/composites/layout/Card/Card.types.ts +1 -1
  79. package/src/composites/layout/Navbar/Navbar.styles.ts +5 -5
  80. package/src/composites/layout/Navbar/Navbar.tsx +2 -2
  81. package/src/composites/layout/Sidebar/Sidebar.styles.ts +5 -5
  82. package/src/composites/layout/Sidebar/Sidebar.tsx +2 -2
  83. package/src/composites/overlays/Popover/Popover.styles.ts +4 -4
  84. package/src/composites/overlays/Popover/Popover.tsx +2 -2
  85. package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.styles.ts +5 -6
  86. package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.tsx +6 -3
  87. package/src/composites/range-inputs/ColorScaleSlider/ColorScaleSlider.types.ts +2 -0
  88. package/src/composites/range-inputs/HueSlider/HueSlider.styles.ts +14 -21
  89. package/src/composites/range-inputs/HueSlider/HueSlider.tsx +8 -9
  90. package/src/composites/range-inputs/Slider/Slider.styles.ts +9 -10
  91. package/src/composites/range-inputs/Slider/Slider.tsx +18 -4
  92. package/src/index.ts +73 -60
  93. package/src/primitives/Frame/Frame.styles.ts +8 -7
  94. package/src/primitives/Frame/Frame.tsx +9 -9
  95. package/src/primitives/Frame/Frame.types.ts +1 -1
  96. package/src/primitives/Frame/Frame.utils.ts +1 -1
  97. package/src/primitives/Icon/Icon.tsx +2 -3
  98. package/src/primitives/Text/Text.spans.ts +1 -1
  99. package/src/primitives/Text/Text.tsx +16 -16
  100. package/src/primitives/Text/Text.types.ts +1 -1
  101. package/src/primitives/Wrapper/Wrapper.styles.ts +1 -1
  102. package/src/primitives/Wrapper/Wrapper.tsx +1 -1
  103. package/dist/fonts/GoogleFontLoader.d.ts +0 -20
  104. package/dist/fonts/GoogleFontLoader.d.ts.map +0 -1
  105. package/dist/fonts/IconFontLoader.d.ts +0 -13
  106. package/dist/fonts/IconFontLoader.d.ts.map +0 -1
  107. package/dist/fonts/SelfHostedFontLoader.d.ts +0 -14
  108. package/dist/fonts/SelfHostedFontLoader.d.ts.map +0 -1
  109. package/dist/fonts/buildGoogleFontsUrl.d.ts +0 -2
  110. package/dist/fonts/buildGoogleFontsUrl.d.ts.map +0 -1
  111. package/dist/fonts/measureFont.d.ts +0 -19
  112. package/dist/fonts/measureFont.d.ts.map +0 -1
  113. package/dist/fonts/reportQueue.d.ts +0 -7
  114. package/dist/fonts/reportQueue.d.ts.map +0 -1
  115. package/dist/fonts/useLocalCalibration.d.ts +0 -19
  116. package/dist/fonts/useLocalCalibration.d.ts.map +0 -1
  117. package/dist/fonts/useTypographyCalibrations.d.ts +0 -11
  118. package/dist/fonts/useTypographyCalibrations.d.ts.map +0 -1
  119. package/dist/theme/FrameContext.d.ts +0 -26
  120. package/dist/theme/FrameContext.d.ts.map +0 -1
  121. package/dist/theme/NewtoneProvider.d.ts +0 -40
  122. package/dist/theme/NewtoneProvider.d.ts.map +0 -1
  123. package/dist/theme/defaults.d.ts +0 -8
  124. package/dist/theme/defaults.d.ts.map +0 -1
  125. package/dist/theme/types.d.ts +0 -156
  126. package/dist/theme/types.d.ts.map +0 -1
  127. package/dist/theme/useBreakpoint.d.ts +0 -9
  128. package/dist/theme/useBreakpoint.d.ts.map +0 -1
  129. package/dist/tokens/computeTokens.d.ts +0 -151
  130. package/dist/tokens/computeTokens.d.ts.map +0 -1
  131. package/dist/tokens/types.d.ts +0 -162
  132. package/dist/tokens/types.d.ts.map +0 -1
  133. package/dist/tokens/useTokens.d.ts +0 -26
  134. package/dist/tokens/useTokens.d.ts.map +0 -1
  135. package/src/fonts/GoogleFontLoader.tsx +0 -80
  136. package/src/fonts/IconFontLoader.tsx +0 -51
  137. package/src/fonts/SelfHostedFontLoader.tsx +0 -44
  138. package/src/fonts/buildGoogleFontsUrl.ts +0 -2
  139. package/src/fonts/measureFont.ts +0 -55
  140. package/src/fonts/reportQueue.ts +0 -54
  141. package/src/fonts/useLocalCalibration.ts +0 -97
  142. package/src/fonts/useTypographyCalibrations.ts +0 -15
  143. package/src/theme/FrameContext.tsx +0 -31
  144. package/src/theme/NewtoneProvider.tsx +0 -84
  145. package/src/theme/defaults.ts +0 -71
  146. package/src/theme/types.ts +0 -191
  147. package/src/theme/useBreakpoint.ts +0 -14
  148. package/src/tokens/computeTokens.ts +0 -516
  149. package/src/tokens/types.ts +0 -146
  150. package/src/tokens/useTokens.ts +0 -62
package/dist/index.js CHANGED
@@ -1,825 +1,505 @@
1
- import React14, { createContext, useState, useMemo, useEffect, useContext, useCallback, useRef } from 'react';
2
- import { srgbToHex, getColor, DEFAULT_NEUTRAL_SATURATION, DEFAULT_NEUTRAL_HUE, DEFAULT_ACCENT_SATURATION, DEFAULT_ACCENT_HUE, DEFAULT_SUCCESS_SATURATION, DEFAULT_SUCCESS_HUE, DEFAULT_WARNING_SATURATION, DEFAULT_WARNING_HUE, DEFAULT_ERROR_SATURATION, DEFAULT_ERROR_HUE } from 'newtone';
3
- import { SEMANTIC_WEIGHT_MAP, ROLE_DEFAULT_WEIGHTS, BREAKPOINT_ROLE_SCALE, scaleRoleStep, resolveResponsiveSize, estimateLineWidths, REFERENCE_LINE_HEIGHT_RATIO, buildFontFeatureSettings, getBreakpointForWidth, fontConfigToFamily, DEFAULT_ROLE_SCALES, DEFAULT_LINE_HEIGHTS, DEFAULT_FONT_SIZES, DEFAULT_FONT_SLOTS, buildGoogleFontsUrl } from '@newtonedev/fonts';
4
- export { DEFAULT_FONT_SIZES, DEFAULT_LINE_HEIGHTS, DEFAULT_ROLE_SCALES, buildGoogleFontsUrl } from '@newtonedev/fonts';
5
- import { Text, View, useWindowDimensions, Pressable, TextInput as TextInput$1, ScrollView, PanResponder, Animated, StyleSheet } from 'react-native';
1
+ import { useTokens, useNewtoneTheme, useBreakpoint, useTypographyCalibrations, useLocalCalibration, enqueueObservation, useFrameContext, computeTokens, FrameContext } from 'newtone-api';
2
+ export { ACCENT_DEFAULTS, DEFAULT_FONT_SIZES, DEFAULT_LINE_HEIGHTS, DEFAULT_ROLE_SCALES, DEFAULT_THEME_CONFIG, ERROR_DEFAULTS, FrameContext, NEUTRAL_DEFAULTS, NewtoneProvider, SUCCESS_DEFAULTS, WARNING_DEFAULTS, buildGoogleFontsUrl, computeTokens, enqueueObservation, isV2TokenOverrides, measureAvgCharWidth, migrateV1ToV2, useBreakpoint, useFrameContext, useLocalCalibration, useNewtoneTheme, useTokens, useTypographyCalibrations } from 'newtone-api';
3
+ import React13, { createContext, useState, useMemo, useEffect, useContext, useCallback, useRef } from 'react';
4
+ import { Text, View, Pressable, TextInput as TextInput$1, ScrollView, PanResponder, Animated, StyleSheet } from 'react-native';
5
+ import { SEMANTIC_WEIGHT_MAP, ROLE_DEFAULT_WEIGHTS, BREAKPOINT_ROLE_SCALE, scaleRoleStep, resolveResponsiveSize, estimateLineWidths, REFERENCE_LINE_HEIGHT_RATIO, buildFontFeatureSettings } from '@newtonedev/fonts';
6
+ import { srgbToHex, gamutMapToSrgb } from 'newtone';
6
7
 
7
- // src/theme/NewtoneProvider.tsx
8
- var DEFAULT_THEME_CONFIG = {
9
- colorSystem: {
10
- dynamicRange: {
11
- lightest: 1,
12
- darkest: 1
13
- },
14
- palettes: [
15
- { hue: DEFAULT_NEUTRAL_HUE, saturation: DEFAULT_NEUTRAL_SATURATION },
16
- { hue: DEFAULT_ACCENT_HUE, saturation: DEFAULT_ACCENT_SATURATION },
17
- { hue: DEFAULT_SUCCESS_HUE, saturation: DEFAULT_SUCCESS_SATURATION },
18
- { hue: DEFAULT_WARNING_HUE, saturation: DEFAULT_WARNING_SATURATION },
19
- { hue: DEFAULT_ERROR_HUE, saturation: DEFAULT_ERROR_SATURATION }
20
- ]
21
- },
22
- spacing: {
23
- "00": 0,
24
- // base * 0
25
- "02": 2,
26
- // base * 0.25
27
- "04": 4,
28
- // base * 0.5
29
- "06": 6,
30
- // base * 0.75
31
- "08": 8,
32
- // base * 1 (Medium preset, 8px base)
33
- "10": 10,
34
- // base * 1.25
35
- "12": 12,
36
- // base * 1.5
37
- "16": 16,
38
- // base * 2
39
- "20": 20,
40
- // base * 2.5
41
- "24": 24,
42
- // base * 3
43
- "32": 32,
44
- // base * 4
45
- "40": 40,
46
- // base * 5
47
- "48": 48
48
- // base * 6
49
- },
50
- radius: {
51
- none: 0,
52
- sm: 4,
53
- md: 6,
54
- lg: 8,
55
- xl: 12,
56
- pill: 999
57
- },
58
- typography: {
59
- fonts: DEFAULT_FONT_SLOTS,
60
- fontSizes: DEFAULT_FONT_SIZES,
61
- lineHeights: DEFAULT_LINE_HEIGHTS,
62
- roles: DEFAULT_ROLE_SCALES
63
- },
64
- icons: {
65
- variant: "rounded",
66
- // Material Design 3 aesthetic
67
- weight: 400,
68
- // Normal weight
69
- autoGrade: true
70
- // Enable mode-aware grade
71
- }
72
- };
73
-
74
- // src/fonts/GoogleFontLoader.tsx
75
- function GoogleFontLoader({ fonts }) {
76
- const linkRef = useRef(null);
77
- useEffect(() => {
78
- if (typeof document === "undefined") return;
79
- const url = buildGoogleFontsUrl(fonts);
80
- if (linkRef.current) {
81
- linkRef.current.remove();
82
- linkRef.current = null;
83
- }
84
- if (!url) return;
85
- const links = Array.from(document.head.querySelectorAll('link[rel="stylesheet"]'));
86
- if (links.some((el) => el.href === url)) return;
87
- const link = document.createElement("link");
88
- link.rel = "stylesheet";
89
- link.href = url;
90
- document.head.appendChild(link);
91
- linkRef.current = link;
92
- return () => {
93
- if (linkRef.current) {
94
- linkRef.current.remove();
95
- linkRef.current = null;
96
- }
97
- };
98
- }, [
99
- fonts.main.config.family,
100
- fonts.main.config.type,
101
- fonts.main.weights.regular,
102
- fonts.main.weights.medium,
103
- fonts.main.weights.bold,
104
- fonts.display.config.family,
105
- fonts.display.config.type,
106
- fonts.display.weights.regular,
107
- fonts.display.weights.medium,
108
- fonts.display.weights.bold,
109
- fonts.mono.config.family,
110
- fonts.mono.config.type,
111
- fonts.mono.weights.regular,
112
- fonts.mono.weights.medium,
113
- fonts.mono.weights.bold,
114
- fonts.currency.config.family,
115
- fonts.currency.config.type,
116
- fonts.currency.weights.regular,
117
- fonts.currency.weights.medium,
118
- fonts.currency.weights.bold
8
+ // src/index.ts
9
+ var hadKeyboardEvent = false;
10
+ var isListenerSetup = false;
11
+ function setupModality() {
12
+ if (isListenerSetup || typeof document === "undefined") return;
13
+ isListenerSetup = true;
14
+ const NAVIGATION_KEYS = /* @__PURE__ */ new Set([
15
+ "Tab",
16
+ "ArrowUp",
17
+ "ArrowDown",
18
+ "ArrowLeft",
19
+ "ArrowRight",
20
+ "Enter",
21
+ " ",
22
+ "Escape"
119
23
  ]);
120
- return null;
121
- }
122
- function SelfHostedFontLoader({ fontFaceCss }) {
123
- const styleRef = useRef(null);
124
- useEffect(() => {
125
- if (typeof document === "undefined") return;
126
- if (styleRef.current) {
127
- styleRef.current.remove();
128
- styleRef.current = null;
24
+ document.addEventListener("keydown", (e) => {
25
+ if (NAVIGATION_KEYS.has(e.key)) {
26
+ hadKeyboardEvent = true;
129
27
  }
130
- if (!fontFaceCss) return;
131
- const style = document.createElement("style");
132
- style.setAttribute("data-newtone-fonts", "self-hosted");
133
- style.textContent = fontFaceCss;
134
- document.head.appendChild(style);
135
- styleRef.current = style;
136
- return () => {
137
- if (styleRef.current) {
138
- styleRef.current.remove();
139
- styleRef.current = null;
140
- }
141
- };
142
- }, [fontFaceCss]);
143
- return null;
28
+ }, true);
29
+ document.addEventListener("pointerdown", () => {
30
+ hadKeyboardEvent = false;
31
+ }, true);
32
+ document.addEventListener("mousedown", () => {
33
+ hadKeyboardEvent = false;
34
+ }, true);
144
35
  }
145
- function IconFontLoader({ icons }) {
146
- const linkRef = useRef(null);
36
+ function useFocusVisible() {
37
+ const [isFocusVisible, setIsFocusVisible] = useState(false);
147
38
  useEffect(() => {
148
- if (typeof document === "undefined") return;
149
- const variantName = icons.variant.charAt(0).toUpperCase() + icons.variant.slice(1);
150
- const family = `Material+Symbols+${variantName}`;
151
- const url = `https://fonts.googleapis.com/css2?family=${family}:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block`;
152
- if (linkRef.current) {
153
- linkRef.current.remove();
154
- linkRef.current = null;
39
+ setupModality();
40
+ }, []);
41
+ const onFocus = useCallback(() => {
42
+ if (hadKeyboardEvent) {
43
+ setIsFocusVisible(true);
155
44
  }
156
- const links = Array.from(document.head.querySelectorAll('link[rel="stylesheet"]'));
157
- if (links.some((el) => el.href === url)) return;
158
- const link = document.createElement("link");
159
- link.rel = "stylesheet";
160
- link.href = url;
161
- document.head.appendChild(link);
162
- linkRef.current = link;
163
- return () => {
164
- if (linkRef.current) {
165
- linkRef.current.remove();
166
- linkRef.current = null;
167
- }
168
- };
169
- }, [icons.variant]);
170
- return null;
45
+ }, []);
46
+ const onBlur = useCallback(() => {
47
+ setIsFocusVisible(false);
48
+ }, []);
49
+ const focusProps = { onFocus, onBlur };
50
+ return { isFocusVisible, focusProps };
171
51
  }
172
52
 
173
- // src/theme/NewtoneProvider.tsx
174
- var ThemeContext = createContext(null);
175
- function NewtoneProvider({
176
- config = DEFAULT_THEME_CONFIG,
177
- initialMode = "light",
178
- children,
179
- reportingEndpoint,
180
- fontFaceCss
181
- }) {
182
- const [mode, setMode] = useState(initialMode);
183
- const value = useMemo(
184
- () => ({
185
- config,
186
- mode,
187
- setMode,
188
- reportingEndpoint
189
- }),
190
- [config, mode, reportingEndpoint]
191
- );
192
- return /* @__PURE__ */ React14.createElement(ThemeContext.Provider, { value }, fontFaceCss ? /* @__PURE__ */ React14.createElement(SelfHostedFontLoader, { fontFaceCss }) : /* @__PURE__ */ React14.createElement(GoogleFontLoader, { fonts: config.typography.fonts }), /* @__PURE__ */ React14.createElement(IconFontLoader, { icons: config.icons }), children);
53
+ // src/primitives/Frame/Frame.utils.ts
54
+ function resolveSpacing(value, tokens) {
55
+ if (typeof value === "number") return value;
56
+ return tokens.spacing[value];
193
57
  }
194
- function useNewtoneTheme() {
195
- const context = useContext(ThemeContext);
196
- if (!context) {
197
- throw new Error("useNewtoneTheme must be used within NewtoneProvider");
198
- }
199
- return context;
200
- }
201
- var FrameContext = createContext(null);
202
- function useFrameContext() {
203
- return useContext(FrameContext);
204
- }
205
- var NEUTRAL_DEFAULTS = {
206
- light: {
207
- background: { elevated: 0, ground: 0.03, sunken: 0.06 },
208
- text: { primary: 0.9, secondary: 0.7, tertiary: 0.5, disabled: 0.3 },
209
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
210
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
211
- },
212
- dark: {
213
- background: { elevated: 0.24, ground: 0.2, sunken: 0.16 },
214
- text: { primary: 1, secondary: 0.85, tertiary: 0.7, disabled: 0.55 },
215
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
216
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
217
- }
218
- };
219
- var ACCENT_DEFAULTS = {
220
- light: {
221
- background: { elevated: 0, ground: 0.03, sunken: 0.06 },
222
- text: { primary: 0.9, secondary: 0.7, tertiary: 0.5, disabled: 0.3 },
223
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
224
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
225
- },
226
- dark: {
227
- background: { elevated: 0.24, ground: 0.2, sunken: 0.16 },
228
- text: { primary: 1, secondary: 0.85, tertiary: 0.7, disabled: 0.55 },
229
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
230
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
231
- }
232
- };
233
- var SUCCESS_DEFAULTS = {
234
- light: {
235
- background: { elevated: 0, ground: 0.03, sunken: 0.06 },
236
- text: { primary: 0.9, secondary: 0.7, tertiary: 0.5, disabled: 0.3 },
237
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
238
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
239
- },
240
- dark: {
241
- background: { elevated: 0.24, ground: 0.2, sunken: 0.16 },
242
- text: { primary: 1, secondary: 0.85, tertiary: 0.7, disabled: 0.55 },
243
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
244
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
245
- }
246
- };
247
- var WARNING_DEFAULTS = {
248
- light: {
249
- background: { elevated: 0, ground: 0.03, sunken: 0.06 },
250
- text: { primary: 0.9, secondary: 0.7, tertiary: 0.5, disabled: 0.3 },
251
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
252
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
253
- },
254
- dark: {
255
- background: { elevated: 0.24, ground: 0.2, sunken: 0.16 },
256
- text: { primary: 1, secondary: 0.85, tertiary: 0.7, disabled: 0.55 },
257
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
258
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
58
+ function resolvePadding(prop, tokens) {
59
+ if (typeof prop === "string" || typeof prop === "number") {
60
+ const px = resolveSpacing(prop, tokens);
61
+ return { top: px, right: px, bottom: px, left: px };
259
62
  }
260
- };
261
- var ERROR_DEFAULTS = {
262
- light: {
263
- background: { elevated: 0, ground: 0.03, sunken: 0.06 },
264
- text: { primary: 0.9, secondary: 0.7, tertiary: 0.5, disabled: 0.3 },
265
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
266
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
267
- },
268
- dark: {
269
- background: { elevated: 0.24, ground: 0.2, sunken: 0.16 },
270
- text: { primary: 1, secondary: 0.85, tertiary: 0.7, disabled: 0.55 },
271
- action: { enabled: 0.04, hovered: 0.06, pressed: 0.08 },
272
- border: { enabled: 0.08, focused: 0.16, filled: 0.24 }
63
+ if ("x" in prop || "y" in prop) {
64
+ const axes = prop;
65
+ const x = axes.x !== void 0 ? resolveSpacing(axes.x, tokens) : 0;
66
+ const y = axes.y !== void 0 ? resolveSpacing(axes.y, tokens) : 0;
67
+ return { top: y, right: x, bottom: y, left: x };
273
68
  }
274
- };
275
- var clamp = (n) => Math.max(0, Math.min(1, n));
276
- function computePaletteTokens(palette, defaults, mode, elevation, dynamicRange, elevationDelta, effectiveTextMode, autoAccentNv, neutralTextPrimary, neutralBgElevated) {
277
- const modeDefaults = defaults[mode];
278
- const toEngineNv = (nv) => mode === "light" ? 1 - nv : nv;
279
- const textToEngineNv = (nv) => effectiveTextMode === "light" ? 1 - nv : nv;
280
- const colorAt = (engineNv) => getColor(
281
- palette.hue,
282
- palette.saturation,
283
- dynamicRange,
284
- clamp(engineNv),
285
- palette.desaturation,
286
- palette.paletteHueGrading
287
- );
288
- const resolveKeyNv = (p) => mode === "dark" ? p.keyNormalizedValueDark : p.keyNormalizedValue;
289
- const keyNv = resolveKeyNv(palette);
290
- const fillBaseNv = keyNv ?? autoAccentNv;
291
- const fillNv = clamp(fillBaseNv + elevationDelta);
292
- const fill = colorAt(fillNv);
293
- const hoverDir = effectiveTextMode === "light" ? -modeDefaults.action.hovered : modeDefaults.action.hovered;
294
- const activeDir = effectiveTextMode === "light" ? -modeDefaults.action.pressed : modeDefaults.action.pressed;
295
- const fillHover = colorAt(clamp(fillNv + hoverDir));
296
- const fillActive = colorAt(clamp(fillNv + activeDir));
297
- const onFill = fill.oklch.L > 0.6 ? neutralTextPrimary : neutralBgElevated;
298
- const bgNormalized = elevation === 2 ? modeDefaults.background.elevated : elevation === 1 ? modeDefaults.background.ground : modeDefaults.background.sunken;
299
- const bgNv = clamp(toEngineNv(bgNormalized));
300
- const background = colorAt(bgNv);
301
- const backgroundElevated = colorAt(clamp(toEngineNv(modeDefaults.background.elevated)));
302
- const backgroundSunken = colorAt(clamp(toEngineNv(modeDefaults.background.sunken)));
303
- const interactiveOffset = modeDefaults.action.enabled;
304
- const interactiveNv = clamp(bgNv + (effectiveTextMode === "light" ? -interactiveOffset : interactiveOffset));
305
- const backgroundInteractive = colorAt(interactiveNv);
306
- const hoverShift = modeDefaults.action.hovered;
307
- const activeShift = modeDefaults.action.pressed;
308
- const backgroundInteractiveHover = colorAt(clamp(interactiveNv + (effectiveTextMode === "light" ? -hoverShift : hoverShift)));
309
- const backgroundInteractiveActive = colorAt(clamp(interactiveNv + (effectiveTextMode === "light" ? -activeShift : activeShift)));
310
- const textPrimary = colorAt(clamp(textToEngineNv(modeDefaults.text.primary) + elevationDelta));
311
- const textSecondary = colorAt(clamp(textToEngineNv(modeDefaults.text.secondary) + elevationDelta));
312
- const textTertiary = colorAt(clamp(textToEngineNv(modeDefaults.text.tertiary) + elevationDelta));
313
- const textDisabled = colorAt(clamp(textToEngineNv(modeDefaults.text.disabled) + elevationDelta));
314
- const borderOffset = modeDefaults.border.enabled;
315
- const borderNv = effectiveTextMode === "light" ? bgNv - borderOffset : bgNv + borderOffset;
316
- const border = colorAt(clamp(borderNv));
69
+ const sides = prop;
317
70
  return {
318
- fill,
319
- fillHover,
320
- fillActive,
321
- onFill,
322
- background,
323
- backgroundElevated,
324
- backgroundSunken,
325
- backgroundInteractive,
326
- backgroundInteractiveHover,
327
- backgroundInteractiveActive,
328
- textPrimary,
329
- textSecondary,
330
- textTertiary,
331
- textDisabled,
332
- border
71
+ top: sides.top !== void 0 ? resolveSpacing(sides.top, tokens) : 0,
72
+ right: sides.right !== void 0 ? resolveSpacing(sides.right, tokens) : 0,
73
+ bottom: sides.bottom !== void 0 ? resolveSpacing(sides.bottom, tokens) : 0,
74
+ left: sides.left !== void 0 ? resolveSpacing(sides.left, tokens) : 0
333
75
  };
334
76
  }
335
- function computeTokens(config, mode, elevation, spacing, radius, typography, icons, tokenOverrides) {
336
- const { dynamicRange, palettes } = config;
337
- const palette = palettes[0];
338
- if (!palette) {
339
- throw new Error("Neutral palette (index 0) not found");
340
- }
341
- const neutralDefaults = NEUTRAL_DEFAULTS[mode];
342
- const toEngineNv = (nv) => mode === "light" ? 1 - nv : nv;
343
- const bgElevatedNorm = mode === "light" ? tokenOverrides?.backgroundElevated : tokenOverrides?.backgroundElevatedDark;
344
- const bgDefaultNorm = mode === "light" ? tokenOverrides?.backgroundDefault : tokenOverrides?.backgroundDefaultDark;
345
- const bgSunkenNorm = mode === "light" ? tokenOverrides?.backgroundSunken : tokenOverrides?.backgroundSunkenDark;
346
- const textPrimaryNorm = mode === "light" ? tokenOverrides?.textPrimaryNormalized : tokenOverrides?.textPrimaryNormalizedDark;
347
- const textSecondaryNorm = mode === "light" ? tokenOverrides?.textSecondaryNormalized : tokenOverrides?.textSecondaryNormalizedDark;
348
- const textTertiaryNorm = mode === "light" ? tokenOverrides?.textTertiaryNormalized : tokenOverrides?.textTertiaryNormalizedDark;
349
- const textDisabledNorm = mode === "light" ? tokenOverrides?.textDisabledNormalized : tokenOverrides?.textDisabledNormalizedDark;
350
- const bgNormalized = elevation === 2 ? bgElevatedNorm ?? neutralDefaults.background.elevated : elevation === 1 ? bgDefaultNorm ?? neutralDefaults.background.ground : bgSunkenNorm ?? neutralDefaults.background.sunken;
351
- const backgroundNv = clamp(toEngineNv(bgNormalized));
352
- const elevatedNv = clamp(toEngineNv(bgElevatedNorm ?? neutralDefaults.background.elevated));
353
- const sunkenNv = clamp(toEngineNv(bgSunkenNorm ?? neutralDefaults.background.sunken));
354
- const elevationDelta = backgroundNv - elevatedNv;
355
- const effectiveTextMode = backgroundNv >= 0.5 ? "light" : "dark";
356
- const background = getColor(
357
- palette.hue,
358
- palette.saturation,
359
- dynamicRange,
360
- backgroundNv,
361
- palette.desaturation,
362
- palette.paletteHueGrading
363
- );
364
- const backgroundElevated = getColor(
365
- palette.hue,
366
- palette.saturation,
367
- dynamicRange,
368
- elevatedNv,
369
- palette.desaturation,
370
- palette.paletteHueGrading
371
- );
372
- const backgroundSunken = getColor(
373
- palette.hue,
374
- palette.saturation,
375
- dynamicRange,
376
- sunkenNv,
377
- palette.desaturation,
378
- palette.paletteHueGrading
379
- );
380
- const INTERACTIVE_COMPONENT_OFFSET = mode === "light" ? tokenOverrides?.interactiveComponentOffset ?? neutralDefaults.action.enabled : tokenOverrides?.interactiveComponentOffsetDark ?? neutralDefaults.action.enabled;
381
- const HOVER_SHIFT = mode === "light" ? tokenOverrides?.hoverShift ?? neutralDefaults.action.hovered : tokenOverrides?.hoverShiftDark ?? neutralDefaults.action.hovered;
382
- const ACTIVE_SHIFT = mode === "light" ? tokenOverrides?.activeShift ?? neutralDefaults.action.pressed : tokenOverrides?.activeShiftDark ?? neutralDefaults.action.pressed;
383
- const BORDER_OFFSET = mode === "light" ? tokenOverrides?.borderOffset ?? neutralDefaults.border.enabled : tokenOverrides?.borderOffsetDark ?? neutralDefaults.border.enabled;
384
- const interactiveComponentNv = clamp(backgroundNv + (effectiveTextMode === "light" ? -INTERACTIVE_COMPONENT_OFFSET : INTERACTIVE_COMPONENT_OFFSET));
385
- const backgroundInteractive = getColor(
386
- palette.hue,
387
- palette.saturation,
388
- dynamicRange,
389
- interactiveComponentNv,
390
- palette.desaturation,
391
- palette.paletteHueGrading
392
- );
393
- const neutralHoverNv = clamp(interactiveComponentNv + (effectiveTextMode === "light" ? -HOVER_SHIFT : HOVER_SHIFT));
394
- const backgroundInteractiveHover = getColor(
395
- palette.hue,
396
- palette.saturation,
397
- dynamicRange,
398
- neutralHoverNv,
399
- palette.desaturation,
400
- palette.paletteHueGrading
401
- );
402
- const neutralActiveNv = clamp(interactiveComponentNv + (effectiveTextMode === "light" ? -ACTIVE_SHIFT : ACTIVE_SHIFT));
403
- const backgroundInteractiveActive = getColor(
404
- palette.hue,
405
- palette.saturation,
406
- dynamicRange,
407
- neutralActiveNv,
408
- palette.desaturation,
409
- palette.paletteHueGrading
410
- );
411
- const textToEngineNv = (nv) => effectiveTextMode === "light" ? 1 - nv : nv;
412
- const textPrimary = getColor(
413
- palette.hue,
414
- palette.saturation,
415
- dynamicRange,
416
- clamp(textToEngineNv(textPrimaryNorm ?? neutralDefaults.text.primary) + elevationDelta),
417
- palette.desaturation,
418
- palette.paletteHueGrading
419
- );
420
- const textSecondary = getColor(
421
- palette.hue,
422
- palette.saturation,
423
- dynamicRange,
424
- clamp(textToEngineNv(textSecondaryNorm ?? neutralDefaults.text.secondary) + elevationDelta),
425
- palette.desaturation,
426
- palette.paletteHueGrading
427
- );
428
- const textTertiary = getColor(
429
- palette.hue,
430
- palette.saturation,
431
- dynamicRange,
432
- clamp(textToEngineNv(textTertiaryNorm ?? neutralDefaults.text.tertiary) + elevationDelta),
433
- palette.desaturation,
434
- palette.paletteHueGrading
435
- );
436
- const textDisabled = getColor(
437
- palette.hue,
438
- palette.saturation,
439
- dynamicRange,
440
- clamp(textToEngineNv(textDisabledNorm ?? neutralDefaults.text.disabled) + elevationDelta),
441
- palette.desaturation,
442
- palette.paletteHueGrading
443
- );
444
- const borderNv = effectiveTextMode === "light" ? backgroundNv - BORDER_OFFSET : backgroundNv + BORDER_OFFSET;
445
- const border = getColor(
446
- palette.hue,
447
- palette.saturation,
448
- dynamicRange,
449
- clamp(borderNv),
450
- palette.desaturation,
451
- palette.paletteHueGrading
452
- );
453
- const autoAccentNv = clamp(textToEngineNv(textPrimaryNorm ?? neutralDefaults.text.primary));
454
- const accentPalette = palettes[1];
455
- if (!accentPalette) {
456
- throw new Error("Accent palette (index 1) not found");
77
+ function resolveGap(prop, tokens) {
78
+ if (typeof prop === "string" || typeof prop === "number") {
79
+ const px = resolveSpacing(prop, tokens);
80
+ return { rowGap: px, columnGap: px };
457
81
  }
458
- const accent = computePaletteTokens(
459
- accentPalette,
460
- ACCENT_DEFAULTS,
461
- mode,
462
- elevation,
463
- dynamicRange,
464
- elevationDelta,
465
- effectiveTextMode,
466
- autoAccentNv,
467
- textPrimary,
468
- backgroundElevated
469
- );
470
- const successPalette = palettes[2];
471
- const warningPalette = palettes[3];
472
- const errorPalette = palettes[4];
473
- const success = successPalette ? computePaletteTokens(
474
- successPalette,
475
- SUCCESS_DEFAULTS,
476
- mode,
477
- elevation,
478
- dynamicRange,
479
- elevationDelta,
480
- effectiveTextMode,
481
- autoAccentNv,
482
- textPrimary,
483
- backgroundElevated
484
- ) : accent;
485
- const warning = warningPalette ? computePaletteTokens(
486
- warningPalette,
487
- WARNING_DEFAULTS,
488
- mode,
489
- elevation,
490
- dynamicRange,
491
- elevationDelta,
492
- effectiveTextMode,
493
- autoAccentNv,
494
- textPrimary,
495
- backgroundElevated
496
- ) : accent;
497
- const error = errorPalette ? computePaletteTokens(
498
- errorPalette,
499
- ERROR_DEFAULTS,
500
- mode,
501
- elevation,
502
- dynamicRange,
503
- elevationDelta,
504
- effectiveTextMode,
505
- autoAccentNv,
506
- textPrimary,
507
- backgroundElevated
508
- ) : accent;
509
82
  return {
510
- background,
511
- backgroundElevated,
512
- backgroundSunken,
513
- backgroundInteractive,
514
- backgroundInteractiveHover,
515
- backgroundInteractiveActive,
516
- textPrimary,
517
- textSecondary,
518
- textTertiary,
519
- textDisabled,
520
- border,
521
- accent,
522
- success,
523
- warning,
524
- error,
525
- spacing,
526
- radius,
527
- typography: {
528
- fonts: {
529
- main: {
530
- family: fontConfigToFamily(typography.fonts.main.config),
531
- weights: typography.fonts.main.weights
532
- },
533
- display: {
534
- family: fontConfigToFamily(typography.fonts.display.config),
535
- weights: typography.fonts.display.weights
536
- },
537
- mono: {
538
- family: fontConfigToFamily(typography.fonts.mono.config),
539
- weights: typography.fonts.mono.weights
540
- },
541
- currency: {
542
- family: fontConfigToFamily(typography.fonts.currency.config),
543
- weights: typography.fonts.currency.weights
544
- }
545
- },
546
- fontSizes: typography.fontSizes,
547
- lineHeights: typography.lineHeights
548
- },
549
- icons: {
550
- variant: icons.variant,
551
- weight: icons.weight,
552
- grade: icons.autoGrade ? mode === "light" ? -25 : 200 : 0
553
- }
83
+ rowGap: prop.row !== void 0 ? resolveSpacing(prop.row, tokens) : 0,
84
+ columnGap: prop.column !== void 0 ? resolveSpacing(prop.column, tokens) : 0
554
85
  };
555
86
  }
556
-
557
- // src/tokens/useTokens.ts
558
- function useTokens(elevation) {
559
- const { config, mode } = useNewtoneTheme();
560
- const frameCtx = useFrameContext();
561
- const resolvedElevation = elevation ?? frameCtx?.elevation ?? 1;
562
- const canReuse = frameCtx !== null && elevation === void 0 && frameCtx.elevation === resolvedElevation;
563
- return useMemo(() => {
564
- if (canReuse) {
565
- return { ...frameCtx.tokens, elevation: resolvedElevation };
566
- }
567
- const tokens = computeTokens(
568
- config.colorSystem,
569
- mode,
570
- resolvedElevation,
571
- config.spacing,
572
- config.radius,
573
- config.typography,
574
- config.icons,
575
- config.tokenOverrides
576
- );
577
- return { ...tokens, elevation: resolvedElevation };
578
- }, [config, mode, resolvedElevation, canReuse, frameCtx?.tokens]);
87
+ function resolveRadius(value, tokens) {
88
+ if (typeof value === "number") return value;
89
+ return tokens.radius[value];
579
90
  }
580
- function computeButtonPadding(size, hasIcon, hasText, iconPosition) {
581
- const basePadding = {
582
- sm: 8,
583
- md: 12,
584
- lg: 16
585
- };
586
- const base = basePadding[size];
587
- const textExtra = 8;
588
- if (!hasText && hasIcon) {
589
- return {
590
- paddingLeft: base,
591
- paddingRight: base,
592
- paddingTop: base,
593
- paddingBottom: base
594
- };
595
- }
596
- if (hasText && !hasIcon) {
597
- return {
598
- paddingLeft: base + textExtra,
599
- paddingRight: base + textExtra,
600
- paddingTop: base,
601
- paddingBottom: base
602
- };
603
- }
604
- if (hasText && hasIcon) {
605
- if (iconPosition === "left") {
606
- return {
607
- paddingLeft: base,
608
- paddingRight: base + textExtra,
609
- paddingTop: base,
610
- paddingBottom: base
611
- };
612
- } else {
613
- return {
614
- paddingLeft: base + textExtra,
615
- paddingRight: base,
616
- paddingTop: base,
617
- paddingBottom: base
618
- };
619
- }
91
+ function resolveRadiusCorners(prop, tokens) {
92
+ if (typeof prop === "string" || typeof prop === "number") {
93
+ const px = resolveRadius(prop, tokens);
94
+ return { topLeft: px, topRight: px, bottomLeft: px, bottomRight: px };
620
95
  }
621
96
  return {
622
- paddingLeft: base,
623
- paddingRight: base,
624
- paddingTop: base,
625
- paddingBottom: base
97
+ topLeft: prop.topLeft !== void 0 ? resolveRadius(prop.topLeft, tokens) : 0,
98
+ topRight: prop.topRight !== void 0 ? resolveRadius(prop.topRight, tokens) : 0,
99
+ bottomLeft: prop.bottomLeft !== void 0 ? resolveRadius(prop.bottomLeft, tokens) : 0,
100
+ bottomRight: prop.bottomRight !== void 0 ? resolveRadius(prop.bottomRight, tokens) : 0
626
101
  };
627
102
  }
628
- function getPaletteTokens(semantic, tokens) {
629
- switch (semantic) {
630
- case "accent":
631
- return tokens.accent;
632
- case "success":
633
- return tokens.success;
634
- case "error":
635
- return tokens.error;
636
- case "warning":
637
- return tokens.warning;
638
- default:
639
- return void 0;
640
- }
103
+ function hasPositiveRadius(corners) {
104
+ return corners.topLeft > 0 || corners.topRight > 0 || corners.bottomLeft > 0 || corners.bottomRight > 0;
641
105
  }
642
- function getButtonConfig(variant, semantic, size, disabled, tokens) {
643
- const sizeConfig = getSizeConfig(size, tokens);
644
- const variantColors = getVariantColors(variant, semantic, disabled, tokens);
645
- return {
646
- variantColors,
647
- sizeTokens: {
648
- padding: sizeConfig.padding,
649
- gap: sizeConfig.gap,
650
- borderRadius: sizeConfig.borderRadius,
651
- textSize: sizeConfig.textSize,
652
- iconSize: sizeConfig.iconSize
106
+ function resolveSizing(width, height) {
107
+ const style = {};
108
+ if (width !== void 0) {
109
+ if (width === "fill") {
110
+ style.flexGrow = 1;
111
+ style.width = "100%";
112
+ } else if (typeof width === "number") {
113
+ style.width = width;
653
114
  }
654
- };
115
+ }
116
+ if (height !== void 0) {
117
+ if (height === "fill") {
118
+ style.flexGrow = 1;
119
+ style.height = "100%";
120
+ } else if (typeof height === "number") {
121
+ style.height = height;
122
+ }
123
+ }
124
+ return style;
655
125
  }
656
- function getSizeConfig(size, tokens) {
657
- const configs = {
658
- sm: {
659
- padding: 8,
660
- gap: tokens.spacing["08"],
661
- borderRadius: 8,
662
- textSize: "md",
663
- // 16px
664
- iconSize: 24
665
- },
666
- md: {
667
- padding: 12,
668
- gap: tokens.spacing["08"],
669
- borderRadius: 12,
670
- textSize: "md",
671
- // 16px
672
- iconSize: 24
673
- },
674
- lg: {
675
- padding: 16,
676
- gap: tokens.spacing["08"],
677
- borderRadius: 16,
678
- textSize: "md",
679
- // 16px
680
- iconSize: 24
681
- }
682
- };
683
- return configs[size];
126
+ var ALIGN_MAP = {
127
+ start: "flex-start",
128
+ center: "center",
129
+ end: "flex-end",
130
+ stretch: "stretch",
131
+ baseline: "baseline"
132
+ };
133
+ var JUSTIFY_MAP = {
134
+ start: "flex-start",
135
+ center: "center",
136
+ end: "flex-end",
137
+ between: "space-between",
138
+ around: "space-around",
139
+ evenly: "space-evenly"
140
+ };
141
+ function resolveAlignment(align) {
142
+ return ALIGN_MAP[align];
684
143
  }
685
- function getVariantColors(variant, semantic, disabled, tokens) {
686
- if (disabled) {
687
- const baseColors = getVariantColorsForState(variant, semantic, tokens);
688
- const disabledBg = srgbToHex(tokens.backgroundSunken.srgb);
689
- return {
690
- ...baseColors,
691
- bg: disabledBg,
692
- hoveredBg: disabledBg,
693
- pressedBg: disabledBg,
694
- textColor: srgbToHex(tokens.textSecondary.srgb),
695
- iconColor: srgbToHex(tokens.textSecondary.srgb)
696
- };
144
+ function resolveJustification(justify) {
145
+ return JUSTIFY_MAP[justify];
146
+ }
147
+ function resolveFlexDirection(direction, reverse) {
148
+ if (direction === "horizontal") {
149
+ return reverse ? "row-reverse" : "row";
697
150
  }
698
- return getVariantColorsForState(variant, semantic, tokens);
151
+ return reverse ? "column-reverse" : "column";
699
152
  }
700
- function getVariantColorsForState(variant, semantic, tokens) {
701
- const paletteTokens = getPaletteTokens(semantic, tokens);
702
- if (variant === "primary") {
703
- if (semantic === "neutral") {
704
- return {
705
- bg: srgbToHex(tokens.backgroundInteractive.srgb),
706
- hoveredBg: srgbToHex(tokens.backgroundInteractiveHover.srgb),
707
- pressedBg: srgbToHex(tokens.backgroundInteractiveActive.srgb),
708
- textColor: srgbToHex(tokens.textPrimary.srgb),
709
- iconColor: srgbToHex(tokens.textPrimary.srgb),
710
- borderWidth: 1,
711
- borderColor: "transparent"
712
- };
713
- }
714
- return {
715
- bg: srgbToHex(paletteTokens.fill.srgb),
716
- hoveredBg: srgbToHex(paletteTokens.fillHover.srgb),
717
- pressedBg: srgbToHex(paletteTokens.fillActive.srgb),
718
- textColor: srgbToHex(paletteTokens.onFill.srgb),
719
- iconColor: srgbToHex(paletteTokens.onFill.srgb),
720
- borderWidth: 1,
721
- borderColor: "transparent"
722
- };
153
+
154
+ // src/primitives/Frame/Frame.styles.ts
155
+ function getFrameStyles(input) {
156
+ const {
157
+ tokens,
158
+ gamut,
159
+ frameElevation,
160
+ layout = "flex",
161
+ direction = "vertical",
162
+ wrap = false,
163
+ reverse = false,
164
+ columns,
165
+ rows,
166
+ align,
167
+ justify,
168
+ padding,
169
+ gap,
170
+ width,
171
+ height,
172
+ minWidth,
173
+ maxWidth,
174
+ minHeight,
175
+ maxHeight,
176
+ radius,
177
+ bordered = false,
178
+ disabled = false
179
+ } = input;
180
+ const container = {};
181
+ container.backgroundColor = tokens.background[gamut];
182
+ container.color = tokens.textPrimary[gamut];
183
+ if (layout === "flex") {
184
+ container.display = "flex";
185
+ container.flexDirection = resolveFlexDirection(direction, reverse);
186
+ if (wrap) container.flexWrap = "wrap";
723
187
  }
724
- if (variant === "secondary") {
725
- if (semantic === "neutral") {
726
- return {
727
- bg: "transparent",
728
- hoveredBg: srgbToHex(tokens.backgroundInteractive.srgb),
729
- pressedBg: srgbToHex(tokens.backgroundInteractiveHover.srgb),
730
- textColor: srgbToHex(tokens.textPrimary.srgb),
731
- iconColor: srgbToHex(tokens.textPrimary.srgb),
732
- borderWidth: 1,
733
- borderColor: srgbToHex(tokens.border.srgb)
734
- };
735
- }
736
- return {
737
- bg: srgbToHex(paletteTokens.background.srgb),
738
- hoveredBg: srgbToHex(paletteTokens.backgroundInteractive.srgb),
739
- pressedBg: srgbToHex(paletteTokens.backgroundInteractiveHover.srgb),
740
- textColor: srgbToHex(paletteTokens.fill.srgb),
741
- iconColor: srgbToHex(paletteTokens.fill.srgb),
742
- borderWidth: 1,
743
- borderColor: "transparent"
744
- };
188
+ if (layout === "grid") {
189
+ container.display = "flex";
190
+ container.flexDirection = "row";
191
+ container.flexWrap = "wrap";
745
192
  }
746
- if (variant === "tertiary") {
747
- if (semantic === "neutral") {
748
- return {
749
- bg: "transparent",
750
- hoveredBg: srgbToHex(tokens.backgroundInteractive.srgb),
751
- pressedBg: srgbToHex(tokens.backgroundInteractiveHover.srgb),
752
- textColor: srgbToHex(tokens.textPrimary.srgb),
753
- iconColor: srgbToHex(tokens.textPrimary.srgb),
754
- borderWidth: 1,
755
- borderColor: "transparent"
756
- };
193
+ if (align) container.alignItems = resolveAlignment(align);
194
+ if (justify) container.justifyContent = resolveJustification(justify);
195
+ if (padding !== void 0) {
196
+ const p = resolvePadding(padding, tokens);
197
+ container.paddingTop = p.top;
198
+ container.paddingRight = p.right;
199
+ container.paddingBottom = p.bottom;
200
+ container.paddingLeft = p.left;
201
+ }
202
+ if (gap !== void 0) {
203
+ const g = resolveGap(gap, tokens);
204
+ container.rowGap = g.rowGap;
205
+ container.columnGap = g.columnGap;
206
+ }
207
+ const sizing = resolveSizing(width, height);
208
+ Object.assign(container, sizing);
209
+ if (minWidth !== void 0) container.minWidth = minWidth;
210
+ if (maxWidth !== void 0) container.maxWidth = maxWidth;
211
+ if (minHeight !== void 0) container.minHeight = minHeight;
212
+ if (maxHeight !== void 0) container.maxHeight = maxHeight;
213
+ if (radius !== void 0) {
214
+ const corners = resolveRadiusCorners(radius, tokens);
215
+ container.borderTopLeftRadius = corners.topLeft;
216
+ container.borderTopRightRadius = corners.topRight;
217
+ container.borderBottomLeftRadius = corners.bottomLeft;
218
+ container.borderBottomRightRadius = corners.bottomRight;
219
+ if (hasPositiveRadius(corners)) {
220
+ container.overflow = "hidden";
757
221
  }
758
- return {
759
- bg: "transparent",
760
- hoveredBg: srgbToHex(paletteTokens.background.srgb),
761
- pressedBg: srgbToHex(paletteTokens.backgroundInteractive.srgb),
762
- textColor: srgbToHex(paletteTokens.fill.srgb),
763
- iconColor: srgbToHex(paletteTokens.fill.srgb),
764
- borderWidth: 1,
765
- borderColor: "transparent"
222
+ }
223
+ if (bordered) {
224
+ container.borderWidth = 1;
225
+ container.borderColor = tokens.border[gamut];
226
+ }
227
+ if (frameElevation === 2) {
228
+ container.shadowColor = "#000";
229
+ container.shadowOffset = { width: 0, height: 2 };
230
+ container.shadowOpacity = 0.12;
231
+ container.shadowRadius = 6;
232
+ container.elevation = 4;
233
+ }
234
+ if (disabled) {
235
+ container.opacity = 0.5;
236
+ }
237
+ const pressed = StyleSheet.create({
238
+ s: { backgroundColor: tokens.backgroundSunken[gamut] }
239
+ }).s;
240
+ let gridWebStyle = null;
241
+ if (layout === "grid") {
242
+ gridWebStyle = {
243
+ display: "grid",
244
+ // Divide into equal-width columns (e.g. 3 columns → "repeat(3, 1fr)").
245
+ gridTemplateColumns: columns ? `repeat(${columns}, 1fr)` : void 0,
246
+ gridTemplateRows: rows ? `repeat(${rows}, 1fr)` : void 0
766
247
  };
767
248
  }
249
+ const insetBoxShadow = frameElevation === -2 ? "inset 0 2px 4px rgba(0,0,0,0.12)" : null;
768
250
  return {
769
- bg: "transparent",
770
- hoveredBg: "transparent",
771
- pressedBg: "transparent",
772
- textColor: srgbToHex(tokens.textPrimary.srgb),
773
- iconColor: srgbToHex(tokens.textPrimary.srgb),
774
- borderWidth: 0
251
+ // Validate and optimize the container styles through StyleSheet.create(),
252
+ // then extract the single style object with `.c`.
253
+ container: StyleSheet.create({ c: container }).c,
254
+ pressed,
255
+ gridWebStyle,
256
+ insetBoxShadow
775
257
  };
776
258
  }
777
- function Icon({
778
- name,
779
- size,
780
- opticalSize,
781
- fill = 0,
782
- color,
783
- style,
259
+
260
+ // src/primitives/Frame/Frame.tsx
261
+ function wrapTextChildren(children, textStyle) {
262
+ return React13.Children.map(children, (child) => {
263
+ if (typeof child === "string" || typeof child === "number") {
264
+ return /* @__PURE__ */ React13.createElement(Text, { style: textStyle }, child);
265
+ }
266
+ return child;
267
+ });
268
+ }
269
+ function toElevationLevel(frameElevation) {
270
+ if (frameElevation <= -1) return 0;
271
+ if (frameElevation === 0) return 1;
272
+ return 2;
273
+ }
274
+ function Frame({
275
+ children,
276
+ // Elevation
277
+ elevation,
278
+ // Layout
279
+ layout,
280
+ direction,
281
+ wrap,
282
+ reverse,
283
+ columns,
284
+ rows,
285
+ // Alignment
286
+ align,
287
+ justify,
288
+ // Spacing
289
+ padding,
290
+ gap,
291
+ // Sizing
292
+ width,
293
+ height,
294
+ minWidth,
295
+ maxWidth,
296
+ minHeight,
297
+ maxHeight,
298
+ // Appearance
299
+ radius,
300
+ bordered,
301
+ // Interactivity
302
+ onPress,
303
+ href,
304
+ disabled = false,
784
305
  // Accessibility
785
306
  accessibilityLabel,
307
+ accessibilityHint,
786
308
  // Testing & platform
787
309
  testID,
788
310
  nativeID,
789
- ref
311
+ ref,
312
+ // Style override
313
+ style
790
314
  }) {
791
- const tokens = useTokens();
792
- const iconStyle = useMemo(() => {
793
- const fontSize = size ?? tokens.typography.fontSizes["05"];
794
- const getOpticalSize = (size2) => {
795
- if (size2 <= 22) return 20;
796
- if (size2 <= 32) return 24;
797
- if (size2 <= 44) return 40;
798
- return 48;
799
- };
800
- const opsz = opticalSize ?? getOpticalSize(fontSize);
801
- const iconColor = color ?? srgbToHex(tokens.textPrimary.srgb);
802
- const fontFamily = `Material Symbols ${tokens.icons.variant.charAt(0).toUpperCase() + tokens.icons.variant.slice(1)}`;
803
- const fillValue = typeof fill === "boolean" ? fill ? 1 : 0 : fill;
804
- const fontVariationSettings = `'FILL' ${fillValue}, 'wght' ${tokens.icons.weight}, 'GRAD' ${tokens.icons.grade}, 'opsz' ${opsz}`;
805
- return {
806
- fontFamily,
807
- fontSize,
808
- width: fontSize,
809
- // Explicit width ensures square rendering
810
- height: fontSize,
811
- // Explicit height ensures square rendering
812
- lineHeight: fontSize,
813
- // Prevent text line-height from affecting total height
814
- color: iconColor,
815
- userSelect: "none",
315
+ const { config, mode, gamut } = useNewtoneTheme();
316
+ const parentFrameCtx = useFrameContext();
317
+ const resolvedFrameElevation = elevation ?? 0;
318
+ const resolvedElevation = elevation !== void 0 ? toElevationLevel(elevation) : parentFrameCtx?.elevation ?? 1;
319
+ const tokens = useMemo(() => {
320
+ return computeTokens(
321
+ config.colorSystem,
322
+ mode,
323
+ resolvedElevation,
324
+ config.spacing,
325
+ config.radius,
326
+ config.typography,
327
+ config.icons,
328
+ config.tokenOverrides
329
+ );
330
+ }, [config, mode, resolvedElevation]);
331
+ const styles = useMemo(
332
+ () => getFrameStyles({
333
+ tokens,
334
+ gamut,
335
+ frameElevation: resolvedFrameElevation,
336
+ layout,
337
+ direction,
338
+ wrap,
339
+ reverse,
340
+ columns,
341
+ rows,
342
+ align,
343
+ justify,
344
+ padding,
345
+ gap,
346
+ width,
347
+ height,
348
+ minWidth,
349
+ maxWidth,
350
+ minHeight,
351
+ maxHeight,
352
+ radius,
353
+ bordered,
354
+ disabled
355
+ }),
356
+ [
357
+ tokens,
358
+ gamut,
359
+ resolvedFrameElevation,
360
+ layout,
361
+ direction,
362
+ wrap,
363
+ reverse,
364
+ columns,
365
+ rows,
366
+ align,
367
+ justify,
368
+ padding,
369
+ gap,
370
+ width,
371
+ height,
372
+ minWidth,
373
+ maxWidth,
374
+ minHeight,
375
+ maxHeight,
376
+ radius,
377
+ bordered,
378
+ disabled
379
+ ]
380
+ );
381
+ const contextValue = useMemo(
382
+ () => ({ elevation: resolvedElevation, tokens }),
383
+ [resolvedElevation, tokens]
384
+ );
385
+ const webOverrides = [];
386
+ if (styles.gridWebStyle) {
387
+ webOverrides.push(styles.gridWebStyle);
388
+ }
389
+ if (styles.insetBoxShadow) {
390
+ webOverrides.push({ boxShadow: styles.insetBoxShadow });
391
+ }
392
+ const userStyles = Array.isArray(style) ? style : style ? [style] : [];
393
+ const isInteractive = onPress !== void 0 || href !== void 0;
394
+ const { isFocusVisible, focusProps } = useFocusVisible();
395
+ const focusRingStyle = isFocusVisible && !disabled ? {
396
+ outlineWidth: 2,
397
+ outlineStyle: "solid",
398
+ outlineColor: tokens.accent.fill[gamut],
399
+ outlineOffset: 2
400
+ } : void 0;
401
+ const webFocusProps = isInteractive ? focusProps : {};
402
+ const textStyle = useMemo(
403
+ () => ({
404
+ color: tokens.textPrimary[gamut],
405
+ fontSize: tokens.typography.fontSizes["05"],
406
+ fontFamily: tokens.typography.fonts.main.family,
407
+ lineHeight: tokens.typography.lineHeights["06"]
408
+ }),
409
+ [tokens]
410
+ );
411
+ const wrappedChildren = useMemo(
412
+ () => wrapTextChildren(children, textStyle),
413
+ [children, textStyle]
414
+ );
415
+ return /* @__PURE__ */ React13.createElement(FrameContext.Provider, { value: contextValue }, isInteractive ? (
416
+ // Pressable handles taps. When href is set, react-native-web renders
417
+ // it as an <a> tag so it works like a regular link on the web.
418
+ /* @__PURE__ */ React13.createElement(
419
+ Pressable,
420
+ {
421
+ ref,
422
+ testID,
423
+ nativeID,
424
+ accessibilityLabel,
425
+ accessibilityHint,
426
+ accessibilityState: disabled ? { disabled: true } : void 0,
427
+ onPress,
428
+ disabled,
429
+ ...href ? { href, accessibilityRole: "link" } : { accessibilityRole: "button" },
430
+ ...webFocusProps,
431
+ style: ({ pressed }) => [
432
+ styles.container,
433
+ pressed && !disabled && styles.pressed,
434
+ focusRingStyle,
435
+ ...webOverrides,
436
+ ...userStyles
437
+ ]
438
+ },
439
+ wrappedChildren
440
+ )
441
+ ) : (
442
+ // Non-interactive Frame: just a plain View with no tap handling.
443
+ /* @__PURE__ */ React13.createElement(
444
+ View,
445
+ {
446
+ ref,
447
+ testID,
448
+ nativeID,
449
+ accessibilityLabel,
450
+ accessibilityHint,
451
+ style: [styles.container, ...webOverrides, ...userStyles]
452
+ },
453
+ wrappedChildren
454
+ )
455
+ ));
456
+ }
457
+ function Icon({
458
+ name,
459
+ size,
460
+ opticalSize,
461
+ fill = 0,
462
+ color,
463
+ style,
464
+ // Accessibility
465
+ accessibilityLabel,
466
+ // Testing & platform
467
+ testID,
468
+ nativeID,
469
+ ref
470
+ }) {
471
+ const tokens = useTokens();
472
+ const iconStyle = useMemo(() => {
473
+ const fontSize = size ?? tokens.typography.fontSizes["05"];
474
+ const getOpticalSize = (size2) => {
475
+ if (size2 <= 22) return 20;
476
+ if (size2 <= 32) return 24;
477
+ if (size2 <= 44) return 40;
478
+ return 48;
479
+ };
480
+ const opsz = opticalSize ?? getOpticalSize(fontSize);
481
+ const iconColor = color ?? tokens.textPrimary[tokens.gamut];
482
+ const fontFamily = `Material Symbols ${tokens.icons.variant.charAt(0).toUpperCase() + tokens.icons.variant.slice(1)}`;
483
+ const fillValue = typeof fill === "boolean" ? fill ? 1 : 0 : fill;
484
+ const fontVariationSettings = `'FILL' ${fillValue}, 'wght' ${tokens.icons.weight}, 'GRAD' ${tokens.icons.grade}, 'opsz' ${opsz}`;
485
+ return {
486
+ fontFamily,
487
+ fontSize,
488
+ width: fontSize,
489
+ // Explicit width ensures square rendering
490
+ height: fontSize,
491
+ // Explicit height ensures square rendering
492
+ lineHeight: fontSize,
493
+ // Prevent text line-height from affecting total height
494
+ color: iconColor,
495
+ userSelect: "none",
816
496
  // web-only: prevents users from selecting the icon as text
817
497
  fontVariationSettings,
818
498
  // web-only: controls the variable font axes listed above
819
499
  ...style
820
500
  };
821
501
  }, [tokens, size, opticalSize, fill, color, style]);
822
- return /* @__PURE__ */ React14.createElement(
502
+ return /* @__PURE__ */ React13.createElement(
823
503
  Text,
824
504
  {
825
505
  ref,
@@ -832,154 +512,144 @@ function Icon({
832
512
  name
833
513
  );
834
514
  }
835
-
836
- // src/fonts/measureFont.ts
837
- var REF_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ";
838
- function withTimeout(promise, ms, fallback) {
839
- return Promise.race([
840
- promise,
841
- new Promise((resolve) => setTimeout(() => resolve(fallback), ms))
842
- ]);
843
- }
844
- async function measureAvgCharWidth(fontFamily, fontWeight, fallback, fontSize = 16) {
845
- if (typeof document === "undefined") return 0.55;
846
- try {
847
- await withTimeout(
848
- document.fonts.load(`${fontWeight} ${fontSize}px "${fontFamily}"`),
849
- 3e3,
850
- []
851
- );
852
- const canvas = document.createElement("canvas");
853
- const ctx = canvas.getContext("2d");
854
- if (!ctx) return 0.55;
855
- ctx.font = `${fontWeight} ${fontSize}px "${fontFamily}", ${fallback}`;
856
- const ratio = ctx.measureText(REF_STRING).width / REF_STRING.length / fontSize;
857
- return Math.round(ratio * 1e3) / 1e3;
858
- } catch {
859
- return 0.55;
860
- }
861
- }
862
-
863
- // src/fonts/useLocalCalibration.ts
864
- var STORAGE_KEY = "newtone:font-metrics:v1";
865
- var TTL_MS = 7 * 24 * 60 * 60 * 1e3;
866
- function readCache() {
867
- if (typeof localStorage === "undefined") return {};
868
- try {
869
- const raw = localStorage.getItem(STORAGE_KEY);
870
- return raw ? JSON.parse(raw) : {};
871
- } catch {
872
- return {};
873
- }
874
- }
875
- function writeCache(cache) {
876
- if (typeof localStorage === "undefined") return;
877
- try {
878
- localStorage.setItem(STORAGE_KEY, JSON.stringify(cache));
879
- } catch {
880
- }
881
- }
882
- function cacheKey(fontFamily, fontWeight) {
883
- return `${fontFamily}:${fontWeight}`;
884
- }
885
- function useLocalCalibration(fontFamily, fontWeight, fallback, baseCalibration) {
886
- const key = cacheKey(fontFamily, fontWeight);
887
- const [ratio, setRatio] = useState(() => {
888
- const cache = readCache();
889
- const entry = cache[key];
890
- if (entry && Date.now() - entry.measuredAt < TTL_MS) {
891
- return entry.ratio;
892
- }
893
- return baseCalibration ?? 0.55;
894
- });
895
- useEffect(() => {
896
- const cache = readCache();
897
- const entry = cache[key];
898
- if (entry && Date.now() - entry.measuredAt < TTL_MS) {
899
- if (entry.ratio !== ratio) setRatio(entry.ratio);
900
- return;
901
- }
902
- let cancelled = false;
903
- measureAvgCharWidth(fontFamily, fontWeight, fallback).then((measured) => {
904
- if (cancelled) return;
905
- const updated = { ...readCache(), [key]: { ratio: measured, measuredAt: Date.now() } };
906
- writeCache(updated);
907
- setRatio(measured);
908
- });
909
- return () => {
910
- cancelled = true;
911
- };
912
- }, [key, fontFamily, fontWeight, fallback]);
913
- return ratio;
914
- }
915
-
916
- // src/fonts/useTypographyCalibrations.ts
917
- function useTypographyCalibrations() {
918
- const { config } = useNewtoneTheme();
919
- return config.typography.calibrations ?? {};
920
- }
921
-
922
- // src/fonts/reportQueue.ts
923
- var queue = [];
924
- var flushTimer;
925
- function flush() {
926
- if (queue.length === 0) return;
927
- const byEndpoint = /* @__PURE__ */ new Map();
928
- for (const item of queue) {
929
- const group = byEndpoint.get(item.endpoint) ?? [];
930
- group.push(item.payload);
931
- byEndpoint.set(item.endpoint, group);
932
- }
933
- queue.length = 0;
934
- for (const [endpoint, observations] of byEndpoint) {
935
- fetch(endpoint, {
936
- method: "POST",
937
- headers: { "Content-Type": "application/json" },
938
- body: JSON.stringify({ observations }),
939
- // keepalive: true allows the request to outlive the page
940
- keepalive: true
941
- }).catch(() => {
942
- });
515
+ function getWrapperStyles(input) {
516
+ const {
517
+ tokens,
518
+ direction = "vertical",
519
+ wrap = false,
520
+ reverse = false,
521
+ align,
522
+ justify,
523
+ padding,
524
+ gap,
525
+ width,
526
+ height,
527
+ minWidth,
528
+ maxWidth,
529
+ minHeight,
530
+ maxHeight
531
+ } = input;
532
+ const container = {};
533
+ container.flexDirection = resolveFlexDirection(direction, reverse);
534
+ if (wrap) container.flexWrap = "wrap";
535
+ if (align) container.alignItems = resolveAlignment(align);
536
+ if (justify) container.justifyContent = resolveJustification(justify);
537
+ if (padding !== void 0) {
538
+ const p = resolvePadding(padding, tokens);
539
+ container.paddingTop = p.top;
540
+ container.paddingRight = p.right;
541
+ container.paddingBottom = p.bottom;
542
+ container.paddingLeft = p.left;
943
543
  }
944
- }
945
- function enqueueObservation(endpoint, payload) {
946
- queue.push({ endpoint, payload });
947
- if (flushTimer !== void 0) clearTimeout(flushTimer);
948
- flushTimer = setTimeout(flush, 2e3);
949
- }
950
- function useBreakpoint() {
951
- const { width } = useWindowDimensions();
952
- return getBreakpointForWidth(width);
953
- }
954
-
955
- // src/primitives/Text/Text.tsx
956
- var TextScopeContext = createContext(null);
957
- function resolveTextColor(color, tokens) {
958
- switch (color) {
959
- case "primary":
960
- return srgbToHex(tokens.textPrimary.srgb);
961
- case "secondary":
962
- return srgbToHex(tokens.textSecondary.srgb);
963
- case "tertiary":
964
- return srgbToHex(tokens.textTertiary.srgb);
965
- case "disabled":
966
- return srgbToHex(tokens.textDisabled.srgb);
967
- case "accent":
968
- return srgbToHex(tokens.accent.fill.srgb);
969
- case "success":
970
- return srgbToHex(tokens.success.fill.srgb);
971
- case "warning":
972
- return srgbToHex(tokens.warning.fill.srgb);
973
- case "error":
974
- return srgbToHex(tokens.error.fill.srgb);
544
+ if (gap !== void 0) {
545
+ const g = resolveGap(gap, tokens);
546
+ container.rowGap = g.rowGap;
547
+ container.columnGap = g.columnGap;
975
548
  }
549
+ Object.assign(container, resolveSizing(width, height));
550
+ if (minWidth !== void 0) container.minWidth = minWidth;
551
+ if (maxWidth !== void 0) container.maxWidth = maxWidth;
552
+ if (minHeight !== void 0) container.minHeight = minHeight;
553
+ if (maxHeight !== void 0) container.maxHeight = maxHeight;
554
+ return StyleSheet.create({ c: container }).c;
976
555
  }
977
- var ADAPTIVE_ROLES = /* @__PURE__ */ new Set(["headline", "title", "heading", "subheading"]);
978
- var ROLE_HEADING_LEVEL = {
979
- headline: 1,
980
- title: 2,
981
- heading: 3
982
- };
556
+ function Wrapper({
557
+ children,
558
+ direction,
559
+ wrap,
560
+ reverse,
561
+ align,
562
+ justify,
563
+ padding,
564
+ gap,
565
+ width,
566
+ height,
567
+ minWidth,
568
+ maxWidth,
569
+ minHeight,
570
+ maxHeight,
571
+ style,
572
+ // Testing & platform
573
+ testID,
574
+ nativeID,
575
+ ref
576
+ }) {
577
+ const tokens = useTokens(1);
578
+ const containerStyle = useMemo(
579
+ () => getWrapperStyles({
580
+ tokens,
581
+ direction,
582
+ wrap,
583
+ reverse,
584
+ align,
585
+ justify,
586
+ padding,
587
+ gap,
588
+ width,
589
+ height,
590
+ minWidth,
591
+ maxWidth,
592
+ minHeight,
593
+ maxHeight
594
+ }),
595
+ [
596
+ tokens,
597
+ direction,
598
+ wrap,
599
+ reverse,
600
+ align,
601
+ justify,
602
+ padding,
603
+ gap,
604
+ width,
605
+ height,
606
+ minWidth,
607
+ maxWidth,
608
+ minHeight,
609
+ maxHeight
610
+ ]
611
+ );
612
+ const userStyles = Array.isArray(style) ? style : style ? [style] : [];
613
+ return /* @__PURE__ */ React13.createElement(
614
+ View,
615
+ {
616
+ ref,
617
+ testID,
618
+ nativeID,
619
+ accessibilityRole: "none",
620
+ style: [containerStyle, ...userStyles]
621
+ },
622
+ children
623
+ );
624
+ }
625
+ var TextScopeContext = createContext(null);
626
+ function resolveTextColor(color, tokens) {
627
+ const { gamut } = tokens;
628
+ switch (color) {
629
+ case "primary":
630
+ return tokens.textPrimary[gamut];
631
+ case "secondary":
632
+ return tokens.textSecondary[gamut];
633
+ case "tertiary":
634
+ return tokens.textTertiary[gamut];
635
+ case "disabled":
636
+ return tokens.textDisabled[gamut];
637
+ case "accent":
638
+ return tokens.accent.fill[gamut];
639
+ case "success":
640
+ return tokens.success.fill[gamut];
641
+ case "warning":
642
+ return tokens.warning.fill[gamut];
643
+ case "error":
644
+ return tokens.error.fill[gamut];
645
+ }
646
+ }
647
+ var ADAPTIVE_ROLES = /* @__PURE__ */ new Set(["headline", "title", "heading", "subheading"]);
648
+ var ROLE_HEADING_LEVEL = {
649
+ headline: 1,
650
+ title: 2,
651
+ heading: 3
652
+ };
983
653
  function extractCharacterCount(node) {
984
654
  if (typeof node === "string") return node.length;
985
655
  if (typeof node === "number") return String(node).length;
@@ -1086,7 +756,7 @@ function TextBase({
1086
756
  const effectiveA11yRole = accessibilityRoleOverride ?? inferredA11yRole;
1087
757
  const ariaLevel = effectiveA11yRole === "header" ? ROLE_HEADING_LEVEL[role] : void 0;
1088
758
  const scopeCtx = useMemo(() => ({ weights: SEMANTIC_WEIGHT_MAP }), []);
1089
- const textNode = /* @__PURE__ */ React14.createElement(TextScopeContext.Provider, { value: scopeCtx }, /* @__PURE__ */ React14.createElement(
759
+ const textNode = /* @__PURE__ */ React13.createElement(TextScopeContext.Provider, { value: scopeCtx }, /* @__PURE__ */ React13.createElement(
1090
760
  Text,
1091
761
  {
1092
762
  ref,
@@ -1100,7 +770,7 @@ function TextBase({
1100
770
  children
1101
771
  ));
1102
772
  if (responsive && isAdaptive) {
1103
- return /* @__PURE__ */ React14.createElement(
773
+ return /* @__PURE__ */ React13.createElement(
1104
774
  View,
1105
775
  {
1106
776
  onLayout: (e) => {
@@ -1126,30 +796,30 @@ function TextSpan({ children, color, weight, italic, underline, highlight, style
1126
796
  if (highlight) s.backgroundColor = resolveTextColor(highlight, tokens);
1127
797
  return s;
1128
798
  }, [tokens, scopeCtx, color, weight, italic, underline, highlight]);
1129
- return React14.createElement(
799
+ return React13.createElement(
1130
800
  Text,
1131
801
  { style: style ? [spanStyle, ...Array.isArray(style) ? style : [style]] : spanStyle },
1132
802
  children
1133
803
  );
1134
804
  }
1135
805
  function TextBold(props) {
1136
- return React14.createElement(TextSpan, { ...props, weight: "bold" });
806
+ return React13.createElement(TextSpan, { ...props, weight: "bold" });
1137
807
  }
1138
808
  function TextMedium(props) {
1139
- return React14.createElement(TextSpan, { ...props, weight: "medium" });
809
+ return React13.createElement(TextSpan, { ...props, weight: "medium" });
1140
810
  }
1141
811
  function TextItalic(props) {
1142
- return React14.createElement(TextSpan, { ...props, italic: true });
812
+ return React13.createElement(TextSpan, { ...props, italic: true });
1143
813
  }
1144
814
  function TextUnderline(props) {
1145
- return React14.createElement(TextSpan, { ...props, underline: true });
815
+ return React13.createElement(TextSpan, { ...props, underline: true });
1146
816
  }
1147
817
  function TextHighlight(props) {
1148
- return React14.createElement(TextSpan, props);
818
+ return React13.createElement(TextSpan, props);
1149
819
  }
1150
820
 
1151
821
  // src/primitives/Text/index.ts
1152
- var Text2 = Object.assign(TextBase, {
822
+ var Text3 = Object.assign(TextBase, {
1153
823
  Span: TextSpan,
1154
824
  Bold: TextBold,
1155
825
  Medium: TextMedium,
@@ -1158,655 +828,297 @@ var Text2 = Object.assign(TextBase, {
1158
828
  Highlight: TextHighlight
1159
829
  });
1160
830
 
1161
- // src/primitives/Frame/Frame.utils.ts
1162
- function resolveSpacing(value, tokens) {
1163
- if (typeof value === "number") return value;
1164
- return tokens.spacing[value];
1165
- }
1166
- function resolvePadding(prop, tokens) {
1167
- if (typeof prop === "string" || typeof prop === "number") {
1168
- const px = resolveSpacing(prop, tokens);
1169
- return { top: px, right: px, bottom: px, left: px };
831
+ // src/composites/actions/Button/Button.styles.ts
832
+ function computeButtonPadding(size, hasIcon, hasText, iconPosition) {
833
+ const basePadding = {
834
+ sm: 8,
835
+ md: 12,
836
+ lg: 16
837
+ };
838
+ const base = basePadding[size];
839
+ const textExtra = 8;
840
+ if (!hasText && hasIcon) {
841
+ return {
842
+ paddingLeft: base,
843
+ paddingRight: base,
844
+ paddingTop: base,
845
+ paddingBottom: base
846
+ };
1170
847
  }
1171
- if ("x" in prop || "y" in prop) {
1172
- const axes = prop;
1173
- const x = axes.x !== void 0 ? resolveSpacing(axes.x, tokens) : 0;
1174
- const y = axes.y !== void 0 ? resolveSpacing(axes.y, tokens) : 0;
1175
- return { top: y, right: x, bottom: y, left: x };
848
+ if (hasText && !hasIcon) {
849
+ return {
850
+ paddingLeft: base + textExtra,
851
+ paddingRight: base + textExtra,
852
+ paddingTop: base,
853
+ paddingBottom: base
854
+ };
855
+ }
856
+ if (hasText && hasIcon) {
857
+ if (iconPosition === "left") {
858
+ return {
859
+ paddingLeft: base,
860
+ paddingRight: base + textExtra,
861
+ paddingTop: base,
862
+ paddingBottom: base
863
+ };
864
+ } else {
865
+ return {
866
+ paddingLeft: base + textExtra,
867
+ paddingRight: base,
868
+ paddingTop: base,
869
+ paddingBottom: base
870
+ };
871
+ }
1176
872
  }
1177
- const sides = prop;
1178
873
  return {
1179
- top: sides.top !== void 0 ? resolveSpacing(sides.top, tokens) : 0,
1180
- right: sides.right !== void 0 ? resolveSpacing(sides.right, tokens) : 0,
1181
- bottom: sides.bottom !== void 0 ? resolveSpacing(sides.bottom, tokens) : 0,
1182
- left: sides.left !== void 0 ? resolveSpacing(sides.left, tokens) : 0
874
+ paddingLeft: base,
875
+ paddingRight: base,
876
+ paddingTop: base,
877
+ paddingBottom: base
1183
878
  };
1184
879
  }
1185
- function resolveGap(prop, tokens) {
1186
- if (typeof prop === "string" || typeof prop === "number") {
1187
- const px = resolveSpacing(prop, tokens);
1188
- return { rowGap: px, columnGap: px };
880
+ function getPaletteTokens(semantic, tokens) {
881
+ switch (semantic) {
882
+ case "accent":
883
+ return tokens.accent;
884
+ case "success":
885
+ return tokens.success;
886
+ case "error":
887
+ return tokens.error;
888
+ case "warning":
889
+ return tokens.warning;
890
+ default:
891
+ return void 0;
1189
892
  }
893
+ }
894
+ function getButtonConfig(variant, semantic, size, disabled, tokens) {
895
+ const sizeConfig = getSizeConfig(size, tokens);
896
+ const variantColors = getVariantColors(variant, semantic, disabled, tokens);
1190
897
  return {
1191
- rowGap: prop.row !== void 0 ? resolveSpacing(prop.row, tokens) : 0,
1192
- columnGap: prop.column !== void 0 ? resolveSpacing(prop.column, tokens) : 0
898
+ variantColors,
899
+ sizeTokens: {
900
+ padding: sizeConfig.padding,
901
+ gap: sizeConfig.gap,
902
+ borderRadius: sizeConfig.borderRadius,
903
+ textSize: sizeConfig.textSize,
904
+ iconSize: sizeConfig.iconSize
905
+ }
1193
906
  };
1194
907
  }
1195
- function resolveRadius(value, tokens) {
1196
- if (typeof value === "number") return value;
1197
- return tokens.radius[value];
1198
- }
1199
- function resolveRadiusCorners(prop, tokens) {
1200
- if (typeof prop === "string" || typeof prop === "number") {
1201
- const px = resolveRadius(prop, tokens);
1202
- return { topLeft: px, topRight: px, bottomLeft: px, bottomRight: px };
1203
- }
1204
- return {
1205
- topLeft: prop.topLeft !== void 0 ? resolveRadius(prop.topLeft, tokens) : 0,
1206
- topRight: prop.topRight !== void 0 ? resolveRadius(prop.topRight, tokens) : 0,
1207
- bottomLeft: prop.bottomLeft !== void 0 ? resolveRadius(prop.bottomLeft, tokens) : 0,
1208
- bottomRight: prop.bottomRight !== void 0 ? resolveRadius(prop.bottomRight, tokens) : 0
908
+ function getSizeConfig(size, tokens) {
909
+ const configs = {
910
+ sm: {
911
+ padding: 8,
912
+ gap: tokens.spacing["08"],
913
+ borderRadius: 8,
914
+ textSize: "md",
915
+ // 16px
916
+ iconSize: 24
917
+ },
918
+ md: {
919
+ padding: 12,
920
+ gap: tokens.spacing["08"],
921
+ borderRadius: 12,
922
+ textSize: "md",
923
+ // 16px
924
+ iconSize: 24
925
+ },
926
+ lg: {
927
+ padding: 16,
928
+ gap: tokens.spacing["08"],
929
+ borderRadius: 16,
930
+ textSize: "md",
931
+ // 16px
932
+ iconSize: 24
933
+ }
1209
934
  };
935
+ return configs[size];
1210
936
  }
1211
- function hasPositiveRadius(corners) {
1212
- return corners.topLeft > 0 || corners.topRight > 0 || corners.bottomLeft > 0 || corners.bottomRight > 0;
937
+ function getVariantColors(variant, semantic, disabled, tokens) {
938
+ if (disabled) {
939
+ const baseColors = getVariantColorsForState(variant, semantic, tokens);
940
+ const { gamut } = tokens;
941
+ const disabledBg = tokens.backgroundSunken[gamut];
942
+ return {
943
+ ...baseColors,
944
+ bg: disabledBg,
945
+ hoveredBg: disabledBg,
946
+ pressedBg: disabledBg,
947
+ textColor: tokens.textSecondary[gamut],
948
+ iconColor: tokens.textSecondary[gamut]
949
+ };
950
+ }
951
+ return getVariantColorsForState(variant, semantic, tokens);
1213
952
  }
1214
- function resolveSizing(width, height) {
1215
- const style = {};
1216
- if (width !== void 0) {
1217
- if (width === "fill") {
1218
- style.flexGrow = 1;
1219
- style.width = "100%";
1220
- } else if (typeof width === "number") {
1221
- style.width = width;
953
+ function getVariantColorsForState(variant, semantic, tokens) {
954
+ const { gamut } = tokens;
955
+ const paletteTokens = getPaletteTokens(semantic, tokens);
956
+ if (variant === "primary") {
957
+ if (semantic === "neutral") {
958
+ return {
959
+ bg: tokens.backgroundInteractive[gamut],
960
+ hoveredBg: tokens.backgroundInteractiveHover[gamut],
961
+ pressedBg: tokens.backgroundInteractiveActive[gamut],
962
+ textColor: tokens.textPrimary[gamut],
963
+ iconColor: tokens.textPrimary[gamut],
964
+ borderWidth: 1,
965
+ borderColor: "transparent"
966
+ };
1222
967
  }
968
+ return {
969
+ bg: paletteTokens.fill[gamut],
970
+ hoveredBg: paletteTokens.fillHover[gamut],
971
+ pressedBg: paletteTokens.fillActive[gamut],
972
+ textColor: paletteTokens.onFill[gamut],
973
+ iconColor: paletteTokens.onFill[gamut],
974
+ borderWidth: 1,
975
+ borderColor: "transparent"
976
+ };
1223
977
  }
1224
- if (height !== void 0) {
1225
- if (height === "fill") {
1226
- style.flexGrow = 1;
1227
- style.height = "100%";
1228
- } else if (typeof height === "number") {
1229
- style.height = height;
978
+ if (variant === "secondary") {
979
+ if (semantic === "neutral") {
980
+ return {
981
+ bg: "transparent",
982
+ hoveredBg: tokens.backgroundInteractive[gamut],
983
+ pressedBg: tokens.backgroundInteractiveHover[gamut],
984
+ textColor: tokens.textPrimary[gamut],
985
+ iconColor: tokens.textPrimary[gamut],
986
+ borderWidth: 1,
987
+ borderColor: tokens.border[gamut]
988
+ };
1230
989
  }
1231
- }
1232
- return style;
1233
- }
1234
- var ALIGN_MAP = {
1235
- start: "flex-start",
1236
- center: "center",
1237
- end: "flex-end",
1238
- stretch: "stretch",
1239
- baseline: "baseline"
1240
- };
1241
- var JUSTIFY_MAP = {
1242
- start: "flex-start",
1243
- center: "center",
1244
- end: "flex-end",
1245
- between: "space-between",
1246
- around: "space-around",
1247
- evenly: "space-evenly"
1248
- };
1249
- function resolveAlignment(align) {
1250
- return ALIGN_MAP[align];
1251
- }
1252
- function resolveJustification(justify) {
1253
- return JUSTIFY_MAP[justify];
1254
- }
1255
- function resolveFlexDirection(direction, reverse) {
1256
- if (direction === "horizontal") {
1257
- return reverse ? "row-reverse" : "row";
1258
- }
1259
- return reverse ? "column-reverse" : "column";
1260
- }
1261
-
1262
- // src/primitives/Wrapper/Wrapper.styles.ts
1263
- function getWrapperStyles(input) {
1264
- const {
1265
- tokens,
1266
- direction = "vertical",
1267
- wrap = false,
1268
- reverse = false,
1269
- align,
1270
- justify,
1271
- padding,
1272
- gap,
1273
- width,
1274
- height,
1275
- minWidth,
1276
- maxWidth,
1277
- minHeight,
1278
- maxHeight
1279
- } = input;
1280
- const container = {};
1281
- container.flexDirection = resolveFlexDirection(direction, reverse);
1282
- if (wrap) container.flexWrap = "wrap";
1283
- if (align) container.alignItems = resolveAlignment(align);
1284
- if (justify) container.justifyContent = resolveJustification(justify);
1285
- if (padding !== void 0) {
1286
- const p = resolvePadding(padding, tokens);
1287
- container.paddingTop = p.top;
1288
- container.paddingRight = p.right;
1289
- container.paddingBottom = p.bottom;
1290
- container.paddingLeft = p.left;
1291
- }
1292
- if (gap !== void 0) {
1293
- const g = resolveGap(gap, tokens);
1294
- container.rowGap = g.rowGap;
1295
- container.columnGap = g.columnGap;
1296
- }
1297
- Object.assign(container, resolveSizing(width, height));
1298
- if (minWidth !== void 0) container.minWidth = minWidth;
1299
- if (maxWidth !== void 0) container.maxWidth = maxWidth;
1300
- if (minHeight !== void 0) container.minHeight = minHeight;
1301
- if (maxHeight !== void 0) container.maxHeight = maxHeight;
1302
- return StyleSheet.create({ c: container }).c;
1303
- }
1304
-
1305
- // src/primitives/Wrapper/Wrapper.tsx
1306
- function Wrapper({
1307
- children,
1308
- direction,
1309
- wrap,
1310
- reverse,
1311
- align,
1312
- justify,
1313
- padding,
1314
- gap,
1315
- width,
1316
- height,
1317
- minWidth,
1318
- maxWidth,
1319
- minHeight,
1320
- maxHeight,
1321
- style,
1322
- // Testing & platform
1323
- testID,
1324
- nativeID,
1325
- ref
1326
- }) {
1327
- const tokens = useTokens(1);
1328
- const containerStyle = useMemo(
1329
- () => getWrapperStyles({
1330
- tokens,
1331
- direction,
1332
- wrap,
1333
- reverse,
1334
- align,
1335
- justify,
1336
- padding,
1337
- gap,
1338
- width,
1339
- height,
1340
- minWidth,
1341
- maxWidth,
1342
- minHeight,
1343
- maxHeight
1344
- }),
1345
- [
1346
- tokens,
1347
- direction,
1348
- wrap,
1349
- reverse,
1350
- align,
1351
- justify,
1352
- padding,
1353
- gap,
1354
- width,
1355
- height,
1356
- minWidth,
1357
- maxWidth,
1358
- minHeight,
1359
- maxHeight
1360
- ]
1361
- );
1362
- const userStyles = Array.isArray(style) ? style : style ? [style] : [];
1363
- return /* @__PURE__ */ React14.createElement(
1364
- View,
1365
- {
1366
- ref,
1367
- testID,
1368
- nativeID,
1369
- accessibilityRole: "none",
1370
- style: [containerStyle, ...userStyles]
1371
- },
1372
- children
1373
- );
1374
- }
1375
-
1376
- // src/composites/actions/Button/Button.tsx
1377
- function Button({
1378
- children,
1379
- icon,
1380
- iconPosition = "left",
1381
- variant = "primary",
1382
- semantic = "neutral",
1383
- size = "md",
1384
- disabled = false,
1385
- style,
1386
- textStyle,
1387
- ...pressableProps
1388
- }) {
1389
- const tokens = useTokens();
1390
- const { variantColors, sizeTokens } = React14.useMemo(
1391
- () => getButtonConfig(variant, semantic, size, disabled, tokens),
1392
- [variant, semantic, size, disabled, tokens]
1393
- );
1394
- const padding = React14.useMemo(
1395
- () => computeButtonPadding(size, !!icon, !!children, iconPosition),
1396
- [size, icon, children, iconPosition]
1397
- );
1398
- return /* @__PURE__ */ React14.createElement(Pressable, { disabled, ...pressableProps }, ({ pressed, hovered }) => (
1399
- // Wrapper handles layout: direction, gap, alignment (padding via style)
1400
- /* @__PURE__ */ React14.createElement(
1401
- Wrapper,
1402
- {
1403
- direction: "horizontal",
1404
- align: "center",
1405
- justify: "center",
1406
- gap: sizeTokens.gap,
1407
- style: [
1408
- {
1409
- ...padding,
1410
- // Asymmetric horizontal padding for text optical balance
1411
- backgroundColor: pressed && !disabled ? variantColors.pressedBg : hovered && !disabled ? variantColors.hoveredBg : variantColors.bg,
1412
- borderRadius: sizeTokens.borderRadius,
1413
- borderWidth: variantColors.borderWidth,
1414
- // Always 1 for consistent sizing
1415
- borderColor: variantColors.borderColor || "transparent",
1416
- opacity: disabled ? 0.4 : 1
1417
- },
1418
- ...Array.isArray(style) ? style : style ? [style] : []
1419
- ]
1420
- },
1421
- icon && iconPosition === "left" && /* @__PURE__ */ React14.createElement(Icon, { name: icon, size: sizeTokens.iconSize, color: variantColors.iconColor }),
1422
- children && // Text primitive with semantic props + color style override
1423
- /* @__PURE__ */ React14.createElement(
1424
- Text2,
1425
- {
1426
- role: "label",
1427
- size: sizeTokens.textSize,
1428
- centerVertically: true,
1429
- style: [
1430
- { color: variantColors.textColor },
1431
- ...Array.isArray(textStyle) ? textStyle : textStyle ? [textStyle] : []
1432
- ]
1433
- },
1434
- children
1435
- ),
1436
- icon && iconPosition === "right" && /* @__PURE__ */ React14.createElement(Icon, { name: icon, size: sizeTokens.iconSize, color: variantColors.iconColor })
1437
- )
1438
- ));
1439
- }
1440
- function getCardStyles(tokens, disabled) {
1441
- return StyleSheet.create({
1442
- container: {
1443
- backgroundColor: srgbToHex(tokens.background.srgb),
990
+ return {
991
+ bg: paletteTokens.background[gamut],
992
+ hoveredBg: paletteTokens.backgroundInteractive[gamut],
993
+ pressedBg: paletteTokens.backgroundInteractiveHover[gamut],
994
+ textColor: paletteTokens.fill[gamut],
995
+ iconColor: paletteTokens.fill[gamut],
1444
996
  borderWidth: 1,
1445
- borderColor: srgbToHex(tokens.border.srgb),
1446
- borderRadius: tokens.radius.lg,
1447
- padding: tokens.spacing["16"],
1448
- opacity: disabled ? 0.5 : 1
1449
- }
1450
- });
1451
- }
1452
-
1453
- // src/composites/layout/Card/Card.tsx
1454
- function Card({
1455
- children,
1456
- elevation = 1,
1457
- style,
1458
- disabled = false
1459
- }) {
1460
- const tokens = useTokens(elevation);
1461
- const styles = React14.useMemo(
1462
- () => getCardStyles(tokens, disabled),
1463
- [tokens, disabled]
1464
- );
1465
- return /* @__PURE__ */ React14.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, children);
1466
- }
1467
- var hadKeyboardEvent = false;
1468
- var isListenerSetup = false;
1469
- function setupModality() {
1470
- if (isListenerSetup || typeof document === "undefined") return;
1471
- isListenerSetup = true;
1472
- const NAVIGATION_KEYS = /* @__PURE__ */ new Set([
1473
- "Tab",
1474
- "ArrowUp",
1475
- "ArrowDown",
1476
- "ArrowLeft",
1477
- "ArrowRight",
1478
- "Enter",
1479
- " ",
1480
- "Escape"
1481
- ]);
1482
- document.addEventListener("keydown", (e) => {
1483
- if (NAVIGATION_KEYS.has(e.key)) {
1484
- hadKeyboardEvent = true;
1485
- }
1486
- }, true);
1487
- document.addEventListener("pointerdown", () => {
1488
- hadKeyboardEvent = false;
1489
- }, true);
1490
- document.addEventListener("mousedown", () => {
1491
- hadKeyboardEvent = false;
1492
- }, true);
1493
- }
1494
- function useFocusVisible() {
1495
- const [isFocusVisible, setIsFocusVisible] = useState(false);
1496
- useEffect(() => {
1497
- setupModality();
1498
- }, []);
1499
- const onFocus = useCallback(() => {
1500
- if (hadKeyboardEvent) {
1501
- setIsFocusVisible(true);
1502
- }
1503
- }, []);
1504
- const onBlur = useCallback(() => {
1505
- setIsFocusVisible(false);
1506
- }, []);
1507
- const focusProps = { onFocus, onBlur };
1508
- return { isFocusVisible, focusProps };
1509
- }
1510
- function getFrameStyles(input) {
1511
- const {
1512
- tokens,
1513
- frameElevation,
1514
- layout = "flex",
1515
- direction = "vertical",
1516
- wrap = false,
1517
- reverse = false,
1518
- columns,
1519
- rows,
1520
- align,
1521
- justify,
1522
- padding,
1523
- gap,
1524
- width,
1525
- height,
1526
- minWidth,
1527
- maxWidth,
1528
- minHeight,
1529
- maxHeight,
1530
- radius,
1531
- bordered = false,
1532
- disabled = false
1533
- } = input;
1534
- const container = {};
1535
- container.backgroundColor = srgbToHex(tokens.background.srgb);
1536
- container.color = srgbToHex(tokens.textPrimary.srgb);
1537
- if (layout === "flex") {
1538
- container.display = "flex";
1539
- container.flexDirection = resolveFlexDirection(direction, reverse);
1540
- if (wrap) container.flexWrap = "wrap";
1541
- }
1542
- if (layout === "grid") {
1543
- container.display = "flex";
1544
- container.flexDirection = "row";
1545
- container.flexWrap = "wrap";
1546
- }
1547
- if (align) container.alignItems = resolveAlignment(align);
1548
- if (justify) container.justifyContent = resolveJustification(justify);
1549
- if (padding !== void 0) {
1550
- const p = resolvePadding(padding, tokens);
1551
- container.paddingTop = p.top;
1552
- container.paddingRight = p.right;
1553
- container.paddingBottom = p.bottom;
1554
- container.paddingLeft = p.left;
1555
- }
1556
- if (gap !== void 0) {
1557
- const g = resolveGap(gap, tokens);
1558
- container.rowGap = g.rowGap;
1559
- container.columnGap = g.columnGap;
997
+ borderColor: "transparent"
998
+ };
1560
999
  }
1561
- const sizing = resolveSizing(width, height);
1562
- Object.assign(container, sizing);
1563
- if (minWidth !== void 0) container.minWidth = minWidth;
1564
- if (maxWidth !== void 0) container.maxWidth = maxWidth;
1565
- if (minHeight !== void 0) container.minHeight = minHeight;
1566
- if (maxHeight !== void 0) container.maxHeight = maxHeight;
1567
- if (radius !== void 0) {
1568
- const corners = resolveRadiusCorners(radius, tokens);
1569
- container.borderTopLeftRadius = corners.topLeft;
1570
- container.borderTopRightRadius = corners.topRight;
1571
- container.borderBottomLeftRadius = corners.bottomLeft;
1572
- container.borderBottomRightRadius = corners.bottomRight;
1573
- if (hasPositiveRadius(corners)) {
1574
- container.overflow = "hidden";
1000
+ if (variant === "tertiary") {
1001
+ if (semantic === "neutral") {
1002
+ return {
1003
+ bg: "transparent",
1004
+ hoveredBg: tokens.backgroundInteractive[gamut],
1005
+ pressedBg: tokens.backgroundInteractiveHover[gamut],
1006
+ textColor: tokens.textPrimary[gamut],
1007
+ iconColor: tokens.textPrimary[gamut],
1008
+ borderWidth: 1,
1009
+ borderColor: "transparent"
1010
+ };
1575
1011
  }
1576
- }
1577
- if (bordered) {
1578
- container.borderWidth = 1;
1579
- container.borderColor = srgbToHex(tokens.border.srgb);
1580
- }
1581
- if (frameElevation === 2) {
1582
- container.shadowColor = "#000";
1583
- container.shadowOffset = { width: 0, height: 2 };
1584
- container.shadowOpacity = 0.12;
1585
- container.shadowRadius = 6;
1586
- container.elevation = 4;
1587
- }
1588
- if (disabled) {
1589
- container.opacity = 0.5;
1590
- }
1591
- const pressed = StyleSheet.create({
1592
- s: { backgroundColor: srgbToHex(tokens.backgroundSunken.srgb) }
1593
- }).s;
1594
- let gridWebStyle = null;
1595
- if (layout === "grid") {
1596
- gridWebStyle = {
1597
- display: "grid",
1598
- // Divide into equal-width columns (e.g. 3 columns → "repeat(3, 1fr)").
1599
- gridTemplateColumns: columns ? `repeat(${columns}, 1fr)` : void 0,
1600
- gridTemplateRows: rows ? `repeat(${rows}, 1fr)` : void 0
1012
+ return {
1013
+ bg: "transparent",
1014
+ hoveredBg: paletteTokens.background[gamut],
1015
+ pressedBg: paletteTokens.backgroundInteractive[gamut],
1016
+ textColor: paletteTokens.fill[gamut],
1017
+ iconColor: paletteTokens.fill[gamut],
1018
+ borderWidth: 1,
1019
+ borderColor: "transparent"
1601
1020
  };
1602
1021
  }
1603
- const insetBoxShadow = frameElevation === -2 ? "inset 0 2px 4px rgba(0,0,0,0.12)" : null;
1604
- return {
1605
- // Validate and optimize the container styles through StyleSheet.create(),
1606
- // then extract the single style object with `.c`.
1607
- container: StyleSheet.create({ c: container }).c,
1608
- pressed,
1609
- gridWebStyle,
1610
- insetBoxShadow
1611
- };
1612
- }
1613
-
1614
- // src/primitives/Frame/Frame.tsx
1615
- function wrapTextChildren(children, textStyle) {
1616
- return React14.Children.map(children, (child) => {
1617
- if (typeof child === "string" || typeof child === "number") {
1618
- return /* @__PURE__ */ React14.createElement(Text, { style: textStyle }, child);
1619
- }
1620
- return child;
1621
- });
1622
- }
1623
- function toElevationLevel(frameElevation) {
1624
- if (frameElevation <= -1) return 0;
1625
- if (frameElevation === 0) return 1;
1626
- return 2;
1022
+ return {
1023
+ bg: "transparent",
1024
+ hoveredBg: "transparent",
1025
+ pressedBg: "transparent",
1026
+ textColor: tokens.textPrimary[gamut],
1027
+ iconColor: tokens.textPrimary[gamut],
1028
+ borderWidth: 0
1029
+ };
1627
1030
  }
1628
- function Frame({
1031
+ function Button({
1629
1032
  children,
1630
- // Elevation
1631
- elevation,
1632
- // Layout
1633
- layout,
1634
- direction,
1635
- wrap,
1636
- reverse,
1637
- columns,
1638
- rows,
1639
- // Alignment
1640
- align,
1641
- justify,
1642
- // Spacing
1643
- padding,
1644
- gap,
1645
- // Sizing
1646
- width,
1647
- height,
1648
- minWidth,
1649
- maxWidth,
1650
- minHeight,
1651
- maxHeight,
1652
- // Appearance
1653
- radius,
1654
- bordered,
1655
- // Interactivity
1656
- onPress,
1657
- href,
1033
+ icon,
1034
+ iconPosition = "left",
1035
+ variant = "primary",
1036
+ semantic = "neutral",
1037
+ size = "md",
1658
1038
  disabled = false,
1659
- // Accessibility
1660
- accessibilityLabel,
1661
- accessibilityHint,
1662
- // Testing & platform
1663
- testID,
1664
- nativeID,
1665
- ref,
1666
- // Style override
1667
- style
1039
+ style,
1040
+ textStyle,
1041
+ ...pressableProps
1668
1042
  }) {
1669
- const { config, mode } = useNewtoneTheme();
1670
- const parentFrameCtx = useFrameContext();
1671
- const resolvedFrameElevation = elevation ?? 0;
1672
- const resolvedElevation = elevation !== void 0 ? toElevationLevel(elevation) : parentFrameCtx?.elevation ?? 1;
1673
- const tokens = useMemo(() => {
1674
- return computeTokens(
1675
- config.colorSystem,
1676
- mode,
1677
- resolvedElevation,
1678
- config.spacing,
1679
- config.radius,
1680
- config.typography,
1681
- config.icons,
1682
- config.tokenOverrides
1683
- );
1684
- }, [config, mode, resolvedElevation]);
1685
- const styles = useMemo(
1686
- () => getFrameStyles({
1687
- tokens,
1688
- frameElevation: resolvedFrameElevation,
1689
- layout,
1690
- direction,
1691
- wrap,
1692
- reverse,
1693
- columns,
1694
- rows,
1695
- align,
1696
- justify,
1697
- padding,
1698
- gap,
1699
- width,
1700
- height,
1701
- minWidth,
1702
- maxWidth,
1703
- minHeight,
1704
- maxHeight,
1705
- radius,
1706
- bordered,
1707
- disabled
1708
- }),
1709
- [
1710
- tokens,
1711
- resolvedFrameElevation,
1712
- layout,
1713
- direction,
1714
- wrap,
1715
- reverse,
1716
- columns,
1717
- rows,
1718
- align,
1719
- justify,
1720
- padding,
1721
- gap,
1722
- width,
1723
- height,
1724
- minWidth,
1725
- maxWidth,
1726
- minHeight,
1727
- maxHeight,
1728
- radius,
1729
- bordered,
1730
- disabled
1731
- ]
1732
- );
1733
- const contextValue = useMemo(
1734
- () => ({ elevation: resolvedElevation, tokens }),
1735
- [resolvedElevation, tokens]
1736
- );
1737
- const webOverrides = [];
1738
- if (styles.gridWebStyle) {
1739
- webOverrides.push(styles.gridWebStyle);
1740
- }
1741
- if (styles.insetBoxShadow) {
1742
- webOverrides.push({ boxShadow: styles.insetBoxShadow });
1743
- }
1744
- const userStyles = Array.isArray(style) ? style : style ? [style] : [];
1745
- const isInteractive = onPress !== void 0 || href !== void 0;
1746
- const { isFocusVisible, focusProps } = useFocusVisible();
1747
- const focusRingStyle = isFocusVisible && !disabled ? {
1748
- outlineWidth: 2,
1749
- outlineStyle: "solid",
1750
- outlineColor: srgbToHex(tokens.accent.fill.srgb),
1751
- outlineOffset: 2
1752
- } : void 0;
1753
- const webFocusProps = isInteractive ? focusProps : {};
1754
- const textStyle = useMemo(
1755
- () => ({
1756
- color: srgbToHex(tokens.textPrimary.srgb),
1757
- fontSize: tokens.typography.fontSizes["05"],
1758
- fontFamily: tokens.typography.fonts.main.family,
1759
- lineHeight: tokens.typography.lineHeights["06"]
1760
- }),
1761
- [tokens]
1043
+ const tokens = useTokens();
1044
+ const { variantColors, sizeTokens } = React13.useMemo(
1045
+ () => getButtonConfig(variant, semantic, size, disabled, tokens),
1046
+ [variant, semantic, size, disabled, tokens]
1762
1047
  );
1763
- const wrappedChildren = useMemo(
1764
- () => wrapTextChildren(children, textStyle),
1765
- [children, textStyle]
1048
+ const padding = React13.useMemo(
1049
+ () => computeButtonPadding(size, !!icon, !!children, iconPosition),
1050
+ [size, icon, children, iconPosition]
1766
1051
  );
1767
- return /* @__PURE__ */ React14.createElement(FrameContext.Provider, { value: contextValue }, isInteractive ? (
1768
- // Pressable handles taps. When href is set, react-native-web renders
1769
- // it as an <a> tag so it works like a regular link on the web.
1770
- /* @__PURE__ */ React14.createElement(
1771
- Pressable,
1052
+ return /* @__PURE__ */ React13.createElement(Pressable, { disabled, ...pressableProps }, ({ pressed, hovered }) => (
1053
+ // Wrapper handles layout: direction, gap, alignment (padding via style)
1054
+ /* @__PURE__ */ React13.createElement(
1055
+ Wrapper,
1772
1056
  {
1773
- ref,
1774
- testID,
1775
- nativeID,
1776
- accessibilityLabel,
1777
- accessibilityHint,
1778
- accessibilityState: disabled ? { disabled: true } : void 0,
1779
- onPress,
1780
- disabled,
1781
- ...href ? { href, accessibilityRole: "link" } : { accessibilityRole: "button" },
1782
- ...webFocusProps,
1783
- style: ({ pressed }) => [
1784
- styles.container,
1785
- pressed && !disabled && styles.pressed,
1786
- focusRingStyle,
1787
- ...webOverrides,
1788
- ...userStyles
1057
+ direction: "horizontal",
1058
+ align: "center",
1059
+ justify: "center",
1060
+ gap: sizeTokens.gap,
1061
+ style: [
1062
+ {
1063
+ ...padding,
1064
+ // Asymmetric horizontal padding for text optical balance
1065
+ backgroundColor: pressed && !disabled ? variantColors.pressedBg : hovered && !disabled ? variantColors.hoveredBg : variantColors.bg,
1066
+ borderRadius: sizeTokens.borderRadius,
1067
+ borderWidth: variantColors.borderWidth,
1068
+ // Always 1 for consistent sizing
1069
+ borderColor: variantColors.borderColor || "transparent",
1070
+ opacity: disabled ? 0.4 : 1
1071
+ },
1072
+ ...Array.isArray(style) ? style : style ? [style] : []
1789
1073
  ]
1790
1074
  },
1791
- wrappedChildren
1792
- )
1793
- ) : (
1794
- // Non-interactive Frame: just a plain View with no tap handling.
1795
- /* @__PURE__ */ React14.createElement(
1796
- View,
1797
- {
1798
- ref,
1799
- testID,
1800
- nativeID,
1801
- accessibilityLabel,
1802
- accessibilityHint,
1803
- style: [styles.container, ...webOverrides, ...userStyles]
1804
- },
1805
- wrappedChildren
1075
+ icon && iconPosition === "left" && /* @__PURE__ */ React13.createElement(Icon, { name: icon, size: sizeTokens.iconSize, color: variantColors.iconColor }),
1076
+ children && // Text primitive with semantic props + color style override
1077
+ /* @__PURE__ */ React13.createElement(
1078
+ Text3,
1079
+ {
1080
+ role: "label",
1081
+ size: sizeTokens.textSize,
1082
+ centerVertically: true,
1083
+ style: [
1084
+ { color: variantColors.textColor },
1085
+ ...Array.isArray(textStyle) ? textStyle : textStyle ? [textStyle] : []
1086
+ ]
1087
+ },
1088
+ children
1089
+ ),
1090
+ icon && iconPosition === "right" && /* @__PURE__ */ React13.createElement(Icon, { name: icon, size: sizeTokens.iconSize, color: variantColors.iconColor })
1806
1091
  )
1807
1092
  ));
1808
1093
  }
1809
- function getTextInputStyles(tokens, disabled) {
1094
+ function getCardStyles(tokens, gamut, disabled) {
1095
+ return StyleSheet.create({
1096
+ container: {
1097
+ backgroundColor: tokens.background[gamut],
1098
+ borderWidth: 1,
1099
+ borderColor: tokens.border[gamut],
1100
+ borderRadius: tokens.radius.lg,
1101
+ padding: tokens.spacing["16"],
1102
+ opacity: disabled ? 0.5 : 1
1103
+ }
1104
+ });
1105
+ }
1106
+
1107
+ // src/composites/layout/Card/Card.tsx
1108
+ function Card({
1109
+ children,
1110
+ elevation = 1,
1111
+ style,
1112
+ disabled = false
1113
+ }) {
1114
+ const tokens = useTokens(elevation);
1115
+ const styles = React13.useMemo(
1116
+ () => getCardStyles(tokens, tokens.gamut, disabled),
1117
+ [tokens, disabled]
1118
+ );
1119
+ return /* @__PURE__ */ React13.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, children);
1120
+ }
1121
+ function getTextInputStyles(tokens, gamut, disabled) {
1810
1122
  return StyleSheet.create({
1811
1123
  container: {
1812
1124
  gap: tokens.spacing["04"]
@@ -1815,22 +1127,24 @@ function getTextInputStyles(tokens, disabled) {
1815
1127
  fontFamily: tokens.typography.fonts.main.family,
1816
1128
  fontSize: tokens.typography.fontSizes["04"],
1817
1129
  fontWeight: tokens.typography.fonts.main.weights.medium,
1818
- color: srgbToHex(tokens.textSecondary.srgb)
1130
+ color: tokens.textSecondary[gamut]
1819
1131
  },
1820
1132
  input: {
1821
1133
  fontFamily: tokens.typography.fonts.main.family,
1822
- backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
1134
+ backgroundColor: tokens.backgroundSunken[gamut],
1823
1135
  borderWidth: 1,
1824
- borderColor: srgbToHex(tokens.border.srgb),
1136
+ borderColor: tokens.border[gamut],
1825
1137
  borderRadius: tokens.radius.md,
1826
1138
  paddingVertical: tokens.spacing["08"],
1827
1139
  paddingHorizontal: tokens.spacing["12"],
1828
1140
  fontSize: tokens.typography.fontSizes["05"],
1829
- color: disabled ? srgbToHex(tokens.textSecondary.srgb) : srgbToHex(tokens.textPrimary.srgb),
1141
+ color: disabled ? tokens.textSecondary[gamut] : tokens.textPrimary[gamut],
1830
1142
  opacity: disabled ? 0.5 : 1
1831
1143
  }
1832
1144
  });
1833
1145
  }
1146
+
1147
+ // src/composites/form-controls/TextInput/TextInput.tsx
1834
1148
  function TextInput({
1835
1149
  label,
1836
1150
  disabled = false,
@@ -1838,21 +1152,21 @@ function TextInput({
1838
1152
  ...textInputProps
1839
1153
  }) {
1840
1154
  const tokens = useTokens(1);
1841
- const styles = React14.useMemo(
1842
- () => getTextInputStyles(tokens, disabled),
1155
+ const styles = React13.useMemo(
1156
+ () => getTextInputStyles(tokens, tokens.gamut, disabled),
1843
1157
  [tokens, disabled]
1844
1158
  );
1845
- return /* @__PURE__ */ React14.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React14.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React14.createElement(
1159
+ return /* @__PURE__ */ React13.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React13.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React13.createElement(
1846
1160
  TextInput$1,
1847
1161
  {
1848
1162
  style: styles.input,
1849
1163
  editable: !disabled,
1850
- placeholderTextColor: srgbToHex(tokens.textSecondary.srgb),
1164
+ placeholderTextColor: tokens.textSecondary[tokens.gamut],
1851
1165
  ...textInputProps
1852
1166
  }
1853
1167
  ));
1854
1168
  }
1855
- function getPopoverStyles(tokens, triggerHeight, offset, maxHeight, width, isOpen) {
1169
+ function getPopoverStyles(tokens, gamut, triggerHeight, offset, maxHeight, width, isOpen) {
1856
1170
  const widthStyle = width === "trigger" ? { left: 0, right: 0 } : typeof width === "number" ? { width, left: 0 } : { left: 0 };
1857
1171
  return StyleSheet.create({
1858
1172
  container: {
@@ -1863,9 +1177,9 @@ function getPopoverStyles(tokens, triggerHeight, offset, maxHeight, width, isOpe
1863
1177
  position: "absolute",
1864
1178
  top: triggerHeight + offset,
1865
1179
  ...widthStyle,
1866
- backgroundColor: srgbToHex(tokens.backgroundElevated.srgb),
1180
+ backgroundColor: tokens.backgroundElevated[gamut],
1867
1181
  borderWidth: 1,
1868
- borderColor: srgbToHex(tokens.border.srgb),
1182
+ borderColor: tokens.border[gamut],
1869
1183
  borderRadius: tokens.radius.md,
1870
1184
  maxHeight,
1871
1185
  zIndex: 1e3,
@@ -1933,7 +1247,7 @@ function Popover({
1933
1247
  [closeOnEscape, onClose]
1934
1248
  );
1935
1249
  const styles = useMemo(
1936
- () => getPopoverStyles(tokens, triggerHeight, offset, maxHeight, width, isOpen),
1250
+ () => getPopoverStyles(tokens, tokens.gamut, triggerHeight, offset, maxHeight, width, isOpen),
1937
1251
  [tokens, triggerHeight, offset, maxHeight, width, isOpen]
1938
1252
  );
1939
1253
  const containerStyles = useMemo(
@@ -1945,15 +1259,15 @@ function Popover({
1945
1259
  [styles.content, contentStyle]
1946
1260
  );
1947
1261
  const webProps = { onKeyDown: handleKeyDown };
1948
- return /* @__PURE__ */ React14.createElement(
1262
+ return /* @__PURE__ */ React13.createElement(
1949
1263
  View,
1950
1264
  {
1951
1265
  ref: containerRef,
1952
1266
  style: containerStyles,
1953
1267
  ...webProps
1954
1268
  },
1955
- /* @__PURE__ */ React14.createElement(View, { onLayout: onTriggerLayout }, trigger),
1956
- isOpen && /* @__PURE__ */ React14.createElement(View, { style: mergedContentStyles }, children)
1269
+ /* @__PURE__ */ React13.createElement(View, { onLayout: onTriggerLayout }, trigger),
1270
+ isOpen && /* @__PURE__ */ React13.createElement(View, { style: mergedContentStyles }, children)
1957
1271
  );
1958
1272
  }
1959
1273
  function usePopover(options) {
@@ -1980,7 +1294,7 @@ function usePopover(options) {
1980
1294
  function isOptionGroup(item) {
1981
1295
  return "options" in item;
1982
1296
  }
1983
- function getSelectStyles(tokens, disabled, size, isOpen) {
1297
+ function getSelectStyles(tokens, gamut, disabled, size, isOpen) {
1984
1298
  const isSm = size === "sm";
1985
1299
  const fontSize = isSm ? tokens.typography.fontSizes["04"] : tokens.typography.fontSizes["05"];
1986
1300
  const iconSize = fontSize + 2;
@@ -1996,14 +1310,14 @@ function getSelectStyles(tokens, disabled, size, isOpen) {
1996
1310
  fontFamily: tokens.typography.fonts.main.family,
1997
1311
  fontSize: tokens.typography.fontSizes["04"],
1998
1312
  fontWeight: tokens.typography.fonts.main.weights.medium,
1999
- color: srgbToHex(tokens.textSecondary.srgb)
1313
+ color: tokens.textSecondary[gamut]
2000
1314
  },
2001
1315
  trigger: {
2002
1316
  flexDirection: "row",
2003
1317
  alignItems: "center",
2004
- backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
1318
+ backgroundColor: tokens.backgroundSunken[gamut],
2005
1319
  borderWidth: 1,
2006
- borderColor: srgbToHex(tokens.border.srgb),
1320
+ borderColor: tokens.border[gamut],
2007
1321
  borderRadius: tokens.radius.md,
2008
1322
  paddingVertical,
2009
1323
  paddingLeft: paddingHorizontal,
@@ -2014,7 +1328,7 @@ function getSelectStyles(tokens, disabled, size, isOpen) {
2014
1328
  flex: 1,
2015
1329
  fontFamily: tokens.typography.fonts.main.family,
2016
1330
  fontSize,
2017
- color: disabled ? srgbToHex(tokens.textSecondary.srgb) : srgbToHex(tokens.textPrimary.srgb)
1331
+ color: disabled ? tokens.textSecondary[gamut] : tokens.textPrimary[gamut]
2018
1332
  },
2019
1333
  iconWrapper: {
2020
1334
  position: "absolute",
@@ -2027,7 +1341,7 @@ function getSelectStyles(tokens, disabled, size, isOpen) {
2027
1341
  fontFamily: tokens.typography.fonts.main.family,
2028
1342
  fontSize: tokens.typography.fontSizes["01"],
2029
1343
  fontWeight: tokens.typography.fonts.main.weights.medium,
2030
- color: srgbToHex(tokens.textSecondary.srgb),
1344
+ color: tokens.textSecondary[gamut],
2031
1345
  textTransform: "uppercase",
2032
1346
  letterSpacing: 0.5,
2033
1347
  paddingVertical: tokens.spacing["04"],
@@ -2150,7 +1464,7 @@ function SelectOptionRow({
2150
1464
  const paddingHorizontal = size === "sm" ? tokens.spacing["08"] : tokens.spacing["12"];
2151
1465
  const fontSize = size === "sm" ? tokens.typography.fontSizes["04"] : tokens.typography.fontSizes["05"];
2152
1466
  if (renderOption) {
2153
- return /* @__PURE__ */ React14.createElement(
1467
+ return /* @__PURE__ */ React13.createElement(
2154
1468
  Pressable,
2155
1469
  {
2156
1470
  onPress: option.disabled ? void 0 : onSelect,
@@ -2161,7 +1475,7 @@ function SelectOptionRow({
2161
1475
  renderOption(option, { isSelected, isFocused })
2162
1476
  );
2163
1477
  }
2164
- return /* @__PURE__ */ React14.createElement(
1478
+ return /* @__PURE__ */ React13.createElement(
2165
1479
  Pressable,
2166
1480
  {
2167
1481
  onPress: option.disabled ? void 0 : onSelect,
@@ -2177,10 +1491,10 @@ function SelectOptionRow({
2177
1491
  paddingHorizontal
2178
1492
  },
2179
1493
  isSelected && {
2180
- backgroundColor: srgbToHex(tokens.backgroundSunken.srgb)
1494
+ backgroundColor: tokens.backgroundSunken[tokens.gamut]
2181
1495
  },
2182
1496
  isFocused && !isSelected && {
2183
- backgroundColor: `${srgbToHex(tokens.border.srgb)}20`
1497
+ backgroundColor: `${tokens.border[tokens.gamut]}20`
2184
1498
  },
2185
1499
  option.disabled && {
2186
1500
  opacity: 0.5
@@ -2190,7 +1504,7 @@ function SelectOptionRow({
2190
1504
  }
2191
1505
  ]
2192
1506
  },
2193
- /* @__PURE__ */ React14.createElement(
1507
+ /* @__PURE__ */ React13.createElement(
2194
1508
  Text,
2195
1509
  {
2196
1510
  style: [
@@ -2198,30 +1512,32 @@ function SelectOptionRow({
2198
1512
  flex: 1,
2199
1513
  fontFamily: tokens.typography.fonts.main.family,
2200
1514
  fontSize,
2201
- color: srgbToHex(tokens.textPrimary.srgb)
1515
+ color: tokens.textPrimary[tokens.gamut]
2202
1516
  },
2203
1517
  isSelected && {
2204
1518
  fontWeight: tokens.typography.fonts.main.weights.medium,
2205
- color: srgbToHex(tokens.accent.fill.srgb)
1519
+ color: tokens.accent.fill[tokens.gamut]
2206
1520
  },
2207
1521
  option.disabled && {
2208
- color: srgbToHex(tokens.textSecondary.srgb)
1522
+ color: tokens.textSecondary[tokens.gamut]
2209
1523
  }
2210
1524
  ],
2211
1525
  numberOfLines: 1
2212
1526
  },
2213
1527
  option.label
2214
1528
  ),
2215
- isSelected && /* @__PURE__ */ React14.createElement(View, { style: { marginLeft: tokens.spacing["08"] } }, /* @__PURE__ */ React14.createElement(
1529
+ isSelected && /* @__PURE__ */ React13.createElement(View, { style: { marginLeft: tokens.spacing["08"] } }, /* @__PURE__ */ React13.createElement(
2216
1530
  Icon,
2217
1531
  {
2218
1532
  name: "check",
2219
1533
  size: fontSize,
2220
- color: srgbToHex(tokens.accent.fill.srgb)
1534
+ color: tokens.accent.fill[tokens.gamut]
2221
1535
  }
2222
1536
  ))
2223
1537
  );
2224
1538
  }
1539
+
1540
+ // src/composites/form-controls/Select/Select.tsx
2225
1541
  function flattenOptions(items) {
2226
1542
  const result = [];
2227
1543
  for (const item of items) {
@@ -2260,14 +1576,14 @@ function Select({
2260
1576
  onOpen: open
2261
1577
  });
2262
1578
  const styles = useMemo(
2263
- () => getSelectStyles(tokens, disabled, size, isOpen),
1579
+ () => getSelectStyles(tokens, tokens.gamut, disabled, size, isOpen),
2264
1580
  [tokens, disabled, size, isOpen]
2265
1581
  );
2266
1582
  const selectedOption = flatOptions.find((o) => o.value === value);
2267
1583
  const displayLabel = selectedOption?.label ?? placeholder ?? value;
2268
- const iconColor = disabled ? srgbToHex(tokens.textSecondary.srgb) : srgbToHex(tokens.textPrimary.srgb);
1584
+ const iconColor = disabled ? tokens.textSecondary[tokens.gamut] : tokens.textPrimary[tokens.gamut];
2269
1585
  const triggerWebProps = { onKeyDown: handleKeyDown };
2270
- const trigger = /* @__PURE__ */ React14.createElement(
1586
+ const trigger = /* @__PURE__ */ React13.createElement(
2271
1587
  Pressable,
2272
1588
  {
2273
1589
  onPress: disabled ? void 0 : toggle,
@@ -2277,8 +1593,8 @@ function Select({
2277
1593
  ...triggerWebProps,
2278
1594
  style: styles.trigger
2279
1595
  },
2280
- renderValue ? renderValue(selectedOption) : /* @__PURE__ */ React14.createElement(Text, { style: styles.triggerText, numberOfLines: 1 }, displayLabel),
2281
- /* @__PURE__ */ React14.createElement(View, { style: styles.iconWrapper, pointerEvents: "none" }, /* @__PURE__ */ React14.createElement(
1596
+ renderValue ? renderValue(selectedOption) : /* @__PURE__ */ React13.createElement(Text, { style: styles.triggerText, numberOfLines: 1 }, displayLabel),
1597
+ /* @__PURE__ */ React13.createElement(View, { style: styles.iconWrapper, pointerEvents: "none" }, /* @__PURE__ */ React13.createElement(
2282
1598
  Icon,
2283
1599
  {
2284
1600
  name: isOpen ? "expand_less" : "expand_more",
@@ -2287,14 +1603,14 @@ function Select({
2287
1603
  }
2288
1604
  ))
2289
1605
  );
2290
- return /* @__PURE__ */ React14.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : style ? [style] : []] }, label && /* @__PURE__ */ React14.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React14.createElement(
1606
+ return /* @__PURE__ */ React13.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : style ? [style] : []] }, label && /* @__PURE__ */ React13.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React13.createElement(
2291
1607
  Popover,
2292
1608
  {
2293
1609
  isOpen: isOpen && !disabled,
2294
1610
  onClose: close,
2295
1611
  trigger
2296
1612
  },
2297
- /* @__PURE__ */ React14.createElement(
1613
+ /* @__PURE__ */ React13.createElement(
2298
1614
  ScrollView,
2299
1615
  {
2300
1616
  bounces: false,
@@ -2303,7 +1619,7 @@ function Select({
2303
1619
  },
2304
1620
  options.map((item) => {
2305
1621
  if (isOptionGroup(item)) {
2306
- return /* @__PURE__ */ React14.createElement(View, { key: item.label }, /* @__PURE__ */ React14.createElement(Text, { style: styles.groupLabel }, item.label), item.options.map((opt) => /* @__PURE__ */ React14.createElement(
1622
+ return /* @__PURE__ */ React13.createElement(View, { key: item.label }, /* @__PURE__ */ React13.createElement(Text, { style: styles.groupLabel }, item.label), item.options.map((opt) => /* @__PURE__ */ React13.createElement(
2307
1623
  SelectOptionRow,
2308
1624
  {
2309
1625
  key: opt.value,
@@ -2319,7 +1635,7 @@ function Select({
2319
1635
  }
2320
1636
  )));
2321
1637
  }
2322
- return /* @__PURE__ */ React14.createElement(
1638
+ return /* @__PURE__ */ React13.createElement(
2323
1639
  SelectOptionRow,
2324
1640
  {
2325
1641
  key: item.value,
@@ -2342,7 +1658,7 @@ var TRACK_WIDTH = 40;
2342
1658
  var TRACK_HEIGHT = 22;
2343
1659
  var THUMB_SIZE = 18;
2344
1660
  var THUMB_OFFSET = 2;
2345
- function getToggleStyles(tokens, value, disabled) {
1661
+ function getToggleStyles(tokens, gamut, value, disabled) {
2346
1662
  return StyleSheet.create({
2347
1663
  container: {
2348
1664
  flexDirection: "row",
@@ -2354,13 +1670,13 @@ function getToggleStyles(tokens, value, disabled) {
2354
1670
  fontFamily: tokens.typography.fonts.main.family,
2355
1671
  fontSize: tokens.typography.fontSizes["04"],
2356
1672
  fontWeight: tokens.typography.fonts.main.weights.medium,
2357
- color: srgbToHex(tokens.textSecondary.srgb)
1673
+ color: tokens.textSecondary[gamut]
2358
1674
  },
2359
1675
  track: {
2360
1676
  width: TRACK_WIDTH,
2361
1677
  height: TRACK_HEIGHT,
2362
1678
  borderRadius: TRACK_HEIGHT / 2,
2363
- backgroundColor: value ? srgbToHex(tokens.accent.fill.srgb) : srgbToHex(tokens.border.srgb),
1679
+ backgroundColor: value ? tokens.accent.fill[gamut] : tokens.border[gamut],
2364
1680
  justifyContent: "center",
2365
1681
  paddingHorizontal: THUMB_OFFSET
2366
1682
  },
@@ -2368,7 +1684,7 @@ function getToggleStyles(tokens, value, disabled) {
2368
1684
  width: THUMB_SIZE,
2369
1685
  height: THUMB_SIZE,
2370
1686
  borderRadius: THUMB_SIZE / 2,
2371
- backgroundColor: srgbToHex(tokens.background.srgb),
1687
+ backgroundColor: tokens.background[gamut],
2372
1688
  alignSelf: value ? "flex-end" : "flex-start"
2373
1689
  }
2374
1690
  });
@@ -2383,16 +1699,16 @@ function Toggle({
2383
1699
  style
2384
1700
  }) {
2385
1701
  const tokens = useTokens(1);
2386
- const styles = React14.useMemo(
2387
- () => getToggleStyles(tokens, value, disabled),
1702
+ const styles = React13.useMemo(
1703
+ () => getToggleStyles(tokens, tokens.gamut, value, disabled),
2388
1704
  [tokens, value, disabled]
2389
1705
  );
2390
- const handlePress = React14.useCallback(() => {
1706
+ const handlePress = React13.useCallback(() => {
2391
1707
  if (!disabled) {
2392
1708
  onValueChange(!value);
2393
1709
  }
2394
1710
  }, [disabled, value, onValueChange]);
2395
- return /* @__PURE__ */ React14.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React14.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React14.createElement(
1711
+ return /* @__PURE__ */ React13.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React13.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React13.createElement(
2396
1712
  Pressable,
2397
1713
  {
2398
1714
  onPress: handlePress,
@@ -2400,12 +1716,12 @@ function Toggle({
2400
1716
  accessibilityRole: "switch",
2401
1717
  accessibilityState: { checked: value, disabled }
2402
1718
  },
2403
- /* @__PURE__ */ React14.createElement(View, { style: styles.track }, /* @__PURE__ */ React14.createElement(View, { style: styles.thumb }))
1719
+ /* @__PURE__ */ React13.createElement(View, { style: styles.track }, /* @__PURE__ */ React13.createElement(View, { style: styles.thumb }))
2404
1720
  ));
2405
1721
  }
2406
1722
  var TRACK_HEIGHT2 = 6;
2407
1723
  var THUMB_SIZE2 = 16;
2408
- function getSliderStyles(tokens, disabled) {
1724
+ function getSliderStyles(tokens, gamut, disabled) {
2409
1725
  return StyleSheet.create({
2410
1726
  container: {
2411
1727
  gap: tokens.spacing["04"],
@@ -2420,23 +1736,23 @@ function getSliderStyles(tokens, disabled) {
2420
1736
  fontFamily: tokens.typography.fonts.main.family,
2421
1737
  fontSize: tokens.typography.fontSizes["04"],
2422
1738
  fontWeight: tokens.typography.fonts.main.weights.medium,
2423
- color: srgbToHex(tokens.textSecondary.srgb)
1739
+ color: tokens.textSecondary[gamut]
2424
1740
  },
2425
1741
  value: {
2426
1742
  fontFamily: tokens.typography.fonts.main.family,
2427
1743
  fontSize: tokens.typography.fontSizes["04"],
2428
1744
  fontWeight: tokens.typography.fonts.main.weights.medium,
2429
- color: srgbToHex(tokens.textPrimary.srgb)
1745
+ color: tokens.textPrimary[gamut]
2430
1746
  },
2431
1747
  valueInput: {
2432
1748
  width: 48,
2433
1749
  paddingVertical: 0,
2434
1750
  paddingHorizontal: 4,
2435
1751
  borderWidth: 1,
2436
- borderColor: srgbToHex(tokens.border.srgb),
1752
+ borderColor: tokens.border[gamut],
2437
1753
  borderRadius: 4,
2438
1754
  backgroundColor: "transparent",
2439
- color: srgbToHex(tokens.textPrimary.srgb),
1755
+ color: tokens.textPrimary[gamut],
2440
1756
  fontFamily: tokens.typography.fonts.main.family,
2441
1757
  fontSize: tokens.typography.fontSizes["04"],
2442
1758
  fontWeight: tokens.typography.fonts.main.weights.medium,
@@ -2453,21 +1769,21 @@ function getSliderStyles(tokens, disabled) {
2453
1769
  right: 0,
2454
1770
  height: TRACK_HEIGHT2,
2455
1771
  borderRadius: TRACK_HEIGHT2 / 2,
2456
- backgroundColor: srgbToHex(tokens.border.srgb)
1772
+ backgroundColor: tokens.border[gamut]
2457
1773
  },
2458
1774
  trackFill: {
2459
1775
  position: "absolute",
2460
1776
  left: 0,
2461
1777
  height: TRACK_HEIGHT2,
2462
1778
  borderRadius: TRACK_HEIGHT2 / 2,
2463
- backgroundColor: srgbToHex(tokens.accent.fill.srgb)
1779
+ backgroundColor: tokens.accent.fill[gamut]
2464
1780
  },
2465
1781
  thumb: {
2466
1782
  position: "absolute",
2467
1783
  width: THUMB_SIZE2,
2468
1784
  height: THUMB_SIZE2,
2469
1785
  borderRadius: THUMB_SIZE2 / 2,
2470
- backgroundColor: srgbToHex(tokens.accent.fill.srgb)
1786
+ backgroundColor: tokens.accent.fill[gamut]
2471
1787
  }
2472
1788
  });
2473
1789
  }
@@ -2486,42 +1802,42 @@ function Slider({
2486
1802
  style
2487
1803
  }) {
2488
1804
  const tokens = useTokens(1);
2489
- const styles = React14.useMemo(
2490
- () => getSliderStyles(tokens, disabled),
1805
+ const styles = React13.useMemo(
1806
+ () => getSliderStyles(tokens, tokens.gamut, disabled),
2491
1807
  [tokens, disabled]
2492
1808
  );
2493
- const trackRef = React14.useRef(null);
2494
- const trackWidth = React14.useRef(0);
2495
- const trackPageX = React14.useRef(0);
2496
- const [layoutWidth, setLayoutWidth] = React14.useState(0);
2497
- const onValueChangeRef = React14.useRef(onValueChange);
2498
- const minRef = React14.useRef(min);
2499
- const maxRef = React14.useRef(max);
2500
- const stepRef = React14.useRef(step);
2501
- const disabledRef = React14.useRef(disabled);
2502
- React14.useEffect(() => {
1809
+ const trackRef = React13.useRef(null);
1810
+ const trackWidth = React13.useRef(0);
1811
+ const trackPageX = React13.useRef(0);
1812
+ const [layoutWidth, setLayoutWidth] = React13.useState(0);
1813
+ const onValueChangeRef = React13.useRef(onValueChange);
1814
+ const minRef = React13.useRef(min);
1815
+ const maxRef = React13.useRef(max);
1816
+ const stepRef = React13.useRef(step);
1817
+ const disabledRef = React13.useRef(disabled);
1818
+ React13.useEffect(() => {
2503
1819
  onValueChangeRef.current = onValueChange;
2504
1820
  }, [onValueChange]);
2505
- React14.useEffect(() => {
1821
+ React13.useEffect(() => {
2506
1822
  minRef.current = min;
2507
1823
  }, [min]);
2508
- React14.useEffect(() => {
1824
+ React13.useEffect(() => {
2509
1825
  maxRef.current = max;
2510
1826
  }, [max]);
2511
- React14.useEffect(() => {
1827
+ React13.useEffect(() => {
2512
1828
  stepRef.current = step;
2513
1829
  }, [step]);
2514
- React14.useEffect(() => {
1830
+ React13.useEffect(() => {
2515
1831
  disabledRef.current = disabled;
2516
1832
  }, [disabled]);
2517
- const computeValue = React14.useCallback((pageX) => {
1833
+ const computeValue = React13.useCallback((pageX) => {
2518
1834
  const localX = pageX - trackPageX.current;
2519
1835
  const ratio2 = Math.min(1, Math.max(0, localX / trackWidth.current));
2520
1836
  const raw = minRef.current + ratio2 * (maxRef.current - minRef.current);
2521
1837
  const stepped = Math.round(raw / stepRef.current) * stepRef.current;
2522
1838
  return Math.min(maxRef.current, Math.max(minRef.current, stepped));
2523
1839
  }, []);
2524
- const panResponder = React14.useRef(
1840
+ const panResponder = React13.useRef(
2525
1841
  PanResponder.create({
2526
1842
  onStartShouldSetPanResponder: () => !disabledRef.current,
2527
1843
  onMoveShouldSetPanResponder: () => !disabledRef.current,
@@ -2536,8 +1852,20 @@ function Slider({
2536
1852
  const ratio = max > min ? (value - min) / (max - min) : 0;
2537
1853
  const usableWidth = Math.max(0, layoutWidth - THUMB_SIZE2);
2538
1854
  const thumbLeft = ratio * usableWidth;
2539
- const fillWidth = thumbLeft + THUMB_SIZE2 / 2;
2540
- const handleValueTextSubmit = React14.useCallback(
1855
+ const isCenterOrigin = min < 0 && max > 0;
1856
+ let fillLeft;
1857
+ let fillWidth;
1858
+ if (isCenterOrigin) {
1859
+ const centerRatio = (0 - min) / (max - min);
1860
+ const centerX = centerRatio * usableWidth + THUMB_SIZE2 / 2;
1861
+ const thumbCenterX = thumbLeft + THUMB_SIZE2 / 2;
1862
+ fillLeft = Math.min(centerX, thumbCenterX);
1863
+ fillWidth = Math.abs(thumbCenterX - centerX);
1864
+ } else {
1865
+ fillLeft = 0;
1866
+ fillWidth = thumbLeft + THUMB_SIZE2 / 2;
1867
+ }
1868
+ const handleValueTextSubmit = React13.useCallback(
2541
1869
  (text) => {
2542
1870
  const raw = Number(text);
2543
1871
  if (!Number.isNaN(raw)) {
@@ -2546,12 +1874,12 @@ function Slider({
2546
1874
  },
2547
1875
  [onValueChange, min, max]
2548
1876
  );
2549
- const [editText, setEditText] = React14.useState(String(value));
2550
- React14.useEffect(() => {
1877
+ const [editText, setEditText] = React13.useState(String(value));
1878
+ React13.useEffect(() => {
2551
1879
  setEditText(String(value));
2552
1880
  }, [value]);
2553
1881
  const showLabel = label || showValue || editableValue;
2554
- return /* @__PURE__ */ React14.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, showLabel && /* @__PURE__ */ React14.createElement(View, { style: styles.labelRow }, label && /* @__PURE__ */ React14.createElement(Text, { style: styles.label }, label), editableValue ? /* @__PURE__ */ React14.createElement(
1882
+ return /* @__PURE__ */ React13.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, showLabel && /* @__PURE__ */ React13.createElement(View, { style: styles.labelRow }, label && /* @__PURE__ */ React13.createElement(Text, { style: styles.label }, label), editableValue ? /* @__PURE__ */ React13.createElement(
2555
1883
  TextInput$1,
2556
1884
  {
2557
1885
  style: styles.valueInput,
@@ -2563,7 +1891,7 @@ function Slider({
2563
1891
  selectTextOnFocus: true,
2564
1892
  editable: !disabled
2565
1893
  }
2566
- ) : showValue && /* @__PURE__ */ React14.createElement(Text, { style: styles.value }, value)), /* @__PURE__ */ React14.createElement(
1894
+ ) : showValue && /* @__PURE__ */ React13.createElement(Text, { style: styles.value }, value)), /* @__PURE__ */ React13.createElement(
2567
1895
  View,
2568
1896
  {
2569
1897
  ref: trackRef,
@@ -2578,45 +1906,19 @@ function Slider({
2578
1906
  },
2579
1907
  ...panResponder.panHandlers
2580
1908
  },
2581
- /* @__PURE__ */ React14.createElement(View, { style: styles.trackRail }),
2582
- /* @__PURE__ */ React14.createElement(View, { style: [styles.trackFill, { width: fillWidth }] }),
2583
- /* @__PURE__ */ React14.createElement(View, { style: [styles.thumb, { left: thumbLeft }] })
1909
+ /* @__PURE__ */ React13.createElement(View, { style: styles.trackRail }),
1910
+ /* @__PURE__ */ React13.createElement(View, { style: [styles.trackFill, { left: fillLeft, width: fillWidth }] }),
1911
+ /* @__PURE__ */ React13.createElement(View, { style: [styles.thumb, { left: thumbLeft }] })
2584
1912
  ));
2585
1913
  }
2586
1914
  var TRACK_HEIGHT3 = 22;
2587
1915
  var THUMB_SIZE3 = 18;
2588
1916
  var SEGMENT_COUNT = 48;
2589
- function hueToHex(hue) {
2590
- const h = (hue % 360 + 360) % 360;
2591
- const x = 1 - Math.abs(h / 60 % 2 - 1);
2592
- let r, g, b;
2593
- if (h < 60) {
2594
- r = 1;
2595
- g = x;
2596
- b = 0;
2597
- } else if (h < 120) {
2598
- r = x;
2599
- g = 1;
2600
- b = 0;
2601
- } else if (h < 180) {
2602
- r = 0;
2603
- g = 1;
2604
- b = x;
2605
- } else if (h < 240) {
2606
- r = 0;
2607
- g = x;
2608
- b = 1;
2609
- } else if (h < 300) {
2610
- r = x;
2611
- g = 0;
2612
- b = 1;
2613
- } else {
2614
- r = 1;
2615
- g = 0;
2616
- b = x;
2617
- }
2618
- const toHex = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
2619
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
1917
+ var OKLCH_L = 0.7;
1918
+ var OKLCH_C = 0.4;
1919
+ function hueToHex(oklchHue) {
1920
+ const { color } = gamutMapToSrgb({ L: OKLCH_L, C: OKLCH_C, h: oklchHue });
1921
+ return srgbToHex(color);
2620
1922
  }
2621
1923
  function buildHueSegments(min, max) {
2622
1924
  return Array.from({ length: SEGMENT_COUNT }, (_, i) => {
@@ -2624,7 +1926,7 @@ function buildHueSegments(min, max) {
2624
1926
  return hueToHex(hue);
2625
1927
  });
2626
1928
  }
2627
- function getHueSliderStyles(tokens, disabled) {
1929
+ function getHueSliderStyles(tokens, gamut, disabled) {
2628
1930
  return StyleSheet.create({
2629
1931
  container: {
2630
1932
  gap: tokens.spacing["04"],
@@ -2639,23 +1941,23 @@ function getHueSliderStyles(tokens, disabled) {
2639
1941
  fontFamily: tokens.typography.fonts.main.family,
2640
1942
  fontSize: tokens.typography.fontSizes["04"],
2641
1943
  fontWeight: tokens.typography.fonts.main.weights.medium,
2642
- color: srgbToHex(tokens.textSecondary.srgb)
1944
+ color: tokens.textSecondary[gamut]
2643
1945
  },
2644
1946
  value: {
2645
1947
  fontFamily: tokens.typography.fonts.main.family,
2646
1948
  fontSize: tokens.typography.fontSizes["04"],
2647
1949
  fontWeight: tokens.typography.fonts.main.weights.medium,
2648
- color: srgbToHex(tokens.textPrimary.srgb)
1950
+ color: tokens.textPrimary[gamut]
2649
1951
  },
2650
1952
  valueInput: {
2651
1953
  width: 48,
2652
1954
  paddingVertical: 0,
2653
1955
  paddingHorizontal: 4,
2654
1956
  borderWidth: 1,
2655
- borderColor: srgbToHex(tokens.border.srgb),
1957
+ borderColor: tokens.border[gamut],
2656
1958
  borderRadius: 4,
2657
1959
  backgroundColor: "transparent",
2658
- color: srgbToHex(tokens.textPrimary.srgb),
1960
+ color: tokens.textPrimary[gamut],
2659
1961
  fontFamily: tokens.typography.fonts.main.family,
2660
1962
  fontSize: tokens.typography.fontSizes["04"],
2661
1963
  fontWeight: tokens.typography.fonts.main.weights.medium,
@@ -2685,7 +1987,7 @@ function getHueSliderStyles(tokens, disabled) {
2685
1987
  borderRadius: THUMB_SIZE3 / 2,
2686
1988
  backgroundColor: "#ffffff",
2687
1989
  borderWidth: 2,
2688
- borderColor: srgbToHex(tokens.border.srgb)
1990
+ borderColor: tokens.border[gamut]
2689
1991
  }
2690
1992
  });
2691
1993
  }
@@ -2695,7 +1997,7 @@ function HueSlider({
2695
1997
  value,
2696
1998
  onValueChange,
2697
1999
  min = 0,
2698
- max = 359,
2000
+ max = 360,
2699
2001
  label,
2700
2002
  showValue = false,
2701
2003
  editableValue = false,
@@ -2703,42 +2005,42 @@ function HueSlider({
2703
2005
  style
2704
2006
  }) {
2705
2007
  const tokens = useTokens(1);
2706
- const styles = React14.useMemo(
2707
- () => getHueSliderStyles(tokens, disabled),
2008
+ const styles = React13.useMemo(
2009
+ () => getHueSliderStyles(tokens, tokens.gamut, disabled),
2708
2010
  [tokens, disabled]
2709
2011
  );
2710
- const segments = React14.useMemo(
2012
+ const segments = React13.useMemo(
2711
2013
  () => buildHueSegments(min, max),
2712
2014
  [min, max]
2713
2015
  );
2714
- const trackRef = React14.useRef(null);
2715
- const trackWidth = React14.useRef(0);
2716
- const trackPageX = React14.useRef(0);
2717
- const [layoutWidth, setLayoutWidth] = React14.useState(0);
2718
- const onValueChangeRef = React14.useRef(onValueChange);
2719
- const minRef = React14.useRef(min);
2720
- const maxRef = React14.useRef(max);
2721
- const disabledRef = React14.useRef(disabled);
2722
- React14.useEffect(() => {
2016
+ const trackRef = React13.useRef(null);
2017
+ const trackWidth = React13.useRef(0);
2018
+ const trackPageX = React13.useRef(0);
2019
+ const [layoutWidth, setLayoutWidth] = React13.useState(0);
2020
+ const onValueChangeRef = React13.useRef(onValueChange);
2021
+ const minRef = React13.useRef(min);
2022
+ const maxRef = React13.useRef(max);
2023
+ const disabledRef = React13.useRef(disabled);
2024
+ React13.useEffect(() => {
2723
2025
  onValueChangeRef.current = onValueChange;
2724
2026
  }, [onValueChange]);
2725
- React14.useEffect(() => {
2027
+ React13.useEffect(() => {
2726
2028
  minRef.current = min;
2727
2029
  }, [min]);
2728
- React14.useEffect(() => {
2030
+ React13.useEffect(() => {
2729
2031
  maxRef.current = max;
2730
2032
  }, [max]);
2731
- React14.useEffect(() => {
2033
+ React13.useEffect(() => {
2732
2034
  disabledRef.current = disabled;
2733
2035
  }, [disabled]);
2734
- const computeHue = React14.useCallback((pageX) => {
2036
+ const computeHue = React13.useCallback((pageX) => {
2735
2037
  const localX = pageX - trackPageX.current;
2736
2038
  const ratio2 = Math.min(1, Math.max(0, localX / trackWidth.current));
2737
2039
  const raw = minRef.current + ratio2 * (maxRef.current - minRef.current);
2738
2040
  const stepped = Math.round(raw);
2739
2041
  return (stepped % 360 + 360) % 360;
2740
2042
  }, []);
2741
- const panResponder = React14.useRef(
2043
+ const panResponder = React13.useRef(
2742
2044
  PanResponder.create({
2743
2045
  onStartShouldSetPanResponder: () => !disabledRef.current,
2744
2046
  onMoveShouldSetPanResponder: () => !disabledRef.current,
@@ -2750,11 +2052,11 @@ function HueSlider({
2750
2052
  }
2751
2053
  })
2752
2054
  ).current;
2753
- const sliderValue = max > 359 && value < min ? value + 360 : value;
2055
+ const sliderValue = max > 360 && value < min ? value + 360 : value;
2754
2056
  const ratio = max > min ? (sliderValue - min) / (max - min) : 0;
2755
2057
  const usableWidth = Math.max(0, layoutWidth - THUMB_SIZE3);
2756
2058
  const thumbLeft = ratio * usableWidth;
2757
- const handleValueTextSubmit = React14.useCallback(
2059
+ const handleValueTextSubmit = React13.useCallback(
2758
2060
  (text) => {
2759
2061
  const raw = Number(text);
2760
2062
  if (!Number.isNaN(raw)) {
@@ -2763,12 +2065,12 @@ function HueSlider({
2763
2065
  },
2764
2066
  [onValueChange]
2765
2067
  );
2766
- const [editText, setEditText] = React14.useState(String(value));
2767
- React14.useEffect(() => {
2068
+ const [editText, setEditText] = React13.useState(String(value));
2069
+ React13.useEffect(() => {
2768
2070
  setEditText(String(value));
2769
2071
  }, [value]);
2770
2072
  const showLabel = label || showValue || editableValue;
2771
- return /* @__PURE__ */ React14.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, showLabel && /* @__PURE__ */ React14.createElement(View, { style: styles.labelRow }, label && /* @__PURE__ */ React14.createElement(Text, { style: styles.label }, label), editableValue ? /* @__PURE__ */ React14.createElement(
2073
+ return /* @__PURE__ */ React13.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, showLabel && /* @__PURE__ */ React13.createElement(View, { style: styles.labelRow }, label && /* @__PURE__ */ React13.createElement(Text, { style: styles.label }, label), editableValue ? /* @__PURE__ */ React13.createElement(
2772
2074
  TextInput$1,
2773
2075
  {
2774
2076
  style: styles.valueInput,
@@ -2780,7 +2082,7 @@ function HueSlider({
2780
2082
  selectTextOnFocus: true,
2781
2083
  editable: !disabled
2782
2084
  }
2783
- ) : showValue && /* @__PURE__ */ React14.createElement(Text, { style: styles.value }, value, "\xB0")), /* @__PURE__ */ React14.createElement(
2085
+ ) : showValue && /* @__PURE__ */ React13.createElement(Text, { style: styles.value }, value, "\xB0")), /* @__PURE__ */ React13.createElement(
2784
2086
  View,
2785
2087
  {
2786
2088
  ref: trackRef,
@@ -2795,13 +2097,69 @@ function HueSlider({
2795
2097
  },
2796
2098
  ...panResponder.panHandlers
2797
2099
  },
2798
- /* @__PURE__ */ React14.createElement(View, { style: styles.gradientTrack }, segments.map((color, i) => /* @__PURE__ */ React14.createElement(View, { key: i, style: [styles.segment, { backgroundColor: color }] }))),
2799
- /* @__PURE__ */ React14.createElement(View, { style: [styles.thumb, { left: thumbLeft }] })
2100
+ /* @__PURE__ */ React13.createElement(View, { style: styles.gradientTrack }, segments.map((color, i) => /* @__PURE__ */ React13.createElement(View, { key: i, style: [styles.segment, { backgroundColor: color }] }))),
2101
+ /* @__PURE__ */ React13.createElement(View, { style: [styles.thumb, { left: thumbLeft }] })
2800
2102
  ));
2801
2103
  }
2104
+
2105
+ // node_modules/@newtonedev/colors/dist/index.js
2106
+ var SRGB_GAMMA_THRESHOLD_LINEAR = 31308e-7;
2107
+ var SRGB_GAMMA_SLOPE = 12.92;
2108
+ var SRGB_GAMMA_EXPONENT = 2.4;
2109
+ var SRGB_GAMMA_OFFSET = 0.055;
2110
+ var SRGB_GAMMA_SCALE = 1.055;
2111
+ var OKLAB_TO_LMS_PRIME = [
2112
+ [1, 0.3963377774, 0.2158037573],
2113
+ [1, -0.1055613458, -0.0638541728],
2114
+ [1, -0.0894841775, -1.291485548]
2115
+ ];
2116
+ var LMS_TO_LINEAR_P3 = [
2117
+ [3.127769439, -2.2570600176, 0.1291828502],
2118
+ [-1.0910091977, 2.4133065499, -0.3222615148],
2119
+ [-0.0260108068, -0.5080402362, 1.5340494942]
2120
+ ];
2121
+ var DEG_TO_RAD = Math.PI / 180;
2122
+ function oklchToOklab(lch) {
2123
+ const hRad = lch.h * DEG_TO_RAD;
2124
+ return {
2125
+ L: lch.L,
2126
+ a: lch.C * Math.cos(hRad),
2127
+ b: lch.C * Math.sin(hRad)
2128
+ };
2129
+ }
2130
+ function oklabToLinearP3(color) {
2131
+ const lp = OKLAB_TO_LMS_PRIME[0][0] * color.L + OKLAB_TO_LMS_PRIME[0][1] * color.a + OKLAB_TO_LMS_PRIME[0][2] * color.b;
2132
+ const mp = OKLAB_TO_LMS_PRIME[1][0] * color.L + OKLAB_TO_LMS_PRIME[1][1] * color.a + OKLAB_TO_LMS_PRIME[1][2] * color.b;
2133
+ const sp = OKLAB_TO_LMS_PRIME[2][0] * color.L + OKLAB_TO_LMS_PRIME[2][1] * color.a + OKLAB_TO_LMS_PRIME[2][2] * color.b;
2134
+ const l = lp * lp * lp;
2135
+ const m = mp * mp * mp;
2136
+ const s = sp * sp * sp;
2137
+ return {
2138
+ r: LMS_TO_LINEAR_P3[0][0] * l + LMS_TO_LINEAR_P3[0][1] * m + LMS_TO_LINEAR_P3[0][2] * s,
2139
+ g: LMS_TO_LINEAR_P3[1][0] * l + LMS_TO_LINEAR_P3[1][1] * m + LMS_TO_LINEAR_P3[1][2] * s,
2140
+ b: LMS_TO_LINEAR_P3[2][0] * l + LMS_TO_LINEAR_P3[2][1] * m + LMS_TO_LINEAR_P3[2][2] * s
2141
+ };
2142
+ }
2143
+ function linearChannelToSrgb(value) {
2144
+ return value <= SRGB_GAMMA_THRESHOLD_LINEAR ? value * SRGB_GAMMA_SLOPE : SRGB_GAMMA_SCALE * value ** (1 / SRGB_GAMMA_EXPONENT) - SRGB_GAMMA_OFFSET;
2145
+ }
2146
+ function linearSrgbToSrgb(color) {
2147
+ return {
2148
+ r: linearChannelToSrgb(color.r),
2149
+ g: linearChannelToSrgb(color.g),
2150
+ b: linearChannelToSrgb(color.b)
2151
+ };
2152
+ }
2153
+ function oklchToP3(color) {
2154
+ return linearSrgbToSrgb(oklabToLinearP3(oklchToOklab(color)));
2155
+ }
2156
+ function oklchToP3Css(color) {
2157
+ const { r, g, b } = oklchToP3(color);
2158
+ return `color(display-p3 ${r} ${g} ${b})`;
2159
+ }
2802
2160
  var TRACK_HEIGHT4 = 22;
2803
2161
  var THUMB_SIZE4 = 18;
2804
- function getColorScaleSliderStyles(tokens, disabled) {
2162
+ function getColorScaleSliderStyles(tokens, gamut, disabled) {
2805
2163
  return StyleSheet.create({
2806
2164
  container: {
2807
2165
  gap: tokens.spacing["04"],
@@ -2816,7 +2174,7 @@ function getColorScaleSliderStyles(tokens, disabled) {
2816
2174
  fontFamily: tokens.typography.fonts.main.family,
2817
2175
  fontSize: tokens.typography.fontSizes["04"],
2818
2176
  fontWeight: tokens.typography.fonts.main.weights.medium,
2819
- color: srgbToHex(tokens.textSecondary.srgb)
2177
+ color: tokens.textSecondary[gamut]
2820
2178
  },
2821
2179
  trackContainer: {
2822
2180
  height: TRACK_HEIGHT4 + THUMB_SIZE4,
@@ -2842,13 +2200,13 @@ function getColorScaleSliderStyles(tokens, disabled) {
2842
2200
  borderRadius: THUMB_SIZE4 / 2,
2843
2201
  backgroundColor: "#ffffff",
2844
2202
  borderWidth: 2,
2845
- borderColor: srgbToHex(tokens.border.srgb)
2203
+ borderColor: tokens.border[gamut]
2846
2204
  },
2847
2205
  warning: {
2848
2206
  fontFamily: tokens.typography.fonts.main.family,
2849
2207
  fontSize: tokens.typography.fontSizes["01"],
2850
2208
  fontWeight: tokens.typography.fonts.main.weights.medium,
2851
- color: srgbToHex(tokens.error.fill.srgb)
2209
+ color: tokens.error.fill[gamut]
2852
2210
  }
2853
2211
  });
2854
2212
  }
@@ -2864,40 +2222,41 @@ function ColorScaleSlider({
2864
2222
  snap = false,
2865
2223
  disabled = false,
2866
2224
  animateValue = false,
2225
+ useP3: _useP3,
2867
2226
  style
2868
2227
  }) {
2869
2228
  const tokens = useTokens(1);
2870
- const styles = React14.useMemo(
2871
- () => getColorScaleSliderStyles(tokens, disabled),
2229
+ const styles = React13.useMemo(
2230
+ () => getColorScaleSliderStyles(tokens, tokens.gamut, disabled),
2872
2231
  [tokens, disabled]
2873
2232
  );
2874
- const trackRef = React14.useRef(null);
2875
- const trackWidth = React14.useRef(0);
2876
- const trackPageX = React14.useRef(0);
2877
- const isDragging = React14.useRef(false);
2878
- const thumbAnim = React14.useRef(new Animated.Value(0)).current;
2879
- const [layoutWidth, setLayoutWidth] = React14.useState(0);
2880
- const onValueChangeRef = React14.useRef(onValueChange);
2881
- const disabledRef = React14.useRef(disabled);
2882
- const colorsLengthRef = React14.useRef(colors.length);
2883
- const trimEndsRef = React14.useRef(trimEnds);
2884
- const snapRef = React14.useRef(snap);
2885
- React14.useEffect(() => {
2233
+ const trackRef = React13.useRef(null);
2234
+ const trackWidth = React13.useRef(0);
2235
+ const trackPageX = React13.useRef(0);
2236
+ const isDragging = React13.useRef(false);
2237
+ const thumbAnim = React13.useRef(new Animated.Value(0)).current;
2238
+ const [layoutWidth, setLayoutWidth] = React13.useState(0);
2239
+ const onValueChangeRef = React13.useRef(onValueChange);
2240
+ const disabledRef = React13.useRef(disabled);
2241
+ const colorsLengthRef = React13.useRef(colors.length);
2242
+ const trimEndsRef = React13.useRef(trimEnds);
2243
+ const snapRef = React13.useRef(snap);
2244
+ React13.useEffect(() => {
2886
2245
  onValueChangeRef.current = onValueChange;
2887
2246
  }, [onValueChange]);
2888
- React14.useEffect(() => {
2247
+ React13.useEffect(() => {
2889
2248
  disabledRef.current = disabled;
2890
2249
  }, [disabled]);
2891
- React14.useEffect(() => {
2250
+ React13.useEffect(() => {
2892
2251
  colorsLengthRef.current = colors.length;
2893
2252
  }, [colors.length]);
2894
- React14.useEffect(() => {
2253
+ React13.useEffect(() => {
2895
2254
  trimEndsRef.current = trimEnds;
2896
2255
  }, [trimEnds]);
2897
- React14.useEffect(() => {
2256
+ React13.useEffect(() => {
2898
2257
  snapRef.current = snap;
2899
2258
  }, [snap]);
2900
- const computeNv = React14.useCallback((pageX) => {
2259
+ const computeNv = React13.useCallback((pageX) => {
2901
2260
  const localX = pageX - trackPageX.current;
2902
2261
  const ratio2 = Math.min(1, Math.max(0, localX / trackWidth.current));
2903
2262
  const totalSteps2 = colorsLengthRef.current - 1;
@@ -2912,7 +2271,7 @@ function ColorScaleSlider({
2912
2271
  }
2913
2272
  return nv;
2914
2273
  }, []);
2915
- const panResponder = React14.useRef(
2274
+ const panResponder = React13.useRef(
2916
2275
  PanResponder.create({
2917
2276
  onStartShouldSetPanResponder: () => !disabledRef.current,
2918
2277
  onMoveShouldSetPanResponder: () => !disabledRef.current,
@@ -2940,7 +2299,7 @@ function ColorScaleSlider({
2940
2299
  const ratio = range > 0 ? (maxNV - clampedValue) / range : 0.5;
2941
2300
  const usableWidth = Math.max(0, layoutWidth - THUMB_SIZE4);
2942
2301
  const thumbLeft = ratio * usableWidth;
2943
- React14.useEffect(() => {
2302
+ React13.useEffect(() => {
2944
2303
  if (isDragging.current || !animateValue) {
2945
2304
  thumbAnim.setValue(thumbLeft);
2946
2305
  } else {
@@ -2951,7 +2310,7 @@ function ColorScaleSlider({
2951
2310
  }).start();
2952
2311
  }
2953
2312
  }, [thumbLeft, animateValue, thumbAnim]);
2954
- return /* @__PURE__ */ React14.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React14.createElement(View, { style: styles.labelRow }, /* @__PURE__ */ React14.createElement(Text, { style: styles.label }, label)), /* @__PURE__ */ React14.createElement(
2313
+ return /* @__PURE__ */ React13.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React13.createElement(View, { style: styles.labelRow }, /* @__PURE__ */ React13.createElement(Text, { style: styles.label }, label)), /* @__PURE__ */ React13.createElement(
2955
2314
  View,
2956
2315
  {
2957
2316
  ref: trackRef,
@@ -2966,17 +2325,17 @@ function ColorScaleSlider({
2966
2325
  },
2967
2326
  ...panResponder.panHandlers
2968
2327
  },
2969
- /* @__PURE__ */ React14.createElement(View, { style: styles.gradientTrack }, visibleColors.map((color, i) => /* @__PURE__ */ React14.createElement(View, { key: i, style: [styles.segment, { backgroundColor: srgbToHex(color.srgb) }] }))),
2970
- /* @__PURE__ */ React14.createElement(Animated.View, { style: [styles.thumb, { left: thumbAnim }] })
2971
- ), warning && /* @__PURE__ */ React14.createElement(Text, { style: styles.warning }, warning));
2328
+ /* @__PURE__ */ React13.createElement(View, { style: styles.gradientTrack }, visibleColors.map((color, i) => /* @__PURE__ */ React13.createElement(View, { key: i, style: [styles.segment, { backgroundColor: tokens.gamut === "p3" ? oklchToP3Css(color.oklch) : srgbToHex(color.srgb) }] }))),
2329
+ /* @__PURE__ */ React13.createElement(Animated.View, { style: [styles.thumb, { left: thumbAnim }] })
2330
+ ), warning && /* @__PURE__ */ React13.createElement(Text, { style: styles.warning }, warning));
2972
2331
  }
2973
- function getAppShellStyles(tokens) {
2332
+ function getAppShellStyles(tokens, gamut) {
2974
2333
  return StyleSheet.create({
2975
2334
  container: {
2976
2335
  flex: 1,
2977
2336
  flexDirection: "row",
2978
2337
  overflow: "hidden",
2979
- backgroundColor: srgbToHex(tokens.background.srgb)
2338
+ backgroundColor: tokens.background[gamut]
2980
2339
  },
2981
2340
  main: {
2982
2341
  flex: 1,
@@ -2990,17 +2349,17 @@ function getAppShellStyles(tokens) {
2990
2349
  // src/composites/layout/AppShell/AppShell.tsx
2991
2350
  function AppShell({ sidebar, children }) {
2992
2351
  const tokens = useTokens();
2993
- const styles = React14.useMemo(() => getAppShellStyles(tokens), [tokens]);
2994
- return /* @__PURE__ */ React14.createElement(View, { style: styles.container }, sidebar, /* @__PURE__ */ React14.createElement(View, { style: styles.main }, children));
2352
+ const styles = React13.useMemo(() => getAppShellStyles(tokens, tokens.gamut), [tokens]);
2353
+ return /* @__PURE__ */ React13.createElement(View, { style: styles.container }, sidebar, /* @__PURE__ */ React13.createElement(View, { style: styles.main }, children));
2995
2354
  }
2996
- function getSidebarStyles({ tokens, width, bordered }) {
2997
- const borderColor = srgbToHex(tokens.border.srgb);
2355
+ function getSidebarStyles({ tokens, gamut, width, bordered }) {
2356
+ const borderColor = tokens.border[gamut];
2998
2357
  return StyleSheet.create({
2999
2358
  container: {
3000
2359
  width,
3001
2360
  flexShrink: 0,
3002
2361
  flexDirection: "column",
3003
- backgroundColor: srgbToHex(tokens.background.srgb),
2362
+ backgroundColor: tokens.background[gamut],
3004
2363
  borderRightWidth: bordered ? 1 : 0,
3005
2364
  borderRightColor: borderColor
3006
2365
  },
@@ -3029,14 +2388,14 @@ function Sidebar({
3029
2388
  bordered = true
3030
2389
  }) {
3031
2390
  const tokens = useTokens();
3032
- const styles = React14.useMemo(
3033
- () => getSidebarStyles({ tokens, width, bordered }),
2391
+ const styles = React13.useMemo(
2392
+ () => getSidebarStyles({ tokens, gamut: tokens.gamut, width, bordered }),
3034
2393
  [tokens, width, bordered]
3035
2394
  );
3036
- return /* @__PURE__ */ React14.createElement(View, { style: styles.container }, header && /* @__PURE__ */ React14.createElement(View, { style: styles.header }, header), /* @__PURE__ */ React14.createElement(ScrollView, { style: styles.body }, children), footer && /* @__PURE__ */ React14.createElement(View, { style: styles.footer }, footer));
2395
+ return /* @__PURE__ */ React13.createElement(View, { style: styles.container }, header && /* @__PURE__ */ React13.createElement(View, { style: styles.header }, header), /* @__PURE__ */ React13.createElement(ScrollView, { style: styles.body }, children), footer && /* @__PURE__ */ React13.createElement(View, { style: styles.footer }, footer));
3037
2396
  }
3038
- function getNavbarStyles({ tokens, height, bordered }) {
3039
- const borderColor = srgbToHex(tokens.border.srgb);
2397
+ function getNavbarStyles({ tokens, gamut, height, bordered }) {
2398
+ const borderColor = tokens.border[gamut];
3040
2399
  return StyleSheet.create({
3041
2400
  container: {
3042
2401
  flexDirection: "row",
@@ -3044,7 +2403,7 @@ function getNavbarStyles({ tokens, height, bordered }) {
3044
2403
  height,
3045
2404
  flexShrink: 0,
3046
2405
  paddingHorizontal: 24,
3047
- backgroundColor: srgbToHex(tokens.background.srgb),
2406
+ backgroundColor: tokens.background[gamut],
3048
2407
  borderBottomWidth: bordered ? 1 : 0,
3049
2408
  borderBottomColor: borderColor
3050
2409
  },
@@ -3071,11 +2430,11 @@ function Navbar({
3071
2430
  bordered = true
3072
2431
  }) {
3073
2432
  const tokens = useTokens();
3074
- const styles = React14.useMemo(
3075
- () => getNavbarStyles({ tokens, height, bordered }),
2433
+ const styles = React13.useMemo(
2434
+ () => getNavbarStyles({ tokens, gamut: tokens.gamut, height, bordered }),
3076
2435
  [tokens, height, bordered]
3077
2436
  );
3078
- return /* @__PURE__ */ React14.createElement(View, { style: styles.container }, children ? children : /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(View, { style: styles.left }, left), /* @__PURE__ */ React14.createElement(View, { style: styles.right }, right)));
2437
+ return /* @__PURE__ */ React13.createElement(View, { style: styles.container }, children ? children : /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(View, { style: styles.left }, left), /* @__PURE__ */ React13.createElement(View, { style: styles.right }, right)));
3079
2438
  }
3080
2439
 
3081
2440
  // src/registry/registry.ts
@@ -4023,6 +3382,6 @@ var ICON_CATALOG = [
4023
3382
  }
4024
3383
  ];
4025
3384
 
4026
- export { ACCENT_DEFAULTS, AppShell, Button, CATEGORIES, COMPONENTS, Card, ColorScaleSlider, DEFAULT_THEME_CONFIG, ERROR_DEFAULTS, Frame, HueSlider, ICON_CATALOG, Icon, NEUTRAL_DEFAULTS, Navbar, NewtoneProvider, Popover, SUCCESS_DEFAULTS, Select, Sidebar, Slider, Text2 as Text, TextInput, Toggle, WARNING_DEFAULTS, Wrapper, computeTokens, generateComponentCode, getCategory, getComponent, getComponentsByCategory, isOptionGroup, measureAvgCharWidth, useFocusVisible, useFrameContext, useLocalCalibration, useNewtoneTheme, usePopover, useTokens, useTypographyCalibrations };
3385
+ export { AppShell, Button, CATEGORIES, COMPONENTS, Card, ColorScaleSlider, Frame, HueSlider, ICON_CATALOG, Icon, Navbar, Popover, Select, Sidebar, Slider, Text3 as Text, TextInput, Toggle, Wrapper, generateComponentCode, getCategory, getComponent, getComponentsByCategory, isOptionGroup, useFocusVisible, usePopover };
4027
3386
  //# sourceMappingURL=index.js.map
4028
3387
  //# sourceMappingURL=index.js.map