jaml-ui 0.24.14 → 0.24.16
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/components/JamlCurator.js +1 -1
- package/dist/components/JamlIde.js +11 -17
- package/dist/components/RunConfigModal.d.ts +8 -0
- package/dist/components/RunConfigModal.js +198 -0
- package/dist/ui/jimbo.css +8 -8
- package/dist/ui/jimboApp.d.ts +2 -2
- package/dist/ui/jimboApp.js +1 -1
- package/dist/ui/radial/RadialMenu.js +1 -1
- package/dist/ui/radial/radialMenuViewport.js +1 -1
- package/dist/ui/showcase.d.ts +1 -1
- package/dist/ui/showcase.js +1 -1
- package/package.json +1 -1
|
@@ -11,7 +11,6 @@ import { JimboColorOption } from "../ui/tokens.js";
|
|
|
11
11
|
import { JimboModal } from "../ui/panel.js";
|
|
12
12
|
import { jamlTextToVisualFilter, visualFilterToJamlText } from "../utils/jamlVisualFilter.js";
|
|
13
13
|
import { DeckSprite } from "./DeckSprite.js";
|
|
14
|
-
import { DECK_OPTIONS, STAKE_OPTIONS } from "../lib/data/constants.js";
|
|
15
14
|
const CATEGORY_CONFIG_MAP = {
|
|
16
15
|
voucher: VOUCHER_PICKER_CONFIG,
|
|
17
16
|
tag: TAG_PICKER_CONFIG,
|
|
@@ -104,25 +103,20 @@ function setRootValue(jaml, key, value) {
|
|
|
104
103
|
const trimmed = jaml.trimEnd();
|
|
105
104
|
return trimmed.length > 0 ? `${line}\n${trimmed}` : line;
|
|
106
105
|
}
|
|
107
|
-
|
|
106
|
+
import { RunConfigModal } from "./RunConfigModal.js";
|
|
107
|
+
function DeckStakeSelector({ jaml, onChange, onSearch, }) {
|
|
108
108
|
const deck = readRootValue(jaml, "deck", "Red");
|
|
109
109
|
const stake = readRootValue(jaml, "stake", "White");
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
|
|
110
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
111
|
+
const handleApply = (nextDeck, nextStake) => {
|
|
112
|
+
let next = setRootValue(jaml, "deck", nextDeck);
|
|
113
|
+
next = setRootValue(next, "stake", nextStake);
|
|
114
|
+
onChange(next);
|
|
115
|
+
onSearch?.();
|
|
116
|
+
};
|
|
117
|
+
return (_jsxs(_Fragment, { children: [_jsx("button", { onClick: () => setModalOpen(true), className: "j-btn j-btn--red", style: { height: 32, padding: 0, borderRadius: 8, overflow: 'hidden' }, children: _jsxs("div", { className: "j-btn__face", style: { display: 'flex', alignItems: 'center', gap: 8, padding: '0 8px 0 4px', height: '100%' }, children: [_jsx(DeckSprite, { deck: deck, stake: stake, size: compactDeckSpriteSize }), _jsxs("span", { style: { fontFamily: "m6x11plus, monospace", fontSize: 14 }, children: [deck, " / ", stake] })] }) }), _jsx(RunConfigModal, { open: modalOpen, onClose: () => setModalOpen(false), deck: deck, stake: stake, onChange: handleApply })] }));
|
|
113
118
|
}
|
|
114
119
|
const compactDeckSpriteSize = 24;
|
|
115
|
-
const selectorStyle = {
|
|
116
|
-
minWidth: 0,
|
|
117
|
-
height: 28,
|
|
118
|
-
borderRadius: 8,
|
|
119
|
-
border: `1px solid ${JimboColorOption.PANEL_EDGE}`,
|
|
120
|
-
background: JimboColorOption.DARKEST,
|
|
121
|
-
color: JimboColorOption.WHITE,
|
|
122
|
-
fontFamily: "m6x11plus, monospace",
|
|
123
|
-
fontSize: 12,
|
|
124
|
-
padding: "0 8px",
|
|
125
|
-
};
|
|
126
120
|
export function JamlIde({ jaml, defaultJaml, onChange, defaultMode = "code", searchResults = [], className = "", style, title = "JAML IDE", subtitle = "Jimbo's Ante Markup Language", compactHeader = false, actions, codePlaceholder = "Enter JAML...", onSearch, isSearching = false, hideFooter = false, visualFilter, onVisualFilterChange, }) {
|
|
127
121
|
const [mode, setMode] = useState(defaultMode);
|
|
128
122
|
const [internalText, setInternalText] = useState(jaml ?? defaultJaml ?? "");
|
|
@@ -223,5 +217,5 @@ export function JamlIde({ jaml, defaultJaml, onChange, defaultMode = "code", sea
|
|
|
223
217
|
padding: compactHeader ? "8px 10px" : "10px 14px",
|
|
224
218
|
borderBottom: `1px solid ${JimboColorOption.PANEL_EDGE}`,
|
|
225
219
|
background: JimboColorOption.TEAL_GREY,
|
|
226
|
-
}, children: [_jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, fontWeight: "normal", fontFamily: "m6x11plus, monospace", color: JimboColorOption.GOLD_TEXT }, children: title }), subtitle ? _jsx("div", { style: { fontSize: 11, color: JimboColorOption.GREY }, children: subtitle }) : null] }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", justifyContent: "flex-end" }, children: [_jsx(DeckStakeSelector, { jaml: text, onChange: handleTextChange }), actions] })] }), _jsx(JamlIdeToolbar, { mode: mode, onModeChange: setMode, resultCount: results.length, onSearch: onSearch, isSearching: isSearching }), _jsxs("div", { style: { flex: 1, minHeight: 0, overflow: mode === "map" ? "hidden" : "auto", background: JimboColorOption.DARKEST }, children: [mode === "visual" ? (_jsx(JamlIdeVisual, { filter: activeFilter, onChange: handleVisualFilterChange, onAddClause: handleAddClause })) : null, mode === "code" ? (_jsx(JamlCodeEditor, { value: text, onChange: handleTextChange, placeholder: codePlaceholder })) : null, mode === "map" ? _jsx(JamlMapEditor, { onChange: handleTextChange }) : null, mode === "results" ? (_jsx("div", { style: { padding: 12 }, children: _jsx(ResultsView, { results: results, jaml: text }) })) : null] }), !hideFooter && _jsx(JimboBalatroFooter, {}), _jsx(JimboModal, { open: addZone !== null, onClose: handlePickerClose, children: addZone !== null && (pickerFlow === "category" ? (_jsx(CategoryMenu, { onSelect: (cat) => setPickerFlow(cat) })) : pickerFlow === "joker" ? (_jsx(JokerPicker, { onSelect: handlePickerSelect, onCancel: handlePickerClose })) : (_jsx(CategoryPicker, { config: CATEGORY_CONFIG_MAP[pickerFlow], onSelect: handlePickerSelect, onCancel: handlePickerClose }))) })] }));
|
|
220
|
+
}, children: [_jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, fontWeight: "normal", fontFamily: "m6x11plus, monospace", color: JimboColorOption.GOLD_TEXT }, children: title }), subtitle ? _jsx("div", { style: { fontSize: 11, color: JimboColorOption.GREY }, children: subtitle }) : null] }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", justifyContent: "flex-end" }, children: [_jsx(DeckStakeSelector, { jaml: text, onChange: handleTextChange, onSearch: onSearch }), actions] })] }), _jsx(JamlIdeToolbar, { mode: mode, onModeChange: setMode, resultCount: results.length, onSearch: onSearch, isSearching: isSearching }), _jsxs("div", { style: { flex: 1, minHeight: 0, overflow: mode === "map" ? "hidden" : "auto", background: JimboColorOption.DARKEST }, children: [mode === "visual" ? (_jsx(JamlIdeVisual, { filter: activeFilter, onChange: handleVisualFilterChange, onAddClause: handleAddClause })) : null, mode === "code" ? (_jsx(JamlCodeEditor, { value: text, onChange: handleTextChange, placeholder: codePlaceholder })) : null, mode === "map" ? _jsx(JamlMapEditor, { onChange: handleTextChange }) : null, mode === "results" ? (_jsx("div", { style: { padding: 12 }, children: _jsx(ResultsView, { results: results, jaml: text }) })) : null] }), !hideFooter && _jsx(JimboBalatroFooter, {}), _jsx(JimboModal, { open: addZone !== null, onClose: handlePickerClose, children: addZone !== null && (pickerFlow === "category" ? (_jsx(CategoryMenu, { onSelect: (cat) => setPickerFlow(cat) })) : pickerFlow === "joker" ? (_jsx(JokerPicker, { onSelect: handlePickerSelect, onCancel: handlePickerClose })) : (_jsx(CategoryPicker, { config: CATEGORY_CONFIG_MAP[pickerFlow], onSelect: handlePickerSelect, onCancel: handlePickerClose }))) })] }));
|
|
227
221
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface RunConfigModalProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
deck: string;
|
|
5
|
+
stake: string;
|
|
6
|
+
onChange: (deck: string, stake: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function RunConfigModal({ open, onClose, deck, stake, onChange, }: RunConfigModalProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { JimboModal } from "../ui/panel.js";
|
|
4
|
+
import { DECK_OPTIONS, STAKE_OPTIONS } from "../lib/data/constants.js";
|
|
5
|
+
import { DeckSprite } from "./DeckSprite.js";
|
|
6
|
+
import { StakeSprite } from "../ui/sprites.js";
|
|
7
|
+
import { JimboColorOption } from "../ui/tokens.js";
|
|
8
|
+
const DECK_DESCRIPTIONS = {
|
|
9
|
+
"Red": "+1 discard every round",
|
|
10
|
+
"Blue": "+1 hand every round",
|
|
11
|
+
"Yellow": "Start with extra $10",
|
|
12
|
+
"Green": "At end of each Round:\n$2 per remaining Hand,\n$1 per remaining Discard.\nEarn no Interest",
|
|
13
|
+
"Black": "+1 Joker slot\n-1 hand every round",
|
|
14
|
+
"Magic": "Start run with the\nCrystal Ball voucher\nand 2 copies of The Fool",
|
|
15
|
+
"Nebula": "Start run with the\nTelescope voucher\n-1 consumable slot",
|
|
16
|
+
"Ghost": "Spectral cards may\nappear in the shop,\nstart with a Hex card",
|
|
17
|
+
"Abandoned": "Start run with no\nFace Cards in your deck",
|
|
18
|
+
"Checkered": "Start run with\n26 Spades and\n26 Hearts in deck",
|
|
19
|
+
"Zodiac": "Start run with\nTarot Merchant,\nPlanet Merchant,\nand Overstock vouchers",
|
|
20
|
+
"Painted": "+2 hand size,\n-1 Joker slot",
|
|
21
|
+
"Anaglyph": "After defeating each\nBoss Blind, gain a\nDouble Tag",
|
|
22
|
+
"Plasma": "Balance Chips and\nMult when calculating\nscore for played hand.\nX2 base Blind size",
|
|
23
|
+
"Erratic": "All Ranks and Suits\nin deck are randomized",
|
|
24
|
+
};
|
|
25
|
+
const STAKE_DESCRIPTIONS = {
|
|
26
|
+
"White": "Base Difficulty",
|
|
27
|
+
"Red": "Small Blind gives\nno reward money\nApplies all previous Stakes",
|
|
28
|
+
"Green": "Required score scales\nfaster for each Ante\nApplies all previous Stakes",
|
|
29
|
+
"Black": "Shop can have Jokers\nwith Eternal\nApplies all previous Stakes",
|
|
30
|
+
"Blue": "-1 Discard\nApplies all previous Stakes",
|
|
31
|
+
"Purple": "Required score scales\nfaster for each Ante\nApplies all previous Stakes",
|
|
32
|
+
"Orange": "Shop can have Jokers\nwith Perishable\nApplies all previous Stakes",
|
|
33
|
+
"Gold": "-1 hand size\nShop can have Jokers\nwith Rental\nApplies all previous Stakes",
|
|
34
|
+
};
|
|
35
|
+
function formatTextWithColors(text) {
|
|
36
|
+
// Hacky basic coloration for Balatro text
|
|
37
|
+
const parts = text.split(/(\d+|Spades|Hearts|Clubs|Diamonds|\$[\d]+|Eternal|Perishable|Rental|Chips|Mult)/g);
|
|
38
|
+
return parts.map((part, i) => {
|
|
39
|
+
let color = JimboColorOption.WHITE;
|
|
40
|
+
if (/^\d+$/.test(part))
|
|
41
|
+
color = JimboColorOption.RED;
|
|
42
|
+
else if (part === 'Spades')
|
|
43
|
+
color = JimboColorOption.BLUE; // Spades are typically blue in high contrast
|
|
44
|
+
else if (part === 'Hearts')
|
|
45
|
+
color = JimboColorOption.RED;
|
|
46
|
+
else if (part === 'Clubs')
|
|
47
|
+
color = JimboColorOption.GREEN_TEXT;
|
|
48
|
+
else if (part === 'Diamonds')
|
|
49
|
+
color = JimboColorOption.ORANGE_TEXT;
|
|
50
|
+
else if (part.startsWith('$'))
|
|
51
|
+
color = JimboColorOption.GOLD_TEXT;
|
|
52
|
+
else if (['Eternal', 'Perishable', 'Rental'].includes(part))
|
|
53
|
+
color = JimboColorOption.GOLD_TEXT; // Should be specific colours
|
|
54
|
+
else if (part === 'Chips')
|
|
55
|
+
color = JimboColorOption.BLUE;
|
|
56
|
+
else if (part === 'Mult')
|
|
57
|
+
color = JimboColorOption.RED;
|
|
58
|
+
if (color !== JimboColorOption.WHITE) {
|
|
59
|
+
return _jsx("span", { style: { color }, children: part }, i);
|
|
60
|
+
}
|
|
61
|
+
return _jsx("span", { children: part }, i);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export function RunConfigModal({ open, onClose, deck, stake, onChange, }) {
|
|
65
|
+
const [activeDeck, setActiveDeck] = useState(deck);
|
|
66
|
+
const [activeStake, setActiveStake] = useState(stake);
|
|
67
|
+
// Sync state if props change when opened
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
if (open) {
|
|
70
|
+
setActiveDeck(deck);
|
|
71
|
+
setActiveStake(stake);
|
|
72
|
+
}
|
|
73
|
+
}, [open, deck, stake]);
|
|
74
|
+
if (!open)
|
|
75
|
+
return null;
|
|
76
|
+
const deckIdx = DECK_OPTIONS.indexOf(activeDeck) >= 0 ? DECK_OPTIONS.indexOf(activeDeck) : 0;
|
|
77
|
+
const stakeIdx = STAKE_OPTIONS.indexOf(activeStake) >= 0 ? STAKE_OPTIONS.indexOf(activeStake) : 0;
|
|
78
|
+
const nextDeck = () => setActiveDeck(DECK_OPTIONS[(deckIdx + 1) % DECK_OPTIONS.length]);
|
|
79
|
+
const prevDeck = () => setActiveDeck(DECK_OPTIONS[(deckIdx - 1 + DECK_OPTIONS.length) % DECK_OPTIONS.length]);
|
|
80
|
+
const nextStake = () => setActiveStake(STAKE_OPTIONS[(stakeIdx + 1) % STAKE_OPTIONS.length]);
|
|
81
|
+
const prevStake = () => setActiveStake(STAKE_OPTIONS[(stakeIdx - 1 + STAKE_OPTIONS.length) % STAKE_OPTIONS.length]);
|
|
82
|
+
const handleApply = () => {
|
|
83
|
+
onChange(activeDeck, activeStake);
|
|
84
|
+
onClose();
|
|
85
|
+
};
|
|
86
|
+
const CarouselButton = ({ onClick, children }) => (_jsx("button", { onClick: onClick, style: {
|
|
87
|
+
width: 32,
|
|
88
|
+
height: "100%",
|
|
89
|
+
borderRadius: 8,
|
|
90
|
+
background: JimboColorOption.RED,
|
|
91
|
+
border: `2px solid ${JimboColorOption.WHITE}`, // Should be dark edge with inner shadow but let's use standard red btn style
|
|
92
|
+
color: JimboColorOption.WHITE,
|
|
93
|
+
fontSize: 24,
|
|
94
|
+
fontFamily: "m6x11plus, monospace",
|
|
95
|
+
display: "flex",
|
|
96
|
+
alignItems: "center",
|
|
97
|
+
justifyContent: "center",
|
|
98
|
+
cursor: "pointer",
|
|
99
|
+
flexShrink: 0,
|
|
100
|
+
}, className: "j-btn j-btn--red" // piggyback on Jimbo button styles
|
|
101
|
+
, children: _jsx("div", { className: "j-btn__face", style: { padding: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: children }) }));
|
|
102
|
+
return (_jsx(JimboModal, { open: open, onClose: onClose, children: _jsxs("div", { style: {
|
|
103
|
+
width: 600,
|
|
104
|
+
maxWidth: "95vw",
|
|
105
|
+
background: JimboColorOption.TEAL_GREY, // A greenish-grey slate color
|
|
106
|
+
borderRadius: 16,
|
|
107
|
+
border: `3px solid ${JimboColorOption.BORDER_SILVER}`,
|
|
108
|
+
boxShadow: `inset 0 0 0 2px ${JimboColorOption.DARKEST}, 0 8px 16px rgba(0,0,0,0.5)`,
|
|
109
|
+
padding: "24px 20px",
|
|
110
|
+
display: "flex",
|
|
111
|
+
flexDirection: "column",
|
|
112
|
+
gap: 24,
|
|
113
|
+
position: "relative",
|
|
114
|
+
}, children: [_jsx("div", { style: {
|
|
115
|
+
position: "absolute",
|
|
116
|
+
top: -20,
|
|
117
|
+
left: 0,
|
|
118
|
+
right: 0,
|
|
119
|
+
display: "flex",
|
|
120
|
+
justifyContent: "center",
|
|
121
|
+
gap: 8,
|
|
122
|
+
}, children: _jsx("div", { className: "j-btn j-btn--red", style: { height: 36, pointerEvents: "none" }, children: _jsx("div", { className: "j-btn__face", style: { fontSize: 16, padding: "0 16px" }, children: "Seed Finder" }) }) }), _jsxs("div", { style: { display: "flex", height: 160, gap: 12 }, children: [_jsx(CarouselButton, { onClick: prevDeck, children: "<" }), _jsxs("div", { style: {
|
|
123
|
+
flex: 1,
|
|
124
|
+
background: JimboColorOption.DARK_GREY,
|
|
125
|
+
borderRadius: 12,
|
|
126
|
+
border: `2px solid ${JimboColorOption.PANEL_EDGE}`,
|
|
127
|
+
display: "flex",
|
|
128
|
+
alignItems: "center",
|
|
129
|
+
padding: "16px",
|
|
130
|
+
gap: 16,
|
|
131
|
+
}, children: [_jsx(DeckSprite, { deck: activeDeck, size: 100, style: { flexShrink: 0 } }), _jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center" }, children: [_jsxs("h2", { style: {
|
|
132
|
+
fontFamily: "m6x11plus, monospace",
|
|
133
|
+
fontSize: 28,
|
|
134
|
+
color: JimboColorOption.WHITE,
|
|
135
|
+
margin: "0 0 8px 0",
|
|
136
|
+
textShadow: `1px 1px 0 ${JimboColorOption.DARKEST}`,
|
|
137
|
+
}, children: [activeDeck, " Deck"] }), _jsx("div", { style: {
|
|
138
|
+
background: JimboColorOption.WHITE,
|
|
139
|
+
borderRadius: 8,
|
|
140
|
+
padding: "12px",
|
|
141
|
+
width: "100%",
|
|
142
|
+
minHeight: 80,
|
|
143
|
+
display: "flex",
|
|
144
|
+
flexDirection: "column",
|
|
145
|
+
alignItems: "center",
|
|
146
|
+
justifyContent: "center",
|
|
147
|
+
boxShadow: `inset 0 -2px 0 0 ${JimboColorOption.PANEL_EDGE}`,
|
|
148
|
+
}, children: _jsx("div", { style: {
|
|
149
|
+
fontFamily: "m6x11plus, monospace",
|
|
150
|
+
fontSize: 16,
|
|
151
|
+
color: JimboColorOption.DARKEST,
|
|
152
|
+
textAlign: "center",
|
|
153
|
+
whiteSpace: "pre-line",
|
|
154
|
+
lineHeight: 1.2,
|
|
155
|
+
}, children: formatTextWithColors(DECK_DESCRIPTIONS[activeDeck] || "Standard 52 card deck") }) })] }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4, paddingRight: 4 }, children: [_jsx("div", { style: { width: 8, height: 8, borderRadius: 4, background: JimboColorOption.GREY } }), _jsx("div", { style: { width: 8, height: 8, borderRadius: 4, background: JimboColorOption.GREY } }), _jsx("div", { style: { width: 8, height: 8, borderRadius: 4, background: JimboColorOption.GREEN } }), _jsx("div", { style: { width: 8, height: 8, borderRadius: 4, background: JimboColorOption.RED } }), _jsx("div", { style: { width: 8, height: 8, borderRadius: 4, background: JimboColorOption.WHITE } })] })] }), _jsx(CarouselButton, { onClick: nextDeck, children: ">" })] }), _jsxs("div", { style: { display: "flex", height: 120, gap: 12 }, children: [_jsx(CarouselButton, { onClick: prevStake, children: "<" }), _jsxs("div", { style: {
|
|
156
|
+
flex: 1,
|
|
157
|
+
background: JimboColorOption.DARK_GREY,
|
|
158
|
+
borderRadius: 12,
|
|
159
|
+
border: `2px solid ${JimboColorOption.PANEL_EDGE}`,
|
|
160
|
+
display: "flex",
|
|
161
|
+
alignItems: "center",
|
|
162
|
+
padding: "12px 16px",
|
|
163
|
+
gap: 16,
|
|
164
|
+
position: "relative",
|
|
165
|
+
}, children: [_jsx("div", { style: {
|
|
166
|
+
position: 'absolute',
|
|
167
|
+
left: -14, // Cut out effect text
|
|
168
|
+
top: '50%',
|
|
169
|
+
transform: 'translateY(-50%) rotate(-90deg)',
|
|
170
|
+
fontFamily: "m6x11plus, monospace",
|
|
171
|
+
fontSize: 16,
|
|
172
|
+
color: JimboColorOption.GREY,
|
|
173
|
+
}, children: "Stake" }), _jsx("div", { style: { paddingLeft: 20 }, children: _jsx(StakeSprite, { stake: activeStake, width: 64, style: { flexShrink: 0 } }) }), _jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center" }, children: [_jsxs("h2", { style: {
|
|
174
|
+
fontFamily: "m6x11plus, monospace",
|
|
175
|
+
fontSize: 22,
|
|
176
|
+
color: JimboColorOption.WHITE,
|
|
177
|
+
margin: "0 0 6px 0",
|
|
178
|
+
textShadow: `1px 1px 0 ${JimboColorOption.DARKEST}`,
|
|
179
|
+
}, children: [activeStake, " Stake"] }), _jsx("div", { style: {
|
|
180
|
+
background: JimboColorOption.WHITE,
|
|
181
|
+
borderRadius: 8,
|
|
182
|
+
padding: "8px 12px",
|
|
183
|
+
width: "100%",
|
|
184
|
+
minHeight: 60,
|
|
185
|
+
display: "flex",
|
|
186
|
+
flexDirection: "column",
|
|
187
|
+
alignItems: "center",
|
|
188
|
+
justifyContent: "center",
|
|
189
|
+
boxShadow: `inset 0 -2px 0 0 ${JimboColorOption.PANEL_EDGE}`,
|
|
190
|
+
}, children: _jsx("div", { style: {
|
|
191
|
+
fontFamily: "m6x11plus, monospace",
|
|
192
|
+
fontSize: 14,
|
|
193
|
+
color: JimboColorOption.DARKEST,
|
|
194
|
+
textAlign: "center",
|
|
195
|
+
whiteSpace: "pre-line",
|
|
196
|
+
lineHeight: 1.2,
|
|
197
|
+
}, children: formatTextWithColors(STAKE_DESCRIPTIONS[activeStake] || "Base Difficulty") }) })] })] }), _jsx(CarouselButton, { onClick: nextStake, children: ">" })] }), _jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, marginTop: 8 }, children: [_jsx("button", { onClick: handleApply, className: "j-btn j-btn--blue j-btn--lg", style: { width: "80%", height: 50, fontSize: 24, padding: 0 }, children: _jsx("div", { className: "j-btn__face", style: { display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: "APPLY" }) }), _jsx("button", { onClick: onClose, className: "j-btn j-btn--orange j-btn--md", style: { width: "100%", height: 40, fontSize: 18, padding: 0 }, children: _jsx("div", { className: "j-btn__face", style: { display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: "Back" }) })] })] }) }));
|
|
198
|
+
}
|
package/dist/ui/jimbo.css
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
:root {
|
|
20
20
|
/* Colors — eyedropped from Balatro's rendered shader output */
|
|
21
|
-
--j-red: #
|
|
21
|
+
--j-red: #fe5148;
|
|
22
22
|
--j-blue: #0093ff;
|
|
23
23
|
--j-green: #429f79;
|
|
24
24
|
--j-orange: #ff9800;
|
|
@@ -915,7 +915,7 @@
|
|
|
915
915
|
|
|
916
916
|
.j-modal {
|
|
917
917
|
width: 100%;
|
|
918
|
-
max-width:
|
|
918
|
+
max-width: 320px;
|
|
919
919
|
max-height: 90vh;
|
|
920
920
|
display: flex;
|
|
921
921
|
flex-direction: column;
|
|
@@ -1142,9 +1142,9 @@
|
|
|
1142
1142
|
}
|
|
1143
1143
|
|
|
1144
1144
|
/* ── App Shell ────────────────────────────────────────────────────────── */
|
|
1145
|
-
/* Mobile-first
|
|
1145
|
+
/* Mobile-first 320px layout container for ALL Jimbo UI screens.
|
|
1146
1146
|
* Supports container queries for responsive breakpoints:
|
|
1147
|
-
* compact ≤400px — iPhone SE, fixed
|
|
1147
|
+
* compact ≤400px — iPhone SE, fixed 568px height, NO scroll
|
|
1148
1148
|
* cozy 401-750px — MCP inline / wider phones, flexible height, scroll OK
|
|
1149
1149
|
* wide 751px+ — tablet/desktop, two-column layouts (future)
|
|
1150
1150
|
*
|
|
@@ -1154,10 +1154,10 @@
|
|
|
1154
1154
|
.j-app {
|
|
1155
1155
|
container-type: inline-size;
|
|
1156
1156
|
container-name: jimbo;
|
|
1157
|
-
width:
|
|
1158
|
-
max-width:
|
|
1159
|
-
height:
|
|
1160
|
-
max-height:
|
|
1157
|
+
width: 320px;
|
|
1158
|
+
max-width: 320px;
|
|
1159
|
+
height: 568px;
|
|
1160
|
+
max-height: 568px;
|
|
1161
1161
|
margin: 0 auto;
|
|
1162
1162
|
display: flex;
|
|
1163
1163
|
flex-direction: column;
|
package/dist/ui/jimboApp.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export interface JimboAppProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
3
|
children: React.ReactNode;
|
|
4
|
-
/** Unlock width/height for MCP inline or desktop use. Default: false (
|
|
4
|
+
/** Unlock width/height for MCP inline or desktop use. Default: false (320×568 locked). */
|
|
5
5
|
fluid?: boolean;
|
|
6
6
|
}
|
|
7
|
-
/** Standard mobile-first app shell.
|
|
7
|
+
/** Standard mobile-first app shell. 320px locked, or fluid for MCP/desktop. */
|
|
8
8
|
export declare function JimboApp({ children, fluid, className, ...props }: JimboAppProps): import("react/jsx-runtime").JSX.Element;
|
|
9
9
|
/** Scrollable content area inside JimboApp. Hidden scrollbar, snap-friendly. */
|
|
10
10
|
export declare function JimboAppScroll({ children, className, ...props }: Omit<JimboAppProps, 'fluid'>): import("react/jsx-runtime").JSX.Element;
|
package/dist/ui/jimboApp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
/** Standard mobile-first app shell.
|
|
3
|
+
/** Standard mobile-first app shell. 320px locked, or fluid for MCP/desktop. */
|
|
4
4
|
export function JimboApp({ children, fluid, className = '', ...props }) {
|
|
5
5
|
const classes = `j-app${fluid ? ' j-app--fluid' : ''} ${className}`.trim();
|
|
6
6
|
return (_jsx("div", { className: classes, ...props, children: children }));
|
|
@@ -80,7 +80,7 @@ function layoutOrbitalEllipse(items, Rx, Ry, startAngle, stepRad, mascotSizePx)
|
|
|
80
80
|
*/
|
|
81
81
|
export function RadialMenu({ items, showClosing, mascotSizePx, orbitRadiusX, orbitRadiusY, mascotTranslateY, currentMenu, onItemClick, onBack, breadcrumb, showPageControls = false, onPagePrev, onPageNext, }) {
|
|
82
82
|
const rootRef = useRef(null);
|
|
83
|
-
const [containerW, setContainerW] = useState(
|
|
83
|
+
const [containerW, setContainerW] = useState(320);
|
|
84
84
|
useLayoutEffect(() => {
|
|
85
85
|
const el = rootRef.current;
|
|
86
86
|
if (!el)
|
|
@@ -21,7 +21,7 @@ function readGeometry() {
|
|
|
21
21
|
return { baseRadius: 66, keyboardHeight: 0 };
|
|
22
22
|
}
|
|
23
23
|
const w = window.innerWidth;
|
|
24
|
-
const baseRadius = w <
|
|
24
|
+
const baseRadius = w < 320 ? 58 : 66;
|
|
25
25
|
const vv = window.visualViewport;
|
|
26
26
|
let keyboardHeight = 0;
|
|
27
27
|
if (vv) {
|
package/dist/ui/showcase.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface ShowcaseProps {
|
|
|
32
32
|
onFilterClick?: (filter: ShowcaseFilter, index: number) => void;
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* Landing/showcase screen —
|
|
35
|
+
* Landing/showcase screen — 320×568, NO SCROLL.
|
|
36
36
|
* Every pixel accounted for. No flex stretching. No gaps.
|
|
37
37
|
*/
|
|
38
38
|
export declare function Showcase({ title, subtitle, hotFilters, recentFinds, mcpInfo, onNewSearch, onBrowseFilters, onFilterClick, }: ShowcaseProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/ui/showcase.js
CHANGED
|
@@ -8,7 +8,7 @@ import { JimboBalatroFooter } from './footer.js';
|
|
|
8
8
|
import { JimboSectionHeader } from './jimboSectionHeader.js';
|
|
9
9
|
import { JimboInfoCard, JimboInfoCardBody, JimboInfoCardTitle, JimboInfoCardSub, JimboInfoCardAside } from './jimboInfoCard.js';
|
|
10
10
|
/**
|
|
11
|
-
* Landing/showcase screen —
|
|
11
|
+
* Landing/showcase screen — 320×568, NO SCROLL.
|
|
12
12
|
* Every pixel accounted for. No flex stretching. No gaps.
|
|
13
13
|
*/
|
|
14
14
|
export function Showcase({ title = 'Balatro', subtitle = 'Seed Curator', hotFilters = [], recentFinds = [], mcpInfo, onNewSearch, onBrowseFilters, onFilterClick, }) {
|