@devrongx/games 0.4.26 → 0.4.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrongx/games",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
4
4
  "description": "Game UI components for sports prediction markets",
5
5
  "license": "MIT",
6
6
  "main": "./src/index.ts",
@@ -462,6 +462,7 @@ export const PreMatchBetsPopup = ({ poolId, matchId: _matchId, match: matchProp
462
462
  editSubmitting={editSubmitting}
463
463
  savedBetSummary={savedBetSummary}
464
464
  hasUnsavedEdits={hasUnsavedEdits}
465
+ onGoToIntro={() => setUserFlowState("intro")}
465
466
  />
466
467
  )}
467
468
 
@@ -56,6 +56,7 @@ interface PreMatchGameProps {
56
56
  editSubmitting?: number | null;
57
57
  savedBetSummary?: IBetSummary | null;
58
58
  hasUnsavedEdits?: boolean;
59
+ onGoToIntro?: () => void;
59
60
  }
60
61
 
61
62
  // ─── Component ───────────────────────────────────────────────────────────────
@@ -66,7 +67,7 @@ export const PreMatchGame = ({
66
67
  parlayEnabled = false, submitting = false,
67
68
  ignoredMarkets: _ignoredMarkets, onToggleIgnore, editingMarkets: _editingMarkets,
68
69
  dirtyMarkets: _dirtyMarkets, onEditMarket, onConfirmMarketEdit, onCancelMarketEdit,
69
- editSubmitting, savedBetSummary, hasUnsavedEdits = false,
70
+ editSubmitting, savedBetSummary, hasUnsavedEdits = false, onGoToIntro,
70
71
  }: PreMatchGameProps) => {
71
72
  const ignoredMarkets = _ignoredMarkets ?? EMPTY_SET;
72
73
  const editingMarkets = _editingMarkets ?? EMPTY_SET;
@@ -77,11 +78,6 @@ export const PreMatchGame = ({
77
78
  // Whether bets have been submitted to the server at least once
78
79
  const hasSubmitted = !!submittedBets && Object.keys(submittedBets).length > 0;
79
80
 
80
- // Button state for initial submit flow (fresh = never submitted)
81
- const buttonState = useMemo<"fresh" | "submitted">(() => {
82
- return hasSubmitted ? "submitted" : "fresh";
83
- }, [hasSubmitted]);
84
-
85
81
  const goTo = useGamePopupStore(s => s.goTo);
86
82
 
87
83
  // ── Onboarding — visible whenever no points have been bet yet ─────────────
@@ -144,11 +140,6 @@ export const PreMatchGame = ({
144
140
  });
145
141
  }, []);
146
142
 
147
- const handleExpandAll = useCallback(() => setCollapsedMarkets(new Set()), []);
148
- const handleCollapseAll = useCallback(() => {
149
- setCollapsedMarkets(new Set(config.markets.map((_, i) => i)));
150
- }, [config.markets]);
151
-
152
143
  // ── Computed: filtered/sorted market indices ─────────────────────────────
153
144
  const sortActive = activeFilters.has("bets_first") || activeFilters.has("unanswered_first");
154
145
 
@@ -165,14 +156,22 @@ export const PreMatchGame = ({
165
156
  });
166
157
  } else if (activeFilters.has("unanswered_first")) {
167
158
  indices.sort((a, b) => {
168
- const aAns = bets[a] !== undefined ? 1 : 0;
169
- const bAns = bets[b] !== undefined ? 1 : 0;
170
- return aAns - bAns || a - b;
159
+ const aHasAmount = (bets[a]?.amount ?? 0) > 0 ? 1 : 0;
160
+ const bHasAmount = (bets[b]?.amount ?? 0) > 0 ? 1 : 0;
161
+ return aHasAmount - bHasAmount || a - b;
171
162
  });
172
163
  }
173
164
  return indices;
174
165
  }, [config.markets, activeFilters, ignoredMarkets, bets]);
175
166
 
167
+ const handleExpandAll = useCallback(() => {
168
+ setCollapsedMarkets(new Set());
169
+ }, []);
170
+
171
+ const handleCollapseAll = useCallback(() => {
172
+ setCollapsedMarkets(new Set(config.markets.map((_, i) => i)));
173
+ }, [config.markets]);
174
+
176
175
  // Category headers — only shown when no sort is active
177
176
  const categoryForIndex = useMemo(() => {
178
177
  const map = new Map<number, string>();
@@ -245,7 +244,7 @@ export const PreMatchGame = ({
245
244
  {/* How to Play + Filter pills */}
246
245
  <div className="pt-2 flex items-center gap-2 overflow-x-auto scrollbar-hide">
247
246
  <button
248
- onClick={() => goTo("intro")}
247
+ onClick={() => { onGoToIntro ? onGoToIntro() : goTo("intro"); }}
249
248
  className="flex-shrink-0 flex items-center gap-1.5 px-3 py-1.5 rounded-full border border-[#22E3E8]/20 bg-[#22E3E8]/[0.06]"
250
249
  >
251
250
  <Play size={10} fill="#22E3E8" strokeWidth={0} className="text-[#22E3E8]" />
@@ -631,9 +630,9 @@ export const PreMatchGame = ({
631
630
  </AnimatePresence>
632
631
  </div>
633
632
 
634
- {/* Right — action button */}
633
+ {/* Right — play button (fresh only) */}
635
634
  <AnimatePresence>
636
- {buttonState === "fresh" && totalEntry > 0 && (
635
+ {!hasSubmitted && totalEntry > 0 && (
637
636
  <motion.button
638
637
  onClick={onSubmit ? onSubmit : undefined}
639
638
  disabled={submitting}
@@ -652,16 +651,6 @@ export const PreMatchGame = ({
652
651
  : <Play size={26} fill="white" strokeWidth={0} className="relative z-10" />}
653
652
  </motion.button>
654
653
  )}
655
- {buttonState === "submitted" && (
656
- <motion.div
657
- className="w-[54px] min-h-[54px] rounded-xl flex-shrink-0 flex items-center justify-center"
658
- style={{ background: "rgba(74,222,128,0.10)" }}
659
- initial={{ opacity: 0, scale: 0.8 }}
660
- animate={{ opacity: 1, scale: 1 }}
661
- transition={{ type: "spring", stiffness: 300, damping: 20 }}>
662
- <Check size={22} strokeWidth={2.5} className="text-white" />
663
- </motion.div>
664
- )}
665
654
  </AnimatePresence>
666
655
  </div>
667
656
 
@@ -44,7 +44,7 @@ export const FilterPill = ({ label, active = false, onClick }: { label: string;
44
44
  }}
45
45
  >
46
46
  <motion.div
47
- className="absolute inset-0 rounded-full"
47
+ className="absolute inset-0 rounded-full pointer-events-none"
48
48
  initial={false}
49
49
  animate={{ scaleX: active ? 1 : 0, opacity: active ? 1 : 0 }}
50
50
  transition={{ duration: 0.25, ease: "easeOut" }}