@blinkdotnew/mobile-ui 2.0.0-alpha.10 → 2.0.0-alpha.12
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.d.mts +173 -5
- package/dist/index.d.ts +173 -5
- package/dist/index.js +1182 -242
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1100 -172
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
SizableStack,
|
|
14
14
|
ThemeableStack,
|
|
15
15
|
Frame,
|
|
16
|
-
XStack as
|
|
17
|
-
YStack as
|
|
16
|
+
XStack as XStack37,
|
|
17
|
+
YStack as YStack41,
|
|
18
18
|
ZStack,
|
|
19
|
-
ScrollView as
|
|
20
|
-
Circle as
|
|
19
|
+
ScrollView as ScrollView7,
|
|
20
|
+
Circle as Circle9,
|
|
21
21
|
Square,
|
|
22
22
|
Spacer,
|
|
23
23
|
EnsureFlexed,
|
|
@@ -38,11 +38,11 @@ import {
|
|
|
38
38
|
H6 as H62,
|
|
39
39
|
Heading,
|
|
40
40
|
Paragraph,
|
|
41
|
-
SizableText as
|
|
41
|
+
SizableText as SizableText44,
|
|
42
42
|
Text,
|
|
43
43
|
Label,
|
|
44
|
-
Button as
|
|
45
|
-
Input as
|
|
44
|
+
Button as Button11,
|
|
45
|
+
Input as Input5,
|
|
46
46
|
TextArea,
|
|
47
47
|
Switch as Switch2,
|
|
48
48
|
Checkbox,
|
|
@@ -54,14 +54,14 @@ import {
|
|
|
54
54
|
Card as Card2,
|
|
55
55
|
Avatar as Avatar2,
|
|
56
56
|
Separator as Separator5,
|
|
57
|
-
Image as
|
|
57
|
+
Image as Image9,
|
|
58
58
|
Progress,
|
|
59
59
|
Spinner as Spinner2,
|
|
60
60
|
ListItem as ListItem2,
|
|
61
61
|
Anchor,
|
|
62
62
|
Sheet as Sheet3,
|
|
63
63
|
Dialog,
|
|
64
|
-
AlertDialog as
|
|
64
|
+
AlertDialog as AlertDialog3,
|
|
65
65
|
Popover as Popover2,
|
|
66
66
|
Tooltip,
|
|
67
67
|
TooltipSimple,
|
|
@@ -89,7 +89,7 @@ import {
|
|
|
89
89
|
addTheme,
|
|
90
90
|
updateTheme,
|
|
91
91
|
replaceTheme,
|
|
92
|
-
styled as
|
|
92
|
+
styled as styled13,
|
|
93
93
|
withStaticProperties as withStaticProperties2,
|
|
94
94
|
isWeb,
|
|
95
95
|
isClient,
|
|
@@ -1035,78 +1035,137 @@ function Container({ children, maxWidth = 500, centered = true, padding = "$4" }
|
|
|
1035
1035
|
}
|
|
1036
1036
|
|
|
1037
1037
|
// src/patterns/PaywallScreen.tsx
|
|
1038
|
-
import {
|
|
1038
|
+
import { useState as useState5, useEffect as useEffect3 } from "react";
|
|
1039
|
+
import { Button as Button3, SizableText as SizableText17, XStack as XStack10, YStack as YStack14, ScrollView as ScrollView2 } from "tamagui";
|
|
1039
1040
|
import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1041
|
+
function useCountdown(minutes) {
|
|
1042
|
+
const [seconds, setSeconds] = useState5((minutes ?? 0) * 60);
|
|
1043
|
+
useEffect3(() => {
|
|
1044
|
+
if (!minutes) return;
|
|
1045
|
+
setSeconds(minutes * 60);
|
|
1046
|
+
const id = setInterval(() => setSeconds((s) => s > 0 ? s - 1 : 0), 1e3);
|
|
1047
|
+
return () => clearInterval(id);
|
|
1048
|
+
}, [minutes]);
|
|
1049
|
+
const mm = String(Math.floor(seconds / 60)).padStart(2, "0");
|
|
1050
|
+
const ss = String(seconds % 60).padStart(2, "0");
|
|
1051
|
+
return { display: `${mm}:${ss}`, expired: seconds <= 0 };
|
|
1052
|
+
}
|
|
1053
|
+
function PlanCard({ plan, selected, onPress }) {
|
|
1054
|
+
return /* @__PURE__ */ jsxs13(
|
|
1055
|
+
YStack14,
|
|
1056
|
+
{
|
|
1057
|
+
flex: 1,
|
|
1058
|
+
padding: "$3",
|
|
1059
|
+
borderRadius: "$5",
|
|
1060
|
+
borderWidth: 2,
|
|
1061
|
+
borderColor: selected ? "$color9" : "$color5",
|
|
1062
|
+
backgroundColor: selected ? "$color3" : "$color1",
|
|
1063
|
+
pressStyle: { scale: 0.97, opacity: 0.9 },
|
|
1064
|
+
animation: "quick",
|
|
1065
|
+
onPress,
|
|
1066
|
+
cursor: "pointer",
|
|
1067
|
+
position: "relative",
|
|
1068
|
+
gap: "$1.5",
|
|
1069
|
+
alignItems: "center",
|
|
1070
|
+
children: [
|
|
1071
|
+
plan.popular && /* @__PURE__ */ jsx20(YStack14, { position: "absolute", top: -10, backgroundColor: "$color9", paddingHorizontal: "$2", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ jsx20(SizableText17, { size: "$1", color: "white", fontWeight: "700", children: "BEST VALUE" }) }),
|
|
1072
|
+
plan.savings && /* @__PURE__ */ jsx20(YStack14, { position: "absolute", top: plan.popular ? -24 : -10, right: 6, backgroundColor: "$green9", paddingHorizontal: "$1.5", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ jsx20(SizableText17, { size: "$1", color: "white", fontWeight: "700", children: plan.savings }) }),
|
|
1073
|
+
/* @__PURE__ */ jsx20(SizableText17, { size: "$2", fontWeight: "600", color: "$color11", paddingTop: plan.popular ? "$1" : 0, children: plan.name }),
|
|
1074
|
+
/* @__PURE__ */ jsx20(SizableText17, { size: "$7", fontWeight: "800", children: plan.price }),
|
|
1075
|
+
/* @__PURE__ */ jsxs13(SizableText17, { size: "$2", color: "$color9", children: [
|
|
1076
|
+
"/",
|
|
1077
|
+
plan.period
|
|
1078
|
+
] }),
|
|
1079
|
+
plan.pricePerWeek && /* @__PURE__ */ jsx20(SizableText17, { size: "$1", color: "$color10", children: plan.pricePerWeek }),
|
|
1080
|
+
plan.trial && /* @__PURE__ */ jsx20(YStack14, { backgroundColor: "$green3", paddingHorizontal: "$2", paddingVertical: 2, borderRadius: "$10", marginTop: "$1", children: /* @__PURE__ */ jsx20(SizableText17, { size: "$1", color: "$green9", fontWeight: "700", children: plan.trial }) })
|
|
1081
|
+
]
|
|
1082
|
+
}
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1040
1085
|
function PaywallScreen({
|
|
1041
|
-
title = "
|
|
1042
|
-
subtitle
|
|
1086
|
+
title = "Unlock Premium",
|
|
1087
|
+
subtitle,
|
|
1088
|
+
features = [],
|
|
1043
1089
|
plans,
|
|
1044
1090
|
selectedPlan,
|
|
1045
1091
|
onSelectPlan,
|
|
1046
1092
|
onContinue,
|
|
1093
|
+
onClose,
|
|
1047
1094
|
onRestore,
|
|
1048
|
-
|
|
1095
|
+
onTerms,
|
|
1096
|
+
onPrivacy,
|
|
1097
|
+
continueLabel = "Continue",
|
|
1098
|
+
reassurance = "Cancel anytime",
|
|
1099
|
+
hero,
|
|
1100
|
+
socialProof,
|
|
1101
|
+
countdownMinutes,
|
|
1102
|
+
badge
|
|
1049
1103
|
}) {
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1104
|
+
const selected = selectedPlan ?? plans.find((p) => p.popular)?.id ?? plans[0]?.id;
|
|
1105
|
+
const countdown = useCountdown(countdownMinutes);
|
|
1106
|
+
return /* @__PURE__ */ jsxs13(YStack14, { flex: 1, backgroundColor: "$background", children: [
|
|
1107
|
+
onClose && /* @__PURE__ */ jsx20(XStack10, { position: "absolute", top: "$4", right: "$4", zIndex: 10, children: /* @__PURE__ */ jsx20(Button3, { size: "$3", circular: true, chromeless: true, onPress: onClose, pressStyle: { opacity: 0.6 }, children: /* @__PURE__ */ jsx20(SizableText17, { size: "$5", color: "$color9", children: "\u2715" }) }) }),
|
|
1108
|
+
/* @__PURE__ */ jsx20(ScrollView2, { flex: 1, contentContainerStyle: { paddingBottom: 220 }, children: /* @__PURE__ */ jsxs13(YStack14, { padding: "$4", gap: "$4", paddingTop: "$8", children: [
|
|
1109
|
+
hero && /* @__PURE__ */ jsx20(YStack14, { alignItems: "center", paddingVertical: "$3", children: hero }),
|
|
1110
|
+
badge && /* @__PURE__ */ jsx20(XStack10, { justifyContent: "center", children: /* @__PURE__ */ jsx20(YStack14, { backgroundColor: "$color9", paddingHorizontal: "$3", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ jsx20(SizableText17, { size: "$2", color: "white", fontWeight: "700", children: badge }) }) }),
|
|
1111
|
+
/* @__PURE__ */ jsxs13(YStack14, { gap: "$1.5", alignItems: "center", children: [
|
|
1112
|
+
/* @__PURE__ */ jsx20(SizableText17, { size: "$9", fontWeight: "800", textAlign: "center", children: title }),
|
|
1113
|
+
subtitle && /* @__PURE__ */ jsx20(SizableText17, { size: "$4", color: "$color10", textAlign: "center", children: subtitle }),
|
|
1114
|
+
socialProof && /* @__PURE__ */ jsx20(SizableText17, { size: "$3", color: "$color9", fontWeight: "600", textAlign: "center", children: socialProof })
|
|
1115
|
+
] }),
|
|
1116
|
+
countdownMinutes && !countdown.expired && /* @__PURE__ */ jsxs13(XStack10, { justifyContent: "center", padding: "$2", backgroundColor: "$red3", borderRadius: "$4", alignSelf: "center", paddingHorizontal: "$4", gap: "$2", alignItems: "center", children: [
|
|
1117
|
+
/* @__PURE__ */ jsx20(SizableText17, { size: "$2", color: "$red9", fontWeight: "600", children: "Offer ends in" }),
|
|
1118
|
+
/* @__PURE__ */ jsx20(SizableText17, { size: "$5", color: "$red9", fontWeight: "800", fontFamily: "$mono", children: countdown.display })
|
|
1119
|
+
] }),
|
|
1120
|
+
features.length > 0 && /* @__PURE__ */ jsx20(YStack14, { gap: "$2.5", paddingHorizontal: "$2", children: features.map((f, i) => /* @__PURE__ */ jsxs13(XStack10, { gap: "$2.5", alignItems: "center", children: [
|
|
1121
|
+
/* @__PURE__ */ jsx20(SizableText17, { size: "$4", color: "$green9", children: "\u2713" }),
|
|
1122
|
+
/* @__PURE__ */ jsx20(SizableText17, { size: "$4", color: "$color11", flex: 1, children: f })
|
|
1123
|
+
] }, i)) }),
|
|
1124
|
+
/* @__PURE__ */ jsx20(XStack10, { gap: "$3", paddingTop: "$1", children: plans.map((plan) => /* @__PURE__ */ jsx20(PlanCard, { plan, selected: selected === plan.id, onPress: () => onSelectPlan?.(plan.id) }, plan.id)) })
|
|
1125
|
+
] }) }),
|
|
1126
|
+
/* @__PURE__ */ jsxs13(
|
|
1056
1127
|
YStack14,
|
|
1057
1128
|
{
|
|
1129
|
+
position: "absolute",
|
|
1130
|
+
bottom: 0,
|
|
1131
|
+
left: 0,
|
|
1132
|
+
right: 0,
|
|
1058
1133
|
padding: "$4",
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
onPress: () => onSelectPlan?.(plan.id),
|
|
1065
|
-
cursor: "pointer",
|
|
1134
|
+
paddingBottom: "$6",
|
|
1135
|
+
backgroundColor: "$background",
|
|
1136
|
+
borderTopWidth: 1,
|
|
1137
|
+
borderTopColor: "$color4",
|
|
1138
|
+
gap: "$2.5",
|
|
1066
1139
|
children: [
|
|
1067
|
-
/* @__PURE__ */
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1140
|
+
/* @__PURE__ */ jsx20(
|
|
1141
|
+
Button3,
|
|
1142
|
+
{
|
|
1143
|
+
size: "$5",
|
|
1144
|
+
backgroundColor: "$color9",
|
|
1145
|
+
color: "$color1",
|
|
1146
|
+
onPress: onContinue,
|
|
1147
|
+
pressStyle: { backgroundColor: "$color8", scale: 0.98 },
|
|
1148
|
+
animation: "quick",
|
|
1149
|
+
borderRadius: "$10",
|
|
1150
|
+
fontWeight: "700",
|
|
1151
|
+
children: continueLabel
|
|
1152
|
+
}
|
|
1153
|
+
),
|
|
1154
|
+
reassurance && /* @__PURE__ */ jsx20(SizableText17, { size: "$2", color: "$color9", textAlign: "center", children: reassurance }),
|
|
1155
|
+
/* @__PURE__ */ jsxs13(XStack10, { justifyContent: "center", gap: "$3", children: [
|
|
1156
|
+
onRestore && /* @__PURE__ */ jsx20(SizableText17, { size: "$2", color: "$color8", onPress: onRestore, pressStyle: { opacity: 0.6 }, children: "Restore" }),
|
|
1157
|
+
onTerms && /* @__PURE__ */ jsx20(SizableText17, { size: "$2", color: "$color8", onPress: onTerms, pressStyle: { opacity: 0.6 }, children: "Terms" }),
|
|
1158
|
+
onPrivacy && /* @__PURE__ */ jsx20(SizableText17, { size: "$2", color: "$color8", onPress: onPrivacy, pressStyle: { opacity: 0.6 }, children: "Privacy" })
|
|
1159
|
+
] })
|
|
1084
1160
|
]
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
)) }),
|
|
1088
|
-
/* @__PURE__ */ jsxs13(YStack14, { gap: "$3", paddingBottom: "$4", children: [
|
|
1089
|
-
/* @__PURE__ */ jsx20(
|
|
1090
|
-
Button3,
|
|
1091
|
-
{
|
|
1092
|
-
size: "$5",
|
|
1093
|
-
backgroundColor: "$color9",
|
|
1094
|
-
color: "$color1",
|
|
1095
|
-
onPress: onContinue,
|
|
1096
|
-
hoverStyle: { backgroundColor: "$color10" },
|
|
1097
|
-
pressStyle: { backgroundColor: "$color8" },
|
|
1098
|
-
borderRadius: "$5",
|
|
1099
|
-
children: continueLabel
|
|
1100
|
-
}
|
|
1101
|
-
),
|
|
1102
|
-
onRestore && /* @__PURE__ */ jsx20(Button3, { size: "$3", chromeless: true, onPress: onRestore, children: /* @__PURE__ */ jsx20(SizableText17, { size: "$3", color: "$color9", children: "Restore Purchases" }) })
|
|
1103
|
-
] })
|
|
1161
|
+
}
|
|
1162
|
+
)
|
|
1104
1163
|
] });
|
|
1105
1164
|
}
|
|
1106
1165
|
|
|
1107
1166
|
// src/patterns/OnboardingCarousel.tsx
|
|
1108
|
-
import { useState as
|
|
1109
|
-
import { Button as Button4, SizableText as SizableText18, XStack as XStack11, YStack as YStack15, Circle as
|
|
1167
|
+
import { useState as useState6 } from "react";
|
|
1168
|
+
import { Button as Button4, SizableText as SizableText18, XStack as XStack11, YStack as YStack15, Circle as Circle2 } from "tamagui";
|
|
1110
1169
|
import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1111
1170
|
function OnboardingCarousel({
|
|
1112
1171
|
steps,
|
|
@@ -1116,13 +1175,13 @@ function OnboardingCarousel({
|
|
|
1116
1175
|
skipLabel = "Skip",
|
|
1117
1176
|
nextLabel = "Next"
|
|
1118
1177
|
}) {
|
|
1119
|
-
const [current, setCurrent] =
|
|
1178
|
+
const [current, setCurrent] = useState6(0);
|
|
1120
1179
|
const isLast = current === steps.length - 1;
|
|
1121
1180
|
const step = steps[current];
|
|
1122
1181
|
return /* @__PURE__ */ jsxs14(YStack15, { flex: 1, backgroundColor: "$background", padding: "$4", justifyContent: "space-between", children: [
|
|
1123
1182
|
/* @__PURE__ */ jsx21(XStack11, { justifyContent: "flex-end", paddingTop: "$4", children: !isLast && onSkip && /* @__PURE__ */ jsx21(Button4, { chromeless: true, onPress: onSkip, children: /* @__PURE__ */ jsx21(SizableText18, { size: "$4", color: "$color9", children: skipLabel }) }) }),
|
|
1124
1183
|
/* @__PURE__ */ jsxs14(YStack15, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$5", paddingHorizontal: "$4", children: [
|
|
1125
|
-
step?.icon && /* @__PURE__ */ jsx21(
|
|
1184
|
+
step?.icon && /* @__PURE__ */ jsx21(Circle2, { size: 120, backgroundColor: "$color2", alignItems: "center", justifyContent: "center", children: step.icon }),
|
|
1126
1185
|
/* @__PURE__ */ jsxs14(YStack15, { gap: "$3", alignItems: "center", children: [
|
|
1127
1186
|
/* @__PURE__ */ jsx21(SizableText18, { size: "$9", fontWeight: "700", textAlign: "center", children: step?.title }),
|
|
1128
1187
|
/* @__PURE__ */ jsx21(SizableText18, { size: "$4", color: "$color10", textAlign: "center", maxWidth: 300, children: step?.description })
|
|
@@ -1130,7 +1189,7 @@ function OnboardingCarousel({
|
|
|
1130
1189
|
] }),
|
|
1131
1190
|
/* @__PURE__ */ jsxs14(YStack15, { gap: "$3", paddingBottom: "$2", children: [
|
|
1132
1191
|
/* @__PURE__ */ jsx21(XStack11, { justifyContent: "center", gap: "$2", children: steps.map((_, i) => /* @__PURE__ */ jsx21(
|
|
1133
|
-
|
|
1192
|
+
Circle2,
|
|
1134
1193
|
{
|
|
1135
1194
|
size: 8,
|
|
1136
1195
|
backgroundColor: i === current ? "$color9" : "$color4",
|
|
@@ -1156,7 +1215,7 @@ function OnboardingCarousel({
|
|
|
1156
1215
|
}
|
|
1157
1216
|
|
|
1158
1217
|
// src/patterns/ChatBubble.tsx
|
|
1159
|
-
import { SizableText as SizableText19, XStack as XStack12, YStack as YStack16, Circle as
|
|
1218
|
+
import { SizableText as SizableText19, XStack as XStack12, YStack as YStack16, Circle as Circle3, Image as Image3 } from "tamagui";
|
|
1160
1219
|
import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1161
1220
|
function ChatBubble({ message, showAvatar = true }) {
|
|
1162
1221
|
const isUser = message.sender === "user";
|
|
@@ -1168,7 +1227,7 @@ function ChatBubble({ message, showAvatar = true }) {
|
|
|
1168
1227
|
gap: "$2",
|
|
1169
1228
|
flexDirection: isUser ? "row-reverse" : "row",
|
|
1170
1229
|
children: [
|
|
1171
|
-
showAvatar && !isUser && /* @__PURE__ */ jsx22(
|
|
1230
|
+
showAvatar && !isUser && /* @__PURE__ */ jsx22(Circle3, { size: 32, backgroundColor: "$color4", overflow: "hidden", children: message.avatar ? /* @__PURE__ */ jsx22(Image3, { source: { uri: message.avatar }, width: 32, height: 32, objectFit: "cover" }) : /* @__PURE__ */ jsx22(SizableText19, { size: "$2", fontWeight: "600", color: "$color11", children: message.senderName?.[0]?.toUpperCase() ?? "?" }) }),
|
|
1172
1231
|
/* @__PURE__ */ jsxs15(
|
|
1173
1232
|
YStack16,
|
|
1174
1233
|
{
|
|
@@ -1267,11 +1326,11 @@ function EmptyState({ icon, title, description, actionLabel, onAction }) {
|
|
|
1267
1326
|
}
|
|
1268
1327
|
|
|
1269
1328
|
// src/patterns/ProfileHeader.tsx
|
|
1270
|
-
import { Circle as
|
|
1329
|
+
import { Circle as Circle4, Image as Image4, SizableText as SizableText22, XStack as XStack14, YStack as YStack19 } from "tamagui";
|
|
1271
1330
|
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1272
1331
|
function ProfileHeader({ name, subtitle, avatar, stats, actions }) {
|
|
1273
1332
|
return /* @__PURE__ */ jsxs18(YStack19, { alignItems: "center", gap: "$4", paddingVertical: "$6", paddingHorizontal: "$4", children: [
|
|
1274
|
-
/* @__PURE__ */ jsx25(
|
|
1333
|
+
/* @__PURE__ */ jsx25(Circle4, { size: 80, backgroundColor: "$color4", overflow: "hidden", children: avatar ? /* @__PURE__ */ jsx25(Image4, { source: { uri: avatar }, width: 80, height: 80, objectFit: "cover" }) : /* @__PURE__ */ jsx25(SizableText22, { size: "$9", fontWeight: "700", color: "$color11", children: name[0]?.toUpperCase() ?? "?" }) }),
|
|
1275
1334
|
/* @__PURE__ */ jsxs18(YStack19, { alignItems: "center", gap: "$1", children: [
|
|
1276
1335
|
/* @__PURE__ */ jsx25(SizableText22, { size: "$7", fontWeight: "700", children: name }),
|
|
1277
1336
|
subtitle && /* @__PURE__ */ jsx25(SizableText22, { size: "$4", color: "$color10", children: subtitle })
|
|
@@ -1316,42 +1375,55 @@ function AppHeader({ title, subtitle, variant = "simple", onBack, avatar, left,
|
|
|
1316
1375
|
|
|
1317
1376
|
// src/patterns/BottomSheet.tsx
|
|
1318
1377
|
import { Sheet, SizableText as SizableText24, XStack as XStack16, YStack as YStack21 } from "tamagui";
|
|
1319
|
-
import { ScrollView as
|
|
1378
|
+
import { ScrollView as ScrollView3 } from "react-native";
|
|
1320
1379
|
import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1321
|
-
function BottomSheet({ open, onOpenChange, title, children, snapPoints = [85], dismissOnSnapToBottom = true, showHandle = true, showClose = false }) {
|
|
1322
|
-
return /* @__PURE__ */ jsxs20(
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1380
|
+
function BottomSheet({ open, onOpenChange, title, children, snapPoints = [85], dismissOnSnapToBottom = true, showHandle = true, showClose = false, zIndex = 1e5 }) {
|
|
1381
|
+
return /* @__PURE__ */ jsxs20(
|
|
1382
|
+
Sheet,
|
|
1383
|
+
{
|
|
1384
|
+
modal: true,
|
|
1385
|
+
forceRemoveScrollEnabled: open,
|
|
1386
|
+
open,
|
|
1387
|
+
onOpenChange,
|
|
1388
|
+
snapPoints,
|
|
1389
|
+
dismissOnSnapToBottom,
|
|
1390
|
+
zIndex,
|
|
1391
|
+
animation: "medium",
|
|
1392
|
+
children: [
|
|
1393
|
+
/* @__PURE__ */ jsx27(Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
|
|
1394
|
+
showHandle && /* @__PURE__ */ jsx27(Sheet.Handle, {}),
|
|
1395
|
+
/* @__PURE__ */ jsxs20(Sheet.Frame, { children: [
|
|
1396
|
+
(title || showClose) && /* @__PURE__ */ jsxs20(XStack16, { paddingHorizontal: "$4", paddingTop: "$3", paddingBottom: "$2", alignItems: "center", justifyContent: "space-between", children: [
|
|
1397
|
+
/* @__PURE__ */ jsx27(SizableText24, { size: "$6", fontWeight: "600", flexShrink: 1, children: title }),
|
|
1398
|
+
showClose && /* @__PURE__ */ jsx27(
|
|
1399
|
+
XStack16,
|
|
1400
|
+
{
|
|
1401
|
+
width: 28,
|
|
1402
|
+
height: 28,
|
|
1403
|
+
borderRadius: "$10",
|
|
1404
|
+
backgroundColor: "$color4",
|
|
1405
|
+
alignItems: "center",
|
|
1406
|
+
justifyContent: "center",
|
|
1407
|
+
pressStyle: { opacity: 0.7 },
|
|
1408
|
+
onPress: () => onOpenChange(false),
|
|
1409
|
+
children: /* @__PURE__ */ jsx27(SizableText24, { size: "$3", color: "$color10", fontWeight: "600", children: "\u2715" })
|
|
1410
|
+
}
|
|
1411
|
+
)
|
|
1412
|
+
] }),
|
|
1413
|
+
/* @__PURE__ */ jsx27(ScrollView3, { contentContainerStyle: { paddingBottom: 40 }, children: /* @__PURE__ */ jsx27(YStack21, { padding: "$4", children }) })
|
|
1414
|
+
] })
|
|
1415
|
+
]
|
|
1416
|
+
}
|
|
1417
|
+
);
|
|
1346
1418
|
}
|
|
1347
1419
|
|
|
1348
1420
|
// src/patterns/LoginScreen.tsx
|
|
1349
|
-
import { useState as
|
|
1421
|
+
import { useState as useState7 } from "react";
|
|
1350
1422
|
import { Button as Button6, SizableText as SizableText25, Spinner, XStack as XStack17, YStack as YStack22 } from "tamagui";
|
|
1351
1423
|
import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1352
1424
|
function LoginScreen({ title = "Welcome", subtitle = "Sign in to continue", logo, providers = [], onProviderPress, showEmailForm, onEmailSubmit, onForgotPassword, onCreateAccount, onTerms, onPrivacy, loading }) {
|
|
1353
|
-
const [email, setEmail] =
|
|
1354
|
-
const [password, setPassword] =
|
|
1425
|
+
const [email, setEmail] = useState7("");
|
|
1426
|
+
const [password, setPassword] = useState7("");
|
|
1355
1427
|
return /* @__PURE__ */ jsxs21(YStack22, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", justifyContent: "center", children: [
|
|
1356
1428
|
/* @__PURE__ */ jsxs21(YStack22, { alignItems: "center", gap: "$2", children: [
|
|
1357
1429
|
logo && /* @__PURE__ */ jsx28(YStack22, { paddingBottom: "$3", children: logo }),
|
|
@@ -1498,55 +1570,68 @@ function FloatingActionButton({ icon, label, onPress, position = "bottom-right",
|
|
|
1498
1570
|
// src/patterns/ActionSheet.tsx
|
|
1499
1571
|
import { Sheet as Sheet2, SizableText as SizableText29, XStack as XStack21, YStack as YStack24 } from "tamagui";
|
|
1500
1572
|
import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1501
|
-
function ActionSheet({ open, onOpenChange, title, items, onSelect, cancelLabel = "Cancel" }) {
|
|
1502
|
-
return /* @__PURE__ */ jsxs25(
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1573
|
+
function ActionSheet({ open, onOpenChange, title, items, onSelect, cancelLabel = "Cancel", zIndex = 1e5 }) {
|
|
1574
|
+
return /* @__PURE__ */ jsxs25(
|
|
1575
|
+
Sheet2,
|
|
1576
|
+
{
|
|
1577
|
+
modal: true,
|
|
1578
|
+
forceRemoveScrollEnabled: open,
|
|
1579
|
+
open,
|
|
1580
|
+
onOpenChange,
|
|
1581
|
+
snapPoints: [50],
|
|
1582
|
+
dismissOnSnapToBottom: true,
|
|
1583
|
+
zIndex,
|
|
1584
|
+
animation: "medium",
|
|
1585
|
+
children: [
|
|
1586
|
+
/* @__PURE__ */ jsx32(Sheet2.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
|
|
1587
|
+
/* @__PURE__ */ jsx32(Sheet2.Handle, {}),
|
|
1588
|
+
/* @__PURE__ */ jsxs25(Sheet2.Frame, { children: [
|
|
1589
|
+
title && /* @__PURE__ */ jsx32(SizableText29, { size: "$3", color: "$color8", textAlign: "center", paddingTop: "$3", paddingBottom: "$1", children: title }),
|
|
1590
|
+
/* @__PURE__ */ jsx32(YStack24, { paddingHorizontal: "$3", paddingTop: "$2", children: items.map((item) => /* @__PURE__ */ jsxs25(
|
|
1591
|
+
XStack21,
|
|
1592
|
+
{
|
|
1593
|
+
height: 52,
|
|
1594
|
+
alignItems: "center",
|
|
1595
|
+
gap: "$3",
|
|
1596
|
+
paddingHorizontal: "$3",
|
|
1597
|
+
borderRadius: "$4",
|
|
1598
|
+
pressStyle: { backgroundColor: "$color3" },
|
|
1599
|
+
onPress: () => {
|
|
1600
|
+
onSelect(item.id);
|
|
1601
|
+
onOpenChange(false);
|
|
1602
|
+
},
|
|
1603
|
+
children: [
|
|
1604
|
+
item.icon && /* @__PURE__ */ jsx32(SizableText29, { size: "$5", children: item.icon }),
|
|
1605
|
+
/* @__PURE__ */ jsx32(
|
|
1606
|
+
SizableText29,
|
|
1607
|
+
{
|
|
1608
|
+
size: "$5",
|
|
1609
|
+
flex: 1,
|
|
1610
|
+
color: item.destructive ? "$red9" : "$color12",
|
|
1611
|
+
fontWeight: item.destructive ? "600" : "400",
|
|
1612
|
+
children: item.label
|
|
1613
|
+
}
|
|
1614
|
+
)
|
|
1615
|
+
]
|
|
1616
|
+
},
|
|
1617
|
+
item.id
|
|
1618
|
+
)) }),
|
|
1619
|
+
/* @__PURE__ */ jsx32(YStack24, { paddingHorizontal: "$3", paddingVertical: "$3", borderTopWidth: 1, borderTopColor: "$borderColor", marginTop: "$2", children: /* @__PURE__ */ jsx32(
|
|
1620
|
+
XStack21,
|
|
1621
|
+
{
|
|
1622
|
+
height: 48,
|
|
1623
|
+
alignItems: "center",
|
|
1624
|
+
justifyContent: "center",
|
|
1625
|
+
borderRadius: "$4",
|
|
1626
|
+
pressStyle: { backgroundColor: "$color3" },
|
|
1627
|
+
onPress: () => onOpenChange(false),
|
|
1628
|
+
children: /* @__PURE__ */ jsx32(SizableText29, { size: "$5", fontWeight: "600", color: "$color9", children: cancelLabel })
|
|
1629
|
+
}
|
|
1630
|
+
) })
|
|
1631
|
+
] })
|
|
1632
|
+
]
|
|
1633
|
+
}
|
|
1634
|
+
);
|
|
1550
1635
|
}
|
|
1551
1636
|
|
|
1552
1637
|
// src/patterns/Skeleton.tsx
|
|
@@ -1594,7 +1679,7 @@ function NotificationBanner({ title, message, variant = "info", onPress, onDismi
|
|
|
1594
1679
|
}
|
|
1595
1680
|
|
|
1596
1681
|
// src/patterns/ProgressSteps.tsx
|
|
1597
|
-
import { Circle as
|
|
1682
|
+
import { Circle as Circle5, SizableText as SizableText31, XStack as XStack23, YStack as YStack27 } from "tamagui";
|
|
1598
1683
|
import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1599
1684
|
function ProgressSteps({ steps, currentStep, variant = "dots" }) {
|
|
1600
1685
|
if (variant === "bar") {
|
|
@@ -1606,7 +1691,7 @@ function ProgressSteps({ steps, currentStep, variant = "dots" }) {
|
|
|
1606
1691
|
}
|
|
1607
1692
|
return /* @__PURE__ */ jsx35(XStack23, { alignItems: "center", justifyContent: "center", gap: "$0", children: steps.map((label, i) => /* @__PURE__ */ jsxs27(XStack23, { alignItems: "center", gap: "$0", children: [
|
|
1608
1693
|
/* @__PURE__ */ jsxs27(YStack27, { alignItems: "center", gap: "$1.5", children: [
|
|
1609
|
-
/* @__PURE__ */ jsx35(
|
|
1694
|
+
/* @__PURE__ */ jsx35(Circle5, { size: variant === "numbered" ? 28 : 10, backgroundColor: i <= currentStep ? "$color9" : "$color4", animation: "quick", children: variant === "numbered" && /* @__PURE__ */ jsx35(SizableText31, { size: "$2", fontWeight: "600", color: i <= currentStep ? "$color1" : "$color8", children: i + 1 }) }),
|
|
1610
1695
|
/* @__PURE__ */ jsx35(SizableText31, { size: "$1", color: i <= currentStep ? "$color11" : "$color8", numberOfLines: 1, children: label })
|
|
1611
1696
|
] }),
|
|
1612
1697
|
i < steps.length - 1 && /* @__PURE__ */ jsx35(YStack27, { height: 2, width: 32, backgroundColor: i < currentStep ? "$color9" : "$color4", marginBottom: "$4" })
|
|
@@ -1614,11 +1699,11 @@ function ProgressSteps({ steps, currentStep, variant = "dots" }) {
|
|
|
1614
1699
|
}
|
|
1615
1700
|
|
|
1616
1701
|
// src/patterns/SwipeableRow.tsx
|
|
1617
|
-
import { useState as
|
|
1702
|
+
import { useState as useState8 } from "react";
|
|
1618
1703
|
import { Button as Button7, SizableText as SizableText32, XStack as XStack24, YStack as YStack28 } from "tamagui";
|
|
1619
1704
|
import { Fragment as Fragment2, jsx as jsx36, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1620
1705
|
function SwipeableRow({ children, leftActions, rightActions }) {
|
|
1621
|
-
const [showActions, setShowActions] =
|
|
1706
|
+
const [showActions, setShowActions] = useState8(false);
|
|
1622
1707
|
const actions = [...leftActions ?? [], ...rightActions ?? []];
|
|
1623
1708
|
if (actions.length === 0) return /* @__PURE__ */ jsx36(Fragment2, { children });
|
|
1624
1709
|
return /* @__PURE__ */ jsxs28(YStack28, { children: [
|
|
@@ -1693,17 +1778,17 @@ function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio =
|
|
|
1693
1778
|
}
|
|
1694
1779
|
|
|
1695
1780
|
// src/patterns/Carousel.tsx
|
|
1696
|
-
import { Children as Children2, useState as
|
|
1697
|
-
import { Circle as
|
|
1698
|
-
import { ScrollView as
|
|
1781
|
+
import { Children as Children2, useState as useState9 } from "react";
|
|
1782
|
+
import { Circle as Circle6, XStack as XStack26, YStack as YStack30 } from "tamagui";
|
|
1783
|
+
import { ScrollView as ScrollView4 } from "react-native";
|
|
1699
1784
|
import { jsx as jsx38, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
1700
1785
|
function Carousel({ children, gap = "$3", snapToInterval, showIndicators = false }) {
|
|
1701
|
-
const [activeIndex, setActiveIndex] =
|
|
1786
|
+
const [activeIndex, setActiveIndex] = useState9(0);
|
|
1702
1787
|
const count = Children2.count(children);
|
|
1703
1788
|
const gapPx = gap === "$2" ? 8 : gap === "$3" ? 12 : 16;
|
|
1704
1789
|
return /* @__PURE__ */ jsxs30(YStack30, { gap: "$3", children: [
|
|
1705
1790
|
/* @__PURE__ */ jsx38(
|
|
1706
|
-
|
|
1791
|
+
ScrollView4,
|
|
1707
1792
|
{
|
|
1708
1793
|
horizontal: true,
|
|
1709
1794
|
showsHorizontalScrollIndicator: false,
|
|
@@ -1716,17 +1801,17 @@ function Carousel({ children, gap = "$3", snapToInterval, showIndicators = false
|
|
|
1716
1801
|
children
|
|
1717
1802
|
}
|
|
1718
1803
|
),
|
|
1719
|
-
showIndicators && count > 1 && /* @__PURE__ */ jsx38(XStack26, { justifyContent: "center", gap: "$1.5", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx38(
|
|
1804
|
+
showIndicators && count > 1 && /* @__PURE__ */ jsx38(XStack26, { justifyContent: "center", gap: "$1.5", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx38(Circle6, { size: 6, backgroundColor: i === activeIndex ? "$color9" : "$color4", animation: "quick" }, i)) })
|
|
1720
1805
|
] });
|
|
1721
1806
|
}
|
|
1722
1807
|
|
|
1723
1808
|
// src/patterns/PullToRefresh.tsx
|
|
1724
1809
|
import { YStack as YStack31 } from "tamagui";
|
|
1725
|
-
import { RefreshControl, ScrollView as
|
|
1810
|
+
import { RefreshControl, ScrollView as ScrollView5 } from "react-native";
|
|
1726
1811
|
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
1727
1812
|
function PullToRefresh({ children, onRefresh, refreshing = false }) {
|
|
1728
1813
|
return /* @__PURE__ */ jsx39(
|
|
1729
|
-
|
|
1814
|
+
ScrollView5,
|
|
1730
1815
|
{
|
|
1731
1816
|
contentContainerStyle: { flexGrow: 1 },
|
|
1732
1817
|
refreshControl: /* @__PURE__ */ jsx39(RefreshControl, { refreshing, onRefresh }),
|
|
@@ -1734,17 +1819,849 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
|
|
|
1734
1819
|
}
|
|
1735
1820
|
);
|
|
1736
1821
|
}
|
|
1822
|
+
|
|
1823
|
+
// src/patterns/ProductCard.tsx
|
|
1824
|
+
import { Button as Button8, Image as Image6, SizableText as SizableText34, XStack as XStack27, YStack as YStack32 } from "tamagui";
|
|
1825
|
+
import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
1826
|
+
function Stars({ rating = 0 }) {
|
|
1827
|
+
return /* @__PURE__ */ jsx40(XStack27, { gap: "$0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx40(SizableText34, { size: "$2", color: i < Math.round(rating) ? "$yellow9" : "$color5", children: "\u2605" }, i)) });
|
|
1828
|
+
}
|
|
1829
|
+
function CardContent2({ title, price, originalPrice, rating, reviewCount, onAddToCart }) {
|
|
1830
|
+
return /* @__PURE__ */ jsxs31(YStack32, { flex: 1, gap: "$1.5", justifyContent: "space-between", children: [
|
|
1831
|
+
/* @__PURE__ */ jsxs31(YStack32, { gap: "$1", children: [
|
|
1832
|
+
/* @__PURE__ */ jsx40(SizableText34, { size: "$4", fontWeight: "600", numberOfLines: 2, children: title }),
|
|
1833
|
+
rating !== void 0 && /* @__PURE__ */ jsxs31(XStack27, { gap: "$1.5", alignItems: "center", children: [
|
|
1834
|
+
/* @__PURE__ */ jsx40(Stars, { rating }),
|
|
1835
|
+
reviewCount !== void 0 && /* @__PURE__ */ jsxs31(SizableText34, { size: "$2", color: "$color9", children: [
|
|
1836
|
+
"(",
|
|
1837
|
+
reviewCount,
|
|
1838
|
+
")"
|
|
1839
|
+
] })
|
|
1840
|
+
] })
|
|
1841
|
+
] }),
|
|
1842
|
+
/* @__PURE__ */ jsxs31(XStack27, { alignItems: "center", justifyContent: "space-between", children: [
|
|
1843
|
+
/* @__PURE__ */ jsxs31(XStack27, { gap: "$2", alignItems: "baseline", children: [
|
|
1844
|
+
/* @__PURE__ */ jsx40(SizableText34, { size: "$6", fontWeight: "700", children: price }),
|
|
1845
|
+
originalPrice && /* @__PURE__ */ jsx40(SizableText34, { size: "$3", color: "$color8", textDecorationLine: "line-through", children: originalPrice })
|
|
1846
|
+
] }),
|
|
1847
|
+
onAddToCart && /* @__PURE__ */ jsx40(
|
|
1848
|
+
Button8,
|
|
1849
|
+
{
|
|
1850
|
+
size: "$3",
|
|
1851
|
+
backgroundColor: "$color9",
|
|
1852
|
+
color: "$color1",
|
|
1853
|
+
borderRadius: "$10",
|
|
1854
|
+
onPress: (e) => {
|
|
1855
|
+
e.stopPropagation?.();
|
|
1856
|
+
onAddToCart();
|
|
1857
|
+
},
|
|
1858
|
+
pressStyle: { backgroundColor: "$color8", scale: 0.95 },
|
|
1859
|
+
animation: "quick",
|
|
1860
|
+
children: "+ Cart"
|
|
1861
|
+
}
|
|
1862
|
+
)
|
|
1863
|
+
] })
|
|
1864
|
+
] });
|
|
1865
|
+
}
|
|
1866
|
+
function ProductCard({ image, title, price, originalPrice, rating, reviewCount, badge, onPress, onAddToCart, variant = "vertical" }) {
|
|
1867
|
+
const isHorizontal = variant === "horizontal";
|
|
1868
|
+
const Wrapper = isHorizontal ? XStack27 : YStack32;
|
|
1869
|
+
return /* @__PURE__ */ jsxs31(
|
|
1870
|
+
Wrapper,
|
|
1871
|
+
{
|
|
1872
|
+
backgroundColor: "$color1",
|
|
1873
|
+
borderRadius: "$5",
|
|
1874
|
+
overflow: "hidden",
|
|
1875
|
+
borderWidth: 1,
|
|
1876
|
+
borderColor: "$color4",
|
|
1877
|
+
onPress,
|
|
1878
|
+
animation: "quick",
|
|
1879
|
+
pressStyle: onPress ? { scale: 0.98, opacity: 0.9 } : void 0,
|
|
1880
|
+
...isHorizontal ? { height: 140 } : {},
|
|
1881
|
+
children: [
|
|
1882
|
+
/* @__PURE__ */ jsxs31(YStack32, { ...isHorizontal ? { width: 140 } : { aspectRatio: 4 / 3 }, position: "relative", children: [
|
|
1883
|
+
/* @__PURE__ */ jsx40(Image6, { source: { uri: image }, width: "100%", height: "100%", objectFit: "cover" }),
|
|
1884
|
+
badge && /* @__PURE__ */ jsx40(
|
|
1885
|
+
XStack27,
|
|
1886
|
+
{
|
|
1887
|
+
position: "absolute",
|
|
1888
|
+
top: "$2",
|
|
1889
|
+
left: "$2",
|
|
1890
|
+
backgroundColor: "$red9",
|
|
1891
|
+
paddingHorizontal: "$2",
|
|
1892
|
+
paddingVertical: "$1",
|
|
1893
|
+
borderRadius: "$10",
|
|
1894
|
+
children: /* @__PURE__ */ jsx40(SizableText34, { size: "$1", fontWeight: "700", color: "white", children: badge })
|
|
1895
|
+
}
|
|
1896
|
+
)
|
|
1897
|
+
] }),
|
|
1898
|
+
/* @__PURE__ */ jsx40(YStack32, { flex: 1, padding: "$3", children: /* @__PURE__ */ jsx40(CardContent2, { ...{ title, price, originalPrice, rating, reviewCount, onAddToCart } }) })
|
|
1899
|
+
]
|
|
1900
|
+
}
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
// src/patterns/PricingTable.tsx
|
|
1905
|
+
import { Button as Button9, ScrollView as ScrollView6, SizableText as SizableText35, XStack as XStack28, YStack as YStack33 } from "tamagui";
|
|
1906
|
+
import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
1907
|
+
function BillingToggle({ annual, onToggle }) {
|
|
1908
|
+
return /* @__PURE__ */ jsx41(XStack28, { alignSelf: "center", backgroundColor: "$color3", borderRadius: "$10", padding: "$1", gap: "$0.5", children: ["Monthly", "Annual"].map((label, i) => {
|
|
1909
|
+
const active = i === 1 ? annual : !annual;
|
|
1910
|
+
return /* @__PURE__ */ jsx41(
|
|
1911
|
+
XStack28,
|
|
1912
|
+
{
|
|
1913
|
+
paddingHorizontal: "$4",
|
|
1914
|
+
paddingVertical: "$2",
|
|
1915
|
+
borderRadius: "$10",
|
|
1916
|
+
backgroundColor: active ? "$color9" : "transparent",
|
|
1917
|
+
onPress: () => onToggle(i === 1),
|
|
1918
|
+
pressStyle: { opacity: 0.8 },
|
|
1919
|
+
animation: "quick",
|
|
1920
|
+
children: /* @__PURE__ */ jsx41(SizableText35, { size: "$3", fontWeight: "600", color: active ? "$color1" : "$color10", children: label })
|
|
1921
|
+
},
|
|
1922
|
+
label
|
|
1923
|
+
);
|
|
1924
|
+
}) });
|
|
1925
|
+
}
|
|
1926
|
+
function PlanCard2({ plan, selected, onSelect }) {
|
|
1927
|
+
return /* @__PURE__ */ jsxs32(
|
|
1928
|
+
YStack33,
|
|
1929
|
+
{
|
|
1930
|
+
flex: 1,
|
|
1931
|
+
minWidth: 260,
|
|
1932
|
+
padding: "$4",
|
|
1933
|
+
borderRadius: "$5",
|
|
1934
|
+
gap: "$3",
|
|
1935
|
+
borderWidth: 2,
|
|
1936
|
+
borderColor: selected ? "$color9" : plan.popular ? "$color9" : "$color4",
|
|
1937
|
+
backgroundColor: plan.popular ? "$color2" : "$color1",
|
|
1938
|
+
position: "relative",
|
|
1939
|
+
pressStyle: { scale: 0.98 },
|
|
1940
|
+
animation: "quick",
|
|
1941
|
+
onPress: onSelect,
|
|
1942
|
+
children: [
|
|
1943
|
+
plan.popular && /* @__PURE__ */ jsx41(
|
|
1944
|
+
XStack28,
|
|
1945
|
+
{
|
|
1946
|
+
position: "absolute",
|
|
1947
|
+
top: -12,
|
|
1948
|
+
alignSelf: "center",
|
|
1949
|
+
backgroundColor: "$color9",
|
|
1950
|
+
paddingHorizontal: "$3",
|
|
1951
|
+
paddingVertical: "$1",
|
|
1952
|
+
borderRadius: "$10",
|
|
1953
|
+
children: /* @__PURE__ */ jsx41(SizableText35, { size: "$1", fontWeight: "700", color: "$color1", children: "POPULAR" })
|
|
1954
|
+
}
|
|
1955
|
+
),
|
|
1956
|
+
/* @__PURE__ */ jsxs32(YStack33, { gap: "$1", alignItems: "center", paddingTop: plan.popular ? "$2" : 0, children: [
|
|
1957
|
+
/* @__PURE__ */ jsx41(SizableText35, { size: "$4", fontWeight: "600", color: "$color11", children: plan.name }),
|
|
1958
|
+
plan.description && /* @__PURE__ */ jsx41(SizableText35, { size: "$2", color: "$color9", textAlign: "center", children: plan.description }),
|
|
1959
|
+
/* @__PURE__ */ jsxs32(XStack28, { alignItems: "baseline", gap: "$1", children: [
|
|
1960
|
+
/* @__PURE__ */ jsx41(SizableText35, { size: "$9", fontWeight: "800", children: plan.price }),
|
|
1961
|
+
plan.period && /* @__PURE__ */ jsxs32(SizableText35, { size: "$3", color: "$color9", children: [
|
|
1962
|
+
"/",
|
|
1963
|
+
plan.period
|
|
1964
|
+
] })
|
|
1965
|
+
] })
|
|
1966
|
+
] }),
|
|
1967
|
+
/* @__PURE__ */ jsx41(YStack33, { gap: "$2", flex: 1, children: plan.features.map((f, i) => /* @__PURE__ */ jsxs32(XStack28, { gap: "$2", alignItems: "center", children: [
|
|
1968
|
+
/* @__PURE__ */ jsx41(SizableText35, { size: "$3", color: f.included ? "$green9" : "$color6", children: f.included ? "\u2713" : "\u2717" }),
|
|
1969
|
+
/* @__PURE__ */ jsx41(SizableText35, { size: "$3", color: f.included ? "$color11" : "$color8", flex: 1, children: f.label })
|
|
1970
|
+
] }, i)) }),
|
|
1971
|
+
/* @__PURE__ */ jsx41(
|
|
1972
|
+
Button9,
|
|
1973
|
+
{
|
|
1974
|
+
size: "$4",
|
|
1975
|
+
borderRadius: "$10",
|
|
1976
|
+
fontWeight: "700",
|
|
1977
|
+
animation: "quick",
|
|
1978
|
+
backgroundColor: selected || plan.popular ? "$color9" : "transparent",
|
|
1979
|
+
color: selected || plan.popular ? "$color1" : "$color11",
|
|
1980
|
+
borderWidth: selected || plan.popular ? 0 : 1,
|
|
1981
|
+
borderColor: "$color7",
|
|
1982
|
+
onPress: onSelect,
|
|
1983
|
+
pressStyle: { scale: 0.97, opacity: 0.9 },
|
|
1984
|
+
children: plan.cta ?? "Get Started"
|
|
1985
|
+
}
|
|
1986
|
+
)
|
|
1987
|
+
]
|
|
1988
|
+
}
|
|
1989
|
+
);
|
|
1990
|
+
}
|
|
1991
|
+
function PricingTable({ plans, selectedPlan, onSelectPlan, annual = false, onToggleBilling }) {
|
|
1992
|
+
const selected = selectedPlan ?? plans.find((p) => p.popular)?.id;
|
|
1993
|
+
return /* @__PURE__ */ jsxs32(YStack33, { gap: "$4", children: [
|
|
1994
|
+
onToggleBilling && /* @__PURE__ */ jsx41(BillingToggle, { annual, onToggle: onToggleBilling }),
|
|
1995
|
+
/* @__PURE__ */ jsx41(
|
|
1996
|
+
ScrollView6,
|
|
1997
|
+
{
|
|
1998
|
+
horizontal: true,
|
|
1999
|
+
showsHorizontalScrollIndicator: false,
|
|
2000
|
+
contentContainerStyle: { gap: 12, paddingHorizontal: 4 },
|
|
2001
|
+
children: plans.map((plan) => /* @__PURE__ */ jsx41(
|
|
2002
|
+
PlanCard2,
|
|
2003
|
+
{
|
|
2004
|
+
plan,
|
|
2005
|
+
selected: selected === plan.id,
|
|
2006
|
+
onSelect: () => onSelectPlan?.(plan.id)
|
|
2007
|
+
},
|
|
2008
|
+
plan.id
|
|
2009
|
+
))
|
|
2010
|
+
}
|
|
2011
|
+
)
|
|
2012
|
+
] });
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
// src/patterns/CountdownBanner.tsx
|
|
2016
|
+
import { useState as useState10, useEffect as useEffect4, useRef, useCallback as useCallback2 } from "react";
|
|
2017
|
+
import { SizableText as SizableText36, XStack as XStack29, YStack as YStack34 } from "tamagui";
|
|
2018
|
+
import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2019
|
+
function useCountdown2(endTime, minutes, onExpire) {
|
|
2020
|
+
const getRemaining = useCallback2(() => {
|
|
2021
|
+
if (endTime) return Math.max(0, Math.floor((endTime.getTime() - Date.now()) / 1e3));
|
|
2022
|
+
return 0;
|
|
2023
|
+
}, [endTime]);
|
|
2024
|
+
const [seconds, setSeconds] = useState10(() => endTime ? getRemaining() : (minutes ?? 0) * 60);
|
|
2025
|
+
const firedRef = useRef(false);
|
|
2026
|
+
useEffect4(() => {
|
|
2027
|
+
if (endTime) setSeconds(getRemaining());
|
|
2028
|
+
else setSeconds((minutes ?? 0) * 60);
|
|
2029
|
+
firedRef.current = false;
|
|
2030
|
+
}, [endTime, minutes, getRemaining]);
|
|
2031
|
+
useEffect4(() => {
|
|
2032
|
+
if (seconds <= 0) return;
|
|
2033
|
+
const id = setInterval(() => {
|
|
2034
|
+
setSeconds((s) => {
|
|
2035
|
+
const next = endTime ? Math.max(0, Math.floor((endTime.getTime() - Date.now()) / 1e3)) : s - 1;
|
|
2036
|
+
if (next <= 0 && !firedRef.current) {
|
|
2037
|
+
firedRef.current = true;
|
|
2038
|
+
onExpire?.();
|
|
2039
|
+
}
|
|
2040
|
+
return Math.max(0, next);
|
|
2041
|
+
});
|
|
2042
|
+
}, 1e3);
|
|
2043
|
+
return () => clearInterval(id);
|
|
2044
|
+
}, [seconds > 0, endTime, onExpire]);
|
|
2045
|
+
const hh = String(Math.floor(seconds / 3600)).padStart(2, "0");
|
|
2046
|
+
const mm = String(Math.floor(seconds % 3600 / 60)).padStart(2, "0");
|
|
2047
|
+
const ss = String(seconds % 60).padStart(2, "0");
|
|
2048
|
+
const display = seconds >= 3600 ? `${hh}:${mm}:${ss}` : `${mm}:${ss}`;
|
|
2049
|
+
return { display, expired: seconds <= 0 };
|
|
2050
|
+
}
|
|
2051
|
+
function TimeBox({ value }) {
|
|
2052
|
+
return /* @__PURE__ */ jsx42(XStack29, { backgroundColor: "rgba(0,0,0,0.15)", paddingHorizontal: "$2", paddingVertical: "$1", borderRadius: "$3", children: /* @__PURE__ */ jsx42(SizableText36, { size: "$6", fontWeight: "800", color: "white", fontFamily: "$mono", children: value }) });
|
|
2053
|
+
}
|
|
2054
|
+
function CountdownBanner({ endTime, minutes, label = "Offer ends in", onExpire, variant = "banner" }) {
|
|
2055
|
+
const { display, expired } = useCountdown2(endTime, minutes, onExpire);
|
|
2056
|
+
if (expired) return null;
|
|
2057
|
+
const parts = display.split(":");
|
|
2058
|
+
if (variant === "badge") {
|
|
2059
|
+
return /* @__PURE__ */ jsxs33(XStack29, { backgroundColor: "$red9", paddingHorizontal: "$2.5", paddingVertical: "$1", borderRadius: "$10", gap: "$1.5", alignItems: "center", children: [
|
|
2060
|
+
/* @__PURE__ */ jsx42(SizableText36, { size: "$1", fontWeight: "600", color: "white", children: label }),
|
|
2061
|
+
/* @__PURE__ */ jsx42(SizableText36, { size: "$2", fontWeight: "800", color: "white", fontFamily: "$mono", children: display })
|
|
2062
|
+
] });
|
|
2063
|
+
}
|
|
2064
|
+
if (variant === "compact") {
|
|
2065
|
+
return /* @__PURE__ */ jsxs33(XStack29, { backgroundColor: "$red3", paddingHorizontal: "$3", paddingVertical: "$2", borderRadius: "$4", gap: "$2", alignItems: "center", alignSelf: "center", children: [
|
|
2066
|
+
/* @__PURE__ */ jsx42(SizableText36, { size: "$3", fontWeight: "600", color: "$red9", children: label }),
|
|
2067
|
+
/* @__PURE__ */ jsx42(SizableText36, { size: "$5", fontWeight: "800", color: "$red9", fontFamily: "$mono", children: display })
|
|
2068
|
+
] });
|
|
2069
|
+
}
|
|
2070
|
+
return /* @__PURE__ */ jsxs33(YStack34, { backgroundColor: "$red9", paddingVertical: "$3", paddingHorizontal: "$4", gap: "$1.5", alignItems: "center", children: [
|
|
2071
|
+
/* @__PURE__ */ jsx42(SizableText36, { size: "$3", fontWeight: "600", color: "white", opacity: 0.9, children: label }),
|
|
2072
|
+
/* @__PURE__ */ jsx42(XStack29, { gap: "$1.5", alignItems: "center", children: parts.map((p, i) => /* @__PURE__ */ jsxs33(XStack29, { gap: "$1.5", alignItems: "center", children: [
|
|
2073
|
+
i > 0 && /* @__PURE__ */ jsx42(SizableText36, { size: "$6", fontWeight: "800", color: "white", children: ":" }),
|
|
2074
|
+
/* @__PURE__ */ jsx42(TimeBox, { value: p })
|
|
2075
|
+
] }, i)) })
|
|
2076
|
+
] });
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
// src/patterns/TestimonialCard.tsx
|
|
2080
|
+
import { Image as Image7, SizableText as SizableText37, XStack as XStack30, YStack as YStack35 } from "tamagui";
|
|
2081
|
+
import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2082
|
+
function Stars2({ count = 0 }) {
|
|
2083
|
+
if (!count) return null;
|
|
2084
|
+
return /* @__PURE__ */ jsx43(XStack30, { gap: "$0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx43(SizableText37, { size: "$3", color: i < Math.round(count) ? "$yellow9" : "$color5", children: "\u2605" }, i)) });
|
|
2085
|
+
}
|
|
2086
|
+
function AuthorRow({ author, role, avatar }) {
|
|
2087
|
+
return /* @__PURE__ */ jsxs34(XStack30, { gap: "$2.5", alignItems: "center", children: [
|
|
2088
|
+
avatar && /* @__PURE__ */ jsx43(Image7, { source: { uri: avatar }, width: 36, height: 36, borderRadius: 18, objectFit: "cover" }),
|
|
2089
|
+
/* @__PURE__ */ jsxs34(YStack35, { children: [
|
|
2090
|
+
/* @__PURE__ */ jsx43(SizableText37, { size: "$3", fontWeight: "600", children: author }),
|
|
2091
|
+
role && /* @__PURE__ */ jsx43(SizableText37, { size: "$2", color: "$color9", children: role })
|
|
2092
|
+
] })
|
|
2093
|
+
] });
|
|
2094
|
+
}
|
|
2095
|
+
function TestimonialCard({ quote, author, role, avatar, rating, variant = "card" }) {
|
|
2096
|
+
if (variant === "minimal") {
|
|
2097
|
+
return /* @__PURE__ */ jsxs34(YStack35, { gap: "$3", paddingVertical: "$2", children: [
|
|
2098
|
+
/* @__PURE__ */ jsx43(Stars2, { count: rating }),
|
|
2099
|
+
/* @__PURE__ */ jsxs34(SizableText37, { size: "$4", color: "$color11", fontStyle: "italic", lineHeight: 24, children: [
|
|
2100
|
+
'"',
|
|
2101
|
+
quote,
|
|
2102
|
+
'"'
|
|
2103
|
+
] }),
|
|
2104
|
+
/* @__PURE__ */ jsx43(AuthorRow, { author, role, avatar })
|
|
2105
|
+
] });
|
|
2106
|
+
}
|
|
2107
|
+
if (variant === "featured") {
|
|
2108
|
+
return /* @__PURE__ */ jsxs34(YStack35, { backgroundColor: "$color3", padding: "$5", borderRadius: "$6", gap: "$4", alignItems: "center", children: [
|
|
2109
|
+
/* @__PURE__ */ jsx43(SizableText37, { size: "$8", color: "$color9", opacity: 0.3, fontWeight: "800", children: '"' }),
|
|
2110
|
+
/* @__PURE__ */ jsx43(Stars2, { count: rating }),
|
|
2111
|
+
/* @__PURE__ */ jsxs34(SizableText37, { size: "$5", color: "$color12", fontStyle: "italic", textAlign: "center", lineHeight: 28, children: [
|
|
2112
|
+
'"',
|
|
2113
|
+
quote,
|
|
2114
|
+
'"'
|
|
2115
|
+
] }),
|
|
2116
|
+
/* @__PURE__ */ jsx43(AuthorRow, { author, role, avatar })
|
|
2117
|
+
] });
|
|
2118
|
+
}
|
|
2119
|
+
return /* @__PURE__ */ jsxs34(
|
|
2120
|
+
YStack35,
|
|
2121
|
+
{
|
|
2122
|
+
backgroundColor: "$color1",
|
|
2123
|
+
padding: "$4",
|
|
2124
|
+
borderRadius: "$5",
|
|
2125
|
+
borderWidth: 1,
|
|
2126
|
+
borderColor: "$color4",
|
|
2127
|
+
gap: "$3",
|
|
2128
|
+
children: [
|
|
2129
|
+
/* @__PURE__ */ jsx43(Stars2, { count: rating }),
|
|
2130
|
+
/* @__PURE__ */ jsxs34(SizableText37, { size: "$4", color: "$color11", fontStyle: "italic", lineHeight: 24, children: [
|
|
2131
|
+
'"',
|
|
2132
|
+
quote,
|
|
2133
|
+
'"'
|
|
2134
|
+
] }),
|
|
2135
|
+
/* @__PURE__ */ jsx43(AuthorRow, { author, role, avatar })
|
|
2136
|
+
]
|
|
2137
|
+
}
|
|
2138
|
+
);
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
// src/patterns/ConfirmDialog.tsx
|
|
2142
|
+
import { AlertDialog as AlertDialog2, Button as Button10, SizableText as SizableText38, XStack as XStack31, YStack as YStack36 } from "tamagui";
|
|
2143
|
+
import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2144
|
+
function ConfirmDialog({
|
|
2145
|
+
open,
|
|
2146
|
+
onOpenChange,
|
|
2147
|
+
title,
|
|
2148
|
+
description,
|
|
2149
|
+
confirmLabel = "Confirm",
|
|
2150
|
+
cancelLabel = "Cancel",
|
|
2151
|
+
onConfirm,
|
|
2152
|
+
onCancel,
|
|
2153
|
+
destructive = false,
|
|
2154
|
+
icon
|
|
2155
|
+
}) {
|
|
2156
|
+
const handleCancel = () => {
|
|
2157
|
+
onCancel?.();
|
|
2158
|
+
onOpenChange(false);
|
|
2159
|
+
};
|
|
2160
|
+
const handleConfirm = () => {
|
|
2161
|
+
onConfirm?.();
|
|
2162
|
+
onOpenChange(false);
|
|
2163
|
+
};
|
|
2164
|
+
return /* @__PURE__ */ jsx44(AlertDialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs35(AlertDialog2.Portal, { children: [
|
|
2165
|
+
/* @__PURE__ */ jsx44(
|
|
2166
|
+
AlertDialog2.Overlay,
|
|
2167
|
+
{
|
|
2168
|
+
opacity: 0.5,
|
|
2169
|
+
enterStyle: { opacity: 0 },
|
|
2170
|
+
exitStyle: { opacity: 0 },
|
|
2171
|
+
animation: "quick"
|
|
2172
|
+
},
|
|
2173
|
+
"overlay"
|
|
2174
|
+
),
|
|
2175
|
+
/* @__PURE__ */ jsx44(
|
|
2176
|
+
AlertDialog2.Content,
|
|
2177
|
+
{
|
|
2178
|
+
bordered: true,
|
|
2179
|
+
elevate: true,
|
|
2180
|
+
width: "90%",
|
|
2181
|
+
maxWidth: 400,
|
|
2182
|
+
enterStyle: { y: -20, opacity: 0, scale: 0.9 },
|
|
2183
|
+
exitStyle: { y: 10, opacity: 0, scale: 0.95 },
|
|
2184
|
+
x: 0,
|
|
2185
|
+
y: 0,
|
|
2186
|
+
scale: 1,
|
|
2187
|
+
opacity: 1,
|
|
2188
|
+
animation: "quick",
|
|
2189
|
+
children: /* @__PURE__ */ jsxs35(YStack36, { gap: "$4", padding: "$4", children: [
|
|
2190
|
+
icon && /* @__PURE__ */ jsx44(YStack36, { alignItems: "center", children: icon }),
|
|
2191
|
+
/* @__PURE__ */ jsxs35(YStack36, { gap: "$2", alignItems: icon ? "center" : "flex-start", children: [
|
|
2192
|
+
/* @__PURE__ */ jsx44(AlertDialog2.Title, { size: "$6", fontWeight: "700", children: title }),
|
|
2193
|
+
description && /* @__PURE__ */ jsx44(
|
|
2194
|
+
AlertDialog2.Description,
|
|
2195
|
+
{
|
|
2196
|
+
size: "$3",
|
|
2197
|
+
color: "$color10",
|
|
2198
|
+
textAlign: icon ? "center" : "left",
|
|
2199
|
+
children: description
|
|
2200
|
+
}
|
|
2201
|
+
)
|
|
2202
|
+
] }),
|
|
2203
|
+
/* @__PURE__ */ jsxs35(XStack31, { gap: "$3", justifyContent: "flex-end", children: [
|
|
2204
|
+
/* @__PURE__ */ jsx44(
|
|
2205
|
+
Button10,
|
|
2206
|
+
{
|
|
2207
|
+
flex: 1,
|
|
2208
|
+
size: "$4",
|
|
2209
|
+
borderRadius: "$4",
|
|
2210
|
+
variant: "outlined",
|
|
2211
|
+
borderColor: "$color7",
|
|
2212
|
+
onPress: handleCancel,
|
|
2213
|
+
pressStyle: { opacity: 0.7 },
|
|
2214
|
+
animation: "quick",
|
|
2215
|
+
children: /* @__PURE__ */ jsx44(SizableText38, { fontWeight: "600", children: cancelLabel })
|
|
2216
|
+
}
|
|
2217
|
+
),
|
|
2218
|
+
/* @__PURE__ */ jsx44(
|
|
2219
|
+
Button10,
|
|
2220
|
+
{
|
|
2221
|
+
flex: 1,
|
|
2222
|
+
size: "$4",
|
|
2223
|
+
borderRadius: "$4",
|
|
2224
|
+
backgroundColor: destructive ? "$red9" : "$color9",
|
|
2225
|
+
onPress: handleConfirm,
|
|
2226
|
+
pressStyle: { backgroundColor: destructive ? "$red8" : "$color8", scale: 0.97 },
|
|
2227
|
+
animation: "quick",
|
|
2228
|
+
children: /* @__PURE__ */ jsx44(SizableText38, { fontWeight: "600", color: "white", children: confirmLabel })
|
|
2229
|
+
}
|
|
2230
|
+
)
|
|
2231
|
+
] })
|
|
2232
|
+
] })
|
|
2233
|
+
},
|
|
2234
|
+
"content"
|
|
2235
|
+
)
|
|
2236
|
+
] }) });
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
// src/patterns/Chip.tsx
|
|
2240
|
+
import { useCallback as useCallback3 } from "react";
|
|
2241
|
+
import { SizableText as SizableText39, XStack as XStack32 } from "tamagui";
|
|
2242
|
+
import { jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2243
|
+
var sizes2 = { sm: { h: 28, px: "$2", text: "$2" }, md: { h: 34, px: "$3", text: "$3" }, lg: { h: 42, px: "$4", text: "$4" } };
|
|
2244
|
+
function Chip({ label, selected, onPress, onRemove, variant = "filled", size = "md", icon, color }) {
|
|
2245
|
+
const s = sizes2[size];
|
|
2246
|
+
const filled = variant === "filled";
|
|
2247
|
+
const active = selected ?? false;
|
|
2248
|
+
const bg = active ? color ?? "$color9" : filled ? "$color3" : "transparent";
|
|
2249
|
+
const border = active ? color ?? "$color9" : "$color6";
|
|
2250
|
+
const fg = active ? "$color1" : "$color11";
|
|
2251
|
+
return /* @__PURE__ */ jsxs36(
|
|
2252
|
+
XStack32,
|
|
2253
|
+
{
|
|
2254
|
+
height: s.h,
|
|
2255
|
+
borderRadius: "$10",
|
|
2256
|
+
paddingHorizontal: s.px,
|
|
2257
|
+
backgroundColor: bg,
|
|
2258
|
+
borderWidth: filled ? 0 : 1,
|
|
2259
|
+
borderColor: border,
|
|
2260
|
+
alignItems: "center",
|
|
2261
|
+
gap: "$1.5",
|
|
2262
|
+
pressStyle: { scale: 0.96, opacity: 0.85 },
|
|
2263
|
+
animation: "quick",
|
|
2264
|
+
onPress,
|
|
2265
|
+
cursor: "pointer",
|
|
2266
|
+
children: [
|
|
2267
|
+
active && /* @__PURE__ */ jsx45(SizableText39, { size: s.text, color: fg, children: "\u2713" }),
|
|
2268
|
+
icon && /* @__PURE__ */ jsx45(SizableText39, { color: fg, children: icon }),
|
|
2269
|
+
/* @__PURE__ */ jsx45(SizableText39, { size: s.text, color: fg, fontWeight: "500", children: label }),
|
|
2270
|
+
onRemove && /* @__PURE__ */ jsx45(
|
|
2271
|
+
SizableText39,
|
|
2272
|
+
{
|
|
2273
|
+
size: "$2",
|
|
2274
|
+
color: fg,
|
|
2275
|
+
opacity: 0.7,
|
|
2276
|
+
pressStyle: { opacity: 1 },
|
|
2277
|
+
onPress: (e) => {
|
|
2278
|
+
e.stopPropagation?.();
|
|
2279
|
+
onRemove();
|
|
2280
|
+
},
|
|
2281
|
+
marginLeft: "$1",
|
|
2282
|
+
children: "\u2715"
|
|
2283
|
+
}
|
|
2284
|
+
)
|
|
2285
|
+
]
|
|
2286
|
+
}
|
|
2287
|
+
);
|
|
2288
|
+
}
|
|
2289
|
+
function ChipGroup({ chips, selected = [], onSelectionChange, multiSelect = true, variant, size }) {
|
|
2290
|
+
const toggle = useCallback3((id) => {
|
|
2291
|
+
if (!onSelectionChange) return;
|
|
2292
|
+
const isSelected = selected.includes(id);
|
|
2293
|
+
if (multiSelect) {
|
|
2294
|
+
onSelectionChange(isSelected ? selected.filter((s) => s !== id) : [...selected, id]);
|
|
2295
|
+
} else {
|
|
2296
|
+
onSelectionChange(isSelected ? [] : [id]);
|
|
2297
|
+
}
|
|
2298
|
+
}, [selected, onSelectionChange, multiSelect]);
|
|
2299
|
+
return /* @__PURE__ */ jsx45(XStack32, { flexWrap: "wrap", gap: "$2", children: chips.map((chip) => /* @__PURE__ */ jsx45(
|
|
2300
|
+
Chip,
|
|
2301
|
+
{
|
|
2302
|
+
label: chip.label,
|
|
2303
|
+
icon: chip.icon,
|
|
2304
|
+
selected: selected.includes(chip.id),
|
|
2305
|
+
onPress: () => toggle(chip.id),
|
|
2306
|
+
variant,
|
|
2307
|
+
size
|
|
2308
|
+
},
|
|
2309
|
+
chip.id
|
|
2310
|
+
)) });
|
|
2311
|
+
}
|
|
2312
|
+
|
|
2313
|
+
// src/patterns/OTPInput.tsx
|
|
2314
|
+
import { useCallback as useCallback4, useRef as useRef2 } from "react";
|
|
2315
|
+
import { Input as Input3, SizableText as SizableText40, XStack as XStack33, YStack as YStack37 } from "tamagui";
|
|
2316
|
+
import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2317
|
+
function OTPInput({ length = 6, value = "", onChange, onComplete, error, autoFocus, secureEntry }) {
|
|
2318
|
+
const inputRef = useRef2(null);
|
|
2319
|
+
const digits = value.padEnd(length, " ").slice(0, length);
|
|
2320
|
+
const handleChange = useCallback4((text) => {
|
|
2321
|
+
const cleaned = text.replace(/\D/g, "").slice(0, length);
|
|
2322
|
+
onChange?.(cleaned);
|
|
2323
|
+
if (cleaned.length === length) onComplete?.(cleaned);
|
|
2324
|
+
}, [length, onChange, onComplete]);
|
|
2325
|
+
return /* @__PURE__ */ jsxs37(YStack37, { children: [
|
|
2326
|
+
/* @__PURE__ */ jsx46(XStack33, { gap: "$2", justifyContent: "center", onPress: () => inputRef.current?.focus(), children: Array.from({ length }, (_, i) => {
|
|
2327
|
+
const char = digits[i]?.trim();
|
|
2328
|
+
const focused = value.length === i;
|
|
2329
|
+
return /* @__PURE__ */ jsxs37(
|
|
2330
|
+
YStack37,
|
|
2331
|
+
{
|
|
2332
|
+
width: 48,
|
|
2333
|
+
height: 56,
|
|
2334
|
+
borderRadius: "$3",
|
|
2335
|
+
borderWidth: 2,
|
|
2336
|
+
borderColor: error ? "$red9" : focused ? "$color9" : "$color6",
|
|
2337
|
+
backgroundColor: error ? "$red2" : "$color2",
|
|
2338
|
+
alignItems: "center",
|
|
2339
|
+
justifyContent: "center",
|
|
2340
|
+
animation: "quick",
|
|
2341
|
+
children: [
|
|
2342
|
+
/* @__PURE__ */ jsx46(SizableText40, { size: "$7", fontWeight: "600", color: "$color12", children: char ? secureEntry ? "\u25CF" : char : "" }),
|
|
2343
|
+
focused && /* @__PURE__ */ jsx46(YStack37, { position: "absolute", bottom: 10, width: 20, height: 2, backgroundColor: "$color9", animation: "quick" })
|
|
2344
|
+
]
|
|
2345
|
+
},
|
|
2346
|
+
i
|
|
2347
|
+
);
|
|
2348
|
+
}) }),
|
|
2349
|
+
/* @__PURE__ */ jsx46(
|
|
2350
|
+
Input3,
|
|
2351
|
+
{
|
|
2352
|
+
ref: inputRef,
|
|
2353
|
+
value,
|
|
2354
|
+
onChangeText: handleChange,
|
|
2355
|
+
keyboardType: "number-pad",
|
|
2356
|
+
maxLength: length,
|
|
2357
|
+
autoFocus,
|
|
2358
|
+
position: "absolute",
|
|
2359
|
+
opacity: 0,
|
|
2360
|
+
width: 1,
|
|
2361
|
+
height: 1
|
|
2362
|
+
}
|
|
2363
|
+
)
|
|
2364
|
+
] });
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/patterns/PasswordInput.tsx
|
|
2368
|
+
import { useState as useState11, useCallback as useCallback5 } from "react";
|
|
2369
|
+
import { Input as Input4, SizableText as SizableText41, XStack as XStack34, YStack as YStack38 } from "tamagui";
|
|
2370
|
+
import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2371
|
+
function getStrength(pw) {
|
|
2372
|
+
if (!pw) return { label: "", color: "$color6", width: "0%" };
|
|
2373
|
+
const score = [pw.length >= 8, /[A-Z]/.test(pw), /[0-9]/.test(pw), /[^A-Za-z0-9]/.test(pw)].filter(Boolean).length;
|
|
2374
|
+
if (score <= 1) return { label: "Weak", color: "$red9", width: "33%" };
|
|
2375
|
+
if (score <= 2) return { label: "Medium", color: "$yellow9", width: "66%" };
|
|
2376
|
+
return { label: "Strong", color: "$green9", width: "100%" };
|
|
2377
|
+
}
|
|
2378
|
+
function PasswordInput({ value = "", onChangeText, placeholder = "Password", label, error, size = "$4", strengthIndicator }) {
|
|
2379
|
+
const [visible, setVisible] = useState11(false);
|
|
2380
|
+
const toggle = useCallback5(() => setVisible((v) => !v), []);
|
|
2381
|
+
const strength = getStrength(value);
|
|
2382
|
+
return /* @__PURE__ */ jsxs38(YStack38, { gap: "$1.5", children: [
|
|
2383
|
+
label && /* @__PURE__ */ jsx47(SizableText41, { size: "$3", color: "$color11", fontWeight: "500", children: label }),
|
|
2384
|
+
/* @__PURE__ */ jsxs38(
|
|
2385
|
+
XStack34,
|
|
2386
|
+
{
|
|
2387
|
+
borderWidth: 1,
|
|
2388
|
+
borderColor: error ? "$red9" : "$color6",
|
|
2389
|
+
borderRadius: "$3",
|
|
2390
|
+
backgroundColor: "$color2",
|
|
2391
|
+
alignItems: "center",
|
|
2392
|
+
paddingRight: "$2",
|
|
2393
|
+
focusStyle: { borderColor: "$color9" },
|
|
2394
|
+
children: [
|
|
2395
|
+
/* @__PURE__ */ jsx47(
|
|
2396
|
+
Input4,
|
|
2397
|
+
{
|
|
2398
|
+
flex: 1,
|
|
2399
|
+
size,
|
|
2400
|
+
value,
|
|
2401
|
+
onChangeText,
|
|
2402
|
+
placeholder,
|
|
2403
|
+
placeholderTextColor: "$color8",
|
|
2404
|
+
secureTextEntry: !visible,
|
|
2405
|
+
backgroundColor: "transparent",
|
|
2406
|
+
borderWidth: 0
|
|
2407
|
+
}
|
|
2408
|
+
),
|
|
2409
|
+
/* @__PURE__ */ jsx47(
|
|
2410
|
+
SizableText41,
|
|
2411
|
+
{
|
|
2412
|
+
size: "$4",
|
|
2413
|
+
color: "$color8",
|
|
2414
|
+
paddingHorizontal: "$2",
|
|
2415
|
+
pressStyle: { opacity: 0.6 },
|
|
2416
|
+
onPress: toggle,
|
|
2417
|
+
cursor: "pointer",
|
|
2418
|
+
children: visible ? "\u25C9" : "\u25CE"
|
|
2419
|
+
}
|
|
2420
|
+
)
|
|
2421
|
+
]
|
|
2422
|
+
}
|
|
2423
|
+
),
|
|
2424
|
+
strengthIndicator && value.length > 0 && /* @__PURE__ */ jsxs38(YStack38, { gap: "$1", children: [
|
|
2425
|
+
/* @__PURE__ */ jsx47(YStack38, { height: 3, backgroundColor: "$color4", borderRadius: 2, overflow: "hidden", children: /* @__PURE__ */ jsx47(YStack38, { height: 3, width: strength.width, backgroundColor: strength.color, borderRadius: 2, animation: "quick" }) }),
|
|
2426
|
+
/* @__PURE__ */ jsx47(SizableText41, { size: "$1", color: strength.color, children: strength.label })
|
|
2427
|
+
] }),
|
|
2428
|
+
error && /* @__PURE__ */ jsx47(SizableText41, { size: "$2", color: "$red9", children: error })
|
|
2429
|
+
] });
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
// src/patterns/AvatarGroup.tsx
|
|
2433
|
+
import { Circle as Circle7, Image as Image8, SizableText as SizableText42, XStack as XStack35 } from "tamagui";
|
|
2434
|
+
import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
2435
|
+
function getInitials(name) {
|
|
2436
|
+
if (!name) return "?";
|
|
2437
|
+
return name.split(" ").map((p) => p[0]).join("").toUpperCase().slice(0, 2);
|
|
2438
|
+
}
|
|
2439
|
+
function AvatarItem({ uri, name, color, size }) {
|
|
2440
|
+
return /* @__PURE__ */ jsx48(
|
|
2441
|
+
Circle7,
|
|
2442
|
+
{
|
|
2443
|
+
size,
|
|
2444
|
+
backgroundColor: color ?? "$color4",
|
|
2445
|
+
borderWidth: 2,
|
|
2446
|
+
borderColor: "$background",
|
|
2447
|
+
overflow: "hidden",
|
|
2448
|
+
alignItems: "center",
|
|
2449
|
+
justifyContent: "center",
|
|
2450
|
+
children: uri ? /* @__PURE__ */ jsx48(Image8, { source: { uri }, width: size, height: size, objectFit: "cover" }) : /* @__PURE__ */ jsx48(SizableText42, { size: "$2", fontWeight: "600", color: color ? "$color1" : "$color11", children: getInitials(name) })
|
|
2451
|
+
}
|
|
2452
|
+
);
|
|
2453
|
+
}
|
|
2454
|
+
function AvatarGroup({ avatars, max = 4, size = 36, overlap = 10 }) {
|
|
2455
|
+
const visible = avatars.slice(0, max);
|
|
2456
|
+
const remaining = avatars.length - max;
|
|
2457
|
+
return /* @__PURE__ */ jsxs39(XStack35, { alignItems: "center", children: [
|
|
2458
|
+
visible.map((avatar, i) => /* @__PURE__ */ jsx48(XStack35, { marginLeft: i === 0 ? 0 : -overlap, zIndex: visible.length - i, children: /* @__PURE__ */ jsx48(AvatarItem, { ...avatar, size }) }, i)),
|
|
2459
|
+
remaining > 0 && /* @__PURE__ */ jsx48(XStack35, { marginLeft: -overlap, zIndex: 0, children: /* @__PURE__ */ jsx48(
|
|
2460
|
+
Circle7,
|
|
2461
|
+
{
|
|
2462
|
+
size,
|
|
2463
|
+
backgroundColor: "$color6",
|
|
2464
|
+
borderWidth: 2,
|
|
2465
|
+
borderColor: "$background",
|
|
2466
|
+
alignItems: "center",
|
|
2467
|
+
justifyContent: "center",
|
|
2468
|
+
children: /* @__PURE__ */ jsxs39(SizableText42, { size: "$2", fontWeight: "600", color: "$color11", children: [
|
|
2469
|
+
"+",
|
|
2470
|
+
remaining
|
|
2471
|
+
] })
|
|
2472
|
+
}
|
|
2473
|
+
) })
|
|
2474
|
+
] });
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
// src/patterns/SwipeCards.tsx
|
|
2478
|
+
import { useState as useState12, useCallback as useCallback6 } from "react";
|
|
2479
|
+
import { Circle as Circle8, SizableText as SizableText43, XStack as XStack36, YStack as YStack39 } from "tamagui";
|
|
2480
|
+
import { jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
2481
|
+
var STACK_SIZE = 3;
|
|
2482
|
+
var CARD_OFFSETS = [
|
|
2483
|
+
{ scale: 1, y: 0, opacity: 1 },
|
|
2484
|
+
{ scale: 0.95, y: 8, opacity: 0.9 },
|
|
2485
|
+
{ scale: 0.9, y: 16, opacity: 0.8 }
|
|
2486
|
+
];
|
|
2487
|
+
function SwipeCards({
|
|
2488
|
+
items,
|
|
2489
|
+
renderCard,
|
|
2490
|
+
onSwipeLeft,
|
|
2491
|
+
onSwipeRight,
|
|
2492
|
+
onEmpty,
|
|
2493
|
+
leftLabel = "Nope",
|
|
2494
|
+
rightLabel = "Like",
|
|
2495
|
+
emptyMessage = "No more cards"
|
|
2496
|
+
}) {
|
|
2497
|
+
const [index, setIndex] = useState12(0);
|
|
2498
|
+
const [exitDir, setExitDir] = useState12(null);
|
|
2499
|
+
const remaining = items.slice(index);
|
|
2500
|
+
const isEmpty = remaining.length === 0;
|
|
2501
|
+
const handleSwipe = useCallback6((dir) => {
|
|
2502
|
+
if (isEmpty) return;
|
|
2503
|
+
const current = items[index];
|
|
2504
|
+
setExitDir(dir);
|
|
2505
|
+
const timer = setTimeout(() => {
|
|
2506
|
+
setExitDir(null);
|
|
2507
|
+
setIndex((i) => {
|
|
2508
|
+
const next = i + 1;
|
|
2509
|
+
if (next >= items.length) onEmpty?.();
|
|
2510
|
+
return next;
|
|
2511
|
+
});
|
|
2512
|
+
dir === "left" ? onSwipeLeft?.(current) : onSwipeRight?.(current);
|
|
2513
|
+
}, 250);
|
|
2514
|
+
return () => clearTimeout(timer);
|
|
2515
|
+
}, [isEmpty, index, items, onEmpty, onSwipeLeft, onSwipeRight]);
|
|
2516
|
+
if (isEmpty) {
|
|
2517
|
+
return /* @__PURE__ */ jsx49(YStack39, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$3", padding: "$4", children: /* @__PURE__ */ jsx49(SizableText43, { size: "$5", color: "$color8", children: emptyMessage }) });
|
|
2518
|
+
}
|
|
2519
|
+
return /* @__PURE__ */ jsxs40(YStack39, { flex: 1, gap: "$4", children: [
|
|
2520
|
+
/* @__PURE__ */ jsx49(YStack39, { flex: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx49(YStack39, { width: "100%", maxWidth: 340, aspectRatio: 3 / 4, position: "relative", children: remaining.slice(0, STACK_SIZE).reverse().map((item, reverseIdx) => {
|
|
2521
|
+
const stackIdx = Math.min(remaining.length, STACK_SIZE) - 1 - reverseIdx;
|
|
2522
|
+
const isTop = stackIdx === 0;
|
|
2523
|
+
const offset = CARD_OFFSETS[stackIdx] ?? CARD_OFFSETS[2];
|
|
2524
|
+
const exitX = exitDir === "left" ? -400 : exitDir === "right" ? 400 : 0;
|
|
2525
|
+
const exitRotate = exitDir === "left" ? "-15deg" : exitDir === "right" ? "15deg" : "0deg";
|
|
2526
|
+
return /* @__PURE__ */ jsxs40(
|
|
2527
|
+
YStack39,
|
|
2528
|
+
{
|
|
2529
|
+
position: "absolute",
|
|
2530
|
+
top: 0,
|
|
2531
|
+
left: 0,
|
|
2532
|
+
right: 0,
|
|
2533
|
+
bottom: 0,
|
|
2534
|
+
animation: "quick",
|
|
2535
|
+
borderRadius: "$5",
|
|
2536
|
+
overflow: "hidden",
|
|
2537
|
+
backgroundColor: "$background",
|
|
2538
|
+
elevate: isTop,
|
|
2539
|
+
shadowColor: "$shadowColor",
|
|
2540
|
+
shadowRadius: isTop ? 16 : 4,
|
|
2541
|
+
scale: isTop && exitDir ? 1 : offset.scale,
|
|
2542
|
+
opacity: isTop && exitDir ? 0 : offset.opacity,
|
|
2543
|
+
y: isTop && exitDir ? 0 : offset.y,
|
|
2544
|
+
x: isTop ? exitX : 0,
|
|
2545
|
+
rotate: isTop ? exitRotate : "0deg",
|
|
2546
|
+
children: [
|
|
2547
|
+
renderCard(item),
|
|
2548
|
+
isTop && exitDir === "left" && /* @__PURE__ */ jsx49(
|
|
2549
|
+
YStack39,
|
|
2550
|
+
{
|
|
2551
|
+
position: "absolute",
|
|
2552
|
+
top: "$4",
|
|
2553
|
+
right: "$4",
|
|
2554
|
+
borderWidth: 3,
|
|
2555
|
+
borderColor: "$red10",
|
|
2556
|
+
borderRadius: "$3",
|
|
2557
|
+
padding: "$2",
|
|
2558
|
+
rotate: "15deg",
|
|
2559
|
+
children: /* @__PURE__ */ jsx49(SizableText43, { size: "$7", fontWeight: "800", color: "$red10", children: leftLabel.toUpperCase() })
|
|
2560
|
+
}
|
|
2561
|
+
),
|
|
2562
|
+
isTop && exitDir === "right" && /* @__PURE__ */ jsx49(
|
|
2563
|
+
YStack39,
|
|
2564
|
+
{
|
|
2565
|
+
position: "absolute",
|
|
2566
|
+
top: "$4",
|
|
2567
|
+
left: "$4",
|
|
2568
|
+
borderWidth: 3,
|
|
2569
|
+
borderColor: "$green10",
|
|
2570
|
+
borderRadius: "$3",
|
|
2571
|
+
padding: "$2",
|
|
2572
|
+
rotate: "-15deg",
|
|
2573
|
+
children: /* @__PURE__ */ jsx49(SizableText43, { size: "$7", fontWeight: "800", color: "$green10", children: rightLabel.toUpperCase() })
|
|
2574
|
+
}
|
|
2575
|
+
)
|
|
2576
|
+
]
|
|
2577
|
+
},
|
|
2578
|
+
item.id
|
|
2579
|
+
);
|
|
2580
|
+
}) }) }),
|
|
2581
|
+
/* @__PURE__ */ jsxs40(XStack36, { justifyContent: "center", gap: "$6", paddingBottom: "$4", children: [
|
|
2582
|
+
/* @__PURE__ */ jsx49(
|
|
2583
|
+
Circle8,
|
|
2584
|
+
{
|
|
2585
|
+
size: 60,
|
|
2586
|
+
backgroundColor: "$red3",
|
|
2587
|
+
borderWidth: 2,
|
|
2588
|
+
borderColor: "$red7",
|
|
2589
|
+
pressStyle: { scale: 0.9, backgroundColor: "$red5" },
|
|
2590
|
+
animation: "quick",
|
|
2591
|
+
onPress: () => handleSwipe("left"),
|
|
2592
|
+
alignItems: "center",
|
|
2593
|
+
justifyContent: "center",
|
|
2594
|
+
children: /* @__PURE__ */ jsx49(SizableText43, { size: "$6", color: "$red10", fontWeight: "700", children: "\u2715" })
|
|
2595
|
+
}
|
|
2596
|
+
),
|
|
2597
|
+
/* @__PURE__ */ jsx49(
|
|
2598
|
+
Circle8,
|
|
2599
|
+
{
|
|
2600
|
+
size: 60,
|
|
2601
|
+
backgroundColor: "$green3",
|
|
2602
|
+
borderWidth: 2,
|
|
2603
|
+
borderColor: "$green7",
|
|
2604
|
+
pressStyle: { scale: 0.9, backgroundColor: "$green5" },
|
|
2605
|
+
animation: "quick",
|
|
2606
|
+
onPress: () => handleSwipe("right"),
|
|
2607
|
+
alignItems: "center",
|
|
2608
|
+
justifyContent: "center",
|
|
2609
|
+
children: /* @__PURE__ */ jsx49(SizableText43, { size: "$6", color: "$green10", fontWeight: "700", children: "\u2665" })
|
|
2610
|
+
}
|
|
2611
|
+
)
|
|
2612
|
+
] })
|
|
2613
|
+
] });
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
// src/patterns/GlassCard.tsx
|
|
2617
|
+
import { styled as styled12, YStack as YStack40 } from "tamagui";
|
|
2618
|
+
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
2619
|
+
var BLUR = { light: 8, medium: 16, heavy: 24 };
|
|
2620
|
+
var TINT_BG = {
|
|
2621
|
+
light: "rgba(255,255,255,0.15)",
|
|
2622
|
+
dark: "rgba(0,0,0,0.25)"
|
|
2623
|
+
};
|
|
2624
|
+
var GlassFrame = styled12(YStack40, {
|
|
2625
|
+
borderWidth: 1,
|
|
2626
|
+
borderColor: "rgba(255,255,255,0.2)",
|
|
2627
|
+
overflow: "hidden"
|
|
2628
|
+
});
|
|
2629
|
+
function GlassCard({
|
|
2630
|
+
children,
|
|
2631
|
+
intensity = "medium",
|
|
2632
|
+
tint = "light",
|
|
2633
|
+
borderRadius = "$4",
|
|
2634
|
+
padding = "$4",
|
|
2635
|
+
elevated = false
|
|
2636
|
+
}) {
|
|
2637
|
+
const blur = BLUR[intensity];
|
|
2638
|
+
return /* @__PURE__ */ jsx50(
|
|
2639
|
+
GlassFrame,
|
|
2640
|
+
{
|
|
2641
|
+
borderRadius,
|
|
2642
|
+
padding,
|
|
2643
|
+
backgroundColor: TINT_BG[tint],
|
|
2644
|
+
elevate: elevated,
|
|
2645
|
+
shadowColor: elevated ? "$shadowColor" : void 0,
|
|
2646
|
+
shadowRadius: elevated ? 20 : void 0,
|
|
2647
|
+
shadowOpacity: elevated ? 0.3 : void 0,
|
|
2648
|
+
style: { backdropFilter: `blur(${blur}px)`, WebkitBackdropFilter: `blur(${blur}px)` },
|
|
2649
|
+
children
|
|
2650
|
+
}
|
|
2651
|
+
);
|
|
2652
|
+
}
|
|
1737
2653
|
export {
|
|
1738
2654
|
Accordion,
|
|
1739
2655
|
ActionSheet,
|
|
1740
2656
|
Adapt,
|
|
1741
|
-
|
|
2657
|
+
AlertDialog3 as AlertDialog,
|
|
1742
2658
|
Anchor,
|
|
1743
2659
|
AnimatePresence,
|
|
1744
2660
|
AppHeader,
|
|
1745
2661
|
Article,
|
|
1746
2662
|
Aside,
|
|
1747
2663
|
Avatar2 as Avatar,
|
|
2664
|
+
AvatarGroup,
|
|
1748
2665
|
Badge,
|
|
1749
2666
|
BlinkAccordion,
|
|
1750
2667
|
Avatar as BlinkAvatar,
|
|
@@ -1758,13 +2675,17 @@ export {
|
|
|
1758
2675
|
BlinkToggleGroup,
|
|
1759
2676
|
BlinkTooltip,
|
|
1760
2677
|
BottomSheet,
|
|
1761
|
-
|
|
2678
|
+
Button11 as Button,
|
|
1762
2679
|
Card2 as Card,
|
|
1763
2680
|
Carousel,
|
|
1764
2681
|
ChatBubble,
|
|
1765
2682
|
Checkbox,
|
|
1766
|
-
|
|
2683
|
+
Chip,
|
|
2684
|
+
ChipGroup,
|
|
2685
|
+
Circle9 as Circle,
|
|
2686
|
+
ConfirmDialog,
|
|
1767
2687
|
Container,
|
|
2688
|
+
CountdownBanner,
|
|
1768
2689
|
Dialog,
|
|
1769
2690
|
DialogProvider,
|
|
1770
2691
|
Divider,
|
|
@@ -1776,6 +2697,7 @@ export {
|
|
|
1776
2697
|
Form,
|
|
1777
2698
|
FormField,
|
|
1778
2699
|
Frame,
|
|
2700
|
+
GlassCard,
|
|
1779
2701
|
Grid,
|
|
1780
2702
|
Group,
|
|
1781
2703
|
H12 as H1,
|
|
@@ -1789,7 +2711,7 @@ export {
|
|
|
1789
2711
|
ICONS,
|
|
1790
2712
|
Icon,
|
|
1791
2713
|
Image2 as Image,
|
|
1792
|
-
|
|
2714
|
+
Input5 as Input,
|
|
1793
2715
|
KeyboardStickyFooter,
|
|
1794
2716
|
Label,
|
|
1795
2717
|
ListItem,
|
|
@@ -1798,10 +2720,12 @@ export {
|
|
|
1798
2720
|
MediaCard,
|
|
1799
2721
|
Nav,
|
|
1800
2722
|
NotificationBanner,
|
|
2723
|
+
OTPInput,
|
|
1801
2724
|
OnboardingCarousel,
|
|
1802
2725
|
PageContainer,
|
|
1803
2726
|
PageMainContainer,
|
|
1804
2727
|
Paragraph,
|
|
2728
|
+
PasswordInput,
|
|
1805
2729
|
PaywallScreen,
|
|
1806
2730
|
Popover2 as Popover,
|
|
1807
2731
|
Portal,
|
|
@@ -1809,6 +2733,8 @@ export {
|
|
|
1809
2733
|
PortalItem,
|
|
1810
2734
|
PortalProvider,
|
|
1811
2735
|
Pressable,
|
|
2736
|
+
PricingTable,
|
|
2737
|
+
ProductCard,
|
|
1812
2738
|
ProfileHeader,
|
|
1813
2739
|
Progress,
|
|
1814
2740
|
ProgressSteps,
|
|
@@ -1816,7 +2742,7 @@ export {
|
|
|
1816
2742
|
RadioGroup,
|
|
1817
2743
|
SafeArea,
|
|
1818
2744
|
ScreenLayout,
|
|
1819
|
-
|
|
2745
|
+
ScrollView7 as ScrollView,
|
|
1820
2746
|
SearchBar,
|
|
1821
2747
|
Section,
|
|
1822
2748
|
Select,
|
|
@@ -1825,7 +2751,7 @@ export {
|
|
|
1825
2751
|
SettingsScreen,
|
|
1826
2752
|
Sheet3 as Sheet,
|
|
1827
2753
|
SizableStack,
|
|
1828
|
-
|
|
2754
|
+
SizableText44 as SizableText,
|
|
1829
2755
|
Skeleton,
|
|
1830
2756
|
Slider,
|
|
1831
2757
|
Spacer,
|
|
@@ -1834,13 +2760,15 @@ export {
|
|
|
1834
2760
|
Stack,
|
|
1835
2761
|
StepPageLayout,
|
|
1836
2762
|
SubHeading,
|
|
2763
|
+
SwipeCards,
|
|
1837
2764
|
SwipeableRow,
|
|
1838
2765
|
Switch2 as Switch,
|
|
1839
2766
|
TabBar,
|
|
1840
2767
|
Tabs,
|
|
1841
|
-
|
|
2768
|
+
Image9 as TamaguiImage,
|
|
1842
2769
|
ListItem2 as TamaguiListItem,
|
|
1843
2770
|
TamaguiProvider,
|
|
2771
|
+
TestimonialCard,
|
|
1844
2772
|
Text,
|
|
1845
2773
|
TextArea,
|
|
1846
2774
|
Theme,
|
|
@@ -1852,9 +2780,9 @@ export {
|
|
|
1852
2780
|
View6 as View,
|
|
1853
2781
|
VisuallyHidden,
|
|
1854
2782
|
XGroup,
|
|
1855
|
-
|
|
2783
|
+
XStack37 as XStack,
|
|
1856
2784
|
YGroup,
|
|
1857
|
-
|
|
2785
|
+
YStack41 as YStack,
|
|
1858
2786
|
ZStack,
|
|
1859
2787
|
addTheme,
|
|
1860
2788
|
blinkConfig,
|
|
@@ -1876,7 +2804,7 @@ export {
|
|
|
1876
2804
|
isWeb,
|
|
1877
2805
|
replaceTheme,
|
|
1878
2806
|
showError,
|
|
1879
|
-
|
|
2807
|
+
styled13 as styled,
|
|
1880
2808
|
defaultConfig2 as tamaguiDefaultConfig,
|
|
1881
2809
|
toast,
|
|
1882
2810
|
updateTheme,
|