jaml-ui 0.16.0 → 0.17.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 (86) hide show
  1. package/DESIGN.md +9 -11
  2. package/dist/assets.d.ts +6 -0
  3. package/dist/assets.js +9 -0
  4. package/dist/components/AnalyzerExplorer.d.ts +4 -1
  5. package/dist/components/AnalyzerExplorer.js +14 -48
  6. package/dist/components/GameCard.js +8 -7
  7. package/dist/components/JamlAestheticSelector.d.ts +4 -0
  8. package/dist/components/JamlAestheticSelector.js +6 -19
  9. package/dist/components/JamlAnalyzerFullscreen.d.ts +7 -1
  10. package/dist/components/JamlAnalyzerFullscreen.js +18 -47
  11. package/dist/components/JamlIde.js +12 -24
  12. package/dist/components/JamlIdeVisual.js +3 -56
  13. package/dist/components/JamlMapPreview.d.ts +6 -1
  14. package/dist/components/JamlMapPreview.js +99 -21
  15. package/dist/components/JamlSeedInput.d.ts +5 -0
  16. package/dist/components/JamlSeedInput.js +11 -14
  17. package/dist/components/JamlSpeedometer.d.ts +8 -8
  18. package/dist/components/JamlSpeedometer.js +24 -46
  19. package/dist/components/MotelyVersionBadge.d.ts +1 -3
  20. package/dist/components/MotelyVersionBadge.js +4 -16
  21. package/dist/components/jamlMap/JamlMapEditorDemo.d.ts +8 -0
  22. package/dist/components/jamlMap/JamlMapEditorDemo.js +170 -0
  23. package/dist/components/jamlMap/JokerPicker.d.ts +7 -0
  24. package/dist/components/jamlMap/JokerPicker.js +258 -0
  25. package/dist/components/jamlMap/MysterySlot.d.ts +32 -0
  26. package/dist/components/jamlMap/MysterySlot.js +109 -0
  27. package/dist/components/jamlMap/index.d.ts +3 -0
  28. package/dist/components/jamlMap/index.js +3 -0
  29. package/dist/core.d.ts +0 -2
  30. package/dist/core.js +0 -2
  31. package/dist/decode/motelyItemDecoder.d.ts +10 -23
  32. package/dist/decode/motelyItemDecoder.js +103 -272
  33. package/dist/decode/motelySprite.d.ts +4 -0
  34. package/dist/decode/motelySprite.js +57 -0
  35. package/dist/hooks/analyzerStreamRegistry.js +30 -82
  36. package/dist/hooks/useAnalyzer.d.ts +10 -3
  37. package/dist/hooks/useAnalyzer.js +11 -6
  38. package/dist/hooks/useIntersectionObserver.d.ts +14 -0
  39. package/dist/hooks/useIntersectionObserver.js +50 -0
  40. package/dist/index.d.ts +5 -8
  41. package/dist/index.js +4 -7
  42. package/dist/motely.d.ts +2 -2
  43. package/dist/motely.js +2 -2
  44. package/dist/motelyDisplay.d.ts +4 -623
  45. package/dist/motelyDisplay.js +26 -165
  46. package/dist/r3f/Card3D.d.ts +2 -2
  47. package/dist/r3f/Card3D.js +13 -48
  48. package/dist/r3f/JimboText3D.js +3 -2
  49. package/dist/render/CanvasRenderer.js +7 -171
  50. package/dist/sprites/spriteMapper.d.ts +71 -0
  51. package/dist/sprites/spriteMapper.js +40 -0
  52. package/dist/ui/JimboBadge.d.ts +8 -2
  53. package/dist/ui/JimboBadge.js +6 -22
  54. package/dist/ui/JimboToggleList.js +2 -7
  55. package/dist/ui/codeBlock.js +2 -3
  56. package/dist/ui/footer.d.ts +4 -0
  57. package/dist/ui/footer.js +6 -4
  58. package/dist/ui/hooks.d.ts +89 -0
  59. package/dist/ui/hooks.js +551 -0
  60. package/dist/ui/jimboBackground.js +2 -131
  61. package/dist/ui/jimboCopyRow.d.ts +4 -0
  62. package/dist/ui/jimboCopyRow.js +5 -22
  63. package/dist/ui/jimboFilterBar.d.ts +1 -4
  64. package/dist/ui/jimboFilterBar.js +2 -61
  65. package/dist/ui/jimboFlankNav.d.ts +1 -2
  66. package/dist/ui/jimboFlankNav.js +5 -30
  67. package/dist/ui/jimboTabs.d.ts +1 -5
  68. package/dist/ui/jimboTabs.js +6 -41
  69. package/dist/ui/jimboText.d.ts +1 -1
  70. package/dist/ui/jimboText.js +15 -32
  71. package/dist/ui/jimboTooltip.d.ts +1 -12
  72. package/dist/ui/jimboTooltip.js +6 -82
  73. package/dist/ui/panel.d.ts +2 -1
  74. package/dist/ui/panel.js +11 -47
  75. package/dist/ui/showcase.d.ts +4 -0
  76. package/dist/ui/showcase.js +9 -36
  77. package/dist/ui/sprites.js +3 -2
  78. package/dist/ui.d.ts +1 -0
  79. package/dist/ui.js +2 -0
  80. package/package.json +7 -6
  81. package/dist/decode/packedBalatroItem.d.ts +0 -13
  82. package/dist/decode/packedBalatroItem.js +0 -26
  83. package/dist/hooks/loadMotelyWasm.d.ts +0 -7
  84. package/dist/hooks/loadMotelyWasm.js +0 -16
  85. package/dist/utils/itemUtils.d.ts +0 -11
  86. package/dist/utils/itemUtils.js +0 -71
@@ -1,24 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { JimboColorOption as C } from './tokens.js';
3
- export function JimboBadge({ size = 'sm', tone = 'dark', children }) {
4
- const bgColors = {
5
- dark: C.DARKEST,
6
- blue: C.BLUE,
7
- red: C.RED,
8
- green: C.GREEN,
9
- gold: C.GOLD,
10
- grey: C.GREY
11
- };
12
- return (_jsx("span", { style: {
13
- display: 'inline-flex',
14
- alignItems: 'center',
15
- padding: size === 'sm' ? '2px 6px' : '4px 8px',
16
- fontSize: size === 'sm' ? 10 : 12,
17
- background: bgColors[tone],
18
- color: tone === 'dark' || tone === 'grey' ? C.WHITE : C.DARKEST,
19
- border: `1px solid ${tone === 'dark' ? C.PANEL_EDGE : C.BLACK}`,
20
- borderRadius: 4,
21
- fontFamily: 'var(--font-sans, m6x11plus), monospace',
22
- whiteSpace: 'nowrap'
23
- }, children: children }));
2
+ /**
3
+ * Small colored label pill. Matches Balatro's in-game tag/rarity badges.
4
+ * All styling via jimbo.css `.j-badge` classes.
5
+ */
6
+ export function JimboBadge({ size = 'sm', tone = 'dark', className, children }) {
7
+ return (_jsx("span", { className: `j-badge j-badge--${size} j-badge--${tone} ${className ?? ''}`, children: children }));
24
8
  }
@@ -1,10 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { JimboPanel, JimboButton } from './panel.js';
2
+ import { JimboPanel } from './panel.js';
3
3
  export function JimboToggleList({ items, onToggle, title }) {
4
- return (_jsx(JimboPanel, { children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [title && _jsx("div", { style: { fontSize: 12, color: 'var(--c-grey)', marginBottom: 4 }, children: title }), items.map(item => (_jsxs(JimboButton, { tone: "grey", size: "sm", onClick: () => onToggle(item.id), style: { justifyContent: 'flex-start', textAlign: 'left', display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsx("div", { style: {
5
- width: 10, height: 10, flexShrink: 0,
6
- background: item.on ? 'var(--c-orange)' : 'var(--c-darkest)',
7
- border: '1px solid var(--c-dark-grey)',
8
- boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.5)'
9
- } }), item.label] }, item.id)))] }) }));
4
+ return (_jsx(JimboPanel, { children: _jsxs("div", { className: "j-toggle-list", children: [title && _jsx("div", { className: "j-toggle-list__title", children: title }), items.map(item => (_jsxs("button", { type: "button", className: "j-toggle-item", onClick: () => onToggle(item.id), children: [_jsx("div", { className: "j-toggle-check", "data-on": item.on }), item.label] }, item.id)))] }) }));
10
5
  }
@@ -1,7 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from 'react';
4
- import { JimboColorOption } from './tokens.js';
5
4
  export function JimboCodeBlock({ code, language, filename, className = '' }) {
6
5
  const [copied, setCopied] = useState(false);
7
6
  const copy = () => {
@@ -9,7 +8,7 @@ export function JimboCodeBlock({ code, language, filename, className = '' }) {
9
8
  setCopied(true);
10
9
  setTimeout(() => setCopied(false), 2000);
11
10
  };
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
11
+ return (_jsxs("div", { className: `j-code-block ${className}`, children: [_jsxs("div", { className: "j-code-block__header", children: [_jsxs("div", { className: "j-code-block__meta", children: [filename && _jsx("span", { className: "j-code-block__filename", children: filename }), language && _jsx("span", { className: "j-code-block__lang", children: language })] }), _jsx("button", { onClick: copy, title: "Copy", className: "j-code-block__copy", "data-copied": copied, children: copied
13
12
  ? _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
- : _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 }) })] }));
13
+ : _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", { className: "j-code-block__pre", children: _jsx("code", { children: code }) })] }));
15
14
  }
@@ -2,4 +2,8 @@ export interface JimboBalatroFooterProps {
2
2
  hidden?: boolean;
3
3
  className?: string;
4
4
  }
5
+ /**
6
+ * Attribution footer with animated suit cycle.
7
+ * All styling via jimbo.css `.j-footer` classes — zero inline styles.
8
+ */
5
9
  export declare function JimboBalatroFooter({ hidden, className }: JimboBalatroFooterProps): import("react/jsx-runtime").JSX.Element;
package/dist/ui/footer.js CHANGED
@@ -1,15 +1,17 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { JimboColorOption } from './tokens.js';
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
4
3
  const SUITS = [
5
4
  { char: '♥️', kf: 'jaml-heart' },
6
5
  { char: '♠️', kf: 'jaml-spade' },
7
6
  { char: '♦️', kf: 'jaml-diamond' },
8
7
  { char: '♣️', kf: 'jaml-club' },
9
8
  ];
10
- const CYCLE = '5s';
9
+ /**
10
+ * Attribution footer with animated suit cycle.
11
+ * All styling via jimbo.css `.j-footer` classes — zero inline styles.
12
+ */
11
13
  export function JimboBalatroFooter({ hidden = false, className = '' }) {
12
- return (_jsxs("div", { className: ['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: `
14
+ return (_jsxs("div", { className: `j-footer ${hidden ? 'j-footer--hidden' : ''} ${className}`, children: [_jsx("div", { className: "j-footer__bar", children: _jsxs("p", { className: "j-footer__text", children: [_jsxs("span", { children: ["Not affiliated with LocalThunk or PlayStack \u2022", ' '] }), _jsx("a", { href: "https://store.steampowered.com/app/2379780/Balatro/", target: "_blank", rel: "noopener noreferrer", className: "j-footer__link", children: "BUY BALATRO" }), _jsxs("span", { children: [' ', "\u2022 Created with", ' '] }), _jsxs("span", { className: "j-footer__suits", children: [_jsx("span", { className: "j-footer__suit-stage", children: SUITS.map(({ char, kf }) => (_jsx("span", { className: "j-footer__suit-char", style: { animationName: kf }, children: char }, char))) }), ' ', "for the Balatro community"] })] }) }), _jsx("style", { children: `
13
15
  @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
16
  @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
17
  @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} }
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+ import { JamlVisualClause, JamlVisualFilter, JamlZone } from '../components/JamlIdeVisual.js';
3
+ import { Layer } from '../render/Layer.js';
4
+ /**
5
+ * Sway animation for Balatro-style UI elements.
6
+ */
7
+ export declare function useSway(active: boolean): React.RefObject<HTMLDivElement | null>;
8
+ /**
9
+ * Handles delayed visibility for transitions (e.g. modals).
10
+ */
11
+ export declare function useDelayedVisibility(open: boolean, delay: number): {
12
+ visible: boolean;
13
+ opacity: number;
14
+ };
15
+ /**
16
+ * Hook for the Balatro hypnotic swirl background.
17
+ * Manages WebGL context, shader compilation, and animation loop.
18
+ */
19
+ export declare function useBalatroBackground(): React.RefObject<HTMLCanvasElement | null>;
20
+ export type JimboTooltipMode = 'snap' | 'mouse';
21
+ export type JimboTooltipPlacement = 'top' | 'bottom' | 'auto';
22
+ /**
23
+ * Hook for managing JimboTooltip state and positioning.
24
+ */
25
+ export declare function useJimboTooltip({ mode, placement, delay, disabled, }: {
26
+ mode?: JimboTooltipMode;
27
+ placement?: JimboTooltipPlacement;
28
+ delay?: number;
29
+ disabled?: boolean;
30
+ }): {
31
+ visible: boolean;
32
+ pos: {
33
+ left: number;
34
+ top: number;
35
+ align: "top" | "bottom";
36
+ } | null;
37
+ targetRef: React.RefObject<HTMLElement | null>;
38
+ tooltipRef: React.RefObject<HTMLDivElement | null>;
39
+ show: () => void;
40
+ hide: () => void;
41
+ handleMouseMove: (e: React.MouseEvent | React.PointerEvent) => void;
42
+ };
43
+ /**
44
+ * Hook for managing the JamlCardRenderer logic.
45
+ */
46
+ export declare function useJamlCardRenderer({ layers, invert, hoverTilt, }: {
47
+ layers: Layer[];
48
+ invert?: boolean;
49
+ hoverTilt?: boolean;
50
+ }): {
51
+ canvasRef: React.RefObject<HTMLCanvasElement | null>;
52
+ containerStyle: React.CSSProperties;
53
+ canvasStyle: React.CSSProperties;
54
+ handlers: {
55
+ onPointerEnter: ((event: React.PointerEvent) => void) | undefined;
56
+ onPointerLeave: (() => void) | undefined;
57
+ onPointerMove: ((event: React.PointerEvent<HTMLDivElement>) => void) | undefined;
58
+ };
59
+ };
60
+ /**
61
+ * Tracks which 'ante' section is currently most visible in a scrollable container.
62
+ * Used in JamlAnalyzerFullscreen and AnalyzerExplorer.
63
+ */
64
+ export declare function useAnteTracker(antes: {
65
+ ante: number;
66
+ }[], options?: {
67
+ threshold?: number[];
68
+ }): {
69
+ currentAnte: number;
70
+ scrollRef: React.RefObject<HTMLDivElement | null>;
71
+ scrollToAnte: (ante: number) => void;
72
+ registerAnteRef: (ante: number, el: HTMLElement | null) => void;
73
+ };
74
+ export interface DragState {
75
+ clause: JamlVisualClause;
76
+ fromZone: JamlZone;
77
+ x: number;
78
+ y: number;
79
+ offX: number;
80
+ offY: number;
81
+ }
82
+ /**
83
+ * Manages drag-and-drop state for the Jaml IDE visual filter editor.
84
+ */
85
+ export declare function useJamlIdeDrag(filter: JamlVisualFilter, onChange: (filter: JamlVisualFilter) => void, rootRef: React.RefObject<HTMLDivElement | null>): {
86
+ drag: DragState | null;
87
+ hoverZone: string | null;
88
+ onDragStart: (e: React.MouseEvent | React.TouchEvent, clause: JamlVisualClause, fromZone: JamlZone) => void;
89
+ };