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