jaml-ui 0.14.2 → 0.14.4
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/DESIGN.md +197 -0
- package/dist/components/AnalyzerExplorer.js +0 -11
- package/dist/components/JamlAestheticSelector.js +1 -3
- package/dist/components/JamlAnalyzerFullscreen.js +3 -3
- package/dist/components/JamlIde.js +0 -2
- package/dist/components/JamlSeedInput.js +1 -2
- package/dist/components/JamlSpeedometer.js +1 -1
- package/dist/ui/codeBlock.js +1 -1
- package/dist/ui/jimboCopyRow.js +1 -2
- package/dist/ui/jimboFilterBar.js +2 -4
- package/dist/ui/showcase.js +4 -4
- package/package.json +8 -5
- package/assets/Balatro Seed Curator (DesignsV2)/.design-canvas.state.json +0 -1
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/BlindChips.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Boosters/Boosters.json +0 -303
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Boosters/boosters.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Boosters.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Bosses/BlindChips.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Bosses/blinds_metadata.json +0 -51
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/8BitDeck.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/Enhancers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/balatro-stake-chips.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/enhancers_metadata.json +0 -52
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/playing_cards_metadata.json +0 -249
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/stakes.json +0 -19
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Editions.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Enhancers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/Editions.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/Jokers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/jokers.json +0 -1087
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/stickers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/stickers_metadata.json +0 -25
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tags/tags.json +0 -191
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tags/tags.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/Tarots.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/planets.json +0 -15
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/spectrals.json +0 -21
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/tarots.json +0 -163
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Vouchers/Vouchers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Vouchers/vouchers.json +0 -130
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/Vouchers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/blinds.json +0 -51
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/boosters.json +0 -303
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/fonts/m6x11plusplus.otf +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/jokers.json +0 -1087
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/planets.json +0 -15
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/spectrals.json +0 -21
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/stakes.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/stickers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/tags.json +0 -191
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/tags.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/tarots.json +0 -163
- package/assets/Balatro Seed Curator (DesignsV2)/Assets/vouchers.json +0 -130
- package/assets/Balatro Seed Curator (DesignsV2)/Seed Detail v2.html +0 -40
- package/assets/Balatro Seed Curator (DesignsV2)/Seed Detail.html +0 -34
- package/assets/Balatro Seed Curator (DesignsV2)/public/fonts/m6x11plusplus.otf +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/src/AntePage.jsx +0 -228
- package/assets/Balatro Seed Curator (DesignsV2)/src/SeedDetail.jsx +0 -222
- package/assets/Balatro Seed Curator (DesignsV2)/src/app.jsx +0 -35
- package/assets/Balatro Seed Curator (DesignsV2)/src/mockData.js +0 -185
- package/assets/Balatro Seed Curator (DesignsV2)/src/sprites.jsx +0 -259
- package/assets/Balatro Seed Curator (DesignsV2)/src/tokens.js +0 -49
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/AntePageV2.jsx +0 -290
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/BalButton.jsx +0 -107
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/JamlBuilderV2.jsx +0 -594
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/JamlIde.jsx +0 -302
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/SearchResultsV2.jsx +0 -286
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/SeedDetailV2.jsx +0 -336
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/SeedOGCard.jsx +0 -251
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/Showcase.jsx +0 -131
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/app.jsx +0 -55
- package/assets/Balatro Seed Curator (DesignsV2)/src/v2/data.js +0 -296
- package/assets/Balatro Seed Curator (DesignsV2)/starters/design-canvas.jsx +0 -622
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/8BitDeck.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/BlindChips.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/Boosters.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/Editions.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/Enhancers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/Jokers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/Tarots.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749540653-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749644934-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749661871-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749674748-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749703076-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749882759-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776750354200-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776750733265-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776751928925-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776800975060-0.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/stickers.png +0 -0
- package/assets/Balatro Seed Curator (DesignsV2)/uploads/tags.png +0 -0
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
// AntePage — one ante's worth of content, scrolled vertically.
|
|
2
|
-
// [voucher row + tags row]
|
|
3
|
-
// [SMALL BLIND section: boss chip + pack(s) + 6 shop items in 2×3]
|
|
4
|
-
// [BIG BLIND section: ditto]
|
|
5
|
-
// [BOSS BLIND section: ditto]
|
|
6
|
-
//
|
|
7
|
-
// Pack tap → fan-out of contents below the pack.
|
|
8
|
-
// Tag tap → reveal of reward preview (same motion as pack tap).
|
|
9
|
-
// Hit items display a corner stamp; a footer strip shows the per-clause
|
|
10
|
-
// running tally across the seed.
|
|
11
|
-
|
|
12
|
-
const { useState: uS, useMemo: uM } = React;
|
|
13
|
-
|
|
14
|
-
// ── Small chrome: a pixel-border card (Balatro panels) ───────
|
|
15
|
-
function BalatroPanel({ children, style = {}, color = '#2a3336' }) {
|
|
16
|
-
return (
|
|
17
|
-
<div
|
|
18
|
-
style={{
|
|
19
|
-
background: color,
|
|
20
|
-
border: '2px solid #1e2b2d',
|
|
21
|
-
borderRadius: 6,
|
|
22
|
-
boxShadow: 'inset 0 0 0 1px #3e4a4d, 0 2px 0 #0b1416',
|
|
23
|
-
padding: 10,
|
|
24
|
-
color: '#fff',
|
|
25
|
-
...style,
|
|
26
|
-
}}
|
|
27
|
-
>
|
|
28
|
-
{children}
|
|
29
|
-
</div>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// ── Chunky Balatro section header pill ───────────────────────
|
|
34
|
-
function BlindHeader({ kind, boss, onTap }) {
|
|
35
|
-
const label = kind === 'small' ? 'SMALL BLIND' : kind === 'big' ? 'BIG BLIND' : 'BOSS BLIND';
|
|
36
|
-
const color = kind === 'boss' ? '#6d2b2b' : '#2b3a5e';
|
|
37
|
-
return (
|
|
38
|
-
<div
|
|
39
|
-
onClick={onTap}
|
|
40
|
-
style={{
|
|
41
|
-
display: 'flex',
|
|
42
|
-
alignItems: 'center',
|
|
43
|
-
gap: 10,
|
|
44
|
-
background: color,
|
|
45
|
-
padding: '6px 12px 6px 8px',
|
|
46
|
-
border: '2px solid #1e2b2d',
|
|
47
|
-
borderRadius: 18,
|
|
48
|
-
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.15), 0 2px 0 #0b1416',
|
|
49
|
-
cursor: onTap ? 'pointer' : 'default',
|
|
50
|
-
alignSelf: 'flex-start',
|
|
51
|
-
}}
|
|
52
|
-
>
|
|
53
|
-
<BossChip name={boss || (kind === 'boss' ? 'TheOx' : kind === 'big' ? 'BigBlind' : 'SmallBlind')} size={32} />
|
|
54
|
-
<span style={{ fontFamily: 'm6x11plus, monospace', fontSize: 16, letterSpacing: 1, color: '#fff' }}>{label}</span>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ── FanOut — used by tap-to-reveal (packs and tags). Renders row of
|
|
60
|
-
// children sliding + fading in from under the parent.
|
|
61
|
-
function FanOut({ open, children }) {
|
|
62
|
-
return (
|
|
63
|
-
<div
|
|
64
|
-
style={{
|
|
65
|
-
overflow: 'hidden',
|
|
66
|
-
transition: 'max-height 260ms cubic-bezier(.33,1,.4,1), opacity 180ms',
|
|
67
|
-
maxHeight: open ? 180 : 0,
|
|
68
|
-
opacity: open ? 1 : 0,
|
|
69
|
-
}}
|
|
70
|
-
>
|
|
71
|
-
<div
|
|
72
|
-
style={{
|
|
73
|
-
display: 'flex',
|
|
74
|
-
gap: 8,
|
|
75
|
-
padding: '10px 0 4px',
|
|
76
|
-
transform: open ? 'translateY(0)' : 'translateY(-8px)',
|
|
77
|
-
transition: 'transform 260ms cubic-bezier(.33,1,.4,1)',
|
|
78
|
-
}}
|
|
79
|
-
>
|
|
80
|
-
{children}
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ── PackCluster — the pack sprite, plus an expanded fan-out of its cards
|
|
87
|
-
function PackCluster({ pack }) {
|
|
88
|
-
const [open, setOpen] = uS(false);
|
|
89
|
-
const kind = pack.kind.toLowerCase();
|
|
90
|
-
const hitKinds = pack.contents?.flatMap((c) => c.hits || []) || [];
|
|
91
|
-
const firstHit = hitKinds.length ? 'should' : null;
|
|
92
|
-
return (
|
|
93
|
-
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
|
|
94
|
-
<PackSprite kind={kind} size={56} onClick={() => setOpen((o) => !o)} open={open} hit={firstHit} />
|
|
95
|
-
{pack.contents?.length ? (
|
|
96
|
-
<FanOut open={open}>
|
|
97
|
-
{pack.contents.map((c, i) => (
|
|
98
|
-
<CardItem key={i} item={c} size={46} />
|
|
99
|
-
))}
|
|
100
|
-
</FanOut>
|
|
101
|
-
) : null}
|
|
102
|
-
</div>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ── CardItem — renders a shop/pack item by kind.
|
|
107
|
-
function CardItem({ item, size = 58 }) {
|
|
108
|
-
const hit = item.hits && item.hits.length ? (item.hits.some((h) => h.startsWith('m')) ? 'must' : 'should') : null;
|
|
109
|
-
if (item.kind === 'Joker') return <JokerMini name={item.name} size={size} hit={hit} edition={item.edition} />;
|
|
110
|
-
if (item.kind === 'Tarot') return <TarotMini name={item.name} size={size} hit={hit} />;
|
|
111
|
-
if (item.kind === 'Voucher') return <VoucherMini name={item.name} size={size} hit={hit} />;
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// ── TagReveal — tap a tag, see its preview (mock)
|
|
116
|
-
function TagCluster({ tag }) {
|
|
117
|
-
const [open, setOpen] = uS(false);
|
|
118
|
-
const preview = TAG_PREVIEWS[tag.name.toLowerCase()] || { label: tag.name, body: 'Tag reward preview' };
|
|
119
|
-
const hit = tag.hits && tag.hits.length ? 'should' : null;
|
|
120
|
-
return (
|
|
121
|
-
<div style={{ position: 'relative' }}>
|
|
122
|
-
<div onClick={() => setOpen((o) => !o)} style={{ cursor: 'pointer' }}>
|
|
123
|
-
<TagChip name={tag.name} size={30} hit={hit} />
|
|
124
|
-
</div>
|
|
125
|
-
{open && (
|
|
126
|
-
<div
|
|
127
|
-
style={{
|
|
128
|
-
position: 'absolute',
|
|
129
|
-
top: 'calc(100% + 6px)',
|
|
130
|
-
left: '50%',
|
|
131
|
-
transform: 'translateX(-50%)',
|
|
132
|
-
background: '#1e2b2d',
|
|
133
|
-
border: '2px solid #3e4a4d',
|
|
134
|
-
borderRadius: 6,
|
|
135
|
-
padding: '6px 10px',
|
|
136
|
-
fontFamily: 'm6x11plus, monospace',
|
|
137
|
-
fontSize: 12,
|
|
138
|
-
color: '#fff',
|
|
139
|
-
whiteSpace: 'nowrap',
|
|
140
|
-
zIndex: 10,
|
|
141
|
-
boxShadow: '0 6px 20px rgba(0,0,0,0.4)',
|
|
142
|
-
}}
|
|
143
|
-
onClick={() => setOpen(false)}
|
|
144
|
-
>
|
|
145
|
-
<div style={{ color: '#e4b643' }}>{preview.label}</div>
|
|
146
|
-
<div style={{ opacity: 0.75, fontSize: 10, marginTop: 2 }}>{preview.body}</div>
|
|
147
|
-
</div>
|
|
148
|
-
)}
|
|
149
|
-
</div>
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const TAG_PREVIEWS = {
|
|
154
|
-
raretag: { label: 'RARE TAG', body: 'Next shop: Free Rare Joker' },
|
|
155
|
-
uncommontag: { label: 'UNCOMMON TAG', body: 'Next shop: Free Uncommon Joker' },
|
|
156
|
-
negativetag: { label: 'NEGATIVE TAG', body: 'Next base Joker becomes Negative' },
|
|
157
|
-
foiltag: { label: 'FOIL TAG', body: 'Next base Joker becomes Foil' },
|
|
158
|
-
holographictag: { label: 'HOLO TAG', body: 'Next base Joker becomes Holographic' },
|
|
159
|
-
polychrometag: { label: 'POLY TAG', body: 'Next base Joker becomes Polychrome' },
|
|
160
|
-
topuptag: { label: 'TOP-UP TAG', body: 'Create up to 2 Common Jokers' },
|
|
161
|
-
standardtag: { label: 'STANDARD TAG', body: 'Free Standard Booster Pack' },
|
|
162
|
-
charmtag: { label: 'CHARM TAG', body: 'Free Mega Arcana Pack' },
|
|
163
|
-
meteortag: { label: 'METEOR TAG', body: 'Free Mega Celestial Pack' },
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// ── BlindSection — boss header + packs + shop 6 items in 2 rows of 3
|
|
167
|
-
function BlindSection({ blind }) {
|
|
168
|
-
return (
|
|
169
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 18 }}>
|
|
170
|
-
<BlindHeader kind={blind.kind} boss={blind.boss} />
|
|
171
|
-
<div style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
|
|
172
|
-
<div style={{ flex: 1 }}>
|
|
173
|
-
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
|
|
174
|
-
{blind.shop.map((item, i) => (
|
|
175
|
-
<div key={i} style={{ display: 'flex', justifyContent: 'center' }}>
|
|
176
|
-
<CardItem item={item} size={58} />
|
|
177
|
-
</div>
|
|
178
|
-
))}
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
{blind.packs && blind.packs.length > 0 && (
|
|
182
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
183
|
-
{blind.packs.map((p, i) => <PackCluster key={i} pack={p} />)}
|
|
184
|
-
</div>
|
|
185
|
-
)}
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// ── AntePage — voucher + tags row, then all three blinds
|
|
192
|
-
function AntePage({ ante }) {
|
|
193
|
-
if (ante.isPre) {
|
|
194
|
-
return (
|
|
195
|
-
<div style={{ padding: 20, color: '#b0c0c4', fontFamily: 'm6x11plus, monospace', fontSize: 14, textAlign: 'center' }}>
|
|
196
|
-
<div style={{ fontSize: 18, color: '#fff', marginBottom: 8 }}>RUN START</div>
|
|
197
|
-
<div style={{ opacity: 0.7 }}>Swipe up to Ante 1 →</div>
|
|
198
|
-
</div>
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
return (
|
|
202
|
-
<div style={{ padding: '16px 14px 40px' }}>
|
|
203
|
-
{/* Ante header */}
|
|
204
|
-
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
|
|
205
|
-
<div style={{ fontFamily: 'm6x11plus, monospace', fontSize: 22, color: '#fff', letterSpacing: 1 }}>ANTE {ante.ante}</div>
|
|
206
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
207
|
-
{ante.tags.map((t, i) => <TagCluster key={i} tag={t} />)}
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
|
|
211
|
-
{/* Voucher strip */}
|
|
212
|
-
{ante.voucher ? (
|
|
213
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14, padding: '8px 10px', background: '#1a2529', border: '2px solid #0b1416', borderRadius: 6 }}>
|
|
214
|
-
<VoucherMini name={ante.voucher.name} size={50} hit={ante.voucher.hits?.length ? 'should' : null} />
|
|
215
|
-
<div>
|
|
216
|
-
<div style={{ fontFamily: 'm6x11plus, monospace', fontSize: 11, color: '#7e8e91', letterSpacing: 1 }}>VOUCHER</div>
|
|
217
|
-
<div style={{ fontFamily: 'm6x11plus, monospace', fontSize: 15, color: '#fff' }}>{ante.voucher.name}</div>
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
) : null}
|
|
221
|
-
|
|
222
|
-
{ante.blinds.map((b) => <BlindSection key={b.kind} blind={b} />)}
|
|
223
|
-
</div>
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
window.AntePage = AntePage;
|
|
228
|
-
window.BalatroPanel = BalatroPanel;
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
// SeedDetail — the full phone-sized screen.
|
|
2
|
-
// ┌──────────────────────────┐
|
|
3
|
-
// │ TOP BAR │ fixed
|
|
4
|
-
// │ seed · deck · score row │
|
|
5
|
-
// │ score column per clause │
|
|
6
|
-
// ├──────────────────────────┤
|
|
7
|
-
// │ ⟨ horizontal pager ⟩ │
|
|
8
|
-
// │ ┃ vertical ante snap │ swipes L/R between seeds,
|
|
9
|
-
// │ ┃ ┃ page 0 (pre) │ swipes up/down between antes
|
|
10
|
-
// │ ┃ ┃ page 1..N │
|
|
11
|
-
// │ ┃ │
|
|
12
|
-
// └──────────────────────────┘
|
|
13
|
-
|
|
14
|
-
const { useState: sdUS, useRef: sdUR, useEffect: sdUE } = React;
|
|
15
|
-
|
|
16
|
-
// ── Score column: one per should-clause + must-clause.
|
|
17
|
-
function ScoreCol({ clause, hits, kind }) {
|
|
18
|
-
const hit = hits > 0;
|
|
19
|
-
const must = kind === 'must';
|
|
20
|
-
return (
|
|
21
|
-
<div
|
|
22
|
-
style={{
|
|
23
|
-
flex: 1,
|
|
24
|
-
background: hit ? '#1e2e2e' : '#161c1e',
|
|
25
|
-
border: `2px solid ${hit ? clause.color || '#3e4a4d' : '#0b1416'}`,
|
|
26
|
-
borderRadius: 4,
|
|
27
|
-
padding: '4px 6px',
|
|
28
|
-
display: 'flex',
|
|
29
|
-
flexDirection: 'column',
|
|
30
|
-
alignItems: 'center',
|
|
31
|
-
gap: 2,
|
|
32
|
-
minWidth: 0,
|
|
33
|
-
}}
|
|
34
|
-
>
|
|
35
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 4, height: 22 }}>
|
|
36
|
-
{clause.kind === 'Joker' && <Sprite sheet="jokers" name={clause.target} width={18} height={24} />}
|
|
37
|
-
{clause.kind === 'Voucher' && <Sprite sheet="vouchers" name={clause.target} width={18} height={24} />}
|
|
38
|
-
{clause.kind === 'Tag' && <Sprite sheet="tags" name={clause.target} width={20} height={20} />}
|
|
39
|
-
</div>
|
|
40
|
-
<div style={{ fontFamily: 'm6x11plus, monospace', fontSize: 9, color: hit ? '#fff' : '#556265', letterSpacing: 0.5, lineHeight: 1, textTransform: 'uppercase', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%' }}>
|
|
41
|
-
{clause.target}
|
|
42
|
-
</div>
|
|
43
|
-
<div
|
|
44
|
-
style={{
|
|
45
|
-
fontFamily: 'm6x11plus, monospace',
|
|
46
|
-
fontSize: 16,
|
|
47
|
-
color: must ? '#e4b643' : hit ? '#35bd86' : '#3e4a4d',
|
|
48
|
-
lineHeight: 1,
|
|
49
|
-
}}
|
|
50
|
-
>
|
|
51
|
-
×{hits}
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function TopBar({ seed, filter }) {
|
|
58
|
-
return (
|
|
59
|
-
<div style={{ background: '#0f1719', borderBottom: '2px solid #000', padding: '10px 12px 10px', position: 'sticky', top: 0, zIndex: 20 }}>
|
|
60
|
-
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
61
|
-
<button style={chromeBtn}>
|
|
62
|
-
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M9 2L4 7l5 5"/></svg>
|
|
63
|
-
</button>
|
|
64
|
-
<div style={{ textAlign: 'center' }}>
|
|
65
|
-
<div style={{ fontFamily: 'm6x11plus, monospace', fontSize: 18, color: '#fff', letterSpacing: 2 }}>{seed.seed}</div>
|
|
66
|
-
<div style={{ fontFamily: 'm6x11plus, monospace', fontSize: 10, color: '#7e8e91', letterSpacing: 1 }}>{seed.deck} · {seed.stake}</div>
|
|
67
|
-
</div>
|
|
68
|
-
<button style={chromeBtn}>
|
|
69
|
-
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><circle cx="7" cy="7" r="1.2"/><circle cx="2" cy="7" r="1.2"/><circle cx="12" cy="7" r="1.2"/></svg>
|
|
70
|
-
</button>
|
|
71
|
-
</div>
|
|
72
|
-
<div style={{ fontFamily: 'm6x11plus, monospace', fontSize: 9, color: '#556265', letterSpacing: 1, marginBottom: 4 }}>
|
|
73
|
-
FILTER · {filter.name.toUpperCase()}
|
|
74
|
-
</div>
|
|
75
|
-
<div style={{ display: 'flex', gap: 4 }}>
|
|
76
|
-
{filter.shouldClauses.map((c) => (
|
|
77
|
-
<ScoreCol key={c.id} clause={c} hits={seed.score.perClause[c.id] || 0} kind="should" />
|
|
78
|
-
))}
|
|
79
|
-
{filter.mustClauses.map((c) => (
|
|
80
|
-
<ScoreCol key={c.id} clause={{ ...c, color: '#e4b643' }} hits={seed.score.perClause[c.id] || 0} kind="must" />
|
|
81
|
-
))}
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const chromeBtn = {
|
|
88
|
-
width: 30, height: 30, border: '2px solid #0b1416', borderRadius: 4, background: '#2a3336',
|
|
89
|
-
color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer',
|
|
90
|
-
boxShadow: 'inset 0 1px 0 rgba(255,255,255,.1), 0 2px 0 #0b1416',
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
// ── Vertical snap scroller of AntePage; shows ante index indicator
|
|
94
|
-
function SeedPager({ seed, filter }) {
|
|
95
|
-
const scrollRef = sdUR(null);
|
|
96
|
-
const [anteIdx, setAnteIdx] = sdUS(1);
|
|
97
|
-
const onScroll = (e) => {
|
|
98
|
-
const el = e.currentTarget;
|
|
99
|
-
const i = Math.round(el.scrollTop / el.clientHeight);
|
|
100
|
-
if (i !== anteIdx) setAnteIdx(i);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
<div style={{ position: 'relative', flex: 1, minHeight: 0, display: 'flex', overflow: 'hidden' }}>
|
|
105
|
-
<div
|
|
106
|
-
ref={scrollRef}
|
|
107
|
-
onScroll={onScroll}
|
|
108
|
-
style={{
|
|
109
|
-
flex: 1,
|
|
110
|
-
overflowY: 'auto',
|
|
111
|
-
overflowX: 'hidden',
|
|
112
|
-
scrollSnapType: 'y mandatory',
|
|
113
|
-
scrollbarWidth: 'none',
|
|
114
|
-
}}
|
|
115
|
-
>
|
|
116
|
-
{seed.antes.map((ante, i) => (
|
|
117
|
-
<div key={i} style={{ minHeight: '100%', scrollSnapAlign: 'start', scrollSnapStop: 'always' }}>
|
|
118
|
-
<AntePage ante={ante} />
|
|
119
|
-
</div>
|
|
120
|
-
))}
|
|
121
|
-
</div>
|
|
122
|
-
|
|
123
|
-
{/* Right-edge ante rail */}
|
|
124
|
-
<div style={{ position: 'absolute', right: 4, top: 8, bottom: 8, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 4, pointerEvents: 'none' }}>
|
|
125
|
-
{seed.antes.map((a, i) => (
|
|
126
|
-
<div
|
|
127
|
-
key={i}
|
|
128
|
-
style={{
|
|
129
|
-
width: 3,
|
|
130
|
-
height: i === anteIdx ? 18 : 8,
|
|
131
|
-
borderRadius: 2,
|
|
132
|
-
background: i === anteIdx ? '#e4b643' : '#3e4a4d',
|
|
133
|
-
transition: 'all 200ms',
|
|
134
|
-
}}
|
|
135
|
-
/>
|
|
136
|
-
))}
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// ── Root: horizontal seed swiper wrapping the vertical pager
|
|
143
|
-
function SeedDetail({ seeds, filter }) {
|
|
144
|
-
const [idx, setIdx] = sdUS(0);
|
|
145
|
-
const [drag, setDrag] = sdUS({ dx: 0, active: false });
|
|
146
|
-
const touch = sdUR({ x0: 0, y0: 0, locked: null });
|
|
147
|
-
|
|
148
|
-
const onDown = (e) => {
|
|
149
|
-
const t = e.touches ? e.touches[0] : e;
|
|
150
|
-
// only start tracking from top bar region (safe)
|
|
151
|
-
touch.current = { x0: t.clientX, y0: t.clientY, locked: null };
|
|
152
|
-
};
|
|
153
|
-
const onMove = (e) => {
|
|
154
|
-
if (!touch.current.x0) return;
|
|
155
|
-
const t = e.touches ? e.touches[0] : e;
|
|
156
|
-
const dx = t.clientX - touch.current.x0;
|
|
157
|
-
const dy = t.clientY - touch.current.y0;
|
|
158
|
-
if (touch.current.locked == null) {
|
|
159
|
-
if (Math.abs(dx) > 8 && Math.abs(dx) > Math.abs(dy) * 1.5) touch.current.locked = 'x';
|
|
160
|
-
else if (Math.abs(dy) > 8) touch.current.locked = 'y';
|
|
161
|
-
}
|
|
162
|
-
if (touch.current.locked === 'x') {
|
|
163
|
-
e.preventDefault?.();
|
|
164
|
-
setDrag({ dx, active: true });
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
const onUp = () => {
|
|
168
|
-
if (touch.current.locked === 'x') {
|
|
169
|
-
const dx = drag.dx;
|
|
170
|
-
if (dx < -70 && idx < seeds.length - 1) setIdx(idx + 1);
|
|
171
|
-
else if (dx > 70 && idx > 0) setIdx(idx - 1);
|
|
172
|
-
}
|
|
173
|
-
touch.current = { x0: 0, y0: 0, locked: null };
|
|
174
|
-
setDrag({ dx: 0, active: false });
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const seed = seeds[idx];
|
|
178
|
-
|
|
179
|
-
return (
|
|
180
|
-
<div
|
|
181
|
-
style={{
|
|
182
|
-
width: '100%',
|
|
183
|
-
height: '100%',
|
|
184
|
-
background: '#0b1416',
|
|
185
|
-
display: 'flex',
|
|
186
|
-
flexDirection: 'column',
|
|
187
|
-
position: 'relative',
|
|
188
|
-
overflow: 'hidden',
|
|
189
|
-
fontFamily: 'm6x11plus, monospace',
|
|
190
|
-
color: '#fff',
|
|
191
|
-
}}
|
|
192
|
-
>
|
|
193
|
-
{/* Seed-swipe layer: only the top bar is draggable for horizontal
|
|
194
|
-
swipes (keeps vertical scroll natural inside the ante pager). */}
|
|
195
|
-
<div onPointerDown={onDown} onPointerMove={onMove} onPointerUp={onUp} onPointerCancel={onUp}
|
|
196
|
-
style={{ touchAction: 'pan-y' }}>
|
|
197
|
-
<TopBar seed={seed} filter={filter} />
|
|
198
|
-
</div>
|
|
199
|
-
|
|
200
|
-
<div
|
|
201
|
-
style={{
|
|
202
|
-
flex: 1,
|
|
203
|
-
minHeight: 0,
|
|
204
|
-
position: 'relative',
|
|
205
|
-
transform: drag.active ? `translateX(${drag.dx * 0.3}px) rotate(${drag.dx * 0.02}deg)` : 'none',
|
|
206
|
-
transition: drag.active ? 'none' : 'transform 260ms cubic-bezier(.33,1,.4,1)',
|
|
207
|
-
}}
|
|
208
|
-
>
|
|
209
|
-
<SeedPager key={seed.seed} seed={seed} filter={filter} />
|
|
210
|
-
</div>
|
|
211
|
-
|
|
212
|
-
{/* Seed dots */}
|
|
213
|
-
<div style={{ position: 'absolute', bottom: 6, left: '50%', transform: 'translateX(-50%)', display: 'flex', gap: 5 }}>
|
|
214
|
-
{seeds.map((_, i) => (
|
|
215
|
-
<div key={i} style={{ width: 6, height: 6, borderRadius: 3, background: i === idx ? '#e4b643' : '#3e4a4d' }} />
|
|
216
|
-
))}
|
|
217
|
-
</div>
|
|
218
|
-
</div>
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
window.SeedDetail = SeedDetail;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// App shell — wraps SeedDetail in a design_canvas artboard at phone size.
|
|
2
|
-
|
|
3
|
-
function App() {
|
|
4
|
-
const [mapsReady, setMapsReady] = React.useState(false);
|
|
5
|
-
|
|
6
|
-
React.useEffect(() => {
|
|
7
|
-
(async () => {
|
|
8
|
-
await Promise.all([
|
|
9
|
-
window.loadSpriteMap('jokers', 'assets/jokers.json'),
|
|
10
|
-
window.loadSpriteMap('tarots', 'assets/tarots.json'),
|
|
11
|
-
window.loadSpriteMap('vouchers', 'assets/vouchers.json'),
|
|
12
|
-
window.loadSpriteMap('tags', 'assets/tags.json'),
|
|
13
|
-
window.loadSpriteMap('boosters', 'assets/boosters.json'),
|
|
14
|
-
window.loadSpriteMap('blinds', 'assets/blinds.json'),
|
|
15
|
-
]);
|
|
16
|
-
setMapsReady(true);
|
|
17
|
-
})();
|
|
18
|
-
}, []);
|
|
19
|
-
|
|
20
|
-
if (!mapsReady) {
|
|
21
|
-
return <div style={{ padding: 40, color: '#fff', fontFamily: 'm6x11plus, monospace' }}>Loading sprites…</div>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<DesignCanvas>
|
|
26
|
-
<DCSection id="seed-detail" title="Seed Detail" subtitle="Mobile seed view — swipe ↕ between antes, ↔ between seeds">
|
|
27
|
-
<DCArtboard id="hifi" label="Hi-fi · Balatro native" width={390} height={844}>
|
|
28
|
-
<SeedDetail seeds={window.MOCK_SEEDS} filter={window.MOCK_FILTER} />
|
|
29
|
-
</DCArtboard>
|
|
30
|
-
</DCSection>
|
|
31
|
-
</DesignCanvas>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
// Mock data: a "Blueprint + Brainstorm + Telescope" filter + one seed.
|
|
2
|
-
// Schema matches JAML should/must clauses. Each hit on the seed carries a
|
|
3
|
-
// clauseId so the card can attribute per-clause score.
|
|
4
|
-
|
|
5
|
-
window.MOCK_FILTER = {
|
|
6
|
-
name: 'Blueprint Parade',
|
|
7
|
-
mustClauses: [
|
|
8
|
-
{ id: 'm1', kind: 'Joker', target: 'Blueprint', antes: [1, 2, 3, 4, 5, 6, 7, 8] },
|
|
9
|
-
],
|
|
10
|
-
shouldClauses: [
|
|
11
|
-
{ id: 's1', kind: 'Joker', target: 'Blueprint', antes: [1, 2, 3, 4, 5, 6, 7, 8], color: '#ff4c40' },
|
|
12
|
-
{ id: 's2', kind: 'Joker', target: 'Brainstorm', antes: [1, 2, 3, 4, 5, 6, 7, 8], color: '#0093ff' },
|
|
13
|
-
{ id: 's3', kind: 'Voucher', target: 'Telescope', antes: [1, 2, 3, 4, 5, 6, 7, 8], color: '#e4b643' },
|
|
14
|
-
],
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// ── Helper for seed generation ────────────────────────────────
|
|
18
|
-
// Each ante has: voucher (or null), tags [2], smallBlindPack,
|
|
19
|
-
// bigBlindPack, boss, and 4 shops (small, big, boss — each has 6 items
|
|
20
|
-
// in 2 rows of 3, but Balatro shops cycle, so we just show a few reroll
|
|
21
|
-
// batches). For simplicity: one shop per blind, 4 items per shop slot row.
|
|
22
|
-
|
|
23
|
-
// Each item: { kind:'Joker'|'Tarot'|'Voucher'|'Pack', name, edition?, hits?:[clauseId] }
|
|
24
|
-
// hits = array of clauseIds this item satisfies. Renderer stamps a badge
|
|
25
|
-
// per hit and builds the per-clause score by counting.
|
|
26
|
-
|
|
27
|
-
const seed1 = {
|
|
28
|
-
seed: 'GR0XQVCF',
|
|
29
|
-
deck: 'Red Deck',
|
|
30
|
-
stake: 'Blue Stake',
|
|
31
|
-
score: { total: 7, perClause: { s1: 3, s2: 3, s3: 1, m1: 3 } },
|
|
32
|
-
antes: [
|
|
33
|
-
// Ante 0 is pre-game (just deck/stake summary)
|
|
34
|
-
{ ante: 0, voucher: null, tags: [], blinds: [], isPre: true },
|
|
35
|
-
|
|
36
|
-
// Ante 1
|
|
37
|
-
{
|
|
38
|
-
ante: 1,
|
|
39
|
-
voucher: { name: 'Overstock', hits: [] },
|
|
40
|
-
tags: [{ name: 'RareTag', hits: [] }, { name: 'UncommonTag', hits: [] }],
|
|
41
|
-
blinds: [
|
|
42
|
-
{ kind: 'small', boss: 'SmallBlind',
|
|
43
|
-
shop: [
|
|
44
|
-
{ kind: 'Joker', name: 'Joker', hits: [] },
|
|
45
|
-
{ kind: 'Joker', name: 'GreedyJoker', hits: [] },
|
|
46
|
-
{ kind: 'Joker', name: 'Blueprint', edition: 'Foil', hits: ['m1', 's1'] },
|
|
47
|
-
{ kind: 'Tarot', name: 'TheFool', hits: [] },
|
|
48
|
-
{ kind: 'Tarot', name: 'TheEmpress', hits: [] },
|
|
49
|
-
{ kind: 'Joker', name: 'JollyJoker', hits: [] },
|
|
50
|
-
],
|
|
51
|
-
packs: [{ kind: 'ArcanaPack', contents: [
|
|
52
|
-
{ kind: 'Tarot', name: 'TheMagician', hits: [] },
|
|
53
|
-
{ kind: 'Tarot', name: 'TheHighPriestess', hits: [] },
|
|
54
|
-
{ kind: 'Tarot', name: 'TheEmperor', hits: [] },
|
|
55
|
-
] }],
|
|
56
|
-
},
|
|
57
|
-
{ kind: 'big', boss: 'BigBlind',
|
|
58
|
-
shop: [
|
|
59
|
-
{ kind: 'Joker', name: 'WrathfulJoker', hits: [] },
|
|
60
|
-
{ kind: 'Joker', name: 'ZanyJoker', hits: [] },
|
|
61
|
-
{ kind: 'Tarot', name: 'TheLovers', hits: [] },
|
|
62
|
-
{ kind: 'Joker', name: 'GrosMichel', hits: [] },
|
|
63
|
-
{ kind: 'Joker', name: 'EvenSteven', hits: [] },
|
|
64
|
-
{ kind: 'Joker', name: 'OddTodd', hits: [] },
|
|
65
|
-
],
|
|
66
|
-
packs: [{ kind: 'BuffoonPack', contents: [
|
|
67
|
-
{ kind: 'Joker', name: 'Brainstorm', hits: ['s2'] },
|
|
68
|
-
{ kind: 'Joker', name: 'Fibonacci', hits: [] },
|
|
69
|
-
] }],
|
|
70
|
-
},
|
|
71
|
-
{ kind: 'boss', boss: 'TheOx',
|
|
72
|
-
shop: [
|
|
73
|
-
{ kind: 'Voucher', name: 'Telescope', hits: ['s3'] },
|
|
74
|
-
{ kind: 'Joker', name: 'Scholar', hits: [] },
|
|
75
|
-
{ kind: 'Joker', name: 'Supernova', hits: [] },
|
|
76
|
-
{ kind: 'Tarot', name: 'TheHierophant', hits: [] },
|
|
77
|
-
{ kind: 'Joker', name: 'Ceremonial', hits: [] },
|
|
78
|
-
{ kind: 'Joker', name: 'Banner', hits: [] },
|
|
79
|
-
],
|
|
80
|
-
packs: [{ kind: 'StandardPack', contents: [] }],
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
// Ante 2
|
|
86
|
-
{
|
|
87
|
-
ante: 2,
|
|
88
|
-
voucher: { name: 'ClearanceSale', hits: [] },
|
|
89
|
-
tags: [{ name: 'TopUpTag', hits: [] }, { name: 'FoilTag', hits: [] }],
|
|
90
|
-
blinds: [
|
|
91
|
-
{ kind: 'small', boss: 'SmallBlind',
|
|
92
|
-
shop: [
|
|
93
|
-
{ kind: 'Joker', name: 'Joker', hits: [] },
|
|
94
|
-
{ kind: 'Joker', name: 'MadJoker', hits: [] },
|
|
95
|
-
{ kind: 'Joker', name: 'CrazyJoker', hits: [] },
|
|
96
|
-
{ kind: 'Tarot', name: 'Strength', hits: [] },
|
|
97
|
-
{ kind: 'Joker', name: 'DrollJoker', hits: [] },
|
|
98
|
-
{ kind: 'Joker', name: 'HalfJoker', hits: [] },
|
|
99
|
-
],
|
|
100
|
-
packs: [{ kind: 'CelestialPack', contents: [] }],
|
|
101
|
-
},
|
|
102
|
-
{ kind: 'big', boss: 'BigBlind',
|
|
103
|
-
shop: [
|
|
104
|
-
{ kind: 'Joker', name: 'Blueprint', edition: 'Holographic', hits: ['m1', 's1'] },
|
|
105
|
-
{ kind: 'Joker', name: 'SlyJoker', hits: [] },
|
|
106
|
-
{ kind: 'Tarot', name: 'TheHermit', hits: [] },
|
|
107
|
-
{ kind: 'Joker', name: 'WilyJoker', hits: [] },
|
|
108
|
-
{ kind: 'Joker', name: 'CleverJoker', hits: [] },
|
|
109
|
-
{ kind: 'Joker', name: 'DeviousJoker', hits: [] },
|
|
110
|
-
],
|
|
111
|
-
packs: [{ kind: 'MegaArcanaPack', contents: [
|
|
112
|
-
{ kind: 'Tarot', name: 'Justice', hits: [] },
|
|
113
|
-
{ kind: 'Tarot', name: 'Death', hits: [] },
|
|
114
|
-
{ kind: 'Tarot', name: 'Temperance', hits: [] },
|
|
115
|
-
{ kind: 'Tarot', name: 'TheDevil', hits: [] },
|
|
116
|
-
{ kind: 'Tarot', name: 'TheTower', hits: [] },
|
|
117
|
-
] }],
|
|
118
|
-
},
|
|
119
|
-
{ kind: 'boss', boss: 'TheHouse',
|
|
120
|
-
shop: [
|
|
121
|
-
{ kind: 'Joker', name: 'Brainstorm', edition: 'Polychrome', hits: ['s2'] },
|
|
122
|
-
{ kind: 'Joker', name: 'Banner', hits: [] },
|
|
123
|
-
{ kind: 'Joker', name: 'MysticSummit', hits: [] },
|
|
124
|
-
{ kind: 'Joker', name: 'MarbleJoker', hits: [] },
|
|
125
|
-
{ kind: 'Joker', name: 'LoyaltyCard', hits: [] },
|
|
126
|
-
{ kind: 'Joker', name: 'EightBall', hits: [] },
|
|
127
|
-
],
|
|
128
|
-
packs: [{ kind: 'SpectralPack', contents: [] }],
|
|
129
|
-
},
|
|
130
|
-
],
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
// Ante 3
|
|
134
|
-
{
|
|
135
|
-
ante: 3,
|
|
136
|
-
voucher: null,
|
|
137
|
-
tags: [{ name: 'HolographicTag', hits: [] }, { name: 'NegativeTag', hits: [] }],
|
|
138
|
-
blinds: [
|
|
139
|
-
{ kind: 'small', boss: 'SmallBlind',
|
|
140
|
-
shop: [
|
|
141
|
-
{ kind: 'Joker', name: 'Brainstorm', edition: 'Foil', hits: ['s2'] },
|
|
142
|
-
{ kind: 'Joker', name: 'Misprint', hits: [] },
|
|
143
|
-
{ kind: 'Tarot', name: 'TheStar', hits: [] },
|
|
144
|
-
{ kind: 'Joker', name: 'RaisedFist', hits: [] },
|
|
145
|
-
{ kind: 'Joker', name: 'Chaos', hits: [] },
|
|
146
|
-
{ kind: 'Joker', name: 'Fibonacci', hits: [] },
|
|
147
|
-
],
|
|
148
|
-
packs: [{ kind: 'ArcanaPack', contents: [] }],
|
|
149
|
-
},
|
|
150
|
-
{ kind: 'big', boss: 'BigBlind',
|
|
151
|
-
shop: [
|
|
152
|
-
{ kind: 'Joker', name: 'SteelJoker', hits: [] },
|
|
153
|
-
{ kind: 'Joker', name: 'ScaryFace', hits: [] },
|
|
154
|
-
{ kind: 'Joker', name: 'AbstractJoker', hits: [] },
|
|
155
|
-
{ kind: 'Joker', name: 'DelayedGratification', hits: [] },
|
|
156
|
-
{ kind: 'Joker', name: 'Pareidolia', hits: [] },
|
|
157
|
-
{ kind: 'Joker', name: 'Hack', hits: [] },
|
|
158
|
-
],
|
|
159
|
-
packs: [{ kind: 'JumboBuffoonPack', contents: [
|
|
160
|
-
{ kind: 'Joker', name: 'Blueprint', hits: ['m1', 's1'] },
|
|
161
|
-
{ kind: 'Joker', name: 'Cartomancer', hits: [] },
|
|
162
|
-
{ kind: 'Joker', name: 'Astronomer', hits: [] },
|
|
163
|
-
] }],
|
|
164
|
-
},
|
|
165
|
-
{ kind: 'boss', boss: 'TheClub',
|
|
166
|
-
shop: [
|
|
167
|
-
{ kind: 'Joker', name: 'Gros Michel', hits: [] },
|
|
168
|
-
{ kind: 'Joker', name: 'EvenSteven', hits: [] },
|
|
169
|
-
{ kind: 'Joker', name: 'OddTodd', hits: [] },
|
|
170
|
-
{ kind: 'Joker', name: 'Scholar', hits: [] },
|
|
171
|
-
{ kind: 'Joker', name: 'BusinessCard', hits: [] },
|
|
172
|
-
{ kind: 'Joker', name: 'Supernova', hits: [] },
|
|
173
|
-
],
|
|
174
|
-
packs: [{ kind: 'StandardPack', contents: [] }],
|
|
175
|
-
},
|
|
176
|
-
],
|
|
177
|
-
},
|
|
178
|
-
],
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
// Two more placeholder seeds so the horizontal swipe has somewhere to go.
|
|
182
|
-
const seed2 = { ...seed1, seed: 'ALEPH999', score: { total: 4, perClause: { s1: 2, s2: 1, s3: 1, m1: 2 } } };
|
|
183
|
-
const seed3 = { ...seed1, seed: 'BETAZERO', score: { total: 6, perClause: { s1: 3, s2: 2, s3: 1, m1: 3 } } };
|
|
184
|
-
|
|
185
|
-
window.MOCK_SEEDS = [seed1, seed2, seed3];
|