jaml-ui 4.3.1 → 4.6.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.
Files changed (104) hide show
  1. package/assets/jammy-seed-mascot.png +0 -0
  2. package/dist/assets/8BitDeck-B09C1jGy.png +0 -0
  3. package/dist/assets/BlindChips-Bnvhn76w.png +0 -0
  4. package/dist/assets/Boosters-Bqv_YhIn.png +0 -0
  5. package/dist/assets/Editions-B3YPqPOl.png +0 -0
  6. package/dist/assets/Enhancers-DhIlUuTX.png +0 -0
  7. package/dist/assets/Jokers-1egXSFFQ.png +0 -0
  8. package/dist/assets/Tarots-DkrFk7iW.png +0 -0
  9. package/dist/assets/Vouchers-Cdp8BeSE.png +0 -0
  10. package/dist/assets/balatro-stake-chips-BdO-bw7c.png +0 -0
  11. package/dist/assets/jammy-seed-mascot-BdoW3O33.png +0 -0
  12. package/dist/assets/m6x11plus-C8RqtTtG.ttf +0 -0
  13. package/dist/assets/stickers-B6y5vEyc.png +0 -0
  14. package/dist/assets/tags-BdxcVWR4.png +0 -0
  15. package/dist/chunks/JimboSwipeDeck-DbzWak3V.js +2051 -0
  16. package/dist/chunks/JimboSwipeDeck-DbzWak3V.js.map +1 -0
  17. package/dist/chunks/spriteMapper-gImEz0wa.js +501 -0
  18. package/dist/chunks/spriteMapper-gImEz0wa.js.map +1 -0
  19. package/dist/components/DailyRitualView.d.ts +17 -0
  20. package/dist/components/DeckStakePicker.d.ts +12 -0
  21. package/dist/components/JamlIde.d.ts +9 -0
  22. package/dist/components/JamlIdeToolbar.d.ts +2 -5
  23. package/dist/components/JamlIdeVisual.d.ts +30 -0
  24. package/dist/components/JamlMapPreview.d.ts +12 -0
  25. package/dist/components/Jamlyzer.d.ts +14 -2
  26. package/dist/components/JamlyzerBulk.d.ts +5 -4
  27. package/dist/components/JamlyzerView.d.ts +1 -12
  28. package/dist/components/SeedLab.d.ts +12 -0
  29. package/dist/components/jamlSeedUtils.d.ts +1 -0
  30. package/dist/components/jamlyzer/JamlyzerAnteDetails.d.ts +4 -0
  31. package/dist/components/jamlyzer/JamlyzerErraticDeck.d.ts +2 -2
  32. package/dist/components/jamlyzer/JamlyzerPackSection.d.ts +1 -5
  33. package/dist/components/jamlyzer/JamlyzerPulls.d.ts +2 -2
  34. package/dist/components/jamlyzer/JamlyzerSeedCard.d.ts +21 -0
  35. package/dist/components/jamlyzer/JamlyzerTape.d.ts +10 -0
  36. package/dist/components/jamlyzer/highlight.d.ts +3 -3
  37. package/dist/core.js +2 -2
  38. package/dist/decode/motelyItemDecoder.d.ts +1 -0
  39. package/dist/decode/motelySprite.d.ts +10 -13
  40. package/dist/decode/motelySpriteLut.generated.d.ts +2 -0
  41. package/dist/index.d.ts +13 -1
  42. package/dist/index.js +20903 -17732
  43. package/dist/index.js.map +1 -1
  44. package/dist/json-render/JimboJsonRenderer.d.ts +21 -0
  45. package/dist/json-render/catalog.d.ts +304 -180
  46. package/dist/json-render/index.d.ts +5 -30
  47. package/dist/json-render/registry.d.ts +2 -12
  48. package/dist/lib/daily/ritual.d.ts +43 -0
  49. package/dist/lib/jaml/{parseClauses.d.ts → jaml.d.ts} +17 -13
  50. package/dist/lib/jaml/rarity.d.ts +53 -0
  51. package/dist/lib/jaml/rarityData.generated.d.ts +727 -0
  52. package/dist/ui/JimboApp.d.ts +8 -6
  53. package/dist/ui/JimboBackground.d.ts +5 -13
  54. package/dist/ui/JimboBox.d.ts +16 -0
  55. package/dist/ui/JimboButton.d.ts +1 -1
  56. package/dist/ui/JimboCanvas.d.ts +12 -0
  57. package/dist/ui/JimboDock.d.ts +21 -0
  58. package/dist/ui/JimboInline.d.ts +11 -0
  59. package/dist/ui/JimboLink.d.ts +11 -0
  60. package/dist/ui/JimboMascot.d.ts +51 -5
  61. package/dist/ui/JimboOrbitalMenu.d.ts +81 -9
  62. package/dist/ui/JimboPanelSpinner.d.ts +14 -0
  63. package/dist/ui/JimboPicker.d.ts +1 -1
  64. package/dist/ui/JimboSeedCopyChip.d.ts +1 -2
  65. package/dist/ui/JimboShopBelt.d.ts +9 -0
  66. package/dist/ui/dockTree.d.ts +31 -0
  67. package/dist/ui/hooks.d.ts +1 -1
  68. package/dist/ui/jammySeedMascotImage.d.ts +1 -1
  69. package/dist/ui/jimbo.css +1 -1
  70. package/dist/ui/orbitalLayout.d.ts +149 -0
  71. package/dist/ui/orbitalMenuStore.d.ts +70 -0
  72. package/dist/ui/tokens.d.ts +9 -36
  73. package/dist/ui/useMotionPreference.d.ts +19 -0
  74. package/dist/ui.d.ts +20 -2
  75. package/dist/ui.js +77 -30
  76. package/dist/vocab.d.ts +26 -0
  77. package/package.json +36 -40
  78. package/README.md +0 -78
  79. package/assets/fonts/README.md +0 -14
  80. package/dist/chunks/JimboSwipeDeck-D2AVuZep.js +0 -967
  81. package/dist/chunks/JimboSwipeDeck-D2AVuZep.js.map +0 -1
  82. package/dist/chunks/motelyItemDecoder-Cb-RjvQ0.js +0 -692
  83. package/dist/chunks/motelyItemDecoder-Cb-RjvQ0.js.map +0 -1
  84. package/dist/chunks/spriteMapper-Dfr2_j0_.js +0 -501
  85. package/dist/chunks/spriteMapper-Dfr2_j0_.js.map +0 -1
  86. package/dist/components/jamlyzer/JamlyzerRail.d.ts +0 -14
  87. package/dist/json-render/builders/analyzer.d.ts +0 -23
  88. package/dist/json-render/builders/encyclopedia.d.ts +0 -14
  89. package/dist/json-render/builders/search.d.ts +0 -24
  90. package/dist/json-render/components/domain.d.ts +0 -59
  91. package/dist/json-render/components/game.d.ts +0 -18
  92. package/dist/json-render/components/layout.d.ts +0 -47
  93. package/dist/json-render/components/mascot.d.ts +0 -23
  94. package/dist/json-render/components/reference.d.ts +0 -39
  95. package/dist/json-render/engine.d.ts +0 -38
  96. package/dist/json-render/knowledge/bosses.d.ts +0 -18
  97. package/dist/json-render/knowledge/decks.d.ts +0 -22
  98. package/dist/json-render/knowledge/jokers.d.ts +0 -23
  99. package/dist/json-render/knowledge/synergies.d.ts +0 -21
  100. package/dist/lib/motely/jamlParse.d.ts +0 -4
  101. package/dist/lib/motely/runtime.d.ts +0 -1
  102. package/dist/motely.d.ts +0 -4
  103. package/dist/motely.js +0 -84
  104. package/dist/motely.js.map +0 -1
@@ -0,0 +1,149 @@
1
+ export declare const FULL_CIRCLE_RAD: number;
2
+ /** Angle reserved for the pinned back/start button. Positive Y is down. */
3
+ export declare const SOUTH_ANGLE_RAD: number;
4
+ /** ~half height of an orbital pill (px) — paired with width for mascot clearance. */
5
+ export declare const PILL_HALF_H = 16;
6
+ /** Gap (px) between the mascot bitmap edge and the nearest pill corner. */
7
+ export declare const MASCOT_CLEARANCE_GAP = 10;
8
+ /** Floor width for the south button so it always reads as the primary action. */
9
+ export declare const MIN_SOUTH_WIDTH = 148;
10
+ /**
11
+ * Inset (px) from the container edge for the bottom-pinned south button.
12
+ *
13
+ * Small on purpose: Balatro's exit button is full-bleed against its modal's
14
+ * inner edge, so this is a hairline breathing gap, not a margin.
15
+ */
16
+ export declare const SOUTH_EDGE_INSET = 4;
17
+ /** Vertical breathing gap (px) between stacked pills. */
18
+ export declare const ARC_STACK_GAP = 6;
19
+ /** How far (px) the page-control centers sit above the south button's center. */
20
+ export declare const PAGE_CONTROL_LIFT = 22;
21
+ /** Distance below orbit center at which a boxless south pill is drawn. */
22
+ export declare const SOUTH_PILL_OFFSET = 8;
23
+ export interface OrbitSlot<T> {
24
+ item: T;
25
+ /** Offset from orbit center, px. */
26
+ x: number;
27
+ /** Offset from orbit center, px. Positive is down (screen coords). */
28
+ y: number;
29
+ }
30
+ /** What the layout needs to know about a pill it has not measured. */
31
+ export interface OrbitMeasure {
32
+ label: string;
33
+ hasToggleDot: boolean;
34
+ }
35
+ /**
36
+ * Estimated pill width for clamp math.
37
+ *
38
+ * Tuned for the pixel font at the `sm` button size plus its padding and the
39
+ * optional toggle dot. Deliberately an estimate — measuring every pill would
40
+ * force a layout pass per frame, and clearance only needs to be close.
41
+ */
42
+ export declare function estimatePillWidth(label: string, hasToggleDot: boolean): number;
43
+ /**
44
+ * Minimum distance from orbit center to pill center so the pill's *corner*
45
+ * clears the round mascot bitmap. Uses diagonal reach, not half-width, so pills
46
+ * at 45° don't clip.
47
+ */
48
+ export declare function minDistanceFromMascotCenter(mascotHalfPx: number, pillHalfW: number): number;
49
+ /**
50
+ * Place items on an ellipse at even angle steps, pushing outward-only when a
51
+ * slot would collide with the mascot.
52
+ *
53
+ * @param items Orbital items — the south-pinned one must already be removed.
54
+ * @param rx Horizontal orbit radius, px.
55
+ * @param ry Vertical orbit radius, px.
56
+ * @param startAngle Angle of the first slot, radians.
57
+ * @param stepRad Angle between slots, radians.
58
+ * @param mascotSizePx Mascot hit-target diameter, px.
59
+ * @param measure Label + toggle-dot presence, for width estimation.
60
+ */
61
+ export declare function layoutOrbitalEllipse<T>(items: T[], rx: number, ry: number, startAngle: number, stepRad: number, mascotSizePx: number, measure: (item: T) => OrbitMeasure): Array<OrbitSlot<T>>;
62
+ /**
63
+ * THE ORBIT LAW (pifreak, 2026-08-17). Read this before touching the geometry.
64
+ *
65
+ * The ring is NOT a circle, and treating it as one is what made it overflow on
66
+ * a short viewport. The real shape:
67
+ *
68
+ * 1. Every pill has the SAME HEIGHT. Only width varies, and it varies with
69
+ * content. So **height is the only parameter that governs overlap** —
70
+ * stack slots vertically with at least one pill-height between them and
71
+ * two pills can never collide, whatever their labels say.
72
+ * 2. Then X FLIES OUT: each pill travels away from center along its own side
73
+ * until its outer edge hits the container wall. Nothing is ever pulled
74
+ * inward toward the mascot.
75
+ * 3. The arc is bounded by the TIPS of the extra-wide south button, which
76
+ * spans nearly the full width along the bottom — so the arc runs from its
77
+ * left tip, up the left wall, across the top, and down to its right tip.
78
+ * Roughly 300°, not 360°.
79
+ *
80
+ * Why this beats the ellipse-with-clamp it replaces: an ellipse sized by
81
+ * min(boxW, boxH) wastes the width of a short-and-wide box and still needs a
82
+ * mascot-clearance push that can exceed any radius bound (measured: a 103px
83
+ * pill shoved 23px out of a 275x185 box). Height-spacing plus wall-flyout fills
84
+ * the box exactly and cannot overflow it, because the wall IS the stop
85
+ * condition — so the mascot never has to shrink to make the math work.
86
+ *
87
+ * The wall is HARD. There is deliberately no mascot-clearance push here: pills
88
+ * render above the mascot, so wall-flush X can graze the character's silhouette
89
+ * — measured up to ~25px for the widest toggle pill at his equator in the
90
+ * tightest 275px-wide phone box, ~1px for ordinary pills. That is a cosmetic
91
+ * cost paid knowingly: the character stays full-size and visible behind the
92
+ * pill, while the alternative — pushing past the wall to clear him — clips the
93
+ * pill out of the container, which is a functional bug. Never shrink the mascot
94
+ * to buy clearance; that trade was made once already and rejected.
95
+ *
96
+ * @param southTopY Y of the topmost south chrome edge (the south button, or the
97
+ * page controls when shown), relative to center, positive down.
98
+ * The arc must not descend past it.
99
+ */
100
+ export declare function layoutOrbitalArc<T>(items: T[], boxW: number, boxH: number, southTopY: number, measure: (item: T) => OrbitMeasure): Array<OrbitSlot<T>>;
101
+ /**
102
+ * How many pills a box holds on the arc without breaking the height law.
103
+ *
104
+ * The band conservatively reserves room for the page controls, so flipping from
105
+ * "fits" to "paginates" can never itself shrink the band it was measured
106
+ * against. This is the number a pager should respect: past it, show fewer items
107
+ * per page — never smaller pills, and never a smaller mascot.
108
+ */
109
+ export declare function arcPageCapacity(boxH: number): number;
110
+ /**
111
+ * Width of the south-pinned button when it rides the orbit (no box height).
112
+ *
113
+ * Sized to fill the angular gap it occupies so it reads as one wide primary
114
+ * action rather than "another pill that happens to be at the bottom", then
115
+ * clamped to the container and floored at {@link MIN_SOUTH_WIDTH}.
116
+ */
117
+ export declare function southButtonWidth(totalSlots: number, orbitRadiusX: number, containerW: number): number;
118
+ /**
119
+ * Orbit radius for a given mascot size and item count.
120
+ *
121
+ * Grows 3px per orbital item so a crowded ring breathes outward instead of
122
+ * cramming, and is floored so pills always clear the mascot.
123
+ */
124
+ export declare function orbitRadiusForCount(mascotSizePx: number, orbitalCount: number, baseRadius: number): number;
125
+ /**
126
+ * Largest orbit radius that still fits inside a boxW x boxH container.
127
+ *
128
+ * The ring is centered in its box, so only half of each dimension is available,
129
+ * and the outermost thing on the ring is not a pill *center* — it is the south
130
+ * pill's bottom edge, which sits SOUTH_PILL_OFFSET + PILL_HALF_H past the
131
+ * radius. Subtract both and the ring is guaranteed to stay inside.
132
+ *
133
+ * Why this exists: orbitRadiusForCount grows the radius with item count from a
134
+ * base derived from viewport WIDTH alone — height is never consulted. On a
135
+ * short viewport that combination puts the south pill below the bottom edge
136
+ * with no upper bound. Clamping to the box makes overflow structurally
137
+ * impossible instead of something every host has to notice and hand-tune.
138
+ */
139
+ export declare function maxOrbitRadiusForBox(boxW: number, boxH: number): number;
140
+ /**
141
+ * Clamp a desired radius to its box.
142
+ *
143
+ * The floor keeps the ring clear of the mascot: squeezing below the mascot's
144
+ * own half-size drops pills on top of the character, which reads as broken
145
+ * rather than as tight. Below that point the box is simply too small for a
146
+ * ring, and the caller should show fewer items rather than a smaller circle —
147
+ * pagination already exists for exactly that.
148
+ */
149
+ export declare function clampOrbitRadius(radius: number, mascotSizePx: number, maxRadius?: number): number;
@@ -0,0 +1,70 @@
1
+ /** Submenu push/pop: pills sink to center, the stack swaps, they rise again. */
2
+ export declare const ORBITAL_SINK_MS = 200;
3
+ /** Full close. Must match the `.j-orbital-pill` transition in jimbo.css. */
4
+ export declare const ORBITAL_CLOSE_MS = 320;
5
+ export interface JimboOrbitalState {
6
+ /** Menu path. Empty = closed. `["main"]` = root open. */
7
+ stack: string[];
8
+ /** Zero-based page within the current menu, for menus past the page size. */
9
+ page: number;
10
+ /** Submenu labels pushed so far, for a breadcrumb. */
11
+ breadcrumb: string[];
12
+ /** Mid-animation: pills are collapsing to center. */
13
+ closing: boolean;
14
+ }
15
+ export interface JimboOrbitalStore {
16
+ subscribe: (listener: () => void) => () => void;
17
+ getState: () => JimboOrbitalState;
18
+ open: (root?: string) => void;
19
+ close: () => void;
20
+ back: () => void;
21
+ navigateTo: (submenuLabel: string) => void;
22
+ nextPage: (totalPages: number) => void;
23
+ prevPage: (totalPages: number) => void;
24
+ reset: () => void;
25
+ /**
26
+ * "Get out of the way — something arrived."
27
+ *
28
+ * Auto-closes the menu when background work produces a result worth looking
29
+ * at, so the user isn't left staring at a submenu over fresh content. In
30
+ * JAMMY this was seed-search results and `topScore` was the seed score; any
31
+ * monotonically-improving quality metric works, and it is optional.
32
+ *
33
+ * Two independent triggers:
34
+ * - a new *best* score closes a submenu (depth > 1) but leaves root open
35
+ * - simply *more* results than last time closes any open menu
36
+ */
37
+ signalIncomingResults: (results: {
38
+ count: number;
39
+ topScore?: number;
40
+ }) => void;
41
+ }
42
+ export declare function createJimboOrbitalStore(): JimboOrbitalStore;
43
+ /** Shared store — the common case, one mascot per app. */
44
+ export declare const jimboOrbitalStore: JimboOrbitalStore;
45
+ export interface JimboOrbitalMenuController extends JimboOrbitalState {
46
+ /** Top of the stack, or `root` when closed. */
47
+ currentMenu: string;
48
+ /** The ring should be mounted. */
49
+ isOpen: boolean;
50
+ /** Pills should be animating toward center. */
51
+ isClosing: boolean;
52
+ /** The stack is deep enough that the south button means "back", not "exit". */
53
+ canGoBack: boolean;
54
+ open: () => void;
55
+ close: () => void;
56
+ back: () => void;
57
+ navigateTo: (submenuLabel: string) => void;
58
+ nextPage: (totalPages: number) => void;
59
+ prevPage: (totalPages: number) => void;
60
+ /** The single tap target: closed → open, open → close. */
61
+ toggle: () => void;
62
+ }
63
+ export interface UseJimboOrbitalMenuProps {
64
+ /** Root menu name. A welcome screen might open to `"welcome"` instead. */
65
+ root?: string;
66
+ /** Use a private store instead of the shared one. */
67
+ store?: JimboOrbitalStore;
68
+ }
69
+ /** Controller for {@link JimboOrbitalMenu} — stack, pagination, close animation. */
70
+ export declare function useJimboOrbitalMenu({ root, store, }?: UseJimboOrbitalMenuProps): JimboOrbitalMenuController;
@@ -1,12 +1,7 @@
1
1
  /**
2
- * Balatro design tokens — JS mirror of src/ui/jimbo-tokens.css :root.
3
- *
4
- * CSS custom properties (--j-*) are the source of truth for DOM.
5
- * Keep every hex here in lockstep with jimbo-tokens.css.
6
- * Do NOT replace with Lua HEX values; the game's shader pipeline transforms them.
7
- *
8
- * Use these JS constants only where CSS vars cannot apply — Canvas, SVG fills,
9
- * CodeMirror themes, or imperative animation APIs.
2
+ * JS mirror of jimbo-tokens.css :root hex.
3
+ * CSS vars win on DOM. Use these for Canvas, SVG, CodeMirror.
4
+ * Post-shader eyedrops — not Lua G.C.
10
5
  */
11
6
  export declare const JimboColorOption: {
12
7
  readonly RED: "#fe5148";
@@ -15,6 +10,8 @@ export declare const JimboColorOption: {
15
10
  readonly ORANGE: "#ff9800";
16
11
  readonly GOLD: "#e4b643";
17
12
  readonly PURPLE: "#9e74ce";
13
+ readonly PLANET: "#00a7ca";
14
+ readonly SPECTRAL: "#2e76fd";
18
15
  readonly DARK_RED: "#a02721";
19
16
  readonly DARK_BLUE: "#0057a1";
20
17
  readonly DARK_ORANGE: "#a05b00";
@@ -29,42 +26,18 @@ export declare const JimboColorOption: {
29
26
  readonly INNER_BORDER: "#334461";
30
27
  readonly BORDER_SILVER: "#b9c2d2";
31
28
  readonly BORDER_SOUTH: "#777e89";
32
- readonly GOLD_TEXT: "#e4b643";
33
29
  readonly GREEN_TEXT: "#35bd86";
34
- readonly ORANGE_TEXT: "#ff8f00";
35
30
  readonly WHITE: "#ffffff";
36
31
  readonly BLACK: "#000000";
37
- readonly TAROT_BUTTON: "#9e74ce";
38
- readonly PLANET_BUTTON: "#00a7ca";
39
- readonly SPECTRAL_BUTTON: "#2e76fd";
40
- readonly TAROT_BUTTON_DARK: "#5e437e";
41
- readonly PLANET_BUTTON_DARK: "#00657c";
42
- readonly SPECTRAL_BUTTON_DARK: "#14449e";
32
+ /** Same decision as GOLD — kept so CodeMirror / old callers don't grow a second gold. */
33
+ readonly GOLD_TEXT: "#e4b643";
43
34
  };
44
35
  export type JimboPaletteColor = keyof typeof JimboColorOption;
45
- /** Convert hex to rgba for inline styles in Canvas/SVG/R3F contexts. */
46
36
  export declare function withAlpha(hex: string, alpha: number): string;
47
- /**
48
- * Motion mirrors engine/moveable.lua juice_up defaults (amount 0.4, ~0.4s)
49
- * and press lip on UI buttons — solid south edge, not soft elevation blur.
50
- */
37
+ /** Juice / sway used by JS motion. Press lip lives in CSS (--j-press-y). */
51
38
  export declare const JIMBO_ANIMATIONS: {
52
39
  readonly JUICE_UP_SCALE: 1.05;
53
- readonly JUICE_DOWN_SCALE: 1;
54
- /** Lua juice_up end_time ≈ start + 0.4s */
55
- readonly JUICE_DURATION: 400;
56
- readonly JUICE_AMOUNT: 0.4;
57
- readonly JUICE_EASING: "cubic-bezier(0.34, 1.56, 0.64, 1)";
58
- /** Lua zoom hover bonus */
59
- readonly HOVER_SCALE: 1.05;
40
+ readonly JUICE_EASING: "cubic-bezier(0.16, 1, 0.3, 1)";
60
41
  readonly SWAY_AMOUNT: 1.5;
61
42
  readonly SWAY_DURATION: 4000;
62
- readonly PRESS_TRANSLATE_Y: 2;
63
- readonly PRESS_DURATION: 55;
64
- readonly CARD_TILT_MAX: 6;
65
- readonly MENU_SINK_DURATION: 200;
66
- readonly MENU_RISE_DURATION: 300;
67
- readonly MENU_ORBIT_DURATION: 320;
68
- readonly LETTER_POP_RATE: 3;
69
- readonly LETTER_BUMP_RATE: 2.666;
70
43
  };
@@ -0,0 +1,19 @@
1
+ export type JimboMotionSetting = 'auto' | 'full' | 'reduced';
2
+ /**
3
+ * A real, user-settable motion preference — not a silent one-way OS override.
4
+ *
5
+ * `setting` starts as `'auto'` (follows the OS prefers-reduced-motion signal, same
6
+ * as before) but a user's explicit `'full'` or `'reduced'` choice always wins over
7
+ * the OS, in both directions: someone can ask for full tactile motion even with the
8
+ * OS set to reduce, or ask for reduced motion even when the OS says nothing. The
9
+ * choice persists across visits via localStorage.
10
+ *
11
+ * Writes the `data-j-motion` attribute on <html>, which jimbo-tokens.css and
12
+ * jimbo.css both key off — see the motion-setting block in jimbo-tokens.css.
13
+ */
14
+ export declare function useMotionPreference(): {
15
+ setting: JimboMotionSetting;
16
+ setSetting: (next: JimboMotionSetting) => void;
17
+ osPrefersReduced: boolean;
18
+ effectiveReducedMotion: boolean;
19
+ };
package/dist/ui.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export * from './ui/tokens.js';
2
+ export { useMotionPreference, type JimboMotionSetting } from './ui/useMotionPreference.js';
2
3
  export { JimboButton, type JimboButtonProps } from './ui/JimboButton.js';
3
4
  export { JimboTextArea, type JimboTextAreaProps } from './ui/JimboTextArea.js';
4
5
  export { JimboPanel, type JimboPanelProps } from './ui/JimboPanel.js';
5
- export { JimboBackground } from './ui/JimboBackground.js';
6
+ export { JimboBackground, type JimboBackgroundConfig } from './ui/JimboBackground.js';
6
7
  export { JimboApp, type JimboAppProps, type JimboAppVariant } from './ui/JimboApp.js';
7
8
  export { JimboInset, type JimboInsetProps } from './ui/JimboInset.js';
8
9
  export { JimboWordmark, type JimboWordmarkProps } from './ui/JimboWordmark.js';
@@ -17,10 +18,27 @@ export { JimboDivider, type JimboDividerProps } from './ui/JimboDivider.js';
17
18
  export { JimboStatusPill, type JimboStatusPillProps, type JimboStatus } from './ui/JimboStatusPill.js';
18
19
  export { JimboErrorBlock, type JimboErrorBlockProps } from './ui/JimboErrorBlock.js';
19
20
  export { JimboMascot, type JimboMascotProps } from './ui/JimboMascot.js';
20
- export { JimboOrbitalMenu, type JimboOrbitalMenuProps, type JimboOrbitalMenuItem, } from './ui/JimboOrbitalMenu.js';
21
+ export { JimboOrbitalMenu, type JimboOrbitalMenuProps, type JimboOrbitalMenuItem, type JimboOrbitalTone, } from './ui/JimboOrbitalMenu.js';
22
+ export { useJimboOrbitalMenu, createJimboOrbitalStore, jimboOrbitalStore, ORBITAL_CLOSE_MS, ORBITAL_SINK_MS, type JimboOrbitalState, type JimboOrbitalStore, type JimboOrbitalMenuController, type UseJimboOrbitalMenuProps, } from './ui/orbitalMenuStore.js';
23
+ export { layoutOrbitalArc, layoutOrbitalEllipse, arcPageCapacity, clampOrbitRadius, estimatePillWidth, maxOrbitRadiusForBox, minDistanceFromMascotCenter, orbitRadiusForCount, southButtonWidth, ARC_STACK_GAP, FULL_CIRCLE_RAD, MASCOT_CLEARANCE_GAP, MIN_SOUTH_WIDTH, PAGE_CONTROL_LIFT, PILL_HALF_H, SOUTH_ANGLE_RAD, SOUTH_EDGE_INSET, SOUTH_PILL_OFFSET, type OrbitSlot, type OrbitMeasure, } from './ui/orbitalLayout.js';
21
24
  export { JimboSeedCopyChip, type JimboSeedCopyChipProps } from './ui/JimboSeedCopyChip.js';
22
25
  export { JimboSpinner, type JimboSpinnerProps } from './ui/JimboSpinner.js';
26
+ export { JimboPanelSpinner, type JimboPanelSpinnerProps } from './ui/JimboPanelSpinner.js';
23
27
  export { JimboTextInput, type JimboTextInputProps } from './ui/JimboTextInput.js';
24
28
  export { JimboInnerPanel, type JimboInnerPanelProps, JimboModal, type JimboModalProps } from './ui/panel.js';
25
29
  export { JimboOuterTab, type JimboOuterTabProps, type JimboOuterTabTone } from './ui/JimboOuterTab.js';
30
+ export { JimboDock, type JimboDockProps, type JimboDockPane, defaultPyramidDock, dockActivate, type DockNode, } from './ui/JimboDock.js';
31
+ export { JimboBox, type JimboBoxProps } from './ui/JimboBox.js';
32
+ export { JimboInline, type JimboInlineProps } from './ui/JimboInline.js';
33
+ export { JimboCanvas, type JimboCanvasProps } from './ui/JimboCanvas.js';
34
+ export { JimboLink, type JimboLinkProps } from './ui/JimboLink.js';
35
+ export { JimboListItem, type JimboListItemProps } from './ui/JimboListItem.js';
36
+ export { JimboInlineEdit, type JimboInlineEditProps, type JimboInlineEditSize, type JimboInlineEditTone, } from './ui/JimboInlineEdit.js';
37
+ export { JimboPicker, JimboPickerSection, JimboPickerSearch, JimboPickerHint, JimboPickerGrid, type JimboPickerGridProps, JimboPickerItem, type JimboPickerItemProps, JimboPickerPair, JimboPickerEmpty, } from './ui/JimboPicker.js';
38
+ export { JimboCodeSurface, type JimboCodeSurfaceProps } from './ui/JimboCodeSurface.js';
39
+ export { JimboFlankNav, type JimboFlankNavProps } from './ui/jimboFlankNav.js';
40
+ export { JimboTabs, type JimboTabsProps, type JimboTabDef } from './ui/jimboTabs.js';
41
+ export { JimboSprite, type JimboSpriteProps } from './ui/sprites.js';
26
42
  export { JimboSwipeDeck, type JimboSwipeDeckProps } from './ui/JimboSwipeDeck.js';
43
+ export { JimboShopBelt, type JimboShopBeltProps } from './ui/JimboShopBelt.js';
44
+ export { type JimboTone } from './ui/panel.js';
package/dist/ui.js CHANGED
@@ -1,35 +1,82 @@
1
1
  "use client";
2
- import { J as i, a as s, b, c as m, d as J, e, f as t, g as r, h as n, i as p, j as l, k as c, l as d, m as u, n as S, o as B, p as I, q as k, r as A, s as x, t as M, u as O, v as T, w as h, x as w, y as C, z as g, A as P, B as f, C as v } from "./chunks/JimboSwipeDeck-D2AVuZep.js";
2
+ import { A as s, F as o, J as e, a as b, b as m, c as t, d as r, e as J, f as n, g as c, h as l, i as S, j as O, k as _, l as P, m as u, n as A, o as I, p as d, q as k, r as T, s as p, t as C, u as L, v as E, w as B, x as M, y as R, z as h, B as D, C as F, D as H, E as N, G as x, H as G, I as y, K as f, L as U, M as g, N as v, O as W, P as w, Q as j, R as K, S as q, T as z, U as Q, V, W as X, X as Y, Y as Z, Z as $, _ as aa, $ as ia, a0 as sa, a1 as oa, a2 as ea, a3 as ba, a4 as ma, a5 as ta, a6 as ra, a7 as Ja, a8 as na, a9 as ca, aa as la, ab as Sa, ac as Oa, ad as _a, ae as Pa, af as ua, ag as Aa, ah as Ia, ai as da, aj as ka, ak as Ta, al as pa, am as Ca } from "./chunks/JimboSwipeDeck-DbzWak3V.js";
3
3
  export {
4
- i as JIMBO_ANIMATIONS,
5
- s as JimboApp,
6
- b as JimboBackground,
7
- m as JimboBadge,
4
+ s as ARC_STACK_GAP,
5
+ o as FULL_CIRCLE_RAD,
6
+ e as JIMBO_ANIMATIONS,
7
+ b as JimboApp,
8
+ m as JimboBackground,
9
+ t as JimboBadge,
10
+ r as JimboBox,
8
11
  J as JimboButton,
9
- e as JimboColorOption,
10
- t as JimboDivider,
11
- r as JimboErrorBlock,
12
- n as JimboGrid,
13
- p as JimboIconButton,
14
- l as JimboInnerPanel,
15
- c as JimboInset,
16
- d as JimboMascot,
17
- u as JimboModal,
18
- S as JimboOrbitalMenu,
19
- B as JimboOuterTab,
20
- I as JimboPanel,
21
- k as JimboRow,
22
- A as JimboSectionHeader,
23
- x as JimboSeedCopyChip,
24
- M as JimboSpacer,
25
- O as JimboSpinner,
26
- T as JimboStack,
27
- h as JimboStatusPill,
28
- w as JimboSwipeDeck,
29
- C as JimboText,
30
- g as JimboTextArea,
31
- P as JimboTextInput,
32
- f as JimboWordmark,
33
- v as withAlpha
12
+ n as JimboCanvas,
13
+ c as JimboCodeSurface,
14
+ l as JimboColorOption,
15
+ S as JimboDivider,
16
+ O as JimboDock,
17
+ _ as JimboErrorBlock,
18
+ P as JimboFlankNav,
19
+ u as JimboGrid,
20
+ A as JimboIconButton,
21
+ I as JimboInline,
22
+ d as JimboInlineEdit,
23
+ k as JimboInnerPanel,
24
+ T as JimboInset,
25
+ p as JimboLink,
26
+ C as JimboListItem,
27
+ L as JimboMascot,
28
+ E as JimboModal,
29
+ B as JimboOrbitalMenu,
30
+ M as JimboOuterTab,
31
+ R as JimboPanel,
32
+ h as JimboPanelSpinner,
33
+ D as JimboPicker,
34
+ F as JimboPickerEmpty,
35
+ H as JimboPickerGrid,
36
+ N as JimboPickerHint,
37
+ x as JimboPickerItem,
38
+ G as JimboPickerPair,
39
+ y as JimboPickerSearch,
40
+ f as JimboPickerSection,
41
+ U as JimboRow,
42
+ g as JimboSectionHeader,
43
+ v as JimboSeedCopyChip,
44
+ W as JimboShopBelt,
45
+ w as JimboSpacer,
46
+ j as JimboSpinner,
47
+ K as JimboSprite,
48
+ q as JimboStack,
49
+ z as JimboStatusPill,
50
+ Q as JimboSwipeDeck,
51
+ V as JimboTabs,
52
+ X as JimboText,
53
+ Y as JimboTextArea,
54
+ Z as JimboTextInput,
55
+ $ as JimboWordmark,
56
+ aa as MASCOT_CLEARANCE_GAP,
57
+ ia as MIN_SOUTH_WIDTH,
58
+ sa as ORBITAL_CLOSE_MS,
59
+ oa as ORBITAL_SINK_MS,
60
+ ea as PAGE_CONTROL_LIFT,
61
+ ba as PILL_HALF_H,
62
+ ma as SOUTH_ANGLE_RAD,
63
+ ta as SOUTH_EDGE_INSET,
64
+ ra as SOUTH_PILL_OFFSET,
65
+ Ja as arcPageCapacity,
66
+ na as clampOrbitRadius,
67
+ ca as createJimboOrbitalStore,
68
+ la as defaultPyramidDock,
69
+ Sa as dockActivate,
70
+ Oa as estimatePillWidth,
71
+ _a as jimboOrbitalStore,
72
+ Pa as layoutOrbitalArc,
73
+ ua as layoutOrbitalEllipse,
74
+ Aa as maxOrbitRadiusForBox,
75
+ Ia as minDistanceFromMascotCenter,
76
+ da as orbitRadiusForCount,
77
+ ka as southButtonWidth,
78
+ Ta as useJimboOrbitalMenu,
79
+ pa as useMotionPreference,
80
+ Ca as withAlpha
34
81
  };
35
82
  //# sourceMappingURL=ui.js.map
@@ -0,0 +1,26 @@
1
+ /** Joker rarity as the engine models it. */
2
+ export type JokerRarityName = "Common" | "Uncommon" | "Rare" | "Legendary";
3
+ /**
4
+ * Engine keys are PascalCase ids ("GreedyJoker"); sprite sheets use spaced
5
+ * display names ("Greedy Joker"). Both collapse to lowercase-alphanumeric so
6
+ * they can be compared.
7
+ */
8
+ export declare const normalizeItemName: (name: string) => string;
9
+ /** Normalize a display name into its engine-comparable key. */
10
+ export declare const engineKey: (name: string) => string;
11
+ export declare const COMMON_JOKER_KEYS: ReadonlySet<string>;
12
+ export declare const UNCOMMON_JOKER_KEYS: ReadonlySet<string>;
13
+ export declare const RARE_JOKER_KEYS: ReadonlySet<string>;
14
+ /**
15
+ * Legendaries are the full joker set minus the three named tiers — the engine
16
+ * ships no legendary-name enum. If a future engine adds a fifth rarity, those
17
+ * jokers would silently land here; `check-vocab-drift.mjs` asserts the tier
18
+ * counts still partition the full list so that shows up as a CI failure.
19
+ */
20
+ export declare const LEGENDARY_JOKER_KEYS: ReadonlySet<string>;
21
+ /** Rarity tier for a joker, by engine key or sprite display name. */
22
+ export declare function jokerRarityOf(name: string): JokerRarityName;
23
+ /** True when the name is one of the engine's legendary jokers. */
24
+ export declare const isLegendaryJokerName: (name: string) => boolean;
25
+ /** The JAML clause discriminator that scopes a search to this rarity. */
26
+ export declare function rarityClauseKey(rarity: JokerRarityName): string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jaml-ui",
3
- "version": "4.3.1",
4
- "description": "Zero-dependency json-render engine + Balatro card sprites for MCP Apps.",
3
+ "version": "4.6.0",
4
+ "description": "Balatro card sprites and the Jimbo design system for MCP Apps, with a @json-render (Vercel Labs) catalog.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -18,10 +18,6 @@
18
18
  "types": "./dist/core.d.ts",
19
19
  "default": "./dist/core.js"
20
20
  },
21
- "./motely": {
22
- "types": "./dist/motely.d.ts",
23
- "default": "./dist/motely.js"
24
- },
25
21
  "./jimbo.css": "./dist/ui/jimbo.css",
26
22
  "./fonts.css": "./fonts.css",
27
23
  "./assets/*": "./assets/*"
@@ -39,26 +35,9 @@
39
35
  "README.md",
40
36
  "LICENSE"
41
37
  ],
42
- "scripts": {
43
- "build": "vite build",
44
- "dev": "storybook dev",
45
- "dev:watch": "vite build --watch",
46
- "jaml:mcp": "node scripts/jaml-mcp-server.mjs",
47
- "typecheck": "tsc --noEmit --pretty false",
48
- "typecheck:all": "pnpm typecheck && pnpm -r --if-present run typecheck",
49
- "prepack": "npm run build",
50
- "storybook": "pnpm run build && storybook dev -p 3141",
51
- "build-storybook": "pnpm run build && storybook build",
52
- "lint": "eslint ."
53
- },
54
38
  "engines": {
55
39
  "node": ">=18"
56
40
  },
57
- "pnpm": {
58
- "onlyBuiltDependencies": [
59
- "esbuild"
60
- ]
61
- },
62
41
  "publishConfig": {
63
42
  "access": "public"
64
43
  },
@@ -84,43 +63,60 @@
84
63
  "author": "pifreak",
85
64
  "license": "MIT",
86
65
  "dependencies": {
66
+ "@json-render/core": "^0.20.0",
67
+ "@json-render/react": "^0.20.0",
87
68
  "jaml-lang": "^3.14.2",
88
69
  "react-icons": "^5.7.0",
89
- "yaml": "^2.9.0"
70
+ "zod": "^4.5.4"
90
71
  },
91
72
  "peerDependencies": {
92
- "motely-wasm": "^25.0.0",
73
+ "motely-wasm": "^25.1.0",
93
74
  "react": "^18.2.0 || ^19.0.0",
94
75
  "react-dom": "^18.2.0 || ^19.0.0"
95
76
  },
96
77
  "devDependencies": {
97
78
  "@codemirror/autocomplete": "^6.20.3",
98
- "@codemirror/commands": "^6.10.4",
79
+ "@codemirror/commands": "^6.11.0",
99
80
  "@codemirror/language": "^6.12.4",
100
81
  "@codemirror/lint": "^6.9.7",
101
- "@codemirror/state": "^6.7.1",
102
- "@codemirror/view": "^6.43.7",
82
+ "@codemirror/state": "^6.7.2",
83
+ "@codemirror/view": "^6.43.10",
103
84
  "@eslint/js": "^10.0.1",
104
85
  "@lezer/highlight": "^1.2.3",
105
- "@storybook/addon-docs": "^10.5.5",
106
- "@storybook/react": "^10.5.5",
107
- "@storybook/react-vite": "^10.5.5",
86
+ "@storybook/addon-docs": "^10.5.10",
87
+ "@storybook/react": "^10.5.10",
88
+ "@storybook/react-vite": "^10.5.10",
108
89
  "@types/node": "^25.9.5",
109
- "@types/react": "^19.2.17",
110
- "@types/react-dom": "^19.2.3",
90
+ "@types/react": "^19.2.18",
91
+ "@types/react-dom": "^19.2.5",
111
92
  "@vitejs/plugin-react": "^5.2.0",
112
- "eslint": "^10.8.0",
93
+ "eslint": "^10.9.1",
113
94
  "eslint-plugin-react-hooks": "^7.1.1",
114
- "eslint-plugin-react-refresh": "^0.5.3",
95
+ "eslint-plugin-react-refresh": "^0.5.5",
115
96
  "eslint-plugin-storybook": "10.4.6",
116
- "globals": "^17.8.0",
117
- "motely-wasm": "25.0.3",
97
+ "globals": "^17.11.0",
98
+ "motely-wasm": "25.1.0",
118
99
  "react": "^19.2.8",
119
100
  "react-dom": "^19.2.8",
120
- "storybook": "^10.5.5",
101
+ "storybook": "^10.5.10",
121
102
  "typescript": "^5.9.3",
122
- "typescript-eslint": "^8.65.0",
103
+ "typescript-eslint": "^8.69.0",
123
104
  "vite": "^6.4.3",
124
105
  "vite-plugin-dts": "^5.0.3"
106
+ },
107
+ "scripts": {
108
+ "build": "vite build",
109
+ "dev": "storybook dev",
110
+ "dev:watch": "vite build --watch",
111
+ "jaml:mcp": "node scripts/jaml-mcp-server.mjs",
112
+ "typecheck": "tsc --noEmit --pretty false",
113
+ "vocab:check": "node --experimental-strip-types scripts/check-vocab-drift.mjs",
114
+ "lut:emit": "node scripts/emit-motely-sprite-lut.mjs",
115
+ "typecheck:all": "pnpm typecheck && pnpm -r --if-present run typecheck",
116
+ "storybook": "pnpm run build && storybook dev -p 3141",
117
+ "build-storybook": "pnpm run build && storybook build",
118
+ "lint": "eslint .",
119
+ "design:detect": "node .agents/skills/impeccable/scripts/detect.mjs --json src",
120
+ "design:doctor": "node .agents/skills/impeccable/scripts/doctor.mjs"
125
121
  }
126
- }
122
+ }