@blinkdotnew/mobile-ui 2.0.0-alpha.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -5,73 +5,286 @@ var blinkConfig = createTamagui({
5
5
  ...defaultConfig
6
6
  });
7
7
 
8
+ // src/index.ts
9
+ import { defaultConfig as defaultConfig2 } from "@tamagui/config/v5";
10
+
11
+ // src/config/design-themes.ts
12
+ var BLINK_DESIGN_THEMES = {
13
+ "mono": {
14
+ id: "mono",
15
+ name: "Mono",
16
+ description: "Black/white neutral",
17
+ palette: { primary: "#18181B", primary_foreground: "#FAFAFA", secondary: "#F4F4F5", secondary_foreground: "#27272A", accent: "#3F3F46", background: "#FFFFFF", dark_mode: "#09090B" }
18
+ },
19
+ "ocean-teal": {
20
+ id: "ocean-teal",
21
+ name: "Ocean Teal",
22
+ description: "SaaS, fintech, healthcare",
23
+ palette: { primary: "#0D9488", primary_foreground: "#FFFFFF", secondary: "#F0FDFA", secondary_foreground: "#134E4A", accent: "#2DD4BF", background: "#FFFFFF", dark_mode: "#042F2E" }
24
+ },
25
+ "warm-amber": {
26
+ id: "warm-amber",
27
+ name: "Warm Amber",
28
+ description: "E-commerce, food, hospitality",
29
+ palette: { primary: "#D97706", primary_foreground: "#FFFFFF", secondary: "#FFFBEB", secondary_foreground: "#78350F", accent: "#FBBF24", background: "#FFFEF7", dark_mode: "#451A03" }
30
+ },
31
+ "rose-coral": {
32
+ id: "rose-coral",
33
+ name: "Rose Coral",
34
+ description: "Lifestyle, beauty, fashion",
35
+ palette: { primary: "#E11D48", primary_foreground: "#FFFFFF", secondary: "#FFF1F2", secondary_foreground: "#881337", accent: "#FB7185", background: "#FFFAFA", dark_mode: "#4C0519" }
36
+ },
37
+ "lavender": {
38
+ id: "lavender",
39
+ name: "Lavender",
40
+ description: "Creative, wellness, meditation",
41
+ palette: { primary: "#7C3AED", primary_foreground: "#FFFFFF", secondary: "#F5F3FF", secondary_foreground: "#4C1D95", accent: "#A78BFA", background: "#FEFEFF", dark_mode: "#2E1065" }
42
+ },
43
+ "glacier": {
44
+ id: "glacier",
45
+ name: "Glacier",
46
+ description: "Professional, corporate, analytics",
47
+ palette: { primary: "#0EA5E9", primary_foreground: "#FFFFFF", secondary: "#F0F9FF", secondary_foreground: "#0C4A6E", accent: "#38BDF8", background: "#FFFFFF", dark_mode: "#082F49" }
48
+ },
49
+ "forest": {
50
+ id: "forest",
51
+ name: "Forest",
52
+ description: "Sustainability, nature, outdoor",
53
+ palette: { primary: "#16A34A", primary_foreground: "#FFFFFF", secondary: "#F0FDF4", secondary_foreground: "#14532D", accent: "#4ADE80", background: "#FEFFFE", dark_mode: "#052E16" }
54
+ },
55
+ "obsidian": {
56
+ id: "obsidian",
57
+ name: "Obsidian",
58
+ description: "Developer tools, gaming, tech",
59
+ palette: { primary: "#475569", primary_foreground: "#FFFFFF", secondary: "#F1F5F9", secondary_foreground: "#1E293B", accent: "#64748B", background: "#FFFFFF", dark_mode: "#0F172A" }
60
+ },
61
+ "solar": {
62
+ id: "solar",
63
+ name: "Solar",
64
+ description: "Energy, optimistic, kid-friendly",
65
+ palette: { primary: "#CA8A04", primary_foreground: "#FFFFFF", secondary: "#FEFCE8", secondary_foreground: "#713F12", accent: "#FACC15", background: "#FFFEF5", dark_mode: "#422006" }
66
+ },
67
+ "orchid": {
68
+ id: "orchid",
69
+ name: "Orchid",
70
+ description: "Beauty, fashion, luxury",
71
+ palette: { primary: "#C026D3", primary_foreground: "#FFFFFF", secondary: "#FDF4FF", secondary_foreground: "#701A75", accent: "#E879F9", background: "#FFFEFF", dark_mode: "#4A044E" }
72
+ },
73
+ "indigo": {
74
+ id: "indigo",
75
+ name: "Indigo",
76
+ description: "Enterprise, fintech, trust",
77
+ palette: { primary: "#4F46E5", primary_foreground: "#FFFFFF", secondary: "#EEF2FF", secondary_foreground: "#312E81", accent: "#818CF8", background: "#FEFEFF", dark_mode: "#1E1B4B" }
78
+ },
79
+ "cosmic-night": {
80
+ id: "cosmic-night",
81
+ name: "Cosmic Night",
82
+ description: "Dark mode, futuristic, gaming",
83
+ palette: { primary: "#6366F1", primary_foreground: "#FFFFFF", secondary: "#1E1B4B", secondary_foreground: "#E0E7FF", accent: "#A855F7", background: "#0F0D1A", dark_mode: "#030014" }
84
+ },
85
+ "soft-pop": {
86
+ id: "soft-pop",
87
+ name: "Soft Pop",
88
+ description: "Playful, modern, creative",
89
+ palette: { primary: "#14B8A6", primary_foreground: "#FFFFFF", secondary: "#FDF2F8", secondary_foreground: "#134E4A", accent: "#F472B6", background: "#FFFBFE", dark_mode: "#0D1117" }
90
+ },
91
+ "neo-brutalism": {
92
+ id: "neo-brutalism",
93
+ name: "Neo Brutalism",
94
+ description: "Bold, striking, artistic",
95
+ palette: { primary: "#FF6B35", primary_foreground: "#000000", secondary: "#FFE66D", secondary_foreground: "#1A1A1A", accent: "#FF3366", background: "#FFFEF0", dark_mode: "#1A1A1A" }
96
+ },
97
+ "vintage-paper": {
98
+ id: "vintage-paper",
99
+ name: "Vintage Paper",
100
+ description: "Classic, warm, nostalgic",
101
+ palette: { primary: "#B45309", primary_foreground: "#FFFFFF", secondary: "#FEF3C7", secondary_foreground: "#78350F", accent: "#92400E", background: "#FFFDF7", dark_mode: "#292524" }
102
+ },
103
+ "modern-minimal": {
104
+ id: "modern-minimal",
105
+ name: "Modern Minimal",
106
+ description: "Clean, professional, corporate",
107
+ palette: { primary: "#2563EB", primary_foreground: "#FFFFFF", secondary: "#F8FAFC", secondary_foreground: "#1E40AF", accent: "#3B82F6", background: "#FFFFFF", dark_mode: "#0F172A" }
108
+ },
109
+ "bubblegum": {
110
+ id: "bubblegum",
111
+ name: "Bubblegum",
112
+ description: "Fun, feminine, youthful",
113
+ palette: { primary: "#EC4899", primary_foreground: "#FFFFFF", secondary: "#FDF4FF", secondary_foreground: "#9D174D", accent: "#F472B6", background: "#FFFBFF", dark_mode: "#500724" }
114
+ }
115
+ };
116
+ function hexToRgb(hex) {
117
+ const h = hex.replace("#", "");
118
+ return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
119
+ }
120
+ function rgbToHex(r, g, b) {
121
+ return "#" + [r, g, b].map((v) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, "0")).join("");
122
+ }
123
+ function mixColors(c1, c2, t) {
124
+ const [r1, g1, b1] = hexToRgb(c1);
125
+ const [r2, g2, b2] = hexToRgb(c2);
126
+ return rgbToHex(r1 + (r2 - r1) * t, g1 + (g2 - g1) * t, b1 + (b2 - b1) * t);
127
+ }
128
+ function generateLightPalette(p) {
129
+ return [
130
+ p.background,
131
+ p.secondary,
132
+ mixColors(p.secondary, p.accent, 0.15),
133
+ mixColors(p.secondary, p.accent, 0.3),
134
+ mixColors(p.accent, p.primary, 0.1),
135
+ mixColors(p.accent, p.primary, 0.3),
136
+ mixColors(p.accent, p.primary, 0.5),
137
+ mixColors(p.accent, p.primary, 0.7),
138
+ p.primary,
139
+ mixColors(p.primary, p.secondary_foreground, 0.3),
140
+ p.secondary_foreground,
141
+ p.dark_mode
142
+ ];
143
+ }
144
+ function generateDarkPalette(p) {
145
+ return [
146
+ p.dark_mode,
147
+ mixColors(p.dark_mode, p.secondary_foreground, 0.15),
148
+ mixColors(p.dark_mode, p.secondary_foreground, 0.25),
149
+ mixColors(p.dark_mode, p.secondary_foreground, 0.35),
150
+ mixColors(p.secondary_foreground, p.accent, 0.2),
151
+ mixColors(p.secondary_foreground, p.accent, 0.4),
152
+ mixColors(p.secondary_foreground, p.accent, 0.6),
153
+ mixColors(p.accent, p.primary, 0.5),
154
+ p.primary,
155
+ p.accent,
156
+ mixColors(p.accent, p.primary_foreground, 0.5),
157
+ p.primary_foreground
158
+ ];
159
+ }
160
+ function getBlinkThemePalettes(themeId) {
161
+ const theme = BLINK_DESIGN_THEMES[themeId];
162
+ if (!theme) throw new Error(`Unknown theme: ${themeId}`);
163
+ const p = theme.palette;
164
+ return {
165
+ base: {
166
+ light: generateLightPalette(p),
167
+ dark: generateDarkPalette(p)
168
+ },
169
+ accent: {
170
+ light: generateDarkPalette(p),
171
+ dark: generateLightPalette(p)
172
+ }
173
+ };
174
+ }
175
+ var BLINK_DESIGN_THEME_IDS = Object.keys(BLINK_DESIGN_THEMES);
176
+ function getBlinkDesignTheme(themeId) {
177
+ return BLINK_DESIGN_THEMES[themeId];
178
+ }
179
+
8
180
  // src/index.ts
9
181
  import {
10
- View as View6,
11
- XStack as XStack26,
12
- YStack as YStack32,
182
+ View as View7,
183
+ Stack,
184
+ SizableStack,
185
+ ThemeableStack,
186
+ Frame,
187
+ XStack as XStack44,
188
+ YStack as YStack49,
13
189
  ZStack,
14
- ScrollView as ScrollView5,
15
- Circle as Circle8,
190
+ ScrollView as ScrollView6,
191
+ Circle as Circle12,
16
192
  Square,
193
+ Spacer,
194
+ EnsureFlexed,
195
+ Group,
17
196
  XGroup,
18
197
  YGroup,
198
+ Header,
199
+ Footer,
200
+ Main,
201
+ Nav,
202
+ Article,
203
+ Aside,
19
204
  H1 as H12,
20
205
  H2 as H22,
21
206
  H3 as H32,
22
207
  H4 as H42,
23
208
  H5 as H52,
24
209
  H6 as H62,
210
+ Heading,
25
211
  Paragraph,
26
- SizableText as SizableText34,
212
+ SizableText as SizableText51,
27
213
  Text,
28
214
  Label,
29
- Button as Button8,
30
- Input as Input3,
215
+ Button as Button13,
216
+ Input as Input5,
31
217
  TextArea,
32
- Switch as Switch2,
218
+ Switch as Switch3,
33
219
  Checkbox,
34
- Slider,
220
+ Slider as Slider2,
35
221
  RadioGroup,
36
- Select,
222
+ Select as Select2,
37
223
  Fieldset,
224
+ Form,
38
225
  Card as Card2,
39
226
  Avatar as Avatar2,
40
- Separator as Separator5,
41
- Image as Image6,
227
+ Separator as Separator7,
228
+ Image as Image9,
42
229
  Progress,
43
230
  Spinner as Spinner2,
44
231
  ListItem as ListItem2,
45
- Sheet as Sheet3,
46
- Dialog,
47
- AlertDialog as AlertDialog2,
48
- Popover as Popover2,
232
+ Anchor,
233
+ Sheet as Sheet5,
234
+ Dialog as Dialog2,
235
+ AlertDialog as AlertDialog3,
236
+ Popover as Popover3,
49
237
  Tooltip,
50
238
  TooltipSimple,
239
+ Portal,
240
+ PortalHost,
241
+ PortalItem,
242
+ PortalProvider,
51
243
  Tabs,
52
244
  Accordion,
53
245
  ToggleGroup,
54
- Adapt,
55
- PortalProvider,
246
+ AnimatePresence,
247
+ Adapt as Adapt4,
56
248
  VisuallyHidden,
57
249
  Unspaced,
58
- Anchor,
59
- Form,
60
- Theme,
250
+ Theme as Theme2,
61
251
  TamaguiProvider,
62
- styled as styled12,
252
+ TamaguiProvider as TamaguiProvider2,
253
+ createTamagui as createTamagui2,
254
+ createFont,
255
+ createMedia,
256
+ createTheme,
257
+ createTokens,
258
+ createVariable,
259
+ createStyledContext,
260
+ addTheme,
261
+ updateTheme,
262
+ replaceTheme,
263
+ styled as styled14,
63
264
  withStaticProperties as withStaticProperties2,
265
+ isWeb,
266
+ isClient,
267
+ getConfig,
268
+ getToken,
269
+ getTokens,
270
+ getTokenValue,
271
+ composeRefs,
272
+ composeEventHandlers,
64
273
  useTheme,
65
- useMedia,
66
- useThemeName
274
+ useMedia as useMedia2,
275
+ useThemeName,
276
+ useControllableState,
277
+ useEvent,
278
+ useForceUpdate,
279
+ useIsomorphicLayoutEffect,
280
+ useComposedRefs,
281
+ useWindowDimensions,
282
+ useDidFinishSSR,
283
+ useDebounce,
284
+ useDebounceValue,
285
+ usePresence,
286
+ useIsPresent
67
287
  } from "tamagui";
68
- import {
69
- Toast,
70
- ToastProvider,
71
- ToastViewport,
72
- useToastController,
73
- useToastState
74
- } from "@tamagui/toast";
75
288
 
76
289
  // src/primitives/Button.tsx
77
290
  import { Button as TamaguiButton, styled } from "tamagui";
@@ -708,26 +921,34 @@ function BlinkToggleGroup({ options, value, onValueChange, size = "md" }) {
708
921
 
709
922
  // src/interface/BlinkToast.tsx
710
923
  import { useState as useState4, useCallback, useEffect as useEffect2, createContext, useContext } from "react";
711
- import { SizableText as SizableText10, YStack as YStack5 } from "tamagui";
924
+ import { SizableText as SizableText10, XStack as XStack6, YStack as YStack5 } from "tamagui";
712
925
  import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
713
926
  var ToastContext = createContext(null);
714
- var variantColors = {
715
- default: "$color9",
716
- success: "$green9",
717
- error: "$red9",
718
- warning: "$yellow9"
927
+ var variantStyles = {
928
+ default: { bg: "$color3", border: "$color6", icon: "\u2139" },
929
+ success: { bg: "$green2", border: "$green7", icon: "\u2713" },
930
+ error: { bg: "$red2", border: "$red7", icon: "\u2715" },
931
+ warning: { bg: "$yellow2", border: "$yellow7", icon: "!" }
719
932
  };
720
933
  var globalToastShow = null;
721
- var toast = (message, variant, duration) => {
722
- if (globalToastShow) globalToastShow(message, variant, duration);
934
+ var toast = (title, options) => {
935
+ const opts = typeof options === "string" ? { variant: options } : options;
936
+ if (globalToastShow) globalToastShow(title, opts);
723
937
  else console.warn("BlinkToastProvider not mounted");
724
938
  };
725
939
  function BlinkToastProvider({ children }) {
726
940
  const [toasts, setToasts] = useState4([]);
727
- const show = useCallback((message, variant = "default", duration = 3e3) => {
941
+ const show = useCallback((title, options) => {
728
942
  const id = Math.random().toString(36).slice(2, 9);
729
- setToasts((prev) => [...prev, { id, message, variant, duration }]);
730
- setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), duration);
943
+ const entry = {
944
+ id,
945
+ title,
946
+ message: options?.message,
947
+ variant: options?.variant ?? "default",
948
+ duration: options?.duration ?? 3e3
949
+ };
950
+ setToasts((prev) => [...prev, entry]);
951
+ setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), entry.duration);
731
952
  }, []);
732
953
  useEffect2(() => {
733
954
  globalToastShow = show;
@@ -735,24 +956,72 @@ function BlinkToastProvider({ children }) {
735
956
  globalToastShow = null;
736
957
  };
737
958
  }, [show]);
959
+ const dismiss = useCallback((id) => {
960
+ setToasts((prev) => prev.filter((t) => t.id !== id));
961
+ }, []);
738
962
  return /* @__PURE__ */ jsxs5(ToastContext.Provider, { value: { show }, children: [
739
963
  children,
740
- /* @__PURE__ */ jsx10(YStack5, { position: "absolute", top: 60, left: 0, right: 0, alignItems: "center", gap: "$2", pointerEvents: "none", zIndex: 1e5, children: toasts.map((t) => /* @__PURE__ */ jsx10(
964
+ /* @__PURE__ */ jsx10(
741
965
  YStack5,
742
966
  {
743
- backgroundColor: variantColors[t.variant ?? "default"],
967
+ position: "absolute",
968
+ top: 50,
969
+ left: 0,
970
+ right: 0,
971
+ alignItems: "center",
972
+ gap: "$2",
973
+ pointerEvents: "box-none",
974
+ zIndex: 1e5,
744
975
  paddingHorizontal: "$4",
745
- paddingVertical: "$2.5",
746
- borderRadius: "$4",
747
- enterStyle: { opacity: 0, y: -10 },
748
- exitStyle: { opacity: 0, y: -10 },
749
- opacity: 1,
750
- y: 0,
751
- animation: "quick",
752
- children: /* @__PURE__ */ jsx10(SizableText10, { size: "$3", color: "white", fontWeight: "600", children: t.message })
753
- },
754
- t.id
755
- )) })
976
+ children: toasts.map((t) => {
977
+ const style = variantStyles[t.variant ?? "default"];
978
+ return /* @__PURE__ */ jsxs5(
979
+ XStack6,
980
+ {
981
+ width: "100%",
982
+ maxWidth: 400,
983
+ backgroundColor: style.bg,
984
+ borderWidth: 1,
985
+ borderColor: style.border,
986
+ borderRadius: "$4",
987
+ paddingHorizontal: "$4",
988
+ paddingVertical: "$3",
989
+ gap: "$3",
990
+ alignItems: "flex-start",
991
+ enterStyle: { opacity: 0, y: -20, scale: 0.95 },
992
+ exitStyle: { opacity: 0, y: -20, scale: 0.95 },
993
+ opacity: 1,
994
+ y: 0,
995
+ scale: 1,
996
+ animation: "quick",
997
+ pointerEvents: "auto",
998
+ elevation: 4,
999
+ children: [
1000
+ /* @__PURE__ */ jsx10(SizableText10, { size: "$4", fontWeight: "700", marginTop: "$0.5", children: style.icon }),
1001
+ /* @__PURE__ */ jsxs5(YStack5, { flex: 1, gap: "$1", children: [
1002
+ /* @__PURE__ */ jsx10(SizableText10, { size: "$4", fontWeight: "600", color: "$color12", children: t.title }),
1003
+ t.message && /* @__PURE__ */ jsx10(SizableText10, { size: "$3", color: "$color10", children: t.message })
1004
+ ] }),
1005
+ /* @__PURE__ */ jsx10(
1006
+ SizableText10,
1007
+ {
1008
+ size: "$3",
1009
+ color: "$color8",
1010
+ fontWeight: "600",
1011
+ pressStyle: { opacity: 0.5 },
1012
+ onPress: () => dismiss(t.id),
1013
+ cursor: "pointer",
1014
+ marginTop: "$0.5",
1015
+ children: "\u2715"
1016
+ }
1017
+ )
1018
+ ]
1019
+ },
1020
+ t.id
1021
+ );
1022
+ })
1023
+ }
1024
+ )
756
1025
  ] });
757
1026
  }
758
1027
  function useBlinkToast() {
@@ -804,17 +1073,43 @@ function BlinkTooltip({ content, children, side = "top" }) {
804
1073
  ] });
805
1074
  }
806
1075
 
1076
+ // src/interface/BrandIcons.tsx
1077
+ import Svg, { Path, Rect } from "react-native-svg";
1078
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1079
+ function GoogleLogo({ size = 20 }) {
1080
+ return /* @__PURE__ */ jsxs8(Svg, { width: size, height: size, viewBox: "0 0 24 24", children: [
1081
+ /* @__PURE__ */ jsx13(Path, { fill: "#4285F4", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" }),
1082
+ /* @__PURE__ */ jsx13(Path, { fill: "#34A853", d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" }),
1083
+ /* @__PURE__ */ jsx13(Path, { fill: "#FBBC05", d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l3.66-2.84z" }),
1084
+ /* @__PURE__ */ jsx13(Path, { fill: "#EA4335", d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" })
1085
+ ] });
1086
+ }
1087
+ function AppleLogo({ size = 20, color = "#000" }) {
1088
+ return /* @__PURE__ */ jsx13(Svg, { width: size, height: size, viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx13(Path, { fill: color, d: "M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z" }) });
1089
+ }
1090
+ function GitHubLogo({ size = 20, color = "#fff" }) {
1091
+ return /* @__PURE__ */ jsx13(Svg, { width: size, height: size, viewBox: "0 0 98 96", children: /* @__PURE__ */ jsx13(Path, { fillRule: "evenodd", clipRule: "evenodd", fill: color, d: "M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" }) });
1092
+ }
1093
+ function MicrosoftLogo({ size = 20 }) {
1094
+ return /* @__PURE__ */ jsxs8(Svg, { width: size, height: size, viewBox: "0 0 21 21", children: [
1095
+ /* @__PURE__ */ jsx13(Rect, { width: "10", height: "10", fill: "#F25022" }),
1096
+ /* @__PURE__ */ jsx13(Rect, { x: "11", width: "10", height: "10", fill: "#7FBA00" }),
1097
+ /* @__PURE__ */ jsx13(Rect, { y: "11", width: "10", height: "10", fill: "#00A4EF" }),
1098
+ /* @__PURE__ */ jsx13(Rect, { x: "11", y: "11", width: "10", height: "10", fill: "#FFB900" })
1099
+ ] });
1100
+ }
1101
+
807
1102
  // src/layouts/StepPageLayout.tsx
808
1103
  import { SizableText as SizableText13, YStack as YStack7 } from "tamagui";
809
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1104
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
810
1105
  function StepPageLayout({ title, description, children, bottom }) {
811
- return /* @__PURE__ */ jsxs8(YStack7, { flex: 1, padding: "$4", maxWidth: 500, marginHorizontal: "auto", width: "100%", children: [
812
- /* @__PURE__ */ jsx13(YStack7, { gap: "$5", children: /* @__PURE__ */ jsxs8(YStack7, { gap: "$2", children: [
813
- /* @__PURE__ */ jsx13(SizableText13, { size: "$8", fontWeight: "700", children: title }),
814
- description && /* @__PURE__ */ jsx13(SizableText13, { size: "$5", fontWeight: "400", color: "$color10", children: description })
1106
+ return /* @__PURE__ */ jsxs9(YStack7, { flex: 1, padding: "$4", maxWidth: 500, marginHorizontal: "auto", width: "100%", children: [
1107
+ /* @__PURE__ */ jsx14(YStack7, { gap: "$5", children: /* @__PURE__ */ jsxs9(YStack7, { gap: "$2", children: [
1108
+ /* @__PURE__ */ jsx14(SizableText13, { size: "$8", fontWeight: "700", children: title }),
1109
+ description && /* @__PURE__ */ jsx14(SizableText13, { size: "$5", fontWeight: "400", color: "$color10", children: description })
815
1110
  ] }) }),
816
- /* @__PURE__ */ jsx13(YStack7, { paddingTop: "$5", gap: "$4", children }),
817
- bottom && /* @__PURE__ */ jsx13(YStack7, { paddingTop: "$4", children: bottom })
1111
+ /* @__PURE__ */ jsx14(YStack7, { paddingTop: "$5", gap: "$4", children }),
1112
+ bottom && /* @__PURE__ */ jsx14(YStack7, { paddingTop: "$4", children: bottom })
818
1113
  ] });
819
1114
  }
820
1115
 
@@ -839,21 +1134,21 @@ var ScreenLayout = styled10(YStack8, {
839
1134
 
840
1135
  // src/layouts/Section.tsx
841
1136
  import { SizableText as SizableText14, YStack as YStack9 } from "tamagui";
842
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
1137
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
843
1138
  function Section({ title, description, children, gap = "$3" }) {
844
- return /* @__PURE__ */ jsxs9(YStack9, { gap, children: [
845
- title && /* @__PURE__ */ jsxs9(YStack9, { gap: "$1", children: [
846
- /* @__PURE__ */ jsx14(SizableText14, { size: "$5", fontWeight: "600", color: "$color12", children: title }),
847
- description && /* @__PURE__ */ jsx14(SizableText14, { size: "$3", color: "$color9", children: description })
1139
+ return /* @__PURE__ */ jsxs10(YStack9, { gap, children: [
1140
+ title && /* @__PURE__ */ jsxs10(YStack9, { gap: "$1", children: [
1141
+ /* @__PURE__ */ jsx15(SizableText14, { size: "$5", fontWeight: "600", color: "$color12", children: title }),
1142
+ description && /* @__PURE__ */ jsx15(SizableText14, { size: "$3", color: "$color9", children: description })
848
1143
  ] }),
849
1144
  children
850
1145
  ] });
851
1146
  }
852
1147
 
853
1148
  // src/layouts/ListItem.tsx
854
- import { styled as styled11, SizableText as SizableText15, XStack as XStack6, YStack as YStack10, View as View5 } from "tamagui";
855
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
856
- var ListItemFrame = styled11(XStack6, {
1149
+ import { styled as styled11, SizableText as SizableText15, XStack as XStack7, YStack as YStack10, View as View5 } from "tamagui";
1150
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1151
+ var ListItemFrame = styled11(XStack7, {
857
1152
  name: "BlinkListItem",
858
1153
  alignItems: "center",
859
1154
  gap: "$3",
@@ -870,40 +1165,40 @@ var ListItemFrame = styled11(XStack6, {
870
1165
  }
871
1166
  });
872
1167
  function ListItem({ icon, title, subtitle, right, onPress }) {
873
- return /* @__PURE__ */ jsxs10(ListItemFrame, { pressable: !!onPress, onPress, children: [
874
- icon && /* @__PURE__ */ jsx15(View5, { children: icon }),
875
- /* @__PURE__ */ jsxs10(YStack10, { flex: 1, gap: "$1", children: [
876
- /* @__PURE__ */ jsx15(SizableText15, { size: "$4", fontWeight: "500", color: "$color12", children: title }),
877
- subtitle && /* @__PURE__ */ jsx15(SizableText15, { size: "$2", color: "$color9", children: subtitle })
1168
+ return /* @__PURE__ */ jsxs11(ListItemFrame, { pressable: !!onPress, onPress, children: [
1169
+ icon && /* @__PURE__ */ jsx16(View5, { children: icon }),
1170
+ /* @__PURE__ */ jsxs11(YStack10, { flex: 1, gap: "$1", children: [
1171
+ /* @__PURE__ */ jsx16(SizableText15, { size: "$4", fontWeight: "500", color: "$color12", children: title }),
1172
+ subtitle && /* @__PURE__ */ jsx16(SizableText15, { size: "$2", color: "$color9", children: subtitle })
878
1173
  ] }),
879
1174
  right
880
1175
  ] });
881
1176
  }
882
1177
 
883
1178
  // src/layouts/Divider.tsx
884
- import { Separator as Separator3, SizableText as SizableText16, XStack as XStack7 } from "tamagui";
885
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1179
+ import { Separator as Separator3, SizableText as SizableText16, XStack as XStack8 } from "tamagui";
1180
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
886
1181
  function Divider({ label }) {
887
- if (!label) return /* @__PURE__ */ jsx16(Separator3, { borderColor: "$color4" });
888
- return /* @__PURE__ */ jsxs11(XStack7, { alignItems: "center", gap: "$3", children: [
889
- /* @__PURE__ */ jsx16(Separator3, { flex: 1, borderColor: "$color4" }),
890
- /* @__PURE__ */ jsx16(SizableText16, { size: "$2", color: "$color9", children: label }),
891
- /* @__PURE__ */ jsx16(Separator3, { flex: 1, borderColor: "$color4" })
1182
+ if (!label) return /* @__PURE__ */ jsx17(Separator3, { borderColor: "$color4" });
1183
+ return /* @__PURE__ */ jsxs12(XStack8, { alignItems: "center", gap: "$3", children: [
1184
+ /* @__PURE__ */ jsx17(Separator3, { flex: 1, borderColor: "$color4" }),
1185
+ /* @__PURE__ */ jsx17(SizableText16, { size: "$2", color: "$color9", children: label }),
1186
+ /* @__PURE__ */ jsx17(Separator3, { flex: 1, borderColor: "$color4" })
892
1187
  ] });
893
1188
  }
894
1189
 
895
1190
  // src/layouts/KeyboardStickyFooter.tsx
896
1191
  import { YStack as YStack11 } from "tamagui";
897
- import { jsx as jsx17 } from "react/jsx-runtime";
1192
+ import { jsx as jsx18 } from "react/jsx-runtime";
898
1193
  function KeyboardStickyFooter({ children, offset }) {
899
- return /* @__PURE__ */ jsx17(YStack11, { maxWidth: 500, alignSelf: "center", paddingTop: "$8", paddingBottom: "$4", style: { paddingBottom: offset }, children });
1194
+ return /* @__PURE__ */ jsx18(YStack11, { maxWidth: 500, alignSelf: "center", paddingTop: "$8", paddingBottom: "$4", style: { paddingBottom: offset }, children });
900
1195
  }
901
1196
 
902
1197
  // src/layouts/SafeArea.tsx
903
1198
  import { YStack as YStack12 } from "tamagui";
904
- import { jsx as jsx18 } from "react/jsx-runtime";
1199
+ import { jsx as jsx19 } from "react/jsx-runtime";
905
1200
  function SafeArea({ children, edges = ["top", "bottom"] }) {
906
- return /* @__PURE__ */ jsx18(
1201
+ return /* @__PURE__ */ jsx19(
907
1202
  YStack12,
908
1203
  {
909
1204
  flex: 1,
@@ -919,159 +1214,357 @@ function SafeArea({ children, edges = ["top", "bottom"] }) {
919
1214
 
920
1215
  // src/layouts/Grid.tsx
921
1216
  import { Children } from "react";
922
- import { XStack as XStack8, YStack as YStack13 } from "tamagui";
923
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
1217
+ import { XStack as XStack9, YStack as YStack13 } from "tamagui";
1218
+ import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
924
1219
  function Grid({ children, columns = 2, gap = "$3" }) {
925
1220
  const items = Children.toArray(children);
926
1221
  const rows = [];
927
1222
  for (let i = 0; i < items.length; i += columns) {
928
1223
  rows.push(items.slice(i, i + columns));
929
1224
  }
930
- return /* @__PURE__ */ jsx19(YStack13, { gap, children: rows.map((row, ri) => /* @__PURE__ */ jsxs12(XStack8, { gap, children: [
931
- row.map((item, ci) => /* @__PURE__ */ jsx19(YStack13, { flex: 1, children: item }, ci)),
932
- row.length < columns && Array.from({ length: columns - row.length }).map((_, i) => /* @__PURE__ */ jsx19(YStack13, { flex: 1 }, `pad-${i}`))
1225
+ return /* @__PURE__ */ jsx20(YStack13, { gap, children: rows.map((row, ri) => /* @__PURE__ */ jsxs13(XStack9, { gap, children: [
1226
+ row.map((item, ci) => /* @__PURE__ */ jsx20(YStack13, { flex: 1, children: item }, ci)),
1227
+ row.length < columns && Array.from({ length: columns - row.length }).map((_, i) => /* @__PURE__ */ jsx20(YStack13, { flex: 1 }, `pad-${i}`))
933
1228
  ] }, ri)) });
934
1229
  }
935
1230
  function Container({ children, maxWidth = 500, centered = true, padding = "$4" }) {
936
- return /* @__PURE__ */ jsx19(YStack13, { width: "100%", maxWidth, alignSelf: centered ? "center" : void 0, padding, children });
1231
+ return /* @__PURE__ */ jsx20(YStack13, { width: "100%", maxWidth, alignSelf: centered ? "center" : void 0, padding, children });
937
1232
  }
938
1233
 
939
1234
  // src/patterns/PaywallScreen.tsx
940
- import { Button as Button3, SizableText as SizableText17, XStack as XStack9, YStack as YStack14, Circle as Circle2 } from "tamagui";
941
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
1235
+ import { useState as useState5, useEffect as useEffect3 } from "react";
1236
+ import { Button as Button3, Circle as Circle2, SizableText as SizableText17, XStack as XStack10, YStack as YStack14, ScrollView as ScrollView2 } from "tamagui";
1237
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
1238
+ function useCountdown(minutes) {
1239
+ const [seconds, setSeconds] = useState5((minutes ?? 0) * 60);
1240
+ useEffect3(() => {
1241
+ if (!minutes) return;
1242
+ setSeconds(minutes * 60);
1243
+ const id = setInterval(() => setSeconds((s) => s > 0 ? s - 1 : 0), 1e3);
1244
+ return () => clearInterval(id);
1245
+ }, [minutes]);
1246
+ const mm = String(Math.floor(seconds / 60)).padStart(2, "0");
1247
+ const ss = String(seconds % 60).padStart(2, "0");
1248
+ return { display: `${mm}:${ss}`, expired: seconds <= 0 };
1249
+ }
1250
+ function normalizeFeature(f) {
1251
+ return typeof f === "string" ? { title: f } : f;
1252
+ }
1253
+ function BenefitRow({ feature, tone, muted }) {
1254
+ const f = normalizeFeature(feature);
1255
+ return /* @__PURE__ */ jsxs14(XStack10, { gap: "$3", alignItems: "center", children: [
1256
+ /* @__PURE__ */ jsx21(Circle2, { size: 40, backgroundColor: "$color3", children: f.icon ?? /* @__PURE__ */ jsx21(SizableText17, { size: "$5", color: "$color9", children: "\u2726" }) }),
1257
+ /* @__PURE__ */ jsxs14(YStack14, { flex: 1, gap: "$0.5", children: [
1258
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$4", fontWeight: "700", color: tone, children: f.title }),
1259
+ f.description ? /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: muted, children: f.description }) : null
1260
+ ] })
1261
+ ] });
1262
+ }
1263
+ function PlanRow({ plan, selected, onPress }) {
1264
+ return /* @__PURE__ */ jsxs14(
1265
+ XStack10,
1266
+ {
1267
+ width: "100%",
1268
+ padding: "$3",
1269
+ paddingHorizontal: "$3.5",
1270
+ borderRadius: "$5",
1271
+ borderWidth: 2,
1272
+ borderColor: selected ? "$color9" : "$color5",
1273
+ backgroundColor: selected ? "$color3" : "$color1",
1274
+ pressStyle: { scale: 0.98, opacity: 0.9 },
1275
+ animation: "quick",
1276
+ onPress,
1277
+ cursor: "pointer",
1278
+ alignItems: "center",
1279
+ gap: "$3",
1280
+ position: "relative",
1281
+ children: [
1282
+ plan.popular && /* @__PURE__ */ jsx21(YStack14, { position: "absolute", top: -10, right: 12, backgroundColor: "$color9", paddingHorizontal: "$2", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ jsx21(SizableText17, { size: "$1", color: "white", fontWeight: "700", children: "BEST VALUE" }) }),
1283
+ /* @__PURE__ */ jsx21(Circle2, { size: 22, borderWidth: 2, borderColor: selected ? "$color9" : "$color7", backgroundColor: selected ? "$color9" : "transparent", children: selected && /* @__PURE__ */ jsx21(Circle2, { size: 8, backgroundColor: "white" }) }),
1284
+ /* @__PURE__ */ jsxs14(YStack14, { flex: 1, gap: "$0.5", children: [
1285
+ /* @__PURE__ */ jsxs14(XStack10, { gap: "$2", alignItems: "center", children: [
1286
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$4", fontWeight: "700", children: plan.name }),
1287
+ plan.trial && /* @__PURE__ */ jsx21(YStack14, { backgroundColor: "$green3", paddingHorizontal: "$1.5", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ jsx21(SizableText17, { size: "$1", color: "$green9", fontWeight: "700", children: plan.trial }) })
1288
+ ] }),
1289
+ plan.tagline ? /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "$color10", children: plan.tagline }) : null
1290
+ ] }),
1291
+ /* @__PURE__ */ jsxs14(YStack14, { alignItems: "flex-end", gap: "$0.5", children: [
1292
+ /* @__PURE__ */ jsxs14(XStack10, { alignItems: "baseline", gap: "$1", children: [
1293
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$5", fontWeight: "800", children: plan.price }),
1294
+ /* @__PURE__ */ jsxs14(SizableText17, { size: "$2", color: "$color10", children: [
1295
+ "/",
1296
+ plan.period
1297
+ ] })
1298
+ ] }),
1299
+ plan.savings && /* @__PURE__ */ jsx21(YStack14, { backgroundColor: "$green3", paddingHorizontal: "$1.5", paddingVertical: 1, borderRadius: "$10", children: /* @__PURE__ */ jsx21(SizableText17, { size: "$1", color: "$green9", fontWeight: "700", children: plan.savings }) }),
1300
+ plan.pricePerWeek && /* @__PURE__ */ jsx21(SizableText17, { size: "$1", color: "$color10", children: plan.pricePerWeek })
1301
+ ] })
1302
+ ]
1303
+ }
1304
+ );
1305
+ }
1306
+ function ComparisonIcon({ enabled }) {
1307
+ return /* @__PURE__ */ jsx21(Circle2, { size: 24, backgroundColor: enabled ? "$green3" : "$color4", children: /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: enabled ? "$green10" : "$color8", fontWeight: "700", children: enabled ? "\u2713" : "\u2715" }) });
1308
+ }
1309
+ function TestimonialCard({ t }) {
1310
+ return /* @__PURE__ */ jsxs14(YStack14, { minWidth: 240, backgroundColor: "$color2", borderRadius: "$6", padding: "$3.5", gap: "$2.5", children: [
1311
+ /* @__PURE__ */ jsxs14(SizableText17, { size: "$3", color: "$color11", fontStyle: "italic", children: [
1312
+ "\u201C",
1313
+ t.quote,
1314
+ "\u201D"
1315
+ ] }),
1316
+ /* @__PURE__ */ jsxs14(XStack10, { gap: "$2", alignItems: "center", children: [
1317
+ /* @__PURE__ */ jsx21(Circle2, { size: 32, backgroundColor: "$color5", children: /* @__PURE__ */ jsx21(SizableText17, { size: "$2", fontWeight: "700", children: t.author[0] }) }),
1318
+ /* @__PURE__ */ jsxs14(YStack14, { children: [
1319
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$2", fontWeight: "700", children: t.author }),
1320
+ t.meta ? /* @__PURE__ */ jsx21(SizableText17, { size: "$1", color: "$color10", children: t.meta }) : null
1321
+ ] })
1322
+ ] })
1323
+ ] });
1324
+ }
1325
+ function CreatorHeader({ c }) {
1326
+ return /* @__PURE__ */ jsxs14(XStack10, { alignItems: "center", justifyContent: "center", gap: "$3", children: [
1327
+ c.avatar && /* @__PURE__ */ jsx21(Circle2, { size: 72, overflow: "hidden", backgroundColor: "$color3", children: c.avatar }),
1328
+ /* @__PURE__ */ jsxs14(YStack14, { alignItems: "center", gap: "$1", children: [
1329
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$6", fontWeight: "800", children: c.name }),
1330
+ c.meta ? /* @__PURE__ */ jsx21(SizableText17, { size: "$3", color: "$color10", children: c.meta }) : null
1331
+ ] })
1332
+ ] });
1333
+ }
1334
+ function TrustBadges({ badges }) {
1335
+ return /* @__PURE__ */ jsx21(XStack10, { justifyContent: "center", gap: "$4", paddingTop: "$1", children: badges.map((b, i) => /* @__PURE__ */ jsxs14(YStack14, { alignItems: "center", gap: "$1", children: [
1336
+ /* @__PURE__ */ jsx21(Circle2, { size: 28, backgroundColor: "$color3", children: b.icon ?? /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "$color9", children: "\u2726" }) }),
1337
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$1", color: "$color10", textAlign: "center", children: b.label })
1338
+ ] }, i)) });
1339
+ }
942
1340
  function PaywallScreen({
943
- title = "Upgrade Your Experience",
944
- subtitle = "Choose the plan that works for you",
1341
+ variant = "default",
1342
+ eyebrow,
1343
+ title = "Unlock Premium",
1344
+ subtitle,
1345
+ features = [],
945
1346
  plans,
946
1347
  selectedPlan,
947
1348
  onSelectPlan,
948
1349
  onContinue,
1350
+ onClose,
949
1351
  onRestore,
950
- continueLabel = "Continue"
1352
+ onTerms,
1353
+ onPrivacy,
1354
+ continueLabel = "Continue",
1355
+ reassurance = "Cancel anytime",
1356
+ hero,
1357
+ socialProof,
1358
+ countdownMinutes,
1359
+ badge,
1360
+ comparisonRows = [],
1361
+ testimonials = [],
1362
+ creator,
1363
+ topSlot,
1364
+ footerSlot,
1365
+ trustBadges
951
1366
  }) {
952
- return /* @__PURE__ */ jsxs13(YStack14, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", children: [
953
- /* @__PURE__ */ jsxs13(YStack14, { gap: "$2", paddingTop: "$6", children: [
954
- /* @__PURE__ */ jsx20(SizableText17, { size: "$9", fontWeight: "700", textAlign: "center", children: title }),
955
- /* @__PURE__ */ jsx20(SizableText17, { size: "$4", color: "$color10", textAlign: "center", children: subtitle })
956
- ] }),
957
- /* @__PURE__ */ jsx20(YStack14, { gap: "$3", flex: 1, children: plans.map((plan) => /* @__PURE__ */ jsxs13(
1367
+ const selected = selectedPlan ?? plans.find((p) => p.popular)?.id ?? plans[0]?.id;
1368
+ const countdown = useCountdown(countdownMinutes);
1369
+ const dark = variant === "immersive-dark";
1370
+ const bg = dark ? "$color1" : "$background";
1371
+ const tone = dark ? "$color12" : "$color11";
1372
+ const muted = "$color10";
1373
+ return /* @__PURE__ */ jsxs14(YStack14, { flex: 1, backgroundColor: bg, children: [
1374
+ onClose && /* @__PURE__ */ jsx21(XStack10, { position: "absolute", top: "$4", right: "$4", zIndex: 10, children: /* @__PURE__ */ jsx21(Button3, { size: "$3", circular: true, chromeless: true, onPress: onClose, pressStyle: { opacity: 0.6 }, children: /* @__PURE__ */ jsx21(SizableText17, { size: "$5", color: muted, children: "\u2715" }) }) }),
1375
+ /* @__PURE__ */ jsx21(ScrollView2, { flex: 1, contentContainerStyle: { paddingBottom: 240 }, children: /* @__PURE__ */ jsxs14(YStack14, { paddingHorizontal: "$5", paddingTop: "$8", gap: "$5", children: [
1376
+ topSlot,
1377
+ creator && variant === "creator-sheet" ? /* @__PURE__ */ jsx21(CreatorHeader, { c: creator }) : null,
1378
+ hero && /* @__PURE__ */ jsx21(YStack14, { alignItems: "center", paddingVertical: "$3", children: hero }),
1379
+ badge && /* @__PURE__ */ jsx21(XStack10, { justifyContent: "center", children: /* @__PURE__ */ jsx21(YStack14, { backgroundColor: "$color9", paddingHorizontal: "$3", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "white", fontWeight: "700", children: badge }) }) }),
1380
+ /* @__PURE__ */ jsxs14(YStack14, { gap: "$1.5", alignItems: "center", children: [
1381
+ eyebrow ? /* @__PURE__ */ jsx21(SizableText17, { size: "$2", fontWeight: "700", color: "$color9", textTransform: "uppercase", children: eyebrow }) : null,
1382
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$9", fontWeight: "800", textAlign: "center", color: tone, children: title }),
1383
+ subtitle && /* @__PURE__ */ jsx21(SizableText17, { size: "$4", color: muted, textAlign: "center", children: subtitle }),
1384
+ socialProof && /* @__PURE__ */ jsx21(SizableText17, { size: "$3", color: "$color9", fontWeight: "600", textAlign: "center", paddingTop: "$1", children: socialProof })
1385
+ ] }),
1386
+ countdownMinutes && !countdown.expired ? /* @__PURE__ */ jsxs14(XStack10, { justifyContent: "center", padding: "$2", backgroundColor: "$red3", borderRadius: "$4", alignSelf: "center", paddingHorizontal: "$4", gap: "$2", alignItems: "center", children: [
1387
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "$red9", fontWeight: "600", children: "Offer ends in" }),
1388
+ /* @__PURE__ */ jsx21(SizableText17, { size: "$5", color: "$red9", fontWeight: "800", fontFamily: "$mono", children: countdown.display })
1389
+ ] }) : null,
1390
+ features.length > 0 && /* @__PURE__ */ jsx21(YStack14, { gap: "$3.5", children: features.map((feature, i) => /* @__PURE__ */ jsx21(BenefitRow, { feature, tone, muted }, i)) }),
1391
+ variant === "social-proof" && testimonials.length > 0 ? /* @__PURE__ */ jsx21(ScrollView2, { horizontal: true, showsHorizontalScrollIndicator: false, children: /* @__PURE__ */ jsx21(XStack10, { gap: "$3", paddingRight: "$4", children: testimonials.map((t, i) => /* @__PURE__ */ jsx21(TestimonialCard, { t }, `${t.author}-${i}`)) }) }) : null,
1392
+ variant === "comparison" && comparisonRows.length > 0 ? /* @__PURE__ */ jsxs14(YStack14, { backgroundColor: dark ? "$color2" : "$color1", borderRadius: "$6", padding: "$3.5", gap: "$2", borderWidth: 1, borderColor: "$color4", children: [
1393
+ /* @__PURE__ */ jsxs14(XStack10, { alignItems: "center", children: [
1394
+ /* @__PURE__ */ jsx21(SizableText17, { flex: 1, size: "$2", fontWeight: "700", color: muted, children: "Feature" }),
1395
+ /* @__PURE__ */ jsx21(SizableText17, { width: 64, size: "$2", fontWeight: "700", textAlign: "center", color: muted, children: "Free" }),
1396
+ /* @__PURE__ */ jsx21(SizableText17, { width: 84, size: "$2", fontWeight: "700", textAlign: "center", color: "$color9", children: "Premium" })
1397
+ ] }),
1398
+ comparisonRows.map((row) => /* @__PURE__ */ jsxs14(XStack10, { alignItems: "center", paddingVertical: "$1.5", children: [
1399
+ /* @__PURE__ */ jsx21(SizableText17, { flex: 1, size: "$3", color: tone, children: row.label }),
1400
+ /* @__PURE__ */ jsx21(XStack10, { width: 64, justifyContent: "center", children: /* @__PURE__ */ jsx21(ComparisonIcon, { enabled: row.free }) }),
1401
+ /* @__PURE__ */ jsx21(XStack10, { width: 84, justifyContent: "center", children: /* @__PURE__ */ jsx21(ComparisonIcon, { enabled: row.premium }) })
1402
+ ] }, row.label))
1403
+ ] }) : null,
1404
+ /* @__PURE__ */ jsx21(YStack14, { gap: "$3", children: plans.map((plan) => /* @__PURE__ */ jsx21(
1405
+ PlanRow,
1406
+ {
1407
+ plan,
1408
+ selected: selected === plan.id,
1409
+ onPress: () => onSelectPlan?.(plan.id)
1410
+ },
1411
+ plan.id
1412
+ )) })
1413
+ ] }) }),
1414
+ /* @__PURE__ */ jsxs14(
958
1415
  YStack14,
959
1416
  {
1417
+ position: "absolute",
1418
+ bottom: 0,
1419
+ left: 0,
1420
+ right: 0,
960
1421
  padding: "$4",
961
- borderRadius: "$5",
962
- borderWidth: 2,
963
- borderColor: selectedPlan === plan.id ? "$color9" : "$color4",
964
- backgroundColor: selectedPlan === plan.id ? "$color2" : "$color1",
965
- pressStyle: { scale: 0.98 },
966
- onPress: () => onSelectPlan?.(plan.id),
967
- cursor: "pointer",
1422
+ paddingBottom: "$6",
1423
+ backgroundColor: bg,
1424
+ borderTopWidth: 1,
1425
+ borderTopColor: "$color4",
1426
+ gap: "$2.5",
968
1427
  children: [
969
- /* @__PURE__ */ jsxs13(XStack9, { justifyContent: "space-between", alignItems: "center", children: [
970
- /* @__PURE__ */ jsxs13(YStack14, { children: [
971
- /* @__PURE__ */ jsx20(SizableText17, { size: "$5", fontWeight: "600", children: plan.name }),
972
- /* @__PURE__ */ jsxs13(XStack9, { alignItems: "baseline", gap: "$1", children: [
973
- /* @__PURE__ */ jsx20(SizableText17, { size: "$8", fontWeight: "700", children: plan.price }),
974
- /* @__PURE__ */ jsxs13(SizableText17, { size: "$3", color: "$color9", children: [
975
- "/",
976
- plan.period
977
- ] })
978
- ] })
979
- ] }),
980
- plan.popular && /* @__PURE__ */ jsx20(YStack14, { backgroundColor: "$color9", paddingHorizontal: "$2", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ jsx20(SizableText17, { size: "$1", color: "$color1", fontWeight: "600", children: "POPULAR" }) })
1428
+ /* @__PURE__ */ jsx21(
1429
+ Button3,
1430
+ {
1431
+ size: "$5",
1432
+ backgroundColor: "$color9",
1433
+ color: "$color1",
1434
+ onPress: onContinue,
1435
+ pressStyle: { backgroundColor: "$color8", scale: 0.98 },
1436
+ animation: "quick",
1437
+ borderRadius: "$10",
1438
+ fontWeight: "700",
1439
+ children: continueLabel
1440
+ }
1441
+ ),
1442
+ reassurance && /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "$color9", textAlign: "center", children: reassurance }),
1443
+ /* @__PURE__ */ jsxs14(XStack10, { justifyContent: "center", gap: "$3", children: [
1444
+ onRestore && /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "$color8", onPress: onRestore, pressStyle: { opacity: 0.6 }, children: "Restore" }),
1445
+ onTerms && /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "$color8", onPress: onTerms, pressStyle: { opacity: 0.6 }, children: "Terms" }),
1446
+ onPrivacy && /* @__PURE__ */ jsx21(SizableText17, { size: "$2", color: "$color8", onPress: onPrivacy, pressStyle: { opacity: 0.6 }, children: "Privacy" })
981
1447
  ] }),
982
- /* @__PURE__ */ jsx20(YStack14, { gap: "$2", paddingTop: "$3", children: plan.features.map((feature, i) => /* @__PURE__ */ jsxs13(XStack9, { gap: "$2", alignItems: "center", children: [
983
- /* @__PURE__ */ jsx20(Circle2, { size: 6, backgroundColor: "$green9" }),
984
- /* @__PURE__ */ jsx20(SizableText17, { size: "$3", color: "$color11", children: feature })
985
- ] }, i)) })
1448
+ trustBadges && trustBadges.length > 0 && /* @__PURE__ */ jsx21(TrustBadges, { badges: trustBadges }),
1449
+ footerSlot
986
1450
  ]
987
- },
988
- plan.id
989
- )) }),
990
- /* @__PURE__ */ jsxs13(YStack14, { gap: "$3", paddingBottom: "$4", children: [
991
- /* @__PURE__ */ jsx20(
992
- Button3,
993
- {
994
- size: "$5",
995
- backgroundColor: "$color9",
996
- color: "$color1",
997
- onPress: onContinue,
998
- hoverStyle: { backgroundColor: "$color10" },
999
- pressStyle: { backgroundColor: "$color8" },
1000
- borderRadius: "$5",
1001
- children: continueLabel
1002
- }
1003
- ),
1004
- onRestore && /* @__PURE__ */ jsx20(Button3, { size: "$3", chromeless: true, onPress: onRestore, children: /* @__PURE__ */ jsx20(SizableText17, { size: "$3", color: "$color9", children: "Restore Purchases" }) })
1005
- ] })
1451
+ }
1452
+ )
1006
1453
  ] });
1007
1454
  }
1008
1455
 
1009
1456
  // src/patterns/OnboardingCarousel.tsx
1010
- import { useState as useState5 } from "react";
1011
- import { Button as Button4, SizableText as SizableText18, XStack as XStack10, YStack as YStack15, Circle as Circle3 } from "tamagui";
1012
- import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
1457
+ import { useState as useState6 } from "react";
1458
+ import { Button as Button4, SizableText as SizableText18, XStack as XStack11, YStack as YStack15, Circle as Circle3 } from "tamagui";
1459
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1013
1460
  function OnboardingCarousel({
1014
1461
  steps,
1462
+ variant = "default",
1463
+ brand,
1464
+ topLeading,
1015
1465
  onComplete,
1016
1466
  onSkip,
1017
1467
  completeLabel = "Get Started",
1018
1468
  skipLabel = "Skip",
1019
- nextLabel = "Next"
1469
+ nextLabel = "Next",
1470
+ footerSlot
1020
1471
  }) {
1021
- const [current, setCurrent] = useState5(0);
1472
+ const [current, setCurrent] = useState6(0);
1473
+ if (steps.length === 0) {
1474
+ return /* @__PURE__ */ jsx22(YStack15, { flex: 1, backgroundColor: "$background", padding: "$4", alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx22(SizableText18, { size: "$5", color: "$color10", textAlign: "center", children: "Add at least one onboarding step." }) });
1475
+ }
1022
1476
  const isLast = current === steps.length - 1;
1023
1477
  const step = steps[current];
1024
- return /* @__PURE__ */ jsxs14(YStack15, { flex: 1, backgroundColor: "$background", padding: "$4", justifyContent: "space-between", children: [
1025
- /* @__PURE__ */ jsx21(XStack10, { 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 }) }) }),
1026
- /* @__PURE__ */ jsxs14(YStack15, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$5", paddingHorizontal: "$4", children: [
1027
- step?.icon && /* @__PURE__ */ jsx21(Circle3, { size: 120, backgroundColor: "$color2", alignItems: "center", justifyContent: "center", children: step.icon }),
1028
- /* @__PURE__ */ jsxs14(YStack15, { gap: "$3", alignItems: "center", children: [
1029
- /* @__PURE__ */ jsx21(SizableText18, { size: "$9", fontWeight: "700", textAlign: "center", children: step?.title }),
1030
- /* @__PURE__ */ jsx21(SizableText18, { size: "$4", color: "$color10", textAlign: "center", maxWidth: 300, children: step?.description })
1478
+ const hero = step?.hero ?? step?.icon;
1479
+ const isEditorial = variant === "editorial";
1480
+ const isSelection = variant === "selection-step";
1481
+ const isPermission = variant === "permission-prompt";
1482
+ const topPadding = isEditorial ? "$6" : "$4";
1483
+ const titleSize = isEditorial ? "$10" : "$9";
1484
+ const backgroundColor = variant === "calm-gradient" ? "$color2" : "$background";
1485
+ const heroBackground = isPermission ? "$color3" : isSelection ? "$color1" : "$color2";
1486
+ const heroRadius = variant === "card-tilt" || isSelection ? "$8" : "$10";
1487
+ const buttonTone = variant === "editorial" ? "$color12" : "$color9";
1488
+ return /* @__PURE__ */ jsxs15(YStack15, { flex: 1, backgroundColor, padding: "$4", justifyContent: "space-between", children: [
1489
+ step?.background ? /* @__PURE__ */ jsx22(YStack15, { position: "absolute", left: 0, right: 0, top: 0, bottom: 0, children: step.background }) : null,
1490
+ /* @__PURE__ */ jsxs15(XStack11, { justifyContent: "space-between", alignItems: "center", paddingTop: topPadding, children: [
1491
+ /* @__PURE__ */ jsx22(XStack11, { minWidth: 40, children: topLeading }),
1492
+ brand ? /* @__PURE__ */ jsx22(YStack15, { alignItems: "center", flex: 1, children: brand }) : /* @__PURE__ */ jsx22(YStack15, { flex: 1 }),
1493
+ !isLast && onSkip && /* @__PURE__ */ jsx22(Button4, { chromeless: true, onPress: onSkip, children: /* @__PURE__ */ jsx22(SizableText18, { size: "$4", color: "$color9", children: skipLabel }) })
1494
+ ] }),
1495
+ /* @__PURE__ */ jsxs15(YStack15, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$5", paddingHorizontal: "$4", children: [
1496
+ hero ? variant === "card-tilt" || isSelection ? /* @__PURE__ */ jsx22(
1497
+ YStack15,
1498
+ {
1499
+ width: "100%",
1500
+ maxWidth: 340,
1501
+ minHeight: 260,
1502
+ borderRadius: heroRadius,
1503
+ backgroundColor: heroBackground,
1504
+ padding: "$3",
1505
+ alignItems: "center",
1506
+ justifyContent: "center",
1507
+ borderWidth: variant === "card-tilt" ? 3 : 1,
1508
+ borderColor: "$color4",
1509
+ shadowColor: "$shadowColor",
1510
+ shadowOpacity: 0.14,
1511
+ shadowRadius: 18,
1512
+ shadowOffset: { width: 0, height: 10 },
1513
+ style: variant === "card-tilt" ? { transform: [{ rotate: "-5deg" }] } : void 0,
1514
+ children: hero
1515
+ }
1516
+ ) : /* @__PURE__ */ jsx22(Circle3, { size: isPermission ? 140 : 120, backgroundColor: heroBackground, alignItems: "center", justifyContent: "center", children: hero }) : null,
1517
+ /* @__PURE__ */ jsxs15(YStack15, { gap: "$3", alignItems: "center", children: [
1518
+ step?.eyebrow ? /* @__PURE__ */ jsx22(SizableText18, { size: "$2", color: "$color9", fontWeight: "700", textTransform: "uppercase", children: step.eyebrow }) : null,
1519
+ /* @__PURE__ */ jsx22(SizableText18, { size: titleSize, fontWeight: "700", textAlign: "center", children: step?.title }),
1520
+ /* @__PURE__ */ jsx22(SizableText18, { size: "$4", color: "$color10", textAlign: "center", maxWidth: 300, children: step?.description })
1031
1521
  ] })
1032
1522
  ] }),
1033
- /* @__PURE__ */ jsxs14(YStack15, { gap: "$3", paddingBottom: "$2", children: [
1034
- /* @__PURE__ */ jsx21(XStack10, { justifyContent: "center", gap: "$2", children: steps.map((_, i) => /* @__PURE__ */ jsx21(
1523
+ /* @__PURE__ */ jsxs15(YStack15, { gap: "$3", paddingBottom: "$2", children: [
1524
+ /* @__PURE__ */ jsx22(XStack11, { justifyContent: "center", gap: "$2", children: steps.map((_, i) => /* @__PURE__ */ jsx22(
1035
1525
  Circle3,
1036
1526
  {
1037
- size: 8,
1527
+ size: variant === "card-tilt" ? 10 : 8,
1528
+ width: i === current && variant !== "default" ? 24 : void 0,
1038
1529
  backgroundColor: i === current ? "$color9" : "$color4",
1530
+ borderRadius: "$10",
1039
1531
  animation: "quick"
1040
1532
  },
1041
1533
  i
1042
1534
  )) }),
1043
- /* @__PURE__ */ jsx21(
1535
+ /* @__PURE__ */ jsx22(
1044
1536
  Button4,
1045
1537
  {
1046
1538
  size: "$5",
1047
- backgroundColor: "$color9",
1539
+ backgroundColor: buttonTone,
1048
1540
  color: "$color1",
1049
- borderRadius: "$5",
1050
- hoverStyle: { backgroundColor: "$color10" },
1541
+ borderRadius: variant === "editorial" ? "$10" : "$5",
1542
+ hoverStyle: { backgroundColor: variant === "editorial" ? "$color11" : "$color10" },
1051
1543
  pressStyle: { backgroundColor: "$color8" },
1052
1544
  onPress: () => isLast ? onComplete?.() : setCurrent((c) => c + 1),
1053
- children: isLast ? completeLabel : nextLabel
1545
+ children: isLast ? step?.ctaLabel ?? completeLabel : step?.ctaLabel ?? nextLabel
1054
1546
  }
1055
- )
1547
+ ),
1548
+ footerSlot
1056
1549
  ] })
1057
1550
  ] });
1058
1551
  }
1059
1552
 
1060
1553
  // src/patterns/ChatBubble.tsx
1061
- import { SizableText as SizableText19, XStack as XStack11, YStack as YStack16, Circle as Circle4, Image as Image3 } from "tamagui";
1062
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1554
+ import { SizableText as SizableText19, XStack as XStack12, YStack as YStack16, Circle as Circle4, Image as Image3 } from "tamagui";
1555
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1063
1556
  function ChatBubble({ message, showAvatar = true }) {
1064
1557
  const isUser = message.sender === "user";
1065
- return /* @__PURE__ */ jsxs15(
1066
- XStack11,
1558
+ return /* @__PURE__ */ jsxs16(
1559
+ XStack12,
1067
1560
  {
1068
1561
  alignSelf: isUser ? "flex-end" : "flex-start",
1069
1562
  maxWidth: "75%",
1070
1563
  gap: "$2",
1071
1564
  flexDirection: isUser ? "row-reverse" : "row",
1072
1565
  children: [
1073
- showAvatar && !isUser && /* @__PURE__ */ jsx22(Circle4, { 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() ?? "?" }) }),
1074
- /* @__PURE__ */ jsxs15(
1566
+ showAvatar && !isUser && /* @__PURE__ */ jsx23(Circle4, { size: 32, backgroundColor: "$color4", overflow: "hidden", children: message.avatar ? /* @__PURE__ */ jsx23(Image3, { source: { uri: message.avatar }, width: 32, height: 32, objectFit: "cover" }) : /* @__PURE__ */ jsx23(SizableText19, { size: "$2", fontWeight: "600", color: "$color11", children: message.senderName?.[0]?.toUpperCase() ?? "?" }) }),
1567
+ /* @__PURE__ */ jsxs16(
1075
1568
  YStack16,
1076
1569
  {
1077
1570
  backgroundColor: isUser ? "$color9" : "$color3",
@@ -1082,8 +1575,8 @@ function ChatBubble({ message, showAvatar = true }) {
1082
1575
  borderBottomLeftRadius: isUser ? "$5" : "$2",
1083
1576
  gap: "$1",
1084
1577
  children: [
1085
- /* @__PURE__ */ jsx22(SizableText19, { size: "$3", color: isUser ? "$color1" : "$color12", children: message.text }),
1086
- message.timestamp && /* @__PURE__ */ jsx22(SizableText19, { size: "$1", color: isUser ? "$color3" : "$color9", alignSelf: "flex-end", children: message.timestamp })
1578
+ /* @__PURE__ */ jsx23(SizableText19, { size: "$3", color: isUser ? "$color1" : "$color12", children: message.text }),
1579
+ message.timestamp && /* @__PURE__ */ jsx23(SizableText19, { size: "$1", color: isUser ? "$color3" : "$color9", alignSelf: "flex-end", children: message.timestamp })
1087
1580
  ]
1088
1581
  }
1089
1582
  )
@@ -1093,11 +1586,11 @@ function ChatBubble({ message, showAvatar = true }) {
1093
1586
  }
1094
1587
 
1095
1588
  // src/patterns/SettingsScreen.tsx
1096
- import { Separator as Separator4, SizableText as SizableText20, Switch, XStack as XStack12, YStack as YStack17 } from "tamagui";
1097
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1589
+ import { Separator as Separator4, SizableText as SizableText20, Switch, XStack as XStack13, YStack as YStack17 } from "tamagui";
1590
+ import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1098
1591
  function SettingsItemRow({ item }) {
1099
- return /* @__PURE__ */ jsxs16(
1100
- XStack12,
1592
+ return /* @__PURE__ */ jsxs17(
1593
+ XStack13,
1101
1594
  {
1102
1595
  alignItems: "center",
1103
1596
  gap: "$3",
@@ -1108,21 +1601,21 @@ function SettingsItemRow({ item }) {
1108
1601
  onPress: item.onPress,
1109
1602
  cursor: item.onPress ? "pointer" : void 0,
1110
1603
  children: [
1111
- item.icon && /* @__PURE__ */ jsx23(YStack17, { width: 24, alignItems: "center", children: item.icon }),
1112
- /* @__PURE__ */ jsxs16(YStack17, { flex: 1, gap: "$1", children: [
1113
- /* @__PURE__ */ jsx23(SizableText20, { size: "$4", fontWeight: "500", children: item.title }),
1114
- item.subtitle && /* @__PURE__ */ jsx23(SizableText20, { size: "$2", color: "$color9", children: item.subtitle })
1604
+ item.icon && /* @__PURE__ */ jsx24(YStack17, { width: 24, alignItems: "center", children: item.icon }),
1605
+ /* @__PURE__ */ jsxs17(YStack17, { flex: 1, gap: "$1", children: [
1606
+ /* @__PURE__ */ jsx24(SizableText20, { size: "$4", fontWeight: "500", children: item.title }),
1607
+ item.subtitle && /* @__PURE__ */ jsx24(SizableText20, { size: "$2", color: "$color9", children: item.subtitle })
1115
1608
  ] }),
1116
- item.type === "toggle" ? /* @__PURE__ */ jsx23(Switch, { size: "$3", checked: item.value, onCheckedChange: item.onValueChange, children: /* @__PURE__ */ jsx23(Switch.Thumb, { animation: "quick" }) }) : item.right ? item.right : item.onPress && /* @__PURE__ */ jsx23(SizableText20, { size: "$5", color: "$color8", children: "\u203A" })
1609
+ item.type === "toggle" ? /* @__PURE__ */ jsx24(Switch, { size: "$3", checked: item.value, onCheckedChange: item.onValueChange, children: /* @__PURE__ */ jsx24(Switch.Thumb, { animation: "quick" }) }) : item.right ? item.right : item.onPress && /* @__PURE__ */ jsx24(SizableText20, { size: "$5", color: "$color8", children: "\u203A" })
1117
1610
  ]
1118
1611
  }
1119
1612
  );
1120
1613
  }
1121
1614
  function SettingsScreen({ sections, header }) {
1122
- return /* @__PURE__ */ jsxs16(YStack17, { flex: 1, backgroundColor: "$background", children: [
1615
+ return /* @__PURE__ */ jsxs17(YStack17, { flex: 1, backgroundColor: "$background", children: [
1123
1616
  header,
1124
- /* @__PURE__ */ jsx23(YStack17, { gap: "$4", paddingVertical: "$2", children: sections.map((section, si) => /* @__PURE__ */ jsxs16(YStack17, { children: [
1125
- section.title && /* @__PURE__ */ jsx23(
1617
+ /* @__PURE__ */ jsx24(YStack17, { gap: "$4", paddingVertical: "$2", children: sections.map((section, si) => /* @__PURE__ */ jsxs17(YStack17, { children: [
1618
+ section.title && /* @__PURE__ */ jsx24(
1126
1619
  SizableText20,
1127
1620
  {
1128
1621
  size: "$2",
@@ -1134,9 +1627,9 @@ function SettingsScreen({ sections, header }) {
1134
1627
  children: section.title
1135
1628
  }
1136
1629
  ),
1137
- /* @__PURE__ */ jsx23(YStack17, { backgroundColor: "$color1", borderRadius: "$4", marginHorizontal: "$3", overflow: "hidden", children: section.items.map((item, ii) => /* @__PURE__ */ jsxs16(YStack17, { children: [
1138
- /* @__PURE__ */ jsx23(SettingsItemRow, { item }),
1139
- ii < section.items.length - 1 && /* @__PURE__ */ jsx23(Separator4, { borderColor: "$color3", marginLeft: "$12" })
1630
+ /* @__PURE__ */ jsx24(YStack17, { backgroundColor: "$color1", borderRadius: "$4", marginHorizontal: "$3", overflow: "hidden", children: section.items.map((item, ii) => /* @__PURE__ */ jsxs17(YStack17, { children: [
1631
+ /* @__PURE__ */ jsx24(SettingsItemRow, { item }),
1632
+ ii < section.items.length - 1 && /* @__PURE__ */ jsx24(Separator4, { borderColor: "$color3", marginLeft: "$12" })
1140
1633
  ] }, item.id)) })
1141
1634
  ] }, si)) })
1142
1635
  ] });
@@ -1144,15 +1637,15 @@ function SettingsScreen({ sections, header }) {
1144
1637
 
1145
1638
  // src/patterns/EmptyState.tsx
1146
1639
  import { Button as Button5, SizableText as SizableText21, YStack as YStack18 } from "tamagui";
1147
- import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1640
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1148
1641
  function EmptyState({ icon, title, description, actionLabel, onAction }) {
1149
- return /* @__PURE__ */ jsxs17(YStack18, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$4", padding: "$6", children: [
1642
+ return /* @__PURE__ */ jsxs18(YStack18, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$4", padding: "$6", children: [
1150
1643
  icon,
1151
- /* @__PURE__ */ jsxs17(YStack18, { gap: "$2", alignItems: "center", children: [
1152
- /* @__PURE__ */ jsx24(SizableText21, { size: "$6", fontWeight: "600", textAlign: "center", children: title }),
1153
- description && /* @__PURE__ */ jsx24(SizableText21, { size: "$4", color: "$color9", textAlign: "center", maxWidth: 280, children: description })
1644
+ /* @__PURE__ */ jsxs18(YStack18, { gap: "$2", alignItems: "center", children: [
1645
+ /* @__PURE__ */ jsx25(SizableText21, { size: "$6", fontWeight: "600", textAlign: "center", children: title }),
1646
+ description && /* @__PURE__ */ jsx25(SizableText21, { size: "$4", color: "$color9", textAlign: "center", maxWidth: 280, children: description })
1154
1647
  ] }),
1155
- actionLabel && onAction && /* @__PURE__ */ jsx24(
1648
+ actionLabel && onAction && /* @__PURE__ */ jsx25(
1156
1649
  Button5,
1157
1650
  {
1158
1651
  size: "$4",
@@ -1169,46 +1662,46 @@ function EmptyState({ icon, title, description, actionLabel, onAction }) {
1169
1662
  }
1170
1663
 
1171
1664
  // src/patterns/ProfileHeader.tsx
1172
- import { Circle as Circle5, Image as Image4, SizableText as SizableText22, XStack as XStack13, YStack as YStack19 } from "tamagui";
1173
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1665
+ import { Circle as Circle5, Image as Image4, SizableText as SizableText22, XStack as XStack14, YStack as YStack19 } from "tamagui";
1666
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1174
1667
  function ProfileHeader({ name, subtitle, avatar, stats, actions }) {
1175
- return /* @__PURE__ */ jsxs18(YStack19, { alignItems: "center", gap: "$4", paddingVertical: "$6", paddingHorizontal: "$4", children: [
1176
- /* @__PURE__ */ jsx25(Circle5, { 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() ?? "?" }) }),
1177
- /* @__PURE__ */ jsxs18(YStack19, { alignItems: "center", gap: "$1", children: [
1178
- /* @__PURE__ */ jsx25(SizableText22, { size: "$7", fontWeight: "700", children: name }),
1179
- subtitle && /* @__PURE__ */ jsx25(SizableText22, { size: "$4", color: "$color10", children: subtitle })
1668
+ return /* @__PURE__ */ jsxs19(YStack19, { alignItems: "center", gap: "$4", paddingVertical: "$6", paddingHorizontal: "$4", children: [
1669
+ /* @__PURE__ */ jsx26(Circle5, { size: 80, backgroundColor: "$color4", overflow: "hidden", children: avatar ? /* @__PURE__ */ jsx26(Image4, { source: { uri: avatar }, width: 80, height: 80, objectFit: "cover" }) : /* @__PURE__ */ jsx26(SizableText22, { size: "$9", fontWeight: "700", color: "$color11", children: name[0]?.toUpperCase() ?? "?" }) }),
1670
+ /* @__PURE__ */ jsxs19(YStack19, { alignItems: "center", gap: "$1", children: [
1671
+ /* @__PURE__ */ jsx26(SizableText22, { size: "$7", fontWeight: "700", children: name }),
1672
+ subtitle && /* @__PURE__ */ jsx26(SizableText22, { size: "$4", color: "$color10", children: subtitle })
1180
1673
  ] }),
1181
- stats && stats.length > 0 && /* @__PURE__ */ jsx25(XStack13, { gap: "$6", children: stats.map((stat, i) => /* @__PURE__ */ jsxs18(YStack19, { alignItems: "center", gap: "$1", children: [
1182
- /* @__PURE__ */ jsx25(SizableText22, { size: "$6", fontWeight: "700", children: stat.value }),
1183
- /* @__PURE__ */ jsx25(SizableText22, { size: "$2", color: "$color9", children: stat.label })
1674
+ stats && stats.length > 0 && /* @__PURE__ */ jsx26(XStack14, { gap: "$6", children: stats.map((stat, i) => /* @__PURE__ */ jsxs19(YStack19, { alignItems: "center", gap: "$1", children: [
1675
+ /* @__PURE__ */ jsx26(SizableText22, { size: "$6", fontWeight: "700", children: stat.value }),
1676
+ /* @__PURE__ */ jsx26(SizableText22, { size: "$2", color: "$color9", children: stat.label })
1184
1677
  ] }, i)) }),
1185
1678
  actions
1186
1679
  ] });
1187
1680
  }
1188
1681
 
1189
1682
  // src/patterns/AppHeader.tsx
1190
- import { SizableText as SizableText23, XStack as XStack14, YStack as YStack20 } from "tamagui";
1191
- import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1683
+ import { SizableText as SizableText23, XStack as XStack15, YStack as YStack20 } from "tamagui";
1684
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
1192
1685
  function AppHeader({ title, subtitle, variant = "simple", onBack, avatar, left, right, transparent, borderless }) {
1193
1686
  const leftContent = (() => {
1194
- if (variant === "back") return /* @__PURE__ */ jsx26(SizableText23, { size: "$6", paddingRight: "$2", onPress: onBack, pressStyle: { opacity: 0.6 }, cursor: "pointer", children: "\u2039" });
1195
- if (variant === "profile") return /* @__PURE__ */ jsx26(Avatar, { uri: avatar, name: title, size: "sm" });
1687
+ if (variant === "back") return /* @__PURE__ */ jsx27(SizableText23, { size: "$6", paddingRight: "$2", onPress: onBack, pressStyle: { opacity: 0.6 }, cursor: "pointer", children: "\u2039" });
1688
+ if (variant === "profile") return /* @__PURE__ */ jsx27(Avatar, { uri: avatar, name: title, size: "sm" });
1196
1689
  if (variant === "centered") return left ?? null;
1197
1690
  return null;
1198
1691
  })();
1199
1692
  const rightContent = variant === "profile" || variant === "centered" ? right ?? null : null;
1200
- return /* @__PURE__ */ jsx26(
1693
+ return /* @__PURE__ */ jsx27(
1201
1694
  YStack20,
1202
1695
  {
1203
1696
  paddingTop: "$6",
1204
1697
  backgroundColor: transparent ? "transparent" : "$background",
1205
1698
  borderBottomWidth: borderless ? 0 : 1,
1206
1699
  borderBottomColor: "$borderColor",
1207
- children: /* @__PURE__ */ jsxs19(XStack14, { height: 56, alignItems: "center", paddingHorizontal: "$4", gap: "$3", children: [
1700
+ children: /* @__PURE__ */ jsxs20(XStack15, { height: 56, alignItems: "center", paddingHorizontal: "$4", gap: "$3", children: [
1208
1701
  leftContent,
1209
- /* @__PURE__ */ jsxs19(YStack20, { flex: 1, alignItems: variant === "centered" ? "center" : "flex-start", children: [
1210
- /* @__PURE__ */ jsx26(SizableText23, { size: "$6", fontWeight: "700", numberOfLines: 1, children: title }),
1211
- subtitle && /* @__PURE__ */ jsx26(SizableText23, { size: "$2", color: "$color9", numberOfLines: 1, children: subtitle })
1702
+ /* @__PURE__ */ jsxs20(YStack20, { flex: 1, alignItems: variant === "centered" ? "center" : "flex-start", children: [
1703
+ /* @__PURE__ */ jsx27(SizableText23, { size: "$6", fontWeight: "700", numberOfLines: 1, children: title }),
1704
+ subtitle && /* @__PURE__ */ jsx27(SizableText23, { size: "$2", color: "$color9", numberOfLines: 1, children: subtitle })
1212
1705
  ] }),
1213
1706
  rightContent
1214
1707
  ] })
@@ -1217,107 +1710,183 @@ function AppHeader({ title, subtitle, variant = "simple", onBack, avatar, left,
1217
1710
  }
1218
1711
 
1219
1712
  // src/patterns/BottomSheet.tsx
1220
- import { Sheet, SizableText as SizableText24, XStack as XStack15, YStack as YStack21 } from "tamagui";
1221
- import { ScrollView as ScrollView2 } from "react-native";
1222
- import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
1223
- function BottomSheet({ open, onOpenChange, title, children, snapPoints = [85], dismissOnSnapToBottom = true, showHandle = true, showClose = false }) {
1224
- return /* @__PURE__ */ jsxs20(Sheet, { modal: true, open, onOpenChange, snapPoints, dismissOnSnapToBottom, animation: "medium", children: [
1225
- /* @__PURE__ */ jsx27(Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1226
- showHandle && /* @__PURE__ */ jsx27(Sheet.Handle, {}),
1227
- /* @__PURE__ */ jsxs20(Sheet.Frame, { borderTopLeftRadius: "$6", borderTopRightRadius: "$6", backgroundColor: "$background", children: [
1228
- (title || showClose) && /* @__PURE__ */ jsxs20(XStack15, { paddingHorizontal: "$4", paddingTop: "$3", paddingBottom: "$2", alignItems: "center", justifyContent: "space-between", children: [
1229
- /* @__PURE__ */ jsx27(SizableText24, { size: "$6", fontWeight: "600", flexShrink: 1, children: title }),
1230
- showClose && /* @__PURE__ */ jsx27(
1231
- XStack15,
1232
- {
1233
- width: 28,
1234
- height: 28,
1235
- borderRadius: "$10",
1236
- backgroundColor: "$color4",
1237
- alignItems: "center",
1238
- justifyContent: "center",
1239
- pressStyle: { opacity: 0.7 },
1240
- onPress: () => onOpenChange(false),
1241
- children: /* @__PURE__ */ jsx27(SizableText24, { size: "$3", color: "$color10", fontWeight: "600", children: "\u2715" })
1242
- }
1243
- )
1244
- ] }),
1245
- /* @__PURE__ */ jsx27(ScrollView2, { contentContainerStyle: { paddingBottom: 40 }, children: /* @__PURE__ */ jsx27(YStack21, { padding: "$4", children }) })
1246
- ] })
1247
- ] });
1713
+ import { Sheet, SizableText as SizableText24, XStack as XStack16, YStack as YStack21 } from "tamagui";
1714
+ import { ScrollView as ScrollView3 } from "react-native";
1715
+ import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1716
+ function BottomSheet({ open, onOpenChange, title, children, snapPoints = [85], dismissOnSnapToBottom = true, showHandle = true, showClose = false, zIndex = 1e5 }) {
1717
+ return /* @__PURE__ */ jsxs21(
1718
+ Sheet,
1719
+ {
1720
+ modal: true,
1721
+ forceRemoveScrollEnabled: open,
1722
+ open,
1723
+ onOpenChange,
1724
+ snapPoints,
1725
+ dismissOnSnapToBottom,
1726
+ zIndex,
1727
+ animation: "medium",
1728
+ children: [
1729
+ /* @__PURE__ */ jsx28(Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1730
+ showHandle && /* @__PURE__ */ jsx28(Sheet.Handle, {}),
1731
+ /* @__PURE__ */ jsxs21(Sheet.Frame, { children: [
1732
+ (title || showClose) && /* @__PURE__ */ jsxs21(XStack16, { paddingHorizontal: "$4", paddingTop: "$3", paddingBottom: "$2", alignItems: "center", justifyContent: "space-between", children: [
1733
+ /* @__PURE__ */ jsx28(SizableText24, { size: "$6", fontWeight: "600", flexShrink: 1, children: title }),
1734
+ showClose && /* @__PURE__ */ jsx28(
1735
+ XStack16,
1736
+ {
1737
+ width: 28,
1738
+ height: 28,
1739
+ borderRadius: "$10",
1740
+ backgroundColor: "$color4",
1741
+ alignItems: "center",
1742
+ justifyContent: "center",
1743
+ pressStyle: { opacity: 0.7 },
1744
+ onPress: () => onOpenChange(false),
1745
+ children: /* @__PURE__ */ jsx28(SizableText24, { size: "$3", color: "$color10", fontWeight: "600", children: "\u2715" })
1746
+ }
1747
+ )
1748
+ ] }),
1749
+ /* @__PURE__ */ jsx28(ScrollView3, { contentContainerStyle: { paddingBottom: 40 }, children: /* @__PURE__ */ jsx28(YStack21, { padding: "$4", children }) })
1750
+ ] })
1751
+ ]
1752
+ }
1753
+ );
1248
1754
  }
1249
1755
 
1250
1756
  // src/patterns/LoginScreen.tsx
1251
- import { useState as useState6 } from "react";
1252
- import { Button as Button6, SizableText as SizableText25, Spinner, XStack as XStack16, YStack as YStack22 } from "tamagui";
1253
- import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
1254
- function LoginScreen({ title = "Welcome", subtitle = "Sign in to continue", logo, providers = [], onProviderPress, showEmailForm, onEmailSubmit, onForgotPassword, onCreateAccount, onTerms, onPrivacy, loading }) {
1255
- const [email, setEmail] = useState6("");
1256
- const [password, setPassword] = useState6("");
1257
- return /* @__PURE__ */ jsxs21(YStack22, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", justifyContent: "center", children: [
1258
- /* @__PURE__ */ jsxs21(YStack22, { alignItems: "center", gap: "$2", children: [
1259
- logo && /* @__PURE__ */ jsx28(YStack22, { paddingBottom: "$3", children: logo }),
1260
- /* @__PURE__ */ jsx28(SizableText25, { size: "$9", fontWeight: "700", textAlign: "center", children: title }),
1261
- /* @__PURE__ */ jsx28(SizableText25, { size: "$4", color: "$color10", textAlign: "center", children: subtitle })
1262
- ] }),
1263
- providers.length > 0 && /* @__PURE__ */ jsx28(YStack22, { gap: "$2.5", children: providers.map((p) => /* @__PURE__ */ jsx28(
1264
- Button6,
1757
+ import { useState as useState7 } from "react";
1758
+ import { Button as Button6, Circle as Circle6, SizableText as SizableText25, Spinner, XStack as XStack17, YStack as YStack22 } from "tamagui";
1759
+ import { Fragment as Fragment2, jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
1760
+ var BRAND_ICON_MAP = {
1761
+ google: ({ size }) => /* @__PURE__ */ jsx29(GoogleLogo, { size }),
1762
+ apple: ({ size, color }) => /* @__PURE__ */ jsx29(AppleLogo, { size, color }),
1763
+ github: ({ size, color }) => /* @__PURE__ */ jsx29(GitHubLogo, { size, color }),
1764
+ microsoft: ({ size }) => /* @__PURE__ */ jsx29(MicrosoftLogo, { size }),
1765
+ custom: ({ size = 20 }) => /* @__PURE__ */ jsx29(Circle6, { size, backgroundColor: "$color4", alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx29(SizableText25, { fontSize: size * 0.6, color: "$color10", children: "\u2022" }) })
1766
+ };
1767
+ var BRAND_STYLES = {
1768
+ google: { backgroundColor: "$color1", borderColor: "$color5", textColor: "$color12" },
1769
+ apple: { backgroundColor: "$color12", borderColor: "$color12", textColor: "$color1" },
1770
+ github: { backgroundColor: "$color12", borderColor: "$color12", textColor: "$color1" },
1771
+ microsoft: { backgroundColor: "$color1", borderColor: "$color5", textColor: "$color12" },
1772
+ custom: { backgroundColor: "$color1", borderColor: "$color5", textColor: "$color12" }
1773
+ };
1774
+ function ProviderBadge({ provider }) {
1775
+ const brand = provider.brand ?? "custom";
1776
+ if (provider.icon) return /* @__PURE__ */ jsx29(Fragment2, { children: provider.icon });
1777
+ const renderIcon = BRAND_ICON_MAP[brand];
1778
+ const iconColor = brand === "apple" || brand === "github" ? "#fff" : void 0;
1779
+ return renderIcon({ size: 20, color: iconColor });
1780
+ }
1781
+ function LoginScreen({
1782
+ variant = "default",
1783
+ title = "Welcome",
1784
+ subtitle = "Sign in to continue",
1785
+ logo,
1786
+ providers = [],
1787
+ hero,
1788
+ backgroundSlot,
1789
+ footerSlot,
1790
+ providerButtonStyle = "brand",
1791
+ onProviderPress,
1792
+ showEmailForm,
1793
+ onEmailSubmit,
1794
+ onForgotPassword,
1795
+ onCreateAccount,
1796
+ onTerms,
1797
+ onPrivacy,
1798
+ loading
1799
+ }) {
1800
+ const [email, setEmail] = useState7("");
1801
+ const [password, setPassword] = useState7("");
1802
+ const isEditorial = variant === "editorial";
1803
+ const isCenteredCard = variant === "centered-card";
1804
+ return /* @__PURE__ */ jsxs22(YStack22, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", justifyContent: "center", children: [
1805
+ backgroundSlot ? /* @__PURE__ */ jsx29(YStack22, { position: "absolute", left: 0, right: 0, top: 0, bottom: 0, children: backgroundSlot }) : null,
1806
+ /* @__PURE__ */ jsxs22(
1807
+ YStack22,
1265
1808
  {
1266
- size: "$5",
1267
- borderWidth: 1.5,
1268
- borderColor: "$color5",
1269
- backgroundColor: "$color1",
1270
- borderRadius: "$4",
1271
- disabled: loading,
1272
- onPress: () => onProviderPress?.(p.id),
1273
- hoverStyle: { backgroundColor: "$color2" },
1274
- pressStyle: { backgroundColor: "$color3" },
1275
- children: /* @__PURE__ */ jsxs21(XStack16, { alignItems: "center", gap: "$2", children: [
1276
- p.icon,
1277
- /* @__PURE__ */ jsx28(SizableText25, { size: "$4", fontWeight: "500", children: p.name })
1278
- ] })
1279
- },
1280
- p.id
1281
- )) }),
1282
- showEmailForm && providers.length > 0 && /* @__PURE__ */ jsx28(Divider, { label: "or" }),
1283
- showEmailForm && /* @__PURE__ */ jsxs21(YStack22, { gap: "$3", children: [
1284
- /* @__PURE__ */ jsx28(Input, { label: "Email", placeholder: "your@email.com", value: email, onChangeText: setEmail, keyboardType: "email-address", autoCapitalize: "none" }),
1285
- /* @__PURE__ */ jsx28(Input, { label: "Password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: password, onChangeText: setPassword, secureTextEntry: true }),
1286
- onForgotPassword && /* @__PURE__ */ jsx28(XStack16, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx28(SizableText25, { size: "$3", color: "$color9", onPress: onForgotPassword, children: "Forgot password?" }) }),
1287
- /* @__PURE__ */ jsx28(
1288
- Button6,
1289
- {
1290
- size: "$5",
1291
- backgroundColor: "$color9",
1292
- color: "$color1",
1293
- borderRadius: "$5",
1294
- disabled: loading,
1295
- onPress: () => onEmailSubmit?.(email, password),
1296
- hoverStyle: { backgroundColor: "$color10" },
1297
- pressStyle: { backgroundColor: "$color8" },
1298
- icon: loading ? /* @__PURE__ */ jsx28(Spinner, { size: "small", color: "$color1" }) : void 0,
1299
- children: "Sign In"
1300
- }
1301
- ),
1302
- onCreateAccount && /* @__PURE__ */ jsx28(Button6, { size: "$3", chromeless: true, onPress: onCreateAccount, children: /* @__PURE__ */ jsx28(SizableText25, { size: "$3", color: "$color9", children: "Create Account" }) })
1303
- ] }),
1304
- (onTerms || onPrivacy) && /* @__PURE__ */ jsx28(YStack22, { paddingTop: "$2", alignItems: "center", children: /* @__PURE__ */ jsxs21(SizableText25, { size: "$2", color: "$color8", textAlign: "center", children: [
1305
- "By continuing you agree to our",
1306
- " ",
1307
- onTerms && /* @__PURE__ */ jsx28(SizableText25, { size: "$2", color: "$color9", onPress: onTerms, children: "Terms of Service" }),
1308
- onTerms && onPrivacy && " & ",
1309
- onPrivacy && /* @__PURE__ */ jsx28(SizableText25, { size: "$2", color: "$color9", onPress: onPrivacy, children: "Privacy Policy" })
1310
- ] }) })
1809
+ gap: "$5",
1810
+ backgroundColor: isCenteredCard ? "$color1" : "transparent",
1811
+ borderRadius: isCenteredCard ? "$7" : void 0,
1812
+ padding: isCenteredCard ? "$4" : void 0,
1813
+ borderWidth: isCenteredCard ? 1 : 0,
1814
+ borderColor: isCenteredCard ? "$color4" : void 0,
1815
+ children: [
1816
+ /* @__PURE__ */ jsxs22(YStack22, { alignItems: "center", gap: "$2", children: [
1817
+ logo && /* @__PURE__ */ jsx29(YStack22, { paddingBottom: "$3", children: logo }),
1818
+ hero ? /* @__PURE__ */ jsx29(YStack22, { paddingBottom: "$2", children: hero }) : null,
1819
+ /* @__PURE__ */ jsx29(SizableText25, { size: isEditorial ? "$10" : "$9", fontWeight: "700", textAlign: "center", fontFamily: isEditorial ? "$heading" : void 0, children: title }),
1820
+ /* @__PURE__ */ jsx29(SizableText25, { size: "$4", color: "$color10", textAlign: "center", children: subtitle })
1821
+ ] }),
1822
+ providers.length > 0 && /* @__PURE__ */ jsx29(YStack22, { gap: "$2.5", children: providers.map((p) => /* @__PURE__ */ jsx29(
1823
+ Button6,
1824
+ {
1825
+ size: "$5",
1826
+ borderWidth: 1.5,
1827
+ borderColor: providerButtonStyle === "brand" ? BRAND_STYLES[p.brand ?? "custom"].borderColor : "$color5",
1828
+ backgroundColor: providerButtonStyle === "brand" ? BRAND_STYLES[p.brand ?? "custom"].backgroundColor : "$color1",
1829
+ borderRadius: isEditorial ? "$6" : "$4",
1830
+ disabled: loading,
1831
+ onPress: () => onProviderPress?.(p.id),
1832
+ hoverStyle: { backgroundColor: providerButtonStyle === "brand" ? BRAND_STYLES[p.brand ?? "custom"].backgroundColor : "$color2" },
1833
+ pressStyle: { backgroundColor: "$color3" },
1834
+ children: /* @__PURE__ */ jsxs22(XStack17, { alignItems: "center", justifyContent: "space-between", width: "100%", gap: "$2", children: [
1835
+ /* @__PURE__ */ jsxs22(XStack17, { alignItems: "center", gap: "$2.5", children: [
1836
+ /* @__PURE__ */ jsx29(ProviderBadge, { provider: p }),
1837
+ /* @__PURE__ */ jsxs22(YStack22, { alignItems: "flex-start", children: [
1838
+ /* @__PURE__ */ jsx29(SizableText25, { size: "$4", fontWeight: "600", color: providerButtonStyle === "brand" ? BRAND_STYLES[p.brand ?? "custom"].textColor : void 0, children: p.name }),
1839
+ p.description ? /* @__PURE__ */ jsx29(SizableText25, { size: "$2", color: "$color10", children: p.description }) : null
1840
+ ] })
1841
+ ] }),
1842
+ /* @__PURE__ */ jsx29(SizableText25, { size: "$4", color: providerButtonStyle === "brand" ? BRAND_STYLES[p.brand ?? "custom"].textColor : "$color9", children: "\u2192" })
1843
+ ] })
1844
+ },
1845
+ p.id
1846
+ )) }),
1847
+ showEmailForm && providers.length > 0 && /* @__PURE__ */ jsx29(Divider, { label: "or" }),
1848
+ showEmailForm && /* @__PURE__ */ jsxs22(YStack22, { gap: "$3", children: [
1849
+ /* @__PURE__ */ jsx29(Input, { label: "Email", placeholder: "your@email.com", value: email, onChangeText: setEmail, keyboardType: "email-address", autoCapitalize: "none" }),
1850
+ /* @__PURE__ */ jsx29(Input, { label: "Password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: password, onChangeText: setPassword, secureTextEntry: true }),
1851
+ onForgotPassword && /* @__PURE__ */ jsx29(XStack17, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx29(SizableText25, { size: "$3", color: "$color9", onPress: onForgotPassword, children: "Forgot password?" }) }),
1852
+ /* @__PURE__ */ jsx29(
1853
+ Button6,
1854
+ {
1855
+ size: "$5",
1856
+ backgroundColor: "$color9",
1857
+ color: "$color1",
1858
+ borderRadius: "$5",
1859
+ disabled: loading,
1860
+ onPress: () => onEmailSubmit?.(email, password),
1861
+ hoverStyle: { backgroundColor: "$color10" },
1862
+ pressStyle: { backgroundColor: "$color8" },
1863
+ icon: loading ? /* @__PURE__ */ jsx29(Spinner, { size: "small", color: "$color1" }) : void 0,
1864
+ children: "Sign In"
1865
+ }
1866
+ ),
1867
+ onCreateAccount && /* @__PURE__ */ jsx29(Button6, { size: "$3", chromeless: true, onPress: onCreateAccount, children: /* @__PURE__ */ jsx29(SizableText25, { size: "$3", color: "$color9", children: "Create Account" }) })
1868
+ ] }),
1869
+ (onTerms || onPrivacy) && /* @__PURE__ */ jsx29(YStack22, { paddingTop: "$2", alignItems: "center", children: /* @__PURE__ */ jsxs22(SizableText25, { size: "$2", color: "$color8", textAlign: "center", children: [
1870
+ "By continuing you agree to our",
1871
+ " ",
1872
+ onTerms && /* @__PURE__ */ jsx29(SizableText25, { size: "$2", color: "$color9", onPress: onTerms, children: "Terms of Service" }),
1873
+ onTerms && onPrivacy && " & ",
1874
+ onPrivacy && /* @__PURE__ */ jsx29(SizableText25, { size: "$2", color: "$color9", onPress: onPrivacy, children: "Privacy Policy" })
1875
+ ] }) }),
1876
+ footerSlot
1877
+ ]
1878
+ }
1879
+ )
1311
1880
  ] });
1312
1881
  }
1313
1882
 
1314
1883
  // src/patterns/TabBar.tsx
1315
- import { SizableText as SizableText26, XStack as XStack17, YStack as YStack23 } from "tamagui";
1316
- import { jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
1884
+ import { SizableText as SizableText26, XStack as XStack18, YStack as YStack23 } from "tamagui";
1885
+ import { jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
1317
1886
  function TabBar({ tabs, activeTab, onTabPress, showLabels = true }) {
1318
- return /* @__PURE__ */ jsx29(XStack17, { height: 56, borderTopWidth: 1, borderTopColor: "$borderColor", backgroundColor: "$background", paddingBottom: "$2", children: tabs.map((tab) => {
1887
+ return /* @__PURE__ */ jsx30(XStack18, { height: 56, borderTopWidth: 1, borderTopColor: "$borderColor", backgroundColor: "$background", paddingBottom: "$2", children: tabs.map((tab) => {
1319
1888
  const active = tab.id === activeTab;
1320
- return /* @__PURE__ */ jsxs22(
1889
+ return /* @__PURE__ */ jsxs23(
1321
1890
  YStack23,
1322
1891
  {
1323
1892
  flex: 1,
@@ -1327,8 +1896,8 @@ function TabBar({ tabs, activeTab, onTabPress, showLabels = true }) {
1327
1896
  pressStyle: { opacity: 0.6 },
1328
1897
  onPress: () => onTabPress(tab.id),
1329
1898
  children: [
1330
- tab.icon && /* @__PURE__ */ jsx29(SizableText26, { size: "$5", color: active ? "$color9" : "$color8", children: tab.icon }),
1331
- showLabels && /* @__PURE__ */ jsx29(SizableText26, { size: "$1", color: active ? "$color9" : "$color8", fontWeight: active ? "600" : "400", children: tab.label })
1899
+ tab.icon && /* @__PURE__ */ jsx30(SizableText26, { size: "$5", color: active ? "$color9" : "$color8", children: tab.icon }),
1900
+ showLabels && /* @__PURE__ */ jsx30(SizableText26, { size: "$1", color: active ? "$color9" : "$color8", fontWeight: active ? "600" : "400", children: tab.label })
1332
1901
  ]
1333
1902
  },
1334
1903
  tab.id
@@ -1337,12 +1906,12 @@ function TabBar({ tabs, activeTab, onTabPress, showLabels = true }) {
1337
1906
  }
1338
1907
 
1339
1908
  // src/patterns/SearchBar.tsx
1340
- import { Input as Input2, SizableText as SizableText27, XStack as XStack18 } from "tamagui";
1341
- import { jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
1909
+ import { Input as Input2, SizableText as SizableText27, XStack as XStack19 } from "tamagui";
1910
+ import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1342
1911
  function SearchBar({ value, onChangeText, placeholder = "Search\u2026", onFilter, onCancel, autoFocus }) {
1343
- return /* @__PURE__ */ jsxs23(XStack18, { height: 44, borderRadius: "$10", backgroundColor: "$color2", alignItems: "center", paddingHorizontal: "$3", gap: "$2", children: [
1344
- /* @__PURE__ */ jsx30(SizableText27, { size: "$4", color: "$color8", children: "\u2315" }),
1345
- /* @__PURE__ */ jsx30(
1912
+ return /* @__PURE__ */ jsxs24(XStack19, { height: 44, borderRadius: "$10", backgroundColor: "$color2", alignItems: "center", paddingHorizontal: "$3", gap: "$2", children: [
1913
+ /* @__PURE__ */ jsx31(SizableText27, { size: "$4", color: "$color8", children: "\u2315" }),
1914
+ /* @__PURE__ */ jsx31(
1346
1915
  Input2,
1347
1916
  {
1348
1917
  flex: 1,
@@ -1356,14 +1925,14 @@ function SearchBar({ value, onChangeText, placeholder = "Search\u2026", onFilter
1356
1925
  autoFocus
1357
1926
  }
1358
1927
  ),
1359
- onFilter && /* @__PURE__ */ jsx30(SizableText27, { size: "$4", color: "$color9", pressStyle: { opacity: 0.6 }, onPress: onFilter, children: "\u2ACF" }),
1360
- onCancel && /* @__PURE__ */ jsx30(SizableText27, { size: "$3", color: "$color9", pressStyle: { opacity: 0.6 }, onPress: onCancel, children: "Cancel" })
1928
+ onFilter && /* @__PURE__ */ jsx31(SizableText27, { size: "$4", color: "$color9", pressStyle: { opacity: 0.6 }, onPress: onFilter, children: "\u2ACF" }),
1929
+ onCancel && /* @__PURE__ */ jsx31(SizableText27, { size: "$3", color: "$color9", pressStyle: { opacity: 0.6 }, onPress: onCancel, children: "Cancel" })
1361
1930
  ] });
1362
1931
  }
1363
1932
 
1364
1933
  // src/patterns/FloatingActionButton.tsx
1365
- import { SizableText as SizableText28, XStack as XStack19 } from "tamagui";
1366
- import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
1934
+ import { SizableText as SizableText28, XStack as XStack20 } from "tamagui";
1935
+ import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1367
1936
  var sizes = { sm: 44, md: 56, lg: 68 };
1368
1937
  var positionStyles = {
1369
1938
  "bottom-right": { right: 20 },
@@ -1372,8 +1941,8 @@ var positionStyles = {
1372
1941
  };
1373
1942
  function FloatingActionButton({ icon, label, onPress, position = "bottom-right", size = "md" }) {
1374
1943
  const dim = sizes[size];
1375
- return /* @__PURE__ */ jsxs24(
1376
- XStack19,
1944
+ return /* @__PURE__ */ jsxs25(
1945
+ XStack20,
1377
1946
  {
1378
1947
  position: "absolute",
1379
1948
  bottom: 32,
@@ -1390,91 +1959,104 @@ function FloatingActionButton({ icon, label, onPress, position = "bottom-right",
1390
1959
  pressStyle: { scale: 0.95, opacity: 0.9 },
1391
1960
  onPress,
1392
1961
  children: [
1393
- icon && /* @__PURE__ */ jsx31(SizableText28, { color: "$color1", children: icon }),
1394
- label && /* @__PURE__ */ jsx31(SizableText28, { color: "$color1", size: "$4", fontWeight: "600", children: label })
1962
+ icon && /* @__PURE__ */ jsx32(SizableText28, { color: "$color1", children: icon }),
1963
+ label && /* @__PURE__ */ jsx32(SizableText28, { color: "$color1", size: "$4", fontWeight: "600", children: label })
1395
1964
  ]
1396
1965
  }
1397
1966
  );
1398
1967
  }
1399
1968
 
1400
1969
  // src/patterns/ActionSheet.tsx
1401
- import { Sheet as Sheet2, SizableText as SizableText29, XStack as XStack20, YStack as YStack24 } from "tamagui";
1402
- import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
1403
- function ActionSheet({ open, onOpenChange, title, items, onSelect, cancelLabel = "Cancel" }) {
1404
- return /* @__PURE__ */ jsxs25(Sheet2, { modal: true, open, onOpenChange, snapPoints: [50], dismissOnSnapToBottom: true, animation: "medium", children: [
1405
- /* @__PURE__ */ jsx32(Sheet2.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1406
- /* @__PURE__ */ jsx32(Sheet2.Handle, {}),
1407
- /* @__PURE__ */ jsxs25(Sheet2.Frame, { borderTopLeftRadius: "$6", borderTopRightRadius: "$6", backgroundColor: "$background", children: [
1408
- title && /* @__PURE__ */ jsx32(SizableText29, { size: "$3", color: "$color8", textAlign: "center", paddingTop: "$3", paddingBottom: "$1", children: title }),
1409
- /* @__PURE__ */ jsx32(YStack24, { paddingHorizontal: "$3", paddingTop: "$2", children: items.map((item) => /* @__PURE__ */ jsxs25(
1410
- XStack20,
1411
- {
1412
- height: 52,
1413
- alignItems: "center",
1414
- gap: "$3",
1415
- paddingHorizontal: "$3",
1416
- borderRadius: "$4",
1417
- pressStyle: { backgroundColor: "$color3" },
1418
- onPress: () => {
1419
- onSelect(item.id);
1420
- onOpenChange(false);
1421
- },
1422
- children: [
1423
- item.icon && /* @__PURE__ */ jsx32(SizableText29, { size: "$5", children: item.icon }),
1424
- /* @__PURE__ */ jsx32(
1425
- SizableText29,
1426
- {
1427
- size: "$5",
1428
- flex: 1,
1429
- color: item.destructive ? "$red9" : "$color12",
1430
- fontWeight: item.destructive ? "600" : "400",
1431
- children: item.label
1432
- }
1433
- )
1434
- ]
1435
- },
1436
- item.id
1437
- )) }),
1438
- /* @__PURE__ */ jsx32(YStack24, { paddingHorizontal: "$3", paddingVertical: "$3", borderTopWidth: 1, borderTopColor: "$borderColor", marginTop: "$2", children: /* @__PURE__ */ jsx32(
1439
- XStack20,
1440
- {
1441
- height: 48,
1442
- alignItems: "center",
1443
- justifyContent: "center",
1444
- borderRadius: "$4",
1445
- pressStyle: { backgroundColor: "$color3" },
1446
- onPress: () => onOpenChange(false),
1447
- children: /* @__PURE__ */ jsx32(SizableText29, { size: "$5", fontWeight: "600", color: "$color9", children: cancelLabel })
1448
- }
1449
- ) })
1450
- ] })
1451
- ] });
1970
+ import { Sheet as Sheet2, SizableText as SizableText29, XStack as XStack21, YStack as YStack24 } from "tamagui";
1971
+ import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
1972
+ function ActionSheet({ open, onOpenChange, title, items, onSelect, cancelLabel = "Cancel", zIndex = 1e5 }) {
1973
+ return /* @__PURE__ */ jsxs26(
1974
+ Sheet2,
1975
+ {
1976
+ modal: true,
1977
+ forceRemoveScrollEnabled: open,
1978
+ open,
1979
+ onOpenChange,
1980
+ snapPoints: [50],
1981
+ dismissOnSnapToBottom: true,
1982
+ zIndex,
1983
+ animation: "medium",
1984
+ children: [
1985
+ /* @__PURE__ */ jsx33(Sheet2.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1986
+ /* @__PURE__ */ jsx33(Sheet2.Handle, {}),
1987
+ /* @__PURE__ */ jsxs26(Sheet2.Frame, { children: [
1988
+ title && /* @__PURE__ */ jsx33(SizableText29, { size: "$3", color: "$color8", textAlign: "center", paddingTop: "$3", paddingBottom: "$1", children: title }),
1989
+ /* @__PURE__ */ jsx33(YStack24, { paddingHorizontal: "$3", paddingTop: "$2", children: items.map((item) => /* @__PURE__ */ jsxs26(
1990
+ XStack21,
1991
+ {
1992
+ height: 52,
1993
+ alignItems: "center",
1994
+ gap: "$3",
1995
+ paddingHorizontal: "$3",
1996
+ borderRadius: "$4",
1997
+ pressStyle: { backgroundColor: "$color3" },
1998
+ onPress: () => {
1999
+ onSelect(item.id);
2000
+ onOpenChange(false);
2001
+ },
2002
+ children: [
2003
+ item.icon && /* @__PURE__ */ jsx33(SizableText29, { size: "$5", children: item.icon }),
2004
+ /* @__PURE__ */ jsx33(
2005
+ SizableText29,
2006
+ {
2007
+ size: "$5",
2008
+ flex: 1,
2009
+ color: item.destructive ? "$red9" : "$color12",
2010
+ fontWeight: item.destructive ? "600" : "400",
2011
+ children: item.label
2012
+ }
2013
+ )
2014
+ ]
2015
+ },
2016
+ item.id
2017
+ )) }),
2018
+ /* @__PURE__ */ jsx33(YStack24, { paddingHorizontal: "$3", paddingVertical: "$3", borderTopWidth: 1, borderTopColor: "$borderColor", marginTop: "$2", children: /* @__PURE__ */ jsx33(
2019
+ XStack21,
2020
+ {
2021
+ height: 48,
2022
+ alignItems: "center",
2023
+ justifyContent: "center",
2024
+ borderRadius: "$4",
2025
+ pressStyle: { backgroundColor: "$color3" },
2026
+ onPress: () => onOpenChange(false),
2027
+ children: /* @__PURE__ */ jsx33(SizableText29, { size: "$5", fontWeight: "600", color: "$color9", children: cancelLabel })
2028
+ }
2029
+ ) })
2030
+ ] })
2031
+ ]
2032
+ }
2033
+ );
1452
2034
  }
1453
2035
 
1454
2036
  // src/patterns/Skeleton.tsx
1455
2037
  import { YStack as YStack25 } from "tamagui";
1456
- import { jsx as jsx33 } from "react/jsx-runtime";
2038
+ import { jsx as jsx34 } from "react/jsx-runtime";
1457
2039
  function Skeleton({ width, height, borderRadius, variant = "rectangular" }) {
1458
2040
  const size = variant === "circular" ? height ?? 40 : height;
1459
2041
  const w = variant === "text" ? width ?? "100%" : width;
1460
2042
  const h = variant === "text" ? height ?? 16 : size;
1461
2043
  const r = variant === "circular" ? 9999 : borderRadius ?? 8;
1462
- return /* @__PURE__ */ jsx33(YStack25, { width: w, height: h, borderRadius: r, backgroundColor: "$color3", opacity: 0.6, animation: "slow", enterStyle: { opacity: 0.3 }, exitStyle: { opacity: 0.3 } });
2044
+ return /* @__PURE__ */ jsx34(YStack25, { width: w, height: h, borderRadius: r, backgroundColor: "$color3", opacity: 0.6, animation: "slow", enterStyle: { opacity: 0.3 }, exitStyle: { opacity: 0.3 } });
1463
2045
  }
1464
2046
 
1465
2047
  // src/patterns/NotificationBanner.tsx
1466
- import { SizableText as SizableText30, XStack as XStack21, YStack as YStack26 } from "tamagui";
1467
- import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
1468
- var variantColors2 = {
1469
- info: { bg: "$blue3", text: "$blue11" },
2048
+ import { SizableText as SizableText30, XStack as XStack22, YStack as YStack26 } from "tamagui";
2049
+ import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2050
+ var variantColors = {
2051
+ info: { bg: "$blue3", text: "$blue11" },
1470
2052
  success: { bg: "$green3", text: "$green11" },
1471
2053
  warning: { bg: "$yellow3", text: "$yellow11" },
1472
2054
  error: { bg: "$red3", text: "$red11" }
1473
2055
  };
1474
2056
  function NotificationBanner({ title, message, variant = "info", onPress, onDismiss, icon }) {
1475
- const colors = variantColors2[variant];
1476
- return /* @__PURE__ */ jsxs26(
1477
- XStack21,
2057
+ const colors = variantColors[variant];
2058
+ return /* @__PURE__ */ jsxs27(
2059
+ XStack22,
1478
2060
  {
1479
2061
  backgroundColor: colors.bg,
1480
2062
  padding: "$3",
@@ -1484,48 +2066,48 @@ function NotificationBanner({ title, message, variant = "info", onPress, onDismi
1484
2066
  onPress,
1485
2067
  pressStyle: onPress ? { opacity: 0.8 } : void 0,
1486
2068
  children: [
1487
- icon && /* @__PURE__ */ jsx34(YStack26, { paddingTop: "$0.5", children: icon }),
1488
- /* @__PURE__ */ jsxs26(YStack26, { flex: 1, gap: "$1", children: [
1489
- /* @__PURE__ */ jsx34(SizableText30, { size: "$4", fontWeight: "600", color: colors.text, children: title }),
1490
- message && /* @__PURE__ */ jsx34(SizableText30, { size: "$3", color: colors.text, opacity: 0.8, children: message })
2069
+ icon && /* @__PURE__ */ jsx35(YStack26, { paddingTop: "$0.5", children: icon }),
2070
+ /* @__PURE__ */ jsxs27(YStack26, { flex: 1, gap: "$1", children: [
2071
+ /* @__PURE__ */ jsx35(SizableText30, { size: "$4", fontWeight: "600", color: colors.text, children: title }),
2072
+ message && /* @__PURE__ */ jsx35(SizableText30, { size: "$3", color: colors.text, opacity: 0.8, children: message })
1491
2073
  ] }),
1492
- onDismiss && /* @__PURE__ */ jsx34(SizableText30, { size: "$3", color: colors.text, opacity: 0.6, onPress: onDismiss, padding: "$1", children: "\u2715" })
2074
+ onDismiss && /* @__PURE__ */ jsx35(SizableText30, { size: "$3", color: colors.text, opacity: 0.6, onPress: onDismiss, padding: "$1", children: "\u2715" })
1493
2075
  ]
1494
2076
  }
1495
2077
  );
1496
2078
  }
1497
2079
 
1498
2080
  // src/patterns/ProgressSteps.tsx
1499
- import { Circle as Circle6, SizableText as SizableText31, XStack as XStack22, YStack as YStack27 } from "tamagui";
1500
- import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2081
+ import { Circle as Circle7, SizableText as SizableText31, XStack as XStack23, YStack as YStack27 } from "tamagui";
2082
+ import { jsx as jsx36, jsxs as jsxs28 } from "react/jsx-runtime";
1501
2083
  function ProgressSteps({ steps, currentStep, variant = "dots" }) {
1502
2084
  if (variant === "bar") {
1503
2085
  const progress = steps.length > 1 ? currentStep / (steps.length - 1) * 100 : 100;
1504
- return /* @__PURE__ */ jsxs27(YStack27, { gap: "$2", children: [
1505
- /* @__PURE__ */ jsx35(YStack27, { height: 4, backgroundColor: "$color4", borderRadius: 2, overflow: "hidden", children: /* @__PURE__ */ jsx35(YStack27, { height: 4, width: `${progress}%`, backgroundColor: "$color9", borderRadius: 2, animation: "quick" }) }),
1506
- /* @__PURE__ */ jsx35(XStack22, { justifyContent: "space-between", children: steps.map((label, i) => /* @__PURE__ */ jsx35(SizableText31, { size: "$2", color: i <= currentStep ? "$color9" : "$color8", children: label }, i)) })
2086
+ return /* @__PURE__ */ jsxs28(YStack27, { gap: "$2", children: [
2087
+ /* @__PURE__ */ jsx36(YStack27, { height: 4, backgroundColor: "$color4", borderRadius: 2, overflow: "hidden", children: /* @__PURE__ */ jsx36(YStack27, { height: 4, width: `${progress}%`, backgroundColor: "$color9", borderRadius: 2, animation: "quick" }) }),
2088
+ /* @__PURE__ */ jsx36(XStack23, { justifyContent: "space-between", children: steps.map((label, i) => /* @__PURE__ */ jsx36(SizableText31, { size: "$2", color: i <= currentStep ? "$color9" : "$color8", children: label }, i)) })
1507
2089
  ] });
1508
2090
  }
1509
- return /* @__PURE__ */ jsx35(XStack22, { alignItems: "center", justifyContent: "center", gap: "$0", children: steps.map((label, i) => /* @__PURE__ */ jsxs27(XStack22, { alignItems: "center", gap: "$0", children: [
1510
- /* @__PURE__ */ jsxs27(YStack27, { alignItems: "center", gap: "$1.5", children: [
1511
- /* @__PURE__ */ jsx35(Circle6, { 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 }) }),
1512
- /* @__PURE__ */ jsx35(SizableText31, { size: "$1", color: i <= currentStep ? "$color11" : "$color8", numberOfLines: 1, children: label })
2091
+ return /* @__PURE__ */ jsx36(XStack23, { alignItems: "center", justifyContent: "center", gap: "$0", children: steps.map((label, i) => /* @__PURE__ */ jsxs28(XStack23, { alignItems: "center", gap: "$0", children: [
2092
+ /* @__PURE__ */ jsxs28(YStack27, { alignItems: "center", gap: "$1.5", children: [
2093
+ /* @__PURE__ */ jsx36(Circle7, { size: variant === "numbered" ? 28 : 10, backgroundColor: i <= currentStep ? "$color9" : "$color4", animation: "quick", children: variant === "numbered" && /* @__PURE__ */ jsx36(SizableText31, { size: "$2", fontWeight: "600", color: i <= currentStep ? "$color1" : "$color8", children: i + 1 }) }),
2094
+ /* @__PURE__ */ jsx36(SizableText31, { size: "$1", color: i <= currentStep ? "$color11" : "$color8", numberOfLines: 1, children: label })
1513
2095
  ] }),
1514
- i < steps.length - 1 && /* @__PURE__ */ jsx35(YStack27, { height: 2, width: 32, backgroundColor: i < currentStep ? "$color9" : "$color4", marginBottom: "$4" })
2096
+ i < steps.length - 1 && /* @__PURE__ */ jsx36(YStack27, { height: 2, width: 32, backgroundColor: i < currentStep ? "$color9" : "$color4", marginBottom: "$4" })
1515
2097
  ] }, i)) });
1516
2098
  }
1517
2099
 
1518
2100
  // src/patterns/SwipeableRow.tsx
1519
- import { useState as useState7 } from "react";
1520
- import { Button as Button7, SizableText as SizableText32, XStack as XStack23, YStack as YStack28 } from "tamagui";
1521
- import { Fragment as Fragment2, jsx as jsx36, jsxs as jsxs28 } from "react/jsx-runtime";
2101
+ import { useState as useState8 } from "react";
2102
+ import { Button as Button7, SizableText as SizableText32, XStack as XStack24, YStack as YStack28 } from "tamagui";
2103
+ import { Fragment as Fragment3, jsx as jsx37, jsxs as jsxs29 } from "react/jsx-runtime";
1522
2104
  function SwipeableRow({ children, leftActions, rightActions }) {
1523
- const [showActions, setShowActions] = useState7(false);
2105
+ const [showActions, setShowActions] = useState8(false);
1524
2106
  const actions = [...leftActions ?? [], ...rightActions ?? []];
1525
- if (actions.length === 0) return /* @__PURE__ */ jsx36(Fragment2, { children });
1526
- return /* @__PURE__ */ jsxs28(YStack28, { children: [
1527
- /* @__PURE__ */ jsx36(YStack28, { onLongPress: () => setShowActions((v) => !v), pressStyle: { opacity: 0.9 }, children }),
1528
- showActions && /* @__PURE__ */ jsx36(XStack23, { gap: "$2", padding: "$2", animation: "quick", enterStyle: { opacity: 0, scale: 0.95 }, children: actions.map((action) => /* @__PURE__ */ jsx36(
2107
+ if (actions.length === 0) return /* @__PURE__ */ jsx37(Fragment3, { children });
2108
+ return /* @__PURE__ */ jsxs29(YStack28, { children: [
2109
+ /* @__PURE__ */ jsx37(YStack28, { onLongPress: () => setShowActions((v) => !v), pressStyle: { opacity: 0.9 }, children }),
2110
+ showActions && /* @__PURE__ */ jsx37(XStack24, { gap: "$2", padding: "$2", animation: "quick", enterStyle: { opacity: 0, scale: 0.95 }, children: actions.map((action) => /* @__PURE__ */ jsx37(
1529
2111
  Button7,
1530
2112
  {
1531
2113
  flex: 1,
@@ -1536,7 +2118,7 @@ function SwipeableRow({ children, leftActions, rightActions }) {
1536
2118
  action.onPress();
1537
2119
  setShowActions(false);
1538
2120
  },
1539
- children: /* @__PURE__ */ jsx36(SizableText32, { size: "$2", fontWeight: "600", color: "white", children: action.label })
2121
+ children: /* @__PURE__ */ jsx37(SizableText32, { size: "$2", fontWeight: "600", color: "white", children: action.label })
1540
2122
  },
1541
2123
  action.id
1542
2124
  )) })
@@ -1544,11 +2126,11 @@ function SwipeableRow({ children, leftActions, rightActions }) {
1544
2126
  }
1545
2127
 
1546
2128
  // src/patterns/MediaCard.tsx
1547
- import { Image as Image5, SizableText as SizableText33, XStack as XStack24, YStack as YStack29 } from "tamagui";
2129
+ import { Image as Image5, SizableText as SizableText33, XStack as XStack25, YStack as YStack29 } from "tamagui";
1548
2130
  import { LinearGradient } from "tamagui/linear-gradient";
1549
- import { jsx as jsx37, jsxs as jsxs29 } from "react/jsx-runtime";
2131
+ import { jsx as jsx38, jsxs as jsxs30 } from "react/jsx-runtime";
1550
2132
  function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio = 16 / 9, onPress, badge }) {
1551
- return /* @__PURE__ */ jsx37(
2133
+ return /* @__PURE__ */ jsx38(
1552
2134
  YStack29,
1553
2135
  {
1554
2136
  borderRadius: "$4",
@@ -1556,9 +2138,9 @@ function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio =
1556
2138
  onPress,
1557
2139
  pressStyle: onPress ? { scale: 0.98, opacity: 0.9 } : void 0,
1558
2140
  animation: "quick",
1559
- children: /* @__PURE__ */ jsxs29(YStack29, { aspectRatio, children: [
1560
- /* @__PURE__ */ jsx37(Image5, { source: { uri: image }, width: "100%", height: "100%", objectFit: "cover" }),
1561
- overlay === "gradient" && /* @__PURE__ */ jsx37(
2141
+ children: /* @__PURE__ */ jsxs30(YStack29, { aspectRatio, children: [
2142
+ /* @__PURE__ */ jsx38(Image5, { source: { uri: image }, width: "100%", height: "100%", objectFit: "cover" }),
2143
+ overlay === "gradient" && /* @__PURE__ */ jsx38(
1562
2144
  LinearGradient,
1563
2145
  {
1564
2146
  colors: ["transparent", "rgba(0,0,0,0.7)"],
@@ -1571,9 +2153,9 @@ function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio =
1571
2153
  height: "60%"
1572
2154
  }
1573
2155
  ),
1574
- overlay === "dark" && /* @__PURE__ */ jsx37(YStack29, { position: "absolute", fullscreen: true, backgroundColor: "rgba(0,0,0,0.4)" }),
1575
- badge && /* @__PURE__ */ jsx37(
1576
- XStack24,
2156
+ overlay === "dark" && /* @__PURE__ */ jsx38(YStack29, { position: "absolute", fullscreen: true, backgroundColor: "rgba(0,0,0,0.4)" }),
2157
+ badge && /* @__PURE__ */ jsx38(
2158
+ XStack25,
1577
2159
  {
1578
2160
  position: "absolute",
1579
2161
  top: "$2",
@@ -1582,12 +2164,12 @@ function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio =
1582
2164
  paddingHorizontal: "$2",
1583
2165
  paddingVertical: "$1",
1584
2166
  borderRadius: "$2",
1585
- children: /* @__PURE__ */ jsx37(SizableText33, { size: "$1", fontWeight: "600", color: "$color1", children: badge })
2167
+ children: /* @__PURE__ */ jsx38(SizableText33, { size: "$1", fontWeight: "600", color: "$color1", children: badge })
1586
2168
  }
1587
2169
  ),
1588
- /* @__PURE__ */ jsxs29(YStack29, { position: "absolute", bottom: 0, left: 0, right: 0, padding: "$3", gap: "$1", children: [
1589
- /* @__PURE__ */ jsx37(SizableText33, { size: "$5", fontWeight: "600", color: "white", children: title }),
1590
- subtitle && /* @__PURE__ */ jsx37(SizableText33, { size: "$3", color: "rgba(255,255,255,0.8)", children: subtitle })
2170
+ /* @__PURE__ */ jsxs30(YStack29, { position: "absolute", bottom: 0, left: 0, right: 0, padding: "$3", gap: "$1", children: [
2171
+ /* @__PURE__ */ jsx38(SizableText33, { size: "$5", fontWeight: "600", color: "white", children: title }),
2172
+ subtitle && /* @__PURE__ */ jsx38(SizableText33, { size: "$3", color: "rgba(255,255,255,0.8)", children: subtitle })
1591
2173
  ] })
1592
2174
  ] })
1593
2175
  }
@@ -1595,17 +2177,17 @@ function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio =
1595
2177
  }
1596
2178
 
1597
2179
  // src/patterns/Carousel.tsx
1598
- import { Children as Children2, useState as useState8 } from "react";
1599
- import { Circle as Circle7, XStack as XStack25, YStack as YStack30 } from "tamagui";
1600
- import { ScrollView as ScrollView3 } from "react-native";
1601
- import { jsx as jsx38, jsxs as jsxs30 } from "react/jsx-runtime";
2180
+ import { Children as Children2, useState as useState9 } from "react";
2181
+ import { Circle as Circle8, XStack as XStack26, YStack as YStack30 } from "tamagui";
2182
+ import { ScrollView as ScrollView4 } from "react-native";
2183
+ import { jsx as jsx39, jsxs as jsxs31 } from "react/jsx-runtime";
1602
2184
  function Carousel({ children, gap = "$3", snapToInterval, showIndicators = false }) {
1603
- const [activeIndex, setActiveIndex] = useState8(0);
2185
+ const [activeIndex, setActiveIndex] = useState9(0);
1604
2186
  const count = Children2.count(children);
1605
2187
  const gapPx = gap === "$2" ? 8 : gap === "$3" ? 12 : 16;
1606
- return /* @__PURE__ */ jsxs30(YStack30, { gap: "$3", children: [
1607
- /* @__PURE__ */ jsx38(
1608
- ScrollView3,
2188
+ return /* @__PURE__ */ jsxs31(YStack30, { gap: "$3", children: [
2189
+ /* @__PURE__ */ jsx39(
2190
+ ScrollView4,
1609
2191
  {
1610
2192
  horizontal: true,
1611
2193
  showsHorizontalScrollIndicator: false,
@@ -1618,84 +2200,1715 @@ function Carousel({ children, gap = "$3", snapToInterval, showIndicators = false
1618
2200
  children
1619
2201
  }
1620
2202
  ),
1621
- showIndicators && count > 1 && /* @__PURE__ */ jsx38(XStack25, { justifyContent: "center", gap: "$1.5", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx38(Circle7, { size: 6, backgroundColor: i === activeIndex ? "$color9" : "$color4", animation: "quick" }, i)) })
2203
+ showIndicators && count > 1 && /* @__PURE__ */ jsx39(XStack26, { justifyContent: "center", gap: "$1.5", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx39(Circle8, { size: 6, backgroundColor: i === activeIndex ? "$color9" : "$color4", animation: "quick" }, i)) })
1622
2204
  ] });
1623
2205
  }
1624
2206
 
1625
2207
  // src/patterns/PullToRefresh.tsx
1626
2208
  import { YStack as YStack31 } from "tamagui";
1627
- import { RefreshControl, ScrollView as ScrollView4 } from "react-native";
1628
- import { jsx as jsx39 } from "react/jsx-runtime";
2209
+ import { RefreshControl, ScrollView as ScrollView5 } from "react-native";
2210
+ import { jsx as jsx40 } from "react/jsx-runtime";
1629
2211
  function PullToRefresh({ children, onRefresh, refreshing = false }) {
1630
- return /* @__PURE__ */ jsx39(
1631
- ScrollView4,
2212
+ return /* @__PURE__ */ jsx40(
2213
+ ScrollView5,
1632
2214
  {
1633
2215
  contentContainerStyle: { flexGrow: 1 },
1634
- refreshControl: /* @__PURE__ */ jsx39(RefreshControl, { refreshing, onRefresh }),
1635
- children: /* @__PURE__ */ jsx39(YStack31, { flex: 1, children })
2216
+ refreshControl: /* @__PURE__ */ jsx40(RefreshControl, { refreshing, onRefresh }),
2217
+ children: /* @__PURE__ */ jsx40(YStack31, { flex: 1, children })
2218
+ }
2219
+ );
2220
+ }
2221
+
2222
+ // src/patterns/ProductCard.tsx
2223
+ import { Button as Button8, Image as Image6, SizableText as SizableText34, XStack as XStack27, YStack as YStack32 } from "tamagui";
2224
+ import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
2225
+ function Stars({ rating = 0 }) {
2226
+ return /* @__PURE__ */ jsx41(XStack27, { gap: "$0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx41(SizableText34, { size: "$2", color: i < Math.round(rating) ? "$yellow9" : "$color5", children: "\u2605" }, i)) });
2227
+ }
2228
+ function CardContent2({ title, price, originalPrice, rating, reviewCount, onAddToCart }) {
2229
+ return /* @__PURE__ */ jsxs32(YStack32, { flex: 1, gap: "$1.5", justifyContent: "space-between", children: [
2230
+ /* @__PURE__ */ jsxs32(YStack32, { gap: "$1", children: [
2231
+ /* @__PURE__ */ jsx41(SizableText34, { size: "$4", fontWeight: "600", numberOfLines: 2, children: title }),
2232
+ rating !== void 0 && /* @__PURE__ */ jsxs32(XStack27, { gap: "$1.5", alignItems: "center", children: [
2233
+ /* @__PURE__ */ jsx41(Stars, { rating }),
2234
+ reviewCount !== void 0 && /* @__PURE__ */ jsxs32(SizableText34, { size: "$2", color: "$color9", children: [
2235
+ "(",
2236
+ reviewCount,
2237
+ ")"
2238
+ ] })
2239
+ ] })
2240
+ ] }),
2241
+ /* @__PURE__ */ jsxs32(XStack27, { alignItems: "center", justifyContent: "space-between", children: [
2242
+ /* @__PURE__ */ jsxs32(XStack27, { gap: "$2", alignItems: "baseline", children: [
2243
+ /* @__PURE__ */ jsx41(SizableText34, { size: "$6", fontWeight: "700", children: price }),
2244
+ originalPrice && /* @__PURE__ */ jsx41(SizableText34, { size: "$3", color: "$color8", textDecorationLine: "line-through", children: originalPrice })
2245
+ ] }),
2246
+ onAddToCart && /* @__PURE__ */ jsx41(
2247
+ Button8,
2248
+ {
2249
+ size: "$3",
2250
+ backgroundColor: "$color9",
2251
+ color: "$color1",
2252
+ borderRadius: "$10",
2253
+ onPress: (e) => {
2254
+ e.stopPropagation?.();
2255
+ onAddToCart();
2256
+ },
2257
+ pressStyle: { backgroundColor: "$color8", scale: 0.95 },
2258
+ animation: "quick",
2259
+ children: "+ Cart"
2260
+ }
2261
+ )
2262
+ ] })
2263
+ ] });
2264
+ }
2265
+ function ProductCard({ image, title, price, originalPrice, rating, reviewCount, badge, onPress, onAddToCart, variant = "vertical" }) {
2266
+ const isHorizontal = variant === "horizontal";
2267
+ const Wrapper = isHorizontal ? XStack27 : YStack32;
2268
+ return /* @__PURE__ */ jsxs32(
2269
+ Wrapper,
2270
+ {
2271
+ backgroundColor: "$color1",
2272
+ borderRadius: "$5",
2273
+ overflow: "hidden",
2274
+ borderWidth: 1,
2275
+ borderColor: "$color4",
2276
+ onPress,
2277
+ animation: "quick",
2278
+ pressStyle: onPress ? { scale: 0.98, opacity: 0.9 } : void 0,
2279
+ ...isHorizontal ? { height: 140 } : {},
2280
+ children: [
2281
+ /* @__PURE__ */ jsxs32(YStack32, { ...isHorizontal ? { width: 140 } : { aspectRatio: 4 / 3 }, position: "relative", children: [
2282
+ /* @__PURE__ */ jsx41(Image6, { source: { uri: image }, width: "100%", height: "100%", objectFit: "cover" }),
2283
+ badge && /* @__PURE__ */ jsx41(
2284
+ XStack27,
2285
+ {
2286
+ position: "absolute",
2287
+ top: "$2",
2288
+ left: "$2",
2289
+ backgroundColor: "$red9",
2290
+ paddingHorizontal: "$2",
2291
+ paddingVertical: "$1",
2292
+ borderRadius: "$10",
2293
+ children: /* @__PURE__ */ jsx41(SizableText34, { size: "$1", fontWeight: "700", color: "white", children: badge })
2294
+ }
2295
+ )
2296
+ ] }),
2297
+ /* @__PURE__ */ jsx41(YStack32, { flex: 1, padding: "$3", children: /* @__PURE__ */ jsx41(CardContent2, { ...{ title, price, originalPrice, rating, reviewCount, onAddToCart } }) })
2298
+ ]
2299
+ }
2300
+ );
2301
+ }
2302
+
2303
+ // src/patterns/PricingTable.tsx
2304
+ import { Button as Button9, Circle as Circle9, SizableText as SizableText35, XStack as XStack28, YStack as YStack33 } from "tamagui";
2305
+ import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
2306
+ function BillingToggle({ annual, onToggle }) {
2307
+ return /* @__PURE__ */ jsx42(XStack28, { alignSelf: "center", backgroundColor: "$color3", borderRadius: "$10", padding: "$1", gap: "$0.5", children: ["Monthly", "Annual"].map((label, i) => {
2308
+ const active = i === 1 ? annual : !annual;
2309
+ return /* @__PURE__ */ jsx42(
2310
+ XStack28,
2311
+ {
2312
+ paddingHorizontal: "$4",
2313
+ paddingVertical: "$2",
2314
+ borderRadius: "$10",
2315
+ backgroundColor: active ? "$color9" : "transparent",
2316
+ onPress: () => onToggle(i === 1),
2317
+ pressStyle: { opacity: 0.8 },
2318
+ animation: "quick",
2319
+ children: /* @__PURE__ */ jsx42(SizableText35, { size: "$3", fontWeight: "600", color: active ? "$color1" : "$color10", children: label })
2320
+ },
2321
+ label
2322
+ );
2323
+ }) });
2324
+ }
2325
+ function PlanRow2({ plan, selected, onSelect }) {
2326
+ return /* @__PURE__ */ jsxs33(
2327
+ XStack28,
2328
+ {
2329
+ padding: "$4",
2330
+ borderRadius: "$6",
2331
+ borderWidth: 2,
2332
+ borderColor: selected ? "$color9" : "$color4",
2333
+ backgroundColor: selected ? "$color2" : "$color1",
2334
+ alignItems: "center",
2335
+ gap: "$3",
2336
+ onPress: onSelect,
2337
+ pressStyle: { scale: 0.98, opacity: 0.9 },
2338
+ animation: "quick",
2339
+ cursor: "pointer",
2340
+ position: "relative",
2341
+ children: [
2342
+ plan.popular && /* @__PURE__ */ jsx42(XStack28, { position: "absolute", top: -10, right: 12, backgroundColor: "$color9", paddingHorizontal: "$2.5", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ jsx42(SizableText35, { size: "$1", fontWeight: "700", color: "$color1", children: "BEST VALUE" }) }),
2343
+ /* @__PURE__ */ jsx42(
2344
+ Circle9,
2345
+ {
2346
+ size: 22,
2347
+ borderWidth: 2,
2348
+ borderColor: selected ? "$color9" : "$color6",
2349
+ backgroundColor: selected ? "$color9" : "transparent",
2350
+ children: selected && /* @__PURE__ */ jsx42(Circle9, { size: 8, backgroundColor: "$color1" })
2351
+ }
2352
+ ),
2353
+ /* @__PURE__ */ jsxs33(YStack33, { flex: 1, gap: "$0.5", children: [
2354
+ /* @__PURE__ */ jsxs33(XStack28, { alignItems: "center", gap: "$2", children: [
2355
+ /* @__PURE__ */ jsx42(SizableText35, { size: "$5", fontWeight: "700", children: plan.name }),
2356
+ plan.trial && /* @__PURE__ */ jsx42(XStack28, { backgroundColor: "$green3", paddingHorizontal: "$2", paddingVertical: 2, borderRadius: "$10", children: /* @__PURE__ */ jsx42(SizableText35, { size: "$1", fontWeight: "700", color: "$green9", children: plan.trial }) })
2357
+ ] }),
2358
+ plan.description && /* @__PURE__ */ jsx42(SizableText35, { size: "$2", color: "$color10", children: plan.description })
2359
+ ] }),
2360
+ /* @__PURE__ */ jsx42(SizableText35, { size: "$5", fontWeight: "800", children: plan.price })
2361
+ ]
2362
+ }
2363
+ );
2364
+ }
2365
+ function FeatureList({ features }) {
2366
+ return /* @__PURE__ */ jsx42(YStack33, { gap: "$2.5", paddingHorizontal: "$1", children: features.map((f, i) => /* @__PURE__ */ jsxs33(XStack28, { gap: "$2.5", alignItems: "center", children: [
2367
+ /* @__PURE__ */ jsx42(Circle9, { size: 20, backgroundColor: f.included ? "$green3" : "$color3", children: /* @__PURE__ */ jsx42(SizableText35, { size: "$1", fontWeight: "700", color: f.included ? "$green9" : "$color8", children: f.included ? "\u2713" : "\u2014" }) }),
2368
+ /* @__PURE__ */ jsx42(SizableText35, { size: "$3", color: f.included ? "$color11" : "$color8", flex: 1, children: f.label })
2369
+ ] }, i)) });
2370
+ }
2371
+ function PricingTable({ plans, selectedPlan, onSelectPlan, annual = false, onToggleBilling, onContinue, continueLabel, reassurance }) {
2372
+ const selected = selectedPlan ?? plans.find((p) => p.popular)?.id ?? plans[0]?.id;
2373
+ const activePlan = plans.find((p) => p.id === selected);
2374
+ return /* @__PURE__ */ jsxs33(YStack33, { gap: "$4", children: [
2375
+ onToggleBilling && /* @__PURE__ */ jsx42(BillingToggle, { annual, onToggle: onToggleBilling }),
2376
+ activePlan && activePlan.features.length > 0 && /* @__PURE__ */ jsx42(YStack33, { backgroundColor: "$color1", borderRadius: "$6", padding: "$4", gap: "$3", borderWidth: 1, borderColor: "$color4", children: /* @__PURE__ */ jsx42(FeatureList, { features: activePlan.features }) }),
2377
+ /* @__PURE__ */ jsx42(YStack33, { gap: "$3", children: plans.map((plan) => /* @__PURE__ */ jsx42(
2378
+ PlanRow2,
2379
+ {
2380
+ plan,
2381
+ selected: selected === plan.id,
2382
+ onSelect: () => onSelectPlan?.(plan.id)
2383
+ },
2384
+ plan.id
2385
+ )) }),
2386
+ reassurance && /* @__PURE__ */ jsx42(SizableText35, { size: "$2", color: "$color10", textAlign: "center", children: reassurance }),
2387
+ onContinue && /* @__PURE__ */ jsx42(
2388
+ Button9,
2389
+ {
2390
+ size: "$5",
2391
+ backgroundColor: "$color9",
2392
+ color: "$color1",
2393
+ borderRadius: "$10",
2394
+ fontWeight: "700",
2395
+ onPress: onContinue,
2396
+ pressStyle: { scale: 0.97, backgroundColor: "$color8" },
2397
+ animation: "quick",
2398
+ children: continueLabel ?? activePlan?.cta ?? "Get Started"
2399
+ }
2400
+ )
2401
+ ] });
2402
+ }
2403
+
2404
+ // src/patterns/CountdownBanner.tsx
2405
+ import { useState as useState10, useEffect as useEffect4, useRef, useCallback as useCallback2 } from "react";
2406
+ import { SizableText as SizableText36, XStack as XStack29, YStack as YStack34 } from "tamagui";
2407
+ import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
2408
+ function useCountdown2(endTime, minutes, onExpire) {
2409
+ const getRemaining = useCallback2(() => {
2410
+ if (endTime) return Math.max(0, Math.floor((endTime.getTime() - Date.now()) / 1e3));
2411
+ return 0;
2412
+ }, [endTime]);
2413
+ const [seconds, setSeconds] = useState10(() => endTime ? getRemaining() : (minutes ?? 0) * 60);
2414
+ const firedRef = useRef(false);
2415
+ useEffect4(() => {
2416
+ if (endTime) setSeconds(getRemaining());
2417
+ else setSeconds((minutes ?? 0) * 60);
2418
+ firedRef.current = false;
2419
+ }, [endTime, minutes, getRemaining]);
2420
+ useEffect4(() => {
2421
+ if (seconds <= 0) return;
2422
+ const id = setInterval(() => {
2423
+ setSeconds((s) => {
2424
+ const next = endTime ? Math.max(0, Math.floor((endTime.getTime() - Date.now()) / 1e3)) : s - 1;
2425
+ if (next <= 0 && !firedRef.current) {
2426
+ firedRef.current = true;
2427
+ onExpire?.();
2428
+ }
2429
+ return Math.max(0, next);
2430
+ });
2431
+ }, 1e3);
2432
+ return () => clearInterval(id);
2433
+ }, [seconds > 0, endTime, onExpire]);
2434
+ const hh = String(Math.floor(seconds / 3600)).padStart(2, "0");
2435
+ const mm = String(Math.floor(seconds % 3600 / 60)).padStart(2, "0");
2436
+ const ss = String(seconds % 60).padStart(2, "0");
2437
+ const display = seconds >= 3600 ? `${hh}:${mm}:${ss}` : `${mm}:${ss}`;
2438
+ return { display, expired: seconds <= 0 };
2439
+ }
2440
+ function TimeBox({ value }) {
2441
+ return /* @__PURE__ */ jsx43(XStack29, { backgroundColor: "rgba(0,0,0,0.15)", paddingHorizontal: "$2", paddingVertical: "$1", borderRadius: "$3", children: /* @__PURE__ */ jsx43(SizableText36, { size: "$6", fontWeight: "800", color: "white", fontFamily: "$mono", children: value }) });
2442
+ }
2443
+ function CountdownBanner({ endTime, minutes, label = "Offer ends in", onExpire, variant = "banner" }) {
2444
+ const { display, expired } = useCountdown2(endTime, minutes, onExpire);
2445
+ if (expired) return null;
2446
+ const parts = display.split(":");
2447
+ if (variant === "badge") {
2448
+ return /* @__PURE__ */ jsxs34(XStack29, { backgroundColor: "$red9", paddingHorizontal: "$2.5", paddingVertical: "$1", borderRadius: "$10", gap: "$1.5", alignItems: "center", children: [
2449
+ /* @__PURE__ */ jsx43(SizableText36, { size: "$1", fontWeight: "600", color: "white", children: label }),
2450
+ /* @__PURE__ */ jsx43(SizableText36, { size: "$2", fontWeight: "800", color: "white", fontFamily: "$mono", children: display })
2451
+ ] });
2452
+ }
2453
+ if (variant === "compact") {
2454
+ return /* @__PURE__ */ jsxs34(XStack29, { backgroundColor: "$red3", paddingHorizontal: "$3", paddingVertical: "$2", borderRadius: "$4", gap: "$2", alignItems: "center", alignSelf: "center", children: [
2455
+ /* @__PURE__ */ jsx43(SizableText36, { size: "$3", fontWeight: "600", color: "$red9", children: label }),
2456
+ /* @__PURE__ */ jsx43(SizableText36, { size: "$5", fontWeight: "800", color: "$red9", fontFamily: "$mono", children: display })
2457
+ ] });
2458
+ }
2459
+ return /* @__PURE__ */ jsxs34(YStack34, { backgroundColor: "$red9", paddingVertical: "$3", paddingHorizontal: "$4", gap: "$1.5", alignItems: "center", children: [
2460
+ /* @__PURE__ */ jsx43(SizableText36, { size: "$3", fontWeight: "600", color: "white", opacity: 0.9, children: label }),
2461
+ /* @__PURE__ */ jsx43(XStack29, { gap: "$1.5", alignItems: "center", children: parts.map((p, i) => /* @__PURE__ */ jsxs34(XStack29, { gap: "$1.5", alignItems: "center", children: [
2462
+ i > 0 && /* @__PURE__ */ jsx43(SizableText36, { size: "$6", fontWeight: "800", color: "white", children: ":" }),
2463
+ /* @__PURE__ */ jsx43(TimeBox, { value: p })
2464
+ ] }, i)) })
2465
+ ] });
2466
+ }
2467
+
2468
+ // src/patterns/TestimonialCard.tsx
2469
+ import { Image as Image7, SizableText as SizableText37, XStack as XStack30, YStack as YStack35 } from "tamagui";
2470
+ import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
2471
+ function Stars2({ count = 0 }) {
2472
+ if (!count) return null;
2473
+ return /* @__PURE__ */ jsx44(XStack30, { gap: "$0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx44(SizableText37, { size: "$3", color: i < Math.round(count) ? "$yellow9" : "$color5", children: "\u2605" }, i)) });
2474
+ }
2475
+ function AuthorRow({ author, role, avatar }) {
2476
+ return /* @__PURE__ */ jsxs35(XStack30, { gap: "$2.5", alignItems: "center", children: [
2477
+ avatar && /* @__PURE__ */ jsx44(Image7, { source: { uri: avatar }, width: 36, height: 36, borderRadius: 18, objectFit: "cover" }),
2478
+ /* @__PURE__ */ jsxs35(YStack35, { children: [
2479
+ /* @__PURE__ */ jsx44(SizableText37, { size: "$3", fontWeight: "600", children: author }),
2480
+ role && /* @__PURE__ */ jsx44(SizableText37, { size: "$2", color: "$color9", children: role })
2481
+ ] })
2482
+ ] });
2483
+ }
2484
+ function TestimonialCard2({ quote, author, role, avatar, rating, variant = "card" }) {
2485
+ if (variant === "minimal") {
2486
+ return /* @__PURE__ */ jsxs35(YStack35, { gap: "$3", paddingVertical: "$2", children: [
2487
+ /* @__PURE__ */ jsx44(Stars2, { count: rating }),
2488
+ /* @__PURE__ */ jsxs35(SizableText37, { size: "$4", color: "$color11", fontStyle: "italic", lineHeight: 24, children: [
2489
+ '"',
2490
+ quote,
2491
+ '"'
2492
+ ] }),
2493
+ /* @__PURE__ */ jsx44(AuthorRow, { author, role, avatar })
2494
+ ] });
2495
+ }
2496
+ if (variant === "featured") {
2497
+ return /* @__PURE__ */ jsxs35(YStack35, { backgroundColor: "$color3", padding: "$5", borderRadius: "$6", gap: "$4", alignItems: "center", children: [
2498
+ /* @__PURE__ */ jsx44(SizableText37, { size: "$8", color: "$color9", opacity: 0.3, fontWeight: "800", children: '"' }),
2499
+ /* @__PURE__ */ jsx44(Stars2, { count: rating }),
2500
+ /* @__PURE__ */ jsxs35(SizableText37, { size: "$5", color: "$color12", fontStyle: "italic", textAlign: "center", lineHeight: 28, children: [
2501
+ '"',
2502
+ quote,
2503
+ '"'
2504
+ ] }),
2505
+ /* @__PURE__ */ jsx44(AuthorRow, { author, role, avatar })
2506
+ ] });
2507
+ }
2508
+ return /* @__PURE__ */ jsxs35(
2509
+ YStack35,
2510
+ {
2511
+ backgroundColor: "$color1",
2512
+ padding: "$4",
2513
+ borderRadius: "$5",
2514
+ borderWidth: 1,
2515
+ borderColor: "$color4",
2516
+ gap: "$3",
2517
+ children: [
2518
+ /* @__PURE__ */ jsx44(Stars2, { count: rating }),
2519
+ /* @__PURE__ */ jsxs35(SizableText37, { size: "$4", color: "$color11", fontStyle: "italic", lineHeight: 24, children: [
2520
+ '"',
2521
+ quote,
2522
+ '"'
2523
+ ] }),
2524
+ /* @__PURE__ */ jsx44(AuthorRow, { author, role, avatar })
2525
+ ]
2526
+ }
2527
+ );
2528
+ }
2529
+
2530
+ // src/patterns/ConfirmDialog.tsx
2531
+ import { AlertDialog as AlertDialog2, Button as Button10, SizableText as SizableText38, XStack as XStack31, YStack as YStack36 } from "tamagui";
2532
+ import { jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
2533
+ function ConfirmDialog({
2534
+ open,
2535
+ onOpenChange,
2536
+ title,
2537
+ description,
2538
+ confirmLabel = "Confirm",
2539
+ cancelLabel = "Cancel",
2540
+ onConfirm,
2541
+ onCancel,
2542
+ destructive = false,
2543
+ icon
2544
+ }) {
2545
+ const handleCancel = () => {
2546
+ onCancel?.();
2547
+ onOpenChange(false);
2548
+ };
2549
+ const handleConfirm = () => {
2550
+ onConfirm?.();
2551
+ onOpenChange(false);
2552
+ };
2553
+ return /* @__PURE__ */ jsx45(AlertDialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs36(AlertDialog2.Portal, { children: [
2554
+ /* @__PURE__ */ jsx45(
2555
+ AlertDialog2.Overlay,
2556
+ {
2557
+ opacity: 0.5,
2558
+ enterStyle: { opacity: 0 },
2559
+ exitStyle: { opacity: 0 },
2560
+ animation: "quick"
2561
+ },
2562
+ "overlay"
2563
+ ),
2564
+ /* @__PURE__ */ jsx45(
2565
+ AlertDialog2.Content,
2566
+ {
2567
+ bordered: true,
2568
+ elevate: true,
2569
+ width: "90%",
2570
+ maxWidth: 400,
2571
+ enterStyle: { y: -20, opacity: 0, scale: 0.9 },
2572
+ exitStyle: { y: 10, opacity: 0, scale: 0.95 },
2573
+ x: 0,
2574
+ y: 0,
2575
+ scale: 1,
2576
+ opacity: 1,
2577
+ animation: "quick",
2578
+ children: /* @__PURE__ */ jsxs36(YStack36, { gap: "$4", padding: "$4", children: [
2579
+ icon && /* @__PURE__ */ jsx45(YStack36, { alignItems: "center", children: icon }),
2580
+ /* @__PURE__ */ jsxs36(YStack36, { gap: "$2", alignItems: icon ? "center" : "flex-start", children: [
2581
+ /* @__PURE__ */ jsx45(AlertDialog2.Title, { size: "$6", fontWeight: "700", children: title }),
2582
+ description && /* @__PURE__ */ jsx45(
2583
+ AlertDialog2.Description,
2584
+ {
2585
+ size: "$3",
2586
+ color: "$color10",
2587
+ textAlign: icon ? "center" : "left",
2588
+ children: description
2589
+ }
2590
+ )
2591
+ ] }),
2592
+ /* @__PURE__ */ jsxs36(XStack31, { gap: "$3", justifyContent: "flex-end", children: [
2593
+ /* @__PURE__ */ jsx45(
2594
+ Button10,
2595
+ {
2596
+ flex: 1,
2597
+ size: "$4",
2598
+ borderRadius: "$4",
2599
+ variant: "outlined",
2600
+ borderColor: "$color7",
2601
+ onPress: handleCancel,
2602
+ pressStyle: { opacity: 0.7 },
2603
+ animation: "quick",
2604
+ children: /* @__PURE__ */ jsx45(SizableText38, { fontWeight: "600", children: cancelLabel })
2605
+ }
2606
+ ),
2607
+ /* @__PURE__ */ jsx45(
2608
+ Button10,
2609
+ {
2610
+ flex: 1,
2611
+ size: "$4",
2612
+ borderRadius: "$4",
2613
+ backgroundColor: destructive ? "$red9" : "$color9",
2614
+ onPress: handleConfirm,
2615
+ pressStyle: { backgroundColor: destructive ? "$red8" : "$color8", scale: 0.97 },
2616
+ animation: "quick",
2617
+ children: /* @__PURE__ */ jsx45(SizableText38, { fontWeight: "600", color: "white", children: confirmLabel })
2618
+ }
2619
+ )
2620
+ ] })
2621
+ ] })
2622
+ },
2623
+ "content"
2624
+ )
2625
+ ] }) });
2626
+ }
2627
+
2628
+ // src/patterns/Chip.tsx
2629
+ import { useCallback as useCallback3 } from "react";
2630
+ import { SizableText as SizableText39, XStack as XStack32 } from "tamagui";
2631
+ import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
2632
+ var sizes2 = { sm: { h: 28, px: "$2", text: "$2" }, md: { h: 34, px: "$3", text: "$3" }, lg: { h: 42, px: "$4", text: "$4" } };
2633
+ function Chip({ label, selected, onPress, onRemove, variant = "filled", size = "md", icon, color }) {
2634
+ const s = sizes2[size];
2635
+ const filled = variant === "filled";
2636
+ const active = selected ?? false;
2637
+ const bg = active ? color ?? "$color9" : filled ? "$color3" : "transparent";
2638
+ const border = active ? color ?? "$color9" : "$color6";
2639
+ const fg = active ? "$color1" : "$color11";
2640
+ return /* @__PURE__ */ jsxs37(
2641
+ XStack32,
2642
+ {
2643
+ height: s.h,
2644
+ borderRadius: "$10",
2645
+ paddingHorizontal: s.px,
2646
+ backgroundColor: bg,
2647
+ borderWidth: filled ? 0 : 1,
2648
+ borderColor: border,
2649
+ alignItems: "center",
2650
+ gap: "$1.5",
2651
+ pressStyle: { scale: 0.96, opacity: 0.85 },
2652
+ animation: "quick",
2653
+ onPress,
2654
+ cursor: "pointer",
2655
+ children: [
2656
+ active && /* @__PURE__ */ jsx46(SizableText39, { size: s.text, color: fg, children: "\u2713" }),
2657
+ icon && /* @__PURE__ */ jsx46(SizableText39, { color: fg, children: icon }),
2658
+ /* @__PURE__ */ jsx46(SizableText39, { size: s.text, color: fg, fontWeight: "500", children: label }),
2659
+ onRemove && /* @__PURE__ */ jsx46(
2660
+ SizableText39,
2661
+ {
2662
+ size: "$2",
2663
+ color: fg,
2664
+ opacity: 0.7,
2665
+ pressStyle: { opacity: 1 },
2666
+ onPress: (e) => {
2667
+ e.stopPropagation?.();
2668
+ onRemove();
2669
+ },
2670
+ marginLeft: "$1",
2671
+ children: "\u2715"
2672
+ }
2673
+ )
2674
+ ]
2675
+ }
2676
+ );
2677
+ }
2678
+ function ChipGroup({ chips, selected = [], onSelectionChange, multiSelect = true, variant, size }) {
2679
+ const toggle = useCallback3((id) => {
2680
+ if (!onSelectionChange) return;
2681
+ const isSelected = selected.includes(id);
2682
+ if (multiSelect) {
2683
+ onSelectionChange(isSelected ? selected.filter((s) => s !== id) : [...selected, id]);
2684
+ } else {
2685
+ onSelectionChange(isSelected ? [] : [id]);
2686
+ }
2687
+ }, [selected, onSelectionChange, multiSelect]);
2688
+ return /* @__PURE__ */ jsx46(XStack32, { flexWrap: "wrap", gap: "$2", children: chips.map((chip) => /* @__PURE__ */ jsx46(
2689
+ Chip,
2690
+ {
2691
+ label: chip.label,
2692
+ icon: chip.icon,
2693
+ selected: selected.includes(chip.id),
2694
+ onPress: () => toggle(chip.id),
2695
+ variant,
2696
+ size
2697
+ },
2698
+ chip.id
2699
+ )) });
2700
+ }
2701
+
2702
+ // src/patterns/OTPInput.tsx
2703
+ import { useCallback as useCallback4, useRef as useRef2, useState as useState11 } from "react";
2704
+ import { Platform } from "react-native";
2705
+ import { Input as Input3, SizableText as SizableText40, XStack as XStack33, YStack as YStack37 } from "tamagui";
2706
+ import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
2707
+ function OTPInput({ length = 6, value = "", onChange, onComplete, error, autoFocus, secureEntry }) {
2708
+ const inputRef = useRef2(null);
2709
+ const [focused, setFocused] = useState11(false);
2710
+ const digits = value.padEnd(length, " ").slice(0, length);
2711
+ const handleChange = useCallback4((text) => {
2712
+ const cleaned = text.replace(/\D/g, "").slice(0, length);
2713
+ onChange?.(cleaned);
2714
+ if (cleaned.length === length) onComplete?.(cleaned);
2715
+ }, [length, onChange, onComplete]);
2716
+ const focusInput = useCallback4(() => {
2717
+ inputRef.current?.focus();
2718
+ }, []);
2719
+ return /* @__PURE__ */ jsxs38(YStack37, { position: "relative", children: [
2720
+ /* @__PURE__ */ jsx47(XStack33, { gap: "$2", justifyContent: "center", children: Array.from({ length }, (_, i) => {
2721
+ const char = digits[i]?.trim();
2722
+ const isCursor = focused && value.length === i;
2723
+ return /* @__PURE__ */ jsxs38(
2724
+ YStack37,
2725
+ {
2726
+ width: 48,
2727
+ height: 56,
2728
+ borderRadius: "$3",
2729
+ borderWidth: 2,
2730
+ borderColor: error ? "$red9" : isCursor ? "$color9" : char ? "$color7" : "$color5",
2731
+ backgroundColor: error ? "$red2" : isCursor ? "$color2" : "$color1",
2732
+ alignItems: "center",
2733
+ justifyContent: "center",
2734
+ animation: "quick",
2735
+ pointerEvents: "none",
2736
+ children: [
2737
+ /* @__PURE__ */ jsx47(SizableText40, { size: "$7", fontWeight: "600", color: "$color12", children: char ? secureEntry ? "\u25CF" : char : "" }),
2738
+ isCursor && /* @__PURE__ */ jsx47(
2739
+ YStack37,
2740
+ {
2741
+ position: "absolute",
2742
+ bottom: 10,
2743
+ width: 20,
2744
+ height: 2,
2745
+ backgroundColor: "$color9",
2746
+ animation: "quick"
2747
+ }
2748
+ )
2749
+ ]
2750
+ },
2751
+ i
2752
+ );
2753
+ }) }),
2754
+ Platform.OS === "web" ? /* @__PURE__ */ jsx47(
2755
+ "input",
2756
+ {
2757
+ ref: inputRef,
2758
+ type: "text",
2759
+ inputMode: "numeric",
2760
+ pattern: "[0-9]*",
2761
+ autoComplete: "one-time-code",
2762
+ maxLength: length,
2763
+ value,
2764
+ autoFocus,
2765
+ onChange: (e) => handleChange(e.target.value),
2766
+ onFocus: () => setFocused(true),
2767
+ onBlur: () => setFocused(false),
2768
+ style: {
2769
+ position: "absolute",
2770
+ top: 0,
2771
+ left: 0,
2772
+ right: 0,
2773
+ bottom: 0,
2774
+ width: "100%",
2775
+ height: "100%",
2776
+ opacity: 0,
2777
+ fontSize: 16,
2778
+ caretColor: "transparent",
2779
+ cursor: "pointer"
2780
+ }
2781
+ }
2782
+ ) : /* @__PURE__ */ jsx47(
2783
+ Input3,
2784
+ {
2785
+ ref: inputRef,
2786
+ value,
2787
+ onChangeText: handleChange,
2788
+ keyboardType: "number-pad",
2789
+ maxLength: length,
2790
+ autoFocus,
2791
+ onFocus: () => setFocused(true),
2792
+ onBlur: () => setFocused(false),
2793
+ position: "absolute",
2794
+ top: 0,
2795
+ left: 0,
2796
+ right: 0,
2797
+ bottom: 0,
2798
+ opacity: 0,
2799
+ fontSize: 16
2800
+ }
2801
+ )
2802
+ ] });
2803
+ }
2804
+
2805
+ // src/patterns/PasswordInput.tsx
2806
+ import { useState as useState12, useCallback as useCallback5 } from "react";
2807
+ import { Input as Input4, SizableText as SizableText41, XStack as XStack34, YStack as YStack38 } from "tamagui";
2808
+ import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
2809
+ function getStrength(pw) {
2810
+ if (!pw) return { label: "", color: "$color6", width: "0%" };
2811
+ const score = [pw.length >= 8, /[A-Z]/.test(pw), /[0-9]/.test(pw), /[^A-Za-z0-9]/.test(pw)].filter(Boolean).length;
2812
+ if (score <= 1) return { label: "Weak", color: "$red9", width: "33%" };
2813
+ if (score <= 2) return { label: "Medium", color: "$yellow9", width: "66%" };
2814
+ return { label: "Strong", color: "$green9", width: "100%" };
2815
+ }
2816
+ function PasswordInput({ value = "", onChangeText, placeholder = "Password", label, error, size = "$4", strengthIndicator }) {
2817
+ const [visible, setVisible] = useState12(false);
2818
+ const toggle = useCallback5(() => setVisible((v) => !v), []);
2819
+ const strength = getStrength(value);
2820
+ return /* @__PURE__ */ jsxs39(YStack38, { gap: "$1.5", children: [
2821
+ label && /* @__PURE__ */ jsx48(SizableText41, { size: "$3", color: "$color11", fontWeight: "500", children: label }),
2822
+ /* @__PURE__ */ jsxs39(
2823
+ XStack34,
2824
+ {
2825
+ borderWidth: 1,
2826
+ borderColor: error ? "$red9" : "$color6",
2827
+ borderRadius: "$3",
2828
+ backgroundColor: "$color2",
2829
+ alignItems: "center",
2830
+ paddingRight: "$2",
2831
+ focusStyle: { borderColor: "$color9" },
2832
+ children: [
2833
+ /* @__PURE__ */ jsx48(
2834
+ Input4,
2835
+ {
2836
+ flex: 1,
2837
+ size,
2838
+ value,
2839
+ onChangeText,
2840
+ placeholder,
2841
+ placeholderTextColor: "$color8",
2842
+ secureTextEntry: !visible,
2843
+ backgroundColor: "transparent",
2844
+ borderWidth: 0
2845
+ }
2846
+ ),
2847
+ /* @__PURE__ */ jsx48(
2848
+ SizableText41,
2849
+ {
2850
+ size: "$4",
2851
+ color: "$color8",
2852
+ paddingHorizontal: "$2",
2853
+ pressStyle: { opacity: 0.6 },
2854
+ onPress: toggle,
2855
+ cursor: "pointer",
2856
+ children: visible ? "\u25C9" : "\u25CE"
2857
+ }
2858
+ )
2859
+ ]
2860
+ }
2861
+ ),
2862
+ strengthIndicator && value.length > 0 && /* @__PURE__ */ jsxs39(YStack38, { gap: "$1", children: [
2863
+ /* @__PURE__ */ jsx48(YStack38, { height: 3, backgroundColor: "$color4", borderRadius: 2, overflow: "hidden", children: /* @__PURE__ */ jsx48(YStack38, { height: 3, width: strength.width, backgroundColor: strength.color, borderRadius: 2, animation: "quick" }) }),
2864
+ /* @__PURE__ */ jsx48(SizableText41, { size: "$1", color: strength.color, children: strength.label })
2865
+ ] }),
2866
+ error && /* @__PURE__ */ jsx48(SizableText41, { size: "$2", color: "$red9", children: error })
2867
+ ] });
2868
+ }
2869
+
2870
+ // src/patterns/AvatarGroup.tsx
2871
+ import { Circle as Circle10, Image as Image8, SizableText as SizableText42, XStack as XStack35 } from "tamagui";
2872
+ import { jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
2873
+ function getInitials(name) {
2874
+ if (!name) return "?";
2875
+ return name.split(" ").map((p) => p[0]).join("").toUpperCase().slice(0, 2);
2876
+ }
2877
+ function AvatarItem({ uri, name, color, size }) {
2878
+ return /* @__PURE__ */ jsx49(
2879
+ Circle10,
2880
+ {
2881
+ size,
2882
+ backgroundColor: color ?? "$color4",
2883
+ borderWidth: 2,
2884
+ borderColor: "$background",
2885
+ overflow: "hidden",
2886
+ alignItems: "center",
2887
+ justifyContent: "center",
2888
+ children: uri ? /* @__PURE__ */ jsx49(Image8, { source: { uri }, width: size, height: size, objectFit: "cover" }) : /* @__PURE__ */ jsx49(SizableText42, { size: "$2", fontWeight: "600", color: color ? "$color1" : "$color11", children: getInitials(name) })
2889
+ }
2890
+ );
2891
+ }
2892
+ function AvatarGroup({ avatars, max = 4, size = 36, overlap = 10 }) {
2893
+ const visible = avatars.slice(0, max);
2894
+ const remaining = avatars.length - max;
2895
+ return /* @__PURE__ */ jsxs40(XStack35, { alignItems: "center", children: [
2896
+ visible.map((avatar, i) => /* @__PURE__ */ jsx49(XStack35, { marginLeft: i === 0 ? 0 : -overlap, zIndex: visible.length - i, children: /* @__PURE__ */ jsx49(AvatarItem, { ...avatar, size }) }, i)),
2897
+ remaining > 0 && /* @__PURE__ */ jsx49(XStack35, { marginLeft: -overlap, zIndex: 0, children: /* @__PURE__ */ jsx49(
2898
+ Circle10,
2899
+ {
2900
+ size,
2901
+ backgroundColor: "$color6",
2902
+ borderWidth: 2,
2903
+ borderColor: "$background",
2904
+ alignItems: "center",
2905
+ justifyContent: "center",
2906
+ children: /* @__PURE__ */ jsxs40(SizableText42, { size: "$2", fontWeight: "600", color: "$color11", children: [
2907
+ "+",
2908
+ remaining
2909
+ ] })
2910
+ }
2911
+ ) })
2912
+ ] });
2913
+ }
2914
+
2915
+ // src/patterns/SwipeCards.tsx
2916
+ import { useState as useState13, useCallback as useCallback6 } from "react";
2917
+ import { Circle as Circle11, SizableText as SizableText43, XStack as XStack36, YStack as YStack39 } from "tamagui";
2918
+ import { jsx as jsx50, jsxs as jsxs41 } from "react/jsx-runtime";
2919
+ var STACK_SIZE = 3;
2920
+ var CARD_OFFSETS = [
2921
+ { scale: 1, y: 0, opacity: 1 },
2922
+ { scale: 0.95, y: 8, opacity: 0.9 },
2923
+ { scale: 0.9, y: 16, opacity: 0.8 }
2924
+ ];
2925
+ function SwipeCards({
2926
+ items,
2927
+ renderCard,
2928
+ onSwipeLeft,
2929
+ onSwipeRight,
2930
+ onEmpty,
2931
+ leftLabel = "Nope",
2932
+ rightLabel = "Like",
2933
+ emptyMessage = "No more cards"
2934
+ }) {
2935
+ const [index, setIndex] = useState13(0);
2936
+ const [exitDir, setExitDir] = useState13(null);
2937
+ const remaining = items.slice(index);
2938
+ const isEmpty = remaining.length === 0;
2939
+ const handleSwipe = useCallback6((dir) => {
2940
+ if (isEmpty) return;
2941
+ const current = items[index];
2942
+ setExitDir(dir);
2943
+ const timer = setTimeout(() => {
2944
+ setExitDir(null);
2945
+ setIndex((i) => {
2946
+ const next = i + 1;
2947
+ if (next >= items.length) onEmpty?.();
2948
+ return next;
2949
+ });
2950
+ dir === "left" ? onSwipeLeft?.(current) : onSwipeRight?.(current);
2951
+ }, 250);
2952
+ return () => clearTimeout(timer);
2953
+ }, [isEmpty, index, items, onEmpty, onSwipeLeft, onSwipeRight]);
2954
+ if (isEmpty) {
2955
+ return /* @__PURE__ */ jsx50(YStack39, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$3", padding: "$4", children: /* @__PURE__ */ jsx50(SizableText43, { size: "$5", color: "$color8", children: emptyMessage }) });
2956
+ }
2957
+ return /* @__PURE__ */ jsxs41(YStack39, { flex: 1, gap: "$4", children: [
2958
+ /* @__PURE__ */ jsx50(YStack39, { flex: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx50(YStack39, { width: "100%", maxWidth: 340, aspectRatio: 3 / 4, position: "relative", children: remaining.slice(0, STACK_SIZE).reverse().map((item, reverseIdx) => {
2959
+ const stackIdx = Math.min(remaining.length, STACK_SIZE) - 1 - reverseIdx;
2960
+ const isTop = stackIdx === 0;
2961
+ const offset = CARD_OFFSETS[stackIdx] ?? CARD_OFFSETS[2];
2962
+ const exitX = exitDir === "left" ? -400 : exitDir === "right" ? 400 : 0;
2963
+ const exitRotate = exitDir === "left" ? "-15deg" : exitDir === "right" ? "15deg" : "0deg";
2964
+ return /* @__PURE__ */ jsxs41(
2965
+ YStack39,
2966
+ {
2967
+ position: "absolute",
2968
+ top: 0,
2969
+ left: 0,
2970
+ right: 0,
2971
+ bottom: 0,
2972
+ animation: "quick",
2973
+ borderRadius: "$5",
2974
+ overflow: "hidden",
2975
+ backgroundColor: "$background",
2976
+ elevation: isTop ? 4 : 1,
2977
+ shadowColor: "$shadowColor",
2978
+ shadowRadius: isTop ? 16 : 4,
2979
+ scale: isTop && exitDir ? 1 : offset.scale,
2980
+ opacity: isTop && exitDir ? 0 : offset.opacity,
2981
+ y: isTop && exitDir ? 0 : offset.y,
2982
+ x: isTop ? exitX : 0,
2983
+ rotate: isTop ? exitRotate : "0deg",
2984
+ children: [
2985
+ renderCard(item),
2986
+ isTop && exitDir === "left" && /* @__PURE__ */ jsx50(
2987
+ YStack39,
2988
+ {
2989
+ position: "absolute",
2990
+ top: "$4",
2991
+ right: "$4",
2992
+ borderWidth: 3,
2993
+ borderColor: "$red10",
2994
+ borderRadius: "$3",
2995
+ padding: "$2",
2996
+ rotate: "15deg",
2997
+ children: /* @__PURE__ */ jsx50(SizableText43, { size: "$7", fontWeight: "800", color: "$red10", children: leftLabel.toUpperCase() })
2998
+ }
2999
+ ),
3000
+ isTop && exitDir === "right" && /* @__PURE__ */ jsx50(
3001
+ YStack39,
3002
+ {
3003
+ position: "absolute",
3004
+ top: "$4",
3005
+ left: "$4",
3006
+ borderWidth: 3,
3007
+ borderColor: "$green10",
3008
+ borderRadius: "$3",
3009
+ padding: "$2",
3010
+ rotate: "-15deg",
3011
+ children: /* @__PURE__ */ jsx50(SizableText43, { size: "$7", fontWeight: "800", color: "$green10", children: rightLabel.toUpperCase() })
3012
+ }
3013
+ )
3014
+ ]
3015
+ },
3016
+ item.id
3017
+ );
3018
+ }) }) }),
3019
+ /* @__PURE__ */ jsxs41(XStack36, { justifyContent: "center", gap: "$6", paddingBottom: "$4", children: [
3020
+ /* @__PURE__ */ jsx50(
3021
+ Circle11,
3022
+ {
3023
+ size: 60,
3024
+ backgroundColor: "$red3",
3025
+ borderWidth: 2,
3026
+ borderColor: "$red7",
3027
+ pressStyle: { scale: 0.9, backgroundColor: "$red5" },
3028
+ animation: "quick",
3029
+ onPress: () => handleSwipe("left"),
3030
+ alignItems: "center",
3031
+ justifyContent: "center",
3032
+ children: /* @__PURE__ */ jsx50(SizableText43, { size: "$6", color: "$red10", fontWeight: "700", children: "\u2715" })
3033
+ }
3034
+ ),
3035
+ /* @__PURE__ */ jsx50(
3036
+ Circle11,
3037
+ {
3038
+ size: 60,
3039
+ backgroundColor: "$green3",
3040
+ borderWidth: 2,
3041
+ borderColor: "$green7",
3042
+ pressStyle: { scale: 0.9, backgroundColor: "$green5" },
3043
+ animation: "quick",
3044
+ onPress: () => handleSwipe("right"),
3045
+ alignItems: "center",
3046
+ justifyContent: "center",
3047
+ children: /* @__PURE__ */ jsx50(SizableText43, { size: "$6", color: "$green10", fontWeight: "700", children: "\u2665" })
3048
+ }
3049
+ )
3050
+ ] })
3051
+ ] });
3052
+ }
3053
+
3054
+ // src/patterns/GlassCard.tsx
3055
+ import { styled as styled12, YStack as YStack40 } from "tamagui";
3056
+ import { jsx as jsx51 } from "react/jsx-runtime";
3057
+ var BLUR = { light: 8, medium: 16, heavy: 24 };
3058
+ var TINT_BG = {
3059
+ light: "rgba(255,255,255,0.15)",
3060
+ dark: "rgba(0,0,0,0.25)"
3061
+ };
3062
+ var GlassFrame = styled12(YStack40, {
3063
+ borderWidth: 1,
3064
+ borderColor: "rgba(255,255,255,0.2)",
3065
+ overflow: "hidden"
3066
+ });
3067
+ function GlassCard({
3068
+ children,
3069
+ intensity = "medium",
3070
+ tint = "light",
3071
+ borderRadius = "$4",
3072
+ padding = "$4",
3073
+ elevated = false
3074
+ }) {
3075
+ const blur = BLUR[intensity];
3076
+ return /* @__PURE__ */ jsx51(
3077
+ GlassFrame,
3078
+ {
3079
+ borderRadius,
3080
+ padding,
3081
+ backgroundColor: TINT_BG[tint],
3082
+ elevation: elevated ? 4 : 0,
3083
+ shadowColor: elevated ? "$shadowColor" : void 0,
3084
+ shadowRadius: elevated ? 20 : void 0,
3085
+ shadowOpacity: elevated ? 0.3 : void 0,
3086
+ style: { backdropFilter: `blur(${blur}px)`, WebkitBackdropFilter: `blur(${blur}px)` },
3087
+ children
1636
3088
  }
1637
3089
  );
1638
3090
  }
3091
+
3092
+ // src/patterns/DataTable.tsx
3093
+ import { useMemo, useState as useState14 } from "react";
3094
+ import { SizableText as SizableText44, Separator as Separator5, XStack as XStack37, YStack as YStack41, useMedia, styled as styled13, View as View6 } from "tamagui";
3095
+ import { jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
3096
+ var TH = styled13(View6, { padding: "$3", justifyContent: "center" });
3097
+ var TD = styled13(View6, { padding: "$3", justifyContent: "center" });
3098
+ function StatusBadge({ status }) {
3099
+ const isActive = status.toLowerCase() === "active";
3100
+ return /* @__PURE__ */ jsxs42(XStack37, { gap: "$2", alignItems: "center", children: [
3101
+ /* @__PURE__ */ jsx52(
3102
+ View6,
3103
+ {
3104
+ width: 8,
3105
+ height: 8,
3106
+ borderRadius: 4,
3107
+ backgroundColor: isActive ? "$green9" : "$orange9"
3108
+ }
3109
+ ),
3110
+ /* @__PURE__ */ jsx52(SizableText44, { size: "$3", color: "$color11", children: status })
3111
+ ] });
3112
+ }
3113
+ function HeaderCell({ col, sort, onSort }) {
3114
+ const active = sort?.key === col.key;
3115
+ const indicator = active ? sort.dir === "asc" ? " \u25B2" : " \u25BC" : "";
3116
+ return /* @__PURE__ */ jsx52(
3117
+ TH,
3118
+ {
3119
+ width: col.width,
3120
+ flexDirection: "row",
3121
+ alignItems: "center",
3122
+ cursor: col.sortable ? "pointer" : void 0,
3123
+ onPress: col.sortable ? onSort : void 0,
3124
+ pressStyle: col.sortable ? { opacity: 0.7 } : void 0,
3125
+ children: /* @__PURE__ */ jsxs42(
3126
+ SizableText44,
3127
+ {
3128
+ size: "$2",
3129
+ fontWeight: "700",
3130
+ color: active ? "$color12" : "$color9",
3131
+ textTransform: "uppercase",
3132
+ letterSpacing: 0.5,
3133
+ children: [
3134
+ col.header,
3135
+ indicator
3136
+ ]
3137
+ }
3138
+ )
3139
+ },
3140
+ col.key
3141
+ );
3142
+ }
3143
+ function TableRow({ row, columns, onPress, odd }) {
3144
+ return /* @__PURE__ */ jsx52(
3145
+ XStack37,
3146
+ {
3147
+ backgroundColor: odd ? "$color2" : "transparent",
3148
+ borderBottomWidth: 0.5,
3149
+ borderColor: "$color4",
3150
+ hoverStyle: { backgroundColor: "$color3" },
3151
+ cursor: onPress ? "pointer" : void 0,
3152
+ onPress: onPress ? () => onPress(row) : void 0,
3153
+ pressStyle: onPress ? { opacity: 0.85 } : void 0,
3154
+ animation: "quick",
3155
+ children: columns.map((col) => /* @__PURE__ */ jsx52(TD, { width: col.width, flex: col.width ? void 0 : 1, children: col.render ? col.render(row[col.key], row) : /* @__PURE__ */ jsx52(SizableText44, { size: "$3", color: "$color11", children: String(row[col.key] ?? "") }) }, col.key))
3156
+ }
3157
+ );
3158
+ }
3159
+ function CardRow({ row, columns, onPress }) {
3160
+ return /* @__PURE__ */ jsx52(
3161
+ YStack41,
3162
+ {
3163
+ backgroundColor: "$color1",
3164
+ borderRadius: "$4",
3165
+ borderWidth: 1,
3166
+ borderColor: "$color4",
3167
+ padding: "$3",
3168
+ gap: "$2",
3169
+ onPress: onPress ? () => onPress(row) : void 0,
3170
+ pressStyle: onPress ? { scale: 0.98, opacity: 0.9 } : void 0,
3171
+ animation: "quick",
3172
+ children: columns.map((col, i) => /* @__PURE__ */ jsxs42(YStack41, { children: [
3173
+ i > 0 && /* @__PURE__ */ jsx52(Separator5, { marginVertical: "$1.5", borderColor: "$color4" }),
3174
+ /* @__PURE__ */ jsxs42(XStack37, { justifyContent: "space-between", alignItems: "center", children: [
3175
+ /* @__PURE__ */ jsx52(SizableText44, { size: "$2", color: "$color9", fontWeight: "600", children: col.header }),
3176
+ col.render ? col.render(row[col.key], row) : /* @__PURE__ */ jsx52(SizableText44, { size: "$3", color: "$color11", children: String(row[col.key] ?? "") })
3177
+ ] })
3178
+ ] }, col.key))
3179
+ }
3180
+ );
3181
+ }
3182
+ function DataTable({ columns, data, onRowPress, emptyMessage = "No data" }) {
3183
+ const [sort, setSort] = useState14(null);
3184
+ const media = useMedia();
3185
+ const isSmall = media.sm;
3186
+ const sorted = useMemo(() => {
3187
+ if (!sort) return data;
3188
+ return [...data].sort((a, b) => {
3189
+ const av = a[sort.key], bv = b[sort.key];
3190
+ const cmp = typeof av === "number" && typeof bv === "number" ? av - bv : String(av ?? "").localeCompare(String(bv ?? ""));
3191
+ return sort.dir === "asc" ? cmp : -cmp;
3192
+ });
3193
+ }, [data, sort]);
3194
+ const toggleSort = (key) => setSort((s) => s?.key === key ? { key, dir: s.dir === "asc" ? "desc" : "asc" } : { key, dir: "asc" });
3195
+ if (!data.length) {
3196
+ return /* @__PURE__ */ jsx52(YStack41, { padding: "$6", alignItems: "center", children: /* @__PURE__ */ jsx52(SizableText44, { size: "$4", color: "$color9", children: emptyMessage }) });
3197
+ }
3198
+ if (isSmall) {
3199
+ return /* @__PURE__ */ jsx52(YStack41, { gap: "$3", children: sorted.map((row, i) => /* @__PURE__ */ jsx52(CardRow, { row, columns, onPress: onRowPress }, i)) });
3200
+ }
3201
+ return /* @__PURE__ */ jsxs42(YStack41, { borderWidth: 1, borderColor: "$color4", borderRadius: "$4", overflow: "hidden", children: [
3202
+ /* @__PURE__ */ jsx52(XStack37, { backgroundColor: "$color1", borderBottomWidth: 1, borderColor: "$color4", children: columns.map((col) => /* @__PURE__ */ jsx52(HeaderCell, { col, sort, onSort: () => toggleSort(col.key) }, col.key)) }),
3203
+ sorted.map((row, i) => /* @__PURE__ */ jsx52(TableRow, { row, columns, onPress: onRowPress, odd: i % 2 === 1 }, i))
3204
+ ] });
3205
+ }
3206
+
3207
+ // src/patterns/DatePicker.tsx
3208
+ import { useCallback as useCallback7, useMemo as useMemo2, useState as useState15 } from "react";
3209
+ import { SizableText as SizableText45, XStack as XStack38, YStack as YStack42 } from "tamagui";
3210
+ import { jsx as jsx53, jsxs as jsxs43 } from "react/jsx-runtime";
3211
+ var MONTH_NAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3212
+ var DAY_LABELS_SUN = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
3213
+ var DAY_LABELS_MON = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
3214
+ function daysInMonth(year, month) {
3215
+ return new Date(year, month + 1, 0).getDate();
3216
+ }
3217
+ function sameDay(a, b) {
3218
+ return a ? a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate() : false;
3219
+ }
3220
+ function buildGrid(year, month, startDay) {
3221
+ const total = daysInMonth(year, month);
3222
+ const firstWeekday = new Date(year, month, 1).getDay();
3223
+ const offset = (firstWeekday - startDay + 7) % 7;
3224
+ const prevTotal = daysInMonth(year, month - 1);
3225
+ const cells = [];
3226
+ for (let i = offset - 1; i >= 0; i--)
3227
+ cells.push({ day: prevTotal - i, month: month - 1, year: month === 0 ? year - 1 : year, outside: true });
3228
+ for (let d = 1; d <= total; d++)
3229
+ cells.push({ day: d, month, year, outside: false });
3230
+ while (cells.length < 42)
3231
+ cells.push({ day: cells.length - offset - total + 1, month: month + 1, year: month === 11 ? year + 1 : year, outside: true });
3232
+ return cells;
3233
+ }
3234
+ function NavButton({ label, onPress }) {
3235
+ return /* @__PURE__ */ jsx53(
3236
+ XStack38,
3237
+ {
3238
+ width: 36,
3239
+ height: 36,
3240
+ borderRadius: "$10",
3241
+ alignItems: "center",
3242
+ justifyContent: "center",
3243
+ backgroundColor: "$color3",
3244
+ pressStyle: { scale: 0.92, backgroundColor: "$color5" },
3245
+ animation: "quick",
3246
+ onPress,
3247
+ cursor: "pointer",
3248
+ children: /* @__PURE__ */ jsx53(SizableText45, { size: "$5", color: "$color11", fontWeight: "600", children: label })
3249
+ }
3250
+ );
3251
+ }
3252
+ function DatePicker({ value, onDateChange, minDate, maxDate, startDay = 1 }) {
3253
+ const today = useMemo2(() => /* @__PURE__ */ new Date(), []);
3254
+ const [viewMonth, setViewMonth] = useState15(value?.getMonth() ?? today.getMonth());
3255
+ const [viewYear, setViewYear] = useState15(value?.getFullYear() ?? today.getFullYear());
3256
+ const headers = startDay === 1 ? DAY_LABELS_MON : DAY_LABELS_SUN;
3257
+ const grid = useMemo2(() => buildGrid(viewYear, viewMonth, startDay), [viewYear, viewMonth, startDay]);
3258
+ const navigate = useCallback7((dir) => {
3259
+ setViewMonth((m) => {
3260
+ const next = m + dir;
3261
+ if (next < 0) {
3262
+ setViewYear((y) => y - 1);
3263
+ return 11;
3264
+ }
3265
+ if (next > 11) {
3266
+ setViewYear((y) => y + 1);
3267
+ return 0;
3268
+ }
3269
+ return next;
3270
+ });
3271
+ }, []);
3272
+ const isDisabled = useCallback7((d) => {
3273
+ if (minDate && d < new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate())) return true;
3274
+ if (maxDate && d > new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate())) return true;
3275
+ return false;
3276
+ }, [minDate, maxDate]);
3277
+ return /* @__PURE__ */ jsxs43(YStack42, { backgroundColor: "$color2", borderRadius: "$4", padding: "$3", gap: "$2", animation: "quick", children: [
3278
+ /* @__PURE__ */ jsxs43(XStack38, { alignItems: "center", justifyContent: "space-between", children: [
3279
+ /* @__PURE__ */ jsx53(NavButton, { label: "\u2039", onPress: () => navigate(-1) }),
3280
+ /* @__PURE__ */ jsxs43(SizableText45, { size: "$4", fontWeight: "700", color: "$color12", children: [
3281
+ MONTH_NAMES[viewMonth],
3282
+ " ",
3283
+ viewYear
3284
+ ] }),
3285
+ /* @__PURE__ */ jsx53(NavButton, { label: "\u203A", onPress: () => navigate(1) })
3286
+ ] }),
3287
+ /* @__PURE__ */ jsx53(XStack38, { children: headers.map((h) => /* @__PURE__ */ jsx53(SizableText45, { size: "$2", color: "$color8", fontWeight: "600", textAlign: "center", flex: 1, children: h }, h)) }),
3288
+ Array.from({ length: Math.ceil(grid.length / 7) }, (_, row) => /* @__PURE__ */ jsx53(XStack38, { children: grid.slice(row * 7, row * 7 + 7).map((cell, i) => {
3289
+ const date = new Date(cell.year, cell.month, cell.day);
3290
+ const selected = sameDay(value, date);
3291
+ const isToday = sameDay(today, date);
3292
+ const disabled = cell.outside || isDisabled(date);
3293
+ return /* @__PURE__ */ jsx53(YStack42, { flex: 1, alignItems: "center", paddingVertical: "$0.5", children: /* @__PURE__ */ jsx53(
3294
+ XStack38,
3295
+ {
3296
+ width: 40,
3297
+ height: 40,
3298
+ borderRadius: "$10",
3299
+ alignItems: "center",
3300
+ justifyContent: "center",
3301
+ backgroundColor: selected ? "$color9" : "transparent",
3302
+ borderWidth: isToday && !selected ? 1.5 : 0,
3303
+ borderColor: "$color9",
3304
+ pressStyle: disabled ? void 0 : { scale: 0.9, backgroundColor: selected ? "$color10" : "$color4" },
3305
+ animation: "quick",
3306
+ opacity: disabled ? 0.35 : 1,
3307
+ cursor: disabled ? "default" : "pointer",
3308
+ onPress: disabled ? void 0 : () => onDateChange?.(date),
3309
+ children: /* @__PURE__ */ jsx53(
3310
+ SizableText45,
3311
+ {
3312
+ size: "$3",
3313
+ fontWeight: selected || isToday ? "700" : "400",
3314
+ color: selected ? "white" : cell.outside ? "$color5" : "$color12",
3315
+ children: cell.day
3316
+ }
3317
+ )
3318
+ }
3319
+ ) }, `${row}-${i}`);
3320
+ }) }, row))
3321
+ ] });
3322
+ }
3323
+
3324
+ // src/patterns/EventCard.tsx
3325
+ import { SizableText as SizableText46, Theme, XStack as XStack39, YStack as YStack43 } from "tamagui";
3326
+ import { jsx as jsx54, jsxs as jsxs44 } from "react/jsx-runtime";
3327
+ var THEME_MAP = {
3328
+ purple: "purple",
3329
+ green: "green",
3330
+ blue: "blue",
3331
+ orange: "orange",
3332
+ red: "red",
3333
+ pink: "pink"
3334
+ };
3335
+ function ParticipantDots({ count, max }) {
3336
+ const dots = Math.min(count, 5);
3337
+ return /* @__PURE__ */ jsxs44(XStack39, { alignItems: "center", gap: "$1.5", children: [
3338
+ /* @__PURE__ */ jsx54(XStack39, { children: Array.from({ length: dots }, (_, i) => /* @__PURE__ */ jsx54(
3339
+ YStack43,
3340
+ {
3341
+ width: 22,
3342
+ height: 22,
3343
+ borderRadius: 11,
3344
+ backgroundColor: "$color7",
3345
+ borderWidth: 2,
3346
+ borderColor: "$color4",
3347
+ marginLeft: i > 0 ? -8 : 0,
3348
+ alignItems: "center",
3349
+ justifyContent: "center",
3350
+ children: /* @__PURE__ */ jsx54(SizableText46, { size: "$1", color: "$color1", fontWeight: "700", children: String.fromCharCode(65 + i) })
3351
+ },
3352
+ i
3353
+ )) }),
3354
+ /* @__PURE__ */ jsxs44(SizableText46, { size: "$2", color: "$color11", fontWeight: "500", children: [
3355
+ count,
3356
+ max ? `/${max}` : ""
3357
+ ] })
3358
+ ] });
3359
+ }
3360
+ function CardInner({ title, subtitle, time, location, label, participants, maxParticipants, onPress, actions }) {
3361
+ return /* @__PURE__ */ jsxs44(
3362
+ YStack43,
3363
+ {
3364
+ backgroundColor: "$color4",
3365
+ borderRadius: "$5",
3366
+ padding: "$4",
3367
+ gap: "$3",
3368
+ borderWidth: 1,
3369
+ borderColor: "$color7",
3370
+ onPress,
3371
+ animation: "quick",
3372
+ pressStyle: onPress ? { scale: 0.97, opacity: 0.9 } : void 0,
3373
+ cursor: onPress ? "pointer" : void 0,
3374
+ children: [
3375
+ /* @__PURE__ */ jsxs44(XStack39, { justifyContent: "space-between", alignItems: "flex-start", children: [
3376
+ /* @__PURE__ */ jsxs44(YStack43, { flex: 1, gap: "$1", children: [
3377
+ /* @__PURE__ */ jsx54(SizableText46, { size: "$6", fontWeight: "700", color: "$color12", children: title }),
3378
+ subtitle && /* @__PURE__ */ jsx54(SizableText46, { size: "$3", color: "$color11", opacity: 0.8, children: subtitle })
3379
+ ] }),
3380
+ time && /* @__PURE__ */ jsx54(YStack43, { backgroundColor: "$color6", paddingHorizontal: "$2.5", paddingVertical: "$1.5", borderRadius: "$3", children: /* @__PURE__ */ jsx54(SizableText46, { size: "$2", fontWeight: "600", color: "$color12", children: time }) })
3381
+ ] }),
3382
+ /* @__PURE__ */ jsxs44(XStack39, { gap: "$4", alignItems: "center", flexWrap: "wrap", children: [
3383
+ location && /* @__PURE__ */ jsxs44(XStack39, { gap: "$1.5", alignItems: "center", children: [
3384
+ /* @__PURE__ */ jsx54(SizableText46, { size: "$3", children: "\u{1F4CD}" }),
3385
+ /* @__PURE__ */ jsx54(SizableText46, { size: "$3", color: "$color11", children: location })
3386
+ ] }),
3387
+ participants !== void 0 && /* @__PURE__ */ jsx54(ParticipantDots, { count: participants, max: maxParticipants })
3388
+ ] }),
3389
+ (label || actions) && /* @__PURE__ */ jsxs44(XStack39, { justifyContent: "space-between", alignItems: "center", children: [
3390
+ label ? /* @__PURE__ */ jsx54(XStack39, { backgroundColor: "$color6", paddingHorizontal: "$2.5", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ jsx54(SizableText46, { size: "$2", fontWeight: "600", color: "$color11", children: label }) }) : /* @__PURE__ */ jsx54(YStack43, {}),
3391
+ actions
3392
+ ] })
3393
+ ]
3394
+ }
3395
+ );
3396
+ }
3397
+ function EventCard({ theme = "purple", ...props }) {
3398
+ return /* @__PURE__ */ jsx54(Theme, { name: THEME_MAP[theme], children: /* @__PURE__ */ jsx54(CardInner, { ...props }) });
3399
+ }
3400
+
3401
+ // src/patterns/UserPreferences.tsx
3402
+ import { Separator as Separator6, SizableText as SizableText47, Slider, Switch as Switch2, XStack as XStack40, YStack as YStack44 } from "tamagui";
3403
+ import { jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
3404
+ function ItemLabel({ title, description, color }) {
3405
+ return /* @__PURE__ */ jsxs45(YStack44, { flex: 1, gap: "$1", children: [
3406
+ /* @__PURE__ */ jsx55(SizableText47, { size: "$4", fontWeight: "500", color: color ?? "$color12", children: title }),
3407
+ description && /* @__PURE__ */ jsx55(SizableText47, { size: "$2", color: "$color9", children: description })
3408
+ ] });
3409
+ }
3410
+ function ToggleRow({ item }) {
3411
+ return /* @__PURE__ */ jsxs45(XStack40, { alignItems: "center", gap: "$3", paddingVertical: "$3", paddingHorizontal: "$4", children: [
3412
+ /* @__PURE__ */ jsx55(ItemLabel, { title: item.title, description: item.description }),
3413
+ /* @__PURE__ */ jsx55(Switch2, { size: "$3", checked: item.value, onCheckedChange: item.onValueChange, children: /* @__PURE__ */ jsx55(Switch2.Thumb, { animation: "quick" }) })
3414
+ ] });
3415
+ }
3416
+ function SelectRow({ item }) {
3417
+ const current = item.options.find((o) => o.value === item.value);
3418
+ return /* @__PURE__ */ jsxs45(
3419
+ XStack40,
3420
+ {
3421
+ alignItems: "center",
3422
+ gap: "$3",
3423
+ paddingVertical: "$3",
3424
+ paddingHorizontal: "$4",
3425
+ pressStyle: { backgroundColor: "$color3" },
3426
+ animation: "quick",
3427
+ cursor: "pointer",
3428
+ onPress: () => {
3429
+ const idx = item.options.findIndex((o) => o.value === item.value);
3430
+ const next = item.options[(idx + 1) % item.options.length];
3431
+ if (next) item.onValueChange(next.value);
3432
+ },
3433
+ children: [
3434
+ /* @__PURE__ */ jsx55(ItemLabel, { title: item.title, description: item.description }),
3435
+ /* @__PURE__ */ jsx55(SizableText47, { size: "$3", color: "$color9", fontWeight: "500", children: current?.label ?? item.value }),
3436
+ /* @__PURE__ */ jsx55(SizableText47, { size: "$4", color: "$color8", children: "\u203A" })
3437
+ ]
3438
+ }
3439
+ );
3440
+ }
3441
+ function SliderRow({ item }) {
3442
+ const min = item.min ?? 0;
3443
+ const max = item.max ?? 100;
3444
+ return /* @__PURE__ */ jsxs45(YStack44, { gap: "$2", paddingVertical: "$3", paddingHorizontal: "$4", children: [
3445
+ /* @__PURE__ */ jsxs45(XStack40, { justifyContent: "space-between", alignItems: "center", children: [
3446
+ /* @__PURE__ */ jsx55(ItemLabel, { title: item.title, description: item.description }),
3447
+ /* @__PURE__ */ jsx55(SizableText47, { size: "$3", fontWeight: "600", color: "$color11", children: item.value })
3448
+ ] }),
3449
+ /* @__PURE__ */ jsxs45(
3450
+ Slider,
3451
+ {
3452
+ value: [item.value],
3453
+ min,
3454
+ max,
3455
+ step: 1,
3456
+ onValueChange: ([v]) => {
3457
+ if (v !== void 0) item.onValueChange(v);
3458
+ },
3459
+ children: [
3460
+ /* @__PURE__ */ jsx55(Slider.Track, { backgroundColor: "$color4", height: 4, children: /* @__PURE__ */ jsx55(Slider.TrackActive, { backgroundColor: "$color9" }) }),
3461
+ /* @__PURE__ */ jsx55(Slider.Thumb, { index: 0, size: "$1.5", backgroundColor: "$color9", borderWidth: 0, circular: true })
3462
+ ]
3463
+ }
3464
+ )
3465
+ ] });
3466
+ }
3467
+ function ActionRow({ item }) {
3468
+ return /* @__PURE__ */ jsxs45(
3469
+ XStack40,
3470
+ {
3471
+ alignItems: "center",
3472
+ gap: "$3",
3473
+ paddingVertical: "$3",
3474
+ paddingHorizontal: "$4",
3475
+ pressStyle: { backgroundColor: "$color3" },
3476
+ animation: "quick",
3477
+ cursor: "pointer",
3478
+ onPress: item.onPress,
3479
+ children: [
3480
+ /* @__PURE__ */ jsx55(
3481
+ ItemLabel,
3482
+ {
3483
+ title: item.title,
3484
+ description: item.description,
3485
+ color: item.destructive ? "$red10" : void 0
3486
+ }
3487
+ ),
3488
+ /* @__PURE__ */ jsx55(SizableText47, { size: "$4", color: "$color8", children: "\u203A" })
3489
+ ]
3490
+ }
3491
+ );
3492
+ }
3493
+ function PreferenceRow({ item }) {
3494
+ switch (item.type) {
3495
+ case "toggle":
3496
+ return /* @__PURE__ */ jsx55(ToggleRow, { item });
3497
+ case "select":
3498
+ return /* @__PURE__ */ jsx55(SelectRow, { item });
3499
+ case "slider":
3500
+ return /* @__PURE__ */ jsx55(SliderRow, { item });
3501
+ case "action":
3502
+ return /* @__PURE__ */ jsx55(ActionRow, { item });
3503
+ }
3504
+ }
3505
+ function UserPreferences({ sections }) {
3506
+ return /* @__PURE__ */ jsx55(YStack44, { gap: "$5", children: sections.map((section, si) => /* @__PURE__ */ jsxs45(YStack44, { gap: "$2", children: [
3507
+ /* @__PURE__ */ jsxs45(YStack44, { paddingHorizontal: "$1", gap: "$0.5", children: [
3508
+ /* @__PURE__ */ jsx55(SizableText47, { size: "$2", fontWeight: "600", color: "$color9", textTransform: "uppercase", children: section.title }),
3509
+ section.description && /* @__PURE__ */ jsx55(SizableText47, { size: "$2", color: "$color8", children: section.description })
3510
+ ] }),
3511
+ /* @__PURE__ */ jsx55(
3512
+ YStack44,
3513
+ {
3514
+ backgroundColor: "$color2",
3515
+ borderRadius: "$4",
3516
+ overflow: "hidden",
3517
+ borderWidth: 1,
3518
+ borderColor: "$color4",
3519
+ children: section.items.map((item, ii) => /* @__PURE__ */ jsxs45(YStack44, { children: [
3520
+ /* @__PURE__ */ jsx55(PreferenceRow, { item }),
3521
+ ii < section.items.length - 1 && /* @__PURE__ */ jsx55(Separator6, { borderColor: "$color4" })
3522
+ ] }, item.id))
3523
+ }
3524
+ )
3525
+ ] }, si)) });
3526
+ }
3527
+
3528
+ // src/patterns/BlinkSelect.tsx
3529
+ import { Select, Adapt, Sheet as Sheet3, YStack as YStack45, SizableText as SizableText48 } from "tamagui";
3530
+ import { jsx as jsx56, jsxs as jsxs46 } from "react/jsx-runtime";
3531
+ function BlinkSelect({
3532
+ items,
3533
+ value,
3534
+ onValueChange,
3535
+ placeholder = "Select...",
3536
+ label,
3537
+ size = "$4",
3538
+ disabled,
3539
+ width = "100%"
3540
+ }) {
3541
+ return /* @__PURE__ */ jsxs46(YStack45, { gap: "$1.5", width, children: [
3542
+ label ? /* @__PURE__ */ jsx56(SizableText48, { size: "$3", fontWeight: "600", children: label }) : null,
3543
+ /* @__PURE__ */ jsxs46(
3544
+ Select,
3545
+ {
3546
+ value,
3547
+ onValueChange,
3548
+ disablePreventBodyScroll: true,
3549
+ ...disabled ? { disabled: true } : {},
3550
+ children: [
3551
+ /* @__PURE__ */ jsx56(Select.Trigger, { width: "100%", iconAfter: () => /* @__PURE__ */ jsx56(SizableText48, { children: "\u25BC" }), size, children: /* @__PURE__ */ jsx56(Select.Value, { placeholder }) }),
3552
+ /* @__PURE__ */ jsx56(Adapt, { when: "maxMd", platform: "touch", children: /* @__PURE__ */ jsxs46(Sheet3, { modal: true, dismissOnSnapToBottom: true, snapPointsMode: "fit", children: [
3553
+ /* @__PURE__ */ jsx56(Sheet3.Frame, { padding: "$4", children: /* @__PURE__ */ jsx56(Adapt.Contents, {}) }),
3554
+ /* @__PURE__ */ jsx56(Sheet3.Overlay, {})
3555
+ ] }) }),
3556
+ /* @__PURE__ */ jsxs46(Select.Content, { zIndex: 2e5, children: [
3557
+ /* @__PURE__ */ jsx56(Select.ScrollUpButton, { alignItems: "center", justifyContent: "center", height: "$3", children: /* @__PURE__ */ jsx56(SizableText48, { children: "\u25B2" }) }),
3558
+ /* @__PURE__ */ jsx56(Select.Viewport, { minWidth: 200, children: /* @__PURE__ */ jsx56(Select.Group, { children: items.map((item, i) => /* @__PURE__ */ jsxs46(Select.Item, { index: i, value: item.value, children: [
3559
+ /* @__PURE__ */ jsx56(Select.ItemText, { children: item.label }),
3560
+ /* @__PURE__ */ jsx56(Select.ItemIndicator, { marginLeft: "auto", children: /* @__PURE__ */ jsx56(SizableText48, { children: "\u2713" }) })
3561
+ ] }, item.value)) }) }),
3562
+ /* @__PURE__ */ jsx56(Select.ScrollDownButton, { alignItems: "center", justifyContent: "center", height: "$3", children: /* @__PURE__ */ jsx56(SizableText48, { children: "\u25BC" }) })
3563
+ ] })
3564
+ ]
3565
+ }
3566
+ )
3567
+ ] });
3568
+ }
3569
+
3570
+ // src/patterns/BlinkDialog.tsx
3571
+ import { Dialog, Adapt as Adapt2, Sheet as Sheet4, Button as Button11, XStack as XStack41 } from "tamagui";
3572
+ import { jsx as jsx57, jsxs as jsxs47 } from "react/jsx-runtime";
3573
+ function BlinkDialog({
3574
+ open,
3575
+ onOpenChange,
3576
+ trigger,
3577
+ title,
3578
+ description,
3579
+ children,
3580
+ confirmLabel = "Confirm",
3581
+ cancelLabel = "Cancel",
3582
+ onConfirm,
3583
+ onCancel,
3584
+ confirmTheme = "active"
3585
+ }) {
3586
+ return /* @__PURE__ */ jsxs47(Dialog, { modal: true, open, onOpenChange, children: [
3587
+ trigger && /* @__PURE__ */ jsx57(Dialog.Trigger, { asChild: true, children: trigger }),
3588
+ /* @__PURE__ */ jsx57(Adapt2, { when: "maxMd", platform: "touch", children: /* @__PURE__ */ jsxs47(Sheet4, { modal: true, dismissOnSnapToBottom: true, snapPointsMode: "fit", children: [
3589
+ /* @__PURE__ */ jsx57(Sheet4.Frame, { padding: "$4", gap: "$4", children: /* @__PURE__ */ jsx57(Adapt2.Contents, {}) }),
3590
+ /* @__PURE__ */ jsx57(Sheet4.Overlay, {})
3591
+ ] }) }),
3592
+ /* @__PURE__ */ jsxs47(Dialog.Portal, { children: [
3593
+ /* @__PURE__ */ jsx57(
3594
+ Dialog.Overlay,
3595
+ {
3596
+ animation: "quick",
3597
+ opacity: 0.5,
3598
+ enterStyle: { opacity: 0 },
3599
+ exitStyle: { opacity: 0 }
3600
+ },
3601
+ "overlay"
3602
+ ),
3603
+ /* @__PURE__ */ jsxs47(
3604
+ Dialog.Content,
3605
+ {
3606
+ bordered: true,
3607
+ elevate: true,
3608
+ animateOnly: ["transform", "opacity"],
3609
+ animation: ["quick", { opacity: { overshootClamping: true } }],
3610
+ enterStyle: { x: 0, y: -20, opacity: 0, scale: 0.9 },
3611
+ exitStyle: { x: 0, y: 10, opacity: 0, scale: 0.95 },
3612
+ gap: "$4",
3613
+ children: [
3614
+ title && /* @__PURE__ */ jsx57(Dialog.Title, { children: title }),
3615
+ description && /* @__PURE__ */ jsx57(Dialog.Description, { size: "$3", color: "$color10", children: description }),
3616
+ children,
3617
+ (onConfirm || onCancel) && /* @__PURE__ */ jsxs47(XStack41, { justifyContent: "flex-end", gap: "$3", children: [
3618
+ onCancel && /* @__PURE__ */ jsx57(Dialog.Close, { displayWhenAdapted: true, asChild: true, children: /* @__PURE__ */ jsx57(Button11, { variant: "outlined", onPress: onCancel, children: cancelLabel }) }),
3619
+ onConfirm && /* @__PURE__ */ jsx57(Dialog.Close, { displayWhenAdapted: true, asChild: true, children: /* @__PURE__ */ jsx57(Button11, { theme: confirmTheme, onPress: onConfirm, children: confirmLabel }) })
3620
+ ] })
3621
+ ]
3622
+ },
3623
+ "content"
3624
+ )
3625
+ ] })
3626
+ ] });
3627
+ }
3628
+
3629
+ // src/patterns/BlinkPopover.tsx
3630
+ import { Popover as Popover2, Adapt as Adapt3, YStack as YStack46 } from "tamagui";
3631
+ import { jsx as jsx58, jsxs as jsxs48 } from "react/jsx-runtime";
3632
+ function BlinkPopover({
3633
+ trigger,
3634
+ children,
3635
+ placement = "bottom",
3636
+ allowFlip = true,
3637
+ size = "$5"
3638
+ }) {
3639
+ return /* @__PURE__ */ jsxs48(Popover2, { size, allowFlip, placement, children: [
3640
+ /* @__PURE__ */ jsx58(Popover2.Trigger, { asChild: true, children: trigger }),
3641
+ /* @__PURE__ */ jsx58(Adapt3, { when: "maxMd", platform: "touch", children: /* @__PURE__ */ jsxs48(Popover2.Sheet, { modal: true, dismissOnSnapToBottom: true, snapPointsMode: "fit", children: [
3642
+ /* @__PURE__ */ jsx58(Popover2.Sheet.Frame, { padding: "$4", children: /* @__PURE__ */ jsx58(Adapt3.Contents, {}) }),
3643
+ /* @__PURE__ */ jsx58(Popover2.Sheet.Overlay, {})
3644
+ ] }) }),
3645
+ /* @__PURE__ */ jsxs48(
3646
+ Popover2.Content,
3647
+ {
3648
+ borderWidth: 1,
3649
+ borderColor: "$borderColor",
3650
+ enterStyle: { y: -10, opacity: 0 },
3651
+ exitStyle: { y: -10, opacity: 0 },
3652
+ elevate: true,
3653
+ animation: ["quick", { opacity: { overshootClamping: true } }],
3654
+ children: [
3655
+ /* @__PURE__ */ jsx58(Popover2.Arrow, { borderWidth: 1, borderColor: "$borderColor" }),
3656
+ /* @__PURE__ */ jsx58(YStack46, { gap: "$3", padding: "$3", children })
3657
+ ]
3658
+ }
3659
+ )
3660
+ ] });
3661
+ }
3662
+
3663
+ // src/index.ts
3664
+ export * from "@tamagui/lucide-icons";
3665
+
3666
+ // src/patterns/ImmersiveMediaScreen.tsx
3667
+ import { Button as Button12, SizableText as SizableText49, XStack as XStack42, YStack as YStack47 } from "tamagui";
3668
+ import { jsx as jsx59, jsxs as jsxs49 } from "react/jsx-runtime";
3669
+ function ImmersiveMediaScreen({
3670
+ variant = "reel",
3671
+ media,
3672
+ title,
3673
+ subtitle,
3674
+ topLeft,
3675
+ topCenter,
3676
+ topRight,
3677
+ actions = [],
3678
+ bottomMeta,
3679
+ inputPlaceholder,
3680
+ onInputPress,
3681
+ sheetContent
3682
+ }) {
3683
+ const showSheet = variant === "sheet";
3684
+ return /* @__PURE__ */ jsxs49(YStack47, { flex: 1, backgroundColor: "$color1", children: [
3685
+ /* @__PURE__ */ jsxs49(YStack47, { flex: 1, position: "relative", children: [
3686
+ media,
3687
+ /* @__PURE__ */ jsxs49(XStack42, { position: "absolute", top: "$5", left: "$4", right: "$4", justifyContent: "space-between", alignItems: "center", children: [
3688
+ /* @__PURE__ */ jsx59(XStack42, { minWidth: 56, children: topLeft }),
3689
+ /* @__PURE__ */ jsx59(YStack47, { alignItems: "center", flex: 1, children: topCenter }),
3690
+ /* @__PURE__ */ jsx59(XStack42, { minWidth: 56, justifyContent: "flex-end", children: topRight })
3691
+ ] }),
3692
+ actions.length > 0 ? /* @__PURE__ */ jsx59(YStack47, { position: "absolute", right: "$3", bottom: showSheet ? "$20" : "$10", gap: "$3", alignItems: "center", children: actions.map((action) => /* @__PURE__ */ jsxs49(YStack47, { gap: "$1", alignItems: "center", onPress: action.onPress, children: [
3693
+ /* @__PURE__ */ jsx59(
3694
+ YStack47,
3695
+ {
3696
+ width: 44,
3697
+ height: 44,
3698
+ borderRadius: "$10",
3699
+ backgroundColor: "rgba(0,0,0,0.55)",
3700
+ alignItems: "center",
3701
+ justifyContent: "center",
3702
+ children: action.icon ?? /* @__PURE__ */ jsx59(SizableText49, { size: "$5", color: "white", children: "\u2022" })
3703
+ }
3704
+ ),
3705
+ action.value ? /* @__PURE__ */ jsx59(SizableText49, { size: "$2", color: "white", children: action.value }) : null,
3706
+ action.label ? /* @__PURE__ */ jsx59(SizableText49, { size: "$1", color: "rgba(255,255,255,0.8)", children: action.label }) : null
3707
+ ] }, action.id)) }) : null,
3708
+ /* @__PURE__ */ jsxs49(YStack47, { position: "absolute", left: "$4", right: "$4", bottom: showSheet ? "$20" : "$6", gap: "$2", children: [
3709
+ title ? /* @__PURE__ */ jsx59(SizableText49, { size: "$6", fontWeight: "800", color: "white", children: title }) : null,
3710
+ subtitle ? /* @__PURE__ */ jsx59(SizableText49, { size: "$3", color: "rgba(255,255,255,0.82)", children: subtitle }) : null,
3711
+ bottomMeta,
3712
+ variant === "story" && inputPlaceholder ? /* @__PURE__ */ jsx59(
3713
+ XStack42,
3714
+ {
3715
+ onPress: onInputPress,
3716
+ alignItems: "center",
3717
+ paddingHorizontal: "$4",
3718
+ paddingVertical: "$3",
3719
+ borderRadius: "$10",
3720
+ backgroundColor: "rgba(255,255,255,0.14)",
3721
+ borderWidth: 1,
3722
+ borderColor: "rgba(255,255,255,0.25)",
3723
+ children: /* @__PURE__ */ jsx59(SizableText49, { size: "$3", color: "rgba(255,255,255,0.82)", children: inputPlaceholder })
3724
+ }
3725
+ ) : null
3726
+ ] })
3727
+ ] }),
3728
+ showSheet ? /* @__PURE__ */ jsxs49(YStack47, { padding: "$4", gap: "$3", backgroundColor: "$background", borderTopLeftRadius: "$8", borderTopRightRadius: "$8", marginTop: -18, children: [
3729
+ /* @__PURE__ */ jsx59(XStack42, { alignSelf: "center", width: 48, height: 5, borderRadius: "$10", backgroundColor: "$color5" }),
3730
+ sheetContent,
3731
+ inputPlaceholder ? /* @__PURE__ */ jsx59(Button12, { size: "$5", backgroundColor: "$color9", color: "$color1", onPress: onInputPress, children: inputPlaceholder }) : null
3732
+ ] }) : null
3733
+ ] });
3734
+ }
3735
+
3736
+ // src/patterns/FinanceDashboard.tsx
3737
+ import { SizableText as SizableText50, XStack as XStack43, YStack as YStack48 } from "tamagui";
3738
+ import { jsx as jsx60, jsxs as jsxs50 } from "react/jsx-runtime";
3739
+ function FinanceDashboard({
3740
+ title = "Overview",
3741
+ balanceLabel = "Available balance",
3742
+ balance,
3743
+ rangeLabel,
3744
+ metrics = [],
3745
+ quickActions = [],
3746
+ sections = [],
3747
+ chartSlot,
3748
+ topRight
3749
+ }) {
3750
+ return /* @__PURE__ */ jsxs50(YStack48, { flex: 1, backgroundColor: "$background", padding: "$4", gap: "$4", children: [
3751
+ /* @__PURE__ */ jsxs50(XStack43, { justifyContent: "space-between", alignItems: "center", paddingTop: "$4", children: [
3752
+ /* @__PURE__ */ jsxs50(YStack48, { gap: "$1", children: [
3753
+ /* @__PURE__ */ jsx60(SizableText50, { size: "$6", fontWeight: "700", children: title }),
3754
+ rangeLabel ? /* @__PURE__ */ jsx60(SizableText50, { size: "$2", color: "$color9", children: rangeLabel }) : null
3755
+ ] }),
3756
+ topRight
3757
+ ] }),
3758
+ /* @__PURE__ */ jsxs50(YStack48, { backgroundColor: "$color1", borderRadius: "$7", padding: "$4", gap: "$2", borderWidth: 1, borderColor: "$color4", children: [
3759
+ /* @__PURE__ */ jsx60(SizableText50, { size: "$3", color: "$color10", children: balanceLabel }),
3760
+ /* @__PURE__ */ jsx60(SizableText50, { size: "$11", fontWeight: "800", children: balance }),
3761
+ chartSlot ? /* @__PURE__ */ jsx60(YStack48, { marginTop: "$2", children: chartSlot }) : null
3762
+ ] }),
3763
+ metrics.length > 0 ? /* @__PURE__ */ jsx60(XStack43, { gap: "$3", flexWrap: "wrap", children: metrics.map((metric) => /* @__PURE__ */ jsxs50(YStack48, { flex: 1, minWidth: 120, backgroundColor: "$color1", borderRadius: "$6", padding: "$3", gap: "$1", borderWidth: 1, borderColor: "$color4", children: [
3764
+ /* @__PURE__ */ jsx60(SizableText50, { size: "$2", color: "$color10", children: metric.label }),
3765
+ /* @__PURE__ */ jsx60(SizableText50, { size: "$7", fontWeight: "800", children: metric.value }),
3766
+ metric.change ? /* @__PURE__ */ jsx60(SizableText50, { size: "$2", color: "$color9", children: metric.change }) : null
3767
+ ] }, metric.label)) }) : null,
3768
+ quickActions.length > 0 ? /* @__PURE__ */ jsx60(XStack43, { gap: "$3", flexWrap: "wrap", children: quickActions.map((action) => /* @__PURE__ */ jsxs50(
3769
+ YStack48,
3770
+ {
3771
+ flex: 1,
3772
+ minWidth: 88,
3773
+ backgroundColor: "$color1",
3774
+ borderRadius: "$6",
3775
+ padding: "$3",
3776
+ gap: "$2",
3777
+ alignItems: "center",
3778
+ justifyContent: "center",
3779
+ borderWidth: 1,
3780
+ borderColor: "$color4",
3781
+ onPress: action.onPress,
3782
+ children: [
3783
+ /* @__PURE__ */ jsx60(YStack48, { width: 36, height: 36, borderRadius: "$10", backgroundColor: "$color3", alignItems: "center", justifyContent: "center", children: action.icon ?? /* @__PURE__ */ jsx60(SizableText50, { size: "$4", children: "\u2022" }) }),
3784
+ /* @__PURE__ */ jsx60(SizableText50, { size: "$2", textAlign: "center", children: action.label })
3785
+ ]
3786
+ },
3787
+ action.id
3788
+ )) }) : null,
3789
+ /* @__PURE__ */ jsx60(YStack48, { gap: "$3", children: sections.map((section, index) => /* @__PURE__ */ jsxs50(YStack48, { backgroundColor: "$color1", borderRadius: "$6", borderWidth: 1, borderColor: "$color4", overflow: "hidden", children: [
3790
+ /* @__PURE__ */ jsx60(XStack43, { padding: "$3", justifyContent: "space-between", alignItems: "center", children: /* @__PURE__ */ jsx60(SizableText50, { size: "$4", fontWeight: "700", children: section.title }) }),
3791
+ /* @__PURE__ */ jsx60(YStack48, { children: section.rows.map((row, index2) => /* @__PURE__ */ jsxs50(
3792
+ XStack43,
3793
+ {
3794
+ padding: "$3",
3795
+ gap: "$3",
3796
+ alignItems: "center",
3797
+ borderTopWidth: index2 === 0 ? 0 : 1,
3798
+ borderTopColor: "$color4",
3799
+ children: [
3800
+ row.leading ? /* @__PURE__ */ jsx60(YStack48, { width: 32, height: 32, borderRadius: "$8", backgroundColor: "$color3", alignItems: "center", justifyContent: "center", children: row.leading }) : null,
3801
+ /* @__PURE__ */ jsxs50(YStack48, { flex: 1, children: [
3802
+ /* @__PURE__ */ jsx60(SizableText50, { size: "$3", fontWeight: "600", children: row.title }),
3803
+ row.subtitle ? /* @__PURE__ */ jsx60(SizableText50, { size: "$2", color: "$color10", children: row.subtitle }) : null
3804
+ ] }),
3805
+ row.value ? /* @__PURE__ */ jsx60(SizableText50, { size: "$3", color: "$color11", children: row.value }) : null
3806
+ ]
3807
+ },
3808
+ row.id
3809
+ )) })
3810
+ ] }, section.id ?? `${section.title}-${index}`)) })
3811
+ ] });
3812
+ }
1639
3813
  export {
1640
3814
  Accordion,
1641
3815
  ActionSheet,
1642
- Adapt,
1643
- AlertDialog2 as AlertDialog,
3816
+ Adapt4 as Adapt,
3817
+ AlertDialog3 as AlertDialog,
1644
3818
  Anchor,
3819
+ AnimatePresence,
1645
3820
  AppHeader,
3821
+ AppleLogo,
3822
+ Article,
3823
+ Aside,
1646
3824
  Avatar2 as Avatar,
3825
+ AvatarGroup,
3826
+ BLINK_DESIGN_THEMES,
3827
+ BLINK_DESIGN_THEME_IDS,
1647
3828
  Badge,
1648
3829
  BlinkAccordion,
1649
3830
  Avatar as BlinkAvatar,
1650
3831
  Button as BlinkButton,
1651
3832
  Card as BlinkCard,
3833
+ BlinkDialog,
1652
3834
  Input as BlinkInput,
3835
+ BlinkPopover,
3836
+ TamaguiProvider2 as BlinkProvider,
3837
+ BlinkSelect,
1653
3838
  BlinkTabs,
1654
3839
  BlinkText,
1655
3840
  BlinkToastProvider,
1656
3841
  BlinkToggleGroup,
1657
3842
  BlinkTooltip,
1658
3843
  BottomSheet,
1659
- Button8 as Button,
3844
+ Button13 as Button,
1660
3845
  Card2 as Card,
1661
3846
  Carousel,
1662
3847
  ChatBubble,
1663
3848
  Checkbox,
1664
- Circle8 as Circle,
3849
+ Chip,
3850
+ ChipGroup,
3851
+ Circle12 as Circle,
3852
+ ConfirmDialog,
1665
3853
  Container,
1666
- Dialog,
3854
+ CountdownBanner,
3855
+ DataTable,
3856
+ DatePicker,
3857
+ Dialog2 as Dialog,
1667
3858
  DialogProvider,
1668
3859
  Divider,
1669
3860
  EmptyState,
3861
+ EnsureFlexed,
3862
+ EventCard,
1670
3863
  Fieldset,
3864
+ FinanceDashboard,
1671
3865
  FloatingActionButton,
3866
+ Footer,
1672
3867
  Form,
1673
3868
  FormField,
3869
+ Frame,
3870
+ GitHubLogo,
3871
+ GlassCard,
3872
+ GoogleLogo,
1674
3873
  Grid,
3874
+ Group,
1675
3875
  H12 as H1,
1676
3876
  H22 as H2,
1677
3877
  H32 as H3,
1678
3878
  H42 as H4,
1679
3879
  H52 as H5,
1680
3880
  H62 as H6,
3881
+ Header,
3882
+ Heading,
1681
3883
  ICONS,
1682
3884
  Icon,
1683
3885
  Image2 as Image,
1684
- Input3 as Input,
3886
+ ImmersiveMediaScreen,
3887
+ Input5 as Input,
1685
3888
  KeyboardStickyFooter,
1686
3889
  Label,
1687
3890
  ListItem,
1688
3891
  LoginScreen,
3892
+ Main,
1689
3893
  MediaCard,
3894
+ MicrosoftLogo,
3895
+ Nav,
1690
3896
  NotificationBanner,
3897
+ OTPInput,
1691
3898
  OnboardingCarousel,
1692
3899
  PageContainer,
1693
3900
  PageMainContainer,
1694
3901
  Paragraph,
3902
+ PasswordInput,
1695
3903
  PaywallScreen,
1696
- Popover2 as Popover,
3904
+ Popover3 as Popover,
3905
+ Portal,
3906
+ PortalHost,
3907
+ PortalItem,
1697
3908
  PortalProvider,
1698
3909
  Pressable,
3910
+ PricingTable,
3911
+ ProductCard,
1699
3912
  ProfileHeader,
1700
3913
  Progress,
1701
3914
  ProgressSteps,
@@ -1703,56 +3916,91 @@ export {
1703
3916
  RadioGroup,
1704
3917
  SafeArea,
1705
3918
  ScreenLayout,
1706
- ScrollView5 as ScrollView,
3919
+ ScrollView6 as ScrollView,
1707
3920
  SearchBar,
1708
3921
  Section,
1709
- Select,
3922
+ Select2 as Select,
1710
3923
  SepHeading,
1711
- Separator5 as Separator,
3924
+ Separator7 as Separator,
1712
3925
  SettingsScreen,
1713
- Sheet3 as Sheet,
1714
- SizableText34 as SizableText,
3926
+ Sheet5 as Sheet,
3927
+ SizableStack,
3928
+ SizableText51 as SizableText,
1715
3929
  Skeleton,
1716
- Slider,
3930
+ Slider2 as Slider,
3931
+ Spacer,
1717
3932
  Spinner2 as Spinner,
1718
3933
  Square,
3934
+ Stack,
3935
+ StatusBadge,
1719
3936
  StepPageLayout,
1720
3937
  SubHeading,
3938
+ SwipeCards,
1721
3939
  SwipeableRow,
1722
- Switch2 as Switch,
3940
+ Switch3 as Switch,
1723
3941
  TabBar,
1724
3942
  Tabs,
1725
- Image6 as TamaguiImage,
3943
+ Image9 as TamaguiImage,
1726
3944
  ListItem2 as TamaguiListItem,
1727
3945
  TamaguiProvider,
3946
+ TestimonialCard2 as TestimonialCard,
1728
3947
  Text,
1729
3948
  TextArea,
1730
- Theme,
1731
- Toast,
1732
- ToastProvider,
1733
- ToastViewport,
3949
+ Theme2 as Theme,
3950
+ ThemeableStack,
1734
3951
  ToggleGroup,
1735
3952
  Tooltip,
1736
3953
  TooltipSimple,
1737
3954
  Unspaced,
1738
- View6 as View,
3955
+ UserPreferences,
3956
+ View7 as View,
1739
3957
  VisuallyHidden,
1740
3958
  XGroup,
1741
- XStack26 as XStack,
3959
+ XStack44 as XStack,
1742
3960
  YGroup,
1743
- YStack32 as YStack,
3961
+ YStack49 as YStack,
1744
3962
  ZStack,
3963
+ addTheme,
1745
3964
  blinkConfig,
3965
+ composeEventHandlers,
3966
+ composeRefs,
3967
+ createFont,
3968
+ createMedia,
3969
+ createStyledContext,
3970
+ createTamagui2 as createTamagui,
3971
+ createTheme,
3972
+ createTokens,
3973
+ createVariable,
1746
3974
  dialogConfirm,
3975
+ getBlinkDesignTheme,
3976
+ getBlinkThemePalettes,
3977
+ getConfig,
3978
+ getToken,
3979
+ getTokenValue,
3980
+ getTokens,
3981
+ isClient,
3982
+ isWeb,
3983
+ replaceTheme,
1747
3984
  showError,
1748
- styled12 as styled,
3985
+ styled14 as styled,
3986
+ defaultConfig2 as tamaguiDefaultConfig,
1749
3987
  toast,
3988
+ updateTheme,
1750
3989
  useBlinkToast,
1751
- useMedia,
3990
+ useComposedRefs,
3991
+ useControllableState,
3992
+ useDebounce,
3993
+ useDebounceValue,
3994
+ useDidFinishSSR,
3995
+ useEvent,
3996
+ useForceUpdate,
3997
+ useIsPresent,
3998
+ useIsomorphicLayoutEffect,
3999
+ useMedia2 as useMedia,
4000
+ usePresence,
1752
4001
  useTheme,
1753
4002
  useThemeName,
1754
- useToastController,
1755
- useToastState,
4003
+ useWindowDimensions,
1756
4004
  withStaticProperties2 as withStaticProperties
1757
4005
  };
1758
4006
  //# sourceMappingURL=index.mjs.map