namps-native 1.0.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,622 @@
1
+ import React2, { createContext, useState, useCallback, useMemo, useRef, useContext } from 'react';
2
+ import { View, useColorScheme, Pressable, ActivityIndicator, Text, TextInput } from 'react-native';
3
+ import Svg, { Circle, Path } from 'react-native-svg';
4
+ import Animated2, { useSharedValue, useAnimatedStyle, withTiming, useDerivedValue, interpolateColor } from 'react-native-reanimated';
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // src/theme/tokens.ts
13
+ var tokens_exports = {};
14
+ __export(tokens_exports, {
15
+ fontFamily: () => fontFamily,
16
+ fontSize: () => fontSize,
17
+ fontWeight: () => fontWeight,
18
+ lineHeight: () => lineHeight,
19
+ motion: () => motion,
20
+ palette: () => palette,
21
+ radius: () => radius,
22
+ sizing: () => sizing,
23
+ space: () => space
24
+ });
25
+ var palette = {
26
+ // Warm paper neutrals
27
+ sand50: "#FBFAF6",
28
+ sand100: "#F3F0E8",
29
+ sand200: "#EAE6DB",
30
+ sand300: "#E5E0D4",
31
+ sand400: "#D4CDBD",
32
+ sand500: "#9C9482",
33
+ sand600: "#6B6555",
34
+ sand700: "#413C33",
35
+ sand800: "#211E18",
36
+ sand900: "#191712",
37
+ ink: "#201E1A",
38
+ paperWhite: "#FFFFFF",
39
+ // Clay accent
40
+ clay400: "#D6805C",
41
+ clay500: "#C15F3C",
42
+ clay600: "#A64E2E",
43
+ clay100: "#F1E1D8",
44
+ // Semantic hues
45
+ green500: "#47795B",
46
+ green400: "#6EA687",
47
+ amber500: "#9E6E1B",
48
+ amber400: "#CDA052",
49
+ red500: "#B0463B",
50
+ red400: "#D67E71",
51
+ blue500: "#3F6591",
52
+ blue400: "#7FA4CF"
53
+ };
54
+ var space = {
55
+ 0: 0,
56
+ 1: 4,
57
+ 2: 8,
58
+ 3: 12,
59
+ 4: 16,
60
+ 5: 20,
61
+ 6: 24,
62
+ 8: 32,
63
+ 10: 40,
64
+ 12: 64
65
+ };
66
+ var radius = {
67
+ none: 0,
68
+ sm: 6,
69
+ md: 10,
70
+ lg: 14,
71
+ xl: 20,
72
+ full: 999
73
+ };
74
+ var fontSize = {
75
+ xs: 12,
76
+ sm: 13,
77
+ base: 15,
78
+ md: 16,
79
+ lg: 18,
80
+ xl: 22,
81
+ "2xl": 28,
82
+ "3xl": 34,
83
+ display: 46
84
+ };
85
+ var lineHeight = {
86
+ tight: 1.15,
87
+ snug: 1.35,
88
+ normal: 1.5,
89
+ relaxed: 1.6
90
+ };
91
+ var fontWeight = {
92
+ regular: "400",
93
+ medium: "500",
94
+ semibold: "600",
95
+ bold: "700"
96
+ };
97
+ var fontFamily = {
98
+ display: "Newsreader",
99
+ body: "Geist",
100
+ mono: "JetBrainsMono"
101
+ };
102
+ var motion = {
103
+ duration: { fast: 120, base: 220, slow: 340 },
104
+ /** Reanimated: `Easing.bezier(...motion.easing.standard)`. */
105
+ easing: {
106
+ standard: [0.2, 0, 0, 1],
107
+ decelerate: [0, 0, 0, 1],
108
+ accelerate: [0.4, 0, 1, 1]
109
+ }
110
+ };
111
+ var sizing = {
112
+ sm: { height: 34, paddingX: space[3], fontSize: fontSize.sm, radius: radius.sm, icon: 16 },
113
+ md: { height: 44, paddingX: space[5], fontSize: fontSize.base, radius: radius.md, icon: 18 },
114
+ lg: { height: 54, paddingX: space[6], fontSize: fontSize.md, radius: radius.lg, icon: 20 }
115
+ };
116
+
117
+ // src/theme/themes.ts
118
+ var shared = { space, radius, fontSize, lineHeight, fontWeight, fontFamily, motion, sizing };
119
+ var lightTheme = {
120
+ name: "light",
121
+ ...shared,
122
+ colors: {
123
+ bg: palette.sand100,
124
+ surface: palette.sand50,
125
+ elevated: palette.paperWhite,
126
+ sunken: palette.sand200,
127
+ border: palette.sand300,
128
+ borderStrong: palette.sand400,
129
+ text: palette.ink,
130
+ textMuted: palette.sand600,
131
+ textSubtle: palette.sand500,
132
+ accent: palette.clay500,
133
+ accentHover: palette.clay600,
134
+ accentSoft: palette.clay100,
135
+ onAccent: palette.paperWhite,
136
+ success: palette.green500,
137
+ successSoft: "#E1ECE4",
138
+ warning: palette.amber500,
139
+ warningSoft: "#F3E8D2",
140
+ danger: palette.red500,
141
+ dangerSoft: "#F3DED9",
142
+ info: palette.blue500,
143
+ infoSoft: "#DDE7F1"
144
+ },
145
+ shadow: {
146
+ sm: { shadowColor: "#2B2214", shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.06, shadowRadius: 2, elevation: 1 },
147
+ md: { shadowColor: "#2B2214", shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.08, shadowRadius: 14, elevation: 4 },
148
+ lg: { shadowColor: "#2B2214", shadowOffset: { width: 0, height: 18 }, shadowOpacity: 0.14, shadowRadius: 48, elevation: 12 }
149
+ }
150
+ };
151
+ var darkTheme = {
152
+ name: "dark",
153
+ ...shared,
154
+ colors: {
155
+ bg: palette.sand900,
156
+ surface: palette.sand800,
157
+ elevated: "#2A261F",
158
+ sunken: "#131109",
159
+ border: "#332F27",
160
+ borderStrong: "#443F35",
161
+ text: "#EDE8DC",
162
+ textMuted: "#A69E8D",
163
+ textSubtle: "#726B5C",
164
+ accent: palette.clay400,
165
+ accentHover: "#E4936F",
166
+ accentSoft: "#3A2A21",
167
+ onAccent: "#1B140F",
168
+ success: palette.green400,
169
+ successSoft: "#20302A",
170
+ warning: palette.amber400,
171
+ warningSoft: "#332916",
172
+ danger: palette.red400,
173
+ dangerSoft: "#3A231E",
174
+ info: palette.blue400,
175
+ infoSoft: "#1F2A38"
176
+ },
177
+ shadow: {
178
+ sm: { shadowColor: "#000", shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.4, shadowRadius: 2, elevation: 1 },
179
+ md: { shadowColor: "#000", shadowOffset: { width: 0, height: 6 }, shadowOpacity: 0.45, shadowRadius: 18, elevation: 6 },
180
+ lg: { shadowColor: "#000", shadowOffset: { width: 0, height: 22 }, shadowOpacity: 0.6, shadowRadius: 55, elevation: 16 }
181
+ }
182
+ };
183
+ function createTheme(base2, overrides = {}) {
184
+ return deepMerge(base2, overrides);
185
+ }
186
+ function deepMerge(base2, override) {
187
+ const out = Array.isArray(base2) ? [...base2] : { ...base2 };
188
+ for (const key in override) {
189
+ const v = override[key];
190
+ if (v && typeof v === "object" && !Array.isArray(v)) out[key] = deepMerge(base2[key], v);
191
+ else if (v !== void 0) out[key] = v;
192
+ }
193
+ return out;
194
+ }
195
+
196
+ // src/theme/ThemeProvider.tsx
197
+ var ThemeContext = createContext(null);
198
+ function ThemeProvider({
199
+ children,
200
+ light = lightTheme,
201
+ dark = darkTheme,
202
+ defaultPreference = "system"
203
+ }) {
204
+ const system = useColorScheme();
205
+ const [preference, setPreference] = useState(defaultPreference);
206
+ const scheme = preference === "system" ? system === "dark" ? "dark" : "light" : preference;
207
+ const toggle = useCallback(
208
+ () => setPreference((p) => {
209
+ const current = p === "system" ? system === "dark" ? "dark" : "light" : p;
210
+ return current === "dark" ? "light" : "dark";
211
+ }),
212
+ [system]
213
+ );
214
+ const value = useMemo(
215
+ () => ({ theme: scheme === "dark" ? dark : light, scheme, preference, setPreference, toggle }),
216
+ [scheme, preference, light, dark, toggle]
217
+ );
218
+ return /* @__PURE__ */ React2.createElement(ThemeContext.Provider, { value }, children);
219
+ }
220
+ function useThemeContext() {
221
+ const ctx = useContext(ThemeContext);
222
+ if (!ctx) throw new Error("Clay: components must be rendered inside <ThemeProvider>.");
223
+ return ctx;
224
+ }
225
+
226
+ // src/theme/useTheme.ts
227
+ function useTheme() {
228
+ return useThemeContext().theme;
229
+ }
230
+ function useColorSchemeControl() {
231
+ const { scheme, preference, setPreference, toggle } = useThemeContext();
232
+ return { scheme, preference, setPreference, toggle };
233
+ }
234
+ function useControllableState(params) {
235
+ const { value, defaultValue, onChange } = params;
236
+ const isControlled = value !== void 0;
237
+ const [internal, setInternal] = useState(defaultValue);
238
+ const onChangeRef = useRef(onChange);
239
+ onChangeRef.current = onChange;
240
+ const resolved = isControlled ? value : internal;
241
+ const setValue = useCallback(
242
+ (next) => {
243
+ if (!isControlled) setInternal(next);
244
+ onChangeRef.current?.(next);
245
+ },
246
+ [isControlled]
247
+ );
248
+ return [resolved, setValue];
249
+ }
250
+ function useDisclosure(defaultOpen = false) {
251
+ const [isOpen, setOpen] = useState(defaultOpen);
252
+ const open = useCallback(() => setOpen(true), []);
253
+ const close = useCallback(() => setOpen(false), []);
254
+ const toggle = useCallback(() => setOpen((v) => !v), []);
255
+ return { isOpen, open, close, toggle };
256
+ }
257
+
258
+ // src/utils/color.ts
259
+ function shade(hex, amount) {
260
+ const { r, g, b } = hexToRgb(hex);
261
+ const t = amount < 0 ? 0 : 255;
262
+ const p = Math.abs(amount);
263
+ const mix = (c) => Math.round((t - c) * p + c);
264
+ return rgbToHex(mix(r), mix(g), mix(b));
265
+ }
266
+ function withAlpha(hex, alpha) {
267
+ const { r, g, b } = hexToRgb(hex);
268
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
269
+ }
270
+ function hexToRgb(hex) {
271
+ const h = hex.replace("#", "");
272
+ const full = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
273
+ return {
274
+ r: parseInt(full.slice(0, 2), 16),
275
+ g: parseInt(full.slice(2, 4), 16),
276
+ b: parseInt(full.slice(4, 6), 16)
277
+ };
278
+ }
279
+ function rgbToHex(r, g, b) {
280
+ return "#" + [r, g, b].map((c) => c.toString(16).padStart(2, "0")).join("");
281
+ }
282
+ var base = (size = 22) => ({ width: size, height: size, viewBox: "0 0 24 24", fill: "none" });
283
+ var stroke = (color = "currentColor") => ({ stroke: color, strokeWidth: 1.7, strokeLinecap: "round", strokeLinejoin: "round" });
284
+ var SearchIcon = ({ size, color }) => /* @__PURE__ */ React2.createElement(Svg, { ...base(size) }, /* @__PURE__ */ React2.createElement(Circle, { cx: 11, cy: 11, r: 6.5, ...stroke(color) }), /* @__PURE__ */ React2.createElement(Path, { d: "m20 20-3.6-3.6", ...stroke(color) }));
285
+ var PlusIcon = ({ size, color }) => /* @__PURE__ */ React2.createElement(Svg, { ...base(size) }, /* @__PURE__ */ React2.createElement(Path, { d: "M12 5v14M5 12h14", ...stroke(color) }));
286
+ var CheckIcon = ({ size, color }) => /* @__PURE__ */ React2.createElement(Svg, { ...base(size) }, /* @__PURE__ */ React2.createElement(Path, { d: "m5 12.5 4.5 4.5L19 7", ...stroke(color), strokeWidth: 2 }));
287
+ var ChevronRightIcon = ({ size, color }) => /* @__PURE__ */ React2.createElement(Svg, { ...base(size) }, /* @__PURE__ */ React2.createElement(Path, { d: "m9 6 6 6-6 6", ...stroke(color) }));
288
+ var CloseIcon = ({ size, color }) => /* @__PURE__ */ React2.createElement(Svg, { ...base(size) }, /* @__PURE__ */ React2.createElement(Path, { d: "m6 6 12 12M18 6 6 18", ...stroke(color), strokeWidth: 1.8 }));
289
+ var BellIcon = ({ size, color }) => /* @__PURE__ */ React2.createElement(Svg, { ...base(size) }, /* @__PURE__ */ React2.createElement(Path, { d: "M18 8.5a6 6 0 1 0-12 0c0 5-2 6.5-2 6.5h16s-2-1.5-2-6.5", ...stroke(color) }), /* @__PURE__ */ React2.createElement(Path, { d: "M10.5 19a1.8 1.8 0 0 0 3 0", ...stroke(color) }));
290
+ var AView = Animated2.createAnimatedComponent(View);
291
+ function Button({
292
+ children,
293
+ variant = "primary",
294
+ size = "md",
295
+ loading = false,
296
+ disabled = false,
297
+ fullWidth = false,
298
+ leftIcon,
299
+ rightIcon,
300
+ onPress,
301
+ style,
302
+ accessibilityLabel,
303
+ accessibilityHint,
304
+ testID
305
+ }) {
306
+ const theme = useTheme();
307
+ const dim = theme.sizing[size];
308
+ const pressed = useSharedValue(0);
309
+ const isDisabled = disabled || loading;
310
+ const palette2 = getVariant(variant, theme);
311
+ const animatedStyle = useAnimatedStyle(() => ({
312
+ opacity: withTiming(pressed.value ? 0.9 : 1, { duration: theme.motion.duration.fast }),
313
+ transform: [{ scale: withTiming(pressed.value ? 0.98 : 1, { duration: theme.motion.duration.fast }) }]
314
+ }));
315
+ return /* @__PURE__ */ React2.createElement(
316
+ Pressable,
317
+ {
318
+ onPress,
319
+ onPressIn: () => pressed.value = 1,
320
+ onPressOut: () => pressed.value = 0,
321
+ disabled: isDisabled,
322
+ accessibilityRole: "button",
323
+ accessibilityState: { disabled: isDisabled, busy: loading },
324
+ accessibilityLabel,
325
+ accessibilityHint,
326
+ testID,
327
+ style: fullWidth ? { alignSelf: "stretch" } : void 0
328
+ },
329
+ /* @__PURE__ */ React2.createElement(
330
+ AView,
331
+ {
332
+ style: [
333
+ {
334
+ height: dim.height,
335
+ paddingHorizontal: dim.paddingX,
336
+ borderRadius: dim.radius,
337
+ backgroundColor: palette2.bg,
338
+ borderWidth: palette2.borderWidth,
339
+ borderColor: palette2.border,
340
+ flexDirection: "row",
341
+ alignItems: "center",
342
+ justifyContent: "center",
343
+ gap: theme.space[2],
344
+ opacity: isDisabled ? 0.55 : 1
345
+ },
346
+ animatedStyle,
347
+ style
348
+ ]
349
+ },
350
+ loading ? /* @__PURE__ */ React2.createElement(ActivityIndicator, { size: "small", color: palette2.fg }) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, leftIcon, children != null && /* @__PURE__ */ React2.createElement(Text, { style: { color: palette2.fg, fontSize: dim.fontSize, fontFamily: theme.fontFamily.body, fontWeight: theme.fontWeight.semibold } }, children), rightIcon)
351
+ )
352
+ );
353
+ }
354
+ function getVariant(variant, theme, _disabled) {
355
+ const c = theme.colors;
356
+ switch (variant) {
357
+ case "secondary":
358
+ return { bg: c.elevated, fg: c.text, border: c.borderStrong, borderWidth: 1 };
359
+ case "soft":
360
+ return { bg: c.accentSoft, fg: c.accent, border: "transparent", borderWidth: 0 };
361
+ case "ghost":
362
+ return { bg: "transparent", fg: c.text, border: "transparent", borderWidth: 0 };
363
+ case "danger":
364
+ return { bg: c.danger, fg: "#fff", border: "transparent", borderWidth: 0 };
365
+ case "primary":
366
+ default:
367
+ return { bg: c.accent, fg: c.onAccent, border: "transparent", borderWidth: 0 };
368
+ }
369
+ }
370
+ function IconButton({
371
+ icon,
372
+ variant = "ghost",
373
+ size = "md",
374
+ round = false,
375
+ disabled = false,
376
+ onPress,
377
+ style,
378
+ accessibilityLabel,
379
+ accessibilityHint,
380
+ testID
381
+ }) {
382
+ const theme = useTheme();
383
+ const dim = theme.sizing[size];
384
+ const c = theme.colors;
385
+ const bg = variant === "primary" ? c.accent : variant === "danger" ? c.danger : variant === "soft" ? c.accentSoft : variant === "secondary" ? c.elevated : "transparent";
386
+ const border = variant === "secondary" ? c.borderStrong : "transparent";
387
+ return /* @__PURE__ */ React2.createElement(
388
+ Pressable,
389
+ {
390
+ onPress,
391
+ disabled,
392
+ accessibilityRole: "button",
393
+ accessibilityLabel,
394
+ accessibilityHint,
395
+ accessibilityState: { disabled },
396
+ testID,
397
+ style: ({ pressed }) => [
398
+ {
399
+ width: dim.height,
400
+ height: dim.height,
401
+ borderRadius: round ? theme.radius.full : dim.radius,
402
+ backgroundColor: bg,
403
+ borderWidth: variant === "secondary" ? 1 : 0,
404
+ borderColor: border,
405
+ alignItems: "center",
406
+ justifyContent: "center",
407
+ opacity: disabled ? 0.5 : pressed ? 0.85 : 1
408
+ },
409
+ style
410
+ ]
411
+ },
412
+ /* @__PURE__ */ React2.createElement(View, null, icon)
413
+ );
414
+ }
415
+ function Text2({ children, variant = "body", tone = "default", weight, align, style, ...rest }) {
416
+ const theme = useTheme();
417
+ const v = {
418
+ body: { fontSize: theme.fontSize.base, lineHeight: theme.fontSize.base * theme.lineHeight.relaxed, family: theme.fontFamily.body },
419
+ bodyLg: { fontSize: theme.fontSize.lg, lineHeight: theme.fontSize.lg * theme.lineHeight.relaxed, family: theme.fontFamily.body },
420
+ label: { fontSize: theme.fontSize.sm, lineHeight: theme.fontSize.sm * theme.lineHeight.snug, family: theme.fontFamily.body },
421
+ caption: { fontSize: theme.fontSize.xs, lineHeight: theme.fontSize.xs * theme.lineHeight.snug, family: theme.fontFamily.body },
422
+ mono: { fontSize: theme.fontSize.sm, lineHeight: theme.fontSize.sm * theme.lineHeight.normal, family: theme.fontFamily.mono }
423
+ }[variant];
424
+ const color = {
425
+ default: theme.colors.text,
426
+ muted: theme.colors.textMuted,
427
+ subtle: theme.colors.textSubtle,
428
+ accent: theme.colors.accent,
429
+ danger: theme.colors.danger,
430
+ success: theme.colors.success,
431
+ onAccent: theme.colors.onAccent
432
+ }[tone];
433
+ return /* @__PURE__ */ React2.createElement(
434
+ Text,
435
+ {
436
+ style: [{ color, fontSize: v.fontSize, lineHeight: v.lineHeight, fontFamily: v.family, fontWeight: weight ? theme.fontWeight[weight] : theme.fontWeight.regular, textAlign: align }, style],
437
+ ...rest
438
+ },
439
+ children
440
+ );
441
+ }
442
+ function Heading({ children, level = 2, align, tone = "default", numberOfLines, style }) {
443
+ const theme = useTheme();
444
+ const map = {
445
+ 1: { fontSize: theme.fontSize["3xl"], weight: theme.fontWeight.medium },
446
+ 2: { fontSize: theme.fontSize["2xl"], weight: theme.fontWeight.medium },
447
+ 3: { fontSize: theme.fontSize.xl, weight: theme.fontWeight.medium },
448
+ 4: { fontSize: theme.fontSize.lg, weight: theme.fontWeight.semibold }
449
+ }[level];
450
+ const color = tone === "accent" ? theme.colors.accent : tone === "onAccent" ? theme.colors.onAccent : theme.colors.text;
451
+ return /* @__PURE__ */ React2.createElement(
452
+ Text,
453
+ {
454
+ accessibilityRole: "header",
455
+ numberOfLines,
456
+ style: [{ color, fontSize: map.fontSize, lineHeight: map.fontSize * theme.lineHeight.tight, fontFamily: theme.fontFamily.display, fontWeight: map.weight, letterSpacing: -0.4, textAlign: align }, style]
457
+ },
458
+ children
459
+ );
460
+ }
461
+ function Card({ variant = "outlined", padding = 4, onPress, style, children, testID }) {
462
+ const theme = useTheme();
463
+ const c = theme.colors;
464
+ const surface = {
465
+ outlined: { backgroundColor: c.surface, borderWidth: 1, borderColor: c.border, shadow: void 0 },
466
+ elevated: { backgroundColor: c.elevated, borderWidth: 0, borderColor: "transparent", shadow: theme.shadow.sm },
467
+ filled: { backgroundColor: c.sunken, borderWidth: 1, borderColor: c.border, shadow: void 0 }
468
+ }[variant];
469
+ const boxStyle = [
470
+ {
471
+ borderRadius: theme.radius.lg,
472
+ padding: theme.space[padding],
473
+ backgroundColor: surface.backgroundColor,
474
+ borderWidth: surface.borderWidth,
475
+ borderColor: surface.borderColor
476
+ },
477
+ surface.shadow,
478
+ style
479
+ ];
480
+ if (onPress) {
481
+ return /* @__PURE__ */ React2.createElement(Pressable, { onPress, testID, accessibilityRole: "button", style: ({ pressed }) => [...boxStyle, { opacity: pressed ? 0.94 : 1 }] }, children);
482
+ }
483
+ return /* @__PURE__ */ React2.createElement(View, { testID, style: boxStyle }, children);
484
+ }
485
+ function Input({
486
+ label,
487
+ helperText,
488
+ error,
489
+ size = "md",
490
+ leftAdornment,
491
+ rightAdornment,
492
+ disabled,
493
+ value,
494
+ onChangeText,
495
+ placeholder,
496
+ style,
497
+ testID,
498
+ onFocus,
499
+ onBlur,
500
+ ...rest
501
+ }) {
502
+ const theme = useTheme();
503
+ const c = theme.colors;
504
+ const dim = theme.sizing[size];
505
+ const [focused, setFocused] = useState(false);
506
+ const hasError = !!error;
507
+ const borderColor = hasError ? c.danger : focused ? c.accent : c.borderStrong;
508
+ return /* @__PURE__ */ React2.createElement(View, { style }, label && /* @__PURE__ */ React2.createElement(Text2, { variant: "label", weight: "medium", tone: hasError ? "danger" : "default", style: { marginBottom: theme.space[2] } }, label), /* @__PURE__ */ React2.createElement(
509
+ View,
510
+ {
511
+ style: {
512
+ minHeight: dim.height,
513
+ flexDirection: "row",
514
+ alignItems: "center",
515
+ gap: theme.space[2],
516
+ paddingHorizontal: theme.space[3] + 2,
517
+ borderRadius: dim.radius,
518
+ borderWidth: 1,
519
+ borderColor,
520
+ backgroundColor: disabled ? c.sunken : c.elevated
521
+ }
522
+ },
523
+ leftAdornment,
524
+ /* @__PURE__ */ React2.createElement(
525
+ TextInput,
526
+ {
527
+ value,
528
+ onChangeText,
529
+ placeholder,
530
+ placeholderTextColor: c.textSubtle,
531
+ editable: !disabled,
532
+ onFocus: (e) => {
533
+ setFocused(true);
534
+ onFocus?.(e);
535
+ },
536
+ onBlur: (e) => {
537
+ setFocused(false);
538
+ onBlur?.(e);
539
+ },
540
+ testID,
541
+ style: { flex: 1, color: disabled ? c.textSubtle : c.text, fontSize: dim.fontSize, fontFamily: theme.fontFamily.body, paddingVertical: theme.space[2] },
542
+ ...rest
543
+ }
544
+ ),
545
+ rightAdornment
546
+ ), (error || helperText) && /* @__PURE__ */ React2.createElement(Text2, { variant: "caption", tone: hasError ? "danger" : "subtle", style: { marginTop: theme.space[1] + 2 } }, error || helperText));
547
+ }
548
+ function Switch({ value, defaultValue = false, onValueChange, disabled, accessibilityLabel, testID }) {
549
+ const theme = useTheme();
550
+ const [on, setOn] = useControllableState({ value, defaultValue, onChange: onValueChange });
551
+ const progress = useDerivedValue(() => withTiming(on ? 1 : 0, { duration: theme.motion.duration.fast }), [on]);
552
+ const trackStyle = useAnimatedStyle(() => ({
553
+ backgroundColor: interpolateColor(progress.value, [0, 1], [theme.colors.borderStrong, theme.colors.accent])
554
+ }));
555
+ const thumbStyle = useAnimatedStyle(() => ({ transform: [{ translateX: 18 * progress.value }] }));
556
+ return /* @__PURE__ */ React2.createElement(
557
+ Pressable,
558
+ {
559
+ onPress: () => setOn(!on),
560
+ disabled,
561
+ accessibilityRole: "switch",
562
+ accessibilityState: { checked: on, disabled },
563
+ accessibilityLabel,
564
+ testID,
565
+ hitSlop: 10,
566
+ style: { opacity: disabled ? 0.5 : 1 }
567
+ },
568
+ /* @__PURE__ */ React2.createElement(Animated2.View, { style: [{ width: 44, height: 26, borderRadius: theme.radius.full, padding: 3, justifyContent: "center" }, trackStyle] }, /* @__PURE__ */ React2.createElement(Animated2.View, { style: [{ width: 20, height: 20, borderRadius: theme.radius.full, backgroundColor: "#fff" }, theme.shadow.sm, thumbStyle] }))
569
+ );
570
+ }
571
+ function Checkbox({ value, defaultValue = false, onValueChange, label, disabled, accessibilityLabel, testID }) {
572
+ const theme = useTheme();
573
+ const [checked, setChecked] = useControllableState({ value, defaultValue, onChange: onValueChange });
574
+ const c = theme.colors;
575
+ return /* @__PURE__ */ React2.createElement(
576
+ Pressable,
577
+ {
578
+ onPress: () => setChecked(!checked),
579
+ disabled,
580
+ accessibilityRole: "checkbox",
581
+ accessibilityState: { checked, disabled },
582
+ accessibilityLabel: accessibilityLabel ?? label,
583
+ testID,
584
+ hitSlop: 8,
585
+ style: { flexDirection: "row", alignItems: "center", gap: theme.space[3], opacity: disabled ? 0.5 : 1 }
586
+ },
587
+ /* @__PURE__ */ React2.createElement(
588
+ View,
589
+ {
590
+ style: {
591
+ width: 22,
592
+ height: 22,
593
+ borderRadius: 7,
594
+ alignItems: "center",
595
+ justifyContent: "center",
596
+ backgroundColor: checked ? c.accent : "transparent",
597
+ borderWidth: checked ? 0 : 1.8,
598
+ borderColor: c.borderStrong
599
+ }
600
+ },
601
+ checked && /* @__PURE__ */ React2.createElement(CheckIcon, { size: 14, color: "#fff" })
602
+ ),
603
+ label && /* @__PURE__ */ React2.createElement(Text2, { variant: "body" }, label)
604
+ );
605
+ }
606
+ function Badge({ children, status = "neutral", dot = false, style, testID }) {
607
+ const theme = useTheme();
608
+ const c = theme.colors;
609
+ const map = {
610
+ info: { bg: c.infoSoft, fg: c.info },
611
+ success: { bg: c.successSoft, fg: c.success },
612
+ warning: { bg: c.warningSoft, fg: c.warning },
613
+ danger: { bg: c.dangerSoft, fg: c.danger },
614
+ neutral: { bg: c.sunken, fg: c.textMuted }
615
+ };
616
+ const tone = map[status];
617
+ return /* @__PURE__ */ React2.createElement(View, { testID, style: [{ flexDirection: "row", alignItems: "center", gap: theme.space[1] + 2, height: 24, paddingHorizontal: theme.space[2] + 2, borderRadius: theme.radius.full, backgroundColor: tone.bg }, style] }, dot && /* @__PURE__ */ React2.createElement(View, { style: { width: 6, height: 6, borderRadius: 3, backgroundColor: tone.fg } }), /* @__PURE__ */ React2.createElement(Text2, { variant: "caption", weight: "semibold", style: { color: tone.fg } }, children));
618
+ }
619
+
620
+ export { Badge, BellIcon, Button, Card, CheckIcon, Checkbox, ChevronRightIcon, CloseIcon, Heading, IconButton, Input, PlusIcon, SearchIcon, Switch, Text2 as Text, ThemeProvider, createTheme, darkTheme, lightTheme, shade, tokens_exports as tokens, useColorSchemeControl, useControllableState, useDisclosure, useTheme, withAlpha };
621
+ //# sourceMappingURL=index.mjs.map
622
+ //# sourceMappingURL=index.mjs.map