@dubsdotapp/expo 0.5.5 → 0.5.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.d.mts CHANGED
@@ -1376,10 +1376,14 @@ interface JoinGameSheetProps {
1376
1376
  /** Callbacks */
1377
1377
  onSuccess?: (result: JoinGameMutationResult) => void;
1378
1378
  onError?: (error: Error) => void;
1379
+ /** Called when the user taps a team card (useful for sound/haptics) */
1380
+ onTeamSelect?: (team: 'home' | 'away') => void;
1381
+ /** Called when the join succeeds (useful for success sound/animation) */
1382
+ onJoinSuccess?: (result: JoinGameMutationResult) => void;
1379
1383
  /** Pool mode: hides team selection, auto-assigns team, shows "Join Pool" labels */
1380
1384
  isPoolModeEnabled?: boolean;
1381
1385
  }
1382
- declare function JoinGameSheet({ visible, onDismiss, game, ImageComponent, shortName, homeColor, awayColor, onSuccess, onError, isPoolModeEnabled, }: JoinGameSheetProps): react_jsx_runtime.JSX.Element;
1386
+ declare function JoinGameSheet({ visible, onDismiss, game, ImageComponent, shortName, homeColor, awayColor, onSuccess, onError, onTeamSelect, onJoinSuccess, isPoolModeEnabled, }: JoinGameSheetProps): react_jsx_runtime.JSX.Element;
1383
1387
 
1384
1388
  interface ClaimPrizeSheetProps {
1385
1389
  visible: boolean;
package/dist/index.d.ts CHANGED
@@ -1376,10 +1376,14 @@ interface JoinGameSheetProps {
1376
1376
  /** Callbacks */
1377
1377
  onSuccess?: (result: JoinGameMutationResult) => void;
1378
1378
  onError?: (error: Error) => void;
1379
+ /** Called when the user taps a team card (useful for sound/haptics) */
1380
+ onTeamSelect?: (team: 'home' | 'away') => void;
1381
+ /** Called when the join succeeds (useful for success sound/animation) */
1382
+ onJoinSuccess?: (result: JoinGameMutationResult) => void;
1379
1383
  /** Pool mode: hides team selection, auto-assigns team, shows "Join Pool" labels */
1380
1384
  isPoolModeEnabled?: boolean;
1381
1385
  }
1382
- declare function JoinGameSheet({ visible, onDismiss, game, ImageComponent, shortName, homeColor, awayColor, onSuccess, onError, isPoolModeEnabled, }: JoinGameSheetProps): react_jsx_runtime.JSX.Element;
1386
+ declare function JoinGameSheet({ visible, onDismiss, game, ImageComponent, shortName, homeColor, awayColor, onSuccess, onError, onTeamSelect, onJoinSuccess, isPoolModeEnabled, }: JoinGameSheetProps): react_jsx_runtime.JSX.Element;
1383
1387
 
1384
1388
  interface ClaimPrizeSheetProps {
1385
1389
  visible: boolean;
package/dist/index.js CHANGED
@@ -5351,6 +5351,13 @@ var STATUS_LABELS3 = {
5351
5351
  success: "Joined!"
5352
5352
  };
5353
5353
  var CUSTOM_GAME_MODE = 6;
5354
+ function formatSol(n) {
5355
+ return parseFloat(n.toFixed(9)).toString();
5356
+ }
5357
+ function toPng(url) {
5358
+ if (!url) return null;
5359
+ return url.replace("/svg?", "/png?");
5360
+ }
5354
5361
  function JoinGameSheet({
5355
5362
  visible,
5356
5363
  onDismiss,
@@ -5361,6 +5368,8 @@ function JoinGameSheet({
5361
5368
  awayColor = "#EF4444",
5362
5369
  onSuccess,
5363
5370
  onError,
5371
+ onTeamSelect,
5372
+ onJoinSuccess,
5364
5373
  isPoolModeEnabled = false
5365
5374
  }) {
5366
5375
  const t = useDubsTheme();
@@ -5368,7 +5377,10 @@ function JoinGameSheet({
5368
5377
  const mutation = useJoinGame();
5369
5378
  const isCustomGame = game.gameMode === CUSTOM_GAME_MODE;
5370
5379
  const [selectedTeam, setSelectedTeam] = (0, import_react33.useState)(null);
5380
+ const [showSuccess, setShowSuccess] = (0, import_react33.useState)(false);
5371
5381
  const overlayOpacity = (0, import_react33.useRef)(new import_react_native19.Animated.Value(0)).current;
5382
+ const successScale = (0, import_react33.useRef)(new import_react_native19.Animated.Value(0)).current;
5383
+ const successOpacity = (0, import_react33.useRef)(new import_react_native19.Animated.Value(0)).current;
5372
5384
  (0, import_react33.useEffect)(() => {
5373
5385
  import_react_native19.Animated.timing(overlayOpacity, {
5374
5386
  toValue: visible ? 1 : 0,
@@ -5379,15 +5391,26 @@ function JoinGameSheet({
5379
5391
  (0, import_react33.useEffect)(() => {
5380
5392
  if (visible) {
5381
5393
  setSelectedTeam(isPoolModeEnabled ? "home" : isCustomGame ? "away" : null);
5394
+ setShowSuccess(false);
5395
+ successScale.setValue(0);
5396
+ successOpacity.setValue(0);
5382
5397
  mutation.reset();
5383
5398
  }
5384
5399
  }, [visible]);
5385
5400
  (0, import_react33.useEffect)(() => {
5386
5401
  if (mutation.status === "success" && mutation.data) {
5402
+ setShowSuccess(true);
5387
5403
  onSuccess?.(mutation.data);
5404
+ onJoinSuccess?.(mutation.data);
5405
+ import_react_native19.Animated.parallel([
5406
+ import_react_native19.Animated.spring(successScale, { toValue: 1, friction: 4, tension: 80, useNativeDriver: true }),
5407
+ import_react_native19.Animated.timing(successOpacity, { toValue: 1, duration: 300, useNativeDriver: true })
5408
+ ]).start();
5388
5409
  const timer = setTimeout(() => {
5389
- onDismiss();
5390
- }, 1500);
5410
+ import_react_native19.Animated.timing(successOpacity, { toValue: 0, duration: 300, useNativeDriver: true }).start(() => {
5411
+ onDismiss();
5412
+ });
5413
+ }, 2500);
5391
5414
  return () => clearTimeout(timer);
5392
5415
  }
5393
5416
  }, [mutation.status, mutation.data]);
@@ -5410,7 +5433,7 @@ function JoinGameSheet({
5410
5433
  }), [totalPool, homePool, awayPool, bettors]);
5411
5434
  const poolAfterJoin = totalPool + buyIn;
5412
5435
  const selectedOdds = selectedTeam === "home" ? homeOdds : selectedTeam === "away" ? awayOdds : "\u2014";
5413
- const potentialWinnings = selectedOdds !== "\u2014" ? (parseFloat(selectedOdds) * buyIn).toFixed(4) : "\u2014";
5436
+ const potentialWinnings = selectedOdds !== "\u2014" ? formatSol(parseFloat(selectedOdds) * buyIn) : "\u2014";
5414
5437
  const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
5415
5438
  const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
5416
5439
  const selectedName = selectedTeam === "home" ? homeName : selectedTeam === "away" ? awayName : "\u2014";
@@ -5443,6 +5466,15 @@ function JoinGameSheet({
5443
5466
  onRequestClose: onDismiss,
5444
5467
  children: [
5445
5468
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Animated.View, { style: [styles13.overlay, { opacity: overlayOpacity }], children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.TouchableOpacity, { style: styles13.overlayTap, activeOpacity: 1, onPress: onDismiss }) }),
5469
+ showSuccess && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.View, { style: styles13.successOverlay, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.Animated.View, { style: [styles13.successContent, { opacity: successOpacity, transform: [{ scale: successScale }] }], children: [
5470
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: styles13.successEmoji, children: "\u{1F389}" }),
5471
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: styles13.successTitle, children: "You're in!" }),
5472
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.Text, { style: styles13.successSub, children: [
5473
+ formatSol(buyIn),
5474
+ " SOL on ",
5475
+ selectedName
5476
+ ] })
5477
+ ] }) }),
5446
5478
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5447
5479
  import_react_native19.KeyboardAvoidingView,
5448
5480
  {
@@ -5454,6 +5486,24 @@ function JoinGameSheet({
5454
5486
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.headerTitle, { color: t.text }], children: isPoolModeEnabled ? "Join Pool" : "Join Game" }),
5455
5487
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.TouchableOpacity, { onPress: onDismiss, activeOpacity: 0.8, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.closeButton, { color: t.textMuted }], children: "\u2715" }) })
5456
5488
  ] }),
5489
+ bettors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.bettorsSection, children: [
5490
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.Text, { style: [styles13.bettorsLabel, { color: t.textMuted }], children: [
5491
+ bettors.length,
5492
+ " ",
5493
+ bettors.length === 1 ? "player" : "players",
5494
+ " in this game"
5495
+ ] }),
5496
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.bettorsRow, children: [
5497
+ bettors.slice(0, 6).map((b, i) => {
5498
+ const pngUrl = toPng(b.avatar);
5499
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.View, { style: [styles13.bettorCircle, { backgroundColor: ["#EF4444", "#3B82F6", "#22C55E", "#F59E0B", "#A855F7", "#EC4899"][i % 6] }], children: pngUrl ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Image, { source: { uri: pngUrl }, style: styles13.bettorImg }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: styles13.bettorInitial, children: (b.username ?? b.wallet).charAt(0).toUpperCase() }) }, b.wallet);
5500
+ }),
5501
+ bettors.length > 6 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.View, { style: [styles13.bettorCircle, { backgroundColor: "#2C2C2E" }], children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.Text, { style: styles13.bettorOverflow, children: [
5502
+ "+",
5503
+ bettors.length - 6
5504
+ ] }) })
5505
+ ] })
5506
+ ] }),
5457
5507
  !isCustomGame && !isPoolModeEnabled && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.section, children: [
5458
5508
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.sectionLabel, { color: t.textSecondary }], children: "Pick Your Side" }),
5459
5509
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.teamsRow, children: [
@@ -5466,7 +5516,10 @@ function JoinGameSheet({
5466
5516
  bets: homeBets,
5467
5517
  color: homeColor,
5468
5518
  selected: selectedTeam === "home",
5469
- onPress: () => setSelectedTeam("home"),
5519
+ onPress: () => {
5520
+ setSelectedTeam("home");
5521
+ onTeamSelect?.("home");
5522
+ },
5470
5523
  ImageComponent,
5471
5524
  t
5472
5525
  }
@@ -5480,7 +5533,10 @@ function JoinGameSheet({
5480
5533
  bets: awayBets,
5481
5534
  color: awayColor,
5482
5535
  selected: selectedTeam === "away",
5483
- onPress: () => setSelectedTeam("away"),
5536
+ onPress: () => {
5537
+ setSelectedTeam("away");
5538
+ onTeamSelect?.("away");
5539
+ },
5484
5540
  ImageComponent,
5485
5541
  t
5486
5542
  }
@@ -5491,7 +5547,7 @@ function JoinGameSheet({
5491
5547
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.summaryRow, children: [
5492
5548
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.summaryLabel, { color: t.textMuted }], children: "Buy-in" }),
5493
5549
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.Text, { style: [styles13.summaryValue, { color: t.text }], children: [
5494
- buyIn,
5550
+ formatSol(buyIn),
5495
5551
  " SOL"
5496
5552
  ] })
5497
5553
  ] }),
@@ -5505,7 +5561,7 @@ function JoinGameSheet({
5505
5561
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.summaryRow, children: [
5506
5562
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.summaryLabel, { color: t.textMuted }], children: "Current pot" }),
5507
5563
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.Text, { style: [styles13.summaryValue, { color: t.success }], children: [
5508
- totalPool,
5564
+ formatSol(totalPool),
5509
5565
  " SOL"
5510
5566
  ] })
5511
5567
  ] })
@@ -5518,7 +5574,7 @@ function JoinGameSheet({
5518
5574
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.summaryRow, children: [
5519
5575
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.summaryLabel, { color: t.textMuted }], children: "Total pool" }),
5520
5576
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.Text, { style: [styles13.summaryValue, { color: t.text }], children: [
5521
- poolAfterJoin,
5577
+ formatSol(poolAfterJoin),
5522
5578
  " SOL"
5523
5579
  ] })
5524
5580
  ] }),
@@ -5544,7 +5600,7 @@ function JoinGameSheet({
5544
5600
  children: isMutating ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native19.View, { style: styles13.ctaLoading, children: [
5545
5601
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
5546
5602
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: styles13.ctaText, children: statusLabel })
5547
- ] }) : mutation.status === "success" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: styles13.ctaText, children: isPoolModeEnabled ? "Joined!" : STATUS_LABELS3.success }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.ctaText, !canJoin && { opacity: 0.5 }], children: alreadyJoined ? "Already Joined" : isPoolModeEnabled ? `Join Pool \u2014 ${buyIn} SOL` : selectedTeam ? `Join Game \u2014 ${buyIn} SOL` : "Pick a side to join" })
5603
+ ] }) : mutation.status === "success" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: styles13.ctaText, children: isPoolModeEnabled ? "Joined!" : STATUS_LABELS3.success }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native19.Text, { style: [styles13.ctaText, !canJoin && { opacity: 0.5 }], children: alreadyJoined ? "Already Joined" : isPoolModeEnabled ? `Join Pool \u2014 ${formatSol(buyIn)} SOL` : selectedTeam ? `Join Game \u2014 ${formatSol(buyIn)} SOL` : "Pick a side to join" })
5548
5604
  }
5549
5605
  )
5550
5606
  ] }) })
@@ -5637,6 +5693,67 @@ var styles13 = import_react_native19.StyleSheet.create({
5637
5693
  fontSize: 20,
5638
5694
  padding: 4
5639
5695
  },
5696
+ // Bettors row
5697
+ bettorsSection: {
5698
+ paddingBottom: 12,
5699
+ gap: 8
5700
+ },
5701
+ bettorsLabel: {
5702
+ fontSize: 12,
5703
+ fontWeight: "600"
5704
+ },
5705
+ bettorsRow: {
5706
+ flexDirection: "row",
5707
+ alignItems: "center",
5708
+ gap: 4
5709
+ },
5710
+ bettorCircle: {
5711
+ width: 28,
5712
+ height: 28,
5713
+ borderRadius: 14,
5714
+ alignItems: "center",
5715
+ justifyContent: "center",
5716
+ overflow: "hidden"
5717
+ },
5718
+ bettorImg: {
5719
+ width: 28,
5720
+ height: 28,
5721
+ borderRadius: 14
5722
+ },
5723
+ bettorInitial: {
5724
+ color: "#FFF",
5725
+ fontSize: 11,
5726
+ fontWeight: "800"
5727
+ },
5728
+ bettorOverflow: {
5729
+ color: "#8E8E93",
5730
+ fontSize: 10,
5731
+ fontWeight: "700"
5732
+ },
5733
+ // Success overlay
5734
+ successOverlay: {
5735
+ ...import_react_native19.StyleSheet.absoluteFillObject,
5736
+ zIndex: 100,
5737
+ alignItems: "center",
5738
+ justifyContent: "center",
5739
+ backgroundColor: "rgba(0,0,0,0.85)"
5740
+ },
5741
+ successContent: {
5742
+ alignItems: "center",
5743
+ gap: 12
5744
+ },
5745
+ successEmoji: {
5746
+ fontSize: 64
5747
+ },
5748
+ successTitle: {
5749
+ color: "#FFFFFF",
5750
+ fontSize: 28,
5751
+ fontWeight: "900"
5752
+ },
5753
+ successSub: {
5754
+ color: "#8E8E93",
5755
+ fontSize: 16
5756
+ },
5640
5757
  section: {
5641
5758
  gap: 12,
5642
5759
  paddingTop: 8