jaml-ui 0.21.4 → 0.22.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/dist/assets.d.ts CHANGED
@@ -15,6 +15,4 @@ export declare const JAML_ASSET_FILES: {
15
15
  export type JamlAssetKey = keyof typeof JAML_ASSET_FILES;
16
16
  export type JamlAssetFile = (typeof JAML_ASSET_FILES)[JamlAssetKey];
17
17
  export declare function setJamlAssetBaseUrl(baseUrl: string | null | undefined): void;
18
- export declare function clearJamlAssetBaseUrl(): void;
19
18
  export declare function resolveJamlAssetUrl(asset: JamlAssetKey | JamlAssetFile): string;
20
- export declare function getDefaultJamlAssetUrlMap(): Readonly<Record<JamlAssetKey, string>>;
package/dist/assets.js CHANGED
@@ -13,28 +13,13 @@ export const JAML_ASSET_FILES = {
13
13
  font: "fonts/m6x11plusplus.otf",
14
14
  };
15
15
  const assetKeyByFileName = Object.fromEntries(Object.entries(JAML_ASSET_FILES).map(([key, fileName]) => [fileName, key]));
16
- const defaultAssetUrls = {
17
- deck: new URL(`../assets/${JAML_ASSET_FILES.deck}`, import.meta.url).href,
18
- blinds: new URL(`../assets/${JAML_ASSET_FILES.blinds}`, import.meta.url).href,
19
- boosters: new URL(`../assets/${JAML_ASSET_FILES.boosters}`, import.meta.url).href,
20
- editions: new URL(`../assets/${JAML_ASSET_FILES.editions}`, import.meta.url).href,
21
- enhancers: new URL(`../assets/${JAML_ASSET_FILES.enhancers}`, import.meta.url).href,
22
- jokers: new URL(`../assets/${JAML_ASSET_FILES.jokers}`, import.meta.url).href,
23
- tarots: new URL(`../assets/${JAML_ASSET_FILES.tarots}`, import.meta.url).href,
24
- vouchers: new URL(`../assets/${JAML_ASSET_FILES.vouchers}`, import.meta.url).href,
25
- stickers: new URL(`../assets/${JAML_ASSET_FILES.stickers}`, import.meta.url).href,
26
- tags: new URL(`../assets/${JAML_ASSET_FILES.tags}`, import.meta.url).href,
27
- stakes: new URL(`../assets/${JAML_ASSET_FILES.stakes}`, import.meta.url).href,
28
- font: new URL(`../assets/${JAML_ASSET_FILES.font}`, import.meta.url).href,
29
- };
16
+ const defaultAssetUrls = Object.fromEntries(Object.entries(JAML_ASSET_FILES).map(([key, fileName]) => [key, new URL(`../assets/${fileName}`, import.meta.url).href]));
30
17
  let customAssetBaseUrl = null;
31
18
  function normalizeBaseUrl(baseUrl) {
32
- const trimmed = baseUrl.trim();
33
- if (trimmed.length === 0) {
34
- throw new Error("Jaml asset base URL must not be empty.");
35
- }
36
- return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
19
+ return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
37
20
  }
21
+ // `new URL(file, base)` requires `base` to be absolute. weejoker.app passes
22
+ // "/assets" (relative path), so we fall back to string concatenation for that case.
38
23
  function joinAssetUrl(baseUrl, fileName) {
39
24
  const normalized = normalizeBaseUrl(baseUrl);
40
25
  if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(normalized) || normalized.startsWith("//")) {
@@ -50,9 +35,6 @@ export function setJamlAssetBaseUrl(baseUrl) {
50
35
  const trimmed = baseUrl.trim();
51
36
  customAssetBaseUrl = trimmed.length === 0 ? null : normalizeBaseUrl(trimmed);
52
37
  }
53
- export function clearJamlAssetBaseUrl() {
54
- customAssetBaseUrl = null;
55
- }
56
38
  export function resolveJamlAssetUrl(asset) {
57
39
  const assetKey = asset in JAML_ASSET_FILES
58
40
  ? asset
@@ -60,11 +42,7 @@ export function resolveJamlAssetUrl(asset) {
60
42
  if (!assetKey) {
61
43
  throw new Error(`Unknown Jaml asset '${asset}'.`);
62
44
  }
63
- if (customAssetBaseUrl) {
64
- return joinAssetUrl(customAssetBaseUrl, JAML_ASSET_FILES[assetKey]);
65
- }
66
- return defaultAssetUrls[assetKey];
67
- }
68
- export function getDefaultJamlAssetUrlMap() {
69
- return defaultAssetUrls;
45
+ return customAssetBaseUrl
46
+ ? joinAssetUrl(customAssetBaseUrl, JAML_ASSET_FILES[assetKey])
47
+ : defaultAssetUrls[assetKey];
70
48
  }
@@ -1,3 +1,5 @@
1
+ import { type MotelyRuntime } from "../hooks/useAnalyzer.js";
1
2
  export interface JamlCuratorProps {
3
+ motelyRuntime: MotelyRuntime;
2
4
  }
3
- export declare function JamlCurator({}: JamlCuratorProps): import("react/jsx-runtime").JSX.Element;
5
+ export declare function JamlCurator({ motelyRuntime }: JamlCuratorProps): import("react/jsx-runtime").JSX.Element;
@@ -11,11 +11,11 @@ import { useSearch } from "../hooks/useSearch.js";
11
11
  import { useAnalyzer } from "../hooks/useAnalyzer.js";
12
12
  import { JamlSpeedometer } from "./JamlSpeedometer.js";
13
13
  const C = JimboColorOption;
14
- export function JamlCurator({}) {
14
+ export function JamlCurator({ motelyRuntime }) {
15
15
  // Use map editor by default to generate JAML
16
16
  const [jamlText, setJamlText] = useState("");
17
17
  const search = useSearch();
18
- const analyzer = useAnalyzer();
18
+ const analyzer = useAnalyzer(motelyRuntime);
19
19
  // Search results pagination
20
20
  const [resultIndex, setResultIndex] = useState(0);
21
21
  const isSearching = search.status === "running";
package/dist/core.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { JAML_ASSET_FILES, clearJamlAssetBaseUrl, getDefaultJamlAssetUrlMap, resolveJamlAssetUrl, setJamlAssetBaseUrl, type JamlAssetFile, type JamlAssetKey, } from "./assets.js";
1
+ export { JAML_ASSET_FILES, resolveJamlAssetUrl, setJamlAssetBaseUrl, type JamlAssetFile, type JamlAssetKey, } from "./assets.js";
2
2
  export { Layer, type LayerOptions } from "./render/Layer.js";
3
3
  export { getSpriteData, type SpriteData, type SpriteSheetType } from "./sprites/spriteMapper.js";
4
4
  export { SPRITE_SHEETS, JOKERS, JOKER_FACES, TAROTS_AND_PLANETS, CONSUMABLE_FACES, VOUCHERS, BOSSES, TAGS, BOOSTER_PACKS, EDITION_MAP, STICKER_MAP, RANK_MAP, SUIT_MAP, ENHANCER_MAP, SEAL_MAP, type SpritePos, type SpriteEntry, type SpriteSheetInfo, } from "./sprites/spriteData.js";
package/dist/core.js CHANGED
@@ -1,4 +1,4 @@
1
- export { JAML_ASSET_FILES, clearJamlAssetBaseUrl, getDefaultJamlAssetUrlMap, resolveJamlAssetUrl, setJamlAssetBaseUrl, } from "./assets.js";
1
+ export { JAML_ASSET_FILES, resolveJamlAssetUrl, setJamlAssetBaseUrl, } from "./assets.js";
2
2
  export { Layer } from "./render/Layer.js";
3
3
  export { getSpriteData } from "./sprites/spriteMapper.js";
4
4
  export { SPRITE_SHEETS, JOKERS, JOKER_FACES, TAROTS_AND_PLANETS, CONSUMABLE_FACES, VOUCHERS, BOSSES, TAGS, BOOSTER_PACKS, EDITION_MAP, STICKER_MAP, RANK_MAP, SUIT_MAP, ENHANCER_MAP, SEAL_MAP, } from "./sprites/spriteData.js";
@@ -1,7 +1,13 @@
1
1
  /**
2
2
  * Motely item decoder — thin wrapper over motely-wasm runtime enums.
3
3
  * No hand-rolled bitmask tables. The WASM enum IS the source of truth.
4
+ *
5
+ * Consumers must call `setMotelyEnums(Motely)` once after `await bootsharp.boot()`
6
+ * for runtime enum lookups to resolve. Before that, decoders return placeholder
7
+ * strings rather than throwing.
4
8
  */
9
+ import type { Motely as MotelyEnumsType } from "motely-wasm";
10
+ export declare function setMotelyEnums(motely: typeof MotelyEnumsType): void;
5
11
  export type CardCategory = "joker" | "consumable" | "playing" | "spectral" | "tarot" | "planet";
6
12
  export type MotelyRenderableCategory = CardCategory | "unknown";
7
13
  export type MotelyItemInput = number | MotelyRuntimeItem | null | undefined;
@@ -1,8 +1,31 @@
1
1
  /**
2
2
  * Motely item decoder — thin wrapper over motely-wasm runtime enums.
3
3
  * No hand-rolled bitmask tables. The WASM enum IS the source of truth.
4
+ *
5
+ * Consumers must call `setMotelyEnums(Motely)` once after `await bootsharp.boot()`
6
+ * for runtime enum lookups to resolve. Before that, decoders return placeholder
7
+ * strings rather than throwing.
4
8
  */
5
- import { Motely } from "motely-wasm";
9
+ let _motely = null;
10
+ let _categoryMap = null;
11
+ export function setMotelyEnums(motely) {
12
+ _motely = motely;
13
+ _categoryMap = null;
14
+ }
15
+ function getCategoryMap() {
16
+ if (_categoryMap)
17
+ return _categoryMap;
18
+ if (!_motely)
19
+ return {};
20
+ _categoryMap = {
21
+ [_motely.MotelyItemTypeCategory.Standardcard]: "playing",
22
+ [_motely.MotelyItemTypeCategory.SpectralCard]: "spectral",
23
+ [_motely.MotelyItemTypeCategory.TarotCard]: "tarot",
24
+ [_motely.MotelyItemTypeCategory.PlanetCard]: "planet",
25
+ [_motely.MotelyItemTypeCategory.Joker]: "joker",
26
+ };
27
+ return _categoryMap;
28
+ }
6
29
  // ─── Helpers using motely-wasm runtime enums directly ────────────────────────
7
30
  function enumKey(e, value) {
8
31
  const k = e[String(value)];
@@ -11,13 +34,6 @@ function enumKey(e, value) {
11
34
  function spaceSplit(value) {
12
35
  return value.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
13
36
  }
14
- const CATEGORY_MAP = {
15
- [Motely.MotelyItemTypeCategory.Standardcard]: "playing",
16
- [Motely.MotelyItemTypeCategory.SpectralCard]: "spectral",
17
- [Motely.MotelyItemTypeCategory.TarotCard]: "tarot",
18
- [Motely.MotelyItemTypeCategory.PlanetCard]: "planet",
19
- [Motely.MotelyItemTypeCategory.Joker]: "joker",
20
- };
21
37
  // ─── Core decoder ────────────────────────────────────────────────────────────
22
38
  function resolvePackedValue(input) {
23
39
  if (input == null)
@@ -34,11 +50,13 @@ export function motelyItemTypeName(input) {
34
50
  const itemType = resolveMotelyItemType(input);
35
51
  if (itemType === null)
36
52
  return "Unknown";
37
- return enumKey(Motely.MotelyItemType, itemType) ?? `item#${itemType}`;
53
+ if (!_motely)
54
+ return `item#${itemType}`;
55
+ return enumKey(_motely.MotelyItemType, itemType) ?? `item#${itemType}`;
38
56
  }
39
57
  export function motelyItemCategory(itemType) {
40
58
  const catValue = (itemType >> 12) & 0xf;
41
- return CATEGORY_MAP[catValue] ?? "unknown";
59
+ return getCategoryMap()[catValue] ?? "unknown";
42
60
  }
43
61
  export function motelyItemRenderCategory(input) {
44
62
  const itemType = resolveMotelyItemType(input);
@@ -50,53 +68,53 @@ export function motelyItemDisplayName(input) {
50
68
  return spaceSplit(motelyItemTypeName(input));
51
69
  }
52
70
  export function motelyItemEditionName(input) {
53
- if (input == null)
71
+ if (input == null || !_motely)
54
72
  return null;
55
73
  const val = typeof input === "number" ? input : input.edition;
56
74
  if (val == null)
57
75
  return null;
58
- const key = enumKey(Motely.MotelyItemEdition, typeof val === "number" ? val : 0);
76
+ const key = enumKey(_motely.MotelyItemEdition, typeof val === "number" ? val : 0);
59
77
  if (!key || key === "None")
60
78
  return null;
61
79
  return key;
62
80
  }
63
81
  export function motelyItemSealName(input) {
64
- if (input == null)
82
+ if (input == null || !_motely)
65
83
  return null;
66
84
  const val = typeof input === "number" ? null : input.seal;
67
85
  if (val == null)
68
86
  return null;
69
- const key = enumKey(Motely.MotelyItemSeal, val);
87
+ const key = enumKey(_motely.MotelyItemSeal, val);
70
88
  if (!key || key === "None")
71
89
  return null;
72
90
  return key;
73
91
  }
74
92
  export function motelyItemEnhancementName(input) {
75
- if (input == null)
93
+ if (input == null || !_motely)
76
94
  return null;
77
95
  const val = typeof input === "number" ? null : input.enhancement;
78
96
  if (val == null)
79
97
  return null;
80
- const key = enumKey(Motely.MotelyItemEnhancement, val);
98
+ const key = enumKey(_motely.MotelyItemEnhancement, val);
81
99
  if (!key || key === "None")
82
100
  return null;
83
101
  return key;
84
102
  }
85
103
  export function motelyStandardcardRankName(input) {
86
- if (input == null)
104
+ if (input == null || !_motely)
87
105
  return null;
88
106
  const val = typeof input === "number" ? null : input.rank;
89
107
  if (val == null)
90
108
  return null;
91
- return enumKey(Motely.MotelyStandardcardRank, val);
109
+ return enumKey(_motely.MotelyStandardcardRank, val);
92
110
  }
93
111
  export function motelyStandardcardSuitName(input) {
94
- if (input == null)
112
+ if (input == null || !_motely)
95
113
  return null;
96
114
  const val = typeof input === "number" ? null : input.suit;
97
115
  if (val == null)
98
116
  return null;
99
- return enumKey(Motely.MotelyStandardcardSuit, val);
117
+ return enumKey(_motely.MotelyStandardcardSuit, val);
100
118
  }
101
119
  export function decodeMotelyItemName(input) {
102
120
  return motelyItemTypeName(input);
@@ -105,7 +123,9 @@ export function decodeMotelyItem(input) {
105
123
  const itemType = resolveMotelyItemType(input);
106
124
  if (itemType === null)
107
125
  return null;
108
- const enumKeyStr = enumKey(Motely.MotelyItemType, itemType) ?? `Unknown_${itemType}`;
126
+ const enumKeyStr = _motely
127
+ ? enumKey(_motely.MotelyItemType, itemType) ?? `Unknown_${itemType}`
128
+ : `Unknown_${itemType}`;
109
129
  const category = motelyItemCategory(itemType);
110
130
  const displayName = spaceSplit(enumKeyStr);
111
131
  return {
@@ -140,6 +160,5 @@ export function decodeMotelyItemToJamlCard(input, scale) {
140
160
  },
141
161
  };
142
162
  }
143
- // Cache warming is now a no-op since we use runtime enums directly
144
163
  export function warmMotelyItemCache() { }
145
164
  export function motelyItemCacheSize() { return 0; }
@@ -1,4 +1,4 @@
1
- import { MotelyWasm, Motely } from "motely-wasm";
1
+ import type { MotelyWasm as MotelyWasmType, Motely as MotelyEnumsType } from "motely-wasm";
2
2
  import type { AnalyzerAnteView } from "../components/AnalyzerExplorer.js";
3
3
  export type AnalyzerStatus = "idle" | "running" | "done" | "error";
4
4
  export type MotelyJsRunState = {
@@ -6,23 +6,25 @@ export type MotelyJsRunState = {
6
6
  bossBitfield: number;
7
7
  };
8
8
  /**
9
- * Snapshot of the live search context after `analyze()` resolves, exposed so
10
- * higher-level components can open additional streams (shop chunks, soul-
11
- * joker chunks, pack contents) on demand without re-walking the seed. The
12
- * `runStates` map is keyed by ante and holds the runState AFTER the boss +
13
- * voucher have been resolved for that ante — i.e. the correct input for
14
- * `createShopItemStream(ante, runState, ...)`.
9
+ * Runtime handle for motely-wasm. Consumers boot motely-wasm once and pass
10
+ * `{ MotelyWasm, Motely }` to hooks that need it. This keeps jaml-ui free of
11
+ * static motely-wasm imports so consumer bundlers don't pull the 12MB engine
12
+ * into their main bundle.
15
13
  */
14
+ export interface MotelyRuntime {
15
+ MotelyWasm: typeof MotelyWasmType;
16
+ Motely: typeof MotelyEnumsType;
17
+ }
16
18
  export interface AnalyzerLive {
17
- ctx: ReturnType<typeof MotelyWasm.createSearchContext>;
18
- Motely: typeof Motely;
19
+ ctx: ReturnType<typeof MotelyWasmType.createSearchContext>;
20
+ Motely: typeof MotelyEnumsType;
19
21
  runStates: Record<number, MotelyJsRunState>;
20
22
  desiredNames: ReadonlySet<string>;
21
23
  seed: string;
22
24
  deck: string;
23
25
  stake: string;
24
26
  }
25
- export declare function useAnalyzer(): {
27
+ export declare function useAnalyzer(runtime: MotelyRuntime): {
26
28
  antes: AnalyzerAnteView[];
27
29
  status: AnalyzerStatus;
28
30
  error: string | null;
@@ -1,11 +1,9 @@
1
1
  "use client";
2
2
  import { useState, useCallback } from "react";
3
- import motely, { MotelyWasm, Motely } from "motely-wasm";
4
- // Boot motely immediately when this module is loaded
5
- motely.boot().catch(console.error);
6
3
  import { extractVisualJamlItems } from "../utils/jamlMapPreview.js";
7
4
  import { motelyItemDisplayNameFromValue } from "../motelyDisplay.js";
8
- export function useAnalyzer() {
5
+ export function useAnalyzer(runtime) {
6
+ const { MotelyWasm, Motely } = runtime;
9
7
  const [antes, setAntes] = useState([]);
10
8
  const [status, setStatus] = useState("idle");
11
9
  const [error, setError] = useState(null);
@@ -79,7 +77,7 @@ export function useAnalyzer() {
79
77
  setError(e instanceof Error ? e.message : String(e));
80
78
  setStatus("error");
81
79
  }
82
- }, []);
80
+ }, [MotelyWasm, Motely]);
83
81
  const clearError = useCallback(() => {
84
82
  setError(null);
85
83
  setStatus((s) => (s === "error" ? "idle" : s));
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { JAML_ASSET_FILES, clearJamlAssetBaseUrl, getDefaultJamlAssetUrlMap, resolveJamlAssetUrl, setJamlAssetBaseUrl, type JamlAssetFile, type JamlAssetKey, } from "./assets.js";
1
+ export { JAML_ASSET_FILES, resolveJamlAssetUrl, setJamlAssetBaseUrl, type JamlAssetFile, type JamlAssetKey, } from "./assets.js";
2
2
  export { Layer, type LayerOptions } from "./render/Layer.js";
3
3
  export { JamlCardRenderer, type JamlCardRendererProps } from "./render/CanvasRenderer.js";
4
4
  export { JamlGameCard, JamlVoucher, JamlTag, JamlBoss, resolveAnalyzerShopItem, type JamlGameCardProps, type AnalyzerShopItem, type AnalyzerResolvedItem, } from "./components/GameCard.js";
@@ -21,7 +21,9 @@ export { Showcase, type ShowcaseFilter, type ShowcaseLiveStats, type ShowcasePro
21
21
  export { extractVisualJamlItems, type JamlPreviewGroups, type JamlPreviewItem, type JamlPreviewSection, type JamlPreviewVisualType, } from "./utils/jamlMapPreview.js";
22
22
  export { useMotelyStream, type StreamItem, type StreamState } from "./hooks/useShopStream.js";
23
23
  export { useSearch, type SearchResult, type SearchStatus, type UseSearchState, } from "./hooks/useSearch.js";
24
- export { useAnalyzer, type AnalyzerStatus, type AnalyzerLive, type MotelyJsRunState, } from "./hooks/useAnalyzer.js";
24
+ export { useAnalyzer, type AnalyzerStatus, type AnalyzerLive, type MotelyJsRunState, type MotelyRuntime, } from "./hooks/useAnalyzer.js";
25
+ export { setMotelyEnums as setMotelyDisplayEnums } from "./motelyDisplay.js";
26
+ export { setMotelyEnums as setMotelyDecoderEnums } from "./decode/motelyItemDecoder.js";
25
27
  export { JamlAestheticSelector, type JamlAestheticSelectorProps, type JamlAestheticOption, } from "./components/JamlAestheticSelector.js";
26
28
  export { JamlSeedInput, type JamlSeedInputProps, } from "./components/JamlSeedInput.js";
27
29
  export { JamlMapEditor, JokerPicker, MysterySlot, CategoryPicker, type JamlMapEditorProps, type JokerPickerProps, type JokerRarity, type MysterySlotProps, type SlotCategory, type SlotSelection, type CategoryPickerConfig, type CategoryPickerProps, VOUCHER_PICKER_CONFIG, TAG_PICKER_CONFIG, BOSS_PICKER_CONFIG, TAROT_PICKER_CONFIG, PLANET_PICKER_CONFIG, SPECTRAL_PICKER_CONFIG, PACK_PICKER_CONFIG, } from "./components/jamlMap/index.js";
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- export { JAML_ASSET_FILES, clearJamlAssetBaseUrl, getDefaultJamlAssetUrlMap, resolveJamlAssetUrl, setJamlAssetBaseUrl, } from "./assets.js";
2
+ export { JAML_ASSET_FILES, resolveJamlAssetUrl, setJamlAssetBaseUrl, } from "./assets.js";
3
3
  export { Layer } from "./render/Layer.js";
4
4
  export { JamlCardRenderer } from "./render/CanvasRenderer.js";
5
5
  export { JamlGameCard, JamlVoucher, JamlTag, JamlBoss, resolveAnalyzerShopItem, } from "./components/GameCard.js";
@@ -23,6 +23,11 @@ export { extractVisualJamlItems, } from "./utils/jamlMapPreview.js";
23
23
  export { useMotelyStream } from "./hooks/useShopStream.js";
24
24
  export { useSearch, } from "./hooks/useSearch.js";
25
25
  export { useAnalyzer, } from "./hooks/useAnalyzer.js";
26
+ // Setter pattern for motely-wasm runtime enums. Consumers boot motely-wasm
27
+ // and call setMotelyEnums(Motely) once after boot so display/decoder helpers
28
+ // can resolve enum keys without statically importing motely-wasm.
29
+ export { setMotelyEnums as setMotelyDisplayEnums } from "./motelyDisplay.js";
30
+ export { setMotelyEnums as setMotelyDecoderEnums } from "./decode/motelyItemDecoder.js";
26
31
  export { JamlAestheticSelector, } from "./components/JamlAestheticSelector.js";
27
32
  export { JamlSeedInput, } from "./components/JamlSeedInput.js";
28
33
  export { JamlMapEditor, JokerPicker, MysterySlot, CategoryPicker, VOUCHER_PICKER_CONFIG, TAG_PICKER_CONFIG, BOSS_PICKER_CONFIG, TAROT_PICKER_CONFIG, PLANET_PICKER_CONFIG, SPECTRAL_PICKER_CONFIG, PACK_PICKER_CONFIG, } from "./components/jamlMap/index.js";
@@ -27,7 +27,7 @@ export interface JamlFilter {
27
27
  should: JamlClause[];
28
28
  mustNot: JamlClause[];
29
29
  }
30
- import { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS } from '@/lib/data/constants';
30
+ import { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS } from '../data/constants.js';
31
31
  export { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS };
32
32
  export declare function useJamlFilter(initialJaml?: string): {
33
33
  filter: JamlFilter;
@@ -1,5 +1,5 @@
1
1
  import { useState, useCallback, useMemo } from 'react';
2
- import { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS } from '@/lib/data/constants';
2
+ import { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS } from '../data/constants.js';
3
3
  export { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS };
4
4
  export function useJamlFilter(initialJaml) {
5
5
  const [filter, setFilter] = useState(parseJamlToFilter(initialJaml || ''));
@@ -1,5 +1,9 @@
1
- import { Analysis } from 'motely-wasm';
2
- export declare function useSeedAnalyzer(seed: string | null): {
1
+ import type { MotelyWasm as MotelyWasmType, Motely as MotelyEnumsType, Analysis } from "motely-wasm";
2
+ export interface MotelyRuntime {
3
+ MotelyWasm: typeof MotelyWasmType;
4
+ Motely: typeof MotelyEnumsType;
5
+ }
6
+ export declare function useSeedAnalyzer(runtime: MotelyRuntime, seed: string | null): {
3
7
  data: Analysis.MotelyLegacyTextAnalyzer | null | undefined;
4
8
  loading: boolean;
5
9
  error: string | null;
@@ -1,7 +1,6 @@
1
1
  "use client";
2
- import { useState, useEffect } from 'react';
3
- import motely, { MotelyWasm } from 'motely-wasm';
4
- export function useSeedAnalyzer(seed) {
2
+ import { useState, useEffect } from "react";
3
+ export function useSeedAnalyzer(runtime, seed) {
5
4
  const [data, setData] = useState(null);
6
5
  const [loading, setLoading] = useState(false);
7
6
  const [error, setError] = useState(null);
@@ -15,11 +14,8 @@ export function useSeedAnalyzer(seed) {
15
14
  setLoading(true);
16
15
  setError(null);
17
16
  try {
18
- await motely.boot();
19
- if (abortController.signal.aborted)
20
- return;
21
17
  const jaml = `version: 1\nconfig:\n deck: Erratic\n stake: White\n`;
22
- const rawResult = MotelyWasm.analyzeJamlSeeds(jaml, [seed]);
18
+ const rawResult = runtime.MotelyWasm.analyzeJamlSeeds(jaml, [seed]);
23
19
  if (abortController.signal.aborted)
24
20
  return;
25
21
  if (rawResult && rawResult.seeds.length > 0) {
@@ -43,6 +39,6 @@ export function useSeedAnalyzer(seed) {
43
39
  };
44
40
  runAnalysis();
45
41
  return () => abortController.abort();
46
- }, [seed]);
42
+ }, [runtime, seed]);
47
43
  return { data, loading, error };
48
44
  }
@@ -1,3 +1,5 @@
1
+ import type { Motely as MotelyEnumsType } from "motely-wasm";
2
+ export declare function setMotelyEnums(motely: typeof MotelyEnumsType): void;
1
3
  export declare function motelyBossDisplayName(value: number): string;
2
4
  export declare function motelyBossDisplayNameFromKey(key: string): string;
3
5
  export declare function motelyVoucherDisplayName(value: number): string;
@@ -1,10 +1,9 @@
1
- import { Motely } from "motely-wasm";
2
- /**
3
- * Display-name utilities thin wrappers over motely-wasm runtime enums.
4
- * No hand-maintained lookup tables. The enum IS the source of truth.
5
- */
6
- function spaceSplit(value) {
7
- return value.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
1
+ // Setter pattern: consumers boot motely-wasm and call `setMotelyEnums(Motely)`
2
+ // once after boot. Display functions degrade gracefully (return placeholder
3
+ // strings) before the setter is called rather than throwing.
4
+ let _motely = null;
5
+ export function setMotelyEnums(motely) {
6
+ _motely = motely;
8
7
  }
9
8
  function runtimeEnumKey(enumObject, value) {
10
9
  if (!enumObject || typeof enumObject !== "object")
@@ -12,39 +11,49 @@ function runtimeEnumKey(enumObject, value) {
12
11
  const key = enumObject[String(value)];
13
12
  return typeof key === "string" && key.length > 0 ? key : null;
14
13
  }
15
- // ─── Public API (same signatures as before, zero hand-rolled tables) ────────
14
+ // ─── Public API ──────────────────────────────────────────────────────────────
16
15
  export function motelyBossDisplayName(value) {
17
- const key = runtimeEnumKey(Motely.MotelyBossBlind, value & 0xff);
18
- return key === null ? `boss#${value}` : spaceSplit(key);
16
+ if (!_motely)
17
+ return `boss#${value}`;
18
+ const key = runtimeEnumKey(_motely.MotelyBossBlind, value & 0xff);
19
+ return key === null ? `boss#${value}` : key;
19
20
  }
20
21
  export function motelyBossDisplayNameFromKey(key) {
21
- return spaceSplit(key);
22
+ return key;
22
23
  }
23
24
  export function motelyVoucherDisplayName(value) {
24
- const key = runtimeEnumKey(Motely.MotelyVoucher, value);
25
- return key === null ? `voucher#${value}` : spaceSplit(key);
25
+ if (!_motely)
26
+ return `voucher#${value}`;
27
+ const key = runtimeEnumKey(_motely.MotelyVoucher, value);
28
+ return key === null ? `voucher#${value}` : key;
26
29
  }
27
30
  export function motelyVoucherDisplayNameFromKey(key) {
28
- return spaceSplit(key);
31
+ return key;
29
32
  }
30
33
  export function motelyTagDisplayName(value) {
31
- const key = runtimeEnumKey(Motely.MotelyTag, value);
32
- return key === null ? `tag#${value}` : spaceSplit(key);
34
+ if (!_motely)
35
+ return `tag#${value}`;
36
+ const key = runtimeEnumKey(_motely.MotelyTag, value);
37
+ return key === null ? `tag#${value}` : key;
33
38
  }
34
39
  export function motelyTagDisplayNameFromKey(key) {
35
- return spaceSplit(key);
40
+ return key;
36
41
  }
37
42
  export function motelyBoosterPackDisplayName(value) {
38
- const key = runtimeEnumKey(Motely.MotelyBoosterPack, value);
39
- return key === null ? `pack#${value}` : spaceSplit(key);
43
+ if (!_motely)
44
+ return `pack#${value}`;
45
+ const key = runtimeEnumKey(_motely.MotelyBoosterPack, value);
46
+ return key === null ? `pack#${value}` : key;
40
47
  }
41
48
  export function motelyBoosterPackDisplayNameFromKey(key) {
42
- return `${spaceSplit(key)} Pack`;
49
+ return `${key} Pack`;
43
50
  }
44
51
  export function motelyItemDisplayNameFromKey(key) {
45
- return spaceSplit(key);
52
+ return key;
46
53
  }
47
54
  export function motelyItemDisplayNameFromValue(value) {
48
- const key = runtimeEnumKey(Motely.MotelyItemType, value & 0xffff);
49
- return key === null ? `item#${value}` : spaceSplit(key);
55
+ if (!_motely)
56
+ return `item#${value}`;
57
+ const key = runtimeEnumKey(_motely.MotelyItemType, value & 0xffff);
58
+ return key === null ? `item#${value}` : key;
50
59
  }
package/dist/ui/jimbo.css CHANGED
@@ -206,7 +206,8 @@
206
206
  transform: translate(0, 0);
207
207
  transition: transform var(--j-press-speed) linear, box-shadow var(--j-press-speed) linear;
208
208
  }
209
- .j-btn[data-pressed="true"] .j-btn__face {
209
+ .j-btn[data-pressed="true"] .j-btn__face,
210
+ .j-btn:active:not(:disabled):not(.j-btn--disabled) .j-btn__face {
210
211
  transform: translateY(var(--j-press-y));
211
212
  box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.6);
212
213
  }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
2
  export interface JimboTabItem {
3
3
  id: string;
4
4
  label: string;
package/dist/ui/panel.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, memo } from 'react';
3
+ import { memo } from 'react';
4
4
  import { useSway } from './hooks.js';
5
5
  import { JimboText } from './jimboText.js';
6
6
  export const JimboPanel = memo(({ children, className = '', sway = false, onBack, hideBack = false, style, ...props }) => {
@@ -11,12 +11,8 @@ JimboPanel.displayName = 'JimboPanel';
11
11
  export const JimboInnerPanel = memo(({ children, className = '', style, ...props }) => (_jsx("div", { className: `j-inner-panel ${className}`, style: style, ...props, children: children })));
12
12
  JimboInnerPanel.displayName = 'JimboInnerPanel';
13
13
  export function JimboButton({ tone = 'orange', size = 'md', fullWidth = false, disabled = false, uppercase = false, onClick, style, className = '', children, }) {
14
- const [pressed, setPressed] = useState(false);
15
14
  const textSize = size === 'xs' ? 'xs' : size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md';
16
- return (_jsx("div", { className: `j-btn j-btn--${tone} j-btn--${size} ${fullWidth ? 'j-btn--full' : ''} ${disabled ? 'j-btn--disabled' : ''} ${className}`, "data-pressed": pressed, onMouseDown: () => { if (!disabled)
17
- setPressed(true); }, onMouseUp: () => setPressed(false), onMouseLeave: () => setPressed(false), onTouchStart: () => { if (!disabled)
18
- setPressed(true); }, onTouchEnd: () => setPressed(false), onClick: () => { if (!disabled)
19
- onClick?.(); }, style: style, children: _jsx("div", { className: "j-btn__face", children: _jsx(JimboText, { size: textSize, uppercase: uppercase, children: children }) }) }));
15
+ return (_jsx("button", { type: "button", className: `j-btn j-btn--${tone} j-btn--${size} ${fullWidth ? 'j-btn--full' : ''} ${disabled ? 'j-btn--disabled' : ''} ${className}`, disabled: disabled, onClick: onClick, style: style, children: _jsx("div", { className: "j-btn__face", children: _jsx(JimboText, { size: textSize, uppercase: uppercase, children: children }) }) }));
20
16
  }
21
17
  export function JimboBackButton({ onClick }) {
22
18
  return (_jsx("div", { className: "j-flex j-justify-center j-w-full", style: { padding: '4px 0' }, children: _jsx(JimboButton, { tone: "orange", size: "md", fullWidth: true, onClick: onClick, children: "Back" }) }));
package/dist/ui.d.ts CHANGED
@@ -21,10 +21,7 @@ export * from './ui/jimboStatGrid.js';
21
21
  export * from './ui/jimboSectionHeader.js';
22
22
  export * from './ui/jimboInfoCard.js';
23
23
  export * from './ui/jimboInset.js';
24
- export * from './ui/ide/JamlBuilder.js';
25
24
  export * from './ui/ide/JamlEditor.js';
26
- export * from './ui/ide/WasmStatus.js';
27
- export * from './ui/ide/AgnosticSeedCard.js';
28
25
  export * from './ui/JimboIconButton.js';
29
26
  export * from './ui/JimboInputModal.js';
30
27
  export * from './ui/JimboSelect.js';
package/dist/ui.js CHANGED
@@ -23,10 +23,13 @@ export * from './ui/jimboStatGrid.js';
23
23
  export * from './ui/jimboSectionHeader.js';
24
24
  export * from './ui/jimboInfoCard.js';
25
25
  export * from './ui/jimboInset.js';
26
- export * from './ui/ide/JamlBuilder.js';
26
+ // Old IDE prototypes — orphaned, statically import motely-wasm + use Vite-only
27
+ // `?worker` syntax. Removed from the public surface so webpack consumers don't
28
+ // transitively bundle motely-wasm. Files left on disk for triage.
29
+ // export * from './ui/ide/JamlBuilder.js'
27
30
  export * from './ui/ide/JamlEditor.js';
28
- export * from './ui/ide/WasmStatus.js';
29
- export * from './ui/ide/AgnosticSeedCard.js';
31
+ // export * from './ui/ide/WasmStatus.js'
32
+ // export * from './ui/ide/AgnosticSeedCard.js'
30
33
  export * from './ui/JimboIconButton.js';
31
34
  export * from './ui/JimboInputModal.js';
32
35
  export * from './ui/JimboSelect.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaml-ui",
3
- "version": "0.21.4",
3
+ "version": "0.22.0",
4
4
  "description": "Balatro rendering components, sprite metadata, and optional Motely helpers for React apps.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",