jaml-ui 0.3.0 → 0.4.0
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/README.md +1 -3
- package/dist/components/AnalyzerExplorer.d.ts +44 -0
- package/dist/components/AnalyzerExplorer.js +451 -0
- package/dist/components/JamlIde.d.ts +3 -1
- package/dist/components/JamlIde.js +2 -2
- package/dist/components/JamlIdeToolbar.d.ts +3 -1
- package/dist/components/JamlIdeToolbar.js +30 -21
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/motely.d.ts +1 -0
- package/dist/motely.js +1 -0
- package/dist/motelyDisplay.d.ts +629 -0
- package/dist/motelyDisplay.js +187 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# jaml-ui
|
|
2
2
|
|
|
3
|
-
Balatro
|
|
4
|
-
|
|
5
|
-
`jaml-ui` is the shared UI layer for Balatro/JAML surfaces: low-level renderers, asset helpers, visual JAML previews, and a lightweight browser-first JAML IDE shell.
|
|
3
|
+
React components and utilities for Balatro/JAML. Pair with **`motely-wasm`** when you need the engine (peer). Update both in consumers with normal **`pnpm update`** / semver like any other deps.
|
|
6
4
|
|
|
7
5
|
## Package shape
|
|
8
6
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type AnalyzerShopItem } from "./GameCard.js";
|
|
2
|
+
export interface AnalyzerBadge {
|
|
3
|
+
label: string;
|
|
4
|
+
tone?: "default" | "accent" | "muted";
|
|
5
|
+
}
|
|
6
|
+
export interface AnalyzerFact {
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AnalyzerItem extends AnalyzerShopItem {
|
|
11
|
+
desired?: boolean;
|
|
12
|
+
badges?: AnalyzerBadge[];
|
|
13
|
+
detail?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface AnalyzerAnteView {
|
|
16
|
+
ante: number;
|
|
17
|
+
boss?: string;
|
|
18
|
+
voucher?: string;
|
|
19
|
+
smallBlindTag?: string;
|
|
20
|
+
bigBlindTag?: string;
|
|
21
|
+
packs?: string[];
|
|
22
|
+
shop?: AnalyzerItem[];
|
|
23
|
+
facts?: AnalyzerFact[];
|
|
24
|
+
}
|
|
25
|
+
export interface AnalyzerHighlight {
|
|
26
|
+
id: string;
|
|
27
|
+
ante: number;
|
|
28
|
+
title: string;
|
|
29
|
+
subtitle?: string;
|
|
30
|
+
desired?: boolean;
|
|
31
|
+
item?: AnalyzerItem;
|
|
32
|
+
boss?: string;
|
|
33
|
+
voucher?: string;
|
|
34
|
+
tag?: string;
|
|
35
|
+
badges?: AnalyzerBadge[];
|
|
36
|
+
}
|
|
37
|
+
export interface AnalyzerExplorerProps {
|
|
38
|
+
antes: AnalyzerAnteView[];
|
|
39
|
+
highlights?: AnalyzerHighlight[];
|
|
40
|
+
visibleAntes?: number;
|
|
41
|
+
totalAntes?: number;
|
|
42
|
+
className?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare function AnalyzerExplorer({ antes, highlights, visibleAntes, totalAntes, className, }: AnalyzerExplorerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { JamlBoss, JamlGameCard, JamlTag, JamlVoucher, resolveAnalyzerShopItem, } from "./GameCard.js";
|
|
5
|
+
export function AnalyzerExplorer({ antes, highlights = [], visibleAntes, totalAntes, className = "", }) {
|
|
6
|
+
const [currentAnte, setCurrentAnte] = useState(antes[0]?.ante ?? 0);
|
|
7
|
+
const scrollRef = useRef(null);
|
|
8
|
+
const anteRefs = useRef(new Map());
|
|
9
|
+
const highlightRefs = useRef(new Map());
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
setCurrentAnte(antes[0]?.ante ?? 0);
|
|
12
|
+
}, [antes]);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const root = scrollRef.current;
|
|
15
|
+
if (!root) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const observer = new IntersectionObserver((entries) => {
|
|
19
|
+
const mostVisibleEntry = entries
|
|
20
|
+
.filter((entry) => entry.isIntersecting)
|
|
21
|
+
.sort((left, right) => right.intersectionRatio - left.intersectionRatio)[0];
|
|
22
|
+
if (!mostVisibleEntry) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const ante = Number(mostVisibleEntry.target.dataset.ante);
|
|
26
|
+
if (!Number.isNaN(ante)) {
|
|
27
|
+
setCurrentAnte(ante);
|
|
28
|
+
}
|
|
29
|
+
}, {
|
|
30
|
+
root,
|
|
31
|
+
threshold: [0.45, 0.72, 0.9],
|
|
32
|
+
});
|
|
33
|
+
for (const [, element] of anteRefs.current) {
|
|
34
|
+
observer.observe(element);
|
|
35
|
+
}
|
|
36
|
+
return () => observer.disconnect();
|
|
37
|
+
}, [antes]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const activeHighlight = highlights.find((highlight) => highlight.ante === currentAnte);
|
|
40
|
+
if (!activeHighlight) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const element = highlightRefs.current.get(activeHighlight.id);
|
|
44
|
+
element?.scrollIntoView({
|
|
45
|
+
behavior: "smooth",
|
|
46
|
+
inline: "center",
|
|
47
|
+
block: "nearest",
|
|
48
|
+
});
|
|
49
|
+
}, [currentAnte, highlights]);
|
|
50
|
+
const scrollToAnte = useCallback((ante) => {
|
|
51
|
+
anteRefs.current.get(ante)?.scrollIntoView({
|
|
52
|
+
behavior: "smooth",
|
|
53
|
+
block: "start",
|
|
54
|
+
});
|
|
55
|
+
}, []);
|
|
56
|
+
const currentAnteIndex = antes.findIndex((ante) => ante.ante === currentAnte);
|
|
57
|
+
const previousAnte = currentAnteIndex > 0 ? antes[currentAnteIndex - 1]?.ante ?? null : null;
|
|
58
|
+
const nextAnte = currentAnteIndex >= 0 && currentAnteIndex < antes.length - 1 ? antes[currentAnteIndex + 1]?.ante ?? null : null;
|
|
59
|
+
const shownAntes = visibleAntes ?? antes.length;
|
|
60
|
+
const availableAntes = totalAntes ?? shownAntes;
|
|
61
|
+
return (_jsxs("div", { className: className, style: styles.root, children: [highlights.length > 0 ? (_jsxs("section", { style: styles.highlightSection, children: [_jsxs("div", { style: styles.highlightHeader, children: [_jsx("span", { style: styles.highlightTitle, children: "Highlights" }), _jsx("span", { style: styles.highlightSubtitle, children: "Swipe, tap, jump" })] }), _jsx("div", { style: styles.highlightRail, children: highlights.map((highlight) => {
|
|
62
|
+
const isActive = highlight.ante === currentAnte;
|
|
63
|
+
return (_jsxs("button", { ref: (element) => {
|
|
64
|
+
if (element) {
|
|
65
|
+
highlightRefs.current.set(highlight.id, element);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
highlightRefs.current.delete(highlight.id);
|
|
69
|
+
}
|
|
70
|
+
}, type: "button", onClick: () => scrollToAnte(highlight.ante), style: isActive ? styles.highlightCardActive : styles.highlightCard, children: [_jsx("div", { style: styles.highlightVisual, children: renderHighlightVisual(highlight) }), _jsxs("div", { style: styles.highlightMeta, children: [_jsxs("span", { style: styles.highlightAnte, children: ["Ante ", highlight.ante] }), _jsx("span", { style: styles.highlightLabel, children: highlight.title }), highlight.subtitle ? (_jsx("span", { style: styles.highlightDescription, children: highlight.subtitle })) : null, _jsx(BadgeRow, { badges: highlight.badges, desired: highlight.desired })] })] }, highlight.id));
|
|
71
|
+
}) })] })) : null, _jsxs("div", { style: styles.navBar, children: [_jsx("button", { type: "button", onClick: () => previousAnte !== null && scrollToAnte(previousAnte), disabled: previousAnte === null, style: {
|
|
72
|
+
...styles.navButton,
|
|
73
|
+
opacity: previousAnte !== null ? 1 : 0.25,
|
|
74
|
+
}, children: "\u25B2" }), _jsxs("div", { style: styles.navLabel, children: ["Ante ", currentAnte, _jsxs("span", { style: styles.navSubLabel, children: ["of ", shownAntes, availableAntes > shownAntes ? ` / ${availableAntes}` : ""] })] }), _jsx("button", { type: "button", onClick: () => nextAnte !== null && scrollToAnte(nextAnte), disabled: nextAnte === null, style: {
|
|
75
|
+
...styles.navButton,
|
|
76
|
+
opacity: nextAnte !== null ? 1 : 0.25,
|
|
77
|
+
}, children: "\u25BC" })] }), _jsx("div", { ref: scrollRef, style: styles.scrollRegion, children: antes.map((ante) => (_jsx("div", { "data-ante": ante.ante, ref: (element) => {
|
|
78
|
+
if (element) {
|
|
79
|
+
anteRefs.current.set(ante.ante, element);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
anteRefs.current.delete(ante.ante);
|
|
83
|
+
}
|
|
84
|
+
}, style: styles.antePage, children: _jsx(AnteSection, { ante: ante }) }, ante.ante))) })] }));
|
|
85
|
+
}
|
|
86
|
+
function AnteSection({ ante }) {
|
|
87
|
+
return (_jsxs("section", { style: styles.anteSection, children: [_jsxs("div", { style: styles.anteHeader, children: [_jsxs("span", { style: styles.anteHeading, children: ["Ante ", ante.ante] }), ante.boss ? (_jsxs("div", { style: styles.bossRow, children: [_jsx(JamlBoss, { bossName: ante.boss, scale: 0.62 }), _jsx("span", { style: styles.bossName, children: ante.boss })] })) : null] }), ante.smallBlindTag || ante.bigBlindTag ? (_jsxs(AnalyzerRow, { label: "Tags", children: [ante.smallBlindTag ? (_jsx(CompactCard, { label: "Small", visual: _jsx(JamlTag, { tagName: ante.smallBlindTag, scale: 0.58, hoverTilt: true }), text: ante.smallBlindTag })) : null, ante.bigBlindTag ? (_jsx(CompactCard, { label: "Big", visual: _jsx(JamlTag, { tagName: ante.bigBlindTag, scale: 0.58, hoverTilt: true }), text: ante.bigBlindTag })) : null] })) : null, ante.voucher ? (_jsx(AnalyzerRow, { label: "Voucher", children: _jsx(CompactCard, { visual: _jsx(JamlVoucher, { voucherName: ante.voucher, scale: 0.58, hoverTilt: true }), text: ante.voucher }) })) : null, ante.shop && ante.shop.length > 0 ? (_jsx(AnalyzerRow, { label: "Shop", dense: true, children: ante.shop.map((item) => (_jsx(ResolvedItemCard, { item: item }, `${ante.ante}-${item.id}-${item.name}`))) })) : null, ante.packs && ante.packs.length > 0 ? (_jsx(AnalyzerRow, { label: "Packs", children: ante.packs.map((pack) => (_jsx("div", { style: styles.packChip, children: pack }, `${ante.ante}-${pack}`))) })) : null, ante.facts && ante.facts.length > 0 ? (_jsx(AnalyzerRow, { label: "Facts", children: ante.facts.map((fact) => (_jsxs("div", { style: styles.factCard, children: [_jsx("span", { style: styles.factLabel, children: fact.label }), _jsx("span", { style: styles.factValue, children: fact.value })] }, `${ante.ante}-${fact.label}-${fact.value}`))) })) : null] }));
|
|
88
|
+
}
|
|
89
|
+
function AnalyzerRow({ label, children, dense = false, }) {
|
|
90
|
+
return (_jsxs("div", { style: styles.row, children: [_jsx("div", { style: styles.rowLabel, children: label }), _jsx("div", { style: dense ? styles.denseGrid : styles.cardFlow, children: children })] }));
|
|
91
|
+
}
|
|
92
|
+
function CompactCard({ label, visual, text, }) {
|
|
93
|
+
return (_jsxs("div", { style: styles.compactCard, children: [label ? _jsx("span", { style: styles.compactLabel, children: label }) : null, visual, _jsx("span", { style: styles.itemText, children: text })] }));
|
|
94
|
+
}
|
|
95
|
+
function ResolvedItemCard({ item }) {
|
|
96
|
+
const resolved = resolveAnalyzerShopItem(item, 0.58);
|
|
97
|
+
const wrapperStyle = item.desired ? styles.itemCardDesired : styles.itemCard;
|
|
98
|
+
if (resolved.kind === "joker" || resolved.kind === "consumable" || resolved.kind === "playing") {
|
|
99
|
+
return (_jsxs("div", { style: wrapperStyle, children: [_jsx(JamlGameCard, { card: resolved.card, type: resolved.type, hoverTilt: true }), _jsx("span", { style: styles.itemText, children: item.name }), _jsx(BadgeRow, { badges: item.badges, desired: item.desired }), item.detail ? _jsx("span", { style: styles.itemDetail, children: item.detail }) : null] }));
|
|
100
|
+
}
|
|
101
|
+
if (resolved.kind === "voucher") {
|
|
102
|
+
return (_jsxs("div", { style: wrapperStyle, children: [_jsx(JamlVoucher, { voucherName: resolved.voucherName, scale: 0.58, hoverTilt: true }), _jsx("span", { style: styles.itemText, children: item.name }), _jsx(BadgeRow, { badges: item.badges, desired: item.desired }), item.detail ? _jsx("span", { style: styles.itemDetail, children: item.detail }) : null] }));
|
|
103
|
+
}
|
|
104
|
+
return (_jsxs("div", { style: wrapperStyle, children: [_jsx("div", { style: styles.packChip, children: item.name }), _jsx(BadgeRow, { badges: item.badges, desired: item.desired }), item.detail ? _jsx("span", { style: styles.itemDetail, children: item.detail }) : null] }));
|
|
105
|
+
}
|
|
106
|
+
function BadgeRow({ badges, desired = false }) {
|
|
107
|
+
const combinedBadges = desired
|
|
108
|
+
? [{ label: "desired", tone: "accent" }, ...(badges ?? [])]
|
|
109
|
+
: (badges ?? []);
|
|
110
|
+
if (combinedBadges.length === 0) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
return (_jsx("div", { style: styles.badgeRow, children: combinedBadges.map((badge) => {
|
|
114
|
+
const badgeStyle = badge.tone === "accent"
|
|
115
|
+
? styles.badgeAccent
|
|
116
|
+
: badge.tone === "muted"
|
|
117
|
+
? styles.badgeMuted
|
|
118
|
+
: styles.badge;
|
|
119
|
+
return (_jsx("span", { style: badgeStyle, children: badge.label }, `${badge.label}-${badge.tone ?? "default"}`));
|
|
120
|
+
}) }));
|
|
121
|
+
}
|
|
122
|
+
function renderHighlightVisual(highlight) {
|
|
123
|
+
if (highlight.item) {
|
|
124
|
+
return _jsx(ResolvedItemCard, { item: highlight.item });
|
|
125
|
+
}
|
|
126
|
+
if (highlight.boss) {
|
|
127
|
+
return _jsx(JamlBoss, { bossName: highlight.boss, scale: 0.92, hoverTilt: true });
|
|
128
|
+
}
|
|
129
|
+
if (highlight.voucher) {
|
|
130
|
+
return _jsx(JamlVoucher, { voucherName: highlight.voucher, scale: 0.92, hoverTilt: true });
|
|
131
|
+
}
|
|
132
|
+
if (highlight.tag) {
|
|
133
|
+
return _jsx(JamlTag, { tagName: highlight.tag, scale: 0.92, hoverTilt: true });
|
|
134
|
+
}
|
|
135
|
+
return _jsx("div", { style: styles.packChip, children: highlight.title });
|
|
136
|
+
}
|
|
137
|
+
const styles = {
|
|
138
|
+
root: {
|
|
139
|
+
display: "flex",
|
|
140
|
+
flexDirection: "column",
|
|
141
|
+
height: "100%",
|
|
142
|
+
minHeight: 0,
|
|
143
|
+
},
|
|
144
|
+
highlightSection: {
|
|
145
|
+
padding: "10px 16px 8px",
|
|
146
|
+
borderBottom: "1px solid #1a1a34",
|
|
147
|
+
background: "#0f0f22",
|
|
148
|
+
},
|
|
149
|
+
highlightHeader: {
|
|
150
|
+
display: "flex",
|
|
151
|
+
alignItems: "center",
|
|
152
|
+
justifyContent: "space-between",
|
|
153
|
+
gap: 12,
|
|
154
|
+
marginBottom: 8,
|
|
155
|
+
},
|
|
156
|
+
highlightTitle: {
|
|
157
|
+
fontSize: 11,
|
|
158
|
+
color: "#6f6fa1",
|
|
159
|
+
textTransform: "uppercase",
|
|
160
|
+
letterSpacing: "0.08em",
|
|
161
|
+
},
|
|
162
|
+
highlightSubtitle: {
|
|
163
|
+
fontSize: 11,
|
|
164
|
+
color: "#6f6fa1",
|
|
165
|
+
},
|
|
166
|
+
highlightRail: {
|
|
167
|
+
display: "flex",
|
|
168
|
+
gap: 10,
|
|
169
|
+
overflowX: "auto",
|
|
170
|
+
paddingBottom: 4,
|
|
171
|
+
scrollSnapType: "x mandatory",
|
|
172
|
+
},
|
|
173
|
+
highlightCard: {
|
|
174
|
+
minWidth: 150,
|
|
175
|
+
maxWidth: 150,
|
|
176
|
+
display: "flex",
|
|
177
|
+
flexDirection: "column",
|
|
178
|
+
gap: 6,
|
|
179
|
+
padding: 8,
|
|
180
|
+
borderRadius: 12,
|
|
181
|
+
border: "1px solid #2a2a55",
|
|
182
|
+
background: "#131326",
|
|
183
|
+
scrollSnapAlign: "center",
|
|
184
|
+
cursor: "pointer",
|
|
185
|
+
},
|
|
186
|
+
highlightCardActive: {
|
|
187
|
+
minWidth: 150,
|
|
188
|
+
maxWidth: 150,
|
|
189
|
+
display: "flex",
|
|
190
|
+
flexDirection: "column",
|
|
191
|
+
gap: 6,
|
|
192
|
+
padding: 8,
|
|
193
|
+
borderRadius: 12,
|
|
194
|
+
border: "1px solid rgba(245,200,66,0.45)",
|
|
195
|
+
background: "rgba(245,200,66,0.08)",
|
|
196
|
+
scrollSnapAlign: "center",
|
|
197
|
+
cursor: "pointer",
|
|
198
|
+
},
|
|
199
|
+
highlightVisual: {
|
|
200
|
+
display: "flex",
|
|
201
|
+
justifyContent: "center",
|
|
202
|
+
alignItems: "flex-start",
|
|
203
|
+
minHeight: 88,
|
|
204
|
+
},
|
|
205
|
+
highlightMeta: {
|
|
206
|
+
display: "flex",
|
|
207
|
+
flexDirection: "column",
|
|
208
|
+
gap: 3,
|
|
209
|
+
alignItems: "flex-start",
|
|
210
|
+
},
|
|
211
|
+
highlightAnte: {
|
|
212
|
+
fontSize: 10,
|
|
213
|
+
color: "#a855f7",
|
|
214
|
+
fontWeight: 700,
|
|
215
|
+
textTransform: "uppercase",
|
|
216
|
+
letterSpacing: "0.08em",
|
|
217
|
+
},
|
|
218
|
+
highlightLabel: {
|
|
219
|
+
fontSize: 12,
|
|
220
|
+
color: "#ececff",
|
|
221
|
+
fontWeight: 700,
|
|
222
|
+
lineHeight: 1.2,
|
|
223
|
+
textAlign: "left",
|
|
224
|
+
},
|
|
225
|
+
highlightDescription: {
|
|
226
|
+
fontSize: 11,
|
|
227
|
+
color: "#8e8eb6",
|
|
228
|
+
lineHeight: 1.2,
|
|
229
|
+
textAlign: "left",
|
|
230
|
+
},
|
|
231
|
+
navBar: {
|
|
232
|
+
display: "flex",
|
|
233
|
+
alignItems: "center",
|
|
234
|
+
justifyContent: "center",
|
|
235
|
+
gap: 12,
|
|
236
|
+
padding: "8px 16px",
|
|
237
|
+
background: "#0f0f22",
|
|
238
|
+
borderBottom: "1px solid #1a1a34",
|
|
239
|
+
},
|
|
240
|
+
navButton: {
|
|
241
|
+
background: "none",
|
|
242
|
+
border: "1px solid #2a2a55",
|
|
243
|
+
borderRadius: 6,
|
|
244
|
+
color: "#9898c0",
|
|
245
|
+
fontSize: 14,
|
|
246
|
+
padding: "4px 10px",
|
|
247
|
+
cursor: "pointer",
|
|
248
|
+
},
|
|
249
|
+
navLabel: {
|
|
250
|
+
fontSize: 12,
|
|
251
|
+
fontWeight: 700,
|
|
252
|
+
color: "#a855f7",
|
|
253
|
+
textTransform: "uppercase",
|
|
254
|
+
letterSpacing: "0.08em",
|
|
255
|
+
minWidth: 130,
|
|
256
|
+
textAlign: "center",
|
|
257
|
+
},
|
|
258
|
+
navSubLabel: {
|
|
259
|
+
color: "#5a5a88",
|
|
260
|
+
fontWeight: 500,
|
|
261
|
+
textTransform: "none",
|
|
262
|
+
letterSpacing: "normal",
|
|
263
|
+
fontSize: 11,
|
|
264
|
+
marginLeft: 4,
|
|
265
|
+
},
|
|
266
|
+
scrollRegion: {
|
|
267
|
+
flex: 1,
|
|
268
|
+
overflowY: "auto",
|
|
269
|
+
overflowX: "hidden",
|
|
270
|
+
scrollSnapType: "y mandatory",
|
|
271
|
+
scrollBehavior: "smooth",
|
|
272
|
+
},
|
|
273
|
+
antePage: {
|
|
274
|
+
scrollSnapAlign: "start",
|
|
275
|
+
scrollSnapStop: "always",
|
|
276
|
+
minHeight: "100%",
|
|
277
|
+
boxSizing: "border-box",
|
|
278
|
+
paddingBottom: 16,
|
|
279
|
+
borderBottom: "1px solid #1a1a34",
|
|
280
|
+
},
|
|
281
|
+
anteSection: {
|
|
282
|
+
paddingBottom: 8,
|
|
283
|
+
},
|
|
284
|
+
anteHeader: {
|
|
285
|
+
display: "flex",
|
|
286
|
+
alignItems: "center",
|
|
287
|
+
gap: 12,
|
|
288
|
+
padding: "8px 16px",
|
|
289
|
+
},
|
|
290
|
+
anteHeading: {
|
|
291
|
+
fontSize: 12,
|
|
292
|
+
fontWeight: 700,
|
|
293
|
+
color: "#a855f7",
|
|
294
|
+
textTransform: "uppercase",
|
|
295
|
+
letterSpacing: "0.1em",
|
|
296
|
+
},
|
|
297
|
+
bossRow: {
|
|
298
|
+
display: "flex",
|
|
299
|
+
alignItems: "center",
|
|
300
|
+
gap: 6,
|
|
301
|
+
},
|
|
302
|
+
bossName: {
|
|
303
|
+
fontSize: 13,
|
|
304
|
+
color: "#e84040",
|
|
305
|
+
fontWeight: 600,
|
|
306
|
+
},
|
|
307
|
+
row: {
|
|
308
|
+
padding: "4px 16px 8px",
|
|
309
|
+
},
|
|
310
|
+
rowLabel: {
|
|
311
|
+
fontSize: 10,
|
|
312
|
+
color: "#5a5a88",
|
|
313
|
+
textTransform: "uppercase",
|
|
314
|
+
letterSpacing: "0.07em",
|
|
315
|
+
marginBottom: 6,
|
|
316
|
+
},
|
|
317
|
+
cardFlow: {
|
|
318
|
+
display: "flex",
|
|
319
|
+
flexWrap: "wrap",
|
|
320
|
+
gap: 8,
|
|
321
|
+
alignItems: "flex-start",
|
|
322
|
+
},
|
|
323
|
+
denseGrid: {
|
|
324
|
+
display: "grid",
|
|
325
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(82px, 1fr))",
|
|
326
|
+
gap: 8,
|
|
327
|
+
alignItems: "start",
|
|
328
|
+
},
|
|
329
|
+
compactCard: {
|
|
330
|
+
display: "flex",
|
|
331
|
+
flexDirection: "column",
|
|
332
|
+
alignItems: "center",
|
|
333
|
+
gap: 4,
|
|
334
|
+
minWidth: 62,
|
|
335
|
+
},
|
|
336
|
+
compactLabel: {
|
|
337
|
+
padding: "2px 6px",
|
|
338
|
+
borderRadius: 999,
|
|
339
|
+
background: "#18182e",
|
|
340
|
+
color: "#7f7fa7",
|
|
341
|
+
border: "1px solid #2a2a55",
|
|
342
|
+
fontSize: 9,
|
|
343
|
+
fontWeight: 700,
|
|
344
|
+
textTransform: "uppercase",
|
|
345
|
+
letterSpacing: "0.05em",
|
|
346
|
+
},
|
|
347
|
+
itemCard: {
|
|
348
|
+
display: "flex",
|
|
349
|
+
flexDirection: "column",
|
|
350
|
+
alignItems: "center",
|
|
351
|
+
gap: 4,
|
|
352
|
+
width: "100%",
|
|
353
|
+
minWidth: 0,
|
|
354
|
+
},
|
|
355
|
+
itemCardDesired: {
|
|
356
|
+
display: "flex",
|
|
357
|
+
flexDirection: "column",
|
|
358
|
+
alignItems: "center",
|
|
359
|
+
gap: 4,
|
|
360
|
+
width: "100%",
|
|
361
|
+
minWidth: 0,
|
|
362
|
+
padding: "4px 4px 6px",
|
|
363
|
+
borderRadius: 10,
|
|
364
|
+
border: "1px solid rgba(245,200,66,0.4)",
|
|
365
|
+
background: "rgba(245,200,66,0.08)",
|
|
366
|
+
},
|
|
367
|
+
itemText: {
|
|
368
|
+
fontSize: 10,
|
|
369
|
+
color: "#8e8eb6",
|
|
370
|
+
textAlign: "center",
|
|
371
|
+
lineHeight: 1.2,
|
|
372
|
+
maxWidth: 84,
|
|
373
|
+
overflow: "hidden",
|
|
374
|
+
textOverflow: "ellipsis",
|
|
375
|
+
whiteSpace: "nowrap",
|
|
376
|
+
},
|
|
377
|
+
itemDetail: {
|
|
378
|
+
fontSize: 10,
|
|
379
|
+
color: "#d8d8ea",
|
|
380
|
+
textAlign: "center",
|
|
381
|
+
lineHeight: 1.2,
|
|
382
|
+
},
|
|
383
|
+
badgeRow: {
|
|
384
|
+
display: "flex",
|
|
385
|
+
flexWrap: "wrap",
|
|
386
|
+
gap: 4,
|
|
387
|
+
justifyContent: "center",
|
|
388
|
+
},
|
|
389
|
+
badge: {
|
|
390
|
+
padding: "2px 6px",
|
|
391
|
+
borderRadius: 999,
|
|
392
|
+
background: "#202043",
|
|
393
|
+
color: "#c7c7ef",
|
|
394
|
+
border: "1px solid #35356d",
|
|
395
|
+
fontSize: 9,
|
|
396
|
+
fontWeight: 700,
|
|
397
|
+
textTransform: "uppercase",
|
|
398
|
+
letterSpacing: "0.05em",
|
|
399
|
+
},
|
|
400
|
+
badgeAccent: {
|
|
401
|
+
padding: "2px 6px",
|
|
402
|
+
borderRadius: 999,
|
|
403
|
+
background: "rgba(245,200,66,0.2)",
|
|
404
|
+
color: "#f5c842",
|
|
405
|
+
border: "1px solid rgba(245,200,66,0.35)",
|
|
406
|
+
fontSize: 9,
|
|
407
|
+
fontWeight: 700,
|
|
408
|
+
textTransform: "uppercase",
|
|
409
|
+
letterSpacing: "0.05em",
|
|
410
|
+
},
|
|
411
|
+
badgeMuted: {
|
|
412
|
+
padding: "2px 6px",
|
|
413
|
+
borderRadius: 999,
|
|
414
|
+
background: "#18182e",
|
|
415
|
+
color: "#7f7fa7",
|
|
416
|
+
border: "1px solid #2a2a55",
|
|
417
|
+
fontSize: 9,
|
|
418
|
+
fontWeight: 700,
|
|
419
|
+
textTransform: "uppercase",
|
|
420
|
+
letterSpacing: "0.05em",
|
|
421
|
+
},
|
|
422
|
+
packChip: {
|
|
423
|
+
fontSize: 12,
|
|
424
|
+
color: "#5a5a88",
|
|
425
|
+
background: "#131326",
|
|
426
|
+
border: "1px solid #2a2a55",
|
|
427
|
+
borderRadius: 6,
|
|
428
|
+
padding: "4px 8px",
|
|
429
|
+
},
|
|
430
|
+
factCard: {
|
|
431
|
+
display: "flex",
|
|
432
|
+
flexDirection: "column",
|
|
433
|
+
gap: 2,
|
|
434
|
+
minWidth: 110,
|
|
435
|
+
padding: "8px 10px",
|
|
436
|
+
borderRadius: 10,
|
|
437
|
+
background: "#131326",
|
|
438
|
+
border: "1px solid #2a2a55",
|
|
439
|
+
},
|
|
440
|
+
factLabel: {
|
|
441
|
+
fontSize: 10,
|
|
442
|
+
color: "#7f7fa7",
|
|
443
|
+
textTransform: "uppercase",
|
|
444
|
+
letterSpacing: "0.07em",
|
|
445
|
+
},
|
|
446
|
+
factValue: {
|
|
447
|
+
fontSize: 12,
|
|
448
|
+
color: "#ececff",
|
|
449
|
+
fontWeight: 700,
|
|
450
|
+
},
|
|
451
|
+
};
|
|
@@ -13,5 +13,7 @@ export interface JamlIdeProps {
|
|
|
13
13
|
title?: string;
|
|
14
14
|
actions?: React.ReactNode;
|
|
15
15
|
codePlaceholder?: string;
|
|
16
|
+
onSearch?: () => void;
|
|
17
|
+
isSearching?: boolean;
|
|
16
18
|
}
|
|
17
|
-
export declare function JamlIde({ jaml, onChange, defaultMode, searchResults, className, title, actions, codePlaceholder, }: JamlIdeProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function JamlIde({ jaml, onChange, defaultMode, searchResults, className, title, actions, codePlaceholder, onSearch, isSearching, }: JamlIdeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -25,7 +25,7 @@ function ResultsView({ results }) {
|
|
|
25
25
|
padding: "10px 12px",
|
|
26
26
|
}, children: [_jsx("div", { style: { fontWeight: 700, letterSpacing: 0.4 }, children: result.seed }), _jsx("div", { style: { fontSize: 12, opacity: 0.7 }, children: result.score !== undefined ? result.score : "-" })] }, `${result.seed}-${index}`))) }));
|
|
27
27
|
}
|
|
28
|
-
export function JamlIde({ jaml, onChange, defaultMode = "code", searchResults = [], className = "", title = "JAML IDE", actions, codePlaceholder = "Enter JAML...", }) {
|
|
28
|
+
export function JamlIde({ jaml, onChange, defaultMode = "code", searchResults = [], className = "", title = "JAML IDE", actions, codePlaceholder = "Enter JAML...", onSearch, isSearching = false, }) {
|
|
29
29
|
const [mode, setMode] = useState(defaultMode);
|
|
30
30
|
const results = useMemo(() => searchResults, [searchResults]);
|
|
31
31
|
return (_jsxs("div", { className: className, style: {
|
|
@@ -45,7 +45,7 @@ export function JamlIde({ jaml, onChange, defaultMode = "code", searchResults =
|
|
|
45
45
|
padding: "12px 14px",
|
|
46
46
|
borderBottom: "1px solid rgba(255,255,255,0.08)",
|
|
47
47
|
background: "rgba(255,255,255,0.03)",
|
|
48
|
-
}, children: [_jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, fontWeight: 800 }, children: title }), _jsx("div", { style: { fontSize: 11, opacity: 0.66 }, children: "Reusable JAML authoring and preview surface." })] }), actions ? _jsx("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: actions }) : null] }), _jsx(JamlIdeToolbar, { mode: mode, onModeChange: setMode, resultCount: results.length }), _jsxs("div", { style: { flex: 1, minHeight: 0, overflow: "auto" }, children: [mode === "code" ? (_jsx("textarea", { title: "JAML IDE Editor", value: jaml, onChange: (event) => onChange(event.target.value), placeholder: codePlaceholder, spellCheck: false, autoCapitalize: "off", autoCorrect: "off", style: {
|
|
48
|
+
}, children: [_jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, fontWeight: 800 }, children: title }), _jsx("div", { style: { fontSize: 11, opacity: 0.66 }, children: "Reusable JAML authoring and preview surface." })] }), actions ? _jsx("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: actions }) : null] }), _jsx(JamlIdeToolbar, { mode: mode, onModeChange: setMode, resultCount: results.length, onSearch: onSearch, isSearching: isSearching }), _jsxs("div", { style: { flex: 1, minHeight: 0, overflow: "auto" }, children: [mode === "code" ? (_jsx("textarea", { title: "JAML IDE Editor", value: jaml, onChange: (event) => onChange(event.target.value), placeholder: codePlaceholder, spellCheck: false, autoCapitalize: "off", autoCorrect: "off", style: {
|
|
49
49
|
width: "100%",
|
|
50
50
|
minHeight: 320,
|
|
51
51
|
resize: "vertical",
|
|
@@ -4,5 +4,7 @@ export interface JamlIdeToolbarProps {
|
|
|
4
4
|
onModeChange: (mode: JamlIdeMode) => void;
|
|
5
5
|
resultCount?: number;
|
|
6
6
|
className?: string;
|
|
7
|
+
onSearch?: () => void;
|
|
8
|
+
isSearching?: boolean;
|
|
7
9
|
}
|
|
8
|
-
export declare function JamlIdeToolbar({ mode, onModeChange, resultCount, className }: JamlIdeToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare function JamlIdeToolbar({ mode, onModeChange, resultCount, className, onSearch, isSearching }: JamlIdeToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -5,8 +5,8 @@ const TABS = [
|
|
|
5
5
|
{ id: "map", label: "Map" },
|
|
6
6
|
{ id: "results", label: "Results" },
|
|
7
7
|
];
|
|
8
|
-
export function JamlIdeToolbar({ mode, onModeChange, resultCount = 0, className = "" }) {
|
|
9
|
-
return (
|
|
8
|
+
export function JamlIdeToolbar({ mode, onModeChange, resultCount = 0, className = "", onSearch, isSearching = false }) {
|
|
9
|
+
return (_jsxs("div", { className: className, style: {
|
|
10
10
|
display: "flex",
|
|
11
11
|
alignItems: "center",
|
|
12
12
|
justifyContent: "space-between",
|
|
@@ -14,23 +14,32 @@ export function JamlIdeToolbar({ mode, onModeChange, resultCount = 0, className
|
|
|
14
14
|
padding: "8px 10px",
|
|
15
15
|
borderBottom: "1px solid rgba(255,255,255,0.08)",
|
|
16
16
|
background: "rgba(255,255,255,0.04)",
|
|
17
|
-
}, children: _jsx("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: TABS.map((tab) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
17
|
+
}, children: [_jsx("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: TABS.map((tab) => {
|
|
18
|
+
const selected = mode === tab.id;
|
|
19
|
+
return (_jsxs("button", { type: "button", onClick: () => onModeChange(tab.id), style: {
|
|
20
|
+
cursor: "pointer",
|
|
21
|
+
borderRadius: 8,
|
|
22
|
+
border: selected ? "1px solid rgba(247,185,85,0.55)" : "1px solid transparent",
|
|
23
|
+
background: selected ? "rgba(247,185,85,0.16)" : "transparent",
|
|
24
|
+
color: selected ? "#f7b955" : "rgba(255,255,255,0.58)",
|
|
25
|
+
padding: "6px 10px",
|
|
26
|
+
fontSize: 11,
|
|
27
|
+
fontWeight: 600,
|
|
28
|
+
}, children: [tab.label, tab.id === "results" && resultCount > 0 ? (_jsx("span", { style: {
|
|
29
|
+
marginLeft: 6,
|
|
30
|
+
borderRadius: 999,
|
|
31
|
+
background: "rgba(0,0,0,0.25)",
|
|
32
|
+
padding: "1px 6px",
|
|
33
|
+
fontSize: 10,
|
|
34
|
+
}, children: resultCount })) : null] }, tab.id));
|
|
35
|
+
}) }), onSearch ? (_jsx("button", { type: "button", onClick: onSearch, disabled: isSearching, style: {
|
|
36
|
+
cursor: isSearching ? "not-allowed" : "pointer",
|
|
37
|
+
borderRadius: 8,
|
|
38
|
+
border: "1px solid rgba(74,222,128,0.4)",
|
|
39
|
+
background: isSearching ? "rgba(239,68,68,0.2)" : "rgba(74,222,128,0.15)",
|
|
40
|
+
color: isSearching ? "#ef4444" : "#4ade80",
|
|
41
|
+
padding: "6px 14px",
|
|
42
|
+
fontSize: 11,
|
|
43
|
+
fontWeight: 700,
|
|
44
|
+
}, children: isSearching ? "Stop" : "Search" })) : null] }));
|
|
36
45
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { JAML_ASSET_FILES, clearJamlAssetBaseUrl, getDefaultJamlAssetUrlMap, res
|
|
|
2
2
|
export { Layer, type LayerOptions } from "./render/Layer.js";
|
|
3
3
|
export { JamlCardRenderer, type JamlCardRendererProps } from "./render/CanvasRenderer.js";
|
|
4
4
|
export { JamlGameCard, JamlVoucher, JamlTag, JamlBoss, resolveAnalyzerShopItem, type JamlGameCardProps, type AnalyzerShopItem, type AnalyzerResolvedItem, } from "./components/GameCard.js";
|
|
5
|
+
export { AnalyzerExplorer, type AnalyzerAnteView, type AnalyzerBadge, type AnalyzerExplorerProps, type AnalyzerFact, type AnalyzerHighlight, type AnalyzerItem, } from "./components/AnalyzerExplorer.js";
|
|
5
6
|
export { JamlMapPreview, type JamlMapPreviewProps } from "./components/JamlMapPreview.js";
|
|
6
7
|
export { JamlIde, type JamlIdeProps, type JamlIdeSearchResult, } from "./components/JamlIde.js";
|
|
7
8
|
export { JamlIdeToolbar, type JamlIdeMode, type JamlIdeToolbarProps, } from "./components/JamlIdeToolbar.js";
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { JAML_ASSET_FILES, clearJamlAssetBaseUrl, getDefaultJamlAssetUrlMap, res
|
|
|
3
3
|
export { Layer } from "./render/Layer.js";
|
|
4
4
|
export { JamlCardRenderer } from "./render/CanvasRenderer.js";
|
|
5
5
|
export { JamlGameCard, JamlVoucher, JamlTag, JamlBoss, resolveAnalyzerShopItem, } from "./components/GameCard.js";
|
|
6
|
+
export { AnalyzerExplorer, } from "./components/AnalyzerExplorer.js";
|
|
6
7
|
export { JamlMapPreview } from "./components/JamlMapPreview.js";
|
|
7
8
|
export { JamlIde, } from "./components/JamlIde.js";
|
|
8
9
|
export { JamlIdeToolbar, } from "./components/JamlIdeToolbar.js";
|
package/dist/motely.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
1
|
export { decodeMotelyItem, decodeMotelyItemToJamlCard, motelyItemTypeName, motelyItemCategory, motelyItemDisplayName, motelyItemRenderCategory, motelyItemEditionName, motelyItemSealName, motelyItemEnhancementName, motelyPlayingCardRankName, motelyPlayingCardSuitName, decodeMotelyItemName, resolveMotelyItemType, warmMotelyItemCache, motelyItemCacheSize, type DecodedMotelyItem, type MotelyItemInput, type MotelyJamlCard, type MotelyRenderableCategory, type MotelyRuntimeItem, } from "./decode/motelyItemDecoder.js";
|
|
2
|
+
export { MOTELY_DISPLAY_SCHEMA, motelyBossDisplayName, motelyBossDisplayNameFromKey, motelyBossKeyFromDisplayName, motelyBoosterPackDisplayName, motelyBoosterPackDisplayNameFromKey, motelyBoosterPackKeyFromDisplayName, motelyItemDisplayNameFromKey, motelyItemDisplayNameFromValue, motelyTagDisplayName, motelyTagDisplayNameFromKey, motelyTagKeyFromDisplayName, motelyVoucherDisplayName, motelyVoucherDisplayNameFromKey, motelyVoucherKeyFromDisplayName, type MotelyBoosterPackKey, type MotelyBossKey, type MotelyDisplaySchema, type MotelyTagKey, type MotelyVoucherKey, } from "./motelyDisplay.js";
|
package/dist/motely.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
export { decodeMotelyItem, decodeMotelyItemToJamlCard, motelyItemTypeName, motelyItemCategory, motelyItemDisplayName, motelyItemRenderCategory, motelyItemEditionName, motelyItemSealName, motelyItemEnhancementName, motelyPlayingCardRankName, motelyPlayingCardSuitName, decodeMotelyItemName, resolveMotelyItemType, warmMotelyItemCache, motelyItemCacheSize, } from "./decode/motelyItemDecoder.js";
|
|
3
|
+
export { MOTELY_DISPLAY_SCHEMA, motelyBossDisplayName, motelyBossDisplayNameFromKey, motelyBossKeyFromDisplayName, motelyBoosterPackDisplayName, motelyBoosterPackDisplayNameFromKey, motelyBoosterPackKeyFromDisplayName, motelyItemDisplayNameFromKey, motelyItemDisplayNameFromValue, motelyTagDisplayName, motelyTagDisplayNameFromKey, motelyTagKeyFromDisplayName, motelyVoucherDisplayName, motelyVoucherDisplayNameFromKey, motelyVoucherKeyFromDisplayName, } from "./motelyDisplay.js";
|