jaml-ui 0.10.0 → 0.11.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 (152) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +135 -135
  3. package/assets/8BitDeck.png +0 -0
  4. package/assets/Balatro Seed Curator (DesignsV2)/.design-canvas.state.json +1 -0
  5. package/assets/Balatro Seed Curator (DesignsV2)/Assets/BlindChips.png +0 -0
  6. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Boosters/Boosters.json +303 -0
  7. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Boosters/boosters.png +0 -0
  8. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Boosters.png +0 -0
  9. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Bosses/BlindChips.png +0 -0
  10. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Bosses/blinds_metadata.json +51 -0
  11. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/8BitDeck.png +0 -0
  12. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/Enhancers.png +0 -0
  13. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/balatro-stake-chips.png +0 -0
  14. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/enhancers_metadata.json +52 -0
  15. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/playing_cards_metadata.json +74 -0
  16. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Decks/stakes.json +19 -0
  17. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Editions.png +0 -0
  18. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Enhancers.png +0 -0
  19. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/Editions.png +0 -0
  20. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/Jokers.png +0 -0
  21. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/jokers.json +1087 -0
  22. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/stickers.png +0 -0
  23. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers/stickers_metadata.json +25 -0
  24. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Jokers.png +0 -0
  25. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tags/tags.json +191 -0
  26. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tags/tags.png +0 -0
  27. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/Tarots.png +0 -0
  28. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/planets.json +15 -0
  29. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/spectrals.json +21 -0
  30. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots/tarots.json +163 -0
  31. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Tarots.png +0 -0
  32. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Vouchers/Vouchers.png +0 -0
  33. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Vouchers/vouchers.json +130 -0
  34. package/assets/Balatro Seed Curator (DesignsV2)/Assets/Vouchers.png +0 -0
  35. package/assets/Balatro Seed Curator (DesignsV2)/Assets/blinds.json +51 -0
  36. package/assets/Balatro Seed Curator (DesignsV2)/Assets/boosters.json +303 -0
  37. package/assets/Balatro Seed Curator (DesignsV2)/Assets/fonts/m6x11plusplus.otf +0 -0
  38. package/assets/Balatro Seed Curator (DesignsV2)/Assets/jokers.json +1087 -0
  39. package/assets/Balatro Seed Curator (DesignsV2)/Assets/planets.json +15 -0
  40. package/assets/Balatro Seed Curator (DesignsV2)/Assets/spectrals.json +21 -0
  41. package/assets/Balatro Seed Curator (DesignsV2)/Assets/stakes.png +0 -0
  42. package/assets/Balatro Seed Curator (DesignsV2)/Assets/stickers.png +0 -0
  43. package/assets/Balatro Seed Curator (DesignsV2)/Assets/tags.json +191 -0
  44. package/assets/Balatro Seed Curator (DesignsV2)/Assets/tags.png +0 -0
  45. package/assets/Balatro Seed Curator (DesignsV2)/Assets/tarots.json +163 -0
  46. package/assets/Balatro Seed Curator (DesignsV2)/Assets/vouchers.json +130 -0
  47. package/assets/Balatro Seed Curator (DesignsV2)/Seed Detail v2.html +40 -0
  48. package/assets/Balatro Seed Curator (DesignsV2)/Seed Detail.html +34 -0
  49. package/assets/Balatro Seed Curator (DesignsV2)/public/fonts/m6x11plusplus.otf +0 -0
  50. package/assets/Balatro Seed Curator (DesignsV2)/src/AntePage.jsx +228 -0
  51. package/assets/Balatro Seed Curator (DesignsV2)/src/SeedDetail.jsx +222 -0
  52. package/assets/Balatro Seed Curator (DesignsV2)/src/app.jsx +35 -0
  53. package/assets/Balatro Seed Curator (DesignsV2)/src/mockData.js +185 -0
  54. package/assets/Balatro Seed Curator (DesignsV2)/src/sprites.jsx +259 -0
  55. package/assets/Balatro Seed Curator (DesignsV2)/src/tokens.js +49 -0
  56. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/AntePageV2.jsx +290 -0
  57. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/BalButton.jsx +107 -0
  58. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/JamlBuilderV2.jsx +594 -0
  59. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/JamlIde.jsx +302 -0
  60. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/SearchResultsV2.jsx +286 -0
  61. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/SeedDetailV2.jsx +336 -0
  62. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/SeedOGCard.jsx +251 -0
  63. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/Showcase.jsx +131 -0
  64. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/app.jsx +55 -0
  65. package/assets/Balatro Seed Curator (DesignsV2)/src/v2/data.js +296 -0
  66. package/assets/Balatro Seed Curator (DesignsV2)/starters/design-canvas.jsx +622 -0
  67. package/assets/Balatro Seed Curator (DesignsV2)/uploads/8BitDeck.png +0 -0
  68. package/assets/Balatro Seed Curator (DesignsV2)/uploads/BlindChips.png +0 -0
  69. package/assets/Balatro Seed Curator (DesignsV2)/uploads/Boosters.png +0 -0
  70. package/assets/Balatro Seed Curator (DesignsV2)/uploads/Editions.png +0 -0
  71. package/assets/Balatro Seed Curator (DesignsV2)/uploads/Enhancers.png +0 -0
  72. package/assets/Balatro Seed Curator (DesignsV2)/uploads/Jokers.png +0 -0
  73. package/assets/Balatro Seed Curator (DesignsV2)/uploads/Tarots.png +0 -0
  74. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749540653-0.png +0 -0
  75. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749644934-0.png +0 -0
  76. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749661871-0.png +0 -0
  77. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749674748-0.png +0 -0
  78. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749703076-0.png +0 -0
  79. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776749882759-0.png +0 -0
  80. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776750354200-0.png +0 -0
  81. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776750733265-0.png +0 -0
  82. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776751928925-0.png +0 -0
  83. package/assets/Balatro Seed Curator (DesignsV2)/uploads/pasted-1776800975060-0.png +0 -0
  84. package/assets/Balatro Seed Curator (DesignsV2)/uploads/stickers.png +0 -0
  85. package/assets/Balatro Seed Curator (DesignsV2)/uploads/tags.png +0 -0
  86. package/assets/BlindChips.png +0 -0
  87. package/assets/Boosters.png +0 -0
  88. package/assets/Editions.png +0 -0
  89. package/assets/Enhancers.png +0 -0
  90. package/assets/Jokers.png +0 -0
  91. package/assets/Tarots.png +0 -0
  92. package/assets/Vouchers.png +0 -0
  93. package/assets/fonts/m6x11plusplus.otf +0 -0
  94. package/assets/stickers.png +0 -0
  95. package/assets/tags.png +0 -0
  96. package/dist/assets.js +10 -13
  97. package/dist/components/GameCard.js +7 -5
  98. package/dist/components/JamlCodeEditor.js +28 -16
  99. package/dist/components/JamlIdeVisual.d.ts +5 -3
  100. package/dist/components/JamlIdeVisual.js +194 -36
  101. package/dist/components/JamlMapPreview.d.ts +1 -5
  102. package/dist/components/JamlMapPreview.js +67 -107
  103. package/dist/components/PlayingCard.js +15 -50
  104. package/dist/data/balatro-jokers.json +1241 -0
  105. package/dist/decode/motelyItemDecoder.js +1 -1
  106. package/dist/hooks/searchWorkerCode.js +59 -59
  107. package/dist/hooks/useAnalyzer.d.ts +1 -0
  108. package/dist/hooks/useAnalyzer.js +5 -1
  109. package/dist/hooks/useSearch.d.ts +1 -0
  110. package/dist/hooks/useSearch.js +4 -1
  111. package/dist/index.d.ts +1 -0
  112. package/dist/index.js +1 -0
  113. package/dist/motelyDisplay.js +2 -0
  114. package/dist/r3f/BalatroJokerMesh3D.d.ts +8 -0
  115. package/dist/r3f/BalatroJokerMesh3D.js +98 -0
  116. package/dist/r3f/BalatroJokerPreview3D.d.ts +14 -0
  117. package/dist/r3f/BalatroJokerPreview3D.js +30 -0
  118. package/dist/r3f/BalatroPlayingCard3D.d.ts +22 -0
  119. package/dist/r3f/BalatroPlayingCard3D.js +62 -0
  120. package/dist/r3f/cardConstants.d.ts +16 -0
  121. package/dist/r3f/cardConstants.js +14 -0
  122. package/dist/r3f/compositedAtlas.d.ts +5 -0
  123. package/dist/r3f/compositedAtlas.js +56 -0
  124. package/dist/r3f/gridUV.d.ts +22 -0
  125. package/dist/r3f/gridUV.js +30 -0
  126. package/dist/r3f/index.d.ts +12 -0
  127. package/dist/r3f/index.js +13 -0
  128. package/dist/r3f/jokerRegistry.d.ts +28 -0
  129. package/dist/r3f/jokerRegistry.js +40 -0
  130. package/dist/r3f/jokerTilt.d.ts +8 -0
  131. package/dist/r3f/jokerTilt.js +41 -0
  132. package/dist/r3f/magneticTilt.d.ts +18 -0
  133. package/dist/r3f/magneticTilt.js +34 -0
  134. package/dist/r3f/playingCardTypes.d.ts +24 -0
  135. package/dist/r3f/playingCardTypes.js +32 -0
  136. package/dist/r3f/playingCardVisuals.d.ts +7 -0
  137. package/dist/r3f/playingCardVisuals.js +45 -0
  138. package/dist/r3f/usePlayingCardTexture.d.ts +7 -0
  139. package/dist/r3f/usePlayingCardTexture.js +92 -0
  140. package/dist/sprites/spriteMapper.d.ts +1 -1
  141. package/dist/sprites/spriteMapper.js +14 -33
  142. package/dist/ui/footer.js +5 -5
  143. package/dist/ui/jimboBackground.js +55 -55
  144. package/dist/ui/jimboCopyRow.d.ts +5 -0
  145. package/dist/ui/jimboCopyRow.js +36 -0
  146. package/dist/ui/jimboTabs.js +5 -5
  147. package/dist/ui.d.ts +1 -0
  148. package/dist/ui.js +1 -0
  149. package/dist/utils/gameCardUtils.d.ts +4 -12
  150. package/dist/utils/gameCardUtils.js +9 -43
  151. package/fonts.css +5 -5
  152. package/package.json +4 -3
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/assets.js CHANGED
@@ -11,20 +11,17 @@ export const JAML_ASSET_FILES = {
11
11
  tags: "tags.png",
12
12
  };
13
13
  const assetKeyByFileName = Object.fromEntries(Object.entries(JAML_ASSET_FILES).map(([key, fileName]) => [fileName, key]));
14
- // Keep in lockstep with package.json version. Upload assets to this path when publishing.
15
- const JAML_UI_VERSION = "0.10.0";
16
- const CDN_BASE = `https://cdn.seedfinder.app/jaml-ui/${JAML_UI_VERSION}/assets/`;
17
14
  const defaultAssetUrls = {
18
- deck: `${CDN_BASE}${JAML_ASSET_FILES.deck}`,
19
- blinds: `${CDN_BASE}${JAML_ASSET_FILES.blinds}`,
20
- boosters: `${CDN_BASE}${JAML_ASSET_FILES.boosters}`,
21
- editions: `${CDN_BASE}${JAML_ASSET_FILES.editions}`,
22
- enhancers: `${CDN_BASE}${JAML_ASSET_FILES.enhancers}`,
23
- jokers: `${CDN_BASE}${JAML_ASSET_FILES.jokers}`,
24
- tarots: `${CDN_BASE}${JAML_ASSET_FILES.tarots}`,
25
- vouchers: `${CDN_BASE}${JAML_ASSET_FILES.vouchers}`,
26
- stickers: `${CDN_BASE}${JAML_ASSET_FILES.stickers}`,
27
- tags: `${CDN_BASE}${JAML_ASSET_FILES.tags}`,
15
+ deck: new URL(`../assets/${JAML_ASSET_FILES.deck}`, import.meta.url).href,
16
+ blinds: new URL(`../assets/${JAML_ASSET_FILES.blinds}`, import.meta.url).href,
17
+ boosters: new URL(`../assets/${JAML_ASSET_FILES.boosters}`, import.meta.url).href,
18
+ editions: new URL(`../assets/${JAML_ASSET_FILES.editions}`, import.meta.url).href,
19
+ enhancers: new URL(`../assets/${JAML_ASSET_FILES.enhancers}`, import.meta.url).href,
20
+ jokers: new URL(`../assets/${JAML_ASSET_FILES.jokers}`, import.meta.url).href,
21
+ tarots: new URL(`../assets/${JAML_ASSET_FILES.tarots}`, import.meta.url).href,
22
+ vouchers: new URL(`../assets/${JAML_ASSET_FILES.vouchers}`, import.meta.url).href,
23
+ stickers: new URL(`../assets/${JAML_ASSET_FILES.stickers}`, import.meta.url).href,
24
+ tags: new URL(`../assets/${JAML_ASSET_FILES.tags}`, import.meta.url).href,
28
25
  };
29
26
  let customAssetBaseUrl = null;
30
27
  function normalizeBaseUrl(baseUrl) {
@@ -2,9 +2,8 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Layer } from "../render/Layer.js";
4
4
  import { JamlCardRenderer } from "../render/CanvasRenderer.js";
5
- import { JOKERS, JOKER_FACES, TAROTS_AND_PLANETS, CONSUMABLE_FACES, TAGS, VOUCHERS, BOSSES, EDITION_MAP, SPRITE_SHEETS, STICKER_MAP, } from "../sprites/spriteData.js";
5
+ import { JOKERS, JOKER_FACES, TAROTS_AND_PLANETS, CONSUMABLE_FACES, TAGS, VOUCHERS, BOSSES, EDITION_MAP, SPRITE_SHEETS, STICKER_MAP, RANK_MAP, SUIT_MAP, ENHANCER_MAP, SEAL_MAP, } from "../sprites/spriteData.js";
6
6
  import { BalatroItemCategory, isPackedItemValid, packedItemCategory } from "../decode/packedBalatroItem.js";
7
- import { getEnhancerPosition, getSealPosition, getStandardCardPosition } from "../utils/gameCardUtils.js";
8
7
  function normalizeCardRank(raw) {
9
8
  const value = raw.trim().toUpperCase();
10
9
  if (value === "A" || value === "ACE")
@@ -225,8 +224,11 @@ export function JamlGameCard({ card, type, className = "", hoverTilt = false })
225
224
  }));
226
225
  }
227
226
  else if (rank && suit) {
227
+ const enhancerPos = (enhancements ?? [])
228
+ .map((m) => ENHANCER_MAP[m])
229
+ .find((pos) => Boolean(pos)) ?? { x: 1, y: 0 };
228
230
  layers.push(new Layer({
229
- pos: getEnhancerPosition(enhancements ?? []),
231
+ pos: enhancerPos,
230
232
  name: "background",
231
233
  order: 0,
232
234
  source: SPRITE_SHEETS.enhancers.src,
@@ -234,7 +236,7 @@ export function JamlGameCard({ card, type, className = "", hoverTilt = false })
234
236
  columns: SPRITE_SHEETS.enhancers.columns,
235
237
  }));
236
238
  layers.push(new Layer({
237
- pos: getStandardCardPosition(rank, suit),
239
+ pos: { x: RANK_MAP[rank] ?? 0, y: SUIT_MAP[suit] ?? 0 },
238
240
  name,
239
241
  order: 1,
240
242
  source: SPRITE_SHEETS.deck.src,
@@ -286,7 +288,7 @@ export function JamlGameCard({ card, type, className = "", hoverTilt = false })
286
288
  }));
287
289
  }
288
290
  if (seal) {
289
- const sealPos = getSealPosition(seal);
291
+ const sealPos = SEAL_MAP[seal];
290
292
  if (sealPos) {
291
293
  layers.push(new Layer({
292
294
  pos: sealPos,
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import Editor from "@monaco-editor/react";
4
4
  import { JimboColorOption } from "../ui/tokens.js";
5
5
  // Monaco needs hex strings for its colors API. We strip the leading `#` from
@@ -40,19 +40,31 @@ const defineBalatroTheme = (monaco) => {
40
40
  });
41
41
  };
42
42
  export function JamlCodeEditor({ value, onChange, minHeight = 320, }) {
43
- return (_jsx("div", { style: { width: "100%", minHeight, background: JimboColorOption.DARKEST }, children: _jsx(Editor, { height: `${minHeight}px`, defaultLanguage: "yaml", value: value, theme: "jaml-balatro-dark", onChange: (next) => onChange(next ?? ""), beforeMount: defineBalatroTheme, options: {
44
- minimap: { enabled: false },
45
- scrollBeyondLastLine: false,
46
- fontSize: 13,
47
- lineHeight: 22,
48
- fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
49
- lineNumbers: "on",
50
- automaticLayout: true,
51
- padding: { top: 12, bottom: 12 },
52
- wordWrap: "on",
53
- formatOnPaste: true,
54
- formatOnType: true,
55
- renderLineHighlight: "line",
56
- scrollbar: { verticalScrollbarSize: 8, horizontalScrollbarSize: 8 },
57
- } }) }));
43
+ return (_jsxs("div", { style: { width: "100%", minHeight, background: JimboColorOption.DARKEST }, children: [_jsx("style", { children: `
44
+ .monaco-editor .iPadShowKeyboard,
45
+ .monaco-editor [class*="iPadShowKeyboard"] { display: none !important; }
46
+ ` }), _jsx(Editor, { height: `${minHeight}px`, defaultLanguage: "yaml", value: value, theme: "jaml-balatro-dark", onChange: (next) => onChange(next ?? ""), beforeMount: defineBalatroTheme, options: {
47
+ minimap: { enabled: false },
48
+ scrollBeyondLastLine: false,
49
+ fontSize: 13,
50
+ lineHeight: 22,
51
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
52
+ lineNumbers: "on",
53
+ lineNumbersMinChars: 2,
54
+ lineDecorationsWidth: 4,
55
+ glyphMargin: false,
56
+ folding: false,
57
+ automaticLayout: true,
58
+ padding: { top: 12, bottom: 12 },
59
+ wordWrap: "on",
60
+ formatOnPaste: true,
61
+ formatOnType: true,
62
+ renderLineHighlight: "line",
63
+ scrollbar: { verticalScrollbarSize: 8, horizontalScrollbarSize: 8 },
64
+ // Mobile/chat-WebView UX: kill the context menu ("Change All Occurrences" etc. covering half
65
+ // the file on long-press) and the accessibility-help keyboard widget that's just clutter when
66
+ // the OS keyboard is already open.
67
+ contextmenu: false,
68
+ accessibilitySupport: "off",
69
+ } })] }));
58
70
  }
@@ -21,7 +21,9 @@ export interface JamlVisualFilter {
21
21
  export interface JamlIdeVisualProps {
22
22
  filter: JamlVisualFilter;
23
23
  onChange: (filter: JamlVisualFilter) => void;
24
- onSave?: () => void;
25
- onBack?: () => void;
24
+ /** Tap a clause to edit it (Pass 2 wires this to the cascade picker). */
25
+ onEditClause?: (zone: JamlZone, clause: JamlVisualClause) => void;
26
+ /** Tap the "?" mystery tile to add a new clause to a zone (Pass 2 wires this to the cascade picker). */
27
+ onAddClause?: (zone: JamlZone) => void;
26
28
  }
27
- export declare function JamlIdeVisual({ filter, onChange, onSave, onBack }: JamlIdeVisualProps): import("react/jsx-runtime").JSX.Element;
29
+ export declare function JamlIdeVisual({ filter, onChange, onEditClause, onAddClause }: JamlIdeVisualProps): import("react/jsx-runtime").JSX.Element;
@@ -1,15 +1,22 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { JimboColorOption } from "../ui/tokens.js";
5
5
  import { JimboSprite } from "../ui/sprites.js";
6
+ const C = JimboColorOption;
6
7
  const ZONE_META = {
7
- must: { label: "MUST", color: JimboColorOption.BLUE },
8
- should: { label: "SHOULD", color: JimboColorOption.RED },
9
- mustnot: { label: "MUST NOT", color: JimboColorOption.ORANGE },
8
+ must: { label: "MUST", hint: "Seed must contain all of these.", color: C.BLUE, accent: "#4db5ff" },
9
+ should: { label: "SHOULD", hint: "Bonus points per match.", color: C.RED, accent: "#ff8076" },
10
+ mustnot: { label: "MUST NOT", hint: "Seed is rejected if any appear.", color: C.ORANGE, accent: "#ffb84d" },
10
11
  };
11
12
  function clauseSpriteSheet(type) {
12
- if (type === "joker" || type === "souljoker" || type === "rareJoker" || type === "commonJoker" || type === "uncommonJoker" || type === "legendaryJoker" || type === "mixedJoker")
13
+ if (type === "joker" ||
14
+ type === "souljoker" ||
15
+ type === "rareJoker" ||
16
+ type === "commonJoker" ||
17
+ type === "uncommonJoker" ||
18
+ type === "legendaryJoker" ||
19
+ type === "mixedJoker")
13
20
  return "Jokers";
14
21
  if (type === "voucher")
15
22
  return "Vouchers";
@@ -21,44 +28,188 @@ function clauseSpriteSheet(type) {
21
28
  return "Tarots";
22
29
  return undefined;
23
30
  }
24
- function ClauseSprite({ clause, size = 26 }) {
31
+ function ClauseSprite({ clause, size = 40 }) {
25
32
  const sheet = clauseSpriteSheet(clause.type);
26
33
  if (!sheet)
27
34
  return null;
28
35
  return _jsx(JimboSprite, { name: clause.value, sheet: sheet, width: size });
29
36
  }
30
- function DragClausePill({ clause, zone, onDragStart, }) {
37
+ function ClauseCard({ clause, zone, onRemove, onEdit, onDragStart, }) {
31
38
  const z = ZONE_META[zone];
32
- return (_jsxs("div", { onMouseDown: (e) => onDragStart(e, clause, zone), onTouchStart: (e) => onDragStart(e, clause, zone), style: {
33
- display: "flex", alignItems: "center", gap: 6,
34
- background: JimboColorOption.DARK_GREY, border: `2px solid ${z.color}`,
35
- borderRadius: 6, padding: "5px 8px 5px 4px",
36
- boxShadow: `0 2px 0 ${JimboColorOption.BLACK}`,
37
- cursor: "grab", userSelect: "none", touchAction: "none",
38
- }, children: [_jsx("div", { style: { color: JimboColorOption.GREY, fontSize: 12, lineHeight: 1, padding: "0 2px" }, children: "\u22EE\u22EE" }), _jsx(ClauseSprite, { clause: clause, size: 26 }), _jsx("div", { style: { fontSize: 10, color: JimboColorOption.WHITE, letterSpacing: 1, textShadow: `1px 1px 0 ${JimboColorOption.BLACK}cc` }, children: clause.label || clause.value }), clause.antes && clause.antes.length > 0 && (_jsxs("div", { style: { display: "flex", gap: 2 }, children: [clause.antes.slice(0, 3).map((a) => (_jsx("div", { style: { fontSize: 8, padding: "0 3px", background: JimboColorOption.DARKEST, color: z.color, borderRadius: 2 }, children: a }, a))), clause.antes.length > 3 && _jsxs("div", { style: { fontSize: 8, color: JimboColorOption.GREY }, children: ["+", clause.antes.length - 3] })] })), clause.score != null && (_jsxs("div", { style: { fontSize: 9, padding: "0 4px", background: JimboColorOption.RED, color: JimboColorOption.WHITE, borderRadius: 2 }, children: ["+", clause.score] }))] }));
39
+ return (_jsxs("div", { onClick: onEdit, onMouseDown: (e) => onDragStart(e, clause, zone), onTouchStart: (e) => onDragStart(e, clause, zone), style: {
40
+ position: "relative",
41
+ background: C.DARK_GREY,
42
+ border: `2px solid ${z.color}`,
43
+ borderRadius: 6,
44
+ padding: "8px 8px 8px 6px",
45
+ display: "flex",
46
+ alignItems: "center",
47
+ gap: 8,
48
+ minWidth: 0,
49
+ cursor: "pointer",
50
+ userSelect: "none",
51
+ touchAction: "none",
52
+ boxShadow: `0 2px 0 ${C.BLACK}`,
53
+ }, children: [_jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: 44, height: 50, flexShrink: 0 }, children: _jsx(ClauseSprite, { clause: clause, size: 40 }) }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: {
54
+ fontFamily: "m6x11plus, ui-monospace, monospace",
55
+ fontSize: 13,
56
+ color: C.WHITE,
57
+ letterSpacing: 0.5,
58
+ whiteSpace: "nowrap",
59
+ overflow: "hidden",
60
+ textOverflow: "ellipsis",
61
+ }, children: clause.label || clause.value }), _jsxs("div", { style: { display: "flex", gap: 3, marginTop: 3, alignItems: "center", flexWrap: "wrap" }, children: [clause.antes && clause.antes.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { style: { fontFamily: "m6x11plus, ui-monospace, monospace", fontSize: 8, color: C.GREY, letterSpacing: 1 }, children: "A" }), clause.antes.map((a) => (_jsx("div", { style: {
62
+ fontFamily: "m6x11plus, ui-monospace, monospace",
63
+ fontSize: 9,
64
+ padding: "1px 4px",
65
+ background: C.DARKEST,
66
+ color: z.accent,
67
+ borderRadius: 3,
68
+ letterSpacing: 0.5,
69
+ lineHeight: 1,
70
+ }, children: a }, a)))] })), zone === "should" && clause.score != null && (_jsxs("div", { style: {
71
+ marginLeft: 4,
72
+ fontFamily: "m6x11plus, ui-monospace, monospace",
73
+ fontSize: 9,
74
+ padding: "1px 5px",
75
+ background: C.RED,
76
+ color: C.WHITE,
77
+ borderRadius: 3,
78
+ letterSpacing: 0.5,
79
+ lineHeight: 1,
80
+ }, children: ["+", clause.score] }))] })] }), _jsx("button", { onClick: (e) => {
81
+ e.stopPropagation();
82
+ onRemove();
83
+ }, "aria-label": `Remove ${clause.label || clause.value}`, style: {
84
+ width: 22,
85
+ height: 22,
86
+ flexShrink: 0,
87
+ border: `2px solid ${C.BLACK}`,
88
+ borderRadius: 4,
89
+ background: C.RED,
90
+ color: C.WHITE,
91
+ fontFamily: "m6x11plus, ui-monospace, monospace",
92
+ fontSize: 12,
93
+ lineHeight: 1,
94
+ cursor: "pointer",
95
+ padding: 0,
96
+ boxShadow: `inset 0 1px 0 rgba(255,255,255,.2), 0 2px 0 ${C.BLACK}`,
97
+ }, children: "\u00D7" })] }));
39
98
  }
40
- function ZoneDropRail({ zone, clauses, onDragStart, highlight, }) {
99
+ function MysteryAddTile({ zone, onTap }) {
100
+ const z = ZONE_META[zone];
101
+ return (_jsxs("div", { onClick: onTap, style: {
102
+ cursor: onTap ? "pointer" : "default",
103
+ opacity: onTap ? 1 : 0.55,
104
+ border: `2px dashed ${z.color}`,
105
+ borderRadius: 6,
106
+ padding: "12px 8px",
107
+ display: "flex",
108
+ alignItems: "center",
109
+ justifyContent: "center",
110
+ gap: 10,
111
+ background: `${z.color}0d`,
112
+ minHeight: 60,
113
+ }, children: [_jsx("div", { style: {
114
+ width: 40,
115
+ height: 40,
116
+ display: "flex",
117
+ alignItems: "center",
118
+ justifyContent: "center",
119
+ background: C.DARKEST,
120
+ border: `2px solid ${z.color}`,
121
+ borderRadius: 6,
122
+ fontFamily: "m6x11plus, ui-monospace, monospace",
123
+ fontSize: 24,
124
+ color: z.color,
125
+ }, children: "?" }), _jsxs("div", { style: {
126
+ fontFamily: "m6x11plus, ui-monospace, monospace",
127
+ fontSize: 12,
128
+ color: z.accent,
129
+ letterSpacing: 2,
130
+ }, children: ["ADD TO ", z.label] })] }));
131
+ }
132
+ function ZoneRail({ zone, clauses, onAdd, onRemove, onEdit, onDragStart, highlight, }) {
41
133
  const z = ZONE_META[zone];
42
134
  return (_jsxs("div", { "data-zone": zone, style: {
43
- border: `2px dashed ${highlight ? z.color : `${z.color}55`}`,
44
- background: highlight ? `${z.color}22` : "transparent",
45
- borderRadius: 6, padding: 8,
135
+ border: `2px dashed ${highlight ? z.color : "transparent"}`,
136
+ borderRadius: 6,
137
+ padding: highlight ? 6 : 0,
138
+ background: highlight ? `${z.color}11` : "transparent",
46
139
  transition: "background 100ms, border-color 100ms",
47
- }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }, children: [_jsx("div", { style: {
48
- fontSize: 10, letterSpacing: 2, padding: "2px 8px",
49
- background: z.color, color: JimboColorOption.WHITE, borderRadius: 3,
50
- textShadow: `1px 1px 0 ${JimboColorOption.BLACK}cc`,
51
- }, children: z.label }), _jsx("div", { style: { flex: 1, height: 1, background: `${z.color}44` } }), _jsx("div", { style: { fontSize: 8, color: JimboColorOption.GREY }, children: clauses.length })] }), _jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: [clauses.map((c) => (_jsx(DragClausePill, { clause: c, zone: zone, onDragStart: onDragStart }, c.id))), clauses.length === 0 && (_jsx("div", { style: { fontSize: 10, color: JimboColorOption.GREY, padding: 10, fontStyle: "italic" }, children: "drop clauses here" }))] })] }));
140
+ }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 6 }, children: [_jsx("div", { style: {
141
+ fontFamily: "m6x11plus, ui-monospace, monospace",
142
+ fontSize: 11,
143
+ padding: "2px 8px",
144
+ background: z.color,
145
+ color: C.WHITE,
146
+ borderRadius: 3,
147
+ letterSpacing: 2,
148
+ boxShadow: `0 2px 0 ${C.BLACK}`,
149
+ }, children: z.label }), _jsx("div", { style: { flex: 1, height: 2, background: `${z.color}55`, borderRadius: 1 } }), _jsx("div", { style: { fontFamily: "m6x11plus, ui-monospace, monospace", fontSize: 8, color: C.GREY }, children: clauses.length })] }), _jsx("div", { style: { fontFamily: "m6x11plus, ui-monospace, monospace", fontSize: 9, color: C.GREY, letterSpacing: 0.5, marginBottom: 8 }, children: z.hint }), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [clauses.map((c) => (_jsx(ClauseCard, { clause: c, zone: zone, onRemove: () => onRemove(c.id), onEdit: () => onEdit(c), onDragStart: onDragStart }, c.id))), _jsx(MysteryAddTile, { zone: zone, onTap: onAdd })] })] }));
52
150
  }
53
- export function JamlIdeVisual({ filter, onChange, onSave, onBack }) {
151
+ function TopMatter({ filter, onChange, }) {
152
+ return (_jsxs("div", { style: {
153
+ background: C.DARK_GREY,
154
+ borderRadius: 6,
155
+ padding: 10,
156
+ border: `2px solid ${C.PANEL_EDGE}`,
157
+ boxShadow: `0 2px 0 ${C.BLACK}`,
158
+ }, children: [_jsx("input", { value: filter.name ?? "", placeholder: "Untitled", onChange: (e) => onChange({ ...filter, name: e.target.value }), style: {
159
+ display: "block",
160
+ width: "100%",
161
+ background: "transparent",
162
+ border: "none",
163
+ outline: "none",
164
+ fontFamily: "m6x11plus, ui-monospace, monospace",
165
+ fontSize: 18,
166
+ color: C.WHITE,
167
+ letterSpacing: 1,
168
+ padding: 0,
169
+ marginBottom: 4,
170
+ } }), _jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [_jsx("div", { style: { fontFamily: "m6x11plus, ui-monospace, monospace", fontSize: 9, color: C.GREY, letterSpacing: 2 }, children: "BY" }), _jsx("input", { value: filter.author ?? "", placeholder: "anonymous", onChange: (e) => onChange({ ...filter, author: e.target.value }), style: {
171
+ flex: 1,
172
+ background: "transparent",
173
+ border: "none",
174
+ outline: "none",
175
+ fontFamily: "m6x11plus, ui-monospace, monospace",
176
+ fontSize: 12,
177
+ color: C.GOLD_TEXT,
178
+ letterSpacing: 1,
179
+ padding: 0,
180
+ } })] }), _jsx("input", { value: filter.description ?? "", placeholder: "description", onChange: (e) => onChange({ ...filter, description: e.target.value }), style: {
181
+ display: "block",
182
+ width: "100%",
183
+ marginTop: 6,
184
+ background: "transparent",
185
+ border: "none",
186
+ outline: "none",
187
+ fontFamily: "m6x11plus, ui-monospace, monospace",
188
+ fontSize: 10,
189
+ color: C.GREY,
190
+ lineHeight: 1.35,
191
+ padding: 0,
192
+ } })] }));
193
+ }
194
+ export function JamlIdeVisual({ filter, onChange, onEditClause, onAddClause }) {
54
195
  const [drag, setDrag] = useState(null);
55
196
  const [hoverZone, setHoverZone] = useState(null);
56
197
  const rootRef = useRef(null);
198
+ const removeClause = (zone, id) => {
199
+ onChange({ ...filter, [zone]: filter[zone].filter((c) => c.id !== id) });
200
+ };
57
201
  const onDragStart = (e, clause, fromZone) => {
58
- e.preventDefault();
202
+ // Don't preventDefault; we want clicks to still fire if there's no actual drag.
59
203
  const t = "touches" in e ? e.touches[0] : e;
60
204
  const rect = e.currentTarget.getBoundingClientRect();
61
- setDrag({ clause, fromZone, x: t.clientX, y: t.clientY, offX: t.clientX - rect.left, offY: t.clientY - rect.top, w: rect.width, h: rect.height });
205
+ setDrag({
206
+ clause,
207
+ fromZone,
208
+ x: t.clientX,
209
+ y: t.clientY,
210
+ offX: t.clientX - rect.left,
211
+ offY: t.clientY - rect.top,
212
+ });
62
213
  };
63
214
  useEffect(() => {
64
215
  if (!drag)
@@ -79,11 +230,11 @@ export function JamlIdeVisual({ filter, onChange, onSave, onBack }) {
79
230
  };
80
231
  const up = () => {
81
232
  if (hoverZone && hoverZone !== drag.fromZone) {
82
- const from = hoverZone;
233
+ const to = hoverZone;
83
234
  onChange({
84
235
  ...filter,
85
236
  [drag.fromZone]: filter[drag.fromZone].filter((c) => c.id !== drag.clause.id),
86
- [from]: [...filter[from], { ...drag.clause }],
237
+ [to]: [...filter[to], { ...drag.clause }],
87
238
  });
88
239
  }
89
240
  setDrag(null);
@@ -100,14 +251,21 @@ export function JamlIdeVisual({ filter, onChange, onSave, onBack }) {
100
251
  window.removeEventListener("touchend", up);
101
252
  };
102
253
  }, [drag, hoverZone, filter, onChange]);
103
- return (_jsxs("div", { ref: rootRef, style: { display: "flex", flexDirection: "column", gap: 10, padding: 10 }, children: [_jsxs("div", { style: {
104
- background: JimboColorOption.DARK_GREY, border: `2px solid ${JimboColorOption.PANEL_EDGE}`,
105
- borderRadius: 6, padding: 8, boxShadow: `0 2px 0 ${JimboColorOption.BLACK}`,
106
- }, children: [_jsx("div", { style: { fontSize: 9, color: JimboColorOption.GREY, letterSpacing: 2 }, children: "FILE" }), _jsxs("div", { style: { fontSize: 14, color: JimboColorOption.WHITE, textShadow: `1px 1px 0 ${JimboColorOption.BLACK}cc` }, children: [filter.name || "Untitled", ".jaml"] }), filter.author && (_jsxs("div", { style: { fontSize: 9, color: JimboColorOption.GOLD_TEXT, marginTop: 2 }, children: ["by ", filter.author] }))] }), _jsx(ZoneDropRail, { zone: "must", clauses: filter.must, onDragStart: onDragStart, highlight: hoverZone === "must" }), _jsx(ZoneDropRail, { zone: "should", clauses: filter.should, onDragStart: onDragStart, highlight: hoverZone === "should" }), _jsx(ZoneDropRail, { zone: "mustnot", clauses: filter.mustnot, onDragStart: onDragStart, highlight: hoverZone === "mustnot" }), drag && (_jsx("div", { style: {
254
+ return (_jsxs("div", { ref: rootRef, style: {
255
+ display: "flex",
256
+ flexDirection: "column",
257
+ gap: 14,
258
+ padding: 10,
259
+ background: C.DARKEST,
260
+ color: C.WHITE,
261
+ }, children: [_jsx(TopMatter, { filter: filter, onChange: onChange }), ["must", "should", "mustnot"].map((zone) => (_jsx(ZoneRail, { zone: zone, clauses: filter[zone], onAdd: onAddClause ? () => onAddClause(zone) : undefined, onRemove: (id) => removeClause(zone, id), onEdit: (c) => onEditClause?.(zone, c), onDragStart: onDragStart, highlight: hoverZone === zone }, zone))), drag && (_jsx("div", { style: {
107
262
  position: "fixed",
108
- left: drag.x - drag.offX, top: drag.y - drag.offY,
109
- pointerEvents: "none", zIndex: 999,
263
+ left: drag.x - drag.offX,
264
+ top: drag.y - drag.offY,
265
+ pointerEvents: "none",
266
+ zIndex: 999,
110
267
  transform: "rotate(-2deg) scale(1.05)",
111
- filter: `drop-shadow(0 4px 6px ${JimboColorOption.BLACK}99)`, opacity: 0.92,
112
- }, children: _jsx(DragClausePill, { clause: drag.clause, zone: drag.fromZone, onDragStart: () => { } }) }))] }));
268
+ filter: `drop-shadow(0 4px 6px ${C.BLACK}99)`,
269
+ opacity: 0.92,
270
+ }, children: _jsx(ClauseCard, { clause: drag.clause, zone: drag.fromZone, onRemove: () => { }, onEdit: () => { }, onDragStart: () => { } }) }))] }));
113
271
  }
@@ -1,10 +1,6 @@
1
1
  export interface JamlMapPreviewProps {
2
2
  jaml: string;
3
3
  className?: string;
4
- title?: string;
5
4
  emptyMessage?: string;
6
- cardScale?: number;
7
- tagScale?: number;
8
- bossScale?: number;
9
5
  }
10
- export declare function JamlMapPreview({ jaml, className, title, emptyMessage, cardScale, tagScale, bossScale, }: JamlMapPreviewProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function JamlMapPreview({ jaml, className, emptyMessage, }: JamlMapPreviewProps): import("react/jsx-runtime").JSX.Element;