@blinkdotnew/mobile-ui 2.0.0-alpha.12 → 2.0.0-alpha.13

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,13 +8,13 @@ var blinkConfig = createTamagui({
8
8
  // src/index.ts
9
9
  import { defaultConfig as defaultConfig2 } from "@tamagui/config/v5";
10
10
  import {
11
- View as View6,
11
+ View as View7,
12
12
  Stack,
13
13
  SizableStack,
14
14
  ThemeableStack,
15
15
  Frame,
16
- XStack as XStack37,
17
- YStack as YStack41,
16
+ XStack as XStack41,
17
+ YStack as YStack45,
18
18
  ZStack,
19
19
  ScrollView as ScrollView7,
20
20
  Circle as Circle9,
@@ -38,22 +38,22 @@ import {
38
38
  H6 as H62,
39
39
  Heading,
40
40
  Paragraph,
41
- SizableText as SizableText44,
41
+ SizableText as SizableText48,
42
42
  Text,
43
43
  Label,
44
44
  Button as Button11,
45
45
  Input as Input5,
46
46
  TextArea,
47
- Switch as Switch2,
47
+ Switch as Switch3,
48
48
  Checkbox,
49
- Slider,
49
+ Slider as Slider2,
50
50
  RadioGroup,
51
51
  Select,
52
52
  Fieldset,
53
53
  Form,
54
54
  Card as Card2,
55
55
  Avatar as Avatar2,
56
- Separator as Separator5,
56
+ Separator as Separator7,
57
57
  Image as Image9,
58
58
  Progress,
59
59
  Spinner as Spinner2,
@@ -76,7 +76,7 @@ import {
76
76
  Adapt,
77
77
  VisuallyHidden,
78
78
  Unspaced,
79
- Theme,
79
+ Theme as Theme2,
80
80
  TamaguiProvider,
81
81
  TamaguiProvider as TamaguiProvider2,
82
82
  createTamagui as createTamagui2,
@@ -89,7 +89,7 @@ import {
89
89
  addTheme,
90
90
  updateTheme,
91
91
  replaceTheme,
92
- styled as styled13,
92
+ styled as styled14,
93
93
  withStaticProperties as withStaticProperties2,
94
94
  isWeb,
95
95
  isClient,
@@ -100,7 +100,7 @@ import {
100
100
  composeRefs,
101
101
  composeEventHandlers,
102
102
  useTheme,
103
- useMedia,
103
+ useMedia as useMedia2,
104
104
  useThemeName,
105
105
  useControllableState,
106
106
  useEvent,
@@ -2311,21 +2311,26 @@ function ChipGroup({ chips, selected = [], onSelectionChange, multiSelect = true
2311
2311
  }
2312
2312
 
2313
2313
  // src/patterns/OTPInput.tsx
2314
- import { useCallback as useCallback4, useRef as useRef2 } from "react";
2314
+ import { useCallback as useCallback4, useRef as useRef2, useState as useState11 } from "react";
2315
+ import { Platform } from "react-native";
2315
2316
  import { Input as Input3, SizableText as SizableText40, XStack as XStack33, YStack as YStack37 } from "tamagui";
2316
2317
  import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
2317
2318
  function OTPInput({ length = 6, value = "", onChange, onComplete, error, autoFocus, secureEntry }) {
2318
2319
  const inputRef = useRef2(null);
2320
+ const [focused, setFocused] = useState11(false);
2319
2321
  const digits = value.padEnd(length, " ").slice(0, length);
2320
2322
  const handleChange = useCallback4((text) => {
2321
2323
  const cleaned = text.replace(/\D/g, "").slice(0, length);
2322
2324
  onChange?.(cleaned);
2323
2325
  if (cleaned.length === length) onComplete?.(cleaned);
2324
2326
  }, [length, onChange, onComplete]);
2325
- return /* @__PURE__ */ jsxs37(YStack37, { children: [
2326
- /* @__PURE__ */ jsx46(XStack33, { gap: "$2", justifyContent: "center", onPress: () => inputRef.current?.focus(), children: Array.from({ length }, (_, i) => {
2327
+ const focusInput = useCallback4(() => {
2328
+ inputRef.current?.focus();
2329
+ }, []);
2330
+ return /* @__PURE__ */ jsxs37(YStack37, { position: "relative", children: [
2331
+ /* @__PURE__ */ jsx46(XStack33, { gap: "$2", justifyContent: "center", children: Array.from({ length }, (_, i) => {
2327
2332
  const char = digits[i]?.trim();
2328
- const focused = value.length === i;
2333
+ const isCursor = focused && value.length === i;
2329
2334
  return /* @__PURE__ */ jsxs37(
2330
2335
  YStack37,
2331
2336
  {
@@ -2333,20 +2338,59 @@ function OTPInput({ length = 6, value = "", onChange, onComplete, error, autoFoc
2333
2338
  height: 56,
2334
2339
  borderRadius: "$3",
2335
2340
  borderWidth: 2,
2336
- borderColor: error ? "$red9" : focused ? "$color9" : "$color6",
2337
- backgroundColor: error ? "$red2" : "$color2",
2341
+ borderColor: error ? "$red9" : isCursor ? "$color9" : char ? "$color7" : "$color5",
2342
+ backgroundColor: error ? "$red2" : isCursor ? "$color2" : "$color1",
2338
2343
  alignItems: "center",
2339
2344
  justifyContent: "center",
2340
2345
  animation: "quick",
2346
+ pointerEvents: "none",
2341
2347
  children: [
2342
2348
  /* @__PURE__ */ jsx46(SizableText40, { size: "$7", fontWeight: "600", color: "$color12", children: char ? secureEntry ? "\u25CF" : char : "" }),
2343
- focused && /* @__PURE__ */ jsx46(YStack37, { position: "absolute", bottom: 10, width: 20, height: 2, backgroundColor: "$color9", animation: "quick" })
2349
+ isCursor && /* @__PURE__ */ jsx46(
2350
+ YStack37,
2351
+ {
2352
+ position: "absolute",
2353
+ bottom: 10,
2354
+ width: 20,
2355
+ height: 2,
2356
+ backgroundColor: "$color9",
2357
+ animation: "quick"
2358
+ }
2359
+ )
2344
2360
  ]
2345
2361
  },
2346
2362
  i
2347
2363
  );
2348
2364
  }) }),
2349
- /* @__PURE__ */ jsx46(
2365
+ Platform.OS === "web" ? /* @__PURE__ */ jsx46(
2366
+ "input",
2367
+ {
2368
+ ref: inputRef,
2369
+ type: "text",
2370
+ inputMode: "numeric",
2371
+ pattern: "[0-9]*",
2372
+ autoComplete: "one-time-code",
2373
+ maxLength: length,
2374
+ value,
2375
+ autoFocus,
2376
+ onChange: (e) => handleChange(e.target.value),
2377
+ onFocus: () => setFocused(true),
2378
+ onBlur: () => setFocused(false),
2379
+ style: {
2380
+ position: "absolute",
2381
+ top: 0,
2382
+ left: 0,
2383
+ right: 0,
2384
+ bottom: 0,
2385
+ width: "100%",
2386
+ height: "100%",
2387
+ opacity: 0,
2388
+ fontSize: 16,
2389
+ caretColor: "transparent",
2390
+ cursor: "pointer"
2391
+ }
2392
+ }
2393
+ ) : /* @__PURE__ */ jsx46(
2350
2394
  Input3,
2351
2395
  {
2352
2396
  ref: inputRef,
@@ -2355,17 +2399,22 @@ function OTPInput({ length = 6, value = "", onChange, onComplete, error, autoFoc
2355
2399
  keyboardType: "number-pad",
2356
2400
  maxLength: length,
2357
2401
  autoFocus,
2402
+ onFocus: () => setFocused(true),
2403
+ onBlur: () => setFocused(false),
2358
2404
  position: "absolute",
2405
+ top: 0,
2406
+ left: 0,
2407
+ right: 0,
2408
+ bottom: 0,
2359
2409
  opacity: 0,
2360
- width: 1,
2361
- height: 1
2410
+ fontSize: 16
2362
2411
  }
2363
2412
  )
2364
2413
  ] });
2365
2414
  }
2366
2415
 
2367
2416
  // src/patterns/PasswordInput.tsx
2368
- import { useState as useState11, useCallback as useCallback5 } from "react";
2417
+ import { useState as useState12, useCallback as useCallback5 } from "react";
2369
2418
  import { Input as Input4, SizableText as SizableText41, XStack as XStack34, YStack as YStack38 } from "tamagui";
2370
2419
  import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
2371
2420
  function getStrength(pw) {
@@ -2376,7 +2425,7 @@ function getStrength(pw) {
2376
2425
  return { label: "Strong", color: "$green9", width: "100%" };
2377
2426
  }
2378
2427
  function PasswordInput({ value = "", onChangeText, placeholder = "Password", label, error, size = "$4", strengthIndicator }) {
2379
- const [visible, setVisible] = useState11(false);
2428
+ const [visible, setVisible] = useState12(false);
2380
2429
  const toggle = useCallback5(() => setVisible((v) => !v), []);
2381
2430
  const strength = getStrength(value);
2382
2431
  return /* @__PURE__ */ jsxs38(YStack38, { gap: "$1.5", children: [
@@ -2475,7 +2524,7 @@ function AvatarGroup({ avatars, max = 4, size = 36, overlap = 10 }) {
2475
2524
  }
2476
2525
 
2477
2526
  // src/patterns/SwipeCards.tsx
2478
- import { useState as useState12, useCallback as useCallback6 } from "react";
2527
+ import { useState as useState13, useCallback as useCallback6 } from "react";
2479
2528
  import { Circle as Circle8, SizableText as SizableText43, XStack as XStack36, YStack as YStack39 } from "tamagui";
2480
2529
  import { jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
2481
2530
  var STACK_SIZE = 3;
@@ -2494,8 +2543,8 @@ function SwipeCards({
2494
2543
  rightLabel = "Like",
2495
2544
  emptyMessage = "No more cards"
2496
2545
  }) {
2497
- const [index, setIndex] = useState12(0);
2498
- const [exitDir, setExitDir] = useState12(null);
2546
+ const [index, setIndex] = useState13(0);
2547
+ const [exitDir, setExitDir] = useState13(null);
2499
2548
  const remaining = items.slice(index);
2500
2549
  const isEmpty = remaining.length === 0;
2501
2550
  const handleSwipe = useCallback6((dir) => {
@@ -2650,6 +2699,442 @@ function GlassCard({
2650
2699
  }
2651
2700
  );
2652
2701
  }
2702
+
2703
+ // src/patterns/DataTable.tsx
2704
+ import { useMemo, useState as useState14 } from "react";
2705
+ import { SizableText as SizableText44, Separator as Separator5, XStack as XStack37, YStack as YStack41, useMedia, styled as styled13, View as View6 } from "tamagui";
2706
+ import { jsx as jsx51, jsxs as jsxs41 } from "react/jsx-runtime";
2707
+ var TH = styled13(View6, { padding: "$3", justifyContent: "center" });
2708
+ var TD = styled13(View6, { padding: "$3", justifyContent: "center" });
2709
+ function StatusBadge({ status }) {
2710
+ const isActive = status.toLowerCase() === "active";
2711
+ return /* @__PURE__ */ jsxs41(XStack37, { gap: "$2", alignItems: "center", children: [
2712
+ /* @__PURE__ */ jsx51(
2713
+ View6,
2714
+ {
2715
+ width: 8,
2716
+ height: 8,
2717
+ borderRadius: 4,
2718
+ backgroundColor: isActive ? "$green9" : "$orange9"
2719
+ }
2720
+ ),
2721
+ /* @__PURE__ */ jsx51(SizableText44, { size: "$3", color: "$color11", children: status })
2722
+ ] });
2723
+ }
2724
+ function HeaderCell({ col, sort, onSort }) {
2725
+ const active = sort?.key === col.key;
2726
+ const indicator = active ? sort.dir === "asc" ? " \u25B2" : " \u25BC" : "";
2727
+ return /* @__PURE__ */ jsx51(
2728
+ TH,
2729
+ {
2730
+ width: col.width,
2731
+ flexDirection: "row",
2732
+ alignItems: "center",
2733
+ cursor: col.sortable ? "pointer" : void 0,
2734
+ onPress: col.sortable ? onSort : void 0,
2735
+ pressStyle: col.sortable ? { opacity: 0.7 } : void 0,
2736
+ children: /* @__PURE__ */ jsxs41(
2737
+ SizableText44,
2738
+ {
2739
+ size: "$2",
2740
+ fontWeight: "700",
2741
+ color: active ? "$color12" : "$color9",
2742
+ textTransform: "uppercase",
2743
+ letterSpacing: 0.5,
2744
+ children: [
2745
+ col.header,
2746
+ indicator
2747
+ ]
2748
+ }
2749
+ )
2750
+ },
2751
+ col.key
2752
+ );
2753
+ }
2754
+ function TableRow({ row, columns, onPress, odd }) {
2755
+ return /* @__PURE__ */ jsx51(
2756
+ XStack37,
2757
+ {
2758
+ backgroundColor: odd ? "$color2" : "transparent",
2759
+ borderBottomWidth: 0.5,
2760
+ borderColor: "$color4",
2761
+ hoverStyle: { backgroundColor: "$color3" },
2762
+ cursor: onPress ? "pointer" : void 0,
2763
+ onPress: onPress ? () => onPress(row) : void 0,
2764
+ pressStyle: onPress ? { opacity: 0.85 } : void 0,
2765
+ animation: "quick",
2766
+ children: columns.map((col) => /* @__PURE__ */ jsx51(TD, { width: col.width, flex: col.width ? void 0 : 1, children: col.render ? col.render(row[col.key], row) : /* @__PURE__ */ jsx51(SizableText44, { size: "$3", color: "$color11", children: String(row[col.key] ?? "") }) }, col.key))
2767
+ }
2768
+ );
2769
+ }
2770
+ function CardRow({ row, columns, onPress }) {
2771
+ return /* @__PURE__ */ jsx51(
2772
+ YStack41,
2773
+ {
2774
+ backgroundColor: "$color1",
2775
+ borderRadius: "$4",
2776
+ borderWidth: 1,
2777
+ borderColor: "$color4",
2778
+ padding: "$3",
2779
+ gap: "$2",
2780
+ onPress: onPress ? () => onPress(row) : void 0,
2781
+ pressStyle: onPress ? { scale: 0.98, opacity: 0.9 } : void 0,
2782
+ animation: "quick",
2783
+ children: columns.map((col, i) => /* @__PURE__ */ jsxs41(YStack41, { children: [
2784
+ i > 0 && /* @__PURE__ */ jsx51(Separator5, { marginVertical: "$1.5", borderColor: "$color4" }),
2785
+ /* @__PURE__ */ jsxs41(XStack37, { justifyContent: "space-between", alignItems: "center", children: [
2786
+ /* @__PURE__ */ jsx51(SizableText44, { size: "$2", color: "$color9", fontWeight: "600", children: col.header }),
2787
+ col.render ? col.render(row[col.key], row) : /* @__PURE__ */ jsx51(SizableText44, { size: "$3", color: "$color11", children: String(row[col.key] ?? "") })
2788
+ ] })
2789
+ ] }, col.key))
2790
+ }
2791
+ );
2792
+ }
2793
+ function DataTable({ columns, data, onRowPress, emptyMessage = "No data" }) {
2794
+ const [sort, setSort] = useState14(null);
2795
+ const media = useMedia();
2796
+ const isSmall = media.sm;
2797
+ const sorted = useMemo(() => {
2798
+ if (!sort) return data;
2799
+ return [...data].sort((a, b) => {
2800
+ const av = a[sort.key], bv = b[sort.key];
2801
+ const cmp = typeof av === "number" && typeof bv === "number" ? av - bv : String(av ?? "").localeCompare(String(bv ?? ""));
2802
+ return sort.dir === "asc" ? cmp : -cmp;
2803
+ });
2804
+ }, [data, sort]);
2805
+ const toggleSort = (key) => setSort((s) => s?.key === key ? { key, dir: s.dir === "asc" ? "desc" : "asc" } : { key, dir: "asc" });
2806
+ if (!data.length) {
2807
+ return /* @__PURE__ */ jsx51(YStack41, { padding: "$6", alignItems: "center", children: /* @__PURE__ */ jsx51(SizableText44, { size: "$4", color: "$color9", children: emptyMessage }) });
2808
+ }
2809
+ if (isSmall) {
2810
+ return /* @__PURE__ */ jsx51(YStack41, { gap: "$3", children: sorted.map((row, i) => /* @__PURE__ */ jsx51(CardRow, { row, columns, onPress: onRowPress }, i)) });
2811
+ }
2812
+ return /* @__PURE__ */ jsxs41(YStack41, { borderWidth: 1, borderColor: "$color4", borderRadius: "$4", overflow: "hidden", children: [
2813
+ /* @__PURE__ */ jsx51(XStack37, { backgroundColor: "$color1", borderBottomWidth: 1, borderColor: "$color4", children: columns.map((col) => /* @__PURE__ */ jsx51(HeaderCell, { col, sort, onSort: () => toggleSort(col.key) }, col.key)) }),
2814
+ sorted.map((row, i) => /* @__PURE__ */ jsx51(TableRow, { row, columns, onPress: onRowPress, odd: i % 2 === 1 }, i))
2815
+ ] });
2816
+ }
2817
+
2818
+ // src/patterns/DatePicker.tsx
2819
+ import { useCallback as useCallback7, useMemo as useMemo2, useState as useState15 } from "react";
2820
+ import { SizableText as SizableText45, XStack as XStack38, YStack as YStack42 } from "tamagui";
2821
+ import { jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
2822
+ var MONTH_NAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
2823
+ var DAY_LABELS_SUN = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
2824
+ var DAY_LABELS_MON = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
2825
+ function daysInMonth(year, month) {
2826
+ return new Date(year, month + 1, 0).getDate();
2827
+ }
2828
+ function sameDay(a, b) {
2829
+ return a ? a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate() : false;
2830
+ }
2831
+ function buildGrid(year, month, startDay) {
2832
+ const total = daysInMonth(year, month);
2833
+ const firstWeekday = new Date(year, month, 1).getDay();
2834
+ const offset = (firstWeekday - startDay + 7) % 7;
2835
+ const prevTotal = daysInMonth(year, month - 1);
2836
+ const cells = [];
2837
+ for (let i = offset - 1; i >= 0; i--)
2838
+ cells.push({ day: prevTotal - i, month: month - 1, year: month === 0 ? year - 1 : year, outside: true });
2839
+ for (let d = 1; d <= total; d++)
2840
+ cells.push({ day: d, month, year, outside: false });
2841
+ while (cells.length < 42)
2842
+ cells.push({ day: cells.length - offset - total + 1, month: month + 1, year: month === 11 ? year + 1 : year, outside: true });
2843
+ return cells;
2844
+ }
2845
+ function NavButton({ label, onPress }) {
2846
+ return /* @__PURE__ */ jsx52(
2847
+ XStack38,
2848
+ {
2849
+ width: 36,
2850
+ height: 36,
2851
+ borderRadius: "$10",
2852
+ alignItems: "center",
2853
+ justifyContent: "center",
2854
+ backgroundColor: "$color3",
2855
+ pressStyle: { scale: 0.92, backgroundColor: "$color5" },
2856
+ animation: "quick",
2857
+ onPress,
2858
+ cursor: "pointer",
2859
+ children: /* @__PURE__ */ jsx52(SizableText45, { size: "$5", color: "$color11", fontWeight: "600", children: label })
2860
+ }
2861
+ );
2862
+ }
2863
+ function DatePicker({ value, onDateChange, minDate, maxDate, startDay = 1 }) {
2864
+ const today = useMemo2(() => /* @__PURE__ */ new Date(), []);
2865
+ const [viewMonth, setViewMonth] = useState15(value?.getMonth() ?? today.getMonth());
2866
+ const [viewYear, setViewYear] = useState15(value?.getFullYear() ?? today.getFullYear());
2867
+ const headers = startDay === 1 ? DAY_LABELS_MON : DAY_LABELS_SUN;
2868
+ const grid = useMemo2(() => buildGrid(viewYear, viewMonth, startDay), [viewYear, viewMonth, startDay]);
2869
+ const navigate = useCallback7((dir) => {
2870
+ setViewMonth((m) => {
2871
+ const next = m + dir;
2872
+ if (next < 0) {
2873
+ setViewYear((y) => y - 1);
2874
+ return 11;
2875
+ }
2876
+ if (next > 11) {
2877
+ setViewYear((y) => y + 1);
2878
+ return 0;
2879
+ }
2880
+ return next;
2881
+ });
2882
+ }, []);
2883
+ const isDisabled = useCallback7((d) => {
2884
+ if (minDate && d < new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate())) return true;
2885
+ if (maxDate && d > new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate())) return true;
2886
+ return false;
2887
+ }, [minDate, maxDate]);
2888
+ return /* @__PURE__ */ jsxs42(YStack42, { backgroundColor: "$color2", borderRadius: "$4", padding: "$3", gap: "$2", animation: "quick", children: [
2889
+ /* @__PURE__ */ jsxs42(XStack38, { alignItems: "center", justifyContent: "space-between", children: [
2890
+ /* @__PURE__ */ jsx52(NavButton, { label: "\u2039", onPress: () => navigate(-1) }),
2891
+ /* @__PURE__ */ jsxs42(SizableText45, { size: "$4", fontWeight: "700", color: "$color12", children: [
2892
+ MONTH_NAMES[viewMonth],
2893
+ " ",
2894
+ viewYear
2895
+ ] }),
2896
+ /* @__PURE__ */ jsx52(NavButton, { label: "\u203A", onPress: () => navigate(1) })
2897
+ ] }),
2898
+ /* @__PURE__ */ jsx52(XStack38, { children: headers.map((h) => /* @__PURE__ */ jsx52(SizableText45, { size: "$2", color: "$color8", fontWeight: "600", textAlign: "center", flex: 1, children: h }, h)) }),
2899
+ Array.from({ length: Math.ceil(grid.length / 7) }, (_, row) => /* @__PURE__ */ jsx52(XStack38, { children: grid.slice(row * 7, row * 7 + 7).map((cell, i) => {
2900
+ const date = new Date(cell.year, cell.month, cell.day);
2901
+ const selected = sameDay(value, date);
2902
+ const isToday = sameDay(today, date);
2903
+ const disabled = cell.outside || isDisabled(date);
2904
+ return /* @__PURE__ */ jsx52(YStack42, { flex: 1, alignItems: "center", paddingVertical: "$0.5", children: /* @__PURE__ */ jsx52(
2905
+ XStack38,
2906
+ {
2907
+ width: 40,
2908
+ height: 40,
2909
+ borderRadius: "$10",
2910
+ alignItems: "center",
2911
+ justifyContent: "center",
2912
+ backgroundColor: selected ? "$color9" : "transparent",
2913
+ borderWidth: isToday && !selected ? 1.5 : 0,
2914
+ borderColor: "$color9",
2915
+ pressStyle: disabled ? void 0 : { scale: 0.9, backgroundColor: selected ? "$color10" : "$color4" },
2916
+ animation: "quick",
2917
+ opacity: disabled ? 0.35 : 1,
2918
+ cursor: disabled ? "default" : "pointer",
2919
+ onPress: disabled ? void 0 : () => onDateChange?.(date),
2920
+ children: /* @__PURE__ */ jsx52(
2921
+ SizableText45,
2922
+ {
2923
+ size: "$3",
2924
+ fontWeight: selected || isToday ? "700" : "400",
2925
+ color: selected ? "white" : cell.outside ? "$color5" : "$color12",
2926
+ children: cell.day
2927
+ }
2928
+ )
2929
+ }
2930
+ ) }, `${row}-${i}`);
2931
+ }) }, row))
2932
+ ] });
2933
+ }
2934
+
2935
+ // src/patterns/EventCard.tsx
2936
+ import { SizableText as SizableText46, Theme, XStack as XStack39, YStack as YStack43 } from "tamagui";
2937
+ import { jsx as jsx53, jsxs as jsxs43 } from "react/jsx-runtime";
2938
+ var THEME_MAP = {
2939
+ purple: "purple",
2940
+ green: "green",
2941
+ blue: "blue",
2942
+ orange: "orange",
2943
+ red: "red",
2944
+ pink: "pink"
2945
+ };
2946
+ function ParticipantDots({ count, max }) {
2947
+ const dots = Math.min(count, 5);
2948
+ return /* @__PURE__ */ jsxs43(XStack39, { alignItems: "center", gap: "$1.5", children: [
2949
+ /* @__PURE__ */ jsx53(XStack39, { children: Array.from({ length: dots }, (_, i) => /* @__PURE__ */ jsx53(
2950
+ YStack43,
2951
+ {
2952
+ width: 22,
2953
+ height: 22,
2954
+ borderRadius: 11,
2955
+ backgroundColor: "$color7",
2956
+ borderWidth: 2,
2957
+ borderColor: "$color4",
2958
+ marginLeft: i > 0 ? -8 : 0,
2959
+ alignItems: "center",
2960
+ justifyContent: "center",
2961
+ children: /* @__PURE__ */ jsx53(SizableText46, { size: "$1", color: "$color1", fontWeight: "700", children: String.fromCharCode(65 + i) })
2962
+ },
2963
+ i
2964
+ )) }),
2965
+ /* @__PURE__ */ jsxs43(SizableText46, { size: "$2", color: "$color11", fontWeight: "500", children: [
2966
+ count,
2967
+ max ? `/${max}` : ""
2968
+ ] })
2969
+ ] });
2970
+ }
2971
+ function CardInner({ title, subtitle, time, location, label, participants, maxParticipants, onPress, actions }) {
2972
+ return /* @__PURE__ */ jsxs43(
2973
+ YStack43,
2974
+ {
2975
+ backgroundColor: "$color4",
2976
+ borderRadius: "$5",
2977
+ padding: "$4",
2978
+ gap: "$3",
2979
+ borderWidth: 1,
2980
+ borderColor: "$color7",
2981
+ onPress,
2982
+ animation: "quick",
2983
+ pressStyle: onPress ? { scale: 0.97, opacity: 0.9 } : void 0,
2984
+ cursor: onPress ? "pointer" : void 0,
2985
+ children: [
2986
+ /* @__PURE__ */ jsxs43(XStack39, { justifyContent: "space-between", alignItems: "flex-start", children: [
2987
+ /* @__PURE__ */ jsxs43(YStack43, { flex: 1, gap: "$1", children: [
2988
+ /* @__PURE__ */ jsx53(SizableText46, { size: "$6", fontWeight: "700", color: "$color12", children: title }),
2989
+ subtitle && /* @__PURE__ */ jsx53(SizableText46, { size: "$3", color: "$color11", opacity: 0.8, children: subtitle })
2990
+ ] }),
2991
+ time && /* @__PURE__ */ jsx53(YStack43, { backgroundColor: "$color6", paddingHorizontal: "$2.5", paddingVertical: "$1.5", borderRadius: "$3", children: /* @__PURE__ */ jsx53(SizableText46, { size: "$2", fontWeight: "600", color: "$color12", children: time }) })
2992
+ ] }),
2993
+ /* @__PURE__ */ jsxs43(XStack39, { gap: "$4", alignItems: "center", flexWrap: "wrap", children: [
2994
+ location && /* @__PURE__ */ jsxs43(XStack39, { gap: "$1.5", alignItems: "center", children: [
2995
+ /* @__PURE__ */ jsx53(SizableText46, { size: "$3", children: "\u{1F4CD}" }),
2996
+ /* @__PURE__ */ jsx53(SizableText46, { size: "$3", color: "$color11", children: location })
2997
+ ] }),
2998
+ participants !== void 0 && /* @__PURE__ */ jsx53(ParticipantDots, { count: participants, max: maxParticipants })
2999
+ ] }),
3000
+ (label || actions) && /* @__PURE__ */ jsxs43(XStack39, { justifyContent: "space-between", alignItems: "center", children: [
3001
+ label ? /* @__PURE__ */ jsx53(XStack39, { backgroundColor: "$color6", paddingHorizontal: "$2.5", paddingVertical: "$1", borderRadius: "$10", children: /* @__PURE__ */ jsx53(SizableText46, { size: "$2", fontWeight: "600", color: "$color11", children: label }) }) : /* @__PURE__ */ jsx53(YStack43, {}),
3002
+ actions
3003
+ ] })
3004
+ ]
3005
+ }
3006
+ );
3007
+ }
3008
+ function EventCard({ theme = "purple", ...props }) {
3009
+ return /* @__PURE__ */ jsx53(Theme, { name: THEME_MAP[theme], children: /* @__PURE__ */ jsx53(CardInner, { ...props }) });
3010
+ }
3011
+
3012
+ // src/patterns/UserPreferences.tsx
3013
+ import { Separator as Separator6, SizableText as SizableText47, Slider, Switch as Switch2, XStack as XStack40, YStack as YStack44 } from "tamagui";
3014
+ import { jsx as jsx54, jsxs as jsxs44 } from "react/jsx-runtime";
3015
+ function ItemLabel({ title, description, color }) {
3016
+ return /* @__PURE__ */ jsxs44(YStack44, { flex: 1, gap: "$1", children: [
3017
+ /* @__PURE__ */ jsx54(SizableText47, { size: "$4", fontWeight: "500", color: color ?? "$color12", children: title }),
3018
+ description && /* @__PURE__ */ jsx54(SizableText47, { size: "$2", color: "$color9", children: description })
3019
+ ] });
3020
+ }
3021
+ function ToggleRow({ item }) {
3022
+ return /* @__PURE__ */ jsxs44(XStack40, { alignItems: "center", gap: "$3", paddingVertical: "$3", paddingHorizontal: "$4", children: [
3023
+ /* @__PURE__ */ jsx54(ItemLabel, { title: item.title, description: item.description }),
3024
+ /* @__PURE__ */ jsx54(Switch2, { size: "$3", checked: item.value, onCheckedChange: item.onValueChange, children: /* @__PURE__ */ jsx54(Switch2.Thumb, { animation: "quick" }) })
3025
+ ] });
3026
+ }
3027
+ function SelectRow({ item }) {
3028
+ const current = item.options.find((o) => o.value === item.value);
3029
+ return /* @__PURE__ */ jsxs44(
3030
+ XStack40,
3031
+ {
3032
+ alignItems: "center",
3033
+ gap: "$3",
3034
+ paddingVertical: "$3",
3035
+ paddingHorizontal: "$4",
3036
+ pressStyle: { backgroundColor: "$color3" },
3037
+ animation: "quick",
3038
+ cursor: "pointer",
3039
+ onPress: () => {
3040
+ const idx = item.options.findIndex((o) => o.value === item.value);
3041
+ const next = item.options[(idx + 1) % item.options.length];
3042
+ if (next) item.onValueChange(next.value);
3043
+ },
3044
+ children: [
3045
+ /* @__PURE__ */ jsx54(ItemLabel, { title: item.title, description: item.description }),
3046
+ /* @__PURE__ */ jsx54(SizableText47, { size: "$3", color: "$color9", fontWeight: "500", children: current?.label ?? item.value }),
3047
+ /* @__PURE__ */ jsx54(SizableText47, { size: "$4", color: "$color8", children: "\u203A" })
3048
+ ]
3049
+ }
3050
+ );
3051
+ }
3052
+ function SliderRow({ item }) {
3053
+ const min = item.min ?? 0;
3054
+ const max = item.max ?? 100;
3055
+ return /* @__PURE__ */ jsxs44(YStack44, { gap: "$2", paddingVertical: "$3", paddingHorizontal: "$4", children: [
3056
+ /* @__PURE__ */ jsxs44(XStack40, { justifyContent: "space-between", alignItems: "center", children: [
3057
+ /* @__PURE__ */ jsx54(ItemLabel, { title: item.title, description: item.description }),
3058
+ /* @__PURE__ */ jsx54(SizableText47, { size: "$3", fontWeight: "600", color: "$color11", children: item.value })
3059
+ ] }),
3060
+ /* @__PURE__ */ jsxs44(
3061
+ Slider,
3062
+ {
3063
+ value: [item.value],
3064
+ min,
3065
+ max,
3066
+ step: 1,
3067
+ onValueChange: ([v]) => {
3068
+ if (v !== void 0) item.onValueChange(v);
3069
+ },
3070
+ children: [
3071
+ /* @__PURE__ */ jsx54(Slider.Track, { backgroundColor: "$color4", height: 4, children: /* @__PURE__ */ jsx54(Slider.TrackActive, { backgroundColor: "$color9" }) }),
3072
+ /* @__PURE__ */ jsx54(Slider.Thumb, { index: 0, size: "$1.5", backgroundColor: "$color9", borderWidth: 0, circular: true })
3073
+ ]
3074
+ }
3075
+ )
3076
+ ] });
3077
+ }
3078
+ function ActionRow({ item }) {
3079
+ return /* @__PURE__ */ jsxs44(
3080
+ XStack40,
3081
+ {
3082
+ alignItems: "center",
3083
+ gap: "$3",
3084
+ paddingVertical: "$3",
3085
+ paddingHorizontal: "$4",
3086
+ pressStyle: { backgroundColor: "$color3" },
3087
+ animation: "quick",
3088
+ cursor: "pointer",
3089
+ onPress: item.onPress,
3090
+ children: [
3091
+ /* @__PURE__ */ jsx54(
3092
+ ItemLabel,
3093
+ {
3094
+ title: item.title,
3095
+ description: item.description,
3096
+ color: item.destructive ? "$red10" : void 0
3097
+ }
3098
+ ),
3099
+ /* @__PURE__ */ jsx54(SizableText47, { size: "$4", color: "$color8", children: "\u203A" })
3100
+ ]
3101
+ }
3102
+ );
3103
+ }
3104
+ function PreferenceRow({ item }) {
3105
+ switch (item.type) {
3106
+ case "toggle":
3107
+ return /* @__PURE__ */ jsx54(ToggleRow, { item });
3108
+ case "select":
3109
+ return /* @__PURE__ */ jsx54(SelectRow, { item });
3110
+ case "slider":
3111
+ return /* @__PURE__ */ jsx54(SliderRow, { item });
3112
+ case "action":
3113
+ return /* @__PURE__ */ jsx54(ActionRow, { item });
3114
+ }
3115
+ }
3116
+ function UserPreferences({ sections }) {
3117
+ return /* @__PURE__ */ jsx54(YStack44, { gap: "$5", children: sections.map((section, si) => /* @__PURE__ */ jsxs44(YStack44, { gap: "$2", children: [
3118
+ /* @__PURE__ */ jsxs44(YStack44, { paddingHorizontal: "$1", gap: "$0.5", children: [
3119
+ /* @__PURE__ */ jsx54(SizableText47, { size: "$2", fontWeight: "600", color: "$color9", textTransform: "uppercase", children: section.title }),
3120
+ section.description && /* @__PURE__ */ jsx54(SizableText47, { size: "$2", color: "$color8", children: section.description })
3121
+ ] }),
3122
+ /* @__PURE__ */ jsx54(
3123
+ YStack44,
3124
+ {
3125
+ backgroundColor: "$color2",
3126
+ borderRadius: "$4",
3127
+ overflow: "hidden",
3128
+ borderWidth: 1,
3129
+ borderColor: "$color4",
3130
+ children: section.items.map((item, ii) => /* @__PURE__ */ jsxs44(YStack44, { children: [
3131
+ /* @__PURE__ */ jsx54(PreferenceRow, { item }),
3132
+ ii < section.items.length - 1 && /* @__PURE__ */ jsx54(Separator6, { borderColor: "$color4" })
3133
+ ] }, item.id))
3134
+ }
3135
+ )
3136
+ ] }, si)) });
3137
+ }
2653
3138
  export {
2654
3139
  Accordion,
2655
3140
  ActionSheet,
@@ -2686,11 +3171,14 @@ export {
2686
3171
  ConfirmDialog,
2687
3172
  Container,
2688
3173
  CountdownBanner,
3174
+ DataTable,
3175
+ DatePicker,
2689
3176
  Dialog,
2690
3177
  DialogProvider,
2691
3178
  Divider,
2692
3179
  EmptyState,
2693
3180
  EnsureFlexed,
3181
+ EventCard,
2694
3182
  Fieldset,
2695
3183
  FloatingActionButton,
2696
3184
  Footer,
@@ -2747,22 +3235,23 @@ export {
2747
3235
  Section,
2748
3236
  Select,
2749
3237
  SepHeading,
2750
- Separator5 as Separator,
3238
+ Separator7 as Separator,
2751
3239
  SettingsScreen,
2752
3240
  Sheet3 as Sheet,
2753
3241
  SizableStack,
2754
- SizableText44 as SizableText,
3242
+ SizableText48 as SizableText,
2755
3243
  Skeleton,
2756
- Slider,
3244
+ Slider2 as Slider,
2757
3245
  Spacer,
2758
3246
  Spinner2 as Spinner,
2759
3247
  Square,
2760
3248
  Stack,
3249
+ StatusBadge,
2761
3250
  StepPageLayout,
2762
3251
  SubHeading,
2763
3252
  SwipeCards,
2764
3253
  SwipeableRow,
2765
- Switch2 as Switch,
3254
+ Switch3 as Switch,
2766
3255
  TabBar,
2767
3256
  Tabs,
2768
3257
  Image9 as TamaguiImage,
@@ -2771,18 +3260,19 @@ export {
2771
3260
  TestimonialCard,
2772
3261
  Text,
2773
3262
  TextArea,
2774
- Theme,
3263
+ Theme2 as Theme,
2775
3264
  ThemeableStack,
2776
3265
  ToggleGroup,
2777
3266
  Tooltip,
2778
3267
  TooltipSimple,
2779
3268
  Unspaced,
2780
- View6 as View,
3269
+ UserPreferences,
3270
+ View7 as View,
2781
3271
  VisuallyHidden,
2782
3272
  XGroup,
2783
- XStack37 as XStack,
3273
+ XStack41 as XStack,
2784
3274
  YGroup,
2785
- YStack41 as YStack,
3275
+ YStack45 as YStack,
2786
3276
  ZStack,
2787
3277
  addTheme,
2788
3278
  blinkConfig,
@@ -2804,7 +3294,7 @@ export {
2804
3294
  isWeb,
2805
3295
  replaceTheme,
2806
3296
  showError,
2807
- styled13 as styled,
3297
+ styled14 as styled,
2808
3298
  defaultConfig2 as tamaguiDefaultConfig,
2809
3299
  toast,
2810
3300
  updateTheme,
@@ -2818,7 +3308,7 @@ export {
2818
3308
  useForceUpdate,
2819
3309
  useIsPresent,
2820
3310
  useIsomorphicLayoutEffect,
2821
- useMedia,
3311
+ useMedia2 as useMedia,
2822
3312
  usePresence,
2823
3313
  useTheme,
2824
3314
  useThemeName,