@retray-dev/ui-kit 1.7.0 → 1.8.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/COMPONENTS.md +181 -34
- package/README.md +6 -5
- package/dist/index.d.mts +73 -8
- package/dist/index.d.ts +73 -8
- package/dist/index.js +385 -16
- package/dist/index.mjs +380 -17
- package/package.json +1 -1
- package/src/components/Alert/Alert.tsx +22 -10
- package/src/components/Alert/index.ts +2 -2
- package/src/components/Button/Button.tsx +11 -4
- package/src/components/Chip/Chip.tsx +142 -0
- package/src/components/Chip/index.ts +2 -0
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +87 -0
- package/src/components/ConfirmDialog/index.ts +2 -0
- package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +4 -2
- package/src/components/EmptyState/EmptyState.tsx +40 -6
- package/src/components/LabelValue/LabelValue.tsx +47 -0
- package/src/components/LabelValue/index.ts +2 -0
- package/src/components/ListItem/ListItem.tsx +121 -0
- package/src/components/ListItem/index.ts +2 -0
- package/src/components/MonthPicker/MonthPicker.tsx +92 -0
- package/src/components/MonthPicker/index.ts +2 -0
- package/src/components/Switch/Switch.tsx +4 -2
- package/src/index.ts +5 -0
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React23, { createContext, useMemo, useContext, useRef, useState, useEffect, useCallback } from 'react';
|
|
2
|
-
import { StyleSheet, useColorScheme, Animated, TouchableOpacity, ActivityIndicator, Text, View, TextInput, Image, Easing, PanResponder } from 'react-native';
|
|
2
|
+
import { Platform, StyleSheet, useColorScheme, Animated, TouchableOpacity, ActivityIndicator, Text, View, TextInput, Image, Easing, PanResponder, Modal } from 'react-native';
|
|
3
3
|
import * as Haptics11 from 'expo-haptics';
|
|
4
4
|
import { LinearGradient } from 'expo-linear-gradient';
|
|
5
5
|
import ReanimatedAnimated, { useSharedValue, useAnimatedStyle, withTiming, Easing as Easing$1, withSpring } from 'react-native-reanimated';
|
|
@@ -73,6 +73,7 @@ function ThemeProvider({ children, theme, colorScheme = "system" }) {
|
|
|
73
73
|
function useTheme() {
|
|
74
74
|
return useContext(ThemeContext);
|
|
75
75
|
}
|
|
76
|
+
var nativeDriver = Platform.OS !== "web";
|
|
76
77
|
var containerSizeStyles = {
|
|
77
78
|
sm: { paddingHorizontal: 20, paddingVertical: 12 },
|
|
78
79
|
md: { paddingHorizontal: 24, paddingVertical: 16 },
|
|
@@ -103,13 +104,13 @@ function Button({
|
|
|
103
104
|
if (isDisabled) return;
|
|
104
105
|
Animated.spring(scale, {
|
|
105
106
|
toValue: 0.95,
|
|
106
|
-
useNativeDriver:
|
|
107
|
+
useNativeDriver: nativeDriver,
|
|
107
108
|
speed: 40,
|
|
108
109
|
bounciness: 0
|
|
109
110
|
}).start();
|
|
110
111
|
};
|
|
111
112
|
const handlePressOut = () => {
|
|
112
|
-
Animated.spring(scale, { toValue: 1, useNativeDriver:
|
|
113
|
+
Animated.spring(scale, { toValue: 1, useNativeDriver: nativeDriver, speed: 40, bounciness: 4 }).start();
|
|
113
114
|
};
|
|
114
115
|
const handlePress = (e) => {
|
|
115
116
|
Haptics11.impactAsync(Haptics11.ImpactFeedbackStyle.Light);
|
|
@@ -119,15 +120,17 @@ function Button({
|
|
|
119
120
|
primary: { backgroundColor: colors.primary },
|
|
120
121
|
secondary: { backgroundColor: colors.secondary },
|
|
121
122
|
outline: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.border },
|
|
122
|
-
ghost: { backgroundColor: "transparent" }
|
|
123
|
+
ghost: { backgroundColor: "transparent" },
|
|
124
|
+
destructive: { backgroundColor: colors.destructive }
|
|
123
125
|
}[variant];
|
|
124
126
|
const labelVariantStyle = {
|
|
125
127
|
primary: { color: colors.primaryForeground },
|
|
126
128
|
secondary: { color: colors.secondaryForeground },
|
|
127
129
|
outline: { color: colors.foreground },
|
|
128
|
-
ghost: { color: colors.foreground }
|
|
130
|
+
ghost: { color: colors.foreground },
|
|
131
|
+
destructive: { color: colors.destructiveForeground }
|
|
129
132
|
}[variant];
|
|
130
|
-
const spinnerColor = variant === "primary" || variant === "secondary" ? colors.primaryForeground : colors.foreground;
|
|
133
|
+
const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" || variant === "secondary" ? colors.primaryForeground : colors.foreground;
|
|
131
134
|
return /* @__PURE__ */ React23.createElement(Animated.View, { style: [fullWidth && styles.fullWidth, { transform: [{ scale }] }] }, /* @__PURE__ */ React23.createElement(
|
|
132
135
|
TouchableOpacity,
|
|
133
136
|
{
|
|
@@ -455,12 +458,13 @@ var styles7 = StyleSheet.create({
|
|
|
455
458
|
fontWeight: "500"
|
|
456
459
|
}
|
|
457
460
|
});
|
|
458
|
-
function
|
|
461
|
+
function AlertBanner({ title, description, variant = "default", icon, style }) {
|
|
459
462
|
const { colors } = useTheme();
|
|
460
|
-
const borderColor = variant === "destructive" ? colors.destructive : colors.border;
|
|
461
|
-
const titleColor = variant === "destructive" ? colors.destructive : colors.foreground;
|
|
462
|
-
const descColor = variant === "destructive" ? colors.destructive : colors.mutedForeground;
|
|
463
|
-
|
|
463
|
+
const borderColor = variant === "destructive" ? colors.destructive : variant === "success" ? colors.success : colors.border;
|
|
464
|
+
const titleColor = variant === "destructive" ? colors.destructive : variant === "success" ? colors.success : colors.foreground;
|
|
465
|
+
const descColor = variant === "destructive" ? colors.destructive : variant === "success" ? colors.success : colors.mutedForeground;
|
|
466
|
+
const defaultIcon = variant === "destructive" ? "\u26A0" : variant === "success" ? "\u2713" : "\u2139";
|
|
467
|
+
return /* @__PURE__ */ React23.createElement(View, { style: [styles8.container, { backgroundColor: colors.card, borderColor }, style] }, icon ? /* @__PURE__ */ React23.createElement(View, { style: styles8.icon }, icon) : /* @__PURE__ */ React23.createElement(View, { style: styles8.icon }, /* @__PURE__ */ React23.createElement(Text, { style: [styles8.defaultIcon, { color: titleColor }] }, defaultIcon)), /* @__PURE__ */ React23.createElement(View, { style: styles8.content }, title ? /* @__PURE__ */ React23.createElement(Text, { style: [styles8.title, { color: titleColor }] }, title) : null, description ? /* @__PURE__ */ React23.createElement(Text, { style: [styles8.description, { color: descColor }] }, description) : null));
|
|
464
468
|
}
|
|
465
469
|
var styles8 = StyleSheet.create({
|
|
466
470
|
container: {
|
|
@@ -531,9 +535,39 @@ var styles9 = StyleSheet.create({
|
|
|
531
535
|
borderRadius: 999
|
|
532
536
|
}
|
|
533
537
|
});
|
|
534
|
-
function EmptyState({ icon, title, description, action, style }) {
|
|
538
|
+
function EmptyState({ icon, title, description, action, size = "default", style }) {
|
|
535
539
|
const { colors } = useTheme();
|
|
536
|
-
|
|
540
|
+
const isCompact = size === "compact";
|
|
541
|
+
return /* @__PURE__ */ React23.createElement(
|
|
542
|
+
View,
|
|
543
|
+
{
|
|
544
|
+
style: [
|
|
545
|
+
styles10.container,
|
|
546
|
+
isCompact && styles10.containerCompact,
|
|
547
|
+
{ borderColor: colors.border },
|
|
548
|
+
style
|
|
549
|
+
]
|
|
550
|
+
},
|
|
551
|
+
icon ? /* @__PURE__ */ React23.createElement(
|
|
552
|
+
View,
|
|
553
|
+
{
|
|
554
|
+
style: [
|
|
555
|
+
styles10.iconWrapper,
|
|
556
|
+
isCompact && styles10.iconWrapperCompact,
|
|
557
|
+
{ backgroundColor: colors.muted }
|
|
558
|
+
]
|
|
559
|
+
},
|
|
560
|
+
icon
|
|
561
|
+
) : null,
|
|
562
|
+
/* @__PURE__ */ React23.createElement(View, { style: styles10.textWrapper }, /* @__PURE__ */ React23.createElement(
|
|
563
|
+
Text,
|
|
564
|
+
{
|
|
565
|
+
style: [styles10.title, isCompact && styles10.titleCompact, { color: colors.foreground }]
|
|
566
|
+
},
|
|
567
|
+
title
|
|
568
|
+
), description && !isCompact ? /* @__PURE__ */ React23.createElement(Text, { style: [styles10.description, { color: colors.mutedForeground }] }, description) : null),
|
|
569
|
+
action && !isCompact ? /* @__PURE__ */ React23.createElement(View, { style: styles10.action }, action) : null
|
|
570
|
+
);
|
|
537
571
|
}
|
|
538
572
|
var styles10 = StyleSheet.create({
|
|
539
573
|
container: {
|
|
@@ -545,6 +579,10 @@ var styles10 = StyleSheet.create({
|
|
|
545
579
|
padding: 32,
|
|
546
580
|
gap: 16
|
|
547
581
|
},
|
|
582
|
+
containerCompact: {
|
|
583
|
+
padding: 20,
|
|
584
|
+
gap: 10
|
|
585
|
+
},
|
|
548
586
|
iconWrapper: {
|
|
549
587
|
width: 48,
|
|
550
588
|
height: 48,
|
|
@@ -552,6 +590,11 @@ var styles10 = StyleSheet.create({
|
|
|
552
590
|
alignItems: "center",
|
|
553
591
|
justifyContent: "center"
|
|
554
592
|
},
|
|
593
|
+
iconWrapperCompact: {
|
|
594
|
+
width: 36,
|
|
595
|
+
height: 36,
|
|
596
|
+
borderRadius: 8
|
|
597
|
+
},
|
|
555
598
|
textWrapper: {
|
|
556
599
|
alignItems: "center",
|
|
557
600
|
gap: 8,
|
|
@@ -562,6 +605,9 @@ var styles10 = StyleSheet.create({
|
|
|
562
605
|
fontWeight: "500",
|
|
563
606
|
textAlign: "center"
|
|
564
607
|
},
|
|
608
|
+
titleCompact: {
|
|
609
|
+
fontSize: 15
|
|
610
|
+
},
|
|
565
611
|
description: {
|
|
566
612
|
fontSize: 14,
|
|
567
613
|
lineHeight: 20,
|
|
@@ -713,6 +759,7 @@ var styles12 = StyleSheet.create({
|
|
|
713
759
|
lineHeight: 22
|
|
714
760
|
}
|
|
715
761
|
});
|
|
762
|
+
var nativeDriver2 = Platform.OS !== "web";
|
|
716
763
|
var TRACK_WIDTH = 60;
|
|
717
764
|
var TRACK_HEIGHT = 36;
|
|
718
765
|
var THUMB_SIZE = 28;
|
|
@@ -726,7 +773,7 @@ function Switch({ checked = false, onCheckedChange, disabled, style }) {
|
|
|
726
773
|
Animated.parallel([
|
|
727
774
|
Animated.spring(translateX, {
|
|
728
775
|
toValue: checked ? THUMB_TRAVEL : 0,
|
|
729
|
-
useNativeDriver:
|
|
776
|
+
useNativeDriver: nativeDriver2,
|
|
730
777
|
bounciness: 4
|
|
731
778
|
}),
|
|
732
779
|
Animated.timing(trackOpacity, {
|
|
@@ -1828,10 +1875,10 @@ function formatValue(value, prefix, showDecimals) {
|
|
|
1828
1875
|
}
|
|
1829
1876
|
return `${sign}${prefix}${intPart}`;
|
|
1830
1877
|
}
|
|
1831
|
-
function CurrencyDisplay({ value, prefix = "$", showDecimals = false, style }) {
|
|
1878
|
+
function CurrencyDisplay({ value, prefix = "$", showDecimals = false, textColor, style }) {
|
|
1832
1879
|
const { colors } = useTheme();
|
|
1833
1880
|
const formatted = formatValue(value, prefix, showDecimals);
|
|
1834
|
-
return /* @__PURE__ */ React23.createElement(View, { style: [styles22.container, style] }, /* @__PURE__ */ React23.createElement(Text, { style: [styles22.amount, { color: colors.foreground }], allowFontScaling: true }, formatted));
|
|
1881
|
+
return /* @__PURE__ */ React23.createElement(View, { style: [styles22.container, style] }, /* @__PURE__ */ React23.createElement(Text, { style: [styles22.amount, { color: textColor ?? colors.foreground }], allowFontScaling: true }, formatted));
|
|
1835
1882
|
}
|
|
1836
1883
|
var styles22 = StyleSheet.create({
|
|
1837
1884
|
container: {},
|
|
@@ -1883,5 +1930,321 @@ function CurrencyInputLarge({
|
|
|
1883
1930
|
}
|
|
1884
1931
|
);
|
|
1885
1932
|
}
|
|
1933
|
+
var nativeDriver3 = Platform.OS !== "web";
|
|
1934
|
+
function ListItem({ icon, title, subtitle, trailing, onPress, disabled, style }) {
|
|
1935
|
+
const { colors } = useTheme();
|
|
1936
|
+
const scale = useRef(new Animated.Value(1)).current;
|
|
1937
|
+
const handlePressIn = () => {
|
|
1938
|
+
if (!onPress || disabled) return;
|
|
1939
|
+
Animated.spring(scale, {
|
|
1940
|
+
toValue: 0.97,
|
|
1941
|
+
useNativeDriver: nativeDriver3,
|
|
1942
|
+
speed: 40,
|
|
1943
|
+
bounciness: 0
|
|
1944
|
+
}).start();
|
|
1945
|
+
};
|
|
1946
|
+
const handlePressOut = () => {
|
|
1947
|
+
Animated.spring(scale, {
|
|
1948
|
+
toValue: 1,
|
|
1949
|
+
useNativeDriver: nativeDriver3,
|
|
1950
|
+
speed: 40,
|
|
1951
|
+
bounciness: 4
|
|
1952
|
+
}).start();
|
|
1953
|
+
};
|
|
1954
|
+
const handlePress = () => {
|
|
1955
|
+
Haptics11.selectionAsync();
|
|
1956
|
+
onPress?.();
|
|
1957
|
+
};
|
|
1958
|
+
return /* @__PURE__ */ React23.createElement(Animated.View, { style: [{ transform: [{ scale }] }, disabled && styles23.disabled] }, /* @__PURE__ */ React23.createElement(
|
|
1959
|
+
TouchableOpacity,
|
|
1960
|
+
{
|
|
1961
|
+
style: [styles23.container, style],
|
|
1962
|
+
onPress: onPress ? handlePress : void 0,
|
|
1963
|
+
onPressIn: handlePressIn,
|
|
1964
|
+
onPressOut: handlePressOut,
|
|
1965
|
+
disabled,
|
|
1966
|
+
activeOpacity: 1,
|
|
1967
|
+
touchSoundDisabled: true
|
|
1968
|
+
},
|
|
1969
|
+
icon ? /* @__PURE__ */ React23.createElement(View, { style: styles23.iconWrapper }, icon) : null,
|
|
1970
|
+
/* @__PURE__ */ React23.createElement(View, { style: styles23.content }, /* @__PURE__ */ React23.createElement(Text, { style: [styles23.title, { color: colors.foreground }], allowFontScaling: true }, title), subtitle ? /* @__PURE__ */ React23.createElement(Text, { style: [styles23.subtitle, { color: colors.mutedForeground }], allowFontScaling: true }, subtitle) : null),
|
|
1971
|
+
trailing !== void 0 ? typeof trailing === "string" ? /* @__PURE__ */ React23.createElement(Text, { style: [styles23.trailing, { color: colors.mutedForeground }], allowFontScaling: true }, trailing) : trailing : null
|
|
1972
|
+
));
|
|
1973
|
+
}
|
|
1974
|
+
var styles23 = StyleSheet.create({
|
|
1975
|
+
container: {
|
|
1976
|
+
flexDirection: "row",
|
|
1977
|
+
alignItems: "center",
|
|
1978
|
+
paddingHorizontal: 16,
|
|
1979
|
+
paddingVertical: 14,
|
|
1980
|
+
gap: 12
|
|
1981
|
+
},
|
|
1982
|
+
iconWrapper: {
|
|
1983
|
+
alignItems: "center",
|
|
1984
|
+
justifyContent: "center"
|
|
1985
|
+
},
|
|
1986
|
+
content: {
|
|
1987
|
+
flex: 1,
|
|
1988
|
+
gap: 3
|
|
1989
|
+
},
|
|
1990
|
+
title: {
|
|
1991
|
+
fontSize: 16,
|
|
1992
|
+
fontWeight: "500",
|
|
1993
|
+
lineHeight: 22
|
|
1994
|
+
},
|
|
1995
|
+
subtitle: {
|
|
1996
|
+
fontSize: 13,
|
|
1997
|
+
lineHeight: 18
|
|
1998
|
+
},
|
|
1999
|
+
trailing: {
|
|
2000
|
+
fontSize: 15
|
|
2001
|
+
},
|
|
2002
|
+
disabled: {
|
|
2003
|
+
opacity: 0.45
|
|
2004
|
+
}
|
|
2005
|
+
});
|
|
2006
|
+
var nativeDriver4 = Platform.OS !== "web";
|
|
2007
|
+
function Chip({ label, selected = false, onPress, style }) {
|
|
2008
|
+
const { colors } = useTheme();
|
|
2009
|
+
const scale = useRef(new Animated.Value(1)).current;
|
|
2010
|
+
const pressAnim = useRef(new Animated.Value(selected ? 1 : 0)).current;
|
|
2011
|
+
useEffect(() => {
|
|
2012
|
+
Animated.timing(pressAnim, {
|
|
2013
|
+
toValue: selected ? 1 : 0,
|
|
2014
|
+
duration: 150,
|
|
2015
|
+
easing: Easing.out(Easing.ease),
|
|
2016
|
+
useNativeDriver: false
|
|
2017
|
+
}).start();
|
|
2018
|
+
}, [selected, pressAnim]);
|
|
2019
|
+
const handlePressIn = () => {
|
|
2020
|
+
Animated.spring(scale, {
|
|
2021
|
+
toValue: 0.95,
|
|
2022
|
+
useNativeDriver: nativeDriver4,
|
|
2023
|
+
speed: 40,
|
|
2024
|
+
bounciness: 0
|
|
2025
|
+
}).start();
|
|
2026
|
+
};
|
|
2027
|
+
const handlePressOut = () => {
|
|
2028
|
+
Animated.spring(scale, {
|
|
2029
|
+
toValue: 1,
|
|
2030
|
+
useNativeDriver: nativeDriver4,
|
|
2031
|
+
speed: 40,
|
|
2032
|
+
bounciness: 4
|
|
2033
|
+
}).start();
|
|
2034
|
+
};
|
|
2035
|
+
const handlePress = () => {
|
|
2036
|
+
Haptics11.selectionAsync();
|
|
2037
|
+
onPress?.();
|
|
2038
|
+
};
|
|
2039
|
+
const backgroundColor = pressAnim.interpolate({
|
|
2040
|
+
inputRange: [0, 1],
|
|
2041
|
+
outputRange: [colors.secondary, colors.primary]
|
|
2042
|
+
});
|
|
2043
|
+
const textColor = pressAnim.interpolate({
|
|
2044
|
+
inputRange: [0, 1],
|
|
2045
|
+
outputRange: [colors.foreground, colors.primaryForeground]
|
|
2046
|
+
});
|
|
2047
|
+
const borderColor = pressAnim.interpolate({
|
|
2048
|
+
inputRange: [0, 1],
|
|
2049
|
+
outputRange: [colors.border, colors.primary]
|
|
2050
|
+
});
|
|
2051
|
+
return /* @__PURE__ */ React23.createElement(Animated.View, { style: [styles24.wrapper, { transform: [{ scale }] }, style] }, /* @__PURE__ */ React23.createElement(
|
|
2052
|
+
TouchableOpacity,
|
|
2053
|
+
{
|
|
2054
|
+
onPress: handlePress,
|
|
2055
|
+
onPressIn: handlePressIn,
|
|
2056
|
+
onPressOut: handlePressOut,
|
|
2057
|
+
activeOpacity: 1,
|
|
2058
|
+
touchSoundDisabled: true
|
|
2059
|
+
},
|
|
2060
|
+
/* @__PURE__ */ React23.createElement(Animated.View, { style: [styles24.chip, { backgroundColor, borderColor }] }, /* @__PURE__ */ React23.createElement(Animated.Text, { style: [styles24.label, { color: textColor }], allowFontScaling: true }, label))
|
|
2061
|
+
));
|
|
2062
|
+
}
|
|
2063
|
+
function ChipGroup({ options, value, onValueChange, style }) {
|
|
2064
|
+
return /* @__PURE__ */ React23.createElement(View, { style: [styles24.group, style] }, options.map((opt) => /* @__PURE__ */ React23.createElement(
|
|
2065
|
+
Chip,
|
|
2066
|
+
{
|
|
2067
|
+
key: opt.value,
|
|
2068
|
+
label: opt.label,
|
|
2069
|
+
selected: opt.value === value,
|
|
2070
|
+
onPress: () => onValueChange?.(opt.value)
|
|
2071
|
+
}
|
|
2072
|
+
)));
|
|
2073
|
+
}
|
|
2074
|
+
var styles24 = StyleSheet.create({
|
|
2075
|
+
wrapper: {},
|
|
2076
|
+
chip: {
|
|
2077
|
+
borderRadius: 999,
|
|
2078
|
+
paddingHorizontal: 14,
|
|
2079
|
+
paddingVertical: 8,
|
|
2080
|
+
borderWidth: 1.5,
|
|
2081
|
+
alignItems: "center",
|
|
2082
|
+
justifyContent: "center"
|
|
2083
|
+
},
|
|
2084
|
+
label: {
|
|
2085
|
+
fontSize: 14,
|
|
2086
|
+
fontWeight: "500",
|
|
2087
|
+
lineHeight: 20
|
|
2088
|
+
},
|
|
2089
|
+
group: {
|
|
2090
|
+
flexDirection: "row",
|
|
2091
|
+
flexWrap: "wrap",
|
|
2092
|
+
gap: 8
|
|
2093
|
+
}
|
|
2094
|
+
});
|
|
2095
|
+
function ConfirmDialog({
|
|
2096
|
+
visible,
|
|
2097
|
+
title,
|
|
2098
|
+
description,
|
|
2099
|
+
confirmLabel = "Confirm",
|
|
2100
|
+
cancelLabel = "Cancel",
|
|
2101
|
+
confirmVariant = "primary",
|
|
2102
|
+
onConfirm,
|
|
2103
|
+
onCancel
|
|
2104
|
+
}) {
|
|
2105
|
+
const { colors } = useTheme();
|
|
2106
|
+
return /* @__PURE__ */ React23.createElement(Modal, { visible, transparent: true, animationType: "fade", onRequestClose: onCancel }, /* @__PURE__ */ React23.createElement(TouchableOpacity, { style: styles25.overlay, activeOpacity: 1, onPress: onCancel }, /* @__PURE__ */ React23.createElement(
|
|
2107
|
+
View,
|
|
2108
|
+
{
|
|
2109
|
+
style: [styles25.dialog, { backgroundColor: colors.card }],
|
|
2110
|
+
onStartShouldSetResponder: () => true
|
|
2111
|
+
},
|
|
2112
|
+
/* @__PURE__ */ React23.createElement(Text, { style: [styles25.title, { color: colors.cardForeground }], allowFontScaling: true }, title),
|
|
2113
|
+
description ? /* @__PURE__ */ React23.createElement(Text, { style: [styles25.description, { color: colors.mutedForeground }], allowFontScaling: true }, description) : null,
|
|
2114
|
+
/* @__PURE__ */ React23.createElement(View, { style: styles25.actions }, /* @__PURE__ */ React23.createElement(Button, { label: cancelLabel, variant: "outline", fullWidth: true, onPress: onCancel }), /* @__PURE__ */ React23.createElement(Button, { label: confirmLabel, variant: confirmVariant, fullWidth: true, onPress: onConfirm }))
|
|
2115
|
+
)));
|
|
2116
|
+
}
|
|
2117
|
+
var styles25 = StyleSheet.create({
|
|
2118
|
+
overlay: {
|
|
2119
|
+
flex: 1,
|
|
2120
|
+
backgroundColor: "rgba(0,0,0,0.5)",
|
|
2121
|
+
justifyContent: "center",
|
|
2122
|
+
alignItems: "center",
|
|
2123
|
+
padding: 24
|
|
2124
|
+
},
|
|
2125
|
+
dialog: {
|
|
2126
|
+
width: "100%",
|
|
2127
|
+
maxWidth: 400,
|
|
2128
|
+
borderRadius: 16,
|
|
2129
|
+
padding: 24,
|
|
2130
|
+
gap: 12,
|
|
2131
|
+
shadowColor: "#000",
|
|
2132
|
+
shadowOffset: { width: 0, height: 8 },
|
|
2133
|
+
shadowOpacity: 0.15,
|
|
2134
|
+
shadowRadius: 16,
|
|
2135
|
+
elevation: 8
|
|
2136
|
+
},
|
|
2137
|
+
title: {
|
|
2138
|
+
fontSize: 18,
|
|
2139
|
+
fontWeight: "600",
|
|
2140
|
+
lineHeight: 26
|
|
2141
|
+
},
|
|
2142
|
+
description: {
|
|
2143
|
+
fontSize: 15,
|
|
2144
|
+
lineHeight: 22
|
|
2145
|
+
},
|
|
2146
|
+
actions: {
|
|
2147
|
+
gap: 10,
|
|
2148
|
+
marginTop: 8
|
|
2149
|
+
}
|
|
2150
|
+
});
|
|
2151
|
+
function LabelValue({ label, value, style }) {
|
|
2152
|
+
const { colors } = useTheme();
|
|
2153
|
+
return /* @__PURE__ */ React23.createElement(View, { style: [styles26.container, style] }, /* @__PURE__ */ React23.createElement(Text, { style: [styles26.label, { color: colors.mutedForeground }], allowFontScaling: true }, label), typeof value === "string" ? /* @__PURE__ */ React23.createElement(Text, { style: [styles26.value, { color: colors.foreground }], allowFontScaling: true }, value) : value);
|
|
2154
|
+
}
|
|
2155
|
+
var styles26 = StyleSheet.create({
|
|
2156
|
+
container: {
|
|
2157
|
+
flexDirection: "row",
|
|
2158
|
+
justifyContent: "space-between",
|
|
2159
|
+
alignItems: "center",
|
|
2160
|
+
gap: 12
|
|
2161
|
+
},
|
|
2162
|
+
label: {
|
|
2163
|
+
fontSize: 13,
|
|
2164
|
+
lineHeight: 18
|
|
2165
|
+
},
|
|
2166
|
+
value: {
|
|
2167
|
+
fontSize: 15,
|
|
2168
|
+
fontWeight: "500",
|
|
2169
|
+
lineHeight: 22,
|
|
2170
|
+
textAlign: "right"
|
|
2171
|
+
}
|
|
2172
|
+
});
|
|
2173
|
+
var MONTH_NAMES = [
|
|
2174
|
+
"January",
|
|
2175
|
+
"February",
|
|
2176
|
+
"March",
|
|
2177
|
+
"April",
|
|
2178
|
+
"May",
|
|
2179
|
+
"June",
|
|
2180
|
+
"July",
|
|
2181
|
+
"August",
|
|
2182
|
+
"September",
|
|
2183
|
+
"October",
|
|
2184
|
+
"November",
|
|
2185
|
+
"December"
|
|
2186
|
+
];
|
|
2187
|
+
function MonthPicker({ value, onChange, style }) {
|
|
2188
|
+
const { colors } = useTheme();
|
|
2189
|
+
const handlePrev = () => {
|
|
2190
|
+
Haptics11.selectionAsync();
|
|
2191
|
+
if (value.month === 1) {
|
|
2192
|
+
onChange({ month: 12, year: value.year - 1 });
|
|
2193
|
+
} else {
|
|
2194
|
+
onChange({ month: value.month - 1, year: value.year });
|
|
2195
|
+
}
|
|
2196
|
+
};
|
|
2197
|
+
const handleNext = () => {
|
|
2198
|
+
Haptics11.selectionAsync();
|
|
2199
|
+
if (value.month === 12) {
|
|
2200
|
+
onChange({ month: 1, year: value.year + 1 });
|
|
2201
|
+
} else {
|
|
2202
|
+
onChange({ month: value.month + 1, year: value.year });
|
|
2203
|
+
}
|
|
2204
|
+
};
|
|
2205
|
+
return /* @__PURE__ */ React23.createElement(View, { style: [styles27.container, style] }, /* @__PURE__ */ React23.createElement(
|
|
2206
|
+
TouchableOpacity,
|
|
2207
|
+
{
|
|
2208
|
+
style: styles27.arrow,
|
|
2209
|
+
onPress: handlePrev,
|
|
2210
|
+
activeOpacity: 0.6,
|
|
2211
|
+
touchSoundDisabled: true
|
|
2212
|
+
},
|
|
2213
|
+
/* @__PURE__ */ React23.createElement(Text, { style: [styles27.arrowText, { color: colors.foreground }] }, "\u2039")
|
|
2214
|
+
), /* @__PURE__ */ React23.createElement(Text, { style: [styles27.label, { color: colors.foreground }], allowFontScaling: true }, MONTH_NAMES[value.month - 1], " ", value.year), /* @__PURE__ */ React23.createElement(
|
|
2215
|
+
TouchableOpacity,
|
|
2216
|
+
{
|
|
2217
|
+
style: styles27.arrow,
|
|
2218
|
+
onPress: handleNext,
|
|
2219
|
+
activeOpacity: 0.6,
|
|
2220
|
+
touchSoundDisabled: true
|
|
2221
|
+
},
|
|
2222
|
+
/* @__PURE__ */ React23.createElement(Text, { style: [styles27.arrowText, { color: colors.foreground }] }, "\u203A")
|
|
2223
|
+
));
|
|
2224
|
+
}
|
|
2225
|
+
var styles27 = StyleSheet.create({
|
|
2226
|
+
container: {
|
|
2227
|
+
flexDirection: "row",
|
|
2228
|
+
alignItems: "center",
|
|
2229
|
+
justifyContent: "space-between"
|
|
2230
|
+
},
|
|
2231
|
+
arrow: {
|
|
2232
|
+
width: 44,
|
|
2233
|
+
height: 44,
|
|
2234
|
+
alignItems: "center",
|
|
2235
|
+
justifyContent: "center"
|
|
2236
|
+
},
|
|
2237
|
+
arrowText: {
|
|
2238
|
+
fontSize: 24,
|
|
2239
|
+
lineHeight: 30
|
|
2240
|
+
},
|
|
2241
|
+
label: {
|
|
2242
|
+
fontSize: 17,
|
|
2243
|
+
fontWeight: "500",
|
|
2244
|
+
lineHeight: 24,
|
|
2245
|
+
textAlign: "center",
|
|
2246
|
+
minWidth: 160
|
|
2247
|
+
}
|
|
2248
|
+
});
|
|
1886
2249
|
|
|
1887
|
-
export { Accordion,
|
|
2250
|
+
export { Accordion, AlertBanner, Avatar, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Chip, ChipGroup, ConfirmDialog, CurrencyDisplay, CurrencyInput, CurrencyInputLarge, EmptyState, Input, LabelValue, ListItem, MonthPicker, Progress, RadioGroup, Select, Separator, Sheet, Skeleton, Slider, Spinner, Switch, Tabs, TabsContent, Text2 as Text, Textarea, ThemeProvider, ToastProvider, Toggle, defaultDark, defaultLight, useTheme, useToast };
|
package/package.json
CHANGED
|
@@ -2,22 +2,36 @@ import React from 'react'
|
|
|
2
2
|
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
4
|
|
|
5
|
-
export type
|
|
5
|
+
export type AlertBannerVariant = 'default' | 'destructive' | 'success'
|
|
6
6
|
|
|
7
|
-
export interface
|
|
7
|
+
export interface AlertBannerProps {
|
|
8
8
|
title?: string
|
|
9
9
|
description?: string
|
|
10
|
-
variant?:
|
|
10
|
+
variant?: AlertBannerVariant
|
|
11
11
|
icon?: React.ReactNode
|
|
12
12
|
style?: ViewStyle
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function
|
|
15
|
+
export function AlertBanner({ title, description, variant = 'default', icon, style }: AlertBannerProps) {
|
|
16
16
|
const { colors } = useTheme()
|
|
17
17
|
|
|
18
|
-
const borderColor =
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const borderColor =
|
|
19
|
+
variant === 'destructive' ? colors.destructive
|
|
20
|
+
: variant === 'success' ? colors.success
|
|
21
|
+
: colors.border
|
|
22
|
+
|
|
23
|
+
const titleColor =
|
|
24
|
+
variant === 'destructive' ? colors.destructive
|
|
25
|
+
: variant === 'success' ? colors.success
|
|
26
|
+
: colors.foreground
|
|
27
|
+
|
|
28
|
+
const descColor =
|
|
29
|
+
variant === 'destructive' ? colors.destructive
|
|
30
|
+
: variant === 'success' ? colors.success
|
|
31
|
+
: colors.mutedForeground
|
|
32
|
+
|
|
33
|
+
const defaultIcon =
|
|
34
|
+
variant === 'destructive' ? '⚠' : variant === 'success' ? '✓' : 'ℹ'
|
|
21
35
|
|
|
22
36
|
return (
|
|
23
37
|
<View style={[styles.container, { backgroundColor: colors.card, borderColor }, style]}>
|
|
@@ -25,9 +39,7 @@ export function Alert({ title, description, variant = 'default', icon, style }:
|
|
|
25
39
|
<View style={styles.icon}>{icon}</View>
|
|
26
40
|
) : (
|
|
27
41
|
<View style={styles.icon}>
|
|
28
|
-
<Text style={[styles.defaultIcon, { color: titleColor }]}>
|
|
29
|
-
{variant === 'destructive' ? '⚠' : 'ℹ'}
|
|
30
|
-
</Text>
|
|
42
|
+
<Text style={[styles.defaultIcon, { color: titleColor }]}>{defaultIcon}</Text>
|
|
31
43
|
</View>
|
|
32
44
|
)}
|
|
33
45
|
<View style={styles.content}>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
1
|
+
export { AlertBanner } from './Alert'
|
|
2
|
+
export type { AlertBannerProps, AlertBannerVariant } from './Alert'
|
|
@@ -8,11 +8,14 @@ import {
|
|
|
8
8
|
TouchableOpacityProps,
|
|
9
9
|
ViewStyle,
|
|
10
10
|
TextStyle,
|
|
11
|
+
Platform,
|
|
11
12
|
} from 'react-native'
|
|
13
|
+
|
|
14
|
+
const nativeDriver = Platform.OS !== 'web'
|
|
12
15
|
import * as Haptics from 'expo-haptics'
|
|
13
16
|
import { useTheme } from '../../theme'
|
|
14
17
|
|
|
15
|
-
export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost'
|
|
18
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive'
|
|
16
19
|
export type ButtonSize = 'sm' | 'md' | 'lg'
|
|
17
20
|
|
|
18
21
|
export interface ButtonProps extends TouchableOpacityProps {
|
|
@@ -67,14 +70,14 @@ export function Button({
|
|
|
67
70
|
if (isDisabled) return
|
|
68
71
|
Animated.spring(scale, {
|
|
69
72
|
toValue: 0.95,
|
|
70
|
-
useNativeDriver:
|
|
73
|
+
useNativeDriver: nativeDriver,
|
|
71
74
|
speed: 40,
|
|
72
75
|
bounciness: 0,
|
|
73
76
|
}).start()
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
const handlePressOut = () => {
|
|
77
|
-
Animated.spring(scale, { toValue: 1, useNativeDriver:
|
|
80
|
+
Animated.spring(scale, { toValue: 1, useNativeDriver: nativeDriver, speed: 40, bounciness: 4 }).start()
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
const handlePress: TouchableOpacityProps['onPress'] = (e) => {
|
|
@@ -87,6 +90,7 @@ export function Button({
|
|
|
87
90
|
secondary: { backgroundColor: colors.secondary },
|
|
88
91
|
outline: { backgroundColor: 'transparent', borderWidth: 1.5, borderColor: colors.border },
|
|
89
92
|
ghost: { backgroundColor: 'transparent' },
|
|
93
|
+
destructive: { backgroundColor: colors.destructive },
|
|
90
94
|
}[variant]
|
|
91
95
|
|
|
92
96
|
const labelVariantStyle: TextStyle = {
|
|
@@ -94,10 +98,13 @@ export function Button({
|
|
|
94
98
|
secondary: { color: colors.secondaryForeground },
|
|
95
99
|
outline: { color: colors.foreground },
|
|
96
100
|
ghost: { color: colors.foreground },
|
|
101
|
+
destructive: { color: colors.destructiveForeground },
|
|
97
102
|
}[variant]
|
|
98
103
|
|
|
99
104
|
const spinnerColor =
|
|
100
|
-
variant === '
|
|
105
|
+
variant === 'destructive' ? colors.destructiveForeground
|
|
106
|
+
: variant === 'primary' || variant === 'secondary' ? colors.primaryForeground
|
|
107
|
+
: colors.foreground
|
|
101
108
|
|
|
102
109
|
return (
|
|
103
110
|
<Animated.View style={[fullWidth && styles.fullWidth, { transform: [{ scale }] }]}>
|