jaml-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +110 -0
- package/assets/8BitDeck.png +0 -0
- package/assets/BlindChips.png +0 -0
- package/assets/Boosters.png +0 -0
- package/assets/Editions.png +0 -0
- package/assets/Enhancers.png +0 -0
- package/assets/Jokers.png +0 -0
- package/assets/Tarots.png +0 -0
- package/assets/Vouchers.png +0 -0
- package/assets/stickers.png +0 -0
- package/assets/tags.png +0 -0
- package/dist/assets.d.ts +18 -0
- package/dist/assets.js +66 -0
- package/dist/components/CardList.d.ts +8 -0
- package/dist/components/CardList.js +5 -0
- package/dist/components/GameCard.d.ts +52 -0
- package/dist/components/GameCard.js +351 -0
- package/dist/components/PlayingCard.d.ts +18 -0
- package/dist/components/PlayingCard.js +115 -0
- package/dist/core.d.ts +7 -0
- package/dist/core.js +7 -0
- package/dist/decode/motelyItemDecoder.d.ts +23 -0
- package/dist/decode/motelyItemDecoder.js +71 -0
- package/dist/decode/packedBalatroItem.d.ts +13 -0
- package/dist/decode/packedBalatroItem.js +26 -0
- package/dist/hooks/useShopStream.d.ts +22 -0
- package/dist/hooks/useShopStream.js +82 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/motely.d.ts +1 -0
- package/dist/motely.js +2 -0
- package/dist/render/CanvasRenderer.d.ts +7 -0
- package/dist/render/CanvasRenderer.js +147 -0
- package/dist/render/Layer.d.ts +29 -0
- package/dist/render/Layer.js +18 -0
- package/dist/sprites/spriteData.d.ts +57 -0
- package/dist/sprites/spriteData.js +99 -0
- package/dist/sprites/spriteMapper.d.ts +11 -0
- package/dist/sprites/spriteMapper.js +42 -0
- package/dist/utils/gameCardUtils.d.ts +12 -0
- package/dist/utils/gameCardUtils.js +49 -0
- package/dist/utils/itemUtils.d.ts +11 -0
- package/dist/utils/itemUtils.js +71 -0
- package/package.json +72 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprite sheet position data for all Balatro game elements.
|
|
3
|
+
* Extracted from Blueprint's const.ts — maps item names to {x, y} grid positions
|
|
4
|
+
* within their respective sprite sheets.
|
|
5
|
+
*/
|
|
6
|
+
import { JAML_ASSET_FILES, resolveJamlAssetUrl } from "../assets.js";
|
|
7
|
+
function defineSpriteSheet(asset, columns, rows) {
|
|
8
|
+
return {
|
|
9
|
+
asset,
|
|
10
|
+
fileName: JAML_ASSET_FILES[asset],
|
|
11
|
+
columns,
|
|
12
|
+
rows,
|
|
13
|
+
get src() {
|
|
14
|
+
return resolveJamlAssetUrl(asset);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Sprite sheet grid dimensions */
|
|
19
|
+
export const SPRITE_SHEETS = {
|
|
20
|
+
jokers: defineSpriteSheet("jokers", 10, 16),
|
|
21
|
+
tarots: defineSpriteSheet("tarots", 10, 6),
|
|
22
|
+
deck: defineSpriteSheet("deck", 13, 4),
|
|
23
|
+
enhancers: defineSpriteSheet("enhancers", 7, 5),
|
|
24
|
+
editions: defineSpriteSheet("editions", 5, 1),
|
|
25
|
+
stickers: defineSpriteSheet("stickers", 5, 3),
|
|
26
|
+
blinds: defineSpriteSheet("blinds", 21, 31),
|
|
27
|
+
vouchers: defineSpriteSheet("vouchers", 9, 4),
|
|
28
|
+
tags: defineSpriteSheet("tags", 6, 5),
|
|
29
|
+
boosters: defineSpriteSheet("boosters", 4, 9),
|
|
30
|
+
};
|
|
31
|
+
export const JOKERS = [
|
|
32
|
+
{ name: "Joker", pos: { x: 0, y: 0 } }, { name: "Greedy Joker", pos: { x: 6, y: 1 } }, { name: "Lusty Joker", pos: { x: 7, y: 1 } }, { name: "Wrathful Joker", pos: { x: 8, y: 1 } }, { name: "Gluttonous Joker", pos: { x: 9, y: 1 } }, { name: "Jolly Joker", pos: { x: 2, y: 0 } }, { name: "Zany Joker", pos: { x: 3, y: 0 } }, { name: "Mad Joker", pos: { x: 4, y: 0 } }, { name: "Crazy Joker", pos: { x: 5, y: 0 } }, { name: "Droll Joker", pos: { x: 6, y: 0 } }, { name: "Sly Joker", pos: { x: 0, y: 14 } }, { name: "Wily Joker", pos: { x: 1, y: 14 } }, { name: "Clever Joker", pos: { x: 2, y: 14 } }, { name: "Devious Joker", pos: { x: 3, y: 14 } }, { name: "Crafty Joker", pos: { x: 4, y: 14 } }, { name: "Half Joker", pos: { x: 7, y: 0 } }, { name: "Joker Stencil", pos: { x: 2, y: 5 } }, { name: "Four Fingers", pos: { x: 6, y: 6 } }, { name: "Mime", pos: { x: 4, y: 1 } }, { name: "Credit Card", pos: { x: 5, y: 1 } }, { name: "Ceremonial Dagger", pos: { x: 5, y: 5 } }, { name: "Banner", pos: { x: 1, y: 2 } }, { name: "Mystic Summit", pos: { x: 2, y: 2 } }, { name: "Marble Joker", pos: { x: 3, y: 2 } }, { name: "Loyalty Card", pos: { x: 4, y: 2 } }, { name: "8 Ball", pos: { x: 0, y: 5 } }, { name: "Misprint", pos: { x: 6, y: 2 } }, { name: "Dusk", pos: { x: 4, y: 7 } }, { name: "Raised Fist", pos: { x: 8, y: 2 } }, { name: "Chaos the Clown", pos: { x: 1, y: 0 } }, { name: "Fibonacci", pos: { x: 1, y: 5 } }, { name: "Steel Joker", pos: { x: 7, y: 2 } }, { name: "Scary Face", pos: { x: 2, y: 3 } }, { name: "Abstract Joker", pos: { x: 3, y: 3 } }, { name: "Delayed Gratification", pos: { x: 4, y: 3 } }, { name: "Hack", pos: { x: 5, y: 2 } }, { name: "Pareidolia", pos: { x: 6, y: 3 } }, { name: "Gros Michel", pos: { x: 7, y: 6 } }, { name: "Even Steven", pos: { x: 8, y: 3 } }, { name: "Odd Todd", pos: { x: 9, y: 3 } }, { name: "Scholar", pos: { x: 3, y: 6 } }, { name: "Business Card", pos: { x: 1, y: 4 } }, { name: "Supernova", pos: { x: 2, y: 4 } }, { name: "Ride the Bus", pos: { x: 1, y: 6 } }, { name: "Space Joker", pos: { x: 3, y: 5 } }, { name: "Egg", pos: { x: 0, y: 10 } }, { name: "Burglar", pos: { x: 1, y: 10 } }, { name: "Blackboard", pos: { x: 2, y: 10 } }, { name: "Runner", pos: { x: 3, y: 10 } }, { name: "Ice Cream", pos: { x: 4, y: 10 } }, { name: "DNA", pos: { x: 5, y: 10 } }, { name: "Splash", pos: { x: 6, y: 10 } }, { name: "Blue Joker", pos: { x: 7, y: 10 } }, { name: "Sixth Sense", pos: { x: 8, y: 10 } }, { name: "Constellation", pos: { x: 9, y: 10 } }, { name: "Hiker", pos: { x: 0, y: 11 } }, { name: "Faceless Joker", pos: { x: 1, y: 11 } }, { name: "Green Joker", pos: { x: 2, y: 11 } }, { name: "Superposition", pos: { x: 3, y: 11 } }, { name: "To Do List", pos: { x: 4, y: 11 } }, { name: "Cavendish", pos: { x: 5, y: 11 } }, { name: "Card Sharp", pos: { x: 6, y: 11 } }, { name: "Red Card", pos: { x: 7, y: 11 } }, { name: "Madness", pos: { x: 8, y: 11 } }, { name: "Square Joker", pos: { x: 9, y: 11 } }, { name: "Seance", pos: { x: 0, y: 12 } }, { name: "Riff-raff", pos: { x: 1, y: 12 } }, { name: "Vampire", pos: { x: 2, y: 12 } }, { name: "Shortcut", pos: { x: 3, y: 12 } }, { name: "Hologram", pos: { x: 4, y: 12 } }, { name: "Vagabond", pos: { x: 5, y: 12 } }, { name: "Baron", pos: { x: 6, y: 12 } }, { name: "Cloud 9", pos: { x: 7, y: 12 } }, { name: "Rocket", pos: { x: 8, y: 12 } }, { name: "Obelisk", pos: { x: 9, y: 12 } }, { name: "Midas Mask", pos: { x: 0, y: 13 } }, { name: "Luchador", pos: { x: 1, y: 13 } }, { name: "Photograph", pos: { x: 2, y: 13 } }, { name: "Gift Card", pos: { x: 3, y: 13 } }, { name: "Turtle Bean", pos: { x: 4, y: 13 } }, { name: "Erosion", pos: { x: 5, y: 13 } }, { name: "Reserved Parking", pos: { x: 6, y: 13 } }, { name: "Mail In Rebate", pos: { x: 7, y: 13 } }, { name: "To the Moon", pos: { x: 8, y: 13 } }, { name: "Hallucination", pos: { x: 9, y: 13 } }, { name: "Fortune Teller", pos: { x: 7, y: 5 } }, { name: "Juggler", pos: { x: 0, y: 1 } }, { name: "Drunkard", pos: { x: 1, y: 1 } }, { name: "Stone Joker", pos: { x: 9, y: 0 } }, { name: "Golden Joker", pos: { x: 9, y: 2 } }, { name: "Lucky Cat", pos: { x: 5, y: 14 } }, { name: "Baseball Card", pos: { x: 6, y: 14 } }, { name: "Bull", pos: { x: 7, y: 14 } }, { name: "Diet Cola", pos: { x: 8, y: 14 } }, { name: "Trading Card", pos: { x: 9, y: 14 } }, { name: "Flash Card", pos: { x: 0, y: 15 } }, { name: "Popcorn", pos: { x: 1, y: 15 } }, { name: "Spare Trousers", pos: { x: 4, y: 15 } }, { name: "Ancient Joker", pos: { x: 7, y: 15 } }, { name: "Ramen", pos: { x: 2, y: 15 } }, { name: "Walkie Talkie", pos: { x: 8, y: 15 } }, { name: "Seltzer", pos: { x: 3, y: 15 } }, { name: "Castle", pos: { x: 9, y: 15 } }, { name: "Smiley Face", pos: { x: 6, y: 15 } }, { name: "Campfire", pos: { x: 5, y: 15 } }, { name: "Golden Ticket", pos: { x: 5, y: 3 } }, { name: "Mr. Bones", pos: { x: 3, y: 4 } }, { name: "Acrobat", pos: { x: 2, y: 1 } }, { name: "Sock and Buskin", pos: { x: 3, y: 1 } }, { name: "Swashbuckler", pos: { x: 9, y: 5 } }, { name: "Troubadour", pos: { x: 0, y: 2 } }, { name: "Certificate", pos: { x: 8, y: 8 } }, { name: "Smeared Joker", pos: { x: 4, y: 6 } }, { name: "Throwback", pos: { x: 5, y: 7 } }, { name: "Hanging Chad", pos: { x: 9, y: 6 } }, { name: "Rough Gem", pos: { x: 9, y: 7 } }, { name: "Bloodstone", pos: { x: 0, y: 8 } }, { name: "Arrowhead", pos: { x: 1, y: 8 } }, { name: "Onyx Agate", pos: { x: 2, y: 8 } }, { name: "Glass Joker", pos: { x: 1, y: 3 } }, { name: "Showman", pos: { x: 6, y: 5 } }, { name: "Flower Pot", pos: { x: 0, y: 6 } }, { name: "Blueprint", pos: { x: 0, y: 3 } }, { name: "Wee Joker", pos: { x: 0, y: 4 } }, { name: "Merry Andy", pos: { x: 8, y: 0 } }, { name: "Oops! All 6s", pos: { x: 5, y: 6 } }, { name: "The Idol", pos: { x: 6, y: 7 } }, { name: "Seeing Double", pos: { x: 4, y: 4 } }, { name: "Matador", pos: { x: 4, y: 5 } }, { name: "Hit the Road", pos: { x: 8, y: 5 } }, { name: "The Duo", pos: { x: 5, y: 4 } }, { name: "The Trio", pos: { x: 6, y: 4 } }, { name: "The Family", pos: { x: 7, y: 4 } }, { name: "The Order", pos: { x: 8, y: 4 } }, { name: "The Tribe", pos: { x: 9, y: 4 } }, { name: "Stuntman", pos: { x: 8, y: 6 } }, { name: "Invisible Joker", pos: { x: 1, y: 7 } }, { name: "Brainstorm", pos: { x: 7, y: 7 } }, { name: "Satellite", pos: { x: 8, y: 7 } }, { name: "Shoot the Moon", pos: { x: 2, y: 6 } }, { name: "Drivers License", pos: { x: 0, y: 7 } }, { name: "Cartomancer", pos: { x: 7, y: 3 } }, { name: "Astronomer", pos: { x: 2, y: 7 } }, { name: "Burnt Joker", pos: { x: 3, y: 7 } }, { name: "Bootstraps", pos: { x: 9, y: 8 } }, { name: "Canio", pos: { x: 3, y: 8 } }, { name: "Triboulet", pos: { x: 4, y: 8 } }, { name: "Yorick", pos: { x: 5, y: 8 } }, { name: "Chicot", pos: { x: 6, y: 8 } }, { name: "Perkeo", pos: { x: 7, y: 8 } },
|
|
33
|
+
];
|
|
34
|
+
export const JOKER_FACES = [
|
|
35
|
+
{ name: "Hologram", pos: { x: 2, y: 9 }, animated: true },
|
|
36
|
+
{ name: "Canio", pos: { x: 3, y: 9 }, animated: true },
|
|
37
|
+
{ name: "Triboulet", pos: { x: 4, y: 9 }, animated: true },
|
|
38
|
+
{ name: "Yorick", pos: { x: 5, y: 9 }, animated: true },
|
|
39
|
+
{ name: "Chicot", pos: { x: 6, y: 9 }, animated: true },
|
|
40
|
+
{ name: "Perkeo", pos: { x: 7, y: 9 }, animated: true },
|
|
41
|
+
];
|
|
42
|
+
export const CONSUMABLE_FACES = [
|
|
43
|
+
{ name: "The Soul", pos: { x: 0, y: 1 }, animated: true },
|
|
44
|
+
];
|
|
45
|
+
export const TAROTS_AND_PLANETS = [
|
|
46
|
+
{ name: "The Fool", pos: { x: 0, y: 0 } }, { name: "The Magician", pos: { x: 1, y: 0 } }, { name: "The High Priestess", pos: { x: 2, y: 0 } }, { name: "The Empress", pos: { x: 3, y: 0 } }, { name: "The Emperor", pos: { x: 4, y: 0 } }, { name: "The Hierophant", pos: { x: 5, y: 0 } }, { name: "The Lovers", pos: { x: 6, y: 0 } }, { name: "The Chariot", pos: { x: 7, y: 0 } }, { name: "Justice", pos: { x: 8, y: 0 } }, { name: "The Hermit", pos: { x: 9, y: 0 } }, { name: "The Wheel of Fortune", pos: { x: 0, y: 1 } }, { name: "Strength", pos: { x: 1, y: 1 } }, { name: "The Hanged Man", pos: { x: 2, y: 1 } }, { name: "Death", pos: { x: 3, y: 1 } }, { name: "Temperance", pos: { x: 4, y: 1 } }, { name: "The Devil", pos: { x: 5, y: 1 } }, { name: "The Tower", pos: { x: 6, y: 1 } }, { name: "The Star", pos: { x: 7, y: 1 } }, { name: "The Moon", pos: { x: 8, y: 1 } }, { name: "The Sun", pos: { x: 9, y: 1 } }, { name: "Judgement", pos: { x: 0, y: 2 } }, { name: "The World", pos: { x: 1, y: 2 } }, { name: "Mercury", pos: { x: 0, y: 3 } }, { name: "Venus", pos: { x: 1, y: 3 } }, { name: "Earth", pos: { x: 2, y: 3 } }, { name: "Mars", pos: { x: 3, y: 3 } }, { name: "Jupiter", pos: { x: 4, y: 3 } }, { name: "Saturn", pos: { x: 5, y: 3 } }, { name: "Uranus", pos: { x: 6, y: 3 } }, { name: "Neptune", pos: { x: 7, y: 3 } }, { name: "Pluto", pos: { x: 8, y: 3 } }, { name: "Planet X", pos: { x: 9, y: 2 } }, { name: "Ceres", pos: { x: 8, y: 2 } }, { name: "Eris", pos: { x: 3, y: 2 } }, { name: "Familiar", pos: { x: 0, y: 4 } }, { name: "Grim", pos: { x: 1, y: 4 } }, { name: "Incantation", pos: { x: 2, y: 4 } }, { name: "Talisman", pos: { x: 3, y: 4 } }, { name: "Aura", pos: { x: 4, y: 4 } }, { name: "Wraith", pos: { x: 5, y: 4 } }, { name: "Sigil", pos: { x: 6, y: 4 } }, { name: "Ouija", pos: { x: 7, y: 4 } }, { name: "Ectoplasm", pos: { x: 8, y: 4 } }, { name: "Immolate", pos: { x: 9, y: 4 } }, { name: "Ankh", pos: { x: 0, y: 5 } }, { name: "Deja Vu", pos: { x: 1, y: 5 } }, { name: "Hex", pos: { x: 2, y: 5 } }, { name: "Trance", pos: { x: 3, y: 5 } }, { name: "Medium", pos: { x: 4, y: 5 } }, { name: "Cryptid", pos: { x: 5, y: 5 } }, { name: "The Soul", pos: { x: 2, y: 2 } }, { name: "Black Hole", pos: { x: 9, y: 3 } },
|
|
47
|
+
];
|
|
48
|
+
export const TAGS = [
|
|
49
|
+
{ name: "Uncommon Tag", pos: { x: 0, y: 0 } }, { name: "Rare Tag", pos: { x: 1, y: 0 } }, { name: "Negative Tag", pos: { x: 2, y: 0 } }, { name: "Foil Tag", pos: { x: 3, y: 0 } }, { name: "Holographic Tag", pos: { x: 0, y: 1 } }, { name: "Polychrome Tag", pos: { x: 1, y: 1 } }, { name: "Investment Tag", pos: { x: 2, y: 1 } }, { name: "Voucher Tag", pos: { x: 3, y: 1 } }, { name: "Boss Tag", pos: { x: 0, y: 2 } }, { name: "Standard Tag", pos: { x: 1, y: 2 } }, { name: "Charm Tag", pos: { x: 2, y: 2 } }, { name: "Meteor Tag", pos: { x: 3, y: 2 } }, { name: "Buffoon Tag", pos: { x: 4, y: 2 } }, { name: "Handy Tag", pos: { x: 1, y: 3 } }, { name: "Garbage Tag", pos: { x: 2, y: 3 } }, { name: "Ethereal Tag", pos: { x: 3, y: 3 } }, { name: "Coupon Tag", pos: { x: 4, y: 0 } }, { name: "Double Tag", pos: { x: 5, y: 0 } }, { name: "Juggle Tag", pos: { x: 5, y: 1 } }, { name: "D6 Tag", pos: { x: 5, y: 3 } }, { name: "Top-up Tag", pos: { x: 4, y: 1 } }, { name: "Speed Tag", pos: { x: 0, y: 3 } }, { name: "Orbital Tag", pos: { x: 5, y: 2 } }, { name: "Economy Tag", pos: { x: 4, y: 3 } },
|
|
50
|
+
];
|
|
51
|
+
export const VOUCHERS = [
|
|
52
|
+
{ name: "Overstock", pos: { x: 0, y: 0 } }, { name: "Clearance Sale", pos: { x: 3, y: 0 } }, { name: "Hone", pos: { x: 4, y: 0 } }, { name: "Reroll Surplus", pos: { x: 0, y: 2 } }, { name: "Crystal Ball", pos: { x: 2, y: 2 } }, { name: "Telescope", pos: { x: 3, y: 2 } }, { name: "Grabber", pos: { x: 5, y: 0 } }, { name: "Wasteful", pos: { x: 6, y: 0 } }, { name: "Tarot Merchant", pos: { x: 1, y: 0 } }, { name: "Planet Merchant", pos: { x: 2, y: 0 } }, { name: "Seed Money", pos: { x: 1, y: 2 } }, { name: "Blank", pos: { x: 7, y: 0 } }, { name: "Magic Trick", pos: { x: 4, y: 2 } }, { name: "Hieroglyph", pos: { x: 5, y: 2 } }, { name: "Director's Cut", pos: { x: 6, y: 2 } }, { name: "Paint Brush", pos: { x: 7, y: 2 } }, { name: "Overstock Plus", pos: { x: 0, y: 1 } }, { name: "Liquidation", pos: { x: 3, y: 1 } }, { name: "Glow Up", pos: { x: 4, y: 1 } }, { name: "Reroll Glut", pos: { x: 0, y: 3 } }, { name: "Omen Globe", pos: { x: 2, y: 3 } }, { name: "Observatory", pos: { x: 3, y: 3 } }, { name: "Nacho Tong", pos: { x: 5, y: 1 } }, { name: "Recyclomancy", pos: { x: 6, y: 1 } }, { name: "Tarot Tycoon", pos: { x: 1, y: 1 } }, { name: "Planet Tycoon", pos: { x: 2, y: 1 } }, { name: "Money Tree", pos: { x: 1, y: 3 } }, { name: "Antimatter", pos: { x: 7, y: 1 } }, { name: "Illusion", pos: { x: 4, y: 3 } }, { name: "Petroglyph", pos: { x: 5, y: 3 } }, { name: "Retcon", pos: { x: 6, y: 3 } }, { name: "Palette", pos: { x: 7, y: 3 } },
|
|
53
|
+
];
|
|
54
|
+
export const BOSSES = [
|
|
55
|
+
{ name: "Small Blind", pos: { x: 0, y: 0 } }, { name: "Big Blind", pos: { x: 0, y: 1 } }, { name: "The Ox", pos: { x: 0, y: 2 } }, { name: "The Hook", pos: { x: 0, y: 7 } }, { name: "The Mouth", pos: { x: 0, y: 18 } }, { name: "The Fish", pos: { x: 0, y: 5 } }, { name: "The Club", pos: { x: 0, y: 4 } }, { name: "The Manacle", pos: { x: 0, y: 8 } }, { name: "The Tooth", pos: { x: 0, y: 22 } }, { name: "The Wall", pos: { x: 0, y: 9 } }, { name: "The House", pos: { x: 0, y: 3 } }, { name: "The Mark", pos: { x: 0, y: 23 } }, { name: "Cerulean Bell", pos: { x: 0, y: 26 } }, { name: "The Wheel", pos: { x: 0, y: 10 } }, { name: "The Arm", pos: { x: 0, y: 11 } }, { name: "The Psychic", pos: { x: 0, y: 12 } }, { name: "The Goad", pos: { x: 0, y: 13 } }, { name: "The Water", pos: { x: 0, y: 14 } }, { name: "The Eye", pos: { x: 0, y: 17 } }, { name: "The Plant", pos: { x: 0, y: 19 } }, { name: "The Needle", pos: { x: 0, y: 20 } }, { name: "The Head", pos: { x: 0, y: 21 } }, { name: "Verdant Leaf", pos: { x: 0, y: 28 } }, { name: "Violet Vessel", pos: { x: 0, y: 29 } }, { name: "The Window", pos: { x: 0, y: 6 } }, { name: "The Serpent", pos: { x: 0, y: 15 } }, { name: "The Pillar", pos: { x: 0, y: 16 } }, { name: "The Flint", pos: { x: 0, y: 24 } }, { name: "Amber Acorn", pos: { x: 0, y: 27 } }, { name: "Crimson Heart", pos: { x: 0, y: 25 } },
|
|
56
|
+
];
|
|
57
|
+
export const BOOSTER_PACKS = [
|
|
58
|
+
{ name: "Arcana Pack", pos: { x: 0, y: 0 } }, { name: "Celestial Pack", pos: { x: 0, y: 1 } }, { name: "Jumbo Arcana Pack", pos: { x: 0, y: 2 } }, { name: "Mega Arcana Pack", pos: { x: 2, y: 2 } }, { name: "Jumbo Celestial Pack", pos: { x: 0, y: 3 } }, { name: "Mega Celestial Pack", pos: { x: 2, y: 3 } }, { name: "Spectral Pack", pos: { x: 0, y: 4 } }, { name: "Jumbo Spectral Pack", pos: { x: 2, y: 4 } }, { name: "Mega Spectral Pack", pos: { x: 3, y: 4 } }, { name: "Standard Pack", pos: { x: 0, y: 6 } }, { name: "Jumbo Standard Pack", pos: { x: 0, y: 7 } }, { name: "Mega Standard Pack", pos: { x: 2, y: 7 } }, { name: "Buffoon Pack", pos: { x: 0, y: 8 } }, { name: "Jumbo Buffoon Pack", pos: { x: 2, y: 8 } }, { name: "Mega Buffoon Pack", pos: { x: 3, y: 8 } },
|
|
59
|
+
];
|
|
60
|
+
export const EDITION_MAP = {
|
|
61
|
+
Foil: 1,
|
|
62
|
+
Holographic: 2,
|
|
63
|
+
Polychrome: 3,
|
|
64
|
+
};
|
|
65
|
+
export const STICKER_MAP = {
|
|
66
|
+
Eternal: { x: 0, y: 0 },
|
|
67
|
+
Perishable: { x: 0, y: 2 },
|
|
68
|
+
Rental: { x: 1, y: 2 },
|
|
69
|
+
};
|
|
70
|
+
export const RANK_MAP = {
|
|
71
|
+
"2": 0, "3": 1, "4": 2, "5": 3, "6": 4, "7": 5, "8": 6, "9": 7, "10": 8, Jack: 9, Queen: 10, King: 11, Ace: 12,
|
|
72
|
+
};
|
|
73
|
+
export const SUIT_MAP = {
|
|
74
|
+
Hearts: 0, Clubs: 1, Diamonds: 2, Spades: 3,
|
|
75
|
+
};
|
|
76
|
+
export const ENHANCER_MAP = {
|
|
77
|
+
Bonus: { x: 1, y: 1 }, Mult: { x: 2, y: 1 }, Wild: { x: 3, y: 1 }, Glass: { x: 5, y: 1 }, Steel: { x: 6, y: 1 }, Stone: { x: 5, y: 0 }, Gold: { x: 6, y: 0 }, Lucky: { x: 4, y: 1 },
|
|
78
|
+
};
|
|
79
|
+
export const SEAL_MAP = {
|
|
80
|
+
"Gold Seal": { x: 2, y: 0 }, "Purple Seal": { x: 4, y: 4 }, "Red Seal": { x: 5, y: 4 }, "Blue Seal": { x: 6, y: 4 },
|
|
81
|
+
Gold: { x: 2, y: 0 }, Purple: { x: 4, y: 4 }, Red: { x: 5, y: 4 }, Blue: { x: 6, y: 4 },
|
|
82
|
+
};
|
|
83
|
+
/** Build fast lookup maps */
|
|
84
|
+
const jokerMap = new Map(JOKERS.map((j) => [j.name, j]));
|
|
85
|
+
const jokerFaceMap = new Map(JOKER_FACES.map((j) => [j.name, j]));
|
|
86
|
+
const consumableMap = new Map(TAROTS_AND_PLANETS.map((t) => [t.name, t]));
|
|
87
|
+
const consumableFaceMap = new Map(CONSUMABLE_FACES.map((c) => [c.name, c]));
|
|
88
|
+
const tagMap = new Map(TAGS.map((t) => [t.name, t]));
|
|
89
|
+
const voucherMap = new Map(VOUCHERS.map((v) => [v.name, v]));
|
|
90
|
+
const bossMap = new Map(BOSSES.map((b) => [b.name, b]));
|
|
91
|
+
const boosterMap = new Map(BOOSTER_PACKS.map((b) => [b.name, b]));
|
|
92
|
+
export function findJoker(name) { return jokerMap.get(name); }
|
|
93
|
+
export function findJokerFace(name) { return jokerFaceMap.get(name); }
|
|
94
|
+
export function findConsumable(name) { return consumableMap.get(name); }
|
|
95
|
+
export function findConsumableFace(name) { return consumableFaceMap.get(name); }
|
|
96
|
+
export function findTag(name) { return tagMap.get(name); }
|
|
97
|
+
export function findVoucher(name) { return voucherMap.get(name); }
|
|
98
|
+
export function findBoss(name) { return bossMap.get(name); }
|
|
99
|
+
export function findBooster(name) { return boosterMap.get(name); }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface SpritePos {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
export type SpriteSheetType = "Jokers" | "Tarots" | "Vouchers" | "Boosters" | "Enhancers" | "Editions" | "BlindChips" | "tags";
|
|
6
|
+
export interface SpriteData {
|
|
7
|
+
pos: SpritePos;
|
|
8
|
+
type: SpriteSheetType;
|
|
9
|
+
}
|
|
10
|
+
/** O(1) sprite lookup by name. Tries multiple normalizations. */
|
|
11
|
+
export declare function getSpriteData(name: string): SpriteData | null;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { JOKERS, JOKER_FACES, TAROTS_AND_PLANETS, CONSUMABLE_FACES, VOUCHERS, BOSSES, TAGS, BOOSTER_PACKS, } from "./spriteData.js";
|
|
2
|
+
const ITEM_MAP = new Map();
|
|
3
|
+
function addToMap(items, type) {
|
|
4
|
+
for (const item of items) {
|
|
5
|
+
if (!item.name || !item.pos)
|
|
6
|
+
continue;
|
|
7
|
+
const data = { pos: item.pos, type };
|
|
8
|
+
ITEM_MAP.set(item.name, data);
|
|
9
|
+
ITEM_MAP.set(item.name.toLowerCase(), data);
|
|
10
|
+
ITEM_MAP.set(item.name.replace(/ /g, ""), data);
|
|
11
|
+
ITEM_MAP.set(item.name.replace(/ /g, "").toLowerCase(), data);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
addToMap(JOKERS, "Jokers");
|
|
15
|
+
addToMap(JOKER_FACES, "Jokers");
|
|
16
|
+
addToMap(TAROTS_AND_PLANETS, "Tarots");
|
|
17
|
+
addToMap(CONSUMABLE_FACES ?? [], "Tarots");
|
|
18
|
+
addToMap(VOUCHERS, "Vouchers");
|
|
19
|
+
addToMap(BOSSES, "BlindChips");
|
|
20
|
+
addToMap(TAGS, "tags");
|
|
21
|
+
addToMap(BOOSTER_PACKS ?? [], "Boosters");
|
|
22
|
+
/** O(1) sprite lookup by name. Tries multiple normalizations. */
|
|
23
|
+
export function getSpriteData(name) {
|
|
24
|
+
const cleaned = name.replace(/^(Joker|Tarot|Planet|Voucher|Pack|Edition|Tag) [|:] /i, "").trim();
|
|
25
|
+
if (ITEM_MAP.has(cleaned))
|
|
26
|
+
return ITEM_MAP.get(cleaned);
|
|
27
|
+
if (ITEM_MAP.has(name))
|
|
28
|
+
return ITEM_MAP.get(name);
|
|
29
|
+
const variants = [
|
|
30
|
+
cleaned.toLowerCase(),
|
|
31
|
+
cleaned.replace(/ /g, ""),
|
|
32
|
+
cleaned.replace(/ /g, "").toLowerCase(),
|
|
33
|
+
name.toLowerCase(),
|
|
34
|
+
name.replace(/ /g, ""),
|
|
35
|
+
name.replace(/ /g, "").toLowerCase(),
|
|
36
|
+
];
|
|
37
|
+
for (const v of variants) {
|
|
38
|
+
if (ITEM_MAP.has(v))
|
|
39
|
+
return ITEM_MAP.get(v);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function getStandardCardPosition(rank: string, suit: string): {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
};
|
|
5
|
+
export declare function getSealPosition(seal: string): {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function getEnhancerPosition(modifiers: Array<string>): {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function getStandardCardPosition(rank, suit) {
|
|
2
|
+
const rankMap = {
|
|
3
|
+
"2": 0,
|
|
4
|
+
"3": 1,
|
|
5
|
+
"4": 2,
|
|
6
|
+
"5": 3,
|
|
7
|
+
"6": 4,
|
|
8
|
+
"7": 5,
|
|
9
|
+
"8": 6,
|
|
10
|
+
"9": 7,
|
|
11
|
+
"10": 8,
|
|
12
|
+
Jack: 9,
|
|
13
|
+
Queen: 10,
|
|
14
|
+
King: 11,
|
|
15
|
+
Ace: 12,
|
|
16
|
+
};
|
|
17
|
+
const suitMap = {
|
|
18
|
+
Hearts: 0,
|
|
19
|
+
Clubs: 1,
|
|
20
|
+
Diamonds: 2,
|
|
21
|
+
Spades: 3,
|
|
22
|
+
};
|
|
23
|
+
const x = rankMap[rank] ?? 0;
|
|
24
|
+
const y = suitMap[suit] ?? 0;
|
|
25
|
+
return { x, y };
|
|
26
|
+
}
|
|
27
|
+
export function getSealPosition(seal) {
|
|
28
|
+
const sealMap = {
|
|
29
|
+
"Gold Seal": { x: 2, y: 0 },
|
|
30
|
+
"Purple Seal": { x: 4, y: 4 },
|
|
31
|
+
"Red Seal": { x: 5, y: 4 },
|
|
32
|
+
"Blue Seal": { x: 6, y: 4 },
|
|
33
|
+
};
|
|
34
|
+
return sealMap[seal];
|
|
35
|
+
}
|
|
36
|
+
export function getEnhancerPosition(modifiers) {
|
|
37
|
+
const enhancerMap = {
|
|
38
|
+
Bonus: { x: 1, y: 1 },
|
|
39
|
+
Mult: { x: 2, y: 1 },
|
|
40
|
+
Wild: { x: 3, y: 1 },
|
|
41
|
+
Glass: { x: 5, y: 1 },
|
|
42
|
+
Steel: { x: 6, y: 1 },
|
|
43
|
+
Stone: { x: 5, y: 0 },
|
|
44
|
+
Gold: { x: 6, y: 0 },
|
|
45
|
+
Lucky: { x: 4, y: 1 },
|
|
46
|
+
};
|
|
47
|
+
const enhancer = modifiers.find((mod) => Object.keys(enhancerMap).includes(mod));
|
|
48
|
+
return enhancer ? enhancerMap[enhancer] : { x: 1, y: 0 };
|
|
49
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Map MotelyItemType enum names to display-friendly strings */
|
|
2
|
+
export declare function getItemDisplayName(enumKey: string): string;
|
|
3
|
+
export type CardCategory = "joker" | "tarot" | "planet" | "spectral" | "playing" | "unknown";
|
|
4
|
+
export declare function getItemCategory(enumKey: string): CardCategory;
|
|
5
|
+
export declare const CATEGORY_COLORS: Record<CardCategory, {
|
|
6
|
+
bg: string;
|
|
7
|
+
border: string;
|
|
8
|
+
text: string;
|
|
9
|
+
}>;
|
|
10
|
+
/** Suit color for playing cards */
|
|
11
|
+
export declare function getSuitColor(enumKey: string): string;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** Map MotelyItemType enum names to display-friendly strings */
|
|
2
|
+
export function getItemDisplayName(enumKey) {
|
|
3
|
+
// Convert PascalCase to spaced: "GreedyJoker" -> "Greedy Joker"
|
|
4
|
+
// Handle special cases first
|
|
5
|
+
const specials = {
|
|
6
|
+
ChaostheClown: "Chaos the Clown",
|
|
7
|
+
OopsAll6s: "Oops! All 6s",
|
|
8
|
+
EightBall: "8 Ball",
|
|
9
|
+
DNA: "DNA",
|
|
10
|
+
MrBones: "Mr. Bones",
|
|
11
|
+
ToDoList: "To Do List",
|
|
12
|
+
Cloud9: "Cloud 9",
|
|
13
|
+
SockAndBuskin: "Sock and Buskin",
|
|
14
|
+
TheSoul: "The Soul",
|
|
15
|
+
BlackHole: "Black Hole",
|
|
16
|
+
PlanetX: "Planet X",
|
|
17
|
+
};
|
|
18
|
+
if (specials[enumKey])
|
|
19
|
+
return specials[enumKey];
|
|
20
|
+
// Playing cards: C2 = 2 of Clubs, D10 = 10 of Diamonds, etc.
|
|
21
|
+
const suitMap = { C: "♣", D: "♦", H: "♥", S: "♠" };
|
|
22
|
+
const cardMatch = enumKey.match(/^([CDHS])([2-9JQKA]|10)$/);
|
|
23
|
+
if (cardMatch) {
|
|
24
|
+
const [, suit, rank] = cardMatch;
|
|
25
|
+
const rankName = { J: "Jack", Q: "Queen", K: "King", A: "Ace" }[rank] ?? rank;
|
|
26
|
+
return `${rankName} ${suitMap[suit]}`;
|
|
27
|
+
}
|
|
28
|
+
// General PascalCase split
|
|
29
|
+
return enumKey.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
|
|
30
|
+
}
|
|
31
|
+
const TAROT_NAMES = new Set([
|
|
32
|
+
"TheFool", "TheMagician", "TheHighPriestess", "TheEmpress", "TheEmperor",
|
|
33
|
+
"TheHierophant", "TheLovers", "TheChariot", "Justice", "TheHermit",
|
|
34
|
+
"TheWheelOfFortune", "Strength", "TheHangedMan", "Death", "Temperance",
|
|
35
|
+
"TheDevil", "TheTower", "TheStar", "TheMoon", "TheSun", "Judgement", "TheWorld",
|
|
36
|
+
]);
|
|
37
|
+
const PLANET_NAMES = new Set([
|
|
38
|
+
"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn",
|
|
39
|
+
"Uranus", "Neptune", "Pluto", "PlanetX", "Ceres", "Eris",
|
|
40
|
+
]);
|
|
41
|
+
const SPECTRAL_NAMES = new Set([
|
|
42
|
+
"Familiar", "Grim", "Incantation", "Talisman", "Aura", "Wraith",
|
|
43
|
+
"Sigil", "Ouija", "Ectoplasm", "Immolate", "Ankh", "DejaVu",
|
|
44
|
+
"Hex", "Trance", "Medium", "Cryptid", "TheSoul", "BlackHole",
|
|
45
|
+
]);
|
|
46
|
+
export function getItemCategory(enumKey) {
|
|
47
|
+
if (/^[CDHS]([2-9JQKA]|10)$/.test(enumKey))
|
|
48
|
+
return "playing";
|
|
49
|
+
if (TAROT_NAMES.has(enumKey))
|
|
50
|
+
return "tarot";
|
|
51
|
+
if (PLANET_NAMES.has(enumKey))
|
|
52
|
+
return "planet";
|
|
53
|
+
if (SPECTRAL_NAMES.has(enumKey))
|
|
54
|
+
return "spectral";
|
|
55
|
+
// Everything else between the playing cards and Invalid is a joker
|
|
56
|
+
return "joker";
|
|
57
|
+
}
|
|
58
|
+
export const CATEGORY_COLORS = {
|
|
59
|
+
joker: { bg: "bg-purple-900/30", border: "border-purple-500/50", text: "text-purple-200" },
|
|
60
|
+
tarot: { bg: "bg-blue-900/30", border: "border-blue-500/50", text: "text-blue-200" },
|
|
61
|
+
planet: { bg: "bg-amber-900/30", border: "border-amber-500/50", text: "text-amber-200" },
|
|
62
|
+
spectral: { bg: "bg-cyan-900/30", border: "border-cyan-500/50", text: "text-cyan-200" },
|
|
63
|
+
playing: { bg: "bg-neutral-100 dark:bg-neutral-800", border: "border-neutral-300 dark:border-neutral-600", text: "text-neutral-900 dark:text-neutral-100" },
|
|
64
|
+
unknown: { bg: "bg-neutral-900/30", border: "border-neutral-500/50", text: "text-neutral-300" },
|
|
65
|
+
};
|
|
66
|
+
/** Suit color for playing cards */
|
|
67
|
+
export function getSuitColor(enumKey) {
|
|
68
|
+
if (enumKey.startsWith("H") || enumKey.startsWith("D"))
|
|
69
|
+
return "text-red-500";
|
|
70
|
+
return "text-neutral-900 dark:text-neutral-100";
|
|
71
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jaml-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
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
|
+
"./assets/*": "./assets/*",
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"assets",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc --pretty false",
|
|
33
|
+
"dev": "tsc --watch",
|
|
34
|
+
"typecheck": "tsc --noEmit --pretty false",
|
|
35
|
+
"prepack": "npm run build"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"balatro",
|
|
45
|
+
"jaml",
|
|
46
|
+
"motely",
|
|
47
|
+
"seed",
|
|
48
|
+
"card",
|
|
49
|
+
"sprite",
|
|
50
|
+
"ui"
|
|
51
|
+
],
|
|
52
|
+
"author": "pifreak",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"motely-wasm": ">=5.7.0",
|
|
56
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
57
|
+
"react-dom": "^18.2.0 || ^19.0.0"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"motely-wasm": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/react": "^19.2.14",
|
|
66
|
+
"@types/react-dom": "^19.2.3",
|
|
67
|
+
"motely-wasm": "^5.8.2",
|
|
68
|
+
"react": "^19.2.4",
|
|
69
|
+
"react-dom": "^19.2.4",
|
|
70
|
+
"typescript": "^5.9.3"
|
|
71
|
+
}
|
|
72
|
+
}
|