@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.js CHANGED
@@ -20,167 +20,179 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- Accordion: () => import_tamagui49.Accordion,
23
+ Accordion: () => import_tamagui60.Accordion,
24
24
  ActionSheet: () => ActionSheet,
25
- Adapt: () => import_tamagui49.Adapt,
26
- AlertDialog: () => import_tamagui49.AlertDialog,
27
- Anchor: () => import_tamagui49.Anchor,
28
- AnimatePresence: () => import_tamagui49.AnimatePresence,
25
+ Adapt: () => import_tamagui60.Adapt,
26
+ AlertDialog: () => import_tamagui60.AlertDialog,
27
+ Anchor: () => import_tamagui60.Anchor,
28
+ AnimatePresence: () => import_tamagui60.AnimatePresence,
29
29
  AppHeader: () => AppHeader,
30
- Article: () => import_tamagui49.Article,
31
- Aside: () => import_tamagui49.Aside,
32
- Avatar: () => import_tamagui49.Avatar,
30
+ Article: () => import_tamagui60.Article,
31
+ Aside: () => import_tamagui60.Aside,
32
+ Avatar: () => import_tamagui60.Avatar,
33
+ AvatarGroup: () => AvatarGroup,
33
34
  Badge: () => Badge,
34
35
  BlinkAccordion: () => BlinkAccordion,
35
36
  BlinkAvatar: () => Avatar,
36
37
  BlinkButton: () => Button,
37
38
  BlinkCard: () => Card,
38
39
  BlinkInput: () => Input,
39
- BlinkProvider: () => import_tamagui49.TamaguiProvider,
40
+ BlinkProvider: () => import_tamagui60.TamaguiProvider,
40
41
  BlinkTabs: () => BlinkTabs,
41
42
  BlinkText: () => BlinkText,
42
43
  BlinkToastProvider: () => BlinkToastProvider,
43
44
  BlinkToggleGroup: () => BlinkToggleGroup,
44
45
  BlinkTooltip: () => BlinkTooltip,
45
46
  BottomSheet: () => BottomSheet,
46
- Button: () => import_tamagui49.Button,
47
- Card: () => import_tamagui49.Card,
47
+ Button: () => import_tamagui60.Button,
48
+ Card: () => import_tamagui60.Card,
48
49
  Carousel: () => Carousel,
49
50
  ChatBubble: () => ChatBubble,
50
- Checkbox: () => import_tamagui49.Checkbox,
51
- Circle: () => import_tamagui49.Circle,
51
+ Checkbox: () => import_tamagui60.Checkbox,
52
+ Chip: () => Chip,
53
+ ChipGroup: () => ChipGroup,
54
+ Circle: () => import_tamagui60.Circle,
55
+ ConfirmDialog: () => ConfirmDialog,
52
56
  Container: () => Container,
53
- Dialog: () => import_tamagui49.Dialog,
57
+ CountdownBanner: () => CountdownBanner,
58
+ Dialog: () => import_tamagui60.Dialog,
54
59
  DialogProvider: () => DialogProvider,
55
60
  Divider: () => Divider,
56
61
  EmptyState: () => EmptyState,
57
- EnsureFlexed: () => import_tamagui49.EnsureFlexed,
58
- Fieldset: () => import_tamagui49.Fieldset,
62
+ EnsureFlexed: () => import_tamagui60.EnsureFlexed,
63
+ Fieldset: () => import_tamagui60.Fieldset,
59
64
  FloatingActionButton: () => FloatingActionButton,
60
- Footer: () => import_tamagui49.Footer,
61
- Form: () => import_tamagui49.Form,
65
+ Footer: () => import_tamagui60.Footer,
66
+ Form: () => import_tamagui60.Form,
62
67
  FormField: () => FormField,
63
- Frame: () => import_tamagui49.Frame,
68
+ Frame: () => import_tamagui60.Frame,
69
+ GlassCard: () => GlassCard,
64
70
  Grid: () => Grid,
65
- Group: () => import_tamagui49.Group,
66
- H1: () => import_tamagui49.H1,
67
- H2: () => import_tamagui49.H2,
68
- H3: () => import_tamagui49.H3,
69
- H4: () => import_tamagui49.H4,
70
- H5: () => import_tamagui49.H5,
71
- H6: () => import_tamagui49.H6,
72
- Header: () => import_tamagui49.Header,
73
- Heading: () => import_tamagui49.Heading,
71
+ Group: () => import_tamagui60.Group,
72
+ H1: () => import_tamagui60.H1,
73
+ H2: () => import_tamagui60.H2,
74
+ H3: () => import_tamagui60.H3,
75
+ H4: () => import_tamagui60.H4,
76
+ H5: () => import_tamagui60.H5,
77
+ H6: () => import_tamagui60.H6,
78
+ Header: () => import_tamagui60.Header,
79
+ Heading: () => import_tamagui60.Heading,
74
80
  ICONS: () => ICONS,
75
81
  Icon: () => Icon,
76
82
  Image: () => Image2,
77
- Input: () => import_tamagui49.Input,
83
+ Input: () => import_tamagui60.Input,
78
84
  KeyboardStickyFooter: () => KeyboardStickyFooter,
79
- Label: () => import_tamagui49.Label,
85
+ Label: () => import_tamagui60.Label,
80
86
  ListItem: () => ListItem,
81
87
  LoginScreen: () => LoginScreen,
82
- Main: () => import_tamagui49.Main,
88
+ Main: () => import_tamagui60.Main,
83
89
  MediaCard: () => MediaCard,
84
- Nav: () => import_tamagui49.Nav,
90
+ Nav: () => import_tamagui60.Nav,
85
91
  NotificationBanner: () => NotificationBanner,
92
+ OTPInput: () => OTPInput,
86
93
  OnboardingCarousel: () => OnboardingCarousel,
87
94
  PageContainer: () => PageContainer,
88
95
  PageMainContainer: () => PageMainContainer,
89
- Paragraph: () => import_tamagui49.Paragraph,
96
+ Paragraph: () => import_tamagui60.Paragraph,
97
+ PasswordInput: () => PasswordInput,
90
98
  PaywallScreen: () => PaywallScreen,
91
- Popover: () => import_tamagui49.Popover,
92
- Portal: () => import_tamagui49.Portal,
93
- PortalHost: () => import_tamagui49.PortalHost,
94
- PortalItem: () => import_tamagui49.PortalItem,
95
- PortalProvider: () => import_tamagui49.PortalProvider,
99
+ Popover: () => import_tamagui60.Popover,
100
+ Portal: () => import_tamagui60.Portal,
101
+ PortalHost: () => import_tamagui60.PortalHost,
102
+ PortalItem: () => import_tamagui60.PortalItem,
103
+ PortalProvider: () => import_tamagui60.PortalProvider,
96
104
  Pressable: () => Pressable,
105
+ PricingTable: () => PricingTable,
106
+ ProductCard: () => ProductCard,
97
107
  ProfileHeader: () => ProfileHeader,
98
- Progress: () => import_tamagui49.Progress,
108
+ Progress: () => import_tamagui60.Progress,
99
109
  ProgressSteps: () => ProgressSteps,
100
110
  PullToRefresh: () => PullToRefresh,
101
- RadioGroup: () => import_tamagui49.RadioGroup,
111
+ RadioGroup: () => import_tamagui60.RadioGroup,
102
112
  SafeArea: () => SafeArea,
103
113
  ScreenLayout: () => ScreenLayout,
104
- ScrollView: () => import_tamagui49.ScrollView,
114
+ ScrollView: () => import_tamagui60.ScrollView,
105
115
  SearchBar: () => SearchBar,
106
116
  Section: () => Section,
107
- Select: () => import_tamagui49.Select,
117
+ Select: () => import_tamagui60.Select,
108
118
  SepHeading: () => SepHeading,
109
- Separator: () => import_tamagui49.Separator,
119
+ Separator: () => import_tamagui60.Separator,
110
120
  SettingsScreen: () => SettingsScreen,
111
- Sheet: () => import_tamagui49.Sheet,
112
- SizableStack: () => import_tamagui49.SizableStack,
113
- SizableText: () => import_tamagui49.SizableText,
121
+ Sheet: () => import_tamagui60.Sheet,
122
+ SizableStack: () => import_tamagui60.SizableStack,
123
+ SizableText: () => import_tamagui60.SizableText,
114
124
  Skeleton: () => Skeleton,
115
- Slider: () => import_tamagui49.Slider,
116
- Spacer: () => import_tamagui49.Spacer,
117
- Spinner: () => import_tamagui49.Spinner,
118
- Square: () => import_tamagui49.Square,
119
- Stack: () => import_tamagui49.Stack,
125
+ Slider: () => import_tamagui60.Slider,
126
+ Spacer: () => import_tamagui60.Spacer,
127
+ Spinner: () => import_tamagui60.Spinner,
128
+ Square: () => import_tamagui60.Square,
129
+ Stack: () => import_tamagui60.Stack,
120
130
  StepPageLayout: () => StepPageLayout,
121
131
  SubHeading: () => SubHeading,
132
+ SwipeCards: () => SwipeCards,
122
133
  SwipeableRow: () => SwipeableRow,
123
- Switch: () => import_tamagui49.Switch,
134
+ Switch: () => import_tamagui60.Switch,
124
135
  TabBar: () => TabBar,
125
- Tabs: () => import_tamagui49.Tabs,
126
- TamaguiImage: () => import_tamagui49.Image,
127
- TamaguiListItem: () => import_tamagui49.ListItem,
128
- TamaguiProvider: () => import_tamagui49.TamaguiProvider,
129
- Text: () => import_tamagui49.Text,
130
- TextArea: () => import_tamagui49.TextArea,
131
- Theme: () => import_tamagui49.Theme,
132
- ThemeableStack: () => import_tamagui49.ThemeableStack,
133
- ToggleGroup: () => import_tamagui49.ToggleGroup,
134
- Tooltip: () => import_tamagui49.Tooltip,
135
- TooltipSimple: () => import_tamagui49.TooltipSimple,
136
- Unspaced: () => import_tamagui49.Unspaced,
137
- View: () => import_tamagui49.View,
138
- VisuallyHidden: () => import_tamagui49.VisuallyHidden,
139
- XGroup: () => import_tamagui49.XGroup,
140
- XStack: () => import_tamagui49.XStack,
141
- YGroup: () => import_tamagui49.YGroup,
142
- YStack: () => import_tamagui49.YStack,
143
- ZStack: () => import_tamagui49.ZStack,
144
- addTheme: () => import_tamagui49.addTheme,
136
+ Tabs: () => import_tamagui60.Tabs,
137
+ TamaguiImage: () => import_tamagui60.Image,
138
+ TamaguiListItem: () => import_tamagui60.ListItem,
139
+ TamaguiProvider: () => import_tamagui60.TamaguiProvider,
140
+ TestimonialCard: () => TestimonialCard,
141
+ Text: () => import_tamagui60.Text,
142
+ TextArea: () => import_tamagui60.TextArea,
143
+ Theme: () => import_tamagui60.Theme,
144
+ ThemeableStack: () => import_tamagui60.ThemeableStack,
145
+ ToggleGroup: () => import_tamagui60.ToggleGroup,
146
+ Tooltip: () => import_tamagui60.Tooltip,
147
+ TooltipSimple: () => import_tamagui60.TooltipSimple,
148
+ Unspaced: () => import_tamagui60.Unspaced,
149
+ View: () => import_tamagui60.View,
150
+ VisuallyHidden: () => import_tamagui60.VisuallyHidden,
151
+ XGroup: () => import_tamagui60.XGroup,
152
+ XStack: () => import_tamagui60.XStack,
153
+ YGroup: () => import_tamagui60.YGroup,
154
+ YStack: () => import_tamagui60.YStack,
155
+ ZStack: () => import_tamagui60.ZStack,
156
+ addTheme: () => import_tamagui60.addTheme,
145
157
  blinkConfig: () => blinkConfig,
146
- composeEventHandlers: () => import_tamagui49.composeEventHandlers,
147
- composeRefs: () => import_tamagui49.composeRefs,
148
- createFont: () => import_tamagui49.createFont,
149
- createMedia: () => import_tamagui49.createMedia,
150
- createStyledContext: () => import_tamagui49.createStyledContext,
151
- createTamagui: () => import_tamagui49.createTamagui,
152
- createTheme: () => import_tamagui49.createTheme,
153
- createTokens: () => import_tamagui49.createTokens,
154
- createVariable: () => import_tamagui49.createVariable,
158
+ composeEventHandlers: () => import_tamagui60.composeEventHandlers,
159
+ composeRefs: () => import_tamagui60.composeRefs,
160
+ createFont: () => import_tamagui60.createFont,
161
+ createMedia: () => import_tamagui60.createMedia,
162
+ createStyledContext: () => import_tamagui60.createStyledContext,
163
+ createTamagui: () => import_tamagui60.createTamagui,
164
+ createTheme: () => import_tamagui60.createTheme,
165
+ createTokens: () => import_tamagui60.createTokens,
166
+ createVariable: () => import_tamagui60.createVariable,
155
167
  dialogConfirm: () => dialogConfirm,
156
- getConfig: () => import_tamagui49.getConfig,
157
- getToken: () => import_tamagui49.getToken,
158
- getTokenValue: () => import_tamagui49.getTokenValue,
159
- getTokens: () => import_tamagui49.getTokens,
160
- isClient: () => import_tamagui49.isClient,
161
- isWeb: () => import_tamagui49.isWeb,
162
- replaceTheme: () => import_tamagui49.replaceTheme,
168
+ getConfig: () => import_tamagui60.getConfig,
169
+ getToken: () => import_tamagui60.getToken,
170
+ getTokenValue: () => import_tamagui60.getTokenValue,
171
+ getTokens: () => import_tamagui60.getTokens,
172
+ isClient: () => import_tamagui60.isClient,
173
+ isWeb: () => import_tamagui60.isWeb,
174
+ replaceTheme: () => import_tamagui60.replaceTheme,
163
175
  showError: () => showError,
164
- styled: () => import_tamagui49.styled,
176
+ styled: () => import_tamagui60.styled,
165
177
  tamaguiDefaultConfig: () => import_v52.defaultConfig,
166
178
  toast: () => toast,
167
- updateTheme: () => import_tamagui49.updateTheme,
179
+ updateTheme: () => import_tamagui60.updateTheme,
168
180
  useBlinkToast: () => useBlinkToast,
169
- useComposedRefs: () => import_tamagui49.useComposedRefs,
170
- useControllableState: () => import_tamagui49.useControllableState,
171
- useDebounce: () => import_tamagui49.useDebounce,
172
- useDebounceValue: () => import_tamagui49.useDebounceValue,
173
- useDidFinishSSR: () => import_tamagui49.useDidFinishSSR,
174
- useEvent: () => import_tamagui49.useEvent,
175
- useForceUpdate: () => import_tamagui49.useForceUpdate,
176
- useIsPresent: () => import_tamagui49.useIsPresent,
177
- useIsomorphicLayoutEffect: () => import_tamagui49.useIsomorphicLayoutEffect,
178
- useMedia: () => import_tamagui49.useMedia,
179
- usePresence: () => import_tamagui49.usePresence,
180
- useTheme: () => import_tamagui49.useTheme,
181
- useThemeName: () => import_tamagui49.useThemeName,
182
- useWindowDimensions: () => import_tamagui49.useWindowDimensions,
183
- withStaticProperties: () => import_tamagui49.withStaticProperties
181
+ useComposedRefs: () => import_tamagui60.useComposedRefs,
182
+ useControllableState: () => import_tamagui60.useControllableState,
183
+ useDebounce: () => import_tamagui60.useDebounce,
184
+ useDebounceValue: () => import_tamagui60.useDebounceValue,
185
+ useDidFinishSSR: () => import_tamagui60.useDidFinishSSR,
186
+ useEvent: () => import_tamagui60.useEvent,
187
+ useForceUpdate: () => import_tamagui60.useForceUpdate,
188
+ useIsPresent: () => import_tamagui60.useIsPresent,
189
+ useIsomorphicLayoutEffect: () => import_tamagui60.useIsomorphicLayoutEffect,
190
+ useMedia: () => import_tamagui60.useMedia,
191
+ usePresence: () => import_tamagui60.usePresence,
192
+ useTheme: () => import_tamagui60.useTheme,
193
+ useThemeName: () => import_tamagui60.useThemeName,
194
+ useWindowDimensions: () => import_tamagui60.useWindowDimensions,
195
+ withStaticProperties: () => import_tamagui60.withStaticProperties
184
196
  });
185
197
  module.exports = __toCommonJS(index_exports);
186
198
 
@@ -193,7 +205,7 @@ var blinkConfig = (0, import_tamagui.createTamagui)({
193
205
 
194
206
  // src/index.ts
195
207
  var import_v52 = require("@tamagui/config/v5");
196
- var import_tamagui49 = require("tamagui");
208
+ var import_tamagui60 = require("tamagui");
197
209
 
198
210
  // src/primitives/Button.tsx
199
211
  var import_tamagui2 = require("tamagui");
@@ -1115,77 +1127,136 @@ function Container({ children, maxWidth = 500, centered = true, padding = "$4" }
1115
1127
  }
1116
1128
 
1117
1129
  // src/patterns/PaywallScreen.tsx
1130
+ var import_react7 = require("react");
1118
1131
  var import_tamagui28 = require("tamagui");
1119
1132
  var import_jsx_runtime20 = require("react/jsx-runtime");
1133
+ function useCountdown(minutes) {
1134
+ const [seconds, setSeconds] = (0, import_react7.useState)((minutes ?? 0) * 60);
1135
+ (0, import_react7.useEffect)(() => {
1136
+ if (!minutes) return;
1137
+ setSeconds(minutes * 60);
1138
+ const id = setInterval(() => setSeconds((s) => s > 0 ? s - 1 : 0), 1e3);
1139
+ return () => clearInterval(id);
1140
+ }, [minutes]);
1141
+ const mm = String(Math.floor(seconds / 60)).padStart(2, "0");
1142
+ const ss = String(seconds % 60).padStart(2, "0");
1143
+ return { display: `${mm}:${ss}`, expired: seconds <= 0 };
1144
+ }
1145
+ function PlanCard({ plan, selected, onPress }) {
1146
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1147
+ import_tamagui28.YStack,
1148
+ {
1149
+ flex: 1,
1150
+ padding: "$3",
1151
+ borderRadius: "$5",
1152
+ borderWidth: 2,
1153
+ borderColor: selected ? "$color9" : "$color5",
1154
+ backgroundColor: selected ? "$color3" : "$color1",
1155
+ pressStyle: { scale: 0.97, opacity: 0.9 },
1156
+ animation: "quick",
1157
+ onPress,
1158
+ cursor: "pointer",
1159
+ position: "relative",
1160
+ gap: "$1.5",
1161
+ alignItems: "center",
1162
+ children: [
1163
+ plan.popular && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { position: "absolute", top: -10, backgroundColor: "$color9", paddingHorizontal: "$2", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$1", color: "white", fontWeight: "700", children: "BEST VALUE" }) }),
1164
+ plan.savings && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { position: "absolute", top: plan.popular ? -24 : -10, right: 6, backgroundColor: "$green9", paddingHorizontal: "$1.5", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$1", color: "white", fontWeight: "700", children: plan.savings }) }),
1165
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$2", fontWeight: "600", color: "$color11", paddingTop: plan.popular ? "$1" : 0, children: plan.name }),
1166
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$7", fontWeight: "800", children: plan.price }),
1167
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.SizableText, { size: "$2", color: "$color9", children: [
1168
+ "/",
1169
+ plan.period
1170
+ ] }),
1171
+ plan.pricePerWeek && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$1", color: "$color10", children: plan.pricePerWeek }),
1172
+ plan.trial && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { backgroundColor: "$green3", paddingHorizontal: "$2", paddingVertical: 2, borderRadius: "$10", marginTop: "$1", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$1", color: "$green9", fontWeight: "700", children: plan.trial }) })
1173
+ ]
1174
+ }
1175
+ );
1176
+ }
1120
1177
  function PaywallScreen({
1121
- title = "Upgrade Your Experience",
1122
- subtitle = "Choose the plan that works for you",
1178
+ title = "Unlock Premium",
1179
+ subtitle,
1180
+ features = [],
1123
1181
  plans,
1124
1182
  selectedPlan,
1125
1183
  onSelectPlan,
1126
1184
  onContinue,
1185
+ onClose,
1127
1186
  onRestore,
1128
- continueLabel = "Continue"
1187
+ onTerms,
1188
+ onPrivacy,
1189
+ continueLabel = "Continue",
1190
+ reassurance = "Cancel anytime",
1191
+ hero,
1192
+ socialProof,
1193
+ countdownMinutes,
1194
+ badge
1129
1195
  }) {
1130
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.YStack, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", children: [
1131
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.YStack, { gap: "$2", paddingTop: "$6", children: [
1132
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$9", fontWeight: "700", textAlign: "center", children: title }),
1133
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$4", color: "$color10", textAlign: "center", children: subtitle })
1134
- ] }),
1135
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { gap: "$3", flex: 1, children: plans.map((plan) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1196
+ const selected = selectedPlan ?? plans.find((p) => p.popular)?.id ?? plans[0]?.id;
1197
+ const countdown = useCountdown(countdownMinutes);
1198
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.YStack, { flex: 1, backgroundColor: "$background", children: [
1199
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.XStack, { position: "absolute", top: "$4", right: "$4", zIndex: 10, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.Button, { size: "$3", circular: true, chromeless: true, onPress: onClose, pressStyle: { opacity: 0.6 }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$5", color: "$color9", children: "\u2715" }) }) }),
1200
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.ScrollView, { flex: 1, contentContainerStyle: { paddingBottom: 220 }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.YStack, { padding: "$4", gap: "$4", paddingTop: "$8", children: [
1201
+ hero && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { alignItems: "center", paddingVertical: "$3", children: hero }),
1202
+ badge && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.XStack, { justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { backgroundColor: "$color9", paddingHorizontal: "$3", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$2", color: "white", fontWeight: "700", children: badge }) }) }),
1203
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.YStack, { gap: "$1.5", alignItems: "center", children: [
1204
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$9", fontWeight: "800", textAlign: "center", children: title }),
1205
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$4", color: "$color10", textAlign: "center", children: subtitle }),
1206
+ socialProof && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$3", color: "$color9", fontWeight: "600", textAlign: "center", children: socialProof })
1207
+ ] }),
1208
+ countdownMinutes && !countdown.expired && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.XStack, { justifyContent: "center", padding: "$2", backgroundColor: "$red3", borderRadius: "$4", alignSelf: "center", paddingHorizontal: "$4", gap: "$2", alignItems: "center", children: [
1209
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$2", color: "$red9", fontWeight: "600", children: "Offer ends in" }),
1210
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$5", color: "$red9", fontWeight: "800", fontFamily: "$mono", children: countdown.display })
1211
+ ] }),
1212
+ features.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { gap: "$2.5", paddingHorizontal: "$2", children: features.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.XStack, { gap: "$2.5", alignItems: "center", children: [
1213
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$4", color: "$green9", children: "\u2713" }),
1214
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$4", color: "$color11", flex: 1, children: f })
1215
+ ] }, i)) }),
1216
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.XStack, { gap: "$3", paddingTop: "$1", children: plans.map((plan) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PlanCard, { plan, selected: selected === plan.id, onPress: () => onSelectPlan?.(plan.id) }, plan.id)) })
1217
+ ] }) }),
1218
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1136
1219
  import_tamagui28.YStack,
1137
1220
  {
1221
+ position: "absolute",
1222
+ bottom: 0,
1223
+ left: 0,
1224
+ right: 0,
1138
1225
  padding: "$4",
1139
- borderRadius: "$5",
1140
- borderWidth: 2,
1141
- borderColor: selectedPlan === plan.id ? "$color9" : "$color4",
1142
- backgroundColor: selectedPlan === plan.id ? "$color2" : "$color1",
1143
- pressStyle: { scale: 0.98 },
1144
- onPress: () => onSelectPlan?.(plan.id),
1145
- cursor: "pointer",
1226
+ paddingBottom: "$6",
1227
+ backgroundColor: "$background",
1228
+ borderTopWidth: 1,
1229
+ borderTopColor: "$color4",
1230
+ gap: "$2.5",
1146
1231
  children: [
1147
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.XStack, { justifyContent: "space-between", alignItems: "center", children: [
1148
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.YStack, { children: [
1149
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$5", fontWeight: "600", children: plan.name }),
1150
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.XStack, { alignItems: "baseline", gap: "$1", children: [
1151
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$8", fontWeight: "700", children: plan.price }),
1152
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.SizableText, { size: "$3", color: "$color9", children: [
1153
- "/",
1154
- plan.period
1155
- ] })
1156
- ] })
1157
- ] }),
1158
- plan.popular && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { backgroundColor: "$color9", paddingHorizontal: "$2", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$1", color: "$color1", fontWeight: "600", children: "POPULAR" }) })
1159
- ] }),
1160
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.YStack, { gap: "$2", paddingTop: "$3", children: plan.features.map((feature, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.XStack, { gap: "$2", alignItems: "center", children: [
1161
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.Circle, { size: 6, backgroundColor: "$green9" }),
1162
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$3", color: "$color11", children: feature })
1163
- ] }, i)) })
1232
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1233
+ import_tamagui28.Button,
1234
+ {
1235
+ size: "$5",
1236
+ backgroundColor: "$color9",
1237
+ color: "$color1",
1238
+ onPress: onContinue,
1239
+ pressStyle: { backgroundColor: "$color8", scale: 0.98 },
1240
+ animation: "quick",
1241
+ borderRadius: "$10",
1242
+ fontWeight: "700",
1243
+ children: continueLabel
1244
+ }
1245
+ ),
1246
+ reassurance && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$2", color: "$color9", textAlign: "center", children: reassurance }),
1247
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.XStack, { justifyContent: "center", gap: "$3", children: [
1248
+ onRestore && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$2", color: "$color8", onPress: onRestore, pressStyle: { opacity: 0.6 }, children: "Restore" }),
1249
+ onTerms && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$2", color: "$color8", onPress: onTerms, pressStyle: { opacity: 0.6 }, children: "Terms" }),
1250
+ onPrivacy && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$2", color: "$color8", onPress: onPrivacy, pressStyle: { opacity: 0.6 }, children: "Privacy" })
1251
+ ] })
1164
1252
  ]
1165
- },
1166
- plan.id
1167
- )) }),
1168
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_tamagui28.YStack, { gap: "$3", paddingBottom: "$4", children: [
1169
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1170
- import_tamagui28.Button,
1171
- {
1172
- size: "$5",
1173
- backgroundColor: "$color9",
1174
- color: "$color1",
1175
- onPress: onContinue,
1176
- hoverStyle: { backgroundColor: "$color10" },
1177
- pressStyle: { backgroundColor: "$color8" },
1178
- borderRadius: "$5",
1179
- children: continueLabel
1180
- }
1181
- ),
1182
- onRestore && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.Button, { size: "$3", chromeless: true, onPress: onRestore, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_tamagui28.SizableText, { size: "$3", color: "$color9", children: "Restore Purchases" }) })
1183
- ] })
1253
+ }
1254
+ )
1184
1255
  ] });
1185
1256
  }
1186
1257
 
1187
1258
  // src/patterns/OnboardingCarousel.tsx
1188
- var import_react7 = require("react");
1259
+ var import_react8 = require("react");
1189
1260
  var import_tamagui29 = require("tamagui");
1190
1261
  var import_jsx_runtime21 = require("react/jsx-runtime");
1191
1262
  function OnboardingCarousel({
@@ -1196,7 +1267,7 @@ function OnboardingCarousel({
1196
1267
  skipLabel = "Skip",
1197
1268
  nextLabel = "Next"
1198
1269
  }) {
1199
- const [current, setCurrent] = (0, import_react7.useState)(0);
1270
+ const [current, setCurrent] = (0, import_react8.useState)(0);
1200
1271
  const isLast = current === steps.length - 1;
1201
1272
  const step = steps[current];
1202
1273
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_tamagui29.YStack, { flex: 1, backgroundColor: "$background", padding: "$4", justifyContent: "space-between", children: [
@@ -1398,40 +1469,53 @@ function AppHeader({ title, subtitle, variant = "simple", onBack, avatar, left,
1398
1469
  var import_tamagui35 = require("tamagui");
1399
1470
  var import_react_native2 = require("react-native");
1400
1471
  var import_jsx_runtime27 = require("react/jsx-runtime");
1401
- function BottomSheet({ open, onOpenChange, title, children, snapPoints = [85], dismissOnSnapToBottom = true, showHandle = true, showClose = false }) {
1402
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_tamagui35.Sheet, { modal: true, open, onOpenChange, snapPoints, dismissOnSnapToBottom, animation: "medium", children: [
1403
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1404
- showHandle && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.Sheet.Handle, {}),
1405
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_tamagui35.Sheet.Frame, { borderTopLeftRadius: "$6", borderTopRightRadius: "$6", backgroundColor: "$background", children: [
1406
- (title || showClose) && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_tamagui35.XStack, { paddingHorizontal: "$4", paddingTop: "$3", paddingBottom: "$2", alignItems: "center", justifyContent: "space-between", children: [
1407
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.SizableText, { size: "$6", fontWeight: "600", flexShrink: 1, children: title }),
1408
- showClose && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1409
- import_tamagui35.XStack,
1410
- {
1411
- width: 28,
1412
- height: 28,
1413
- borderRadius: "$10",
1414
- backgroundColor: "$color4",
1415
- alignItems: "center",
1416
- justifyContent: "center",
1417
- pressStyle: { opacity: 0.7 },
1418
- onPress: () => onOpenChange(false),
1419
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.SizableText, { size: "$3", color: "$color10", fontWeight: "600", children: "\u2715" })
1420
- }
1421
- )
1422
- ] }),
1423
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native2.ScrollView, { contentContainerStyle: { paddingBottom: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.YStack, { padding: "$4", children }) })
1424
- ] })
1425
- ] });
1472
+ function BottomSheet({ open, onOpenChange, title, children, snapPoints = [85], dismissOnSnapToBottom = true, showHandle = true, showClose = false, zIndex = 1e5 }) {
1473
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
1474
+ import_tamagui35.Sheet,
1475
+ {
1476
+ modal: true,
1477
+ forceRemoveScrollEnabled: open,
1478
+ open,
1479
+ onOpenChange,
1480
+ snapPoints,
1481
+ dismissOnSnapToBottom,
1482
+ zIndex,
1483
+ animation: "medium",
1484
+ children: [
1485
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1486
+ showHandle && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.Sheet.Handle, {}),
1487
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_tamagui35.Sheet.Frame, { children: [
1488
+ (title || showClose) && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_tamagui35.XStack, { paddingHorizontal: "$4", paddingTop: "$3", paddingBottom: "$2", alignItems: "center", justifyContent: "space-between", children: [
1489
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.SizableText, { size: "$6", fontWeight: "600", flexShrink: 1, children: title }),
1490
+ showClose && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1491
+ import_tamagui35.XStack,
1492
+ {
1493
+ width: 28,
1494
+ height: 28,
1495
+ borderRadius: "$10",
1496
+ backgroundColor: "$color4",
1497
+ alignItems: "center",
1498
+ justifyContent: "center",
1499
+ pressStyle: { opacity: 0.7 },
1500
+ onPress: () => onOpenChange(false),
1501
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.SizableText, { size: "$3", color: "$color10", fontWeight: "600", children: "\u2715" })
1502
+ }
1503
+ )
1504
+ ] }),
1505
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native2.ScrollView, { contentContainerStyle: { paddingBottom: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_tamagui35.YStack, { padding: "$4", children }) })
1506
+ ] })
1507
+ ]
1508
+ }
1509
+ );
1426
1510
  }
1427
1511
 
1428
1512
  // src/patterns/LoginScreen.tsx
1429
- var import_react8 = require("react");
1513
+ var import_react9 = require("react");
1430
1514
  var import_tamagui36 = require("tamagui");
1431
1515
  var import_jsx_runtime28 = require("react/jsx-runtime");
1432
1516
  function LoginScreen({ title = "Welcome", subtitle = "Sign in to continue", logo, providers = [], onProviderPress, showEmailForm, onEmailSubmit, onForgotPassword, onCreateAccount, onTerms, onPrivacy, loading }) {
1433
- const [email, setEmail] = (0, import_react8.useState)("");
1434
- const [password, setPassword] = (0, import_react8.useState)("");
1517
+ const [email, setEmail] = (0, import_react9.useState)("");
1518
+ const [password, setPassword] = (0, import_react9.useState)("");
1435
1519
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_tamagui36.YStack, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", justifyContent: "center", children: [
1436
1520
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_tamagui36.YStack, { alignItems: "center", gap: "$2", children: [
1437
1521
  logo && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_tamagui36.YStack, { paddingBottom: "$3", children: logo }),
@@ -1578,55 +1662,68 @@ function FloatingActionButton({ icon, label, onPress, position = "bottom-right",
1578
1662
  // src/patterns/ActionSheet.tsx
1579
1663
  var import_tamagui40 = require("tamagui");
1580
1664
  var import_jsx_runtime32 = require("react/jsx-runtime");
1581
- function ActionSheet({ open, onOpenChange, title, items, onSelect, cancelLabel = "Cancel" }) {
1582
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_tamagui40.Sheet, { modal: true, open, onOpenChange, snapPoints: [50], dismissOnSnapToBottom: true, animation: "medium", children: [
1583
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1584
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.Sheet.Handle, {}),
1585
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_tamagui40.Sheet.Frame, { borderTopLeftRadius: "$6", borderTopRightRadius: "$6", backgroundColor: "$background", children: [
1586
- title && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.SizableText, { size: "$3", color: "$color8", textAlign: "center", paddingTop: "$3", paddingBottom: "$1", children: title }),
1587
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.YStack, { paddingHorizontal: "$3", paddingTop: "$2", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1588
- import_tamagui40.XStack,
1589
- {
1590
- height: 52,
1591
- alignItems: "center",
1592
- gap: "$3",
1593
- paddingHorizontal: "$3",
1594
- borderRadius: "$4",
1595
- pressStyle: { backgroundColor: "$color3" },
1596
- onPress: () => {
1597
- onSelect(item.id);
1598
- onOpenChange(false);
1599
- },
1600
- children: [
1601
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.SizableText, { size: "$5", children: item.icon }),
1602
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1603
- import_tamagui40.SizableText,
1604
- {
1605
- size: "$5",
1606
- flex: 1,
1607
- color: item.destructive ? "$red9" : "$color12",
1608
- fontWeight: item.destructive ? "600" : "400",
1609
- children: item.label
1610
- }
1611
- )
1612
- ]
1613
- },
1614
- item.id
1615
- )) }),
1616
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.YStack, { paddingHorizontal: "$3", paddingVertical: "$3", borderTopWidth: 1, borderTopColor: "$borderColor", marginTop: "$2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1617
- import_tamagui40.XStack,
1618
- {
1619
- height: 48,
1620
- alignItems: "center",
1621
- justifyContent: "center",
1622
- borderRadius: "$4",
1623
- pressStyle: { backgroundColor: "$color3" },
1624
- onPress: () => onOpenChange(false),
1625
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.SizableText, { size: "$5", fontWeight: "600", color: "$color9", children: cancelLabel })
1626
- }
1627
- ) })
1628
- ] })
1629
- ] });
1665
+ function ActionSheet({ open, onOpenChange, title, items, onSelect, cancelLabel = "Cancel", zIndex = 1e5 }) {
1666
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1667
+ import_tamagui40.Sheet,
1668
+ {
1669
+ modal: true,
1670
+ forceRemoveScrollEnabled: open,
1671
+ open,
1672
+ onOpenChange,
1673
+ snapPoints: [50],
1674
+ dismissOnSnapToBottom: true,
1675
+ zIndex,
1676
+ animation: "medium",
1677
+ children: [
1678
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1679
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.Sheet.Handle, {}),
1680
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_tamagui40.Sheet.Frame, { children: [
1681
+ title && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.SizableText, { size: "$3", color: "$color8", textAlign: "center", paddingTop: "$3", paddingBottom: "$1", children: title }),
1682
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.YStack, { paddingHorizontal: "$3", paddingTop: "$2", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1683
+ import_tamagui40.XStack,
1684
+ {
1685
+ height: 52,
1686
+ alignItems: "center",
1687
+ gap: "$3",
1688
+ paddingHorizontal: "$3",
1689
+ borderRadius: "$4",
1690
+ pressStyle: { backgroundColor: "$color3" },
1691
+ onPress: () => {
1692
+ onSelect(item.id);
1693
+ onOpenChange(false);
1694
+ },
1695
+ children: [
1696
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.SizableText, { size: "$5", children: item.icon }),
1697
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1698
+ import_tamagui40.SizableText,
1699
+ {
1700
+ size: "$5",
1701
+ flex: 1,
1702
+ color: item.destructive ? "$red9" : "$color12",
1703
+ fontWeight: item.destructive ? "600" : "400",
1704
+ children: item.label
1705
+ }
1706
+ )
1707
+ ]
1708
+ },
1709
+ item.id
1710
+ )) }),
1711
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.YStack, { paddingHorizontal: "$3", paddingVertical: "$3", borderTopWidth: 1, borderTopColor: "$borderColor", marginTop: "$2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1712
+ import_tamagui40.XStack,
1713
+ {
1714
+ height: 48,
1715
+ alignItems: "center",
1716
+ justifyContent: "center",
1717
+ borderRadius: "$4",
1718
+ pressStyle: { backgroundColor: "$color3" },
1719
+ onPress: () => onOpenChange(false),
1720
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_tamagui40.SizableText, { size: "$5", fontWeight: "600", color: "$color9", children: cancelLabel })
1721
+ }
1722
+ ) })
1723
+ ] })
1724
+ ]
1725
+ }
1726
+ );
1630
1727
  }
1631
1728
 
1632
1729
  // src/patterns/Skeleton.tsx
@@ -1694,11 +1791,11 @@ function ProgressSteps({ steps, currentStep, variant = "dots" }) {
1694
1791
  }
1695
1792
 
1696
1793
  // src/patterns/SwipeableRow.tsx
1697
- var import_react9 = require("react");
1794
+ var import_react10 = require("react");
1698
1795
  var import_tamagui44 = require("tamagui");
1699
1796
  var import_jsx_runtime36 = require("react/jsx-runtime");
1700
1797
  function SwipeableRow({ children, leftActions, rightActions }) {
1701
- const [showActions, setShowActions] = (0, import_react9.useState)(false);
1798
+ const [showActions, setShowActions] = (0, import_react10.useState)(false);
1702
1799
  const actions = [...leftActions ?? [], ...rightActions ?? []];
1703
1800
  if (actions.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_jsx_runtime36.Fragment, { children });
1704
1801
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_tamagui44.YStack, { children: [
@@ -1773,13 +1870,13 @@ function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio =
1773
1870
  }
1774
1871
 
1775
1872
  // src/patterns/Carousel.tsx
1776
- var import_react10 = require("react");
1873
+ var import_react11 = require("react");
1777
1874
  var import_tamagui46 = require("tamagui");
1778
1875
  var import_react_native3 = require("react-native");
1779
1876
  var import_jsx_runtime38 = require("react/jsx-runtime");
1780
1877
  function Carousel({ children, gap = "$3", snapToInterval, showIndicators = false }) {
1781
- const [activeIndex, setActiveIndex] = (0, import_react10.useState)(0);
1782
- const count = import_react10.Children.count(children);
1878
+ const [activeIndex, setActiveIndex] = (0, import_react11.useState)(0);
1879
+ const count = import_react11.Children.count(children);
1783
1880
  const gapPx = gap === "$2" ? 8 : gap === "$3" ? 12 : 16;
1784
1881
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_tamagui46.YStack, { gap: "$3", children: [
1785
1882
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
@@ -1814,6 +1911,837 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1814
1911
  }
1815
1912
  );
1816
1913
  }
1914
+
1915
+ // src/patterns/ProductCard.tsx
1916
+ var import_tamagui48 = require("tamagui");
1917
+ var import_jsx_runtime40 = require("react/jsx-runtime");
1918
+ function Stars({ rating = 0 }) {
1919
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.XStack, { gap: "$0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.SizableText, { size: "$2", color: i < Math.round(rating) ? "$yellow9" : "$color5", children: "\u2605" }, i)) });
1920
+ }
1921
+ function CardContent2({ title, price, originalPrice, rating, reviewCount, onAddToCart }) {
1922
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_tamagui48.YStack, { flex: 1, gap: "$1.5", justifyContent: "space-between", children: [
1923
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_tamagui48.YStack, { gap: "$1", children: [
1924
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.SizableText, { size: "$4", fontWeight: "600", numberOfLines: 2, children: title }),
1925
+ rating !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_tamagui48.XStack, { gap: "$1.5", alignItems: "center", children: [
1926
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Stars, { rating }),
1927
+ reviewCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_tamagui48.SizableText, { size: "$2", color: "$color9", children: [
1928
+ "(",
1929
+ reviewCount,
1930
+ ")"
1931
+ ] })
1932
+ ] })
1933
+ ] }),
1934
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_tamagui48.XStack, { alignItems: "center", justifyContent: "space-between", children: [
1935
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_tamagui48.XStack, { gap: "$2", alignItems: "baseline", children: [
1936
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.SizableText, { size: "$6", fontWeight: "700", children: price }),
1937
+ originalPrice && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.SizableText, { size: "$3", color: "$color8", textDecorationLine: "line-through", children: originalPrice })
1938
+ ] }),
1939
+ onAddToCart && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
1940
+ import_tamagui48.Button,
1941
+ {
1942
+ size: "$3",
1943
+ backgroundColor: "$color9",
1944
+ color: "$color1",
1945
+ borderRadius: "$10",
1946
+ onPress: (e) => {
1947
+ e.stopPropagation?.();
1948
+ onAddToCart();
1949
+ },
1950
+ pressStyle: { backgroundColor: "$color8", scale: 0.95 },
1951
+ animation: "quick",
1952
+ children: "+ Cart"
1953
+ }
1954
+ )
1955
+ ] })
1956
+ ] });
1957
+ }
1958
+ function ProductCard({ image, title, price, originalPrice, rating, reviewCount, badge, onPress, onAddToCart, variant = "vertical" }) {
1959
+ const isHorizontal = variant === "horizontal";
1960
+ const Wrapper = isHorizontal ? import_tamagui48.XStack : import_tamagui48.YStack;
1961
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
1962
+ Wrapper,
1963
+ {
1964
+ backgroundColor: "$color1",
1965
+ borderRadius: "$5",
1966
+ overflow: "hidden",
1967
+ borderWidth: 1,
1968
+ borderColor: "$color4",
1969
+ onPress,
1970
+ animation: "quick",
1971
+ pressStyle: onPress ? { scale: 0.98, opacity: 0.9 } : void 0,
1972
+ ...isHorizontal ? { height: 140 } : {},
1973
+ children: [
1974
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_tamagui48.YStack, { ...isHorizontal ? { width: 140 } : { aspectRatio: 4 / 3 }, position: "relative", children: [
1975
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.Image, { source: { uri: image }, width: "100%", height: "100%", objectFit: "cover" }),
1976
+ badge && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
1977
+ import_tamagui48.XStack,
1978
+ {
1979
+ position: "absolute",
1980
+ top: "$2",
1981
+ left: "$2",
1982
+ backgroundColor: "$red9",
1983
+ paddingHorizontal: "$2",
1984
+ paddingVertical: "$1",
1985
+ borderRadius: "$10",
1986
+ children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.SizableText, { size: "$1", fontWeight: "700", color: "white", children: badge })
1987
+ }
1988
+ )
1989
+ ] }),
1990
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_tamagui48.YStack, { flex: 1, padding: "$3", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(CardContent2, { ...{ title, price, originalPrice, rating, reviewCount, onAddToCart } }) })
1991
+ ]
1992
+ }
1993
+ );
1994
+ }
1995
+
1996
+ // src/patterns/PricingTable.tsx
1997
+ var import_tamagui49 = require("tamagui");
1998
+ var import_jsx_runtime41 = require("react/jsx-runtime");
1999
+ function BillingToggle({ annual, onToggle }) {
2000
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.XStack, { alignSelf: "center", backgroundColor: "$color3", borderRadius: "$10", padding: "$1", gap: "$0.5", children: ["Monthly", "Annual"].map((label, i) => {
2001
+ const active = i === 1 ? annual : !annual;
2002
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2003
+ import_tamagui49.XStack,
2004
+ {
2005
+ paddingHorizontal: "$4",
2006
+ paddingVertical: "$2",
2007
+ borderRadius: "$10",
2008
+ backgroundColor: active ? "$color9" : "transparent",
2009
+ onPress: () => onToggle(i === 1),
2010
+ pressStyle: { opacity: 0.8 },
2011
+ animation: "quick",
2012
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.SizableText, { size: "$3", fontWeight: "600", color: active ? "$color1" : "$color10", children: label })
2013
+ },
2014
+ label
2015
+ );
2016
+ }) });
2017
+ }
2018
+ function PlanCard2({ plan, selected, onSelect }) {
2019
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
2020
+ import_tamagui49.YStack,
2021
+ {
2022
+ flex: 1,
2023
+ minWidth: 260,
2024
+ padding: "$4",
2025
+ borderRadius: "$5",
2026
+ gap: "$3",
2027
+ borderWidth: 2,
2028
+ borderColor: selected ? "$color9" : plan.popular ? "$color9" : "$color4",
2029
+ backgroundColor: plan.popular ? "$color2" : "$color1",
2030
+ position: "relative",
2031
+ pressStyle: { scale: 0.98 },
2032
+ animation: "quick",
2033
+ onPress: onSelect,
2034
+ children: [
2035
+ plan.popular && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2036
+ import_tamagui49.XStack,
2037
+ {
2038
+ position: "absolute",
2039
+ top: -12,
2040
+ alignSelf: "center",
2041
+ backgroundColor: "$color9",
2042
+ paddingHorizontal: "$3",
2043
+ paddingVertical: "$1",
2044
+ borderRadius: "$10",
2045
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.SizableText, { size: "$1", fontWeight: "700", color: "$color1", children: "POPULAR" })
2046
+ }
2047
+ ),
2048
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_tamagui49.YStack, { gap: "$1", alignItems: "center", paddingTop: plan.popular ? "$2" : 0, children: [
2049
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.SizableText, { size: "$4", fontWeight: "600", color: "$color11", children: plan.name }),
2050
+ plan.description && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.SizableText, { size: "$2", color: "$color9", textAlign: "center", children: plan.description }),
2051
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_tamagui49.XStack, { alignItems: "baseline", gap: "$1", children: [
2052
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.SizableText, { size: "$9", fontWeight: "800", children: plan.price }),
2053
+ plan.period && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_tamagui49.SizableText, { size: "$3", color: "$color9", children: [
2054
+ "/",
2055
+ plan.period
2056
+ ] })
2057
+ ] })
2058
+ ] }),
2059
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.YStack, { gap: "$2", flex: 1, children: plan.features.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_tamagui49.XStack, { gap: "$2", alignItems: "center", children: [
2060
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.SizableText, { size: "$3", color: f.included ? "$green9" : "$color6", children: f.included ? "\u2713" : "\u2717" }),
2061
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_tamagui49.SizableText, { size: "$3", color: f.included ? "$color11" : "$color8", flex: 1, children: f.label })
2062
+ ] }, i)) }),
2063
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2064
+ import_tamagui49.Button,
2065
+ {
2066
+ size: "$4",
2067
+ borderRadius: "$10",
2068
+ fontWeight: "700",
2069
+ animation: "quick",
2070
+ backgroundColor: selected || plan.popular ? "$color9" : "transparent",
2071
+ color: selected || plan.popular ? "$color1" : "$color11",
2072
+ borderWidth: selected || plan.popular ? 0 : 1,
2073
+ borderColor: "$color7",
2074
+ onPress: onSelect,
2075
+ pressStyle: { scale: 0.97, opacity: 0.9 },
2076
+ children: plan.cta ?? "Get Started"
2077
+ }
2078
+ )
2079
+ ]
2080
+ }
2081
+ );
2082
+ }
2083
+ function PricingTable({ plans, selectedPlan, onSelectPlan, annual = false, onToggleBilling }) {
2084
+ const selected = selectedPlan ?? plans.find((p) => p.popular)?.id;
2085
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_tamagui49.YStack, { gap: "$4", children: [
2086
+ onToggleBilling && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(BillingToggle, { annual, onToggle: onToggleBilling }),
2087
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2088
+ import_tamagui49.ScrollView,
2089
+ {
2090
+ horizontal: true,
2091
+ showsHorizontalScrollIndicator: false,
2092
+ contentContainerStyle: { gap: 12, paddingHorizontal: 4 },
2093
+ children: plans.map((plan) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2094
+ PlanCard2,
2095
+ {
2096
+ plan,
2097
+ selected: selected === plan.id,
2098
+ onSelect: () => onSelectPlan?.(plan.id)
2099
+ },
2100
+ plan.id
2101
+ ))
2102
+ }
2103
+ )
2104
+ ] });
2105
+ }
2106
+
2107
+ // src/patterns/CountdownBanner.tsx
2108
+ var import_react12 = require("react");
2109
+ var import_tamagui50 = require("tamagui");
2110
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2111
+ function useCountdown2(endTime, minutes, onExpire) {
2112
+ const getRemaining = (0, import_react12.useCallback)(() => {
2113
+ if (endTime) return Math.max(0, Math.floor((endTime.getTime() - Date.now()) / 1e3));
2114
+ return 0;
2115
+ }, [endTime]);
2116
+ const [seconds, setSeconds] = (0, import_react12.useState)(() => endTime ? getRemaining() : (minutes ?? 0) * 60);
2117
+ const firedRef = (0, import_react12.useRef)(false);
2118
+ (0, import_react12.useEffect)(() => {
2119
+ if (endTime) setSeconds(getRemaining());
2120
+ else setSeconds((minutes ?? 0) * 60);
2121
+ firedRef.current = false;
2122
+ }, [endTime, minutes, getRemaining]);
2123
+ (0, import_react12.useEffect)(() => {
2124
+ if (seconds <= 0) return;
2125
+ const id = setInterval(() => {
2126
+ setSeconds((s) => {
2127
+ const next = endTime ? Math.max(0, Math.floor((endTime.getTime() - Date.now()) / 1e3)) : s - 1;
2128
+ if (next <= 0 && !firedRef.current) {
2129
+ firedRef.current = true;
2130
+ onExpire?.();
2131
+ }
2132
+ return Math.max(0, next);
2133
+ });
2134
+ }, 1e3);
2135
+ return () => clearInterval(id);
2136
+ }, [seconds > 0, endTime, onExpire]);
2137
+ const hh = String(Math.floor(seconds / 3600)).padStart(2, "0");
2138
+ const mm = String(Math.floor(seconds % 3600 / 60)).padStart(2, "0");
2139
+ const ss = String(seconds % 60).padStart(2, "0");
2140
+ const display = seconds >= 3600 ? `${hh}:${mm}:${ss}` : `${mm}:${ss}`;
2141
+ return { display, expired: seconds <= 0 };
2142
+ }
2143
+ function TimeBox({ value }) {
2144
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.XStack, { backgroundColor: "rgba(0,0,0,0.15)", paddingHorizontal: "$2", paddingVertical: "$1", borderRadius: "$3", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.SizableText, { size: "$6", fontWeight: "800", color: "white", fontFamily: "$mono", children: value }) });
2145
+ }
2146
+ function CountdownBanner({ endTime, minutes, label = "Offer ends in", onExpire, variant = "banner" }) {
2147
+ const { display, expired } = useCountdown2(endTime, minutes, onExpire);
2148
+ if (expired) return null;
2149
+ const parts = display.split(":");
2150
+ if (variant === "badge") {
2151
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_tamagui50.XStack, { backgroundColor: "$red9", paddingHorizontal: "$2.5", paddingVertical: "$1", borderRadius: "$10", gap: "$1.5", alignItems: "center", children: [
2152
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.SizableText, { size: "$1", fontWeight: "600", color: "white", children: label }),
2153
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.SizableText, { size: "$2", fontWeight: "800", color: "white", fontFamily: "$mono", children: display })
2154
+ ] });
2155
+ }
2156
+ if (variant === "compact") {
2157
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_tamagui50.XStack, { backgroundColor: "$red3", paddingHorizontal: "$3", paddingVertical: "$2", borderRadius: "$4", gap: "$2", alignItems: "center", alignSelf: "center", children: [
2158
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.SizableText, { size: "$3", fontWeight: "600", color: "$red9", children: label }),
2159
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.SizableText, { size: "$5", fontWeight: "800", color: "$red9", fontFamily: "$mono", children: display })
2160
+ ] });
2161
+ }
2162
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_tamagui50.YStack, { backgroundColor: "$red9", paddingVertical: "$3", paddingHorizontal: "$4", gap: "$1.5", alignItems: "center", children: [
2163
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.SizableText, { size: "$3", fontWeight: "600", color: "white", opacity: 0.9, children: label }),
2164
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.XStack, { gap: "$1.5", alignItems: "center", children: parts.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_tamagui50.XStack, { gap: "$1.5", alignItems: "center", children: [
2165
+ i > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_tamagui50.SizableText, { size: "$6", fontWeight: "800", color: "white", children: ":" }),
2166
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(TimeBox, { value: p })
2167
+ ] }, i)) })
2168
+ ] });
2169
+ }
2170
+
2171
+ // src/patterns/TestimonialCard.tsx
2172
+ var import_tamagui51 = require("tamagui");
2173
+ var import_jsx_runtime43 = require("react/jsx-runtime");
2174
+ function Stars2({ count = 0 }) {
2175
+ if (!count) return null;
2176
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_tamagui51.XStack, { gap: "$0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_tamagui51.SizableText, { size: "$3", color: i < Math.round(count) ? "$yellow9" : "$color5", children: "\u2605" }, i)) });
2177
+ }
2178
+ function AuthorRow({ author, role, avatar }) {
2179
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_tamagui51.XStack, { gap: "$2.5", alignItems: "center", children: [
2180
+ avatar && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_tamagui51.Image, { source: { uri: avatar }, width: 36, height: 36, borderRadius: 18, objectFit: "cover" }),
2181
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_tamagui51.YStack, { children: [
2182
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_tamagui51.SizableText, { size: "$3", fontWeight: "600", children: author }),
2183
+ role && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_tamagui51.SizableText, { size: "$2", color: "$color9", children: role })
2184
+ ] })
2185
+ ] });
2186
+ }
2187
+ function TestimonialCard({ quote, author, role, avatar, rating, variant = "card" }) {
2188
+ if (variant === "minimal") {
2189
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_tamagui51.YStack, { gap: "$3", paddingVertical: "$2", children: [
2190
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Stars2, { count: rating }),
2191
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_tamagui51.SizableText, { size: "$4", color: "$color11", fontStyle: "italic", lineHeight: 24, children: [
2192
+ '"',
2193
+ quote,
2194
+ '"'
2195
+ ] }),
2196
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AuthorRow, { author, role, avatar })
2197
+ ] });
2198
+ }
2199
+ if (variant === "featured") {
2200
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_tamagui51.YStack, { backgroundColor: "$color3", padding: "$5", borderRadius: "$6", gap: "$4", alignItems: "center", children: [
2201
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_tamagui51.SizableText, { size: "$8", color: "$color9", opacity: 0.3, fontWeight: "800", children: '"' }),
2202
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Stars2, { count: rating }),
2203
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_tamagui51.SizableText, { size: "$5", color: "$color12", fontStyle: "italic", textAlign: "center", lineHeight: 28, children: [
2204
+ '"',
2205
+ quote,
2206
+ '"'
2207
+ ] }),
2208
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AuthorRow, { author, role, avatar })
2209
+ ] });
2210
+ }
2211
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
2212
+ import_tamagui51.YStack,
2213
+ {
2214
+ backgroundColor: "$color1",
2215
+ padding: "$4",
2216
+ borderRadius: "$5",
2217
+ borderWidth: 1,
2218
+ borderColor: "$color4",
2219
+ gap: "$3",
2220
+ children: [
2221
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Stars2, { count: rating }),
2222
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_tamagui51.SizableText, { size: "$4", color: "$color11", fontStyle: "italic", lineHeight: 24, children: [
2223
+ '"',
2224
+ quote,
2225
+ '"'
2226
+ ] }),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AuthorRow, { author, role, avatar })
2228
+ ]
2229
+ }
2230
+ );
2231
+ }
2232
+
2233
+ // src/patterns/ConfirmDialog.tsx
2234
+ var import_tamagui52 = require("tamagui");
2235
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2236
+ function ConfirmDialog({
2237
+ open,
2238
+ onOpenChange,
2239
+ title,
2240
+ description,
2241
+ confirmLabel = "Confirm",
2242
+ cancelLabel = "Cancel",
2243
+ onConfirm,
2244
+ onCancel,
2245
+ destructive = false,
2246
+ icon
2247
+ }) {
2248
+ const handleCancel = () => {
2249
+ onCancel?.();
2250
+ onOpenChange(false);
2251
+ };
2252
+ const handleConfirm = () => {
2253
+ onConfirm?.();
2254
+ onOpenChange(false);
2255
+ };
2256
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_tamagui52.AlertDialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_tamagui52.AlertDialog.Portal, { children: [
2257
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2258
+ import_tamagui52.AlertDialog.Overlay,
2259
+ {
2260
+ opacity: 0.5,
2261
+ enterStyle: { opacity: 0 },
2262
+ exitStyle: { opacity: 0 },
2263
+ animation: "quick"
2264
+ },
2265
+ "overlay"
2266
+ ),
2267
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2268
+ import_tamagui52.AlertDialog.Content,
2269
+ {
2270
+ bordered: true,
2271
+ elevate: true,
2272
+ width: "90%",
2273
+ maxWidth: 400,
2274
+ enterStyle: { y: -20, opacity: 0, scale: 0.9 },
2275
+ exitStyle: { y: 10, opacity: 0, scale: 0.95 },
2276
+ x: 0,
2277
+ y: 0,
2278
+ scale: 1,
2279
+ opacity: 1,
2280
+ animation: "quick",
2281
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_tamagui52.YStack, { gap: "$4", padding: "$4", children: [
2282
+ icon && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_tamagui52.YStack, { alignItems: "center", children: icon }),
2283
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_tamagui52.YStack, { gap: "$2", alignItems: icon ? "center" : "flex-start", children: [
2284
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_tamagui52.AlertDialog.Title, { size: "$6", fontWeight: "700", children: title }),
2285
+ description && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2286
+ import_tamagui52.AlertDialog.Description,
2287
+ {
2288
+ size: "$3",
2289
+ color: "$color10",
2290
+ textAlign: icon ? "center" : "left",
2291
+ children: description
2292
+ }
2293
+ )
2294
+ ] }),
2295
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_tamagui52.XStack, { gap: "$3", justifyContent: "flex-end", children: [
2296
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2297
+ import_tamagui52.Button,
2298
+ {
2299
+ flex: 1,
2300
+ size: "$4",
2301
+ borderRadius: "$4",
2302
+ variant: "outlined",
2303
+ borderColor: "$color7",
2304
+ onPress: handleCancel,
2305
+ pressStyle: { opacity: 0.7 },
2306
+ animation: "quick",
2307
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_tamagui52.SizableText, { fontWeight: "600", children: cancelLabel })
2308
+ }
2309
+ ),
2310
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2311
+ import_tamagui52.Button,
2312
+ {
2313
+ flex: 1,
2314
+ size: "$4",
2315
+ borderRadius: "$4",
2316
+ backgroundColor: destructive ? "$red9" : "$color9",
2317
+ onPress: handleConfirm,
2318
+ pressStyle: { backgroundColor: destructive ? "$red8" : "$color8", scale: 0.97 },
2319
+ animation: "quick",
2320
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_tamagui52.SizableText, { fontWeight: "600", color: "white", children: confirmLabel })
2321
+ }
2322
+ )
2323
+ ] })
2324
+ ] })
2325
+ },
2326
+ "content"
2327
+ )
2328
+ ] }) });
2329
+ }
2330
+
2331
+ // src/patterns/Chip.tsx
2332
+ var import_react13 = require("react");
2333
+ var import_tamagui53 = require("tamagui");
2334
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2335
+ var sizes2 = { sm: { h: 28, px: "$2", text: "$2" }, md: { h: 34, px: "$3", text: "$3" }, lg: { h: 42, px: "$4", text: "$4" } };
2336
+ function Chip({ label, selected, onPress, onRemove, variant = "filled", size = "md", icon, color }) {
2337
+ const s = sizes2[size];
2338
+ const filled = variant === "filled";
2339
+ const active = selected ?? false;
2340
+ const bg = active ? color ?? "$color9" : filled ? "$color3" : "transparent";
2341
+ const border = active ? color ?? "$color9" : "$color6";
2342
+ const fg = active ? "$color1" : "$color11";
2343
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
2344
+ import_tamagui53.XStack,
2345
+ {
2346
+ height: s.h,
2347
+ borderRadius: "$10",
2348
+ paddingHorizontal: s.px,
2349
+ backgroundColor: bg,
2350
+ borderWidth: filled ? 0 : 1,
2351
+ borderColor: border,
2352
+ alignItems: "center",
2353
+ gap: "$1.5",
2354
+ pressStyle: { scale: 0.96, opacity: 0.85 },
2355
+ animation: "quick",
2356
+ onPress,
2357
+ cursor: "pointer",
2358
+ children: [
2359
+ active && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_tamagui53.SizableText, { size: s.text, color: fg, children: "\u2713" }),
2360
+ icon && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_tamagui53.SizableText, { color: fg, children: icon }),
2361
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_tamagui53.SizableText, { size: s.text, color: fg, fontWeight: "500", children: label }),
2362
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2363
+ import_tamagui53.SizableText,
2364
+ {
2365
+ size: "$2",
2366
+ color: fg,
2367
+ opacity: 0.7,
2368
+ pressStyle: { opacity: 1 },
2369
+ onPress: (e) => {
2370
+ e.stopPropagation?.();
2371
+ onRemove();
2372
+ },
2373
+ marginLeft: "$1",
2374
+ children: "\u2715"
2375
+ }
2376
+ )
2377
+ ]
2378
+ }
2379
+ );
2380
+ }
2381
+ function ChipGroup({ chips, selected = [], onSelectionChange, multiSelect = true, variant, size }) {
2382
+ const toggle = (0, import_react13.useCallback)((id) => {
2383
+ if (!onSelectionChange) return;
2384
+ const isSelected = selected.includes(id);
2385
+ if (multiSelect) {
2386
+ onSelectionChange(isSelected ? selected.filter((s) => s !== id) : [...selected, id]);
2387
+ } else {
2388
+ onSelectionChange(isSelected ? [] : [id]);
2389
+ }
2390
+ }, [selected, onSelectionChange, multiSelect]);
2391
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_tamagui53.XStack, { flexWrap: "wrap", gap: "$2", children: chips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2392
+ Chip,
2393
+ {
2394
+ label: chip.label,
2395
+ icon: chip.icon,
2396
+ selected: selected.includes(chip.id),
2397
+ onPress: () => toggle(chip.id),
2398
+ variant,
2399
+ size
2400
+ },
2401
+ chip.id
2402
+ )) });
2403
+ }
2404
+
2405
+ // src/patterns/OTPInput.tsx
2406
+ var import_react14 = require("react");
2407
+ var import_tamagui54 = require("tamagui");
2408
+ var import_jsx_runtime46 = require("react/jsx-runtime");
2409
+ function OTPInput({ length = 6, value = "", onChange, onComplete, error, autoFocus, secureEntry }) {
2410
+ const inputRef = (0, import_react14.useRef)(null);
2411
+ const digits = value.padEnd(length, " ").slice(0, length);
2412
+ const handleChange = (0, import_react14.useCallback)((text) => {
2413
+ const cleaned = text.replace(/\D/g, "").slice(0, length);
2414
+ onChange?.(cleaned);
2415
+ if (cleaned.length === length) onComplete?.(cleaned);
2416
+ }, [length, onChange, onComplete]);
2417
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_tamagui54.YStack, { children: [
2418
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_tamagui54.XStack, { gap: "$2", justifyContent: "center", onPress: () => inputRef.current?.focus(), children: Array.from({ length }, (_, i) => {
2419
+ const char = digits[i]?.trim();
2420
+ const focused = value.length === i;
2421
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
2422
+ import_tamagui54.YStack,
2423
+ {
2424
+ width: 48,
2425
+ height: 56,
2426
+ borderRadius: "$3",
2427
+ borderWidth: 2,
2428
+ borderColor: error ? "$red9" : focused ? "$color9" : "$color6",
2429
+ backgroundColor: error ? "$red2" : "$color2",
2430
+ alignItems: "center",
2431
+ justifyContent: "center",
2432
+ animation: "quick",
2433
+ children: [
2434
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_tamagui54.SizableText, { size: "$7", fontWeight: "600", color: "$color12", children: char ? secureEntry ? "\u25CF" : char : "" }),
2435
+ focused && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_tamagui54.YStack, { position: "absolute", bottom: 10, width: 20, height: 2, backgroundColor: "$color9", animation: "quick" })
2436
+ ]
2437
+ },
2438
+ i
2439
+ );
2440
+ }) }),
2441
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
2442
+ import_tamagui54.Input,
2443
+ {
2444
+ ref: inputRef,
2445
+ value,
2446
+ onChangeText: handleChange,
2447
+ keyboardType: "number-pad",
2448
+ maxLength: length,
2449
+ autoFocus,
2450
+ position: "absolute",
2451
+ opacity: 0,
2452
+ width: 1,
2453
+ height: 1
2454
+ }
2455
+ )
2456
+ ] });
2457
+ }
2458
+
2459
+ // src/patterns/PasswordInput.tsx
2460
+ var import_react15 = require("react");
2461
+ var import_tamagui55 = require("tamagui");
2462
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2463
+ function getStrength(pw) {
2464
+ if (!pw) return { label: "", color: "$color6", width: "0%" };
2465
+ const score = [pw.length >= 8, /[A-Z]/.test(pw), /[0-9]/.test(pw), /[^A-Za-z0-9]/.test(pw)].filter(Boolean).length;
2466
+ if (score <= 1) return { label: "Weak", color: "$red9", width: "33%" };
2467
+ if (score <= 2) return { label: "Medium", color: "$yellow9", width: "66%" };
2468
+ return { label: "Strong", color: "$green9", width: "100%" };
2469
+ }
2470
+ function PasswordInput({ value = "", onChangeText, placeholder = "Password", label, error, size = "$4", strengthIndicator }) {
2471
+ const [visible, setVisible] = (0, import_react15.useState)(false);
2472
+ const toggle = (0, import_react15.useCallback)(() => setVisible((v) => !v), []);
2473
+ const strength = getStrength(value);
2474
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_tamagui55.YStack, { gap: "$1.5", children: [
2475
+ label && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_tamagui55.SizableText, { size: "$3", color: "$color11", fontWeight: "500", children: label }),
2476
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
2477
+ import_tamagui55.XStack,
2478
+ {
2479
+ borderWidth: 1,
2480
+ borderColor: error ? "$red9" : "$color6",
2481
+ borderRadius: "$3",
2482
+ backgroundColor: "$color2",
2483
+ alignItems: "center",
2484
+ paddingRight: "$2",
2485
+ focusStyle: { borderColor: "$color9" },
2486
+ children: [
2487
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2488
+ import_tamagui55.Input,
2489
+ {
2490
+ flex: 1,
2491
+ size,
2492
+ value,
2493
+ onChangeText,
2494
+ placeholder,
2495
+ placeholderTextColor: "$color8",
2496
+ secureTextEntry: !visible,
2497
+ backgroundColor: "transparent",
2498
+ borderWidth: 0
2499
+ }
2500
+ ),
2501
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2502
+ import_tamagui55.SizableText,
2503
+ {
2504
+ size: "$4",
2505
+ color: "$color8",
2506
+ paddingHorizontal: "$2",
2507
+ pressStyle: { opacity: 0.6 },
2508
+ onPress: toggle,
2509
+ cursor: "pointer",
2510
+ children: visible ? "\u25C9" : "\u25CE"
2511
+ }
2512
+ )
2513
+ ]
2514
+ }
2515
+ ),
2516
+ strengthIndicator && value.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_tamagui55.YStack, { gap: "$1", children: [
2517
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_tamagui55.YStack, { height: 3, backgroundColor: "$color4", borderRadius: 2, overflow: "hidden", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_tamagui55.YStack, { height: 3, width: strength.width, backgroundColor: strength.color, borderRadius: 2, animation: "quick" }) }),
2518
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_tamagui55.SizableText, { size: "$1", color: strength.color, children: strength.label })
2519
+ ] }),
2520
+ error && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_tamagui55.SizableText, { size: "$2", color: "$red9", children: error })
2521
+ ] });
2522
+ }
2523
+
2524
+ // src/patterns/AvatarGroup.tsx
2525
+ var import_tamagui56 = require("tamagui");
2526
+ var import_jsx_runtime48 = require("react/jsx-runtime");
2527
+ function getInitials(name) {
2528
+ if (!name) return "?";
2529
+ return name.split(" ").map((p) => p[0]).join("").toUpperCase().slice(0, 2);
2530
+ }
2531
+ function AvatarItem({ uri, name, color, size }) {
2532
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
2533
+ import_tamagui56.Circle,
2534
+ {
2535
+ size,
2536
+ backgroundColor: color ?? "$color4",
2537
+ borderWidth: 2,
2538
+ borderColor: "$background",
2539
+ overflow: "hidden",
2540
+ alignItems: "center",
2541
+ justifyContent: "center",
2542
+ children: uri ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_tamagui56.Image, { source: { uri }, width: size, height: size, objectFit: "cover" }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_tamagui56.SizableText, { size: "$2", fontWeight: "600", color: color ? "$color1" : "$color11", children: getInitials(name) })
2543
+ }
2544
+ );
2545
+ }
2546
+ function AvatarGroup({ avatars, max = 4, size = 36, overlap = 10 }) {
2547
+ const visible = avatars.slice(0, max);
2548
+ const remaining = avatars.length - max;
2549
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_tamagui56.XStack, { alignItems: "center", children: [
2550
+ visible.map((avatar, i) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_tamagui56.XStack, { marginLeft: i === 0 ? 0 : -overlap, zIndex: visible.length - i, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(AvatarItem, { ...avatar, size }) }, i)),
2551
+ remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_tamagui56.XStack, { marginLeft: -overlap, zIndex: 0, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
2552
+ import_tamagui56.Circle,
2553
+ {
2554
+ size,
2555
+ backgroundColor: "$color6",
2556
+ borderWidth: 2,
2557
+ borderColor: "$background",
2558
+ alignItems: "center",
2559
+ justifyContent: "center",
2560
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_tamagui56.SizableText, { size: "$2", fontWeight: "600", color: "$color11", children: [
2561
+ "+",
2562
+ remaining
2563
+ ] })
2564
+ }
2565
+ ) })
2566
+ ] });
2567
+ }
2568
+
2569
+ // src/patterns/SwipeCards.tsx
2570
+ var import_react16 = require("react");
2571
+ var import_tamagui57 = require("tamagui");
2572
+ var import_jsx_runtime49 = require("react/jsx-runtime");
2573
+ var STACK_SIZE = 3;
2574
+ var CARD_OFFSETS = [
2575
+ { scale: 1, y: 0, opacity: 1 },
2576
+ { scale: 0.95, y: 8, opacity: 0.9 },
2577
+ { scale: 0.9, y: 16, opacity: 0.8 }
2578
+ ];
2579
+ function SwipeCards({
2580
+ items,
2581
+ renderCard,
2582
+ onSwipeLeft,
2583
+ onSwipeRight,
2584
+ onEmpty,
2585
+ leftLabel = "Nope",
2586
+ rightLabel = "Like",
2587
+ emptyMessage = "No more cards"
2588
+ }) {
2589
+ const [index, setIndex] = (0, import_react16.useState)(0);
2590
+ const [exitDir, setExitDir] = (0, import_react16.useState)(null);
2591
+ const remaining = items.slice(index);
2592
+ const isEmpty = remaining.length === 0;
2593
+ const handleSwipe = (0, import_react16.useCallback)((dir) => {
2594
+ if (isEmpty) return;
2595
+ const current = items[index];
2596
+ setExitDir(dir);
2597
+ const timer = setTimeout(() => {
2598
+ setExitDir(null);
2599
+ setIndex((i) => {
2600
+ const next = i + 1;
2601
+ if (next >= items.length) onEmpty?.();
2602
+ return next;
2603
+ });
2604
+ dir === "left" ? onSwipeLeft?.(current) : onSwipeRight?.(current);
2605
+ }, 250);
2606
+ return () => clearTimeout(timer);
2607
+ }, [isEmpty, index, items, onEmpty, onSwipeLeft, onSwipeRight]);
2608
+ if (isEmpty) {
2609
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.YStack, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$3", padding: "$4", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.SizableText, { size: "$5", color: "$color8", children: emptyMessage }) });
2610
+ }
2611
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_tamagui57.YStack, { flex: 1, gap: "$4", children: [
2612
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.YStack, { flex: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.YStack, { width: "100%", maxWidth: 340, aspectRatio: 3 / 4, position: "relative", children: remaining.slice(0, STACK_SIZE).reverse().map((item, reverseIdx) => {
2613
+ const stackIdx = Math.min(remaining.length, STACK_SIZE) - 1 - reverseIdx;
2614
+ const isTop = stackIdx === 0;
2615
+ const offset = CARD_OFFSETS[stackIdx] ?? CARD_OFFSETS[2];
2616
+ const exitX = exitDir === "left" ? -400 : exitDir === "right" ? 400 : 0;
2617
+ const exitRotate = exitDir === "left" ? "-15deg" : exitDir === "right" ? "15deg" : "0deg";
2618
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
2619
+ import_tamagui57.YStack,
2620
+ {
2621
+ position: "absolute",
2622
+ top: 0,
2623
+ left: 0,
2624
+ right: 0,
2625
+ bottom: 0,
2626
+ animation: "quick",
2627
+ borderRadius: "$5",
2628
+ overflow: "hidden",
2629
+ backgroundColor: "$background",
2630
+ elevate: isTop,
2631
+ shadowColor: "$shadowColor",
2632
+ shadowRadius: isTop ? 16 : 4,
2633
+ scale: isTop && exitDir ? 1 : offset.scale,
2634
+ opacity: isTop && exitDir ? 0 : offset.opacity,
2635
+ y: isTop && exitDir ? 0 : offset.y,
2636
+ x: isTop ? exitX : 0,
2637
+ rotate: isTop ? exitRotate : "0deg",
2638
+ children: [
2639
+ renderCard(item),
2640
+ isTop && exitDir === "left" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2641
+ import_tamagui57.YStack,
2642
+ {
2643
+ position: "absolute",
2644
+ top: "$4",
2645
+ right: "$4",
2646
+ borderWidth: 3,
2647
+ borderColor: "$red10",
2648
+ borderRadius: "$3",
2649
+ padding: "$2",
2650
+ rotate: "15deg",
2651
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.SizableText, { size: "$7", fontWeight: "800", color: "$red10", children: leftLabel.toUpperCase() })
2652
+ }
2653
+ ),
2654
+ isTop && exitDir === "right" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2655
+ import_tamagui57.YStack,
2656
+ {
2657
+ position: "absolute",
2658
+ top: "$4",
2659
+ left: "$4",
2660
+ borderWidth: 3,
2661
+ borderColor: "$green10",
2662
+ borderRadius: "$3",
2663
+ padding: "$2",
2664
+ rotate: "-15deg",
2665
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.SizableText, { size: "$7", fontWeight: "800", color: "$green10", children: rightLabel.toUpperCase() })
2666
+ }
2667
+ )
2668
+ ]
2669
+ },
2670
+ item.id
2671
+ );
2672
+ }) }) }),
2673
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_tamagui57.XStack, { justifyContent: "center", gap: "$6", paddingBottom: "$4", children: [
2674
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2675
+ import_tamagui57.Circle,
2676
+ {
2677
+ size: 60,
2678
+ backgroundColor: "$red3",
2679
+ borderWidth: 2,
2680
+ borderColor: "$red7",
2681
+ pressStyle: { scale: 0.9, backgroundColor: "$red5" },
2682
+ animation: "quick",
2683
+ onPress: () => handleSwipe("left"),
2684
+ alignItems: "center",
2685
+ justifyContent: "center",
2686
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.SizableText, { size: "$6", color: "$red10", fontWeight: "700", children: "\u2715" })
2687
+ }
2688
+ ),
2689
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2690
+ import_tamagui57.Circle,
2691
+ {
2692
+ size: 60,
2693
+ backgroundColor: "$green3",
2694
+ borderWidth: 2,
2695
+ borderColor: "$green7",
2696
+ pressStyle: { scale: 0.9, backgroundColor: "$green5" },
2697
+ animation: "quick",
2698
+ onPress: () => handleSwipe("right"),
2699
+ alignItems: "center",
2700
+ justifyContent: "center",
2701
+ children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_tamagui57.SizableText, { size: "$6", color: "$green10", fontWeight: "700", children: "\u2665" })
2702
+ }
2703
+ )
2704
+ ] })
2705
+ ] });
2706
+ }
2707
+
2708
+ // src/patterns/GlassCard.tsx
2709
+ var import_tamagui58 = require("tamagui");
2710
+ var import_jsx_runtime50 = require("react/jsx-runtime");
2711
+ var BLUR = { light: 8, medium: 16, heavy: 24 };
2712
+ var TINT_BG = {
2713
+ light: "rgba(255,255,255,0.15)",
2714
+ dark: "rgba(0,0,0,0.25)"
2715
+ };
2716
+ var GlassFrame = (0, import_tamagui58.styled)(import_tamagui58.YStack, {
2717
+ borderWidth: 1,
2718
+ borderColor: "rgba(255,255,255,0.2)",
2719
+ overflow: "hidden"
2720
+ });
2721
+ function GlassCard({
2722
+ children,
2723
+ intensity = "medium",
2724
+ tint = "light",
2725
+ borderRadius = "$4",
2726
+ padding = "$4",
2727
+ elevated = false
2728
+ }) {
2729
+ const blur = BLUR[intensity];
2730
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
2731
+ GlassFrame,
2732
+ {
2733
+ borderRadius,
2734
+ padding,
2735
+ backgroundColor: TINT_BG[tint],
2736
+ elevate: elevated,
2737
+ shadowColor: elevated ? "$shadowColor" : void 0,
2738
+ shadowRadius: elevated ? 20 : void 0,
2739
+ shadowOpacity: elevated ? 0.3 : void 0,
2740
+ style: { backdropFilter: `blur(${blur}px)`, WebkitBackdropFilter: `blur(${blur}px)` },
2741
+ children
2742
+ }
2743
+ );
2744
+ }
1817
2745
  // Annotate the CommonJS export names for ESM import in node:
1818
2746
  0 && (module.exports = {
1819
2747
  Accordion,
@@ -1826,6 +2754,7 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1826
2754
  Article,
1827
2755
  Aside,
1828
2756
  Avatar,
2757
+ AvatarGroup,
1829
2758
  Badge,
1830
2759
  BlinkAccordion,
1831
2760
  BlinkAvatar,
@@ -1844,8 +2773,12 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1844
2773
  Carousel,
1845
2774
  ChatBubble,
1846
2775
  Checkbox,
2776
+ Chip,
2777
+ ChipGroup,
1847
2778
  Circle,
2779
+ ConfirmDialog,
1848
2780
  Container,
2781
+ CountdownBanner,
1849
2782
  Dialog,
1850
2783
  DialogProvider,
1851
2784
  Divider,
@@ -1857,6 +2790,7 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1857
2790
  Form,
1858
2791
  FormField,
1859
2792
  Frame,
2793
+ GlassCard,
1860
2794
  Grid,
1861
2795
  Group,
1862
2796
  H1,
@@ -1879,10 +2813,12 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1879
2813
  MediaCard,
1880
2814
  Nav,
1881
2815
  NotificationBanner,
2816
+ OTPInput,
1882
2817
  OnboardingCarousel,
1883
2818
  PageContainer,
1884
2819
  PageMainContainer,
1885
2820
  Paragraph,
2821
+ PasswordInput,
1886
2822
  PaywallScreen,
1887
2823
  Popover,
1888
2824
  Portal,
@@ -1890,6 +2826,8 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1890
2826
  PortalItem,
1891
2827
  PortalProvider,
1892
2828
  Pressable,
2829
+ PricingTable,
2830
+ ProductCard,
1893
2831
  ProfileHeader,
1894
2832
  Progress,
1895
2833
  ProgressSteps,
@@ -1915,6 +2853,7 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1915
2853
  Stack,
1916
2854
  StepPageLayout,
1917
2855
  SubHeading,
2856
+ SwipeCards,
1918
2857
  SwipeableRow,
1919
2858
  Switch,
1920
2859
  TabBar,
@@ -1922,6 +2861,7 @@ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1922
2861
  TamaguiImage,
1923
2862
  TamaguiListItem,
1924
2863
  TamaguiProvider,
2864
+ TestimonialCard,
1925
2865
  Text,
1926
2866
  TextArea,
1927
2867
  Theme,