jaml-ui 0.14.1 → 0.14.3

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.
Files changed (44) hide show
  1. package/dist/components/AnalyzerExplorer.js +0 -11
  2. package/dist/components/JamlAestheticSelector.js +1 -3
  3. package/dist/components/JamlAnalyzerFullscreen.js +3 -3
  4. package/dist/components/JamlIde.js +0 -2
  5. package/dist/components/JamlSeedInput.js +1 -2
  6. package/dist/components/JamlSpeedometer.js +1 -1
  7. package/dist/index.d.ts +0 -1
  8. package/dist/index.js +0 -1
  9. package/dist/ui/codeBlock.js +1 -1
  10. package/dist/ui/jimboCopyRow.js +1 -2
  11. package/dist/ui/jimboFilterBar.js +2 -4
  12. package/dist/ui/showcase.js +4 -4
  13. package/package.json +5 -3
  14. package/dist/components/PlayingCard.d.ts +0 -18
  15. package/dist/components/PlayingCard.js +0 -80
  16. package/dist/data/balatro-jokers.json +0 -1241
  17. package/dist/r3f/BalatroJokerMesh3D.d.ts +0 -8
  18. package/dist/r3f/BalatroJokerMesh3D.js +0 -98
  19. package/dist/r3f/BalatroJokerPreview3D.d.ts +0 -14
  20. package/dist/r3f/BalatroJokerPreview3D.js +0 -30
  21. package/dist/r3f/BalatroPlayingCard3D.d.ts +0 -22
  22. package/dist/r3f/BalatroPlayingCard3D.js +0 -62
  23. package/dist/r3f/cardConstants.d.ts +0 -16
  24. package/dist/r3f/cardConstants.js +0 -14
  25. package/dist/r3f/compositedAtlas.d.ts +0 -5
  26. package/dist/r3f/compositedAtlas.js +0 -56
  27. package/dist/r3f/gridUV.d.ts +0 -22
  28. package/dist/r3f/gridUV.js +0 -30
  29. package/dist/r3f/index.d.ts +0 -12
  30. package/dist/r3f/index.js +0 -13
  31. package/dist/r3f/jokerRegistry.d.ts +0 -28
  32. package/dist/r3f/jokerRegistry.js +0 -40
  33. package/dist/r3f/jokerTilt.d.ts +0 -8
  34. package/dist/r3f/jokerTilt.js +0 -41
  35. package/dist/r3f/magneticTilt.d.ts +0 -18
  36. package/dist/r3f/magneticTilt.js +0 -34
  37. package/dist/r3f/playingCardTypes.d.ts +0 -24
  38. package/dist/r3f/playingCardTypes.js +0 -32
  39. package/dist/r3f/playingCardVisuals.d.ts +0 -7
  40. package/dist/r3f/playingCardVisuals.js +0 -45
  41. package/dist/r3f/usePlayingCardTexture.d.ts +0 -7
  42. package/dist/r3f/usePlayingCardTexture.js +0 -92
  43. package/dist/utils/fileSystem.d.ts +0 -1
  44. package/dist/utils/fileSystem.js +0 -23
@@ -157,7 +157,6 @@ const styles = {
157
157
  highlightTitle: {
158
158
  fontSize: 12,
159
159
  color: "#6f6fa1",
160
- textTransform: "uppercase",
161
160
  letterSpacing: "0.05em",
162
161
  },
163
162
  highlightSubtitle: {
@@ -212,7 +211,6 @@ const styles = {
212
211
  highlightAnte: {
213
212
  fontSize: 11,
214
213
  color: "#a855f7",
215
- textTransform: "uppercase",
216
214
  letterSpacing: "0.05em",
217
215
  },
218
216
  highlightLabel: {
@@ -248,14 +246,12 @@ const styles = {
248
246
  navLabel: {
249
247
  fontSize: 13,
250
248
  color: "#a855f7",
251
- textTransform: "uppercase",
252
249
  letterSpacing: "0.05em",
253
250
  minWidth: 110,
254
251
  textAlign: "center",
255
252
  },
256
253
  navSubLabel: {
257
254
  color: "#5a5a88",
258
- textTransform: "none",
259
255
  letterSpacing: "normal",
260
256
  fontSize: 11,
261
257
  marginLeft: 4,
@@ -287,7 +283,6 @@ const styles = {
287
283
  anteHeading: {
288
284
  fontSize: 14,
289
285
  color: "#a855f7",
290
- textTransform: "uppercase",
291
286
  letterSpacing: "0.05em",
292
287
  },
293
288
  bossRow: {
@@ -305,7 +300,6 @@ const styles = {
305
300
  rowLabel: {
306
301
  fontSize: 11,
307
302
  color: "#5a5a88",
308
- textTransform: "uppercase",
309
303
  letterSpacing: "0.05em",
310
304
  marginBottom: 4,
311
305
  },
@@ -335,7 +329,6 @@ const styles = {
335
329
  color: "#7f7fa7",
336
330
  border: "1px solid #2a2a55",
337
331
  fontSize: 11,
338
- textTransform: "uppercase",
339
332
  },
340
333
  itemCard: {
341
334
  display: "flex",
@@ -386,7 +379,6 @@ const styles = {
386
379
  color: "#c7c7ef",
387
380
  border: "1px solid #35356d",
388
381
  fontSize: 11,
389
- textTransform: "uppercase",
390
382
  },
391
383
  badgeAccent: {
392
384
  padding: "1px 4px",
@@ -395,7 +387,6 @@ const styles = {
395
387
  color: "#f5c842",
396
388
  border: "1px solid rgba(245,200,66,0.35)",
397
389
  fontSize: 11,
398
- textTransform: "uppercase",
399
390
  },
400
391
  badgeMuted: {
401
392
  padding: "1px 4px",
@@ -404,7 +395,6 @@ const styles = {
404
395
  color: "#7f7fa7",
405
396
  border: "1px solid #2a2a55",
406
397
  fontSize: 11,
407
- textTransform: "uppercase",
408
398
  },
409
399
  packChip: {
410
400
  fontSize: 13,
@@ -427,7 +417,6 @@ const styles = {
427
417
  factLabel: {
428
418
  fontSize: 11,
429
419
  color: "#7f7fa7",
430
- textTransform: "uppercase",
431
420
  },
432
421
  factValue: {
433
422
  fontSize: 13,
@@ -16,7 +16,7 @@ export function JamlAestheticSelector({ value, onChange, className, style }) {
16
16
  flexDirection: "column",
17
17
  gap: 4,
18
18
  ...style,
19
- }, children: [_jsx(JimboText, { size: "xs", tone: "grey", uppercase: true, children: "Seed Aesthetics" }), _jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: AESTHETICS.map((a) => {
19
+ }, children: [_jsx(JimboText, { size: "xs", tone: "grey", children: "Seed Aesthetics" }), _jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: AESTHETICS.map((a) => {
20
20
  const isActive = value === a.id;
21
21
  return (_jsx("button", { type: "button", onClick: () => onChange(isActive ? null : a.id, a.value), title: a.desc, style: {
22
22
  padding: "4px 10px",
@@ -26,9 +26,7 @@ export function JamlAestheticSelector({ value, onChange, className, style }) {
26
26
  color: isActive ? JimboColorOption.GOLD_TEXT : JimboColorOption.GREY,
27
27
  cursor: "pointer",
28
28
  fontSize: 11,
29
- fontWeight: 700,
30
29
  fontFamily: "m6x11plus, monospace",
31
- textTransform: "uppercase",
32
30
  letterSpacing: 0.5,
33
31
  transition: "border-color 100ms, background 100ms",
34
32
  }, children: a.label }, a.id));
@@ -52,7 +52,7 @@ export function JamlAnalyzerFullscreen({ antes, live, enabledStreams, onEnabledS
52
52
  } }, ante.ante))) }), _jsx(SideRail, { antes: antes.map((a) => a.ante), currentAnte: currentAnte, onJump: scrollToAnte }), !hidePicker && (_jsx(StreamPicker, { enabled: effectiveEnabled, onChange: setEnabled, open: pickerOpen, onToggle: () => setPickerOpen((v) => !v) }))] }));
53
53
  }
54
54
  function AnteSection({ ante, live, enabledStreams, chunkSize, registerRef }) {
55
- return (_jsxs("section", { ref: registerRef, "data-ante": ante.ante, style: styles.section, children: [_jsxs("header", { style: styles.header, children: [_jsxs("div", { children: [_jsx("div", { style: styles.anteLabel, children: "ANTE" }), _jsx("div", { style: styles.anteNumber, children: ante.ante })] }), ante.voucher && (_jsxs("div", { style: styles.voucherBlock, children: [_jsx(JamlVoucher, { voucherName: ante.voucher, scale: 0.85 }), _jsx("div", { style: styles.voucherCaption, children: ante.voucher })] }))] }), _jsxs("div", { style: styles.blindRow, children: [_jsx(BlindCell, { label: "SMALL", tag: ante.smallBlindTag }), _jsx(BlindCell, { label: "BIG", tag: ante.bigBlindTag }), ante.boss && (_jsxs("div", { style: styles.bossCell, children: [_jsx("div", { style: styles.cellLabel, children: "BOSS" }), _jsx(JamlBoss, { bossName: ante.boss, scale: 0.7 }), _jsx("div", { style: styles.cellCaption, children: ante.boss })] }))] }), ante.packs && ante.packs.length > 0 && (_jsxs("div", { style: styles.streamLane, children: [_jsx("div", { style: styles.streamLabel, children: "PACKS" }), _jsx("div", { style: styles.packRow, children: ante.packs.map((pack, i) => (_jsx("div", { style: styles.packPill, children: pack }, `${ante.ante}-pack-${i}`))) })] })), enabledStreams.map((key) => {
55
+ return (_jsxs("section", { ref: registerRef, "data-ante": ante.ante, style: styles.section, children: [_jsxs("header", { style: styles.header, children: [_jsxs("div", { children: [_jsx("div", { style: styles.anteLabel, children: "Ante" }), _jsx("div", { style: styles.anteNumber, children: ante.ante })] }), ante.voucher && (_jsxs("div", { style: styles.voucherBlock, children: [_jsx(JamlVoucher, { voucherName: ante.voucher, scale: 0.85 }), _jsx("div", { style: styles.voucherCaption, children: ante.voucher })] }))] }), _jsxs("div", { style: styles.blindRow, children: [_jsx(BlindCell, { label: "Small", tag: ante.smallBlindTag }), _jsx(BlindCell, { label: "Big", tag: ante.bigBlindTag }), ante.boss && (_jsxs("div", { style: styles.bossCell, children: [_jsx("div", { style: styles.cellLabel, children: "Boss" }), _jsx(JamlBoss, { bossName: ante.boss, scale: 0.7 }), _jsx("div", { style: styles.cellCaption, children: ante.boss })] }))] }), ante.packs && ante.packs.length > 0 && (_jsxs("div", { style: styles.streamLane, children: [_jsx("div", { style: styles.streamLabel, children: "Packs" }), _jsx("div", { style: styles.packRow, children: ante.packs.map((pack, i) => (_jsx("div", { style: styles.packPill, children: pack }, `${ante.ante}-pack-${i}`))) })] })), enabledStreams.map((key) => {
56
56
  const isShop = key === "shop";
57
57
  const initialItems = isShop
58
58
  ? (ante.shop ?? []).map((item) => ({
@@ -70,7 +70,7 @@ function StreamLane({ ante, streamKey, live, chunkSize, initialItems }) {
70
70
  const stream = useMotelyStream(handle?.initStream ?? null, handle?.nextItem ?? null, [ante, streamKey, live?.seed, live?.deck, live?.stake], initialItems);
71
71
  const desired = live?.desiredNames ?? new Set();
72
72
  const toneColor = TONE_COLORS[meta.tone] ?? TONE_COLORS.default;
73
- return (_jsxs("div", { style: styles.streamLane, children: [_jsxs("div", { style: { ...styles.streamLabel, color: toneColor }, children: [meta.label.toUpperCase(), stream.items.length > 0 ? ` · ${stream.items.length}` : ""] }), _jsx(ShopRow, { items: stream.items, desired: desired, loadingMore: stream.loadingMore, ready: stream.ready, onPullMore: () => stream.pullMore(chunkSize) }), stream.error && _jsxs("div", { style: styles.errorLine, children: ["stream error: ", stream.error] })] }));
73
+ return (_jsxs("div", { style: styles.streamLane, children: [_jsxs("div", { style: { ...styles.streamLabel, color: toneColor }, children: [meta.label, stream.items.length > 0 ? ` · ${stream.items.length}` : ""] }), _jsx(ShopRow, { items: stream.items, desired: desired, loadingMore: stream.loadingMore, ready: stream.ready, onPullMore: () => stream.pullMore(chunkSize) }), stream.error && _jsxs("div", { style: styles.errorLine, children: ["stream error: ", stream.error] })] }));
74
74
  }
75
75
  function BlindCell({ label, tag }) {
76
76
  if (!tag)
@@ -139,7 +139,7 @@ function StreamPicker({ enabled, onChange, open, onToggle }) {
139
139
  next.add(key);
140
140
  onChange(all.map((m) => m.key).filter((k) => next.has(k)));
141
141
  }
142
- return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: onToggle, style: styles.pickerButton, "aria-label": "Toggle stream picker", children: open ? "✕" : "≡" }), open && (_jsxs("div", { style: styles.pickerPanel, children: [_jsx("div", { style: styles.pickerHeader, children: "STREAMS" }), all.map((meta) => {
142
+ return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: onToggle, style: styles.pickerButton, "aria-label": "Toggle stream picker", children: open ? "✕" : "≡" }), open && (_jsxs("div", { style: styles.pickerPanel, children: [_jsx("div", { style: styles.pickerHeader, children: "Streams" }), all.map((meta) => {
143
143
  const isOn = enabledSet.has(meta.key);
144
144
  const tone = TONE_COLORS[meta.tone] ?? TONE_COLORS.default;
145
145
  return (_jsxs("button", { type: "button", onClick: () => toggle(meta.key), style: {
@@ -61,7 +61,6 @@ function ResultsView({ results }) {
61
61
  minWidth: 80,
62
62
  }, children: result.seed }), result.score !== undefined ? (_jsxs(_Fragment, { children: [_jsx(TallyBar, { value: result.score, max: maxScore }), _jsx("span", { style: {
63
63
  fontSize: 12,
64
- fontWeight: 700,
65
64
  color: result.score > 0 ? JimboColorOption.GREEN_TEXT : JimboColorOption.GREY,
66
65
  minWidth: 36,
67
66
  textAlign: "right",
@@ -83,7 +82,6 @@ function ResultsView({ results }) {
83
82
  whiteSpace: "nowrap",
84
83
  }, children: label }), _jsx(TallyBar, { value: val, max: maxVal }), _jsx("span", { style: {
85
84
  fontSize: 11,
86
- fontWeight: 700,
87
85
  color: val > 0 ? JimboColorOption.GREEN_TEXT : JimboColorOption.DARK_GREY,
88
86
  minWidth: 24,
89
87
  textAlign: "right",
@@ -13,14 +13,13 @@ export function JamlSeedInput({ value, onChange, placeholder = "Enter seed (e.g.
13
13
  setInternal(raw);
14
14
  onChange?.(raw);
15
15
  };
16
- return (_jsxs("div", { className: className, style: { display: "flex", flexDirection: "column", gap: 4, ...style }, children: [_jsx(JimboText, { size: "xs", tone: "grey", uppercase: true, children: "Seed" }), _jsx("input", { type: "text", value: display, onChange: handleChange, placeholder: placeholder, maxLength: 8, spellCheck: false, autoComplete: "off", style: {
16
+ return (_jsxs("div", { className: className, style: { display: "flex", flexDirection: "column", gap: 4, ...style }, children: [_jsx(JimboText, { size: "xs", tone: "grey", children: "Seed" }), _jsx("input", { type: "text", value: display, onChange: handleChange, placeholder: placeholder, maxLength: 8, spellCheck: false, autoComplete: "off", style: {
17
17
  padding: "6px 10px",
18
18
  borderRadius: 6,
19
19
  border: `2px solid ${!isValid ? JimboColorOption.RED : display.length === 8 ? JimboColorOption.GREEN : JimboColorOption.PANEL_EDGE}`,
20
20
  background: JimboColorOption.DARKEST,
21
21
  color: JimboColorOption.GOLD_TEXT,
22
22
  fontSize: 16,
23
- fontWeight: 900,
24
23
  fontFamily: "m6x11plus, monospace",
25
24
  letterSpacing: 2,
26
25
  textTransform: "uppercase",
@@ -50,5 +50,5 @@ export function JamlSpeedometer({ seedsPerSecond, totalSearched, matchingSeeds,
50
50
  transformOrigin: "60px 65px",
51
51
  transform: `rotate(${angle}deg)`,
52
52
  transition: "transform 300ms ease",
53
- } }), _jsx("circle", { cx: 60, cy: 65, r: 4, fill: JimboColorOption.RED })] }) }), _jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 20, fontWeight: 900, fontFamily: "m6x11plus, monospace", color: isActive ? speedColor : JimboColorOption.GREY }, children: isActive ? formatSpeed(seedsPerSecond) : "---" }), _jsx(JimboText, { size: "xs", tone: "grey", uppercase: true, children: "seeds / sec" })] }), _jsxs("div", { style: { display: "flex", gap: 16, marginTop: 2 }, children: [_jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 13, fontWeight: 700, fontFamily: "m6x11plus, monospace", color: JimboColorOption.WHITE }, children: formatCount(totalSearched) }), _jsx(JimboText, { size: "xs", tone: "grey", uppercase: true, children: "searched" })] }), _jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 13, fontWeight: 700, fontFamily: "m6x11plus, monospace", color: JimboColorOption.GREEN_TEXT }, children: formatCount(matchingSeeds) }), _jsx(JimboText, { size: "xs", tone: "grey", uppercase: true, children: "matches" })] })] })] }));
53
+ } }), _jsx("circle", { cx: 60, cy: 65, r: 4, fill: JimboColorOption.RED })] }) }), _jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 20, fontFamily: "m6x11plus, monospace", color: isActive ? speedColor : JimboColorOption.GREY }, children: isActive ? formatSpeed(seedsPerSecond) : "---" }), _jsx(JimboText, { size: "xs", tone: "grey", children: "seeds / sec" })] }), _jsxs("div", { style: { display: "flex", gap: 16, marginTop: 2 }, children: [_jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 13, fontFamily: "m6x11plus, monospace", color: JimboColorOption.WHITE }, children: formatCount(totalSearched) }), _jsx(JimboText, { size: "xs", tone: "grey", children: "searched" })] }), _jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 13, fontFamily: "m6x11plus, monospace", color: JimboColorOption.GREEN_TEXT }, children: formatCount(matchingSeeds) }), _jsx(JimboText, { size: "xs", tone: "grey", children: "matches" })] })] })] }));
54
54
  }
package/dist/index.d.ts CHANGED
@@ -28,4 +28,3 @@ export { useAnalyzer, type AnalyzerStatus, type AnalyzerLive, type MotelyJsRunSt
28
28
  export { JamlSpeedometer, type JamlSpeedometerProps, } from "./components/JamlSpeedometer.js";
29
29
  export { JamlAestheticSelector, type JamlAestheticSelectorProps, type JamlAestheticOption, } from "./components/JamlAestheticSelector.js";
30
30
  export { JamlSeedInput, type JamlSeedInputProps, } from "./components/JamlSeedInput.js";
31
- export { initJamlFileSystem } from "./utils/fileSystem.js";
package/dist/index.js CHANGED
@@ -29,4 +29,3 @@ export { useAnalyzer, } from "./hooks/useAnalyzer.js";
29
29
  export { JamlSpeedometer, } from "./components/JamlSpeedometer.js";
30
30
  export { JamlAestheticSelector, } from "./components/JamlAestheticSelector.js";
31
31
  export { JamlSeedInput, } from "./components/JamlSeedInput.js";
32
- export { initJamlFileSystem } from "./utils/fileSystem.js";
@@ -9,7 +9,7 @@ export function JimboCodeBlock({ code, language, filename, className = '' }) {
9
9
  setCopied(true);
10
10
  setTimeout(() => setCopied(false), 2000);
11
11
  };
12
- return (_jsxs("div", { className: 'rounded-xl overflow-hidden flex flex-col border-2 ' + className, style: { backgroundColor: JimboColorOption.DARKEST, borderColor: JimboColorOption.PANEL_EDGE, boxShadow: '0 3px 0 0 rgba(0,0,0,0.5)' }, children: [_jsxs("div", { style: { padding: '0.5rem 1rem', display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: `1px solid ${JimboColorOption.INNER_BORDER}` }, children: [_jsxs("div", { style: { display: 'flex', gap: '0.5rem', alignItems: 'center' }, children: [filename && _jsx("span", { style: { fontSize: 10, textTransform: 'uppercase', opacity: 0.6 }, children: filename }), language && _jsx("span", { style: { fontSize: 9, padding: '1px 6px', borderRadius: 3, background: 'rgba(0,0,0,0.4)', color: '#60a5fa', textTransform: 'uppercase' }, children: language })] }), _jsx("button", { onClick: copy, title: "Copy", style: { padding: 4, background: 'none', border: 'none', cursor: 'pointer', color: copied ? '#4ade80' : 'rgba(255,255,255,0.5)', display: 'flex' }, children: copied
12
+ return (_jsxs("div", { className: 'rounded-xl overflow-hidden flex flex-col border-2 ' + className, style: { backgroundColor: JimboColorOption.DARKEST, borderColor: JimboColorOption.PANEL_EDGE, boxShadow: '0 3px 0 0 rgba(0,0,0,0.5)' }, children: [_jsxs("div", { style: { padding: '0.5rem 1rem', display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: `1px solid ${JimboColorOption.INNER_BORDER}` }, children: [_jsxs("div", { style: { display: 'flex', gap: '0.5rem', alignItems: 'center' }, children: [filename && _jsx("span", { style: { fontSize: 10, opacity: 0.6 }, children: filename }), language && _jsx("span", { style: { fontSize: 9, padding: '1px 6px', borderRadius: 3, background: 'rgba(0,0,0,0.4)', color: '#60a5fa' }, children: language })] }), _jsx("button", { onClick: copy, title: "Copy", style: { padding: 4, background: 'none', border: 'none', cursor: 'pointer', color: copied ? '#4ade80' : 'rgba(255,255,255,0.5)', display: 'flex' }, children: copied
13
13
  ? _jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) })
14
14
  : _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }), _jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] }) })] }), _jsx("pre", { style: { padding: '1rem', overflowX: 'auto', fontFamily: 'monospace', fontSize: '0.875rem', lineHeight: 1.6, color: '#f6f0d5', margin: 0 }, children: _jsx("code", { children: code }) })] }));
15
15
  }
@@ -12,7 +12,7 @@ export function JimboCopyRow({ value, label }) {
12
12
  setTimeout(() => setCopied(false), 1500);
13
13
  });
14
14
  }
15
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [label && (_jsx(JimboText, { size: "xs", tone: "grey", uppercase: true, style: { letterSpacing: 2 }, children: label })), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("div", { style: {
15
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [label && (_jsx(JimboText, { size: "xs", tone: "grey", style: { letterSpacing: 2 }, children: label })), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("div", { style: {
16
16
  flex: 1,
17
17
  padding: '6px 10px',
18
18
  background: C.DARKEST,
@@ -31,6 +31,5 @@ export function JimboCopyRow({ value, label }) {
31
31
  cursor: 'pointer',
32
32
  flexShrink: 0,
33
33
  transition: 'color 0.15s, background 0.15s, border-color 0.15s',
34
- textTransform: 'uppercase',
35
34
  }, children: copied ? 'Copied' : 'Copy' })] })] }));
36
35
  }
@@ -9,7 +9,7 @@ import { JimboText } from './jimboText.js';
9
9
  *
10
10
  * Pass `sortOptions` to show the sort side; omit to show search only.
11
11
  */
12
- export function JimboFilterBar({ search, onSearchChange, searchPlaceholder = 'SEARCH...', searchLabel = 'Search', sort, onSortChange, sortLabel = 'Sort By', sortOptions, className = '', style, }) {
12
+ export function JimboFilterBar({ search, onSearchChange, searchPlaceholder = 'Search...', searchLabel = 'Search', sort, onSortChange, sortLabel = 'Sort By', sortOptions, className = '', style, }) {
13
13
  return (_jsxs("div", { className: className, style: {
14
14
  display: 'flex',
15
15
  gap: 24,
@@ -35,7 +35,6 @@ export function JimboFilterBar({ search, onSearchChange, searchPlaceholder = 'SE
35
35
  fontFamily: "'m6x11plus', 'Courier New', monospace",
36
36
  fontSize: 20,
37
37
  letterSpacing: 2,
38
- textTransform: 'uppercase',
39
38
  outline: 'none',
40
39
  } })] }) })) : null, sortOptions && onSortChange ? (_jsx(FloatingLabelField, { label: sortLabel, children: _jsxs("div", { style: { position: 'relative' }, children: [_jsx("select", { value: sort ?? sortOptions[0]?.value, onChange: (e) => onSortChange(e.target.value), style: {
41
40
  appearance: 'none',
@@ -50,7 +49,6 @@ export function JimboFilterBar({ search, onSearchChange, searchPlaceholder = 'SE
50
49
  fontFamily: "'m6x11plus', 'Courier New', monospace",
51
50
  fontSize: 18,
52
51
  letterSpacing: 2,
53
- textTransform: 'uppercase',
54
52
  padding: '14px 48px 14px 24px',
55
53
  minWidth: 200,
56
54
  textAlign: 'center',
@@ -67,7 +65,7 @@ function FloatingLabelField({ label, children }) {
67
65
  borderRadius: 6,
68
66
  padding: '4px 12px',
69
67
  zIndex: 2,
70
- }, children: _jsx(JimboText, { size: "xs", uppercase: true, children: label }) }), children] }));
68
+ }, children: _jsx(JimboText, { size: "xs", children: label }) }), children] }));
71
69
  }
72
70
  function SearchIcon() {
73
71
  return (_jsxs("svg", { width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [_jsx("circle", { cx: 11, cy: 11, r: 8 }), _jsx("line", { x1: 21, y1: 21, x2: 16.65, y2: 16.65 })] }));
@@ -16,7 +16,7 @@ export function Showcase({ hotFilters = [], recentFinds = [], stats = DEFAULT_ST
16
16
  width: '100%', height: '100%', background: C.DARKEST,
17
17
  display: 'flex', flexDirection: 'column',
18
18
  fontFamily: 'm6x11plus, monospace', color: C.WHITE, overflow: 'hidden',
19
- }, children: [_jsxs("div", { style: { flex: 1, minHeight: 0, overflowY: 'auto', padding: '18px 14px 10px' }, children: [_jsxs("div", { style: { textAlign: 'center', marginBottom: 18 }, children: [_jsx("div", { style: { fontSize: 32, letterSpacing: 3, lineHeight: 1, color: C.GOLD, textShadow: '2px 2px 0 rgba(0,0,0,.8)' }, children: "Balatro" }), _jsx("div", { style: { fontSize: 14, letterSpacing: 4, color: C.GREY, marginTop: 4, textShadow: '1px 1px 0 rgba(0,0,0,.8)' }, children: "SEED \u00B7 CURATOR" })] }), _jsx("div", { style: {
19
+ }, children: [_jsxs("div", { style: { flex: 1, minHeight: 0, overflowY: 'auto', padding: '18px 14px 10px' }, children: [_jsxs("div", { style: { textAlign: 'center', marginBottom: 18 }, children: [_jsx("div", { style: { fontSize: 32, letterSpacing: 3, lineHeight: 1, color: C.GOLD, textShadow: '2px 2px 0 rgba(0,0,0,.8)' }, children: "Balatro" }), _jsx("div", { style: { fontSize: 14, letterSpacing: 4, color: C.GREY, marginTop: 4, textShadow: '1px 1px 0 rgba(0,0,0,.8)' }, children: "Seed \u00B7 Curator" })] }), _jsx("div", { style: {
20
20
  background: C.DARK_GREY, borderRadius: 6, padding: 10,
21
21
  border: `2px solid ${C.PANEL_EDGE}`, boxShadow: `0 2px 0 ${C.BLACK}`,
22
22
  display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8, textAlign: 'center', marginBottom: 16,
@@ -24,11 +24,11 @@ export function Showcase({ hotFilters = [], recentFinds = [], stats = DEFAULT_ST
24
24
  [stats.searched, 'searched'],
25
25
  [stats.matches, 'matches'],
26
26
  [stats.speed, 'speed'],
27
- ].map(([n, l]) => (_jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, color: C.GOLD, textShadow: '1px 1px 0 rgba(0,0,0,.8)' }, children: n }), _jsx("div", { style: { fontSize: 9, color: C.GREY, letterSpacing: 2, marginTop: 2 }, children: l.toUpperCase() })] }, l))) }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }, children: [_jsx("div", { style: {
27
+ ].map(([n, l]) => (_jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, color: C.GOLD, textShadow: '1px 1px 0 rgba(0,0,0,.8)' }, children: n }), _jsx("div", { style: { fontSize: 9, color: C.GREY, letterSpacing: 2, marginTop: 2 }, children: l })] }, l))) }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }, children: [_jsx("div", { style: {
28
28
  fontSize: 11, letterSpacing: 2, padding: '2px 8px',
29
29
  background: C.BLUE, color: C.WHITE, borderRadius: 3,
30
30
  textShadow: '1px 1px 0 rgba(0,0,0,.8)',
31
- }, children: "HOT FILTERS" }), _jsx("div", { style: { flex: 1, height: 2, background: `${C.BLUE}55`, borderRadius: 1 } })] }), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 16 }, children: hotFilters.map((f, i) => {
31
+ }, children: "Hot Filters" }), _jsx("div", { style: { flex: 1, height: 2, background: `${C.BLUE}55`, borderRadius: 1 } })] }), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 16 }, children: hotFilters.map((f, i) => {
32
32
  const tColor = TONE_COLOR[f.tone];
33
33
  return (_jsxs("div", { style: {
34
34
  background: C.DARK_GREY, borderRadius: 6, padding: 10,
@@ -43,7 +43,7 @@ export function Showcase({ hotFilters = [], recentFinds = [], stats = DEFAULT_ST
43
43
  fontSize: 11, letterSpacing: 2, padding: '2px 8px',
44
44
  background: C.GREEN, color: C.WHITE, borderRadius: 3,
45
45
  textShadow: '1px 1px 0 rgba(0,0,0,.8)',
46
- }, children: "RECENT FINDS" }), _jsx("div", { style: { flex: 1, height: 2, background: `${C.GREEN}55`, borderRadius: 1 } })] }), _jsx("div", { style: {
46
+ }, children: "Recent Finds" }), _jsx("div", { style: { flex: 1, height: 2, background: `${C.GREEN}55`, borderRadius: 1 } })] }), _jsx("div", { style: {
47
47
  background: C.DARK_GREY, borderRadius: 6, padding: '8px 10px',
48
48
  border: `2px solid ${C.PANEL_EDGE}`, boxShadow: `0 2px 0 ${C.BLACK}`,
49
49
  fontSize: 11, color: C.GREY, letterSpacing: 1, lineHeight: 1.7,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaml-ui",
3
- "version": "0.14.1",
3
+ "version": "0.14.3",
4
4
  "description": "Balatro rendering components, sprite metadata, and optional Motely helpers for React apps.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -108,13 +108,15 @@
108
108
  "@types/three": "^0.184.0",
109
109
  "@vitejs/plugin-react": "^5.0.4",
110
110
  "monaco-editor": "^0.55.1",
111
- "motely-wasm": "link:../JammySeedFinder/src/MotelyJAML/Motely.Wasm/bin/motely-wasm",
112
- "@rewaffle/bootsharp-file-system": "link:D:/extra/bootsharp/dist/packages/file-system",
111
+ "motely-wasm": "^14.0.2",
113
112
  "react": "^19.2.4",
114
113
  "react-dom": "^19.2.4",
115
114
  "react-icons": "^5.6.0",
116
115
  "three": "^0.184.0",
117
116
  "typescript": "^5.9.3",
118
117
  "vite": "^8.0.9"
118
+ },
119
+ "dependencies": {
120
+ "@google/design.md": "^0.1.1"
119
121
  }
120
122
  }
@@ -1,18 +0,0 @@
1
- import React from 'react';
2
- export type CardSuit = 'Hearts' | 'Diamonds' | 'Clubs' | 'Spades' | 'hearts' | 'diamonds' | 'clubs' | 'spades';
3
- export type CardRank = 'Ace' | 'King' | 'Queen' | 'Jack' | '10' | '9' | '8' | '7' | '6' | '5' | '4' | '3' | '2' | 'A' | 'K' | 'Q' | 'J';
4
- export type CardEnhancement = 'bonus' | 'mult' | 'wild' | 'glass' | 'steel' | 'stone' | 'gold' | 'lucky' | null;
5
- export type CardSeal = 'gold' | 'red' | 'blue' | 'purple' | null;
6
- export type CardEdition = 'Foil' | 'Holographic' | 'Polychrome' | 'Negative' | null;
7
- interface RealPlayingCardProps {
8
- suit: CardSuit;
9
- rank: CardRank;
10
- enhancement?: CardEnhancement;
11
- seal?: CardSeal;
12
- edition?: CardEdition;
13
- className?: string;
14
- size?: number;
15
- style?: React.CSSProperties;
16
- }
17
- export declare function RealPlayingCard({ suit, rank, enhancement, seal, edition, className, size, style }: RealPlayingCardProps): import("react/jsx-runtime").JSX.Element | null;
18
- export {};
@@ -1,80 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { resolveJamlAssetUrl } from '../assets.js';
4
- import { RANK_MAP, SUIT_MAP, ENHANCER_MAP, SEAL_MAP, EDITION_MAP } from '../sprites/spriteData.js';
5
- function cn(...classes) { return classes.filter(Boolean).join(" "); }
6
- const CARD_WIDTH = 71;
7
- const CARD_HEIGHT = 95;
8
- const RANK_ALIAS = { A: 'Ace', K: 'King', Q: 'Queen', J: 'Jack' };
9
- const pascal = (s) => s[0].toUpperCase() + s.slice(1).toLowerCase();
10
- export function RealPlayingCard({ suit, rank, enhancement, seal, edition, className, size = 71, style }) {
11
- const rankKey = RANK_ALIAS[rank] ?? rank;
12
- const suitKey = pascal(suit);
13
- const col = RANK_MAP[rankKey];
14
- const row = SUIT_MAP[suitKey];
15
- if (col === undefined || row === undefined) {
16
- console.warn(`Invalid card: ${rank} of ${suit}`);
17
- return null;
18
- }
19
- const scale = size / CARD_WIDTH;
20
- const finalH = size * (CARD_HEIGHT / CARD_WIDTH);
21
- // Base card position
22
- const bgX = -col * CARD_WIDTH;
23
- const bgY = -row * CARD_HEIGHT;
24
- // Enhancement background (if any) — ENHANCER_MAP is PascalCase, prop is lowercase
25
- const enhPos = enhancement ? ENHANCER_MAP[pascal(enhancement)] ?? { x: 0, y: 0 } : { x: 0, y: 0 };
26
- const enhBgX = -enhPos.x * CARD_WIDTH;
27
- const enhBgY = -enhPos.y * CARD_HEIGHT;
28
- // Seal overlay — SEAL_MAP is keyed by "Gold"/"Red"/"Blue"/"Purple"
29
- const sealPos = seal ? SEAL_MAP[pascal(seal)] ?? null : null;
30
- const sealBgX = sealPos ? -sealPos.x * CARD_WIDTH : 0;
31
- const sealBgY = sealPos ? -sealPos.y * CARD_HEIGHT : 0;
32
- // Edition overlay — EDITION_MAP gives column index on 5-wide editions sheet
33
- const editionCol = edition ? EDITION_MAP[edition] : undefined;
34
- const editionBgX = editionCol !== undefined ? -editionCol * CARD_WIDTH : 0;
35
- const editionBgY = 0;
36
- const isNegative = edition === 'Negative';
37
- const baseFilter = isNegative ? 'invert(0.94)' : 'none';
38
- const enhancersUrl = resolveJamlAssetUrl('enhancers');
39
- const deckUrl = resolveJamlAssetUrl('deck');
40
- const editionsUrl = resolveJamlAssetUrl('editions');
41
- return (_jsxs("div", { className: cn('relative overflow-hidden inline-block select-none', className), style: {
42
- width: size,
43
- height: finalH,
44
- imageRendering: 'pixelated',
45
- ...style
46
- }, title: `${rank} of ${suit}${enhancement ? ` (${enhancement})` : ''}${seal ? ` [${seal} seal]` : ''}${edition ? ` {${edition}}` : ''}`, children: [_jsx("div", { className: "absolute inset-0", style: {
47
- backgroundImage: `url(${enhancersUrl})`,
48
- backgroundPosition: `${enhBgX}px ${enhBgY}px`,
49
- width: CARD_WIDTH,
50
- height: CARD_HEIGHT,
51
- transform: `scale(${scale})`,
52
- transformOrigin: 'top left',
53
- backgroundRepeat: 'no-repeat',
54
- } }), _jsx("div", { className: "absolute inset-0 z-[1]", style: {
55
- backgroundImage: `url(${deckUrl})`,
56
- backgroundPosition: `${bgX}px ${bgY}px`,
57
- width: CARD_WIDTH,
58
- height: CARD_HEIGHT,
59
- transform: `scale(${scale})`,
60
- transformOrigin: 'top left',
61
- backgroundRepeat: 'no-repeat',
62
- filter: baseFilter
63
- } }), edition && edition !== 'Negative' && (_jsx("div", { className: "absolute inset-0 z-[2] mix-blend-screen opacity-60", style: {
64
- backgroundImage: `url(${editionsUrl})`,
65
- backgroundPosition: `${editionBgX}px ${editionBgY}px`,
66
- width: CARD_WIDTH,
67
- height: CARD_HEIGHT,
68
- transform: `scale(${scale})`,
69
- transformOrigin: 'top left',
70
- backgroundRepeat: 'no-repeat',
71
- } })), seal && (_jsx("div", { className: "absolute inset-0 z-[3]", style: {
72
- backgroundImage: `url(${enhancersUrl})`,
73
- backgroundPosition: `${sealBgX}px ${sealBgY}px`,
74
- width: CARD_WIDTH,
75
- height: CARD_HEIGHT,
76
- transform: `scale(${scale})`,
77
- transformOrigin: 'top left',
78
- backgroundRepeat: 'no-repeat',
79
- } })), isNegative && (_jsx("div", { className: "absolute inset-0 z-[4] bg-red-500/10 pointer-events-none mix-blend-overlay" }))] }));
80
- }