@dubsdotapp/expo 0.5.10 → 0.5.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -37,6 +37,7 @@ __export(index_exports, {
37
37
  ConnectWalletButton: () => ConnectWalletButton,
38
38
  ConnectWalletScreen: () => ConnectWalletScreen,
39
39
  CreateCustomGameSheet: () => CreateCustomGameSheet,
40
+ CreateGameSheet: () => CreateGameSheet,
40
41
  DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
41
42
  DEFAULT_RPC_URL: () => DEFAULT_RPC_URL,
42
43
  DubsApiError: () => DubsApiError,
@@ -5669,9 +5670,9 @@ function JoinGameSheet({
5669
5670
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native20.Text, { style: styles14.successEmoji, children: "\u{1F389}" }),
5670
5671
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native20.Text, { style: styles14.successTitle, children: "You're in!" }),
5671
5672
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react_native20.Text, { style: styles14.successSub, children: [
5672
- formatSol(buyIn),
5673
+ formatSol(wager),
5673
5674
  " SOL on ",
5674
- selectedName
5675
+ selectedTeam === "home" ? homeName : awayName
5675
5676
  ] })
5676
5677
  ] }) }),
5677
5678
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -6879,6 +6880,253 @@ var styles18 = import_react_native24.StyleSheet.create({
6879
6880
  emptyState: { paddingVertical: 40, alignItems: "center" },
6880
6881
  emptyText: { fontSize: 14, fontWeight: "600" }
6881
6882
  });
6883
+
6884
+ // src/ui/game/CreateGameSheet.tsx
6885
+ var import_react39 = require("react");
6886
+ var import_react_native25 = require("react-native");
6887
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6888
+ var STATUS_LABELS6 = {
6889
+ building: "Building transaction...",
6890
+ signing: "Approve in wallet...",
6891
+ confirming: "Confirming...",
6892
+ success: "Game Created!"
6893
+ };
6894
+ function formatSol2(n) {
6895
+ return parseFloat(n.toFixed(9)).toString();
6896
+ }
6897
+ function CreateGameSheet({
6898
+ visible,
6899
+ onDismiss,
6900
+ event,
6901
+ homeColor = "#3B82F6",
6902
+ awayColor = "#EF4444",
6903
+ onSuccess,
6904
+ onError,
6905
+ onTeamSelect,
6906
+ onCreateSuccess,
6907
+ onSliderTick,
6908
+ maxWager = 1,
6909
+ shortName
6910
+ }) {
6911
+ const t = useDubsTheme();
6912
+ const { wallet } = useDubs();
6913
+ const mutation = useCreateGame();
6914
+ const [selectedTeam, setSelectedTeam] = (0, import_react39.useState)(null);
6915
+ const [wager, setWager] = (0, import_react39.useState)(0.01);
6916
+ const [showSuccess, setShowSuccess] = (0, import_react39.useState)(false);
6917
+ const overlayOpacity = (0, import_react39.useRef)(new import_react_native25.Animated.Value(0)).current;
6918
+ const successScale = (0, import_react39.useRef)(new import_react_native25.Animated.Value(0)).current;
6919
+ const successOpacity = (0, import_react39.useRef)(new import_react_native25.Animated.Value(0)).current;
6920
+ (0, import_react39.useEffect)(() => {
6921
+ import_react_native25.Animated.timing(overlayOpacity, {
6922
+ toValue: visible ? 1 : 0,
6923
+ duration: 250,
6924
+ useNativeDriver: true
6925
+ }).start();
6926
+ }, [visible]);
6927
+ (0, import_react39.useEffect)(() => {
6928
+ if (visible) {
6929
+ setSelectedTeam(null);
6930
+ setWager(0.01);
6931
+ setShowSuccess(false);
6932
+ successScale.setValue(0);
6933
+ successOpacity.setValue(0);
6934
+ mutation.reset();
6935
+ }
6936
+ }, [visible]);
6937
+ (0, import_react39.useEffect)(() => {
6938
+ if (mutation.status === "success" && mutation.data) {
6939
+ setShowSuccess(true);
6940
+ onSuccess?.(mutation.data);
6941
+ onCreateSuccess?.(mutation.data);
6942
+ import_react_native25.Animated.parallel([
6943
+ import_react_native25.Animated.spring(successScale, { toValue: 1, friction: 4, tension: 80, useNativeDriver: true }),
6944
+ import_react_native25.Animated.timing(successOpacity, { toValue: 1, duration: 300, useNativeDriver: true })
6945
+ ]).start();
6946
+ const timer = setTimeout(() => {
6947
+ import_react_native25.Animated.timing(successOpacity, { toValue: 0, duration: 300, useNativeDriver: true }).start(() => {
6948
+ onDismiss();
6949
+ });
6950
+ }, 2500);
6951
+ return () => clearTimeout(timer);
6952
+ }
6953
+ }, [mutation.status, mutation.data]);
6954
+ (0, import_react39.useEffect)(() => {
6955
+ if (mutation.status === "error" && mutation.error) {
6956
+ onError?.(mutation.error);
6957
+ }
6958
+ }, [mutation.status, mutation.error]);
6959
+ const opponents = event.opponents || [];
6960
+ const homeName = shortName ? shortName(opponents[0]?.name) : opponents[0]?.name || "Home";
6961
+ const awayName = shortName ? shortName(opponents[1]?.name) : opponents[1]?.name || "Away";
6962
+ const isMutating = mutation.status !== "idle" && mutation.status !== "success" && mutation.status !== "error";
6963
+ const canCreate = selectedTeam !== null && !isMutating && mutation.status !== "success";
6964
+ const handleCreate = (0, import_react39.useCallback)(async () => {
6965
+ if (!selectedTeam || !wallet.publicKey) return;
6966
+ try {
6967
+ await mutation.execute({
6968
+ id: event.id,
6969
+ playerWallet: wallet.publicKey.toBase58(),
6970
+ teamChoice: selectedTeam,
6971
+ wagerAmount: wager
6972
+ });
6973
+ } catch {
6974
+ }
6975
+ }, [selectedTeam, wallet.publicKey, mutation.execute, event.id, wager]);
6976
+ const statusLabel = STATUS_LABELS6[mutation.status] || "";
6977
+ const startTime = event.startTime ? new Date(event.startTime) : null;
6978
+ const timeLabel = startTime ? startTime.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" }) + " at " + startTime.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }) : "TBD";
6979
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.Modal, { visible, animationType: "slide", transparent: true, onRequestClose: onDismiss, children: [
6980
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Animated.View, { style: [styles19.overlay, { opacity: overlayOpacity }], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.TouchableOpacity, { style: styles19.overlayTap, activeOpacity: 1, onPress: onDismiss }) }),
6981
+ showSuccess && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: styles19.successOverlay, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.Animated.View, { style: [styles19.successContent, { opacity: successOpacity, transform: [{ scale: successScale }] }], children: [
6982
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: styles19.successEmoji, children: "\u{1F3AF}" }),
6983
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: styles19.successTitle, children: "Game Created!" }),
6984
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.Text, { style: styles19.successSub, children: [
6985
+ formatSol2(wager),
6986
+ " SOL on ",
6987
+ selectedTeam === "home" ? homeName : awayName
6988
+ ] })
6989
+ ] }) }),
6990
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.KeyboardAvoidingView, { style: styles19.keyboardView, behavior: import_react_native25.Platform.OS === "ios" ? "padding" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: styles19.sheetPositioner, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: [styles19.sheet, { backgroundColor: t.background }], children: [
6991
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: styles19.handleRow, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: [styles19.handle, { backgroundColor: t.textMuted }] }) }),
6992
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.header, children: [
6993
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { children: [
6994
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.headerTitle, { color: t.text }], children: "Create Game" }),
6995
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.headerSub, { color: t.textMuted }], children: timeLabel })
6996
+ ] }),
6997
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.TouchableOpacity, { onPress: onDismiss, activeOpacity: 0.8, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.closeButton, { color: t.textMuted }], children: "\u2715" }) })
6998
+ ] }),
6999
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: [styles19.matchupBanner, { borderColor: t.border }], children: [
7000
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.matchupTeam, children: [
7001
+ opponents[0]?.imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Image, { source: { uri: opponents[0].imageUrl }, style: styles19.matchupLogo, resizeMode: "contain" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: [styles19.matchupPlaceholder, { backgroundColor: homeColor + "20" }], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.matchupInitial, { color: homeColor }], children: homeName.charAt(0) }) }),
7002
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.matchupName, { color: t.text }], numberOfLines: 1, children: homeName })
7003
+ ] }),
7004
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.matchupVs, { color: t.textMuted }], children: "vs" }),
7005
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.matchupTeam, children: [
7006
+ opponents[1]?.imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Image, { source: { uri: opponents[1].imageUrl }, style: styles19.matchupLogo, resizeMode: "contain" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: [styles19.matchupPlaceholder, { backgroundColor: awayColor + "20" }], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.matchupInitial, { color: awayColor }], children: awayName.charAt(0) }) }),
7007
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.matchupName, { color: t.text }], numberOfLines: 1, children: awayName })
7008
+ ] })
7009
+ ] }),
7010
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.section, children: [
7011
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.sectionLabel, { color: t.textSecondary }], children: "Pick Your Side" }),
7012
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.teamsRow, children: [
7013
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
7014
+ import_react_native25.TouchableOpacity,
7015
+ {
7016
+ style: [styles19.teamOption, { borderColor: selectedTeam === "home" ? homeColor : t.border, backgroundColor: selectedTeam === "home" ? homeColor + "15" : t.background }],
7017
+ onPress: () => {
7018
+ setSelectedTeam("home");
7019
+ onTeamSelect?.("home");
7020
+ },
7021
+ activeOpacity: 0.7,
7022
+ children: [
7023
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.teamLabel, { color: t.text }], children: homeName }),
7024
+ selectedTeam === "home" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: [styles19.teamBadge, { backgroundColor: homeColor }], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: styles19.teamBadgeText, children: "Selected" }) })
7025
+ ]
7026
+ }
7027
+ ),
7028
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
7029
+ import_react_native25.TouchableOpacity,
7030
+ {
7031
+ style: [styles19.teamOption, { borderColor: selectedTeam === "away" ? awayColor : t.border, backgroundColor: selectedTeam === "away" ? awayColor + "15" : t.background }],
7032
+ onPress: () => {
7033
+ setSelectedTeam("away");
7034
+ onTeamSelect?.("away");
7035
+ },
7036
+ activeOpacity: 0.7,
7037
+ children: [
7038
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.teamLabel, { color: t.text }], children: awayName }),
7039
+ selectedTeam === "away" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: [styles19.teamBadge, { backgroundColor: awayColor }], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: styles19.teamBadgeText, children: "Selected" }) })
7040
+ ]
7041
+ }
7042
+ )
7043
+ ] })
7044
+ ] }),
7045
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: [styles19.summaryCard, { backgroundColor: t.surface, borderColor: t.border }], children: [
7046
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.summaryRow, children: [
7047
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.summaryLabel, { color: t.textMuted }], children: "Your wager" }),
7048
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.Text, { style: [styles19.summaryValue, { color: t.text }], children: [
7049
+ formatSol2(wager),
7050
+ " SOL"
7051
+ ] })
7052
+ ] }),
7053
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: [styles19.summarySep, { backgroundColor: t.border }] }),
7054
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.summaryRow, children: [
7055
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.summaryLabel, { color: t.textMuted }], children: "You're the first" }),
7056
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.summaryValue, { color: t.success }], children: "Set the odds" })
7057
+ ] })
7058
+ ] }),
7059
+ selectedTeam && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7060
+ SolSlider,
7061
+ {
7062
+ value: wager,
7063
+ min: 0.01,
7064
+ max: maxWager,
7065
+ step: 0.01,
7066
+ accentColor: selectedTeam === "home" ? homeColor : awayColor,
7067
+ onValueChange: setWager,
7068
+ onTick: onSliderTick
7069
+ }
7070
+ ),
7071
+ mutation.error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.View, { style: [styles19.errorBox, { backgroundColor: t.errorBg, borderColor: t.errorBorder }], children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.errorText, { color: t.errorText }], children: mutation.error.message }) }),
7072
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7073
+ import_react_native25.TouchableOpacity,
7074
+ {
7075
+ style: [styles19.ctaButton, { backgroundColor: canCreate ? t.accent : t.border }],
7076
+ disabled: !canCreate,
7077
+ onPress: handleCreate,
7078
+ activeOpacity: 0.8,
7079
+ children: isMutating ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react_native25.View, { style: styles19.ctaLoading, children: [
7080
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.ActivityIndicator, { size: "small", color: "#FFFFFF" }),
7081
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: styles19.ctaText, children: statusLabel })
7082
+ ] }) : mutation.status === "success" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: styles19.ctaText, children: "Game Created!" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native25.Text, { style: [styles19.ctaText, !canCreate && { opacity: 0.5 }], children: selectedTeam ? `Create Game \u2014 ${formatSol2(wager)} SOL` : "Pick a side to start" })
7083
+ }
7084
+ )
7085
+ ] }) }) })
7086
+ ] });
7087
+ }
7088
+ var styles19 = import_react_native25.StyleSheet.create({
7089
+ overlay: { ...import_react_native25.StyleSheet.absoluteFillObject, backgroundColor: "rgba(0,0,0,0.5)" },
7090
+ overlayTap: { flex: 1 },
7091
+ keyboardView: { flex: 1, justifyContent: "flex-end" },
7092
+ sheetPositioner: { justifyContent: "flex-end" },
7093
+ sheet: { borderTopLeftRadius: 24, borderTopRightRadius: 24, paddingHorizontal: 20, paddingBottom: 40 },
7094
+ handleRow: { alignItems: "center", paddingTop: 10, paddingBottom: 8 },
7095
+ handle: { width: 36, height: 4, borderRadius: 2, opacity: 0.4 },
7096
+ header: { flexDirection: "row", alignItems: "flex-start", justifyContent: "space-between", paddingVertical: 8 },
7097
+ headerTitle: { fontSize: 20, fontWeight: "700" },
7098
+ headerSub: { fontSize: 13, marginTop: 2 },
7099
+ closeButton: { fontSize: 20, padding: 4 },
7100
+ matchupBanner: { flexDirection: "row", alignItems: "center", justifyContent: "center", paddingVertical: 16, borderBottomWidth: 1, gap: 16 },
7101
+ matchupTeam: { flex: 1, alignItems: "center", gap: 6 },
7102
+ matchupLogo: { width: 40, height: 40 },
7103
+ matchupPlaceholder: { width: 40, height: 40, borderRadius: 20, alignItems: "center", justifyContent: "center" },
7104
+ matchupInitial: { fontSize: 18, fontWeight: "800" },
7105
+ matchupName: { fontSize: 13, fontWeight: "600", textAlign: "center" },
7106
+ matchupVs: { fontSize: 13, fontWeight: "600" },
7107
+ section: { gap: 10, paddingTop: 12 },
7108
+ sectionLabel: { fontSize: 14, fontWeight: "600" },
7109
+ teamsRow: { flexDirection: "row", gap: 10 },
7110
+ teamOption: { flex: 1, borderWidth: 2, borderRadius: 14, paddingVertical: 14, alignItems: "center", gap: 6 },
7111
+ teamLabel: { fontSize: 15, fontWeight: "700" },
7112
+ teamBadge: { borderRadius: 8, paddingHorizontal: 10, paddingVertical: 3 },
7113
+ teamBadgeText: { color: "#FFF", fontSize: 11, fontWeight: "700" },
7114
+ summaryCard: { marginTop: 12, borderRadius: 14, borderWidth: 1, overflow: "hidden" },
7115
+ summaryRow: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16, paddingVertical: 12 },
7116
+ summaryLabel: { fontSize: 14 },
7117
+ summaryValue: { fontSize: 15, fontWeight: "700" },
7118
+ summarySep: { height: 1, marginHorizontal: 16 },
7119
+ errorBox: { marginTop: 12, borderRadius: 12, borderWidth: 1, padding: 12 },
7120
+ errorText: { fontSize: 13, fontWeight: "500" },
7121
+ ctaButton: { marginTop: 16, height: 54, borderRadius: 14, justifyContent: "center", alignItems: "center" },
7122
+ ctaText: { color: "#FFFFFF", fontSize: 16, fontWeight: "700" },
7123
+ ctaLoading: { flexDirection: "row", alignItems: "center", gap: 10 },
7124
+ successOverlay: { ...import_react_native25.StyleSheet.absoluteFillObject, zIndex: 100, alignItems: "center", justifyContent: "center", backgroundColor: "rgba(0,0,0,0.85)" },
7125
+ successContent: { alignItems: "center", gap: 12 },
7126
+ successEmoji: { fontSize: 64 },
7127
+ successTitle: { color: "#FFFFFF", fontSize: 28, fontWeight: "900" },
7128
+ successSub: { color: "#8E8E93", fontSize: 16 }
7129
+ });
6882
7130
  // Annotate the CommonJS export names for ESM import in node:
6883
7131
  0 && (module.exports = {
6884
7132
  ArcadeLeaderboardSheet,
@@ -6888,6 +7136,7 @@ var styles18 = import_react_native24.StyleSheet.create({
6888
7136
  ConnectWalletButton,
6889
7137
  ConnectWalletScreen,
6890
7138
  CreateCustomGameSheet,
7139
+ CreateGameSheet,
6891
7140
  DEFAULT_BASE_URL,
6892
7141
  DEFAULT_RPC_URL,
6893
7142
  DubsApiError,