jaml-ui 0.21.5 → 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.
@@ -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";
@@ -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
@@ -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
@@ -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";
@@ -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,34 +1,48 @@
1
- import { Motely } from "motely-wasm";
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;
7
+ }
2
8
  function runtimeEnumKey(enumObject, value) {
3
9
  if (!enumObject || typeof enumObject !== "object")
4
10
  return null;
5
11
  const key = enumObject[String(value)];
6
12
  return typeof key === "string" && key.length > 0 ? key : null;
7
13
  }
8
- // ─── Public API (same signatures as before, zero hand-rolled tables) ────────
14
+ // ─── Public API ──────────────────────────────────────────────────────────────
9
15
  export function motelyBossDisplayName(value) {
10
- const key = runtimeEnumKey(Motely.MotelyBossBlind, value & 0xff);
16
+ if (!_motely)
17
+ return `boss#${value}`;
18
+ const key = runtimeEnumKey(_motely.MotelyBossBlind, value & 0xff);
11
19
  return key === null ? `boss#${value}` : key;
12
20
  }
13
21
  export function motelyBossDisplayNameFromKey(key) {
14
22
  return key;
15
23
  }
16
24
  export function motelyVoucherDisplayName(value) {
17
- const key = runtimeEnumKey(Motely.MotelyVoucher, value);
25
+ if (!_motely)
26
+ return `voucher#${value}`;
27
+ const key = runtimeEnumKey(_motely.MotelyVoucher, value);
18
28
  return key === null ? `voucher#${value}` : key;
19
29
  }
20
30
  export function motelyVoucherDisplayNameFromKey(key) {
21
31
  return key;
22
32
  }
23
33
  export function motelyTagDisplayName(value) {
24
- const key = runtimeEnumKey(Motely.MotelyTag, value);
34
+ if (!_motely)
35
+ return `tag#${value}`;
36
+ const key = runtimeEnumKey(_motely.MotelyTag, value);
25
37
  return key === null ? `tag#${value}` : key;
26
38
  }
27
39
  export function motelyTagDisplayNameFromKey(key) {
28
40
  return key;
29
41
  }
30
42
  export function motelyBoosterPackDisplayName(value) {
31
- const key = runtimeEnumKey(Motely.MotelyBoosterPack, value);
43
+ if (!_motely)
44
+ return `pack#${value}`;
45
+ const key = runtimeEnumKey(_motely.MotelyBoosterPack, value);
32
46
  return key === null ? `pack#${value}` : key;
33
47
  }
34
48
  export function motelyBoosterPackDisplayNameFromKey(key) {
@@ -38,6 +52,8 @@ export function motelyItemDisplayNameFromKey(key) {
38
52
  return key;
39
53
  }
40
54
  export function motelyItemDisplayNameFromValue(value) {
41
- const key = runtimeEnumKey(Motely.MotelyItemType, value & 0xffff);
55
+ if (!_motely)
56
+ return `item#${value}`;
57
+ const key = runtimeEnumKey(_motely.MotelyItemType, value & 0xffff);
42
58
  return key === null ? `item#${value}` : key;
43
59
  }
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.5",
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",