@newtonedev/components 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +506 -0
  2. package/dist/Button/Button.d.ts +23 -0
  3. package/dist/Button/Button.d.ts.map +1 -0
  4. package/dist/Button/Button.styles.d.ts +39 -0
  5. package/dist/Button/Button.styles.d.ts.map +1 -0
  6. package/dist/Button/Button.types.d.ts +42 -0
  7. package/dist/Button/Button.types.d.ts.map +1 -0
  8. package/dist/Button/index.d.ts +3 -0
  9. package/dist/Button/index.d.ts.map +1 -0
  10. package/dist/Card/Card.d.ts +4 -0
  11. package/dist/Card/Card.d.ts.map +1 -0
  12. package/dist/Card/Card.styles.d.ts +12 -0
  13. package/dist/Card/Card.styles.d.ts.map +1 -0
  14. package/dist/Card/Card.types.d.ts +9 -0
  15. package/dist/Card/Card.types.d.ts.map +1 -0
  16. package/dist/Card/index.d.ts +3 -0
  17. package/dist/Card/index.d.ts.map +1 -0
  18. package/dist/HueSlider/HueSlider.d.ts +14 -0
  19. package/dist/HueSlider/HueSlider.d.ts.map +1 -0
  20. package/dist/HueSlider/HueSlider.styles.d.ts +28 -0
  21. package/dist/HueSlider/HueSlider.styles.d.ts.map +1 -0
  22. package/dist/HueSlider/HueSlider.types.d.ts +12 -0
  23. package/dist/HueSlider/HueSlider.types.d.ts.map +1 -0
  24. package/dist/HueSlider/index.d.ts +3 -0
  25. package/dist/HueSlider/index.d.ts.map +1 -0
  26. package/dist/Select/Select.d.ts +11 -0
  27. package/dist/Select/Select.d.ts.map +1 -0
  28. package/dist/Select/Select.styles.d.ts +23 -0
  29. package/dist/Select/Select.styles.d.ts.map +1 -0
  30. package/dist/Select/Select.types.d.ts +14 -0
  31. package/dist/Select/Select.types.d.ts.map +1 -0
  32. package/dist/Select/index.d.ts +3 -0
  33. package/dist/Select/index.d.ts.map +1 -0
  34. package/dist/Slider/Slider.d.ts +4 -0
  35. package/dist/Slider/Slider.d.ts.map +1 -0
  36. package/dist/Slider/Slider.styles.d.ts +27 -0
  37. package/dist/Slider/Slider.styles.d.ts.map +1 -0
  38. package/dist/Slider/Slider.types.d.ts +13 -0
  39. package/dist/Slider/Slider.types.d.ts.map +1 -0
  40. package/dist/Slider/index.d.ts +3 -0
  41. package/dist/Slider/index.d.ts.map +1 -0
  42. package/dist/TextInput/TextInput.d.ts +4 -0
  43. package/dist/TextInput/TextInput.d.ts.map +1 -0
  44. package/dist/TextInput/TextInput.styles.d.ts +23 -0
  45. package/dist/TextInput/TextInput.styles.d.ts.map +1 -0
  46. package/dist/TextInput/TextInput.types.d.ts +7 -0
  47. package/dist/TextInput/TextInput.types.d.ts.map +1 -0
  48. package/dist/TextInput/index.d.ts +3 -0
  49. package/dist/TextInput/index.d.ts.map +1 -0
  50. package/dist/Toggle/Toggle.d.ts +4 -0
  51. package/dist/Toggle/Toggle.d.ts.map +1 -0
  52. package/dist/Toggle/Toggle.styles.d.ts +30 -0
  53. package/dist/Toggle/Toggle.styles.d.ts.map +1 -0
  54. package/dist/Toggle/Toggle.types.d.ts +9 -0
  55. package/dist/Toggle/Toggle.types.d.ts.map +1 -0
  56. package/dist/Toggle/index.d.ts +3 -0
  57. package/dist/Toggle/index.d.ts.map +1 -0
  58. package/dist/index.cjs +736 -0
  59. package/dist/index.cjs.map +1 -0
  60. package/dist/index.d.ts +22 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +719 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/theme/NewtoneProvider.d.ts +33 -0
  65. package/dist/theme/NewtoneProvider.d.ts.map +1 -0
  66. package/dist/theme/defaults.d.ts +7 -0
  67. package/dist/theme/defaults.d.ts.map +1 -0
  68. package/dist/theme/types.d.ts +56 -0
  69. package/dist/theme/types.d.ts.map +1 -0
  70. package/dist/tokens/computeTokens.d.ts +30 -0
  71. package/dist/tokens/computeTokens.d.ts.map +1 -0
  72. package/dist/tokens/types.d.ts +31 -0
  73. package/dist/tokens/types.d.ts.map +1 -0
  74. package/dist/tokens/useTokens.d.ts +26 -0
  75. package/dist/tokens/useTokens.d.ts.map +1 -0
  76. package/package.json +57 -0
  77. package/src/Button/Button.styles.ts +100 -0
  78. package/src/Button/Button.tsx +67 -0
  79. package/src/Button/Button.types.ts +49 -0
  80. package/src/Button/index.ts +2 -0
  81. package/src/Card/Card.styles.ts +16 -0
  82. package/src/Card/Card.tsx +25 -0
  83. package/src/Card/Card.types.ts +9 -0
  84. package/src/Card/index.ts +2 -0
  85. package/src/HueSlider/HueSlider.styles.ts +77 -0
  86. package/src/HueSlider/HueSlider.tsx +70 -0
  87. package/src/HueSlider/HueSlider.types.ts +12 -0
  88. package/src/HueSlider/index.ts +2 -0
  89. package/src/Select/Select.styles.ts +29 -0
  90. package/src/Select/Select.tsx +60 -0
  91. package/src/Select/Select.types.ts +15 -0
  92. package/src/Select/index.ts +2 -0
  93. package/src/Slider/Slider.styles.ts +45 -0
  94. package/src/Slider/Slider.tsx +57 -0
  95. package/src/Slider/Slider.types.ts +13 -0
  96. package/src/Slider/index.ts +2 -0
  97. package/src/TextInput/TextInput.styles.ts +29 -0
  98. package/src/TextInput/TextInput.tsx +32 -0
  99. package/src/TextInput/TextInput.types.ts +7 -0
  100. package/src/TextInput/index.ts +2 -0
  101. package/src/Toggle/Toggle.styles.ts +45 -0
  102. package/src/Toggle/Toggle.tsx +42 -0
  103. package/src/Toggle/Toggle.types.ts +9 -0
  104. package/src/Toggle/index.ts +2 -0
  105. package/src/index.ts +49 -0
  106. package/src/theme/NewtoneProvider.tsx +65 -0
  107. package/src/theme/defaults.ts +42 -0
  108. package/src/theme/types.ts +62 -0
  109. package/src/tokens/computeTokens.ts +217 -0
  110. package/src/tokens/types.ts +31 -0
  111. package/src/tokens/useTokens.ts +42 -0
package/dist/index.js ADDED
@@ -0,0 +1,719 @@
1
+ import React7, { createContext, useState, useMemo, useContext } from 'react';
2
+ import { 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, getColor, getColorByContrast, srgbToHex } from 'newtone';
3
+ import { Pressable, Text, View, TextInput as TextInput$1, StyleSheet } from 'react-native';
4
+
5
+ // src/theme/NewtoneProvider.tsx
6
+ var DEFAULT_THEME_CONFIG = {
7
+ colorSystem: {
8
+ dynamicRange: {
9
+ lightest: 1,
10
+ darkest: 1
11
+ },
12
+ palettes: [
13
+ { hue: DEFAULT_NEUTRAL_HUE, saturation: DEFAULT_NEUTRAL_SATURATION },
14
+ { hue: DEFAULT_ACCENT_HUE, saturation: DEFAULT_ACCENT_SATURATION },
15
+ { hue: DEFAULT_SUCCESS_HUE, saturation: DEFAULT_SUCCESS_SATURATION },
16
+ { hue: DEFAULT_WARNING_HUE, saturation: DEFAULT_WARNING_SATURATION },
17
+ { hue: DEFAULT_ERROR_HUE, saturation: DEFAULT_ERROR_SATURATION }
18
+ ]
19
+ },
20
+ themes: {
21
+ neutral: { paletteIndex: 0, lightModeNv: 0.95, darkModeNv: 0.1 },
22
+ primary: { paletteIndex: 1, lightModeNv: 0.95, darkModeNv: 0.1 },
23
+ secondary: { paletteIndex: 1, lightModeNv: 0.85, darkModeNv: 0.15 },
24
+ strong: { paletteIndex: 0, lightModeNv: 0.1, darkModeNv: 0.95 }
25
+ },
26
+ elevation: {
27
+ offsets: [-0.02, 0, 0.04]
28
+ // [sunken, default, elevated]
29
+ }
30
+ };
31
+
32
+ // src/theme/NewtoneProvider.tsx
33
+ var ThemeContext = createContext(null);
34
+ function NewtoneProvider({
35
+ config = DEFAULT_THEME_CONFIG,
36
+ initialMode = "light",
37
+ initialTheme = "neutral",
38
+ children
39
+ }) {
40
+ const [mode, setMode] = useState(initialMode);
41
+ const [theme, setTheme] = useState(initialTheme);
42
+ const value = useMemo(
43
+ () => ({
44
+ config,
45
+ mode,
46
+ theme,
47
+ setMode,
48
+ setTheme
49
+ }),
50
+ [config, mode, theme]
51
+ );
52
+ return /* @__PURE__ */ React7.createElement(ThemeContext.Provider, { value }, children);
53
+ }
54
+ function useNewtoneTheme() {
55
+ const context = useContext(ThemeContext);
56
+ if (!context) {
57
+ throw new Error("useNewtoneTheme must be used within NewtoneProvider");
58
+ }
59
+ return context;
60
+ }
61
+ function computeTokens(config, mode, themeMapping, elevation, elevationOffsets) {
62
+ const { dynamicRange, palettes } = config;
63
+ const palette = palettes[themeMapping.paletteIndex];
64
+ if (!palette) {
65
+ throw new Error(`Palette at index ${themeMapping.paletteIndex} not found`);
66
+ }
67
+ const baseNv = mode === "light" ? themeMapping.lightModeNv : themeMapping.darkModeNv;
68
+ const elevationOffset = elevationOffsets[elevation];
69
+ const backgroundNv = Math.max(0, Math.min(1, baseNv + elevationOffset));
70
+ const effectiveTextMode = backgroundNv >= 0.5 ? "light" : "dark";
71
+ const background = getColor(
72
+ palette.hue,
73
+ palette.saturation,
74
+ dynamicRange,
75
+ backgroundNv,
76
+ palette.desaturation,
77
+ palette.paletteHueGrading
78
+ );
79
+ const elevatedNv = Math.max(0, Math.min(1, baseNv + elevationOffsets[2]));
80
+ const backgroundElevated = getColor(
81
+ palette.hue,
82
+ palette.saturation,
83
+ dynamicRange,
84
+ elevatedNv,
85
+ palette.desaturation,
86
+ palette.paletteHueGrading
87
+ );
88
+ const sunkenNv = Math.max(0, Math.min(1, baseNv + elevationOffsets[0]));
89
+ const backgroundSunken = getColor(
90
+ palette.hue,
91
+ palette.saturation,
92
+ dynamicRange,
93
+ sunkenNv,
94
+ palette.desaturation,
95
+ palette.paletteHueGrading
96
+ );
97
+ const textPrimary = getColorByContrast(
98
+ palette.hue,
99
+ palette.saturation,
100
+ dynamicRange,
101
+ 4.5,
102
+ effectiveTextMode,
103
+ palette.desaturation,
104
+ palette.paletteHueGrading
105
+ );
106
+ const textSecondary = getColorByContrast(
107
+ palette.hue,
108
+ palette.saturation,
109
+ dynamicRange,
110
+ 3,
111
+ effectiveTextMode,
112
+ palette.desaturation,
113
+ palette.paletteHueGrading
114
+ );
115
+ const accentPalette = palettes[1];
116
+ if (!accentPalette) {
117
+ throw new Error("Accent palette (index 1) not found");
118
+ }
119
+ const interactive = getColorByContrast(
120
+ accentPalette.hue,
121
+ accentPalette.saturation,
122
+ dynamicRange,
123
+ 4.5,
124
+ effectiveTextMode,
125
+ accentPalette.desaturation,
126
+ accentPalette.paletteHueGrading
127
+ );
128
+ const interactiveNv = effectiveTextMode === "light" ? 0.3 : 0.7;
129
+ const interactiveHover = getColor(
130
+ accentPalette.hue,
131
+ accentPalette.saturation,
132
+ dynamicRange,
133
+ interactiveNv + (effectiveTextMode === "light" ? -0.05 : 0.05),
134
+ accentPalette.desaturation,
135
+ accentPalette.paletteHueGrading
136
+ );
137
+ const interactiveActive = getColor(
138
+ accentPalette.hue,
139
+ accentPalette.saturation,
140
+ dynamicRange,
141
+ interactiveNv + (effectiveTextMode === "light" ? -0.1 : 0.1),
142
+ accentPalette.desaturation,
143
+ accentPalette.paletteHueGrading
144
+ );
145
+ const borderNv = effectiveTextMode === "light" ? backgroundNv - 0.1 : backgroundNv + 0.1;
146
+ const border = getColor(
147
+ palette.hue,
148
+ palette.saturation,
149
+ dynamicRange,
150
+ Math.max(0, Math.min(1, borderNv)),
151
+ palette.desaturation,
152
+ palette.paletteHueGrading
153
+ );
154
+ const successPalette = palettes[2];
155
+ const warningPalette = palettes[3];
156
+ const errorPalette = palettes[4];
157
+ const success = successPalette ? getColorByContrast(
158
+ successPalette.hue,
159
+ successPalette.saturation,
160
+ dynamicRange,
161
+ 4.5,
162
+ effectiveTextMode,
163
+ successPalette.desaturation,
164
+ successPalette.paletteHueGrading
165
+ ) : interactive;
166
+ const warning = warningPalette ? getColorByContrast(
167
+ warningPalette.hue,
168
+ warningPalette.saturation,
169
+ dynamicRange,
170
+ 4.5,
171
+ effectiveTextMode,
172
+ warningPalette.desaturation,
173
+ warningPalette.paletteHueGrading
174
+ ) : interactive;
175
+ const error = errorPalette ? getColorByContrast(
176
+ errorPalette.hue,
177
+ errorPalette.saturation,
178
+ dynamicRange,
179
+ 4.5,
180
+ effectiveTextMode,
181
+ errorPalette.desaturation,
182
+ errorPalette.paletteHueGrading
183
+ ) : interactive;
184
+ return {
185
+ background,
186
+ backgroundElevated,
187
+ backgroundSunken,
188
+ textPrimary,
189
+ textSecondary,
190
+ interactive,
191
+ interactiveHover,
192
+ interactiveActive,
193
+ border,
194
+ success,
195
+ warning,
196
+ error
197
+ };
198
+ }
199
+
200
+ // src/tokens/useTokens.ts
201
+ function useTokens(elevation = 1) {
202
+ const { config, mode, theme } = useNewtoneTheme();
203
+ return useMemo(() => {
204
+ const themeMapping = config.themes[theme];
205
+ return computeTokens(
206
+ config.colorSystem,
207
+ mode,
208
+ themeMapping,
209
+ elevation,
210
+ config.elevation.offsets
211
+ );
212
+ }, [config, mode, theme, elevation]);
213
+ }
214
+ var SIZE_CONFIG = {
215
+ sm: { paddingVertical: 6, paddingHorizontal: 12, fontSize: 12, borderRadius: 4 },
216
+ md: { paddingVertical: 10, paddingHorizontal: 20, fontSize: 14, borderRadius: 6 },
217
+ lg: { paddingVertical: 14, paddingHorizontal: 28, fontSize: 16, borderRadius: 8 }
218
+ };
219
+ function getButtonStyles(tokens, variant, size, disabled) {
220
+ const sizeConfig = SIZE_CONFIG[size];
221
+ const base = {
222
+ paddingVertical: sizeConfig.paddingVertical,
223
+ paddingHorizontal: sizeConfig.paddingHorizontal,
224
+ borderRadius: sizeConfig.borderRadius,
225
+ alignItems: "center",
226
+ justifyContent: "center",
227
+ flexDirection: "row"
228
+ };
229
+ let backgroundColor;
230
+ let textColor;
231
+ let borderColor;
232
+ let borderWidth = 0;
233
+ switch (variant) {
234
+ case "primary":
235
+ backgroundColor = srgbToHex(tokens.interactive.srgb);
236
+ textColor = srgbToHex(tokens.background.srgb);
237
+ break;
238
+ case "secondary":
239
+ backgroundColor = srgbToHex(tokens.backgroundElevated.srgb);
240
+ textColor = srgbToHex(tokens.textPrimary.srgb);
241
+ break;
242
+ case "outline":
243
+ backgroundColor = "transparent";
244
+ textColor = srgbToHex(tokens.interactive.srgb);
245
+ borderColor = srgbToHex(tokens.border.srgb);
246
+ borderWidth = 1;
247
+ break;
248
+ case "ghost":
249
+ backgroundColor = "transparent";
250
+ textColor = srgbToHex(tokens.interactive.srgb);
251
+ break;
252
+ }
253
+ return StyleSheet.create({
254
+ base: {
255
+ ...base,
256
+ backgroundColor: disabled ? srgbToHex(tokens.backgroundSunken.srgb) : backgroundColor,
257
+ borderWidth,
258
+ ...borderColor && { borderColor }
259
+ },
260
+ pressed: {
261
+ backgroundColor: variant === "primary" ? srgbToHex(tokens.interactiveActive.srgb) : variant === "secondary" ? srgbToHex(tokens.backgroundSunken.srgb) : "transparent",
262
+ opacity: variant === "ghost" || variant === "outline" ? 0.7 : 1
263
+ },
264
+ disabled: {
265
+ opacity: 0.4
266
+ },
267
+ text: {
268
+ fontSize: sizeConfig.fontSize,
269
+ fontWeight: "600",
270
+ color: disabled ? srgbToHex(tokens.textSecondary.srgb) : textColor
271
+ },
272
+ textPressed: {
273
+ // Color changes handled by parent opacity
274
+ },
275
+ textDisabled: {
276
+ // Color already set in text style via disabled check
277
+ }
278
+ });
279
+ }
280
+
281
+ // src/Button/Button.tsx
282
+ function Button({
283
+ children,
284
+ variant = "primary",
285
+ size = "md",
286
+ disabled = false,
287
+ style,
288
+ textStyle,
289
+ ...pressableProps
290
+ }) {
291
+ const tokens = useTokens(1);
292
+ const styles = React7.useMemo(
293
+ () => getButtonStyles(tokens, variant, size, disabled),
294
+ [tokens, variant, size, disabled]
295
+ );
296
+ return /* @__PURE__ */ React7.createElement(
297
+ Pressable,
298
+ {
299
+ style: ({ pressed }) => [
300
+ styles.base,
301
+ pressed && !disabled && styles.pressed,
302
+ disabled && styles.disabled,
303
+ ...Array.isArray(style) ? style : [style]
304
+ ],
305
+ disabled,
306
+ ...pressableProps
307
+ },
308
+ ({ pressed }) => /* @__PURE__ */ React7.createElement(
309
+ Text,
310
+ {
311
+ style: [
312
+ styles.text,
313
+ pressed && !disabled && styles.textPressed,
314
+ disabled && styles.textDisabled,
315
+ ...Array.isArray(textStyle) ? textStyle : [textStyle]
316
+ ]
317
+ },
318
+ children
319
+ )
320
+ );
321
+ }
322
+ function getCardStyles(tokens, disabled) {
323
+ return StyleSheet.create({
324
+ container: {
325
+ backgroundColor: srgbToHex(tokens.background.srgb),
326
+ borderWidth: 1,
327
+ borderColor: srgbToHex(tokens.border.srgb),
328
+ borderRadius: 8,
329
+ padding: 16,
330
+ opacity: disabled ? 0.5 : 1
331
+ }
332
+ });
333
+ }
334
+
335
+ // src/Card/Card.tsx
336
+ function Card({
337
+ children,
338
+ elevation = 1,
339
+ style,
340
+ disabled = false
341
+ }) {
342
+ const tokens = useTokens(elevation);
343
+ const styles = React7.useMemo(
344
+ () => getCardStyles(tokens, disabled),
345
+ [tokens, disabled]
346
+ );
347
+ return /* @__PURE__ */ React7.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, children);
348
+ }
349
+ function getTextInputStyles(tokens, disabled) {
350
+ return StyleSheet.create({
351
+ container: {
352
+ gap: 4
353
+ },
354
+ label: {
355
+ fontSize: 12,
356
+ fontWeight: "600",
357
+ color: srgbToHex(tokens.textSecondary.srgb)
358
+ },
359
+ input: {
360
+ backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
361
+ borderWidth: 1,
362
+ borderColor: srgbToHex(tokens.border.srgb),
363
+ borderRadius: 6,
364
+ paddingVertical: 8,
365
+ paddingHorizontal: 12,
366
+ fontSize: 14,
367
+ color: disabled ? srgbToHex(tokens.textSecondary.srgb) : srgbToHex(tokens.textPrimary.srgb),
368
+ opacity: disabled ? 0.5 : 1
369
+ }
370
+ });
371
+ }
372
+ function TextInput({
373
+ label,
374
+ disabled = false,
375
+ style,
376
+ ...textInputProps
377
+ }) {
378
+ const tokens = useTokens(1);
379
+ const styles = React7.useMemo(
380
+ () => getTextInputStyles(tokens, disabled),
381
+ [tokens, disabled]
382
+ );
383
+ return /* @__PURE__ */ React7.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React7.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React7.createElement(
384
+ TextInput$1,
385
+ {
386
+ style: styles.input,
387
+ editable: !disabled,
388
+ placeholderTextColor: srgbToHex(tokens.textSecondary.srgb),
389
+ ...textInputProps
390
+ }
391
+ ));
392
+ }
393
+ function getSelectStyles(tokens, disabled) {
394
+ return StyleSheet.create({
395
+ container: {
396
+ gap: 4
397
+ },
398
+ label: {
399
+ fontSize: 12,
400
+ fontWeight: "600",
401
+ color: srgbToHex(tokens.textSecondary.srgb)
402
+ },
403
+ select: {
404
+ backgroundColor: srgbToHex(tokens.backgroundSunken.srgb),
405
+ borderWidth: 1,
406
+ borderColor: srgbToHex(tokens.border.srgb),
407
+ borderRadius: 6,
408
+ paddingVertical: 8,
409
+ paddingHorizontal: 12,
410
+ fontSize: 14,
411
+ color: disabled ? srgbToHex(tokens.textSecondary.srgb) : srgbToHex(tokens.textPrimary.srgb),
412
+ opacity: disabled ? 0.5 : 1
413
+ }
414
+ });
415
+ }
416
+
417
+ // src/Select/Select.tsx
418
+ function Select({
419
+ options,
420
+ value,
421
+ onValueChange,
422
+ label,
423
+ disabled = false,
424
+ style
425
+ }) {
426
+ const tokens = useTokens(1);
427
+ const styles = React7.useMemo(
428
+ () => getSelectStyles(tokens, disabled),
429
+ [tokens, disabled]
430
+ );
431
+ const handleChange = React7.useCallback(
432
+ (e) => {
433
+ onValueChange(e.target.value);
434
+ },
435
+ [onValueChange]
436
+ );
437
+ const selectStyle = StyleSheet.flatten(styles.select);
438
+ return /* @__PURE__ */ React7.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React7.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React7.createElement(
439
+ "select",
440
+ {
441
+ value,
442
+ onChange: handleChange,
443
+ disabled,
444
+ style: {
445
+ ...selectStyle,
446
+ cursor: disabled ? "default" : "pointer",
447
+ appearance: "auto"
448
+ }
449
+ },
450
+ options.map((option) => /* @__PURE__ */ React7.createElement("option", { key: option.value, value: option.value }, option.label))
451
+ ));
452
+ }
453
+ var TRACK_WIDTH = 40;
454
+ var TRACK_HEIGHT = 22;
455
+ var THUMB_SIZE = 18;
456
+ var THUMB_OFFSET = 2;
457
+ function getToggleStyles(tokens, value, disabled) {
458
+ return StyleSheet.create({
459
+ container: {
460
+ flexDirection: "row",
461
+ alignItems: "center",
462
+ gap: 8,
463
+ opacity: disabled ? 0.5 : 1
464
+ },
465
+ label: {
466
+ fontSize: 12,
467
+ fontWeight: "600",
468
+ color: srgbToHex(tokens.textSecondary.srgb)
469
+ },
470
+ track: {
471
+ width: TRACK_WIDTH,
472
+ height: TRACK_HEIGHT,
473
+ borderRadius: TRACK_HEIGHT / 2,
474
+ backgroundColor: value ? srgbToHex(tokens.interactive.srgb) : srgbToHex(tokens.border.srgb),
475
+ justifyContent: "center",
476
+ paddingHorizontal: THUMB_OFFSET
477
+ },
478
+ thumb: {
479
+ width: THUMB_SIZE,
480
+ height: THUMB_SIZE,
481
+ borderRadius: THUMB_SIZE / 2,
482
+ backgroundColor: srgbToHex(tokens.background.srgb),
483
+ alignSelf: value ? "flex-end" : "flex-start"
484
+ }
485
+ });
486
+ }
487
+
488
+ // src/Toggle/Toggle.tsx
489
+ function Toggle({
490
+ value,
491
+ onValueChange,
492
+ label,
493
+ disabled = false,
494
+ style
495
+ }) {
496
+ const tokens = useTokens(1);
497
+ const styles = React7.useMemo(
498
+ () => getToggleStyles(tokens, value, disabled),
499
+ [tokens, value, disabled]
500
+ );
501
+ const handlePress = React7.useCallback(() => {
502
+ if (!disabled) {
503
+ onValueChange(!value);
504
+ }
505
+ }, [disabled, value, onValueChange]);
506
+ return /* @__PURE__ */ React7.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, label && /* @__PURE__ */ React7.createElement(Text, { style: styles.label }, label), /* @__PURE__ */ React7.createElement(
507
+ Pressable,
508
+ {
509
+ onPress: handlePress,
510
+ disabled,
511
+ accessibilityRole: "switch",
512
+ accessibilityState: { checked: value, disabled }
513
+ },
514
+ /* @__PURE__ */ React7.createElement(View, { style: styles.track }, /* @__PURE__ */ React7.createElement(View, { style: styles.thumb }))
515
+ ));
516
+ }
517
+ function getSliderStyles(tokens) {
518
+ return StyleSheet.create({
519
+ container: {
520
+ gap: 4
521
+ },
522
+ labelRow: {
523
+ flexDirection: "row",
524
+ justifyContent: "space-between",
525
+ alignItems: "center"
526
+ },
527
+ label: {
528
+ fontSize: 12,
529
+ fontWeight: "600",
530
+ color: srgbToHex(tokens.textSecondary.srgb)
531
+ },
532
+ value: {
533
+ fontSize: 12,
534
+ fontWeight: "500",
535
+ color: srgbToHex(tokens.textPrimary.srgb)
536
+ }
537
+ });
538
+ }
539
+ function getSliderInputStyle(tokens, disabled) {
540
+ return {
541
+ width: "100%",
542
+ height: 6,
543
+ borderRadius: 3,
544
+ appearance: "auto",
545
+ cursor: disabled ? "default" : "pointer",
546
+ opacity: disabled ? 0.5 : 1,
547
+ accentColor: srgbToHex(tokens.interactive.srgb)
548
+ };
549
+ }
550
+
551
+ // src/Slider/Slider.tsx
552
+ function Slider({
553
+ value,
554
+ onValueChange,
555
+ min = 0,
556
+ max = 100,
557
+ step = 1,
558
+ label,
559
+ showValue = false,
560
+ disabled = false,
561
+ style
562
+ }) {
563
+ const tokens = useTokens(1);
564
+ const styles = React7.useMemo(
565
+ () => getSliderStyles(tokens),
566
+ [tokens]
567
+ );
568
+ const inputStyle = React7.useMemo(
569
+ () => getSliderInputStyle(tokens, disabled),
570
+ [tokens, disabled]
571
+ );
572
+ const handleChange = React7.useCallback(
573
+ (e) => {
574
+ onValueChange(Number(e.target.value));
575
+ },
576
+ [onValueChange]
577
+ );
578
+ return /* @__PURE__ */ React7.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, (label || showValue) && /* @__PURE__ */ React7.createElement(View, { style: styles.labelRow }, label && /* @__PURE__ */ React7.createElement(Text, { style: styles.label }, label), showValue && /* @__PURE__ */ React7.createElement(Text, { style: styles.value }, value)), /* @__PURE__ */ React7.createElement(
579
+ "input",
580
+ {
581
+ type: "range",
582
+ min,
583
+ max,
584
+ step,
585
+ value,
586
+ onChange: handleChange,
587
+ disabled,
588
+ style: inputStyle
589
+ }
590
+ ));
591
+ }
592
+ var HUE_GRADIENT = "linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)";
593
+ function hueToHex(hue) {
594
+ const h = (hue % 360 + 360) % 360;
595
+ const x = 1 - Math.abs(h / 60 % 2 - 1);
596
+ let r, g, b;
597
+ if (h < 60) {
598
+ r = 1;
599
+ g = x;
600
+ b = 0;
601
+ } else if (h < 120) {
602
+ r = x;
603
+ g = 1;
604
+ b = 0;
605
+ } else if (h < 180) {
606
+ r = 0;
607
+ g = 1;
608
+ b = x;
609
+ } else if (h < 240) {
610
+ r = 0;
611
+ g = x;
612
+ b = 1;
613
+ } else if (h < 300) {
614
+ r = x;
615
+ g = 0;
616
+ b = 1;
617
+ } else {
618
+ r = 1;
619
+ g = 0;
620
+ b = x;
621
+ }
622
+ const toHex = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
623
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
624
+ }
625
+ function buildHueGradient(min, max) {
626
+ if (min === 0 && max === 359) return HUE_GRADIENT;
627
+ const steps = 7;
628
+ const stops = [];
629
+ for (let i = 0; i <= steps; i++) {
630
+ const hue = min + (max - min) * (i / steps);
631
+ stops.push(hueToHex(hue));
632
+ }
633
+ return `linear-gradient(to right, ${stops.join(", ")})`;
634
+ }
635
+ function getHueSliderStyles(tokens) {
636
+ return StyleSheet.create({
637
+ container: {
638
+ gap: 4
639
+ },
640
+ labelRow: {
641
+ flexDirection: "row",
642
+ justifyContent: "space-between",
643
+ alignItems: "center"
644
+ },
645
+ label: {
646
+ fontSize: 12,
647
+ fontWeight: "600",
648
+ color: srgbToHex(tokens.textSecondary.srgb)
649
+ },
650
+ value: {
651
+ fontSize: 12,
652
+ fontWeight: "500",
653
+ color: srgbToHex(tokens.textPrimary.srgb)
654
+ },
655
+ sliderTrack: {
656
+ height: 22,
657
+ borderRadius: 11,
658
+ overflow: "hidden"
659
+ }
660
+ });
661
+ }
662
+ function getHueSliderInputStyle(disabled, min = 0, max = 359) {
663
+ return {
664
+ width: "100%",
665
+ height: 22,
666
+ borderRadius: 11,
667
+ cursor: disabled ? "default" : "pointer",
668
+ opacity: disabled ? 0.5 : 1,
669
+ background: buildHueGradient(min, max),
670
+ appearance: "auto"
671
+ };
672
+ }
673
+
674
+ // src/HueSlider/HueSlider.tsx
675
+ function HueSlider({
676
+ value,
677
+ onValueChange,
678
+ min = 0,
679
+ max = 359,
680
+ label,
681
+ showValue = false,
682
+ disabled = false,
683
+ style
684
+ }) {
685
+ const tokens = useTokens(1);
686
+ const styles = React7.useMemo(
687
+ () => getHueSliderStyles(tokens),
688
+ [tokens]
689
+ );
690
+ const inputStyle = React7.useMemo(
691
+ () => getHueSliderInputStyle(disabled, min, max),
692
+ [disabled, min, max]
693
+ );
694
+ const sliderValue = max > 359 && value < min ? value + 360 : value;
695
+ const handleChange = React7.useCallback(
696
+ (e) => {
697
+ const raw = Number(e.target.value);
698
+ onValueChange((raw % 360 + 360) % 360);
699
+ },
700
+ [onValueChange]
701
+ );
702
+ return /* @__PURE__ */ React7.createElement(View, { style: [styles.container, ...Array.isArray(style) ? style : [style]] }, (label || showValue) && /* @__PURE__ */ React7.createElement(View, { style: styles.labelRow }, label && /* @__PURE__ */ React7.createElement(Text, { style: styles.label }, label), showValue && /* @__PURE__ */ React7.createElement(Text, { style: styles.value }, value, "\xB0")), /* @__PURE__ */ React7.createElement(
703
+ "input",
704
+ {
705
+ type: "range",
706
+ min,
707
+ max,
708
+ step: 1,
709
+ value: sliderValue,
710
+ onChange: handleChange,
711
+ disabled,
712
+ style: inputStyle
713
+ }
714
+ ));
715
+ }
716
+
717
+ export { Button, Card, DEFAULT_THEME_CONFIG, HueSlider, NewtoneProvider, Select, Slider, TextInput, Toggle, computeTokens, useNewtoneTheme, useTokens };
718
+ //# sourceMappingURL=index.js.map
719
+ //# sourceMappingURL=index.js.map