jaml-ui 0.6.1 → 0.7.1

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 (58) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +135 -145
  3. package/dist/assets.js +13 -10
  4. package/dist/components/JamlIdeToolbar.js +2 -36
  5. package/dist/components/JamlIdeVisual.js +2 -2
  6. package/dist/hooks/loadMotelyWasm.d.ts +7 -0
  7. package/dist/hooks/loadMotelyWasm.js +16 -0
  8. package/dist/hooks/searchWorkerCode.d.ts +1 -0
  9. package/dist/hooks/searchWorkerCode.js +62 -0
  10. package/dist/hooks/useAnalyzer.d.ts +8 -0
  11. package/dist/hooks/useAnalyzer.js +72 -0
  12. package/dist/hooks/useSearch.d.ts +21 -0
  13. package/dist/hooks/useSearch.js +76 -0
  14. package/dist/ui/footer.js +5 -5
  15. package/dist/ui/panel.d.ts +6 -17
  16. package/dist/ui/panel.js +12 -47
  17. package/dist/ui/showcase.js +4 -4
  18. package/dist/ui/sprites.d.ts +2 -2
  19. package/dist/ui/sprites.js +1 -1
  20. package/package.json +107 -109
  21. package/assets/8BitDeck.png +0 -0
  22. package/assets/BlindChips.png +0 -0
  23. package/assets/Boosters.png +0 -0
  24. package/assets/Editions.png +0 -0
  25. package/assets/Enhancers.png +0 -0
  26. package/assets/Jokers.png +0 -0
  27. package/assets/Tarots.png +0 -0
  28. package/assets/Vouchers.png +0 -0
  29. package/assets/fonts/m6x11plusplus.otf +0 -0
  30. package/assets/stickers.png +0 -0
  31. package/assets/tags.png +0 -0
  32. package/dist/data/balatro-jokers.json +0 -1241
  33. package/dist/r3f/BalatroJokerMesh3D.d.ts +0 -8
  34. package/dist/r3f/BalatroJokerMesh3D.js +0 -98
  35. package/dist/r3f/BalatroJokerPreview3D.d.ts +0 -14
  36. package/dist/r3f/BalatroJokerPreview3D.js +0 -30
  37. package/dist/r3f/BalatroPlayingCard3D.d.ts +0 -22
  38. package/dist/r3f/BalatroPlayingCard3D.js +0 -62
  39. package/dist/r3f/cardConstants.d.ts +0 -16
  40. package/dist/r3f/cardConstants.js +0 -14
  41. package/dist/r3f/compositedAtlas.d.ts +0 -5
  42. package/dist/r3f/compositedAtlas.js +0 -56
  43. package/dist/r3f/gridUV.d.ts +0 -22
  44. package/dist/r3f/gridUV.js +0 -30
  45. package/dist/r3f/index.d.ts +0 -12
  46. package/dist/r3f/index.js +0 -13
  47. package/dist/r3f/jokerRegistry.d.ts +0 -28
  48. package/dist/r3f/jokerRegistry.js +0 -40
  49. package/dist/r3f/jokerTilt.d.ts +0 -8
  50. package/dist/r3f/jokerTilt.js +0 -41
  51. package/dist/r3f/magneticTilt.d.ts +0 -18
  52. package/dist/r3f/magneticTilt.js +0 -34
  53. package/dist/r3f/playingCardTypes.d.ts +0 -24
  54. package/dist/r3f/playingCardTypes.js +0 -32
  55. package/dist/r3f/playingCardVisuals.d.ts +0 -7
  56. package/dist/r3f/playingCardVisuals.js +0 -45
  57. package/dist/r3f/usePlayingCardTexture.d.ts +0 -7
  58. package/dist/r3f/usePlayingCardTexture.js +0 -92
@@ -0,0 +1,76 @@
1
+ "use client";
2
+ import { useState, useCallback, useRef, useEffect } from "react";
3
+ import { SEARCH_WORKER_CODE } from "./searchWorkerCode.js";
4
+ function createWorker(motelyWasmUrl) {
5
+ const blob = new Blob([SEARCH_WORKER_CODE], { type: "text/javascript" });
6
+ const blobUrl = URL.createObjectURL(blob);
7
+ const worker = new Worker(blobUrl);
8
+ worker.postMessage({ type: "init", url: motelyWasmUrl });
9
+ return worker;
10
+ }
11
+ export function useSearch(motelyWasmUrl) {
12
+ const [state, setState] = useState({
13
+ results: [],
14
+ totalSearched: 0n,
15
+ matchingSeeds: 0n,
16
+ status: "idle",
17
+ error: null,
18
+ });
19
+ const workerRef = useRef(null);
20
+ const readyRef = useRef(false);
21
+ useEffect(() => {
22
+ setState((s) => ({ ...s, status: "booting" }));
23
+ const worker = createWorker(motelyWasmUrl);
24
+ workerRef.current = worker;
25
+ readyRef.current = false;
26
+ worker.onmessage = (e) => {
27
+ const msg = e.data;
28
+ if (msg.type === "ready") {
29
+ readyRef.current = true;
30
+ setState((s) => s.status === "booting" ? { ...s, status: "idle" } : s);
31
+ }
32
+ else if (msg.type === "result") {
33
+ setState((s) => ({ ...s, results: [...s.results, { seed: msg.seed, score: msg.score }] }));
34
+ }
35
+ else if (msg.type === "progress") {
36
+ setState((s) => ({ ...s, totalSearched: BigInt(msg.searched), matchingSeeds: BigInt(msg.matching) }));
37
+ }
38
+ else if (msg.type === "complete") {
39
+ setState((s) => ({ ...s, status: msg.status === "Completed" ? "completed" : "error", error: msg.status !== "Completed" ? msg.status : null, totalSearched: BigInt(msg.searched), matchingSeeds: BigInt(msg.matched) }));
40
+ }
41
+ else if (msg.type === "cancelled") {
42
+ setState((s) => ({ ...s, status: "cancelled" }));
43
+ }
44
+ else if (msg.type === "error") {
45
+ setState((s) => ({ ...s, status: "error", error: msg.message }));
46
+ }
47
+ };
48
+ return () => {
49
+ worker.terminate();
50
+ workerRef.current = null;
51
+ };
52
+ }, [motelyWasmUrl]);
53
+ const start = useCallback((jaml, count) => {
54
+ const worker = workerRef.current;
55
+ if (!worker)
56
+ return;
57
+ setState({ results: [], totalSearched: 0n, matchingSeeds: 0n, status: "running", error: null });
58
+ if (readyRef.current) {
59
+ worker.postMessage({ type: "start", jaml, count });
60
+ }
61
+ else {
62
+ const orig = worker.onmessage;
63
+ worker.onmessage = (e) => {
64
+ orig?.call(worker, e);
65
+ if (e.data.type === "ready") {
66
+ worker.onmessage = orig;
67
+ worker.postMessage({ type: "start", jaml, count });
68
+ }
69
+ };
70
+ }
71
+ }, []);
72
+ const cancel = useCallback(() => {
73
+ workerRef.current?.postMessage({ type: "stop" });
74
+ }, []);
75
+ return { ...state, start, cancel };
76
+ }
package/dist/ui/footer.js CHANGED
@@ -9,10 +9,10 @@ const SUITS = [
9
9
  ];
10
10
  const CYCLE = '5s';
11
11
  export function JimboBalatroFooter({ hidden = false, className = '' }) {
12
- return (_jsxs("div", { className: ['fixed right-0 bottom-0 left-0 w-screen min-w-full transition-opacity duration-200', hidden ? 'pointer-events-none opacity-0' : 'opacity-100', className].filter(Boolean).join(' '), children: [_jsx("div", { style: { width: '100%', borderTop: '1px solid rgba(255,255,255,0.1)', background: 'rgba(0,0,0,0.9)', padding: '0 1rem 3px', textAlign: 'center' }, children: _jsxs("p", { style: { fontFamily: 'm6x11plus, monospace', fontSize: 'clamp(11px, 0.8vw + 8px, 14px)', display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center', gap: '0 0.5rem', color: 'white', margin: 0 }, children: [_jsx("span", { children: "Not affiliated with LocalThunk or PlayStack" }), _jsxs("span", { style: { display: 'inline-flex', alignItems: 'center', gap: '0.25rem' }, children: ["Made with", ' ', _jsx("span", { style: { position: 'relative', display: 'inline-block', width: '1.5em', height: '1em', verticalAlign: 'middle' }, children: SUITS.map(({ char, kf }) => (_jsx("span", { style: { position: 'absolute', inset: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', opacity: 0, animationName: kf, animationDuration: CYCLE, animationDelay: '0s', animationIterationCount: 'infinite', animationTimingFunction: 'ease-out' }, children: char }, char))) }), ' ', "for the", ' ', _jsx("a", { href: "https://playbalatro.com", target: "_blank", rel: "noopener noreferrer", style: { color: JimboColorOption.GOLD, textDecoration: 'none' }, children: "Balatro" }), ' ', "community"] })] }) }), _jsx("style", { children: `
13
- @keyframes jaml-heart { 0%{opacity:0;transform:scale(1)} 1%{opacity:1;transform:scale(1.45)} 3.5%{opacity:1;transform:scale(1)} 61.5%{opacity:1;transform:scale(1)} 62%{opacity:0} 100%{opacity:0} }
14
- @keyframes jaml-spade { 0%,61.5%{opacity:0} 62%{opacity:1;transform:scale(1.45)} 64.5%{opacity:1;transform:scale(1)} 71.5%{opacity:1} 72%{opacity:0} 100%{opacity:0} }
15
- @keyframes jaml-diamond { 0%,71.5%{opacity:0} 72%{opacity:1;transform:scale(1.45)} 74.5%{opacity:1;transform:scale(1)} 81.5%{opacity:1} 82%{opacity:0} 100%{opacity:0} }
16
- @keyframes jaml-club { 0%,81.5%{opacity:0} 82%{opacity:1;transform:scale(1.45)} 84.5%{opacity:1;transform:scale(1)} 95%{opacity:1} 96%{opacity:0} 100%{opacity:0} }
12
+ return (_jsxs("div", { className: ['fixed right-0 bottom-0 left-0 w-screen min-w-full transition-opacity duration-200', hidden ? 'pointer-events-none opacity-0' : 'opacity-100', className].filter(Boolean).join(' '), children: [_jsx("div", { style: { width: '100%', borderTop: '1px solid rgba(255,255,255,0.1)', background: 'rgba(0,0,0,0.9)', padding: '0 1rem 3px', textAlign: 'center' }, children: _jsxs("p", { style: { fontFamily: 'm6x11plus, monospace', fontSize: 'clamp(11px, 0.8vw + 8px, 14px)', display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center', gap: '0 0.5rem', color: 'white', margin: 0 }, children: [_jsx("span", { children: "Not affiliated with LocalThunk or PlayStack" }), _jsxs("span", { style: { display: 'inline-flex', alignItems: 'center', gap: '0.25rem' }, children: ["Made with", ' ', _jsx("span", { style: { position: 'relative', display: 'inline-block', width: '1.5em', height: '1em', verticalAlign: 'middle' }, children: SUITS.map(({ char, kf }) => (_jsx("span", { style: { position: 'absolute', inset: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', opacity: 0, animationName: kf, animationDuration: CYCLE, animationDelay: '0s', animationIterationCount: 'infinite', animationTimingFunction: 'ease-out' }, children: char }, char))) }), ' ', "for the", ' ', _jsx("a", { href: "https://playbalatro.com", target: "_blank", rel: "noopener noreferrer", style: { color: JimboColorOption.GOLD, textDecoration: 'none' }, children: "Balatro" }), ' ', "community"] })] }) }), _jsx("style", { children: `
13
+ @keyframes jaml-heart { 0%{opacity:0;transform:scale(1)} 1%{opacity:1;transform:scale(1.45)} 3.5%{opacity:1;transform:scale(1)} 61.5%{opacity:1;transform:scale(1)} 62%{opacity:0} 100%{opacity:0} }
14
+ @keyframes jaml-spade { 0%,61.5%{opacity:0} 62%{opacity:1;transform:scale(1.45)} 64.5%{opacity:1;transform:scale(1)} 71.5%{opacity:1} 72%{opacity:0} 100%{opacity:0} }
15
+ @keyframes jaml-diamond { 0%,71.5%{opacity:0} 72%{opacity:1;transform:scale(1.45)} 74.5%{opacity:1;transform:scale(1)} 81.5%{opacity:1} 82%{opacity:0} 100%{opacity:0} }
16
+ @keyframes jaml-club { 0%,81.5%{opacity:0} 82%{opacity:1;transform:scale(1.45)} 84.5%{opacity:1;transform:scale(1)} 95%{opacity:1} 96%{opacity:0} 100%{opacity:0} }
17
17
  ` })] }));
18
18
  }
@@ -1,36 +1,25 @@
1
1
  import React from 'react';
2
- import { type ButtonVariant } from './tokens.js';
3
2
  export interface JimboPanelProps extends React.HTMLAttributes<HTMLDivElement> {
4
3
  sway?: boolean;
5
4
  onBack?: () => void;
6
- backLabel?: string;
7
5
  hideBack?: boolean;
8
6
  }
9
- export declare const JimboPanel: React.MemoExoticComponent<({ children, className, sway, onBack, backLabel, hideBack, style, ...props }: JimboPanelProps) => import("react/jsx-runtime").JSX.Element>;
7
+ export declare const JimboPanel: React.MemoExoticComponent<({ children, className, sway, onBack, hideBack, style, ...props }: JimboPanelProps) => import("react/jsx-runtime").JSX.Element>;
10
8
  export interface JimboInnerPanelProps extends React.HTMLAttributes<HTMLDivElement> {
11
9
  }
12
10
  export declare const JimboInnerPanel: React.MemoExoticComponent<({ children, className, style, ...props }: JimboInnerPanelProps) => import("react/jsx-runtime").JSX.Element>;
13
- export interface JimboButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
14
- variant?: ButtonVariant;
11
+ export type JimboTone = 'orange' | 'red' | 'blue' | 'green' | 'gold' | 'grey';
12
+ export interface JimboButtonProps {
13
+ tone?: JimboTone;
15
14
  size?: 'xs' | 'sm' | 'md' | 'lg';
16
15
  fullWidth?: boolean;
17
- }
18
- export declare function JimboButton({ children, variant, size, fullWidth, className, style, disabled, ...props }: JimboButtonProps): import("react/jsx-runtime").JSX.Element;
19
- export declare function JimboBackButton({ label, ...props }: Omit<JimboButtonProps, 'variant' | 'children'> & {
20
- label?: string;
21
- }): import("react/jsx-runtime").JSX.Element;
22
- export type BalTone = 'orange' | 'red' | 'blue' | 'green' | 'gold' | 'grey';
23
- export interface BalButtonProps {
24
- tone?: BalTone;
25
- size?: 'sm' | 'md' | 'lg';
26
- fullWidth?: boolean;
27
16
  disabled?: boolean;
28
17
  onClick?: () => void;
29
18
  style?: React.CSSProperties;
30
19
  children?: React.ReactNode;
31
20
  }
32
- export declare function BalButton({ tone, size, fullWidth, disabled, onClick, style, children, }: BalButtonProps): import("react/jsx-runtime").JSX.Element;
33
- export declare function BalBackButton({ onClick }: {
21
+ export declare function JimboButton({ tone, size, fullWidth, disabled, onClick, style, children, }: JimboButtonProps): import("react/jsx-runtime").JSX.Element;
22
+ export declare function JimboBackButton({ onClick }: {
34
23
  onClick?: () => void;
35
24
  }): import("react/jsx-runtime").JSX.Element;
36
25
  export interface JimboModalProps {
package/dist/ui/panel.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useRef, memo } from 'react';
4
4
  import { JimboColorOption, JIMBO_ANIMATIONS } from './tokens.js';
5
- export const JimboPanel = memo(({ children, className = '', sway = false, onBack, backLabel = 'Back', hideBack = false, style, ...props }) => {
5
+ export const JimboPanel = memo(({ children, className = '', sway = false, onBack, hideBack = false, style, ...props }) => {
6
6
  const panelRef = useRef(null);
7
7
  useEffect(() => {
8
8
  if (!sway || !panelRef.current)
@@ -23,51 +23,16 @@ export const JimboPanel = memo(({ children, className = '', sway = false, onBack
23
23
  border: `3px solid ${JimboColorOption.BORDER_SILVER}`,
24
24
  boxShadow: `0 3px 0 0 ${JimboColorOption.BORDER_SOUTH}`,
25
25
  ...style,
26
- }, ...props, children: [_jsx("div", { className: "flex-1 overflow-auto", children: children }), onBack && !hideBack && (_jsx("div", { className: "mt-4 pt-2 shrink-0", children: _jsx(JimboBackButton, { onClick: onBack, label: backLabel }) }))] }));
26
+ }, ...props, children: [_jsx("div", { className: "flex-1 overflow-auto", children: children }), onBack && !hideBack && (_jsx("div", { className: "mt-4 pt-2 shrink-0", children: _jsx(JimboBackButton, { onClick: onBack }) }))] }));
27
27
  });
28
28
  JimboPanel.displayName = 'JimboPanel';
29
29
  export const JimboInnerPanel = memo(({ children, className = '', style, ...props }) => (_jsx("div", { className: 'rounded-lg p-3 ' + className, style: { backgroundColor: JimboColorOption.INNER_BORDER, border: `2px solid ${JimboColorOption.PANEL_EDGE}`, ...style }, ...props, children: children })));
30
30
  JimboInnerPanel.displayName = 'JimboInnerPanel';
31
- // ─── Button ──────────────────────────────────────────────────────────────────
32
- const VARIANT_COLORS = {
33
- primary: { bg: JimboColorOption.RED, hover: JimboColorOption.DARK_RED, text: '#fff' },
34
- secondary: { bg: JimboColorOption.BLUE, hover: JimboColorOption.DARK_BLUE, text: '#fff' },
35
- danger: { bg: JimboColorOption.RED, hover: JimboColorOption.DARK_RED, text: '#fff' },
36
- back: { bg: JimboColorOption.ORANGE, hover: JimboColorOption.DARK_ORANGE, text: '#fff' },
37
- ghost: { bg: 'transparent', hover: 'rgba(255,255,255,0.1)', text: '#fff' },
38
- };
39
- export function JimboButton({ children, variant = 'primary', size = 'md', fullWidth = false, className = '', style, disabled, ...props }) {
40
- const [hovered, setHovered] = useState(false);
41
- const [pressed, setPressed] = useState(false);
42
- const c = VARIANT_COLORS[variant];
43
- const pad = { xs: '0.2rem 0.5rem', sm: '0.25rem 0.75rem', md: '0.375rem 1rem', lg: '0.5rem 1.5rem' }[size];
44
- return (_jsx("button", { disabled: disabled, onMouseEnter: () => { if (!disabled)
45
- setHovered(true); }, onMouseLeave: () => { setHovered(false); setPressed(false); }, onMouseDown: () => { if (!disabled)
46
- setPressed(true); }, onMouseUp: () => setPressed(false), className: className, style: {
47
- fontFamily: 'm6x11plus, monospace',
48
- backgroundColor: hovered ? c.hover : c.bg,
49
- color: c.text,
50
- padding: pad,
51
- borderRadius: '0.5rem',
52
- border: 'none',
53
- cursor: disabled ? 'not-allowed' : 'pointer',
54
- width: fullWidth ? '100%' : undefined,
55
- opacity: disabled ? 0.5 : 1,
56
- transform: pressed ? 'translateY(3px)' : 'none',
57
- boxShadow: pressed ? 'none' : '0 3px 0 0 rgba(0,0,0,0.5)',
58
- textShadow: '1px 1px 0 rgba(0,0,0,0.8)',
59
- userSelect: 'none',
60
- ...style,
61
- }, ...props, children: children }));
62
- }
63
- export function JimboBackButton({ label = 'Back', ...props }) {
64
- return _jsx(JimboButton, { variant: "back", size: "sm", fullWidth: true, ...props, children: label });
65
- }
66
- // ─── BalButton ────────────────────────────────────────────────────────────────
67
- // Canonical Balatro-style flat 2D button.
31
+ // ─── JimboButton ──────────────────────────────────────────────────────────────
32
+ // Canonical flat 2D Balatro-style button.
68
33
  // Two-layer: separate shadow div (3px south + 1px east) that disappears on press.
69
34
  // Press translates the face onto the shadow. No gradients, no hover color change.
70
- const BAL_PAIRS = {
35
+ const JIMBO_TONE_PAIRS = {
71
36
  orange: [JimboColorOption.ORANGE, JimboColorOption.DARK_ORANGE],
72
37
  red: [JimboColorOption.RED, JimboColorOption.DARK_RED],
73
38
  blue: [JimboColorOption.BLUE, JimboColorOption.DARK_BLUE],
@@ -75,11 +40,11 @@ const BAL_PAIRS = {
75
40
  gold: [JimboColorOption.GOLD, '#8a6a1e'],
76
41
  grey: [JimboColorOption.DARK_GREY, JimboColorOption.DARKEST],
77
42
  };
78
- export function BalButton({ tone = 'orange', size = 'md', fullWidth = false, disabled = false, onClick, style, children, }) {
43
+ export function JimboButton({ tone = 'orange', size = 'md', fullWidth = false, disabled = false, onClick, style, children, }) {
79
44
  const [pressed, setPressed] = useState(false);
80
- const [fg, sh] = BAL_PAIRS[tone] ?? BAL_PAIRS.orange;
81
- const pad = size === 'sm' ? '4px 10px' : size === 'lg' ? '14px 18px' : '9px 14px';
82
- const fs = size === 'sm' ? 12 : size === 'lg' ? 18 : 14;
45
+ const [fg, sh] = JIMBO_TONE_PAIRS[tone] ?? JIMBO_TONE_PAIRS.orange;
46
+ const pad = size === 'xs' ? '2px 8px' : size === 'sm' ? '4px 10px' : size === 'lg' ? '14px 18px' : '9px 14px';
47
+ const fs = size === 'xs' ? 10 : size === 'sm' ? 12 : size === 'lg' ? 18 : 14;
83
48
  return (_jsxs("div", { onMouseDown: () => { if (!disabled)
84
49
  setPressed(true); }, onMouseUp: () => setPressed(false), onMouseLeave: () => setPressed(false), onTouchStart: () => { if (!disabled)
85
50
  setPressed(true); }, onTouchEnd: () => setPressed(false), onClick: () => { if (!disabled)
@@ -93,8 +58,8 @@ export function BalButton({ tone = 'orange', size = 'md', fullWidth = false, dis
93
58
  textTransform: 'uppercase', lineHeight: 1.1,
94
59
  }, children: children })] }));
95
60
  }
96
- export function BalBackButton({ onClick }) {
97
- return (_jsx("div", { style: { display: 'flex', justifyContent: 'center', width: '100%', padding: '8px 10px 10px' }, children: _jsx(BalButton, { tone: "orange", size: "md", onClick: onClick, style: { width: '66.666%' }, children: "Back" }) }));
61
+ export function JimboBackButton({ onClick }) {
62
+ return (_jsx("div", { style: { display: 'flex', justifyContent: 'center', width: '100%', padding: '8px 10px 10px' }, children: _jsx(JimboButton, { tone: "orange", size: "md", onClick: onClick, style: { width: '66.666%' }, children: "Back" }) }));
98
63
  }
99
64
  export function JimboModal({ children, open, onClose, title, className }) {
100
65
  const [visible, setVisible] = useState(open);
@@ -112,5 +77,5 @@ export function JimboModal({ children, open, onClose, title, className }) {
112
77
  }, [open]);
113
78
  if (!visible)
114
79
  return null;
115
- return (_jsx("div", { style: { position: 'fixed', inset: 0, zIndex: 50, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '1rem', background: 'rgba(0,0,0,0.7)', opacity, transition: `opacity ${JIMBO_ANIMATIONS.MENU_SINK_DURATION}ms ease` }, onClick: onClose, children: _jsxs(JimboPanel, { sway: true, onBack: onClose, backLabel: "Close", className: 'w-full flex flex-col max-h-[90vh] ' + (className ?? 'max-w-lg'), onClick: (e) => e.stopPropagation(), children: [title && _jsx("h2", { style: { fontFamily: 'm6x11plus, monospace', color: '#fff', textAlign: 'center', margin: '0 0 1rem', fontSize: '1.25rem' }, children: title }), children] }) }));
80
+ return (_jsx("div", { style: { position: 'fixed', inset: 0, zIndex: 50, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '1rem', background: 'rgba(0,0,0,0.7)', opacity, transition: `opacity ${JIMBO_ANIMATIONS.MENU_SINK_DURATION}ms ease` }, onClick: onClose, children: _jsxs(JimboPanel, { sway: true, onBack: onClose, className: 'w-full flex flex-col max-h-[90vh] ' + (className ?? 'max-w-lg'), onClick: (e) => e.stopPropagation(), children: [title && _jsx("h2", { style: { fontFamily: 'm6x11plus, monospace', color: '#fff', textAlign: 'center', margin: '0 0 1rem', fontSize: '1.25rem' }, children: title }), children] }) }));
116
81
  }
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { JimboColorOption } from './tokens.js';
4
- import { BalButton } from './panel.js';
5
- import { BalSprite } from './sprites.js';
4
+ import { JimboButton } from './panel.js';
5
+ import { JimboSprite } from './sprites.js';
6
6
  const TONE_COLOR = {
7
7
  blue: JimboColorOption.BLUE,
8
8
  red: JimboColorOption.RED,
@@ -34,7 +34,7 @@ export function Showcase({ hotFilters = [], recentFinds = [], stats = DEFAULT_ST
34
34
  background: C.DARK_GREY, borderRadius: 6, padding: 10,
35
35
  border: `2px solid ${tColor}`, boxShadow: `0 2px 0 ${C.BLACK}`,
36
36
  display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer',
37
- }, children: [_jsx("div", { style: { display: 'flex', gap: 2 }, children: f.sample.map((name, j) => (_jsx("div", { style: { width: 30, height: 40, display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx(BalSprite, { name: name, width: 28 }) }, j))) }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: {
37
+ }, children: [_jsx("div", { style: { display: 'flex', gap: 2 }, children: f.sample.map((name, j) => (_jsx("div", { style: { width: 30, height: 40, display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx(JimboSprite, { name: name, width: 28 }) }, j))) }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: {
38
38
  fontSize: 13, color: C.WHITE, letterSpacing: 1,
39
39
  textShadow: '1px 1px 0 rgba(0,0,0,.8)',
40
40
  overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
@@ -50,5 +50,5 @@ export function Showcase({ hotFilters = [], recentFinds = [], stats = DEFAULT_ST
50
50
  }, children: recentFinds.length === 0 ? (_jsx("div", { style: { color: C.GREY }, children: "No recent finds yet." })) : recentFinds.map((r, i) => (_jsxs("div", { children: [_jsx("span", { style: { color: C.GOLD_TEXT }, children: r.seed }), ' · ', r.filterName, r.score > 0 && _jsxs("span", { style: { color: C.GREEN_TEXT }, children: [" +", r.score] })] }, i))) }), _jsx("div", { style: { height: 16 } })] }), _jsxs("div", { style: {
51
51
  padding: '8px 10px 10px', borderTop: `2px solid ${C.BLACK}`, background: C.DARK_GREY,
52
52
  display: 'flex', flexDirection: 'column', gap: 6,
53
- }, children: [_jsx(BalButton, { tone: "green", fullWidth: true, size: "md", onClick: onNewSearch, children: "New Search" }), _jsx(BalButton, { tone: "blue", fullWidth: true, size: "md", onClick: onBrowseFilters, children: "Browse Filters" }), _jsx(BalButton, { tone: "orange", fullWidth: true, size: "md", onClick: onBack, children: "Back" })] })] }));
53
+ }, children: [_jsx(JimboButton, { tone: "green", fullWidth: true, size: "md", onClick: onNewSearch, children: "New Search" }), _jsx(JimboButton, { tone: "blue", fullWidth: true, size: "md", onClick: onBrowseFilters, children: "Browse Filters" }), _jsx(JimboButton, { tone: "orange", fullWidth: true, size: "md", onClick: onBack, children: "Back" })] })] }));
54
54
  }
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import { type SpriteSheetType } from '../sprites/spriteMapper.js';
3
- export interface BalSpriteProps {
3
+ export interface JimboSpriteProps {
4
4
  name: string;
5
5
  sheet?: SpriteSheetType;
6
6
  width?: number;
7
7
  height?: number;
8
8
  style?: React.CSSProperties;
9
9
  }
10
- export declare function BalSprite({ name, sheet, width, height, style }: BalSpriteProps): import("react/jsx-runtime").JSX.Element | null;
10
+ export declare function JimboSprite({ name, sheet, width, height, style }: JimboSpriteProps): import("react/jsx-runtime").JSX.Element | null;
@@ -12,7 +12,7 @@ const SHEET_META = {
12
12
  Enhancers: { cols: 7, rows: 5, assetKey: 'enhancers' },
13
13
  Editions: { cols: 5, rows: 1, assetKey: 'editions' },
14
14
  };
15
- export function BalSprite({ name, sheet, width = 40, height, style }) {
15
+ export function JimboSprite({ name, sheet, width = 40, height, style }) {
16
16
  const sprite = getSpriteData(name);
17
17
  const resolvedSheet = sheet ?? sprite?.type ?? 'Jokers';
18
18
  const meta = SHEET_META[resolvedSheet];
package/package.json CHANGED
@@ -1,109 +1,107 @@
1
- {
2
- "name": "jaml-ui",
3
- "version": "0.6.1",
4
- "description": "Balatro rendering components, sprite metadata, and optional Motely helpers for React apps.",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
12
- },
13
- "./core": {
14
- "types": "./dist/core.d.ts",
15
- "import": "./dist/core.js"
16
- },
17
- "./motely": {
18
- "types": "./dist/motely.d.ts",
19
- "import": "./dist/motely.js"
20
- },
21
- "./ui": {
22
- "types": "./dist/ui.d.ts",
23
- "import": "./dist/ui.js"
24
- },
25
- "./r3f": {
26
- "types": "./dist/r3f.d.ts",
27
- "import": "./dist/r3f.js"
28
- },
29
- "./assets/*": "./assets/*",
30
- "./package.json": "./package.json"
31
- },
32
- "sideEffects": false,
33
- "files": [
34
- "dist",
35
- "assets",
36
- "README.md",
37
- "LICENSE"
38
- ],
39
- "scripts": {
40
- "build": "tsc --pretty false",
41
- "dev": "tsc --watch",
42
- "typecheck": "tsc --noEmit --pretty false",
43
- "prepack": "npm run build"
44
- },
45
- "engines": {
46
- "node": ">=18"
47
- },
48
- "publishConfig": {
49
- "access": "public"
50
- },
51
- "repository": {
52
- "type": "git",
53
- "url": "https://github.com/OptimusPi/jaml-ui"
54
- },
55
- "homepage": "https://github.com/OptimusPi/jaml-ui#readme",
56
- "bugs": {
57
- "url": "https://github.com/OptimusPi/jaml-ui/issues"
58
- },
59
- "keywords": [
60
- "balatro",
61
- "jaml",
62
- "motely",
63
- "seed",
64
- "card",
65
- "sprite",
66
- "ui"
67
- ],
68
- "author": "pifreak",
69
- "license": "MIT",
70
- "peerDependencies": {
71
- "@react-spring/three": ">=9.0.0",
72
- "@react-three/fiber": ">=8.0.0",
73
- "motely-wasm": "^10.2.0 || ^11.0.0 || ^12.0.0",
74
- "react": "^18.2.0 || ^19.0.0",
75
- "react-dom": "^18.2.0 || ^19.0.0",
76
- "react-icons": ">=5.0.0",
77
- "three": ">=0.150.0"
78
- },
79
- "peerDependenciesMeta": {
80
- "@react-spring/three": {
81
- "optional": true
82
- },
83
- "@react-three/fiber": {
84
- "optional": true
85
- },
86
- "motely-wasm": {
87
- "optional": true
88
- },
89
- "react-icons": {
90
- "optional": true
91
- },
92
- "three": {
93
- "optional": true
94
- }
95
- },
96
- "devDependencies": {
97
- "@react-spring/three": "^10.0.3",
98
- "@react-three/fiber": "^9.6.0",
99
- "@types/react": "^19.2.14",
100
- "@types/react-dom": "^19.2.3",
101
- "@types/three": "^0.184.0",
102
- "motely-wasm": "^12.0.0",
103
- "react": "^19.2.4",
104
- "react-dom": "^19.2.4",
105
- "react-icons": "^5.6.0",
106
- "three": "^0.184.0",
107
- "typescript": "^5.9.3"
108
- }
109
- }
1
+ {
2
+ "name": "jaml-ui",
3
+ "version": "0.7.1",
4
+ "description": "Balatro rendering components, sprite metadata, and optional Motely helpers for React apps.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./core": {
14
+ "types": "./dist/core.d.ts",
15
+ "import": "./dist/core.js"
16
+ },
17
+ "./motely": {
18
+ "types": "./dist/motely.d.ts",
19
+ "import": "./dist/motely.js"
20
+ },
21
+ "./ui": {
22
+ "types": "./dist/ui.d.ts",
23
+ "import": "./dist/ui.js"
24
+ },
25
+ "./r3f": {
26
+ "types": "./dist/r3f.d.ts",
27
+ "import": "./dist/r3f.js"
28
+ },
29
+ "./package.json": "./package.json"
30
+ },
31
+ "sideEffects": false,
32
+ "files": [
33
+ "dist",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsc --pretty false",
39
+ "dev": "tsc --watch",
40
+ "typecheck": "tsc --noEmit --pretty false",
41
+ "prepack": "npm run build"
42
+ },
43
+ "engines": {
44
+ "node": ">=18"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/OptimusPi/jaml-ui"
52
+ },
53
+ "homepage": "https://github.com/OptimusPi/jaml-ui#readme",
54
+ "bugs": {
55
+ "url": "https://github.com/OptimusPi/jaml-ui/issues"
56
+ },
57
+ "keywords": [
58
+ "balatro",
59
+ "jaml",
60
+ "motely",
61
+ "seed",
62
+ "card",
63
+ "sprite",
64
+ "ui"
65
+ ],
66
+ "author": "pifreak",
67
+ "license": "MIT",
68
+ "peerDependencies": {
69
+ "@react-spring/three": ">=9.0.0",
70
+ "@react-three/fiber": ">=8.0.0",
71
+ "motely-wasm": "^10.2.0 || ^11.0.0 || ^12.0.0",
72
+ "react": "^18.2.0 || ^19.0.0",
73
+ "react-dom": "^18.2.0 || ^19.0.0",
74
+ "react-icons": ">=5.0.0",
75
+ "three": ">=0.150.0"
76
+ },
77
+ "peerDependenciesMeta": {
78
+ "@react-spring/three": {
79
+ "optional": true
80
+ },
81
+ "@react-three/fiber": {
82
+ "optional": true
83
+ },
84
+ "motely-wasm": {
85
+ "optional": true
86
+ },
87
+ "react-icons": {
88
+ "optional": true
89
+ },
90
+ "three": {
91
+ "optional": true
92
+ }
93
+ },
94
+ "devDependencies": {
95
+ "@react-spring/three": "^10.0.3",
96
+ "@react-three/fiber": "^9.6.0",
97
+ "@types/react": "^19.2.14",
98
+ "@types/react-dom": "^19.2.3",
99
+ "@types/three": "^0.184.0",
100
+ "motely-wasm": "^12.0.0",
101
+ "react": "^19.2.4",
102
+ "react-dom": "^19.2.4",
103
+ "react-icons": "^5.6.0",
104
+ "three": "^0.184.0",
105
+ "typescript": "^5.9.3"
106
+ }
107
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
package/assets/Jokers.png DELETED
Binary file
package/assets/Tarots.png DELETED
Binary file
Binary file
Binary file
Binary file
package/assets/tags.png DELETED
Binary file