@retray-dev/ui-kit 1.0.0 → 1.6.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 CHANGED
@@ -1,8 +1,12 @@
1
1
  import React23, { createContext, useMemo, useContext, useRef, useState, useEffect, useCallback } from 'react';
2
- import { StyleSheet, useColorScheme, Animated, TouchableOpacity, ActivityIndicator, Text, View, TextInput, Image, PanResponder, Modal, FlatList, Easing } from 'react-native';
3
- import * as Haptics10 from 'expo-haptics';
2
+ import { StyleSheet, useColorScheme, Animated, TouchableOpacity, ActivityIndicator, Text, View, TextInput, Image, PanResponder } from 'react-native';
3
+ import * as Haptics11 from 'expo-haptics';
4
+ import { LinearGradient } from 'expo-linear-gradient';
5
+ import ReanimatedAnimated, { useSharedValue, useAnimatedStyle, withTiming, Easing, withSpring } from 'react-native-reanimated';
4
6
  import { BottomSheetModal, BottomSheetView, BottomSheetBackdrop } from '@gorhom/bottom-sheet';
5
7
  export { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
8
+ import { scheduleOnRN } from 'react-native-worklets';
9
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
6
10
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
7
11
 
8
12
  // src/theme/ThemeProvider.tsx
@@ -25,7 +29,9 @@ var defaultLight = {
25
29
  destructiveForeground: "#fafafa",
26
30
  border: "#e5e5e5",
27
31
  input: "#e5e5e5",
28
- ring: "#a3a3a3"
32
+ ring: "#a3a3a3",
33
+ success: "#16a34a",
34
+ successForeground: "#ffffff"
29
35
  };
30
36
  var defaultDark = {
31
37
  background: "#171717",
@@ -44,7 +50,9 @@ var defaultDark = {
44
50
  destructiveForeground: "#fafafa",
45
51
  border: "#2a2a2a",
46
52
  input: "#2a2a2a",
47
- ring: "#d4d4d4"
53
+ ring: "#d4d4d4",
54
+ success: "#22c55e",
55
+ successForeground: "#ffffff"
48
56
  };
49
57
 
50
58
  // src/theme/ThemeProvider.tsx
@@ -81,6 +89,8 @@ function Button({
81
89
  size = "md",
82
90
  loading = false,
83
91
  fullWidth = false,
92
+ icon,
93
+ iconPosition = "left",
84
94
  disabled,
85
95
  style,
86
96
  onPress,
@@ -91,13 +101,18 @@ function Button({
91
101
  const scale = useRef(new Animated.Value(1)).current;
92
102
  const handlePressIn = () => {
93
103
  if (isDisabled) return;
94
- Animated.spring(scale, { toValue: 0.97, useNativeDriver: true, speed: 40, bounciness: 0 }).start();
104
+ Animated.spring(scale, {
105
+ toValue: 0.95,
106
+ useNativeDriver: true,
107
+ speed: 40,
108
+ bounciness: 0
109
+ }).start();
95
110
  };
96
111
  const handlePressOut = () => {
97
- Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 2 }).start();
112
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start();
98
113
  };
99
114
  const handlePress = (e) => {
100
- Haptics10.impactAsync(Haptics10.ImpactFeedbackStyle.Light);
115
+ Haptics11.impactAsync(Haptics11.ImpactFeedbackStyle.Light);
101
116
  onPress?.(e);
102
117
  };
103
118
  const containerVariantStyle = {
@@ -126,12 +141,13 @@ function Button({
126
141
  ],
127
142
  disabled: isDisabled,
128
143
  activeOpacity: 1,
144
+ touchSoundDisabled: true,
129
145
  onPress: handlePress,
130
146
  onPressIn: handlePressIn,
131
147
  onPressOut: handlePressOut,
132
148
  ...props
133
149
  },
134
- loading ? /* @__PURE__ */ React23.createElement(ActivityIndicator, { size: "small", color: spinnerColor }) : /* @__PURE__ */ React23.createElement(Text, { style: [styles.label, labelVariantStyle, labelSizeStyles[size]] }, label)
150
+ loading ? /* @__PURE__ */ React23.createElement(ActivityIndicator, { size: "small", color: spinnerColor }) : /* @__PURE__ */ React23.createElement(React23.Fragment, null, icon && iconPosition === "left" && /* @__PURE__ */ React23.createElement(React23.Fragment, null, icon), /* @__PURE__ */ React23.createElement(Text, { style: [styles.label, labelVariantStyle, labelSizeStyles[size], icon ? styles.labelWithIcon : void 0] }, label), icon && iconPosition === "right" && /* @__PURE__ */ React23.createElement(React23.Fragment, null, icon))
135
151
  ));
136
152
  }
137
153
  var styles = StyleSheet.create({
@@ -149,6 +165,9 @@ var styles = StyleSheet.create({
149
165
  },
150
166
  label: {
151
167
  fontWeight: "600"
168
+ },
169
+ labelWithIcon: {
170
+ marginHorizontal: 6
152
171
  }
153
172
  });
154
173
  var variantStyles = {
@@ -172,10 +191,10 @@ function Text2({ variant = "body", color, style, children, ...props }) {
172
191
  children
173
192
  );
174
193
  }
175
- function Input({ label, error, hint, style, onFocus, onBlur, ...props }) {
194
+ function Input({ label, error, hint, containerStyle, style, onFocus, onBlur, ...props }) {
176
195
  const { colors } = useTheme();
177
196
  const [focused, setFocused] = useState(false);
178
- return /* @__PURE__ */ React23.createElement(View, { style: styles2.container }, label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles2.label, { color: colors.foreground }] }, label) : null, /* @__PURE__ */ React23.createElement(
197
+ return /* @__PURE__ */ React23.createElement(View, { style: [styles2.container, containerStyle] }, label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles2.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React23.createElement(
179
198
  TextInput,
180
199
  {
181
200
  style: [
@@ -199,7 +218,7 @@ function Input({ label, error, hint, style, onFocus, onBlur, ...props }) {
199
218
  allowFontScaling: true,
200
219
  ...props
201
220
  }
202
- ), error ? /* @__PURE__ */ React23.createElement(Text, { style: [styles2.helperText, { color: colors.destructive }] }, error) : null, !error && hint ? /* @__PURE__ */ React23.createElement(Text, { style: [styles2.helperText, { color: colors.mutedForeground }] }, hint) : null);
221
+ ), error ? /* @__PURE__ */ React23.createElement(Text, { style: [styles2.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null, !error && hint ? /* @__PURE__ */ React23.createElement(Text, { style: [styles2.helperText, { color: colors.mutedForeground }], allowFontScaling: true }, hint) : null);
203
222
  }
204
223
  var styles2 = StyleSheet.create({
205
224
  container: {
@@ -235,7 +254,7 @@ function Badge({ label, variant = "default", style }) {
235
254
  destructive: colors.destructiveForeground,
236
255
  outline: colors.foreground
237
256
  }[variant];
238
- return /* @__PURE__ */ React23.createElement(View, { style: [styles3.container, containerStyle, style] }, /* @__PURE__ */ React23.createElement(Text, { style: [styles3.label, { color: textColor }] }, label));
257
+ return /* @__PURE__ */ React23.createElement(View, { style: [styles3.container, containerStyle, style] }, /* @__PURE__ */ React23.createElement(Text, { style: [styles3.label, { color: textColor }], allowFontScaling: true }, label));
239
258
  }
240
259
  var styles3 = StyleSheet.create({
241
260
  container: {
@@ -254,11 +273,7 @@ function Card({ children, style }) {
254
273
  return /* @__PURE__ */ React23.createElement(
255
274
  View,
256
275
  {
257
- style: [
258
- styles4.card,
259
- { backgroundColor: colors.card, borderColor: colors.border },
260
- style
261
- ]
276
+ style: [styles4.card, { backgroundColor: colors.card, borderColor: colors.border }, style]
262
277
  },
263
278
  children
264
279
  );
@@ -344,41 +359,53 @@ var sizeMap = {
344
359
  };
345
360
  function Spinner({ size = "md", color, ...props }) {
346
361
  const { colors } = useTheme();
347
- return /* @__PURE__ */ React23.createElement(
348
- ActivityIndicator,
349
- {
350
- size: sizeMap[size],
351
- color: color ?? colors.primary,
352
- ...props
353
- }
354
- );
362
+ return /* @__PURE__ */ React23.createElement(ActivityIndicator, { size: sizeMap[size], color: color ?? colors.primary, ...props });
355
363
  }
356
364
  function Skeleton({ width = "100%", height = 16, borderRadius = 6, style }) {
357
- const { colors } = useTheme();
358
- const opacity = useRef(new Animated.Value(1)).current;
365
+ const { colors, colorScheme } = useTheme();
366
+ const shimmerAnim = useRef(new Animated.Value(0)).current;
367
+ const [containerWidth, setContainerWidth] = useState(300);
368
+ const shimmerHighlight = colorScheme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(255,255,255,0.7)";
359
369
  useEffect(() => {
360
370
  const animation = Animated.loop(
361
- Animated.sequence([
362
- Animated.timing(opacity, { toValue: 0.4, duration: 800, useNativeDriver: true }),
363
- Animated.timing(opacity, { toValue: 1, duration: 800, useNativeDriver: true })
364
- ])
371
+ Animated.timing(shimmerAnim, {
372
+ toValue: 1,
373
+ duration: 1200,
374
+ useNativeDriver: true
375
+ })
365
376
  );
366
377
  animation.start();
367
378
  return () => animation.stop();
368
- }, [opacity]);
379
+ }, [shimmerAnim]);
380
+ const translateX = shimmerAnim.interpolate({
381
+ inputRange: [0, 1],
382
+ outputRange: [-containerWidth, containerWidth]
383
+ });
369
384
  return /* @__PURE__ */ React23.createElement(
370
- Animated.View,
385
+ View,
371
386
  {
372
387
  style: [
373
388
  styles6.base,
374
- { width, height, borderRadius, backgroundColor: colors.muted, opacity },
389
+ { width, height, borderRadius, backgroundColor: colors.muted },
375
390
  style
376
- ]
377
- }
391
+ ],
392
+ onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width)
393
+ },
394
+ /* @__PURE__ */ React23.createElement(Animated.View, { style: [StyleSheet.absoluteFill, { transform: [{ translateX }] }] }, /* @__PURE__ */ React23.createElement(
395
+ LinearGradient,
396
+ {
397
+ colors: ["transparent", shimmerHighlight, "transparent"],
398
+ start: { x: 0, y: 0 },
399
+ end: { x: 1, y: 0 },
400
+ style: StyleSheet.absoluteFill
401
+ }
402
+ ))
378
403
  );
379
404
  }
380
405
  var styles6 = StyleSheet.create({
381
- base: {}
406
+ base: {
407
+ overflow: "hidden"
408
+ }
382
409
  });
383
410
  var sizeMap2 = {
384
411
  sm: 24,
@@ -411,7 +438,13 @@ function Avatar({ src, fallback, size = "md", style }) {
411
438
  style: { width: dimension, height: dimension },
412
439
  onError: () => setImageError(true)
413
440
  }
414
- ) : /* @__PURE__ */ React23.createElement(Text, { style: [styles7.fallback, { color: colors.mutedForeground, fontSize: fontSizeMap[size] }] }, fallback?.slice(0, 2).toUpperCase() ?? "?"));
441
+ ) : /* @__PURE__ */ React23.createElement(
442
+ Text,
443
+ {
444
+ style: [styles7.fallback, { color: colors.mutedForeground, fontSize: fontSizeMap[size] }]
445
+ },
446
+ fallback?.slice(0, 2).toUpperCase() ?? "?"
447
+ ));
415
448
  }
416
449
  var styles7 = StyleSheet.create({
417
450
  base: {
@@ -477,10 +510,7 @@ function Progress({ value = 0, max = 100, style }) {
477
510
  /* @__PURE__ */ React23.createElement(
478
511
  Animated.View,
479
512
  {
480
- style: [
481
- styles9.indicator,
482
- { width: animatedWidth, backgroundColor: colors.primary }
483
- ]
513
+ style: [styles9.indicator, { width: animatedWidth, backgroundColor: colors.primary }]
484
514
  }
485
515
  )
486
516
  );
@@ -537,10 +567,20 @@ var styles10 = StyleSheet.create({
537
567
  marginTop: 8
538
568
  }
539
569
  });
540
- function Textarea({ label, error, hint, rows = 4, style, onFocus, onBlur, ...props }) {
570
+ function Textarea({
571
+ label,
572
+ error,
573
+ hint,
574
+ rows = 4,
575
+ containerStyle,
576
+ style,
577
+ onFocus,
578
+ onBlur,
579
+ ...props
580
+ }) {
541
581
  const { colors } = useTheme();
542
582
  const [focused, setFocused] = useState(false);
543
- return /* @__PURE__ */ React23.createElement(View, { style: styles11.container }, label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles11.label, { color: colors.foreground }] }, label) : null, /* @__PURE__ */ React23.createElement(
583
+ return /* @__PURE__ */ React23.createElement(View, { style: [styles11.container, containerStyle] }, label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles11.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React23.createElement(
544
584
  TextInput,
545
585
  {
546
586
  multiline: true,
@@ -568,7 +608,7 @@ function Textarea({ label, error, hint, rows = 4, style, onFocus, onBlur, ...pro
568
608
  allowFontScaling: true,
569
609
  ...props
570
610
  }
571
- ), error ? /* @__PURE__ */ React23.createElement(Text, { style: [styles11.helperText, { color: colors.destructive }] }, error) : null, !error && hint ? /* @__PURE__ */ React23.createElement(Text, { style: [styles11.helperText, { color: colors.mutedForeground }] }, hint) : null);
611
+ ), error ? /* @__PURE__ */ React23.createElement(Text, { style: [styles11.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null, !error && hint ? /* @__PURE__ */ React23.createElement(Text, { style: [styles11.helperText, { color: colors.mutedForeground }], allowFontScaling: true }, hint) : null);
572
612
  }
573
613
  var styles11 = StyleSheet.create({
574
614
  container: {
@@ -590,18 +630,35 @@ var styles11 = StyleSheet.create({
590
630
  fontSize: 12
591
631
  }
592
632
  });
593
- function Checkbox({ checked = false, onCheckedChange, label, disabled, style }) {
633
+ function Checkbox({
634
+ checked = false,
635
+ onCheckedChange,
636
+ label,
637
+ disabled,
638
+ style
639
+ }) {
594
640
  const { colors } = useTheme();
595
- return /* @__PURE__ */ React23.createElement(
641
+ const scale = useRef(new Animated.Value(1)).current;
642
+ const handlePressIn = () => {
643
+ if (disabled) return;
644
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: true, speed: 40, bounciness: 0 }).start();
645
+ };
646
+ const handlePressOut = () => {
647
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start();
648
+ };
649
+ return /* @__PURE__ */ React23.createElement(Animated.View, { style: { transform: [{ scale }] } }, /* @__PURE__ */ React23.createElement(
596
650
  TouchableOpacity,
597
651
  {
598
652
  style: [styles12.row, style],
599
653
  onPress: () => {
600
- Haptics10.selectionAsync();
654
+ Haptics11.selectionAsync();
601
655
  onCheckedChange?.(!checked);
602
656
  },
657
+ onPressIn: handlePressIn,
658
+ onPressOut: handlePressOut,
603
659
  disabled,
604
- activeOpacity: 0.7
660
+ activeOpacity: 1,
661
+ touchSoundDisabled: true
605
662
  },
606
663
  /* @__PURE__ */ React23.createElement(
607
664
  View,
@@ -617,8 +674,14 @@ function Checkbox({ checked = false, onCheckedChange, label, disabled, style })
617
674
  },
618
675
  checked ? /* @__PURE__ */ React23.createElement(View, { style: [styles12.checkmark, { borderColor: colors.primaryForeground }] }) : null
619
676
  ),
620
- label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles12.label, { color: disabled ? colors.mutedForeground : colors.foreground }] }, label) : null
621
- );
677
+ label ? /* @__PURE__ */ React23.createElement(
678
+ Text,
679
+ {
680
+ style: [styles12.label, { color: disabled ? colors.mutedForeground : colors.foreground }]
681
+ },
682
+ label
683
+ ) : null
684
+ ));
622
685
  }
623
686
  var styles12 = StyleSheet.create({
624
687
  row: {
@@ -677,11 +740,12 @@ function Switch({ checked = false, onCheckedChange, disabled, style }) {
677
740
  TouchableOpacity,
678
741
  {
679
742
  onPress: () => {
680
- Haptics10.selectionAsync();
743
+ Haptics11.selectionAsync();
681
744
  onCheckedChange?.(!checked);
682
745
  },
683
746
  disabled,
684
747
  activeOpacity: 0.8,
748
+ touchSoundDisabled: true,
685
749
  style: [styles13.wrapper, { opacity: disabled ? 0.45 : 1 }, style]
686
750
  },
687
751
  /* @__PURE__ */ React23.createElement(Animated.View, { style: [styles13.track, { backgroundColor: trackColor }] }, /* @__PURE__ */ React23.createElement(
@@ -732,29 +796,34 @@ function Toggle({
732
796
  ...props
733
797
  }) {
734
798
  const { colors } = useTheme();
799
+ const scale = useRef(new Animated.Value(1)).current;
800
+ const handlePressIn = () => {
801
+ if (disabled) return;
802
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: true, speed: 40, bounciness: 0 }).start();
803
+ };
804
+ const handlePressOut = () => {
805
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start();
806
+ };
735
807
  const containerStyle = pressed ? { backgroundColor: colors.accent } : variant === "outline" ? { backgroundColor: "transparent", borderWidth: 1, borderColor: colors.border } : { backgroundColor: "transparent" };
736
808
  const textColor = pressed ? colors.accentForeground : colors.foreground;
737
- return /* @__PURE__ */ React23.createElement(
809
+ return /* @__PURE__ */ React23.createElement(Animated.View, { style: { transform: [{ scale }] } }, /* @__PURE__ */ React23.createElement(
738
810
  TouchableOpacity,
739
811
  {
740
- style: [
741
- styles14.base,
742
- containerStyle,
743
- sizeStyles[size],
744
- disabled && styles14.disabled,
745
- style
746
- ],
812
+ style: [styles14.base, containerStyle, sizeStyles[size], disabled && styles14.disabled, style],
747
813
  onPress: () => {
748
- Haptics10.selectionAsync();
814
+ Haptics11.selectionAsync();
749
815
  onPressedChange?.(!pressed);
750
816
  },
817
+ onPressIn: handlePressIn,
818
+ onPressOut: handlePressOut,
751
819
  disabled,
752
- activeOpacity: 0.7,
820
+ activeOpacity: 1,
821
+ touchSoundDisabled: true,
753
822
  ...props
754
823
  },
755
824
  icon,
756
825
  label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles14.label, { color: textColor }] }, label) : null
757
- );
826
+ ));
758
827
  }
759
828
  var styles14 = StyleSheet.create({
760
829
  base: {
@@ -772,6 +841,61 @@ var styles14 = StyleSheet.create({
772
841
  fontWeight: "500"
773
842
  }
774
843
  });
844
+ function RadioItem({
845
+ option,
846
+ selected,
847
+ onSelect
848
+ }) {
849
+ const { colors } = useTheme();
850
+ const scale = useRef(new Animated.Value(1)).current;
851
+ const handlePressIn = () => {
852
+ if (option.disabled) return;
853
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: true, speed: 40, bounciness: 0 }).start();
854
+ };
855
+ const handlePressOut = () => {
856
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start();
857
+ };
858
+ return /* @__PURE__ */ React23.createElement(Animated.View, { style: { transform: [{ scale }] } }, /* @__PURE__ */ React23.createElement(
859
+ TouchableOpacity,
860
+ {
861
+ style: styles15.row,
862
+ onPress: () => {
863
+ if (!option.disabled) {
864
+ Haptics11.selectionAsync();
865
+ onSelect();
866
+ }
867
+ },
868
+ onPressIn: handlePressIn,
869
+ onPressOut: handlePressOut,
870
+ activeOpacity: 1,
871
+ touchSoundDisabled: true,
872
+ disabled: option.disabled
873
+ },
874
+ /* @__PURE__ */ React23.createElement(
875
+ View,
876
+ {
877
+ style: [
878
+ styles15.radio,
879
+ {
880
+ borderColor: selected ? colors.primary : colors.border,
881
+ opacity: option.disabled ? 0.45 : 1
882
+ }
883
+ ]
884
+ },
885
+ selected ? /* @__PURE__ */ React23.createElement(View, { style: [styles15.dot, { backgroundColor: colors.primary }] }) : null
886
+ ),
887
+ /* @__PURE__ */ React23.createElement(
888
+ Text,
889
+ {
890
+ style: [
891
+ styles15.label,
892
+ { color: option.disabled ? colors.mutedForeground : colors.foreground }
893
+ ]
894
+ },
895
+ option.label
896
+ )
897
+ ));
898
+ }
775
899
  function RadioGroup({
776
900
  options,
777
901
  value,
@@ -779,58 +903,15 @@ function RadioGroup({
779
903
  orientation = "vertical",
780
904
  style
781
905
  }) {
782
- const { colors } = useTheme();
783
- return /* @__PURE__ */ React23.createElement(
784
- View,
906
+ return /* @__PURE__ */ React23.createElement(View, { style: [styles15.container, orientation === "horizontal" && styles15.horizontal, style] }, options.map((option) => /* @__PURE__ */ React23.createElement(
907
+ RadioItem,
785
908
  {
786
- style: [
787
- styles15.container,
788
- orientation === "horizontal" && styles15.horizontal,
789
- style
790
- ]
791
- },
792
- options.map((option) => {
793
- const selected = option.value === value;
794
- return /* @__PURE__ */ React23.createElement(
795
- TouchableOpacity,
796
- {
797
- key: option.value,
798
- style: styles15.row,
799
- onPress: () => {
800
- if (!option.disabled) {
801
- Haptics10.selectionAsync();
802
- onValueChange?.(option.value);
803
- }
804
- },
805
- activeOpacity: 0.7,
806
- disabled: option.disabled
807
- },
808
- /* @__PURE__ */ React23.createElement(
809
- View,
810
- {
811
- style: [
812
- styles15.radio,
813
- {
814
- borderColor: selected ? colors.primary : colors.border,
815
- opacity: option.disabled ? 0.45 : 1
816
- }
817
- ]
818
- },
819
- selected ? /* @__PURE__ */ React23.createElement(View, { style: [styles15.dot, { backgroundColor: colors.primary }] }) : null
820
- ),
821
- /* @__PURE__ */ React23.createElement(
822
- Text,
823
- {
824
- style: [
825
- styles15.label,
826
- { color: option.disabled ? colors.mutedForeground : colors.foreground }
827
- ]
828
- },
829
- option.label
830
- )
831
- );
832
- })
833
- );
909
+ key: option.value,
910
+ option,
911
+ selected: option.value === value,
912
+ onSelect: () => onValueChange?.(option.value)
913
+ }
914
+ )));
834
915
  }
835
916
  var styles15 = StyleSheet.create({
836
917
  container: {
@@ -863,6 +944,44 @@ var styles15 = StyleSheet.create({
863
944
  lineHeight: 20
864
945
  }
865
946
  });
947
+ function TabTrigger({
948
+ tab,
949
+ isActive,
950
+ onPress,
951
+ onLayout
952
+ }) {
953
+ const { colors } = useTheme();
954
+ const scale = useRef(new Animated.Value(1)).current;
955
+ const handlePressIn = () => {
956
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: true, speed: 40, bounciness: 0 }).start();
957
+ };
958
+ const handlePressOut = () => {
959
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start();
960
+ };
961
+ return /* @__PURE__ */ React23.createElement(
962
+ TouchableOpacity,
963
+ {
964
+ style: styles16.trigger,
965
+ onPress,
966
+ onPressIn: handlePressIn,
967
+ onPressOut: handlePressOut,
968
+ onLayout,
969
+ activeOpacity: 1,
970
+ touchSoundDisabled: true
971
+ },
972
+ /* @__PURE__ */ React23.createElement(Animated.View, { style: { transform: [{ scale }] } }, /* @__PURE__ */ React23.createElement(
973
+ Text,
974
+ {
975
+ style: [
976
+ styles16.triggerLabel,
977
+ { color: isActive ? colors.foreground : colors.mutedForeground },
978
+ isActive && styles16.activeTriggerLabel
979
+ ]
980
+ },
981
+ tab.label
982
+ ))
983
+ );
984
+ }
866
985
  function Tabs({ tabs, value, onValueChange, children, style }) {
867
986
  const [internal, setInternal] = useState(tabs[0]?.value ?? "");
868
987
  const { colors } = useTheme();
@@ -876,8 +995,18 @@ function Tabs({ tabs, value, onValueChange, children, style }) {
876
995
  if (!layout) return;
877
996
  if (animate) {
878
997
  Animated.parallel([
879
- Animated.spring(pillX, { toValue: layout.x, useNativeDriver: false, speed: 20, bounciness: 0 }),
880
- Animated.spring(pillWidth, { toValue: layout.width, useNativeDriver: false, speed: 20, bounciness: 0 })
998
+ Animated.spring(pillX, {
999
+ toValue: layout.x,
1000
+ useNativeDriver: false,
1001
+ speed: 20,
1002
+ bounciness: 0
1003
+ }),
1004
+ Animated.spring(pillWidth, {
1005
+ toValue: layout.width,
1006
+ useNativeDriver: false,
1007
+ speed: 20,
1008
+ bounciness: 0
1009
+ })
881
1010
  ]).start();
882
1011
  } else {
883
1012
  pillX.setValue(layout.x);
@@ -890,6 +1019,7 @@ function Tabs({ tabs, value, onValueChange, children, style }) {
890
1019
  }
891
1020
  }, [active]);
892
1021
  const handlePress = (v) => {
1022
+ Haptics11.selectionAsync();
893
1023
  if (!value) setInternal(v);
894
1024
  onValueChange?.(v);
895
1025
  };
@@ -914,37 +1044,23 @@ function Tabs({ tabs, value, onValueChange, children, style }) {
914
1044
  }
915
1045
  ]
916
1046
  }
917
- ), tabs.map((tab) => {
918
- const isActive = tab.value === active;
919
- return /* @__PURE__ */ React23.createElement(
920
- TouchableOpacity,
921
- {
922
- key: tab.value,
923
- style: styles16.trigger,
924
- onPress: () => handlePress(tab.value),
925
- activeOpacity: 0.7,
926
- onLayout: (e) => {
927
- const { x, width } = e.nativeEvent.layout;
928
- tabLayouts.current[tab.value] = { x, width };
929
- if (tab.value === active) {
930
- animatePill(tab.value, false);
931
- initialised.current = true;
932
- }
1047
+ ), tabs.map((tab) => /* @__PURE__ */ React23.createElement(
1048
+ TabTrigger,
1049
+ {
1050
+ key: tab.value,
1051
+ tab,
1052
+ isActive: tab.value === active,
1053
+ onPress: () => handlePress(tab.value),
1054
+ onLayout: (e) => {
1055
+ const { x, width } = e.nativeEvent.layout;
1056
+ tabLayouts.current[tab.value] = { x, width };
1057
+ if (tab.value === active) {
1058
+ animatePill(tab.value, false);
1059
+ initialised.current = true;
933
1060
  }
934
- },
935
- /* @__PURE__ */ React23.createElement(
936
- Text,
937
- {
938
- style: [
939
- styles16.triggerLabel,
940
- { color: isActive ? colors.foreground : colors.mutedForeground },
941
- isActive && styles16.activeTriggerLabel
942
- ]
943
- },
944
- tab.label
945
- )
946
- );
947
- })), children);
1061
+ }
1062
+ }
1063
+ ))), children);
948
1064
  }
949
1065
  function TabsContent({ value, activeValue, children, style }) {
950
1066
  if (value !== activeValue) return null;
@@ -964,6 +1080,7 @@ var styles16 = StyleSheet.create({
964
1080
  paddingHorizontal: 12,
965
1081
  borderRadius: 6,
966
1082
  alignItems: "center",
1083
+ justifyContent: "center",
967
1084
  zIndex: 1
968
1085
  },
969
1086
  triggerLabel: {
@@ -980,24 +1097,14 @@ function AccordionItemComponent({
980
1097
  onToggle
981
1098
  }) {
982
1099
  const { colors } = useTheme();
983
- const animatedHeight = useRef(new Animated.Value(0)).current;
984
- const animatedRotation = useRef(new Animated.Value(0)).current;
1100
+ const animatedHeight = useSharedValue(0);
1101
+ const animatedRotation = useSharedValue(0);
985
1102
  const contentHeight = useRef(0);
1103
+ const scale = useRef(new Animated.Value(1)).current;
986
1104
  const toggle = (open) => {
987
- Animated.parallel([
988
- Animated.timing(animatedHeight, {
989
- toValue: open ? contentHeight.current : 0,
990
- duration: 220,
991
- easing: open ? Easing.out(Easing.ease) : Easing.in(Easing.ease),
992
- useNativeDriver: false
993
- }),
994
- Animated.timing(animatedRotation, {
995
- toValue: open ? 1 : 0,
996
- duration: 220,
997
- easing: open ? Easing.out(Easing.ease) : Easing.in(Easing.ease),
998
- useNativeDriver: true
999
- })
1000
- ]).start();
1105
+ const easing = open ? Easing.out(Easing.ease) : Easing.in(Easing.ease);
1106
+ animatedHeight.value = withTiming(open ? contentHeight.current : 0, { duration: 220, easing });
1107
+ animatedRotation.value = withTiming(open ? 1 : 0, { duration: 220, easing });
1001
1108
  };
1002
1109
  React23.useEffect(() => {
1003
1110
  toggle(isOpen);
@@ -1005,32 +1112,44 @@ function AccordionItemComponent({
1005
1112
  const onLayout = (e) => {
1006
1113
  if (contentHeight.current === 0) {
1007
1114
  contentHeight.current = e.nativeEvent.layout.height;
1008
- if (isOpen) animatedHeight.setValue(contentHeight.current);
1115
+ if (isOpen) animatedHeight.value = contentHeight.current;
1009
1116
  }
1010
1117
  };
1011
- const rotate = animatedRotation.interpolate({
1012
- inputRange: [0, 1],
1013
- outputRange: ["0deg", "180deg"]
1014
- });
1015
- return /* @__PURE__ */ React23.createElement(View, { style: [styles17.item, { borderBottomColor: colors.border }] }, /* @__PURE__ */ React23.createElement(
1118
+ const heightStyle = useAnimatedStyle(() => ({
1119
+ height: animatedHeight.value,
1120
+ overflow: "hidden"
1121
+ }));
1122
+ const rotationStyle = useAnimatedStyle(() => ({
1123
+ transform: [{ rotate: `${animatedRotation.value * 180}deg` }]
1124
+ }));
1125
+ const handlePressIn = () => {
1126
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: true, speed: 40, bounciness: 0 }).start();
1127
+ };
1128
+ const handlePressOut = () => {
1129
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start();
1130
+ };
1131
+ return /* @__PURE__ */ React23.createElement(View, { style: [styles17.item, { borderBottomColor: colors.border }] }, /* @__PURE__ */ React23.createElement(Animated.View, { style: { transform: [{ scale }] } }, /* @__PURE__ */ React23.createElement(
1016
1132
  TouchableOpacity,
1017
1133
  {
1018
1134
  style: styles17.trigger,
1019
1135
  onPress: () => {
1020
- Haptics10.selectionAsync();
1136
+ Haptics11.selectionAsync();
1021
1137
  onToggle();
1022
1138
  },
1023
- activeOpacity: 0.7
1139
+ onPressIn: handlePressIn,
1140
+ onPressOut: handlePressOut,
1141
+ activeOpacity: 1,
1142
+ touchSoundDisabled: true
1024
1143
  },
1025
1144
  /* @__PURE__ */ React23.createElement(Text, { style: [styles17.triggerText, { color: colors.foreground }] }, item.trigger),
1026
1145
  /* @__PURE__ */ React23.createElement(
1027
- Animated.Text,
1146
+ ReanimatedAnimated.Text,
1028
1147
  {
1029
- style: [styles17.chevron, { color: colors.foreground, transform: [{ rotate }] }]
1148
+ style: [styles17.chevron, { color: colors.foreground }, rotationStyle]
1030
1149
  },
1031
1150
  "\u25BE"
1032
1151
  )
1033
- ), /* @__PURE__ */ React23.createElement(Animated.View, { style: [styles17.contentWrapper, { height: animatedHeight, overflow: "hidden" }] }, /* @__PURE__ */ React23.createElement(View, { style: styles17.content, onLayout }, item.content)));
1152
+ )), /* @__PURE__ */ React23.createElement(ReanimatedAnimated.View, { style: heightStyle }, /* @__PURE__ */ React23.createElement(View, { style: styles17.content, onLayout }, item.content)));
1034
1153
  }
1035
1154
  function Accordion({ items, type = "single", defaultValue, style }) {
1036
1155
  const [openValues, setOpenValues] = useState(() => {
@@ -1075,7 +1194,6 @@ var styles17 = StyleSheet.create({
1075
1194
  fontSize: 16,
1076
1195
  marginLeft: 8
1077
1196
  },
1078
- contentWrapper: {},
1079
1197
  content: {
1080
1198
  paddingBottom: 16,
1081
1199
  position: "absolute",
@@ -1122,7 +1240,7 @@ function Slider({
1122
1240
  const newValue = xToValue(x);
1123
1241
  if (newValue !== lastSteppedValue.current) {
1124
1242
  lastSteppedValue.current = newValue;
1125
- Haptics10.selectionAsync();
1243
+ Haptics11.selectionAsync();
1126
1244
  }
1127
1245
  setInternalValue(newValue);
1128
1246
  onValueChange?.(newValue);
@@ -1149,10 +1267,7 @@ function Slider({
1149
1267
  /* @__PURE__ */ React23.createElement(View, { style: [styles18.track, { backgroundColor: colors.muted }] }, /* @__PURE__ */ React23.createElement(
1150
1268
  View,
1151
1269
  {
1152
- style: [
1153
- styles18.range,
1154
- { width: `${percent}%`, backgroundColor: colors.primary }
1155
- ]
1270
+ style: [styles18.range, { width: `${percent}%`, backgroundColor: colors.primary }]
1156
1271
  }
1157
1272
  )),
1158
1273
  /* @__PURE__ */ React23.createElement(
@@ -1217,7 +1332,7 @@ function Sheet({
1217
1332
  const ref = useRef(null);
1218
1333
  useEffect(() => {
1219
1334
  if (open) {
1220
- Haptics10.impactAsync(Haptics10.ImpactFeedbackStyle.Light);
1335
+ Haptics11.impactAsync(Haptics11.ImpactFeedbackStyle.Light);
1221
1336
  ref.current?.present();
1222
1337
  } else {
1223
1338
  ref.current?.dismiss();
@@ -1284,26 +1399,49 @@ function Select({
1284
1399
  style
1285
1400
  }) {
1286
1401
  const { colors } = useTheme();
1287
- const [open, setOpen] = useState(false);
1402
+ const bottomSheetRef = useRef(null);
1403
+ const scale = useRef(new Animated.Value(1)).current;
1288
1404
  const selected = options.find((o) => o.value === value);
1289
- return /* @__PURE__ */ React23.createElement(View, { style: [styles20.container, style] }, label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles20.label, { color: colors.foreground }] }, label) : null, /* @__PURE__ */ React23.createElement(
1405
+ const handlePressIn = () => {
1406
+ if (disabled) return;
1407
+ Animated.spring(scale, { toValue: 0.95, useNativeDriver: true, speed: 40, bounciness: 0 }).start();
1408
+ };
1409
+ const handlePressOut = () => {
1410
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 40, bounciness: 4 }).start();
1411
+ };
1412
+ const handleOpen = () => {
1413
+ if (!disabled) {
1414
+ Haptics11.selectionAsync();
1415
+ bottomSheetRef.current?.present();
1416
+ }
1417
+ };
1418
+ const renderBackdrop = useCallback(
1419
+ (props) => /* @__PURE__ */ React23.createElement(
1420
+ BottomSheetBackdrop,
1421
+ {
1422
+ ...props,
1423
+ disappearsOnIndex: -1,
1424
+ appearsOnIndex: 0,
1425
+ pressBehavior: "close"
1426
+ }
1427
+ ),
1428
+ []
1429
+ );
1430
+ return /* @__PURE__ */ React23.createElement(View, { style: [styles20.container, style] }, label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles20.label, { color: colors.foreground }] }, label) : null, /* @__PURE__ */ React23.createElement(Animated.View, { style: { transform: [{ scale }], opacity: disabled ? 0.45 : 1 } }, /* @__PURE__ */ React23.createElement(
1290
1431
  TouchableOpacity,
1291
1432
  {
1292
1433
  style: [
1293
1434
  styles20.trigger,
1294
1435
  {
1295
1436
  borderColor: error ? colors.destructive : colors.border,
1296
- backgroundColor: colors.background,
1297
- opacity: disabled ? 0.45 : 1
1437
+ backgroundColor: colors.background
1298
1438
  }
1299
1439
  ],
1300
- onPress: () => {
1301
- if (!disabled) {
1302
- Haptics10.selectionAsync();
1303
- setOpen(true);
1304
- }
1305
- },
1306
- activeOpacity: 0.7
1440
+ onPress: handleOpen,
1441
+ onPressIn: handlePressIn,
1442
+ onPressOut: handlePressOut,
1443
+ activeOpacity: 1,
1444
+ touchSoundDisabled: true
1307
1445
  },
1308
1446
  /* @__PURE__ */ React23.createElement(
1309
1447
  Text,
@@ -1317,46 +1455,52 @@ function Select({
1317
1455
  selected?.label ?? placeholder
1318
1456
  ),
1319
1457
  /* @__PURE__ */ React23.createElement(Text, { style: [styles20.chevron, { color: colors.mutedForeground }] }, "\u25BE")
1320
- ), error ? /* @__PURE__ */ React23.createElement(Text, { style: [styles20.helperText, { color: colors.destructive }] }, error) : null, /* @__PURE__ */ React23.createElement(Modal, { transparent: true, visible: open, onRequestClose: () => setOpen(false), animationType: "fade" }, /* @__PURE__ */ React23.createElement(TouchableOpacity, { style: styles20.overlay, onPress: () => setOpen(false), activeOpacity: 1 }, /* @__PURE__ */ React23.createElement(View, { style: [styles20.list, { backgroundColor: colors.card, borderColor: colors.border }] }, /* @__PURE__ */ React23.createElement(
1321
- FlatList,
1458
+ )), error ? /* @__PURE__ */ React23.createElement(Text, { style: [styles20.helperText, { color: colors.destructive }] }, error) : null, /* @__PURE__ */ React23.createElement(
1459
+ BottomSheetModal,
1322
1460
  {
1323
- data: options,
1324
- keyExtractor: (item) => item.value,
1325
- renderItem: ({ item }) => {
1326
- const isSelected = item.value === value;
1327
- return /* @__PURE__ */ React23.createElement(
1328
- TouchableOpacity,
1461
+ ref: bottomSheetRef,
1462
+ enableDynamicSizing: true,
1463
+ enablePanDownToClose: true,
1464
+ backdropComponent: renderBackdrop,
1465
+ backgroundStyle: [styles20.sheetBackground, { backgroundColor: colors.card }],
1466
+ handleIndicatorStyle: [styles20.sheetHandle, { backgroundColor: colors.border }]
1467
+ },
1468
+ /* @__PURE__ */ React23.createElement(BottomSheetView, { style: styles20.sheetContent }, label ? /* @__PURE__ */ React23.createElement(Text, { style: [styles20.sheetTitle, { color: colors.foreground }] }, label) : null, options.map((item) => {
1469
+ const isSelected = item.value === value;
1470
+ return /* @__PURE__ */ React23.createElement(
1471
+ TouchableOpacity,
1472
+ {
1473
+ key: item.value,
1474
+ style: [
1475
+ styles20.option,
1476
+ isSelected && { backgroundColor: colors.accent },
1477
+ item.disabled && styles20.disabledOption
1478
+ ],
1479
+ onPress: () => {
1480
+ if (!item.disabled) {
1481
+ Haptics11.selectionAsync();
1482
+ onValueChange?.(item.value);
1483
+ bottomSheetRef.current?.dismiss();
1484
+ }
1485
+ },
1486
+ activeOpacity: 0.7,
1487
+ touchSoundDisabled: true
1488
+ },
1489
+ /* @__PURE__ */ React23.createElement(
1490
+ Text,
1329
1491
  {
1330
1492
  style: [
1331
- styles20.option,
1332
- isSelected && { backgroundColor: colors.accent },
1333
- item.disabled && styles20.disabledOption
1334
- ],
1335
- onPress: () => {
1336
- if (!item.disabled) {
1337
- Haptics10.selectionAsync();
1338
- onValueChange?.(item.value);
1339
- setOpen(false);
1340
- }
1341
- },
1342
- activeOpacity: 0.7
1493
+ styles20.optionText,
1494
+ { color: item.disabled ? colors.mutedForeground : colors.foreground },
1495
+ isSelected && { fontWeight: "500" }
1496
+ ]
1343
1497
  },
1344
- /* @__PURE__ */ React23.createElement(
1345
- Text,
1346
- {
1347
- style: [
1348
- styles20.optionText,
1349
- { color: item.disabled ? colors.mutedForeground : colors.foreground },
1350
- isSelected && { fontWeight: "500" }
1351
- ]
1352
- },
1353
- item.label
1354
- ),
1355
- isSelected ? /* @__PURE__ */ React23.createElement(Text, { style: [styles20.checkmark, { color: colors.primary }] }, "\u2713") : null
1356
- );
1357
- }
1358
- }
1359
- )))));
1498
+ item.label
1499
+ ),
1500
+ isSelected ? /* @__PURE__ */ React23.createElement(Text, { style: [styles20.checkmark, { color: colors.primary }] }, "\u2713") : null
1501
+ );
1502
+ }))
1503
+ ));
1360
1504
  }
1361
1505
  var styles20 = StyleSheet.create({
1362
1506
  container: {
@@ -1387,34 +1531,44 @@ var styles20 = StyleSheet.create({
1387
1531
  helperText: {
1388
1532
  fontSize: 12
1389
1533
  },
1390
- overlay: {
1391
- flex: 1,
1392
- backgroundColor: "rgba(0,0,0,0.3)",
1393
- justifyContent: "center",
1394
- padding: 24
1534
+ sheetBackground: {
1535
+ borderTopLeftRadius: 16,
1536
+ borderTopRightRadius: 16
1395
1537
  },
1396
- list: {
1397
- borderRadius: 12,
1398
- borderWidth: 1,
1399
- maxHeight: 300,
1400
- overflow: "hidden"
1538
+ sheetHandle: {
1539
+ width: 36,
1540
+ height: 4,
1541
+ borderRadius: 2
1542
+ },
1543
+ sheetContent: {
1544
+ paddingHorizontal: 16,
1545
+ paddingBottom: 32
1546
+ },
1547
+ sheetTitle: {
1548
+ fontSize: 16,
1549
+ fontWeight: "600",
1550
+ paddingVertical: 12,
1551
+ paddingHorizontal: 4
1401
1552
  },
1402
1553
  option: {
1403
1554
  flexDirection: "row",
1404
1555
  alignItems: "center",
1405
1556
  justifyContent: "space-between",
1406
1557
  paddingHorizontal: 12,
1407
- paddingVertical: 10
1558
+ paddingVertical: 14,
1559
+ borderRadius: 8
1408
1560
  },
1409
1561
  optionText: {
1410
- fontSize: 15
1562
+ fontSize: 15,
1563
+ flex: 1
1411
1564
  },
1412
1565
  disabledOption: {
1413
1566
  opacity: 0.45
1414
1567
  },
1415
1568
  checkmark: {
1416
1569
  fontSize: 14,
1417
- fontWeight: "600"
1570
+ fontWeight: "600",
1571
+ marginLeft: 8
1418
1572
  }
1419
1573
  });
1420
1574
  var ToastContext = createContext({
@@ -1426,41 +1580,53 @@ var ToastContext = createContext({
1426
1580
  function useToast() {
1427
1581
  return useContext(ToastContext);
1428
1582
  }
1583
+ var SWIPE_THRESHOLD = 80;
1584
+ var VELOCITY_THRESHOLD = 800;
1429
1585
  function ToastNotification({ item, onDismiss }) {
1430
1586
  const { colors } = useTheme();
1431
- const translateY = useRef(new Animated.Value(-80)).current;
1432
- const opacity = useRef(new Animated.Value(0)).current;
1587
+ const translateY = useSharedValue(-80);
1588
+ const translateX = useSharedValue(0);
1589
+ const opacity = useSharedValue(0);
1433
1590
  useEffect(() => {
1434
- Animated.parallel([
1435
- Animated.spring(translateY, { toValue: 0, useNativeDriver: true, bounciness: 2 }),
1436
- Animated.timing(opacity, { toValue: 1, duration: 200, useNativeDriver: true })
1437
- ]).start();
1591
+ translateY.value = withTiming(0, { duration: 120, easing: Easing.out(Easing.exp) });
1592
+ opacity.value = withTiming(1, { duration: 100 });
1438
1593
  const timer = setTimeout(() => {
1439
- Animated.parallel([
1440
- Animated.timing(translateY, { toValue: -80, duration: 200, useNativeDriver: true }),
1441
- Animated.timing(opacity, { toValue: 0, duration: 200, useNativeDriver: true })
1442
- ]).start(onDismiss);
1594
+ translateY.value = withTiming(-80, { duration: 200 });
1595
+ opacity.value = withTiming(0, { duration: 200 }, (done) => {
1596
+ if (done) scheduleOnRN(onDismiss);
1597
+ });
1443
1598
  }, item.duration ?? 3e3);
1444
1599
  return () => clearTimeout(timer);
1445
1600
  }, []);
1601
+ const panGesture = Gesture.Pan().onUpdate((e) => {
1602
+ translateX.value = e.translationX;
1603
+ }).onEnd((e) => {
1604
+ const shouldDismiss = Math.abs(translateX.value) > SWIPE_THRESHOLD || Math.abs(e.velocityX) > VELOCITY_THRESHOLD;
1605
+ if (shouldDismiss) {
1606
+ const direction = translateX.value > 0 ? 1 : -1;
1607
+ translateX.value = withTiming(direction * 500, { duration: 200 }, (done) => {
1608
+ if (done) scheduleOnRN(onDismiss);
1609
+ });
1610
+ opacity.value = withTiming(0, { duration: 150 });
1611
+ } else {
1612
+ translateX.value = withSpring(0, { damping: 20, stiffness: 300 });
1613
+ }
1614
+ });
1615
+ const animatedStyle = useAnimatedStyle(() => ({
1616
+ opacity: opacity.value,
1617
+ transform: [{ translateY: translateY.value }, { translateX: translateX.value }]
1618
+ }));
1446
1619
  const bgColor = {
1447
1620
  default: colors.foreground,
1448
1621
  destructive: colors.destructive,
1449
- success: "#16a34a"
1622
+ success: colors.success
1450
1623
  }[item.variant ?? "default"];
1451
1624
  const textColor = {
1452
1625
  default: colors.background,
1453
1626
  destructive: colors.destructiveForeground,
1454
- success: "#ffffff"
1627
+ success: colors.successForeground
1455
1628
  }[item.variant ?? "default"];
1456
- return /* @__PURE__ */ React23.createElement(
1457
- Animated.View,
1458
- {
1459
- style: [styles21.toast, { backgroundColor: bgColor, opacity, transform: [{ translateY }] }]
1460
- },
1461
- /* @__PURE__ */ React23.createElement(View, { style: styles21.toastContent }, item.title ? /* @__PURE__ */ React23.createElement(Text, { style: [styles21.toastTitle, { color: textColor }] }, item.title) : null, item.description ? /* @__PURE__ */ React23.createElement(Text, { style: [styles21.toastDescription, { color: textColor, opacity: 0.85 }] }, item.description) : null),
1462
- /* @__PURE__ */ React23.createElement(TouchableOpacity, { onPress: onDismiss, style: styles21.dismissButton }, /* @__PURE__ */ React23.createElement(Text, { style: [styles21.dismissIcon, { color: textColor }] }, "\u2715"))
1463
- );
1629
+ return /* @__PURE__ */ React23.createElement(GestureDetector, { gesture: panGesture }, /* @__PURE__ */ React23.createElement(ReanimatedAnimated.View, { style: [styles21.toast, { backgroundColor: bgColor }, animatedStyle] }, /* @__PURE__ */ React23.createElement(View, { style: styles21.toastContent }, item.title ? /* @__PURE__ */ React23.createElement(Text, { style: [styles21.toastTitle, { color: textColor }] }, item.title) : null, item.description ? /* @__PURE__ */ React23.createElement(Text, { style: [styles21.toastDescription, { color: textColor, opacity: 0.85 }] }, item.description) : null), /* @__PURE__ */ React23.createElement(TouchableOpacity, { onPress: onDismiss, style: styles21.dismissButton, touchSoundDisabled: true }, /* @__PURE__ */ React23.createElement(Text, { style: [styles21.dismissIcon, { color: textColor }] }, "\u2715"))));
1464
1630
  }
1465
1631
  function ToastProvider({ children }) {
1466
1632
  const [toasts, setToasts] = useState([]);
@@ -1468,11 +1634,11 @@ function ToastProvider({ children }) {
1468
1634
  const toast = useCallback((item) => {
1469
1635
  const id = Math.random().toString(36).slice(2);
1470
1636
  if (item.variant === "success") {
1471
- Haptics10.notificationAsync(Haptics10.NotificationFeedbackType.Success);
1637
+ Haptics11.notificationAsync(Haptics11.NotificationFeedbackType.Success);
1472
1638
  } else if (item.variant === "destructive") {
1473
- Haptics10.notificationAsync(Haptics10.NotificationFeedbackType.Error);
1639
+ Haptics11.notificationAsync(Haptics11.NotificationFeedbackType.Error);
1474
1640
  } else {
1475
- Haptics10.impactAsync(Haptics10.ImpactFeedbackStyle.Light);
1641
+ Haptics11.impactAsync(Haptics11.ImpactFeedbackStyle.Light);
1476
1642
  }
1477
1643
  setToasts((prev) => [{ ...item, id }, ...prev].slice(0, 3));
1478
1644
  }, []);
@@ -1513,12 +1679,54 @@ var styles21 = StyleSheet.create({
1513
1679
  fontSize: 13
1514
1680
  },
1515
1681
  dismissButton: {
1516
- padding: 4,
1517
- marginLeft: 8
1682
+ padding: 12,
1683
+ marginLeft: 4
1518
1684
  },
1519
1685
  dismissIcon: {
1520
1686
  fontSize: 12
1521
1687
  }
1522
1688
  });
1689
+ function formatCurrency(raw, separator) {
1690
+ const digits = raw.replace(/\D/g, "");
1691
+ if (!digits) return "";
1692
+ return digits.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
1693
+ }
1694
+ function CurrencyInput({
1695
+ value,
1696
+ onChangeText,
1697
+ onChangeValue,
1698
+ prefix = "$",
1699
+ thousandsSeparator = ".",
1700
+ label,
1701
+ error,
1702
+ hint,
1703
+ placeholder,
1704
+ editable,
1705
+ containerStyle
1706
+ }) {
1707
+ const handleChange = (text) => {
1708
+ const withoutPrefix = prefix && text.startsWith(prefix) ? text.slice(prefix.length) : text;
1709
+ const formatted = formatCurrency(withoutPrefix, thousandsSeparator);
1710
+ const display = formatted ? `${prefix}${formatted}` : "";
1711
+ onChangeText?.(display);
1712
+ const separatorRegex = new RegExp(`\\${thousandsSeparator}`, "g");
1713
+ const raw = parseFloat(formatted.replace(separatorRegex, "") || "0");
1714
+ onChangeValue?.(isNaN(raw) ? 0 : raw);
1715
+ };
1716
+ return /* @__PURE__ */ React23.createElement(
1717
+ Input,
1718
+ {
1719
+ value,
1720
+ onChangeText: handleChange,
1721
+ keyboardType: "numeric",
1722
+ label,
1723
+ error,
1724
+ hint,
1725
+ placeholder: placeholder ?? `${prefix}0`,
1726
+ editable,
1727
+ containerStyle
1728
+ }
1729
+ );
1730
+ }
1523
1731
 
1524
- export { Accordion, Alert, Avatar, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, EmptyState, Input, Progress, RadioGroup, Select, Separator, Sheet, Skeleton, Slider, Spinner, Switch, Tabs, TabsContent, Text2 as Text, Textarea, ThemeProvider, ToastProvider, Toggle, defaultDark, defaultLight, useTheme, useToast };
1732
+ export { Accordion, Alert, Avatar, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CurrencyInput, EmptyState, Input, Progress, RadioGroup, Select, Separator, Sheet, Skeleton, Slider, Spinner, Switch, Tabs, TabsContent, Text2 as Text, Textarea, ThemeProvider, ToastProvider, Toggle, defaultDark, defaultLight, useTheme, useToast };