@blinkdotnew/mobile-ui 2.0.0-alpha.5 → 2.0.0-alpha.7

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
@@ -8,11 +8,14 @@ var blinkConfig = createTamagui({
8
8
  // src/index.ts
9
9
  import {
10
10
  View as View6,
11
- XStack as XStack10,
12
- YStack as YStack14,
11
+ XStack as XStack26,
12
+ YStack as YStack32,
13
13
  ZStack,
14
- ScrollView,
15
- Circle as Circle6,
14
+ ScrollView as ScrollView5,
15
+ Circle as Circle8,
16
+ Square,
17
+ XGroup,
18
+ YGroup,
16
19
  H1 as H12,
17
20
  H2 as H22,
18
21
  H3 as H32,
@@ -20,28 +23,40 @@ import {
20
23
  H5 as H52,
21
24
  H6 as H62,
22
25
  Paragraph,
23
- SizableText as SizableText16,
26
+ SizableText as SizableText34,
24
27
  Text,
25
- Button as Button6,
26
- Input as Input2,
28
+ Label,
29
+ Button as Button8,
30
+ Input as Input3,
27
31
  TextArea,
28
32
  Switch as Switch2,
29
33
  Checkbox,
30
34
  Slider,
31
35
  RadioGroup,
32
36
  Select,
33
- Label,
37
+ Fieldset,
34
38
  Card as Card2,
35
39
  Avatar as Avatar2,
36
- Separator as Separator4,
37
- Image as Image5,
40
+ Separator as Separator5,
41
+ Image as Image6,
38
42
  Progress,
39
- Spinner,
40
- Sheet,
43
+ Spinner as Spinner2,
44
+ ListItem as ListItem2,
45
+ Sheet as Sheet3,
41
46
  Dialog,
42
47
  AlertDialog as AlertDialog2,
43
- Popover,
48
+ Popover as Popover2,
44
49
  Tooltip,
50
+ TooltipSimple,
51
+ Tabs,
52
+ Accordion,
53
+ ToggleGroup,
54
+ Adapt,
55
+ PortalProvider,
56
+ VisuallyHidden,
57
+ Unspaced,
58
+ Anchor,
59
+ Form,
45
60
  Theme,
46
61
  TamaguiProvider,
47
62
  styled as styled12,
@@ -523,23 +538,282 @@ function Badge({ children, variant = "default" }) {
523
538
  return /* @__PURE__ */ jsx5(BadgeFrame, { variant, children: /* @__PURE__ */ jsx5(BadgeText, { children }) });
524
539
  }
525
540
 
541
+ // src/interface/Icon.tsx
542
+ import { SizableText as SizableText6 } from "tamagui";
543
+ import { jsx as jsx6 } from "react/jsx-runtime";
544
+ var ICONS = {
545
+ home: "\u2302",
546
+ search: "\u2315",
547
+ back: "\u2039",
548
+ forward: "\u203A",
549
+ close: "\u2715",
550
+ menu: "\u2630",
551
+ more: "\u22EF",
552
+ plus: "+",
553
+ minus: "\u2212",
554
+ check: "\u2713",
555
+ star: "\u2605",
556
+ starOutline: "\u2606",
557
+ heart: "\u2665",
558
+ heartOutline: "\u2661",
559
+ share: "\u2934",
560
+ edit: "\u270E",
561
+ trash: "\u232B",
562
+ copy: "\u2398",
563
+ chat: "\u{1F4AC}",
564
+ mail: "\u2709",
565
+ bell: "\u{1F514}",
566
+ bellOff: "\u{1F515}",
567
+ send: "\u27A4",
568
+ play: "\u25B6",
569
+ pause: "\u23F8",
570
+ camera: "\u{1F4F7}",
571
+ image: "\u{1F5BC}",
572
+ info: "\u2139",
573
+ warning: "\u26A0",
574
+ error: "\u2715",
575
+ success: "\u2713",
576
+ loading: "\u27F3",
577
+ user: "\u{1F464}",
578
+ users: "\u{1F465}",
579
+ settings: "\u2699",
580
+ lock: "\u{1F512}",
581
+ unlock: "\u{1F513}",
582
+ arrowUp: "\u2191",
583
+ arrowDown: "\u2193",
584
+ arrowLeft: "\u2190",
585
+ arrowRight: "\u2192",
586
+ chevronUp: "\u2303",
587
+ chevronDown: "\u2304",
588
+ chevronLeft: "\u2039",
589
+ chevronRight: "\u203A"
590
+ };
591
+ function Icon({ name, size = 20, color = "$color12" }) {
592
+ return /* @__PURE__ */ jsx6(SizableText6, { fontSize: size, lineHeight: size, color, textAlign: "center", width: size, height: size, children: ICONS[name] });
593
+ }
594
+
595
+ // src/interface/BlinkAccordion.tsx
596
+ import { useState as useState2 } from "react";
597
+ import { Separator as Separator2, SizableText as SizableText7, XStack as XStack3, YStack as YStack3 } from "tamagui";
598
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
599
+ function BlinkAccordion({ items, defaultOpen, allowMultiple = false }) {
600
+ const [openIds, setOpenIds] = useState2(defaultOpen ?? []);
601
+ const toggle = (id) => {
602
+ setOpenIds((prev) => {
603
+ if (prev.includes(id)) return prev.filter((i) => i !== id);
604
+ return allowMultiple ? [...prev, id] : [id];
605
+ });
606
+ };
607
+ return /* @__PURE__ */ jsx7(YStack3, { children: items.map((item, index) => {
608
+ const isOpen = openIds.includes(item.id);
609
+ return /* @__PURE__ */ jsxs4(YStack3, { children: [
610
+ index > 0 && /* @__PURE__ */ jsx7(Separator2, { borderColor: "$borderColor" }),
611
+ /* @__PURE__ */ jsxs4(
612
+ XStack3,
613
+ {
614
+ paddingVertical: "$3",
615
+ paddingHorizontal: "$2",
616
+ justifyContent: "space-between",
617
+ alignItems: "center",
618
+ pressStyle: { opacity: 0.7 },
619
+ onPress: () => toggle(item.id),
620
+ cursor: "pointer",
621
+ children: [
622
+ /* @__PURE__ */ jsx7(SizableText7, { size: "$4", fontWeight: "600", children: item.title }),
623
+ /* @__PURE__ */ jsx7(SizableText7, { size: "$3", color: "$color10", children: isOpen ? "\u2303" : "\u2304" })
624
+ ]
625
+ }
626
+ ),
627
+ isOpen && /* @__PURE__ */ jsx7(YStack3, { paddingHorizontal: "$2", paddingBottom: "$3", children: item.content })
628
+ ] }, item.id);
629
+ }) });
630
+ }
631
+
632
+ // src/interface/BlinkTabs.tsx
633
+ import { useState as useState3 } from "react";
634
+ import { ScrollView } from "react-native";
635
+ import { SizableText as SizableText8, XStack as XStack4, YStack as YStack4 } from "tamagui";
636
+ import { jsx as jsx8 } from "react/jsx-runtime";
637
+ function BlinkTabs({ tabs, activeTab, onTabChange, variant = "underline" }) {
638
+ const [internalActive, setInternalActive] = useState3(tabs[0]?.key ?? "");
639
+ const current = activeTab ?? internalActive;
640
+ const handlePress = (key) => {
641
+ if (!activeTab) setInternalActive(key);
642
+ onTabChange?.(key);
643
+ };
644
+ return /* @__PURE__ */ jsx8(YStack4, { children: /* @__PURE__ */ jsx8(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: /* @__PURE__ */ jsx8(XStack4, { gap: "$2", paddingHorizontal: "$2", paddingBottom: "$2", children: tabs.map((tab) => {
645
+ const isActive = tab.key === current;
646
+ return /* @__PURE__ */ jsx8(
647
+ YStack4,
648
+ {
649
+ paddingVertical: "$2",
650
+ paddingHorizontal: "$3",
651
+ borderRadius: variant === "pill" ? "$4" : "$0",
652
+ backgroundColor: variant === "pill" && isActive ? "$color9" : "transparent",
653
+ borderBottomWidth: variant === "underline" ? 2 : 0,
654
+ borderBottomColor: variant === "underline" && isActive ? "$color9" : "transparent",
655
+ pressStyle: { opacity: 0.7 },
656
+ onPress: () => handlePress(tab.key),
657
+ cursor: "pointer",
658
+ children: /* @__PURE__ */ jsx8(
659
+ SizableText8,
660
+ {
661
+ size: "$3",
662
+ fontWeight: isActive ? "600" : "400",
663
+ color: variant === "pill" && isActive ? "$color1" : isActive ? "$color12" : "$color10",
664
+ children: tab.label
665
+ }
666
+ )
667
+ },
668
+ tab.key
669
+ );
670
+ }) }) }) });
671
+ }
672
+
673
+ // src/interface/BlinkToggleGroup.tsx
674
+ import { SizableText as SizableText9, XStack as XStack5 } from "tamagui";
675
+ import { jsx as jsx9 } from "react/jsx-runtime";
676
+ var sizeMap = { sm: "$2", md: "$3", lg: "$4" };
677
+ function BlinkToggleGroup({ options, value, onValueChange, size = "md" }) {
678
+ const textSize = sizeMap[size];
679
+ return /* @__PURE__ */ jsx9(XStack5, { borderRadius: "$4", overflow: "hidden", backgroundColor: "$color2", children: options.map((option, index) => {
680
+ const isActive = option.value === value;
681
+ return /* @__PURE__ */ jsx9(
682
+ XStack5,
683
+ {
684
+ flex: 1,
685
+ justifyContent: "center",
686
+ alignItems: "center",
687
+ paddingVertical: "$2",
688
+ paddingHorizontal: "$3",
689
+ backgroundColor: isActive ? "$color9" : "$color2",
690
+ borderLeftWidth: index > 0 ? 1 : 0,
691
+ borderLeftColor: isActive ? "$color9" : "$color4",
692
+ pressStyle: { opacity: 0.7 },
693
+ onPress: () => onValueChange(option.value),
694
+ cursor: "pointer",
695
+ children: /* @__PURE__ */ jsx9(SizableText9, { size: textSize, fontWeight: isActive ? "600" : "400", color: isActive ? "$color1" : "$color11", children: option.label })
696
+ },
697
+ option.value
698
+ );
699
+ }) });
700
+ }
701
+
702
+ // src/interface/BlinkToast.tsx
703
+ import { useState as useState4, useCallback, useEffect as useEffect2, createContext, useContext } from "react";
704
+ import { SizableText as SizableText10, YStack as YStack5 } from "tamagui";
705
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
706
+ var ToastContext = createContext(null);
707
+ var variantColors = {
708
+ default: "$color9",
709
+ success: "$green9",
710
+ error: "$red9",
711
+ warning: "$yellow9"
712
+ };
713
+ var globalToastShow = null;
714
+ var toast = (message, variant, duration) => {
715
+ if (globalToastShow) globalToastShow(message, variant, duration);
716
+ else console.warn("BlinkToastProvider not mounted");
717
+ };
718
+ function BlinkToastProvider({ children }) {
719
+ const [toasts, setToasts] = useState4([]);
720
+ const show = useCallback((message, variant = "default", duration = 3e3) => {
721
+ const id = Math.random().toString(36).slice(2, 9);
722
+ setToasts((prev) => [...prev, { id, message, variant, duration }]);
723
+ setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), duration);
724
+ }, []);
725
+ useEffect2(() => {
726
+ globalToastShow = show;
727
+ return () => {
728
+ globalToastShow = null;
729
+ };
730
+ }, [show]);
731
+ return /* @__PURE__ */ jsxs5(ToastContext.Provider, { value: { show }, children: [
732
+ children,
733
+ /* @__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(
734
+ YStack5,
735
+ {
736
+ backgroundColor: variantColors[t.variant ?? "default"],
737
+ paddingHorizontal: "$4",
738
+ paddingVertical: "$2.5",
739
+ borderRadius: "$4",
740
+ enterStyle: { opacity: 0, y: -10 },
741
+ exitStyle: { opacity: 0, y: -10 },
742
+ opacity: 1,
743
+ y: 0,
744
+ animation: "quick",
745
+ children: /* @__PURE__ */ jsx10(SizableText10, { size: "$3", color: "white", fontWeight: "600", children: t.message })
746
+ },
747
+ t.id
748
+ )) })
749
+ ] });
750
+ }
751
+ function useBlinkToast() {
752
+ const ctx = useContext(ToastContext);
753
+ if (!ctx) throw new Error("useBlinkToast must be used within BlinkToastProvider");
754
+ return ctx;
755
+ }
756
+
757
+ // src/interface/FormField.tsx
758
+ import { SizableText as SizableText11, YStack as YStack6 } from "tamagui";
759
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
760
+ function FormField({ label, error, helperText, required, children }) {
761
+ return /* @__PURE__ */ jsxs6(YStack6, { gap: "$1.5", children: [
762
+ label && /* @__PURE__ */ jsxs6(SizableText11, { size: "$3", fontWeight: "600", color: "$color11", children: [
763
+ label,
764
+ required && /* @__PURE__ */ jsx11(SizableText11, { color: "$red9", children: " *" })
765
+ ] }),
766
+ children,
767
+ helperText && !error && /* @__PURE__ */ jsx11(SizableText11, { size: "$2", color: "$color9", children: helperText }),
768
+ error && /* @__PURE__ */ jsx11(SizableText11, { size: "$2", color: "$red9", children: error })
769
+ ] });
770
+ }
771
+
772
+ // src/interface/Tooltip.tsx
773
+ import { Popover, SizableText as SizableText12 } from "tamagui";
774
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
775
+ function BlinkTooltip({ content, children, side = "top" }) {
776
+ return /* @__PURE__ */ jsxs7(Popover, { size: "$2", placement: side, children: [
777
+ /* @__PURE__ */ jsx12(Popover.Trigger, { asChild: true, children }),
778
+ /* @__PURE__ */ jsxs7(
779
+ Popover.Content,
780
+ {
781
+ backgroundColor: "$color11",
782
+ borderRadius: "$2",
783
+ paddingHorizontal: "$2.5",
784
+ paddingVertical: "$1.5",
785
+ elevate: true,
786
+ enterStyle: { opacity: 0, y: side === "bottom" ? -4 : 4 },
787
+ exitStyle: { opacity: 0, y: side === "bottom" ? -4 : 4 },
788
+ opacity: 1,
789
+ y: 0,
790
+ animation: "quick",
791
+ children: [
792
+ /* @__PURE__ */ jsx12(Popover.Arrow, { backgroundColor: "$color11", size: "$1" }),
793
+ /* @__PURE__ */ jsx12(SizableText12, { size: "$2", color: "$color1", children: content })
794
+ ]
795
+ }
796
+ )
797
+ ] });
798
+ }
799
+
526
800
  // src/layouts/StepPageLayout.tsx
527
- import { SizableText as SizableText6, YStack as YStack3 } from "tamagui";
528
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
801
+ import { SizableText as SizableText13, YStack as YStack7 } from "tamagui";
802
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
529
803
  function StepPageLayout({ title, description, children, bottom }) {
530
- return /* @__PURE__ */ jsxs4(YStack3, { flex: 1, padding: "$4", maxWidth: 500, marginHorizontal: "auto", width: "100%", children: [
531
- /* @__PURE__ */ jsx6(YStack3, { gap: "$5", children: /* @__PURE__ */ jsxs4(YStack3, { gap: "$2", children: [
532
- /* @__PURE__ */ jsx6(SizableText6, { size: "$8", fontWeight: "700", children: title }),
533
- description && /* @__PURE__ */ jsx6(SizableText6, { size: "$5", fontWeight: "400", color: "$color10", children: description })
804
+ return /* @__PURE__ */ jsxs8(YStack7, { flex: 1, padding: "$4", maxWidth: 500, marginHorizontal: "auto", width: "100%", children: [
805
+ /* @__PURE__ */ jsx13(YStack7, { gap: "$5", children: /* @__PURE__ */ jsxs8(YStack7, { gap: "$2", children: [
806
+ /* @__PURE__ */ jsx13(SizableText13, { size: "$8", fontWeight: "700", children: title }),
807
+ description && /* @__PURE__ */ jsx13(SizableText13, { size: "$5", fontWeight: "400", color: "$color10", children: description })
534
808
  ] }) }),
535
- /* @__PURE__ */ jsx6(YStack3, { paddingTop: "$5", gap: "$4", children }),
536
- bottom && /* @__PURE__ */ jsx6(YStack3, { paddingTop: "$4", children: bottom })
809
+ /* @__PURE__ */ jsx13(YStack7, { paddingTop: "$5", gap: "$4", children }),
810
+ bottom && /* @__PURE__ */ jsx13(YStack7, { paddingTop: "$4", children: bottom })
537
811
  ] });
538
812
  }
539
813
 
540
814
  // src/layouts/ScreenLayout.tsx
541
- import { styled as styled10, YStack as YStack4 } from "tamagui";
542
- var ScreenLayout = styled10(YStack4, {
815
+ import { styled as styled10, YStack as YStack8 } from "tamagui";
816
+ var ScreenLayout = styled10(YStack8, {
543
817
  name: "BlinkScreenLayout",
544
818
  flex: 1,
545
819
  backgroundColor: "$background",
@@ -557,22 +831,22 @@ var ScreenLayout = styled10(YStack4, {
557
831
  });
558
832
 
559
833
  // src/layouts/Section.tsx
560
- import { SizableText as SizableText7, YStack as YStack5 } from "tamagui";
561
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
834
+ import { SizableText as SizableText14, YStack as YStack9 } from "tamagui";
835
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
562
836
  function Section({ title, description, children, gap = "$3" }) {
563
- return /* @__PURE__ */ jsxs5(YStack5, { gap, children: [
564
- title && /* @__PURE__ */ jsxs5(YStack5, { gap: "$1", children: [
565
- /* @__PURE__ */ jsx7(SizableText7, { size: "$5", fontWeight: "600", color: "$color12", children: title }),
566
- description && /* @__PURE__ */ jsx7(SizableText7, { size: "$3", color: "$color9", children: description })
837
+ return /* @__PURE__ */ jsxs9(YStack9, { gap, children: [
838
+ title && /* @__PURE__ */ jsxs9(YStack9, { gap: "$1", children: [
839
+ /* @__PURE__ */ jsx14(SizableText14, { size: "$5", fontWeight: "600", color: "$color12", children: title }),
840
+ description && /* @__PURE__ */ jsx14(SizableText14, { size: "$3", color: "$color9", children: description })
567
841
  ] }),
568
842
  children
569
843
  ] });
570
844
  }
571
845
 
572
846
  // src/layouts/ListItem.tsx
573
- import { styled as styled11, SizableText as SizableText8, XStack as XStack3, YStack as YStack6, View as View5 } from "tamagui";
574
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
575
- var ListItemFrame = styled11(XStack3, {
847
+ import { styled as styled11, SizableText as SizableText15, XStack as XStack6, YStack as YStack10, View as View5 } from "tamagui";
848
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
849
+ var ListItemFrame = styled11(XStack6, {
576
850
  name: "BlinkListItem",
577
851
  alignItems: "center",
578
852
  gap: "$3",
@@ -589,38 +863,67 @@ var ListItemFrame = styled11(XStack3, {
589
863
  }
590
864
  });
591
865
  function ListItem({ icon, title, subtitle, right, onPress }) {
592
- return /* @__PURE__ */ jsxs6(ListItemFrame, { pressable: !!onPress, onPress, children: [
593
- icon && /* @__PURE__ */ jsx8(View5, { children: icon }),
594
- /* @__PURE__ */ jsxs6(YStack6, { flex: 1, gap: "$1", children: [
595
- /* @__PURE__ */ jsx8(SizableText8, { size: "$4", fontWeight: "500", color: "$color12", children: title }),
596
- subtitle && /* @__PURE__ */ jsx8(SizableText8, { size: "$2", color: "$color9", children: subtitle })
866
+ return /* @__PURE__ */ jsxs10(ListItemFrame, { pressable: !!onPress, onPress, children: [
867
+ icon && /* @__PURE__ */ jsx15(View5, { children: icon }),
868
+ /* @__PURE__ */ jsxs10(YStack10, { flex: 1, gap: "$1", children: [
869
+ /* @__PURE__ */ jsx15(SizableText15, { size: "$4", fontWeight: "500", color: "$color12", children: title }),
870
+ subtitle && /* @__PURE__ */ jsx15(SizableText15, { size: "$2", color: "$color9", children: subtitle })
597
871
  ] }),
598
872
  right
599
873
  ] });
600
874
  }
601
875
 
602
876
  // src/layouts/Divider.tsx
603
- import { Separator as Separator2, SizableText as SizableText9, XStack as XStack4 } from "tamagui";
604
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
877
+ import { Separator as Separator3, SizableText as SizableText16, XStack as XStack7 } from "tamagui";
878
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
605
879
  function Divider({ label }) {
606
- if (!label) return /* @__PURE__ */ jsx9(Separator2, { borderColor: "$color4" });
607
- return /* @__PURE__ */ jsxs7(XStack4, { alignItems: "center", gap: "$3", children: [
608
- /* @__PURE__ */ jsx9(Separator2, { flex: 1, borderColor: "$color4" }),
609
- /* @__PURE__ */ jsx9(SizableText9, { size: "$2", color: "$color9", children: label }),
610
- /* @__PURE__ */ jsx9(Separator2, { flex: 1, borderColor: "$color4" })
880
+ if (!label) return /* @__PURE__ */ jsx16(Separator3, { borderColor: "$color4" });
881
+ return /* @__PURE__ */ jsxs11(XStack7, { alignItems: "center", gap: "$3", children: [
882
+ /* @__PURE__ */ jsx16(Separator3, { flex: 1, borderColor: "$color4" }),
883
+ /* @__PURE__ */ jsx16(SizableText16, { size: "$2", color: "$color9", children: label }),
884
+ /* @__PURE__ */ jsx16(Separator3, { flex: 1, borderColor: "$color4" })
611
885
  ] });
612
886
  }
613
887
 
614
888
  // src/layouts/KeyboardStickyFooter.tsx
615
- import { YStack as YStack7 } from "tamagui";
616
- import { jsx as jsx10 } from "react/jsx-runtime";
889
+ import { YStack as YStack11 } from "tamagui";
890
+ import { jsx as jsx17 } from "react/jsx-runtime";
617
891
  function KeyboardStickyFooter({ children, offset }) {
618
- return /* @__PURE__ */ jsx10(YStack7, { maxWidth: 500, alignSelf: "center", paddingTop: "$8", paddingBottom: "$4", style: { paddingBottom: offset }, children });
892
+ return /* @__PURE__ */ jsx17(YStack11, { maxWidth: 500, alignSelf: "center", paddingTop: "$8", paddingBottom: "$4", style: { paddingBottom: offset }, children });
893
+ }
894
+
895
+ // src/layouts/SafeArea.tsx
896
+ import { YStack as YStack12 } from "tamagui";
897
+ import { jsx as jsx18 } from "react/jsx-runtime";
898
+ function SafeArea({ children, edges = ["top", "bottom"] }) {
899
+ return /* @__PURE__ */ jsx18(
900
+ YStack12,
901
+ {
902
+ flex: 1,
903
+ backgroundColor: "$background",
904
+ paddingTop: edges.includes("top") ? "$6" : void 0,
905
+ paddingBottom: edges.includes("bottom") ? "$6" : void 0,
906
+ paddingLeft: edges.includes("left") ? "$4" : void 0,
907
+ paddingRight: edges.includes("right") ? "$4" : void 0,
908
+ children
909
+ }
910
+ );
911
+ }
912
+
913
+ // src/layouts/Grid.tsx
914
+ import { XStack as XStack8, YStack as YStack13 } from "tamagui";
915
+ import { jsx as jsx19 } from "react/jsx-runtime";
916
+ function Grid({ children, columns = 2, gap = "$3" }) {
917
+ const childWidth = `${100 / columns}%`;
918
+ return /* @__PURE__ */ jsx19(XStack8, { flexWrap: "wrap", gap, children: Array.isArray(children) ? children.map((child, i) => /* @__PURE__ */ jsx19(YStack13, { width: childWidth, flexBasis: childWidth, children: child }, i)) : children });
919
+ }
920
+ function Container({ children, maxWidth = 500, centered = true }) {
921
+ return /* @__PURE__ */ jsx19(YStack13, { width: "100%", maxWidth, alignSelf: centered ? "center" : void 0, children });
619
922
  }
620
923
 
621
924
  // src/patterns/PaywallScreen.tsx
622
- import { Button as Button3, SizableText as SizableText10, XStack as XStack5, YStack as YStack8, Circle as Circle2 } from "tamagui";
623
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
925
+ import { Button as Button3, SizableText as SizableText17, XStack as XStack9, YStack as YStack14, Circle as Circle2 } from "tamagui";
926
+ import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
624
927
  function PaywallScreen({
625
928
  title = "Upgrade Your Experience",
626
929
  subtitle = "Choose the plan that works for you",
@@ -631,13 +934,13 @@ function PaywallScreen({
631
934
  onRestore,
632
935
  continueLabel = "Continue"
633
936
  }) {
634
- return /* @__PURE__ */ jsxs8(YStack8, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", children: [
635
- /* @__PURE__ */ jsxs8(YStack8, { gap: "$2", paddingTop: "$6", children: [
636
- /* @__PURE__ */ jsx11(SizableText10, { size: "$9", fontWeight: "700", textAlign: "center", children: title }),
637
- /* @__PURE__ */ jsx11(SizableText10, { size: "$4", color: "$color10", textAlign: "center", children: subtitle })
937
+ return /* @__PURE__ */ jsxs12(YStack14, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", children: [
938
+ /* @__PURE__ */ jsxs12(YStack14, { gap: "$2", paddingTop: "$6", children: [
939
+ /* @__PURE__ */ jsx20(SizableText17, { size: "$9", fontWeight: "700", textAlign: "center", children: title }),
940
+ /* @__PURE__ */ jsx20(SizableText17, { size: "$4", color: "$color10", textAlign: "center", children: subtitle })
638
941
  ] }),
639
- /* @__PURE__ */ jsx11(YStack8, { gap: "$3", flex: 1, children: plans.map((plan) => /* @__PURE__ */ jsxs8(
640
- YStack8,
942
+ /* @__PURE__ */ jsx20(YStack14, { gap: "$3", flex: 1, children: plans.map((plan) => /* @__PURE__ */ jsxs12(
943
+ YStack14,
641
944
  {
642
945
  padding: "$4",
643
946
  borderRadius: "$5",
@@ -648,29 +951,29 @@ function PaywallScreen({
648
951
  onPress: () => onSelectPlan?.(plan.id),
649
952
  cursor: "pointer",
650
953
  children: [
651
- /* @__PURE__ */ jsxs8(XStack5, { justifyContent: "space-between", alignItems: "center", children: [
652
- /* @__PURE__ */ jsxs8(YStack8, { children: [
653
- /* @__PURE__ */ jsx11(SizableText10, { size: "$5", fontWeight: "600", children: plan.name }),
654
- /* @__PURE__ */ jsxs8(XStack5, { alignItems: "baseline", gap: "$1", children: [
655
- /* @__PURE__ */ jsx11(SizableText10, { size: "$8", fontWeight: "700", children: plan.price }),
656
- /* @__PURE__ */ jsxs8(SizableText10, { size: "$3", color: "$color9", children: [
954
+ /* @__PURE__ */ jsxs12(XStack9, { justifyContent: "space-between", alignItems: "center", children: [
955
+ /* @__PURE__ */ jsxs12(YStack14, { children: [
956
+ /* @__PURE__ */ jsx20(SizableText17, { size: "$5", fontWeight: "600", children: plan.name }),
957
+ /* @__PURE__ */ jsxs12(XStack9, { alignItems: "baseline", gap: "$1", children: [
958
+ /* @__PURE__ */ jsx20(SizableText17, { size: "$8", fontWeight: "700", children: plan.price }),
959
+ /* @__PURE__ */ jsxs12(SizableText17, { size: "$3", color: "$color9", children: [
657
960
  "/",
658
961
  plan.period
659
962
  ] })
660
963
  ] })
661
964
  ] }),
662
- plan.popular && /* @__PURE__ */ jsx11(YStack8, { backgroundColor: "$color9", paddingHorizontal: "$2", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ jsx11(SizableText10, { size: "$1", color: "$color1", fontWeight: "600", children: "POPULAR" }) })
965
+ 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" }) })
663
966
  ] }),
664
- /* @__PURE__ */ jsx11(YStack8, { gap: "$2", paddingTop: "$3", children: plan.features.map((feature, i) => /* @__PURE__ */ jsxs8(XStack5, { gap: "$2", alignItems: "center", children: [
665
- /* @__PURE__ */ jsx11(Circle2, { size: 6, backgroundColor: "$green9" }),
666
- /* @__PURE__ */ jsx11(SizableText10, { size: "$3", color: "$color11", children: feature })
967
+ /* @__PURE__ */ jsx20(YStack14, { gap: "$2", paddingTop: "$3", children: plan.features.map((feature, i) => /* @__PURE__ */ jsxs12(XStack9, { gap: "$2", alignItems: "center", children: [
968
+ /* @__PURE__ */ jsx20(Circle2, { size: 6, backgroundColor: "$green9" }),
969
+ /* @__PURE__ */ jsx20(SizableText17, { size: "$3", color: "$color11", children: feature })
667
970
  ] }, i)) })
668
971
  ]
669
972
  },
670
973
  plan.id
671
974
  )) }),
672
- /* @__PURE__ */ jsxs8(YStack8, { gap: "$3", paddingBottom: "$4", children: [
673
- /* @__PURE__ */ jsx11(
975
+ /* @__PURE__ */ jsxs12(YStack14, { gap: "$3", paddingBottom: "$4", children: [
976
+ /* @__PURE__ */ jsx20(
674
977
  Button3,
675
978
  {
676
979
  size: "$5",
@@ -683,15 +986,15 @@ function PaywallScreen({
683
986
  children: continueLabel
684
987
  }
685
988
  ),
686
- onRestore && /* @__PURE__ */ jsx11(Button3, { size: "$3", chromeless: true, onPress: onRestore, children: /* @__PURE__ */ jsx11(SizableText10, { size: "$3", color: "$color9", children: "Restore Purchases" }) })
989
+ onRestore && /* @__PURE__ */ jsx20(Button3, { size: "$3", chromeless: true, onPress: onRestore, children: /* @__PURE__ */ jsx20(SizableText17, { size: "$3", color: "$color9", children: "Restore Purchases" }) })
687
990
  ] })
688
991
  ] });
689
992
  }
690
993
 
691
994
  // src/patterns/OnboardingCarousel.tsx
692
- import { useState as useState2 } from "react";
693
- import { Button as Button4, SizableText as SizableText11, XStack as XStack6, YStack as YStack9, Circle as Circle3 } from "tamagui";
694
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
995
+ import { useState as useState5 } from "react";
996
+ import { Button as Button4, SizableText as SizableText18, XStack as XStack10, YStack as YStack15, Circle as Circle3 } from "tamagui";
997
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
695
998
  function OnboardingCarousel({
696
999
  steps,
697
1000
  onComplete,
@@ -700,20 +1003,20 @@ function OnboardingCarousel({
700
1003
  skipLabel = "Skip",
701
1004
  nextLabel = "Next"
702
1005
  }) {
703
- const [current, setCurrent] = useState2(0);
1006
+ const [current, setCurrent] = useState5(0);
704
1007
  const isLast = current === steps.length - 1;
705
1008
  const step = steps[current];
706
- return /* @__PURE__ */ jsxs9(YStack9, { flex: 1, backgroundColor: "$background", padding: "$4", justifyContent: "space-between", children: [
707
- /* @__PURE__ */ jsx12(XStack6, { justifyContent: "flex-end", paddingTop: "$4", children: !isLast && onSkip && /* @__PURE__ */ jsx12(Button4, { chromeless: true, onPress: onSkip, children: /* @__PURE__ */ jsx12(SizableText11, { size: "$4", color: "$color9", children: skipLabel }) }) }),
708
- /* @__PURE__ */ jsxs9(YStack9, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$5", paddingHorizontal: "$4", children: [
709
- step?.icon && /* @__PURE__ */ jsx12(Circle3, { size: 120, backgroundColor: "$color2", alignItems: "center", justifyContent: "center", children: step.icon }),
710
- /* @__PURE__ */ jsxs9(YStack9, { gap: "$3", alignItems: "center", children: [
711
- /* @__PURE__ */ jsx12(SizableText11, { size: "$9", fontWeight: "700", textAlign: "center", children: step?.title }),
712
- /* @__PURE__ */ jsx12(SizableText11, { size: "$4", color: "$color10", textAlign: "center", maxWidth: 300, children: step?.description })
1009
+ return /* @__PURE__ */ jsxs13(YStack15, { flex: 1, backgroundColor: "$background", padding: "$4", justifyContent: "space-between", children: [
1010
+ /* @__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 }) }) }),
1011
+ /* @__PURE__ */ jsxs13(YStack15, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$5", paddingHorizontal: "$4", children: [
1012
+ step?.icon && /* @__PURE__ */ jsx21(Circle3, { size: 120, backgroundColor: "$color2", alignItems: "center", justifyContent: "center", children: step.icon }),
1013
+ /* @__PURE__ */ jsxs13(YStack15, { gap: "$3", alignItems: "center", children: [
1014
+ /* @__PURE__ */ jsx21(SizableText18, { size: "$9", fontWeight: "700", textAlign: "center", children: step?.title }),
1015
+ /* @__PURE__ */ jsx21(SizableText18, { size: "$4", color: "$color10", textAlign: "center", maxWidth: 300, children: step?.description })
713
1016
  ] })
714
1017
  ] }),
715
- /* @__PURE__ */ jsxs9(YStack9, { gap: "$3", paddingBottom: "$2", children: [
716
- /* @__PURE__ */ jsx12(XStack6, { justifyContent: "center", gap: "$2", children: steps.map((_, i) => /* @__PURE__ */ jsx12(
1018
+ /* @__PURE__ */ jsxs13(YStack15, { gap: "$3", paddingBottom: "$2", children: [
1019
+ /* @__PURE__ */ jsx21(XStack10, { justifyContent: "center", gap: "$2", children: steps.map((_, i) => /* @__PURE__ */ jsx21(
717
1020
  Circle3,
718
1021
  {
719
1022
  size: 8,
@@ -722,7 +1025,7 @@ function OnboardingCarousel({
722
1025
  },
723
1026
  i
724
1027
  )) }),
725
- /* @__PURE__ */ jsx12(
1028
+ /* @__PURE__ */ jsx21(
726
1029
  Button4,
727
1030
  {
728
1031
  size: "$5",
@@ -740,21 +1043,21 @@ function OnboardingCarousel({
740
1043
  }
741
1044
 
742
1045
  // src/patterns/ChatBubble.tsx
743
- import { SizableText as SizableText12, XStack as XStack7, YStack as YStack10, Circle as Circle4, Image as Image3 } from "tamagui";
744
- import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1046
+ import { SizableText as SizableText19, XStack as XStack11, YStack as YStack16, Circle as Circle4, Image as Image3 } from "tamagui";
1047
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
745
1048
  function ChatBubble({ message, showAvatar = true }) {
746
1049
  const isUser = message.sender === "user";
747
- return /* @__PURE__ */ jsxs10(
748
- XStack7,
1050
+ return /* @__PURE__ */ jsxs14(
1051
+ XStack11,
749
1052
  {
750
1053
  alignSelf: isUser ? "flex-end" : "flex-start",
751
1054
  maxWidth: "75%",
752
1055
  gap: "$2",
753
1056
  flexDirection: isUser ? "row-reverse" : "row",
754
1057
  children: [
755
- showAvatar && !isUser && /* @__PURE__ */ jsx13(Circle4, { size: 32, backgroundColor: "$color4", overflow: "hidden", children: message.avatar ? /* @__PURE__ */ jsx13(Image3, { source: { uri: message.avatar }, width: 32, height: 32, objectFit: "cover" }) : /* @__PURE__ */ jsx13(SizableText12, { size: "$2", fontWeight: "600", color: "$color11", children: message.senderName?.[0]?.toUpperCase() ?? "?" }) }),
756
- /* @__PURE__ */ jsxs10(
757
- YStack10,
1058
+ 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() ?? "?" }) }),
1059
+ /* @__PURE__ */ jsxs14(
1060
+ YStack16,
758
1061
  {
759
1062
  backgroundColor: isUser ? "$color9" : "$color3",
760
1063
  paddingHorizontal: "$3",
@@ -764,8 +1067,8 @@ function ChatBubble({ message, showAvatar = true }) {
764
1067
  borderBottomLeftRadius: isUser ? "$5" : "$2",
765
1068
  gap: "$1",
766
1069
  children: [
767
- /* @__PURE__ */ jsx13(SizableText12, { size: "$3", color: isUser ? "$color1" : "$color12", children: message.text }),
768
- message.timestamp && /* @__PURE__ */ jsx13(SizableText12, { size: "$1", color: isUser ? "$color3" : "$color9", alignSelf: "flex-end", children: message.timestamp })
1070
+ /* @__PURE__ */ jsx22(SizableText19, { size: "$3", color: isUser ? "$color1" : "$color12", children: message.text }),
1071
+ message.timestamp && /* @__PURE__ */ jsx22(SizableText19, { size: "$1", color: isUser ? "$color3" : "$color9", alignSelf: "flex-end", children: message.timestamp })
769
1072
  ]
770
1073
  }
771
1074
  )
@@ -775,11 +1078,11 @@ function ChatBubble({ message, showAvatar = true }) {
775
1078
  }
776
1079
 
777
1080
  // src/patterns/SettingsScreen.tsx
778
- import { Separator as Separator3, SizableText as SizableText13, Switch, XStack as XStack8, YStack as YStack11 } from "tamagui";
779
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1081
+ import { Separator as Separator4, SizableText as SizableText20, Switch, XStack as XStack12, YStack as YStack17 } from "tamagui";
1082
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
780
1083
  function SettingsItemRow({ item }) {
781
- return /* @__PURE__ */ jsxs11(
782
- XStack8,
1084
+ return /* @__PURE__ */ jsxs15(
1085
+ XStack12,
783
1086
  {
784
1087
  alignItems: "center",
785
1088
  gap: "$3",
@@ -790,22 +1093,22 @@ function SettingsItemRow({ item }) {
790
1093
  onPress: item.onPress,
791
1094
  cursor: item.onPress ? "pointer" : void 0,
792
1095
  children: [
793
- item.icon && /* @__PURE__ */ jsx14(YStack11, { width: 24, alignItems: "center", children: item.icon }),
794
- /* @__PURE__ */ jsxs11(YStack11, { flex: 1, gap: "$1", children: [
795
- /* @__PURE__ */ jsx14(SizableText13, { size: "$4", fontWeight: "500", children: item.title }),
796
- item.subtitle && /* @__PURE__ */ jsx14(SizableText13, { size: "$2", color: "$color9", children: item.subtitle })
1096
+ item.icon && /* @__PURE__ */ jsx23(YStack17, { width: 24, alignItems: "center", children: item.icon }),
1097
+ /* @__PURE__ */ jsxs15(YStack17, { flex: 1, gap: "$1", children: [
1098
+ /* @__PURE__ */ jsx23(SizableText20, { size: "$4", fontWeight: "500", children: item.title }),
1099
+ item.subtitle && /* @__PURE__ */ jsx23(SizableText20, { size: "$2", color: "$color9", children: item.subtitle })
797
1100
  ] }),
798
- item.type === "toggle" ? /* @__PURE__ */ jsx14(Switch, { size: "$3", checked: item.value, onCheckedChange: item.onValueChange, children: /* @__PURE__ */ jsx14(Switch.Thumb, { animation: "quick" }) }) : item.right ? item.right : item.onPress && /* @__PURE__ */ jsx14(SizableText13, { size: "$5", color: "$color8", children: "\u203A" })
1101
+ 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" })
799
1102
  ]
800
1103
  }
801
1104
  );
802
1105
  }
803
1106
  function SettingsScreen({ sections, header }) {
804
- return /* @__PURE__ */ jsxs11(YStack11, { flex: 1, backgroundColor: "$background", children: [
1107
+ return /* @__PURE__ */ jsxs15(YStack17, { flex: 1, backgroundColor: "$background", children: [
805
1108
  header,
806
- /* @__PURE__ */ jsx14(YStack11, { gap: "$4", paddingVertical: "$2", children: sections.map((section, si) => /* @__PURE__ */ jsxs11(YStack11, { children: [
807
- section.title && /* @__PURE__ */ jsx14(
808
- SizableText13,
1109
+ /* @__PURE__ */ jsx23(YStack17, { gap: "$4", paddingVertical: "$2", children: sections.map((section, si) => /* @__PURE__ */ jsxs15(YStack17, { children: [
1110
+ section.title && /* @__PURE__ */ jsx23(
1111
+ SizableText20,
809
1112
  {
810
1113
  size: "$2",
811
1114
  fontWeight: "600",
@@ -816,25 +1119,25 @@ function SettingsScreen({ sections, header }) {
816
1119
  children: section.title
817
1120
  }
818
1121
  ),
819
- /* @__PURE__ */ jsx14(YStack11, { backgroundColor: "$color1", borderRadius: "$4", marginHorizontal: "$3", overflow: "hidden", children: section.items.map((item, ii) => /* @__PURE__ */ jsxs11(YStack11, { children: [
820
- /* @__PURE__ */ jsx14(SettingsItemRow, { item }),
821
- ii < section.items.length - 1 && /* @__PURE__ */ jsx14(Separator3, { borderColor: "$color3", marginLeft: "$12" })
1122
+ /* @__PURE__ */ jsx23(YStack17, { backgroundColor: "$color1", borderRadius: "$4", marginHorizontal: "$3", overflow: "hidden", children: section.items.map((item, ii) => /* @__PURE__ */ jsxs15(YStack17, { children: [
1123
+ /* @__PURE__ */ jsx23(SettingsItemRow, { item }),
1124
+ ii < section.items.length - 1 && /* @__PURE__ */ jsx23(Separator4, { borderColor: "$color3", marginLeft: "$12" })
822
1125
  ] }, item.id)) })
823
1126
  ] }, si)) })
824
1127
  ] });
825
1128
  }
826
1129
 
827
1130
  // src/patterns/EmptyState.tsx
828
- import { Button as Button5, SizableText as SizableText14, YStack as YStack12 } from "tamagui";
829
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1131
+ import { Button as Button5, SizableText as SizableText21, YStack as YStack18 } from "tamagui";
1132
+ import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
830
1133
  function EmptyState({ icon, title, description, actionLabel, onAction }) {
831
- return /* @__PURE__ */ jsxs12(YStack12, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$4", padding: "$6", children: [
1134
+ return /* @__PURE__ */ jsxs16(YStack18, { flex: 1, alignItems: "center", justifyContent: "center", gap: "$4", padding: "$6", children: [
832
1135
  icon,
833
- /* @__PURE__ */ jsxs12(YStack12, { gap: "$2", alignItems: "center", children: [
834
- /* @__PURE__ */ jsx15(SizableText14, { size: "$6", fontWeight: "600", textAlign: "center", children: title }),
835
- description && /* @__PURE__ */ jsx15(SizableText14, { size: "$4", color: "$color9", textAlign: "center", maxWidth: 280, children: description })
1136
+ /* @__PURE__ */ jsxs16(YStack18, { gap: "$2", alignItems: "center", children: [
1137
+ /* @__PURE__ */ jsx24(SizableText21, { size: "$6", fontWeight: "600", textAlign: "center", children: title }),
1138
+ description && /* @__PURE__ */ jsx24(SizableText21, { size: "$4", color: "$color9", textAlign: "center", maxWidth: 280, children: description })
836
1139
  ] }),
837
- actionLabel && onAction && /* @__PURE__ */ jsx15(
1140
+ actionLabel && onAction && /* @__PURE__ */ jsx24(
838
1141
  Button5,
839
1142
  {
840
1143
  size: "$4",
@@ -851,89 +1154,582 @@ function EmptyState({ icon, title, description, actionLabel, onAction }) {
851
1154
  }
852
1155
 
853
1156
  // src/patterns/ProfileHeader.tsx
854
- import { Circle as Circle5, Image as Image4, SizableText as SizableText15, XStack as XStack9, YStack as YStack13 } from "tamagui";
855
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1157
+ import { Circle as Circle5, Image as Image4, SizableText as SizableText22, XStack as XStack13, YStack as YStack19 } from "tamagui";
1158
+ import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
856
1159
  function ProfileHeader({ name, subtitle, avatar, stats, actions }) {
857
- return /* @__PURE__ */ jsxs13(YStack13, { alignItems: "center", gap: "$4", paddingVertical: "$6", paddingHorizontal: "$4", children: [
858
- /* @__PURE__ */ jsx16(Circle5, { size: 80, backgroundColor: "$color4", overflow: "hidden", children: avatar ? /* @__PURE__ */ jsx16(Image4, { source: { uri: avatar }, width: 80, height: 80, objectFit: "cover" }) : /* @__PURE__ */ jsx16(SizableText15, { size: "$9", fontWeight: "700", color: "$color11", children: name[0]?.toUpperCase() ?? "?" }) }),
859
- /* @__PURE__ */ jsxs13(YStack13, { alignItems: "center", gap: "$1", children: [
860
- /* @__PURE__ */ jsx16(SizableText15, { size: "$7", fontWeight: "700", children: name }),
861
- subtitle && /* @__PURE__ */ jsx16(SizableText15, { size: "$4", color: "$color10", children: subtitle })
1160
+ return /* @__PURE__ */ jsxs17(YStack19, { alignItems: "center", gap: "$4", paddingVertical: "$6", paddingHorizontal: "$4", children: [
1161
+ /* @__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() ?? "?" }) }),
1162
+ /* @__PURE__ */ jsxs17(YStack19, { alignItems: "center", gap: "$1", children: [
1163
+ /* @__PURE__ */ jsx25(SizableText22, { size: "$7", fontWeight: "700", children: name }),
1164
+ subtitle && /* @__PURE__ */ jsx25(SizableText22, { size: "$4", color: "$color10", children: subtitle })
862
1165
  ] }),
863
- stats && stats.length > 0 && /* @__PURE__ */ jsx16(XStack9, { gap: "$6", children: stats.map((stat, i) => /* @__PURE__ */ jsxs13(YStack13, { alignItems: "center", gap: "$1", children: [
864
- /* @__PURE__ */ jsx16(SizableText15, { size: "$6", fontWeight: "700", children: stat.value }),
865
- /* @__PURE__ */ jsx16(SizableText15, { size: "$2", color: "$color9", children: stat.label })
1166
+ stats && stats.length > 0 && /* @__PURE__ */ jsx25(XStack13, { gap: "$6", children: stats.map((stat, i) => /* @__PURE__ */ jsxs17(YStack19, { alignItems: "center", gap: "$1", children: [
1167
+ /* @__PURE__ */ jsx25(SizableText22, { size: "$6", fontWeight: "700", children: stat.value }),
1168
+ /* @__PURE__ */ jsx25(SizableText22, { size: "$2", color: "$color9", children: stat.label })
866
1169
  ] }, i)) }),
867
1170
  actions
868
1171
  ] });
869
1172
  }
1173
+
1174
+ // src/patterns/AppHeader.tsx
1175
+ import { SizableText as SizableText23, XStack as XStack14, YStack as YStack20 } from "tamagui";
1176
+ import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
1177
+ function AppHeader({ title, subtitle, variant = "simple", onBack, avatar, left, right, transparent, borderless }) {
1178
+ const leftContent = (() => {
1179
+ if (variant === "back") return /* @__PURE__ */ jsx26(SizableText23, { size: "$6", paddingRight: "$2", onPress: onBack, pressStyle: { opacity: 0.6 }, cursor: "pointer", children: "\u2039" });
1180
+ if (variant === "profile") return /* @__PURE__ */ jsx26(Avatar, { uri: avatar, name: title, size: "sm" });
1181
+ if (variant === "centered") return left ?? null;
1182
+ return null;
1183
+ })();
1184
+ const rightContent = variant === "profile" || variant === "centered" ? right ?? null : null;
1185
+ return /* @__PURE__ */ jsx26(
1186
+ YStack20,
1187
+ {
1188
+ paddingTop: "$6",
1189
+ backgroundColor: transparent ? "transparent" : "$background",
1190
+ borderBottomWidth: borderless ? 0 : 1,
1191
+ borderBottomColor: "$borderColor",
1192
+ children: /* @__PURE__ */ jsxs18(XStack14, { height: 56, alignItems: "center", paddingHorizontal: "$4", gap: "$3", children: [
1193
+ leftContent,
1194
+ /* @__PURE__ */ jsxs18(YStack20, { flex: 1, alignItems: variant === "centered" ? "center" : "flex-start", children: [
1195
+ /* @__PURE__ */ jsx26(SizableText23, { size: "$6", fontWeight: "700", numberOfLines: 1, children: title }),
1196
+ subtitle && /* @__PURE__ */ jsx26(SizableText23, { size: "$2", color: "$color9", numberOfLines: 1, children: subtitle })
1197
+ ] }),
1198
+ rightContent
1199
+ ] })
1200
+ }
1201
+ );
1202
+ }
1203
+
1204
+ // src/patterns/BottomSheet.tsx
1205
+ import { Sheet, SizableText as SizableText24, XStack as XStack15, YStack as YStack21 } from "tamagui";
1206
+ import { ScrollView as ScrollView2 } from "react-native";
1207
+ import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
1208
+ function BottomSheet({ open, onOpenChange, title, children, snapPoints = [85], dismissOnSnapToBottom = true, showHandle = true, showClose = false }) {
1209
+ return /* @__PURE__ */ jsxs19(Sheet, { modal: true, open, onOpenChange, snapPoints, dismissOnSnapToBottom, animation: "medium", children: [
1210
+ /* @__PURE__ */ jsx27(Sheet.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1211
+ showHandle && /* @__PURE__ */ jsx27(Sheet.Handle, {}),
1212
+ /* @__PURE__ */ jsxs19(Sheet.Frame, { borderTopLeftRadius: "$6", borderTopRightRadius: "$6", backgroundColor: "$background", children: [
1213
+ (title || showClose) && /* @__PURE__ */ jsxs19(XStack15, { paddingHorizontal: "$4", paddingTop: "$3", paddingBottom: "$2", alignItems: "center", justifyContent: "space-between", children: [
1214
+ /* @__PURE__ */ jsx27(SizableText24, { size: "$6", fontWeight: "600", flexShrink: 1, children: title }),
1215
+ showClose && /* @__PURE__ */ jsx27(
1216
+ XStack15,
1217
+ {
1218
+ width: 28,
1219
+ height: 28,
1220
+ borderRadius: "$10",
1221
+ backgroundColor: "$color4",
1222
+ alignItems: "center",
1223
+ justifyContent: "center",
1224
+ pressStyle: { opacity: 0.7 },
1225
+ onPress: () => onOpenChange(false),
1226
+ children: /* @__PURE__ */ jsx27(SizableText24, { size: "$3", color: "$color10", fontWeight: "600", children: "\u2715" })
1227
+ }
1228
+ )
1229
+ ] }),
1230
+ /* @__PURE__ */ jsx27(ScrollView2, { contentContainerStyle: { paddingBottom: 40 }, children: /* @__PURE__ */ jsx27(YStack21, { padding: "$4", children }) })
1231
+ ] })
1232
+ ] });
1233
+ }
1234
+
1235
+ // src/patterns/LoginScreen.tsx
1236
+ import { useState as useState6 } from "react";
1237
+ import { Button as Button6, SizableText as SizableText25, Spinner, XStack as XStack16, YStack as YStack22 } from "tamagui";
1238
+ import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
1239
+ function LoginScreen({ title = "Welcome", subtitle = "Sign in to continue", logo, providers = [], onProviderPress, showEmailForm, onEmailSubmit, onForgotPassword, onCreateAccount, onTerms, onPrivacy, loading }) {
1240
+ const [email, setEmail] = useState6("");
1241
+ const [password, setPassword] = useState6("");
1242
+ return /* @__PURE__ */ jsxs20(YStack22, { flex: 1, padding: "$4", gap: "$5", backgroundColor: "$background", justifyContent: "center", children: [
1243
+ /* @__PURE__ */ jsxs20(YStack22, { alignItems: "center", gap: "$2", children: [
1244
+ logo && /* @__PURE__ */ jsx28(YStack22, { paddingBottom: "$3", children: logo }),
1245
+ /* @__PURE__ */ jsx28(SizableText25, { size: "$9", fontWeight: "700", textAlign: "center", children: title }),
1246
+ /* @__PURE__ */ jsx28(SizableText25, { size: "$4", color: "$color10", textAlign: "center", children: subtitle })
1247
+ ] }),
1248
+ providers.length > 0 && /* @__PURE__ */ jsx28(YStack22, { gap: "$2.5", children: providers.map((p) => /* @__PURE__ */ jsx28(
1249
+ Button6,
1250
+ {
1251
+ size: "$5",
1252
+ borderWidth: 1.5,
1253
+ borderColor: "$color5",
1254
+ backgroundColor: "$color1",
1255
+ borderRadius: "$4",
1256
+ disabled: loading,
1257
+ onPress: () => onProviderPress?.(p.id),
1258
+ hoverStyle: { backgroundColor: "$color2" },
1259
+ pressStyle: { backgroundColor: "$color3" },
1260
+ children: /* @__PURE__ */ jsxs20(XStack16, { alignItems: "center", gap: "$2", children: [
1261
+ p.icon,
1262
+ /* @__PURE__ */ jsx28(SizableText25, { size: "$4", fontWeight: "500", children: p.name })
1263
+ ] })
1264
+ },
1265
+ p.id
1266
+ )) }),
1267
+ showEmailForm && providers.length > 0 && /* @__PURE__ */ jsx28(Divider, { label: "or" }),
1268
+ showEmailForm && /* @__PURE__ */ jsxs20(YStack22, { gap: "$3", children: [
1269
+ /* @__PURE__ */ jsx28(Input, { label: "Email", placeholder: "your@email.com", value: email, onChangeText: setEmail, keyboardType: "email-address", autoCapitalize: "none" }),
1270
+ /* @__PURE__ */ jsx28(Input, { label: "Password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: password, onChangeText: setPassword, secureTextEntry: true }),
1271
+ onForgotPassword && /* @__PURE__ */ jsx28(XStack16, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx28(SizableText25, { size: "$3", color: "$color9", onPress: onForgotPassword, children: "Forgot password?" }) }),
1272
+ /* @__PURE__ */ jsx28(
1273
+ Button6,
1274
+ {
1275
+ size: "$5",
1276
+ backgroundColor: "$color9",
1277
+ color: "$color1",
1278
+ borderRadius: "$5",
1279
+ disabled: loading,
1280
+ onPress: () => onEmailSubmit?.(email, password),
1281
+ hoverStyle: { backgroundColor: "$color10" },
1282
+ pressStyle: { backgroundColor: "$color8" },
1283
+ icon: loading ? /* @__PURE__ */ jsx28(Spinner, { size: "small", color: "$color1" }) : void 0,
1284
+ children: "Sign In"
1285
+ }
1286
+ ),
1287
+ onCreateAccount && /* @__PURE__ */ jsx28(Button6, { size: "$3", chromeless: true, onPress: onCreateAccount, children: /* @__PURE__ */ jsx28(SizableText25, { size: "$3", color: "$color9", children: "Create Account" }) })
1288
+ ] }),
1289
+ (onTerms || onPrivacy) && /* @__PURE__ */ jsx28(YStack22, { paddingTop: "$2", alignItems: "center", children: /* @__PURE__ */ jsxs20(SizableText25, { size: "$2", color: "$color8", textAlign: "center", children: [
1290
+ "By continuing you agree to our",
1291
+ " ",
1292
+ onTerms && /* @__PURE__ */ jsx28(SizableText25, { size: "$2", color: "$color9", onPress: onTerms, children: "Terms of Service" }),
1293
+ onTerms && onPrivacy && " & ",
1294
+ onPrivacy && /* @__PURE__ */ jsx28(SizableText25, { size: "$2", color: "$color9", onPress: onPrivacy, children: "Privacy Policy" })
1295
+ ] }) })
1296
+ ] });
1297
+ }
1298
+
1299
+ // src/patterns/TabBar.tsx
1300
+ import { SizableText as SizableText26, XStack as XStack17, YStack as YStack23 } from "tamagui";
1301
+ import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
1302
+ function TabBar({ tabs, activeTab, onTabPress, showLabels = true }) {
1303
+ return /* @__PURE__ */ jsx29(XStack17, { height: 56, borderTopWidth: 1, borderTopColor: "$borderColor", backgroundColor: "$background", paddingBottom: "$2", children: tabs.map((tab) => {
1304
+ const active = tab.id === activeTab;
1305
+ return /* @__PURE__ */ jsxs21(
1306
+ YStack23,
1307
+ {
1308
+ flex: 1,
1309
+ alignItems: "center",
1310
+ justifyContent: "center",
1311
+ gap: "$1",
1312
+ pressStyle: { opacity: 0.6 },
1313
+ onPress: () => onTabPress(tab.id),
1314
+ children: [
1315
+ tab.icon && /* @__PURE__ */ jsx29(SizableText26, { size: "$5", color: active ? "$color9" : "$color8", children: tab.icon }),
1316
+ showLabels && /* @__PURE__ */ jsx29(SizableText26, { size: "$1", color: active ? "$color9" : "$color8", fontWeight: active ? "600" : "400", children: tab.label })
1317
+ ]
1318
+ },
1319
+ tab.id
1320
+ );
1321
+ }) });
1322
+ }
1323
+
1324
+ // src/patterns/SearchBar.tsx
1325
+ import { Input as Input2, SizableText as SizableText27, XStack as XStack18 } from "tamagui";
1326
+ import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
1327
+ function SearchBar({ value, onChangeText, placeholder = "Search\u2026", onFilter, onCancel, autoFocus }) {
1328
+ return /* @__PURE__ */ jsxs22(XStack18, { height: 44, borderRadius: "$10", backgroundColor: "$color2", alignItems: "center", paddingHorizontal: "$3", gap: "$2", children: [
1329
+ /* @__PURE__ */ jsx30(SizableText27, { size: "$4", color: "$color8", children: "\u2315" }),
1330
+ /* @__PURE__ */ jsx30(
1331
+ Input2,
1332
+ {
1333
+ flex: 1,
1334
+ size: "$4",
1335
+ value,
1336
+ onChangeText,
1337
+ placeholder,
1338
+ placeholderTextColor: "$color8",
1339
+ backgroundColor: "transparent",
1340
+ borderWidth: 0,
1341
+ autoFocus
1342
+ }
1343
+ ),
1344
+ onFilter && /* @__PURE__ */ jsx30(SizableText27, { size: "$4", color: "$color9", pressStyle: { opacity: 0.6 }, onPress: onFilter, children: "\u2ACF" }),
1345
+ onCancel && /* @__PURE__ */ jsx30(SizableText27, { size: "$3", color: "$color9", pressStyle: { opacity: 0.6 }, onPress: onCancel, children: "Cancel" })
1346
+ ] });
1347
+ }
1348
+
1349
+ // src/patterns/FloatingActionButton.tsx
1350
+ import { SizableText as SizableText28, XStack as XStack19 } from "tamagui";
1351
+ import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
1352
+ var sizes = { sm: 44, md: 56, lg: 68 };
1353
+ var positionStyles = {
1354
+ "bottom-right": { right: 20 },
1355
+ "bottom-center": { left: "50%", marginLeft: -28 },
1356
+ "bottom-left": { left: 20 }
1357
+ };
1358
+ function FloatingActionButton({ icon, label, onPress, position = "bottom-right", size = "md" }) {
1359
+ const dim = sizes[size];
1360
+ return /* @__PURE__ */ jsxs23(
1361
+ XStack19,
1362
+ {
1363
+ position: "absolute",
1364
+ bottom: 32,
1365
+ ...positionStyles[position],
1366
+ height: dim,
1367
+ minWidth: dim,
1368
+ borderRadius: label ? "$6" : "$10",
1369
+ backgroundColor: "$color9",
1370
+ alignItems: "center",
1371
+ justifyContent: "center",
1372
+ gap: "$2",
1373
+ paddingHorizontal: label ? "$4" : 0,
1374
+ elevation: 4,
1375
+ pressStyle: { scale: 0.95, opacity: 0.9 },
1376
+ onPress,
1377
+ children: [
1378
+ icon && /* @__PURE__ */ jsx31(SizableText28, { color: "$color1", children: icon }),
1379
+ label && /* @__PURE__ */ jsx31(SizableText28, { color: "$color1", size: "$4", fontWeight: "600", children: label })
1380
+ ]
1381
+ }
1382
+ );
1383
+ }
1384
+
1385
+ // src/patterns/ActionSheet.tsx
1386
+ import { Sheet as Sheet2, SizableText as SizableText29, XStack as XStack20, YStack as YStack24 } from "tamagui";
1387
+ import { jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
1388
+ function ActionSheet({ open, onOpenChange, title, items, onSelect, cancelLabel = "Cancel" }) {
1389
+ return /* @__PURE__ */ jsxs24(Sheet2, { modal: true, open, onOpenChange, snapPoints: [50], dismissOnSnapToBottom: true, animation: "medium", children: [
1390
+ /* @__PURE__ */ jsx32(Sheet2.Overlay, { animation: "lazy", enterStyle: { opacity: 0 }, exitStyle: { opacity: 0 } }),
1391
+ /* @__PURE__ */ jsx32(Sheet2.Handle, {}),
1392
+ /* @__PURE__ */ jsxs24(Sheet2.Frame, { borderTopLeftRadius: "$6", borderTopRightRadius: "$6", backgroundColor: "$background", children: [
1393
+ title && /* @__PURE__ */ jsx32(SizableText29, { size: "$3", color: "$color8", textAlign: "center", paddingTop: "$3", paddingBottom: "$1", children: title }),
1394
+ /* @__PURE__ */ jsx32(YStack24, { paddingHorizontal: "$3", paddingTop: "$2", children: items.map((item) => /* @__PURE__ */ jsxs24(
1395
+ XStack20,
1396
+ {
1397
+ height: 52,
1398
+ alignItems: "center",
1399
+ gap: "$3",
1400
+ paddingHorizontal: "$3",
1401
+ borderRadius: "$4",
1402
+ pressStyle: { backgroundColor: "$color3" },
1403
+ onPress: () => {
1404
+ onSelect(item.id);
1405
+ onOpenChange(false);
1406
+ },
1407
+ children: [
1408
+ item.icon && /* @__PURE__ */ jsx32(SizableText29, { size: "$5", children: item.icon }),
1409
+ /* @__PURE__ */ jsx32(
1410
+ SizableText29,
1411
+ {
1412
+ size: "$5",
1413
+ flex: 1,
1414
+ color: item.destructive ? "$red9" : "$color12",
1415
+ fontWeight: item.destructive ? "600" : "400",
1416
+ children: item.label
1417
+ }
1418
+ )
1419
+ ]
1420
+ },
1421
+ item.id
1422
+ )) }),
1423
+ /* @__PURE__ */ jsx32(YStack24, { paddingHorizontal: "$3", paddingVertical: "$3", borderTopWidth: 1, borderTopColor: "$borderColor", marginTop: "$2", children: /* @__PURE__ */ jsx32(
1424
+ XStack20,
1425
+ {
1426
+ height: 48,
1427
+ alignItems: "center",
1428
+ justifyContent: "center",
1429
+ borderRadius: "$4",
1430
+ pressStyle: { backgroundColor: "$color3" },
1431
+ onPress: () => onOpenChange(false),
1432
+ children: /* @__PURE__ */ jsx32(SizableText29, { size: "$5", fontWeight: "600", color: "$color9", children: cancelLabel })
1433
+ }
1434
+ ) })
1435
+ ] })
1436
+ ] });
1437
+ }
1438
+
1439
+ // src/patterns/Skeleton.tsx
1440
+ import { YStack as YStack25 } from "tamagui";
1441
+ import { jsx as jsx33 } from "react/jsx-runtime";
1442
+ function Skeleton({ width, height, borderRadius, variant = "rectangular" }) {
1443
+ const size = variant === "circular" ? height ?? 40 : height;
1444
+ const w = variant === "text" ? width ?? "100%" : width;
1445
+ const h = variant === "text" ? height ?? 16 : size;
1446
+ const r = variant === "circular" ? 9999 : borderRadius ?? 8;
1447
+ 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 } });
1448
+ }
1449
+
1450
+ // src/patterns/NotificationBanner.tsx
1451
+ import { SizableText as SizableText30, XStack as XStack21, YStack as YStack26 } from "tamagui";
1452
+ import { jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
1453
+ var variantColors2 = {
1454
+ info: { bg: "$blue3", text: "$blue11" },
1455
+ success: { bg: "$green3", text: "$green11" },
1456
+ warning: { bg: "$yellow3", text: "$yellow11" },
1457
+ error: { bg: "$red3", text: "$red11" }
1458
+ };
1459
+ function NotificationBanner({ title, message, variant = "info", onPress, onDismiss, icon }) {
1460
+ const colors = variantColors2[variant];
1461
+ return /* @__PURE__ */ jsxs25(
1462
+ XStack21,
1463
+ {
1464
+ backgroundColor: colors.bg,
1465
+ padding: "$3",
1466
+ borderRadius: "$4",
1467
+ gap: "$3",
1468
+ alignItems: "flex-start",
1469
+ onPress,
1470
+ pressStyle: onPress ? { opacity: 0.8 } : void 0,
1471
+ children: [
1472
+ icon && /* @__PURE__ */ jsx34(YStack26, { paddingTop: "$0.5", children: icon }),
1473
+ /* @__PURE__ */ jsxs25(YStack26, { flex: 1, gap: "$1", children: [
1474
+ /* @__PURE__ */ jsx34(SizableText30, { size: "$4", fontWeight: "600", color: colors.text, children: title }),
1475
+ message && /* @__PURE__ */ jsx34(SizableText30, { size: "$3", color: colors.text, opacity: 0.8, children: message })
1476
+ ] }),
1477
+ onDismiss && /* @__PURE__ */ jsx34(SizableText30, { size: "$3", color: colors.text, opacity: 0.6, onPress: onDismiss, padding: "$1", children: "\u2715" })
1478
+ ]
1479
+ }
1480
+ );
1481
+ }
1482
+
1483
+ // src/patterns/ProgressSteps.tsx
1484
+ import { Circle as Circle6, SizableText as SizableText31, XStack as XStack22, YStack as YStack27 } from "tamagui";
1485
+ import { jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
1486
+ function ProgressSteps({ steps, currentStep, variant = "dots" }) {
1487
+ if (variant === "bar") {
1488
+ const progress = steps.length > 1 ? currentStep / (steps.length - 1) * 100 : 100;
1489
+ return /* @__PURE__ */ jsxs26(YStack27, { gap: "$2", children: [
1490
+ /* @__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" }) }),
1491
+ /* @__PURE__ */ jsx35(XStack22, { justifyContent: "space-between", children: steps.map((label, i) => /* @__PURE__ */ jsx35(SizableText31, { size: "$2", color: i <= currentStep ? "$color9" : "$color8", children: label }, i)) })
1492
+ ] });
1493
+ }
1494
+ return /* @__PURE__ */ jsx35(XStack22, { alignItems: "center", justifyContent: "center", gap: "$0", children: steps.map((label, i) => /* @__PURE__ */ jsxs26(XStack22, { alignItems: "center", gap: "$0", children: [
1495
+ /* @__PURE__ */ jsxs26(YStack27, { alignItems: "center", gap: "$1.5", children: [
1496
+ /* @__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 }) }),
1497
+ /* @__PURE__ */ jsx35(SizableText31, { size: "$1", color: i <= currentStep ? "$color11" : "$color8", numberOfLines: 1, children: label })
1498
+ ] }),
1499
+ i < steps.length - 1 && /* @__PURE__ */ jsx35(YStack27, { height: 2, width: 32, backgroundColor: i < currentStep ? "$color9" : "$color4", marginBottom: "$4" })
1500
+ ] }, i)) });
1501
+ }
1502
+
1503
+ // src/patterns/SwipeableRow.tsx
1504
+ import { useState as useState7 } from "react";
1505
+ import { Button as Button7, SizableText as SizableText32, XStack as XStack23, YStack as YStack28 } from "tamagui";
1506
+ import { Fragment as Fragment2, jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
1507
+ function SwipeableRow({ children, leftActions, rightActions }) {
1508
+ const [showActions, setShowActions] = useState7(false);
1509
+ const actions = [...leftActions ?? [], ...rightActions ?? []];
1510
+ if (actions.length === 0) return /* @__PURE__ */ jsx36(Fragment2, { children });
1511
+ return /* @__PURE__ */ jsxs27(YStack28, { children: [
1512
+ /* @__PURE__ */ jsx36(YStack28, { onLongPress: () => setShowActions((v) => !v), pressStyle: { opacity: 0.9 }, children }),
1513
+ showActions && /* @__PURE__ */ jsx36(XStack23, { gap: "$2", padding: "$2", animation: "quick", enterStyle: { opacity: 0, scale: 0.95 }, children: actions.map((action) => /* @__PURE__ */ jsx36(
1514
+ Button7,
1515
+ {
1516
+ flex: 1,
1517
+ size: "$3",
1518
+ backgroundColor: action.color,
1519
+ borderRadius: "$3",
1520
+ onPress: () => {
1521
+ action.onPress();
1522
+ setShowActions(false);
1523
+ },
1524
+ children: /* @__PURE__ */ jsx36(SizableText32, { size: "$2", fontWeight: "600", color: "white", children: action.label })
1525
+ },
1526
+ action.id
1527
+ )) })
1528
+ ] });
1529
+ }
1530
+
1531
+ // src/patterns/MediaCard.tsx
1532
+ import { Image as Image5, SizableText as SizableText33, XStack as XStack24, YStack as YStack29 } from "tamagui";
1533
+ import { LinearGradient } from "tamagui/linear-gradient";
1534
+ import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
1535
+ function MediaCard({ image, title, subtitle, overlay = "gradient", aspectRatio = 16 / 9, onPress, badge }) {
1536
+ return /* @__PURE__ */ jsx37(
1537
+ YStack29,
1538
+ {
1539
+ borderRadius: "$4",
1540
+ overflow: "hidden",
1541
+ onPress,
1542
+ pressStyle: onPress ? { scale: 0.98, opacity: 0.9 } : void 0,
1543
+ animation: "quick",
1544
+ children: /* @__PURE__ */ jsxs28(YStack29, { aspectRatio, children: [
1545
+ /* @__PURE__ */ jsx37(Image5, { source: { uri: image }, width: "100%", height: "100%", objectFit: "cover" }),
1546
+ overlay === "gradient" && /* @__PURE__ */ jsx37(
1547
+ LinearGradient,
1548
+ {
1549
+ colors: ["transparent", "rgba(0,0,0,0.7)"],
1550
+ start: [0, 0],
1551
+ end: [0, 1],
1552
+ position: "absolute",
1553
+ bottom: 0,
1554
+ left: 0,
1555
+ right: 0,
1556
+ height: "60%"
1557
+ }
1558
+ ),
1559
+ overlay === "dark" && /* @__PURE__ */ jsx37(YStack29, { position: "absolute", fullscreen: true, backgroundColor: "rgba(0,0,0,0.4)" }),
1560
+ badge && /* @__PURE__ */ jsx37(
1561
+ XStack24,
1562
+ {
1563
+ position: "absolute",
1564
+ top: "$2",
1565
+ right: "$2",
1566
+ backgroundColor: "$color9",
1567
+ paddingHorizontal: "$2",
1568
+ paddingVertical: "$1",
1569
+ borderRadius: "$2",
1570
+ children: /* @__PURE__ */ jsx37(SizableText33, { size: "$1", fontWeight: "600", color: "$color1", children: badge })
1571
+ }
1572
+ ),
1573
+ /* @__PURE__ */ jsxs28(YStack29, { position: "absolute", bottom: 0, left: 0, right: 0, padding: "$3", gap: "$1", children: [
1574
+ /* @__PURE__ */ jsx37(SizableText33, { size: "$5", fontWeight: "600", color: "white", children: title }),
1575
+ subtitle && /* @__PURE__ */ jsx37(SizableText33, { size: "$3", color: "rgba(255,255,255,0.8)", children: subtitle })
1576
+ ] })
1577
+ ] })
1578
+ }
1579
+ );
1580
+ }
1581
+
1582
+ // src/patterns/Carousel.tsx
1583
+ import { Children, useState as useState8 } from "react";
1584
+ import { Circle as Circle7, XStack as XStack25, YStack as YStack30 } from "tamagui";
1585
+ import { ScrollView as ScrollView3 } from "react-native";
1586
+ import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
1587
+ function Carousel({ children, gap = "$3", snapToInterval, showIndicators = false }) {
1588
+ const [activeIndex, setActiveIndex] = useState8(0);
1589
+ const count = Children.count(children);
1590
+ const gapPx = gap === "$2" ? 8 : gap === "$3" ? 12 : 16;
1591
+ return /* @__PURE__ */ jsxs29(YStack30, { gap: "$3", children: [
1592
+ /* @__PURE__ */ jsx38(
1593
+ ScrollView3,
1594
+ {
1595
+ horizontal: true,
1596
+ showsHorizontalScrollIndicator: false,
1597
+ snapToInterval,
1598
+ decelerationRate: "fast",
1599
+ contentContainerStyle: { gap: gapPx, paddingHorizontal: 16 },
1600
+ onMomentumScrollEnd: (e) => {
1601
+ if (snapToInterval) setActiveIndex(Math.round(e.nativeEvent.contentOffset.x / snapToInterval));
1602
+ },
1603
+ children
1604
+ }
1605
+ ),
1606
+ 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)) })
1607
+ ] });
1608
+ }
1609
+
1610
+ // src/patterns/PullToRefresh.tsx
1611
+ import { YStack as YStack31 } from "tamagui";
1612
+ import { RefreshControl, ScrollView as ScrollView4 } from "react-native";
1613
+ import { jsx as jsx39 } from "react/jsx-runtime";
1614
+ function PullToRefresh({ children, onRefresh, refreshing = false }) {
1615
+ return /* @__PURE__ */ jsx39(
1616
+ ScrollView4,
1617
+ {
1618
+ contentContainerStyle: { flexGrow: 1 },
1619
+ refreshControl: /* @__PURE__ */ jsx39(RefreshControl, { refreshing, onRefresh }),
1620
+ children: /* @__PURE__ */ jsx39(YStack31, { flex: 1, children })
1621
+ }
1622
+ );
1623
+ }
870
1624
  export {
1625
+ Accordion,
1626
+ ActionSheet,
1627
+ Adapt,
871
1628
  AlertDialog2 as AlertDialog,
1629
+ Anchor,
1630
+ AppHeader,
872
1631
  Avatar2 as Avatar,
873
1632
  Badge,
1633
+ BlinkAccordion,
874
1634
  Avatar as BlinkAvatar,
875
1635
  Button as BlinkButton,
876
1636
  Card as BlinkCard,
877
1637
  Input as BlinkInput,
1638
+ BlinkTabs,
878
1639
  BlinkText,
879
- Button6 as Button,
1640
+ BlinkToastProvider,
1641
+ BlinkToggleGroup,
1642
+ BlinkTooltip,
1643
+ BottomSheet,
1644
+ Button8 as Button,
880
1645
  Card2 as Card,
1646
+ Carousel,
881
1647
  ChatBubble,
882
1648
  Checkbox,
883
- Circle6 as Circle,
1649
+ Circle8 as Circle,
1650
+ Container,
884
1651
  Dialog,
885
1652
  DialogProvider,
886
1653
  Divider,
887
1654
  EmptyState,
1655
+ Fieldset,
1656
+ FloatingActionButton,
1657
+ Form,
1658
+ FormField,
1659
+ Grid,
888
1660
  H12 as H1,
889
1661
  H22 as H2,
890
1662
  H32 as H3,
891
1663
  H42 as H4,
892
1664
  H52 as H5,
893
1665
  H62 as H6,
1666
+ ICONS,
1667
+ Icon,
894
1668
  Image2 as Image,
895
- Input2 as Input,
1669
+ Input3 as Input,
896
1670
  KeyboardStickyFooter,
897
1671
  Label,
898
1672
  ListItem,
1673
+ LoginScreen,
1674
+ MediaCard,
1675
+ NotificationBanner,
899
1676
  OnboardingCarousel,
900
1677
  PageContainer,
901
1678
  PageMainContainer,
902
1679
  Paragraph,
903
1680
  PaywallScreen,
904
- Popover,
1681
+ Popover2 as Popover,
1682
+ PortalProvider,
905
1683
  Pressable,
906
1684
  ProfileHeader,
907
1685
  Progress,
1686
+ ProgressSteps,
1687
+ PullToRefresh,
908
1688
  RadioGroup,
1689
+ SafeArea,
909
1690
  ScreenLayout,
910
- ScrollView,
1691
+ ScrollView5 as ScrollView,
1692
+ SearchBar,
911
1693
  Section,
912
1694
  Select,
913
1695
  SepHeading,
914
- Separator4 as Separator,
1696
+ Separator5 as Separator,
915
1697
  SettingsScreen,
916
- Sheet,
917
- SizableText16 as SizableText,
1698
+ Sheet3 as Sheet,
1699
+ SizableText34 as SizableText,
1700
+ Skeleton,
918
1701
  Slider,
919
- Spinner,
1702
+ Spinner2 as Spinner,
1703
+ Square,
920
1704
  StepPageLayout,
921
1705
  SubHeading,
1706
+ SwipeableRow,
922
1707
  Switch2 as Switch,
923
- Image5 as TamaguiImage,
1708
+ TabBar,
1709
+ Tabs,
1710
+ Image6 as TamaguiImage,
1711
+ ListItem2 as TamaguiListItem,
924
1712
  TamaguiProvider,
925
1713
  Text,
926
1714
  TextArea,
927
1715
  Theme,
1716
+ ToggleGroup,
928
1717
  Tooltip,
1718
+ TooltipSimple,
1719
+ Unspaced,
929
1720
  View6 as View,
930
- XStack10 as XStack,
931
- YStack14 as YStack,
1721
+ VisuallyHidden,
1722
+ XGroup,
1723
+ XStack26 as XStack,
1724
+ YGroup,
1725
+ YStack32 as YStack,
932
1726
  ZStack,
933
1727
  blinkConfig,
934
1728
  dialogConfirm,
935
1729
  showError,
936
1730
  styled12 as styled,
1731
+ toast,
1732
+ useBlinkToast,
937
1733
  useMedia,
938
1734
  useTheme,
939
1735
  useThemeName,