jaml-ui 0.24.19 → 0.25.1

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 (235) hide show
  1. package/DESIGN.md +2 -2
  2. package/README.md +0 -13
  3. package/assets/WeeJokerExampleDAilyGame.png +0 -0
  4. package/assets/balatro-stake-chips.png +0 -0
  5. package/dist/assets.d.ts +1 -2
  6. package/dist/chunks/Layer-BBPJFHfs.js +17 -0
  7. package/dist/chunks/Layer-BBPJFHfs.js.map +1 -0
  8. package/dist/chunks/assets-RWUiFSTc.js +37 -0
  9. package/dist/chunks/assets-RWUiFSTc.js.map +1 -0
  10. package/dist/chunks/motelyItemDecoder-CueyZ0XD.js +6039 -0
  11. package/dist/chunks/motelyItemDecoder-CueyZ0XD.js.map +1 -0
  12. package/dist/chunks/spriteMapper-CFjN0_TV.js +2415 -0
  13. package/dist/chunks/spriteMapper-CFjN0_TV.js.map +1 -0
  14. package/dist/chunks/tokens-B65Fzble.js +57 -0
  15. package/dist/chunks/tokens-B65Fzble.js.map +1 -0
  16. package/dist/chunks/ui-5cBy3zAm.js +1387 -0
  17. package/dist/chunks/ui-5cBy3zAm.js.map +1 -0
  18. package/dist/components/AnalyzerExplorer.d.ts +1 -1
  19. package/dist/components/CardFan.d.ts +1 -1
  20. package/dist/components/CardList.d.ts +1 -1
  21. package/dist/components/DeckSprite.d.ts +1 -1
  22. package/dist/components/JamlAestheticSelector.d.ts +1 -1
  23. package/dist/components/JamlAnalyzerFullscreen.d.ts +5 -5
  24. package/dist/components/JamlCurator.d.ts +1 -1
  25. package/dist/components/JamlIde.d.ts +5 -5
  26. package/dist/components/JamlSeedInput.d.ts +1 -1
  27. package/dist/components/JamlSpeedometer.d.ts +1 -1
  28. package/dist/components/MotelyVersionBadge.d.ts +1 -1
  29. package/dist/components/Standardcard.d.ts +1 -1
  30. package/dist/components/jamlMap/CategoryPicker.d.ts +3 -3
  31. package/dist/components/jamlMap/JamlMapEditor.d.ts +1 -1
  32. package/dist/components/jamlMap/JokerPicker.d.ts +1 -1
  33. package/dist/components/jamlMap/MysterySlot.d.ts +2 -2
  34. package/dist/components/jamlMap/index.d.ts +4 -4
  35. package/dist/core.d.ts +5 -5
  36. package/dist/core.js +27 -5
  37. package/dist/core.js.map +1 -0
  38. package/dist/decode/motelyItemDecoder.d.ts +0 -10
  39. package/dist/decode/motelySprite.d.ts +1 -1
  40. package/dist/fonts/m6x11plus.otf +0 -0
  41. package/dist/hooks/analyzerStreamRegistry.d.ts +2 -2
  42. package/dist/hooks/useAnalyzer.d.ts +2 -2
  43. package/dist/hooks/useSearch.d.ts +2 -2
  44. package/dist/index.d.ts +29 -31
  45. package/dist/index.js +16725 -34
  46. package/dist/index.js.map +1 -0
  47. package/dist/lib/const.d.ts +2 -2
  48. package/dist/lib/hooks/useDragScroll.d.ts +1 -1
  49. package/dist/lib/hooks/useJamlFilter.d.ts +2 -2
  50. package/dist/lib/hooks/useSeedAnalyzer.d.ts +2 -2
  51. package/dist/lib/utils.d.ts +1 -1
  52. package/dist/motely.d.ts +4 -3
  53. package/dist/motely.js +65 -3
  54. package/dist/motely.js.map +1 -0
  55. package/dist/motelyBoot.d.ts +2 -0
  56. package/dist/motelyDisplay.d.ts +0 -2
  57. package/dist/r3f/Card3D.d.ts +2 -2
  58. package/dist/r3f/JimboBillboard.d.ts +1 -1
  59. package/dist/r3f.js +235 -3
  60. package/dist/r3f.js.map +1 -0
  61. package/dist/render/CanvasRenderer.d.ts +1 -1
  62. package/dist/sprites/spriteData.d.ts +1 -6
  63. package/dist/sprites/spriteMapper.d.ts +1 -1
  64. package/dist/ui/JimboBadge.d.ts +1 -1
  65. package/dist/ui/JimboFloating.d.ts +1 -1
  66. package/dist/ui/JimboIconButton.d.ts +1 -1
  67. package/dist/ui/JimboSelect.d.ts +1 -1
  68. package/dist/ui/footer.d.ts +2 -3
  69. package/dist/ui/hooks.d.ts +1 -1
  70. package/dist/ui/ide/DeckSprite.d.ts +1 -1
  71. package/dist/ui/jimbo.css +2 -1837
  72. package/dist/ui/jimboApp.d.ts +1 -1
  73. package/dist/ui/jimboBackground.d.ts +4 -4
  74. package/dist/ui/jimboFilterBar.d.ts +1 -1
  75. package/dist/ui/jimboFlankNav.d.ts +1 -1
  76. package/dist/ui/jimboInfoCard.d.ts +1 -1
  77. package/dist/ui/jimboInset.d.ts +1 -1
  78. package/dist/ui/jimboStatGrid.d.ts +1 -1
  79. package/dist/ui/jimboText.d.ts +1 -1
  80. package/dist/ui/jimboTooltip.d.ts +2 -2
  81. package/dist/ui/mascot/SeedMascot.d.ts +2 -2
  82. package/dist/ui/panel.d.ts +1 -1
  83. package/dist/ui/radial/RadialBadge.d.ts +1 -2
  84. package/dist/ui/radial/RadialButton.d.ts +1 -2
  85. package/dist/ui/radial/RadialMenu.d.ts +2 -2
  86. package/dist/ui/radial/RadialPill.d.ts +1 -2
  87. package/dist/ui/radial/index.d.ts +16 -16
  88. package/dist/ui/radial/radialMenuStore.d.ts +1 -1
  89. package/dist/ui/showcase.d.ts +1 -1
  90. package/dist/ui/sprites.d.ts +2 -2
  91. package/dist/ui.d.ts +0 -1
  92. package/dist/ui.js +3 -36
  93. package/dist/utils/gameCardUtils.d.ts +1 -1
  94. package/dist/utils/jamlVisualFilter.d.ts +1 -7
  95. package/package.json +18 -30
  96. package/dist/assets.js +0 -48
  97. package/dist/components/AnalyzerExplorer.js +0 -391
  98. package/dist/components/CardFan.js +0 -80
  99. package/dist/components/CardList.js +0 -5
  100. package/dist/components/DeckSprite.js +0 -75
  101. package/dist/components/GameCard.js +0 -355
  102. package/dist/components/JamlAestheticSelector.js +0 -22
  103. package/dist/components/JamlAnalyzerFullscreen.js +0 -263
  104. package/dist/components/JamlCodeEditor.js +0 -137
  105. package/dist/components/JamlCurator.js +0 -64
  106. package/dist/components/JamlCurator.stories.d.ts +0 -6
  107. package/dist/components/JamlCurator.stories.js +0 -14
  108. package/dist/components/JamlIde.js +0 -193
  109. package/dist/components/JamlIdeToolbar.js +0 -23
  110. package/dist/components/JamlIdeVisual.js +0 -218
  111. package/dist/components/JamlMapPreview.js +0 -121
  112. package/dist/components/JamlSeedInput.js +0 -26
  113. package/dist/components/JamlSpeedometer.js +0 -70
  114. package/dist/components/Jimbolate.js +0 -17
  115. package/dist/components/MotelyVersionBadge.js +0 -19
  116. package/dist/components/PaginatedFilterBrowser.js +0 -54
  117. package/dist/components/RunConfigModal.js +0 -59
  118. package/dist/components/Standardcard.js +0 -80
  119. package/dist/components/jamlMap/CategoryPicker.js +0 -135
  120. package/dist/components/jamlMap/JamlMapEditor.js +0 -304
  121. package/dist/components/jamlMap/JamlMapEditor.stories.d.ts +0 -7
  122. package/dist/components/jamlMap/JamlMapEditor.stories.js +0 -26
  123. package/dist/components/jamlMap/JamlMapEditorDemo.d.ts +0 -8
  124. package/dist/components/jamlMap/JamlMapEditorDemo.js +0 -323
  125. package/dist/components/jamlMap/JokerPicker.js +0 -113
  126. package/dist/components/jamlMap/MysterySlot.js +0 -128
  127. package/dist/components/jamlMap/MysterySlot.stories.d.ts +0 -7
  128. package/dist/components/jamlMap/MysterySlot.stories.js +0 -31
  129. package/dist/components/jamlMap/index.js +0 -4
  130. package/dist/decode/motelyItemDecoder.js +0 -164
  131. package/dist/decode/motelySprite.js +0 -84
  132. package/dist/hooks/analyzerStreamRegistry.js +0 -96
  133. package/dist/hooks/searchWorker.d.ts +0 -1
  134. package/dist/hooks/searchWorker.js +0 -119
  135. package/dist/hooks/searchWorkerCode.d.ts +0 -1
  136. package/dist/hooks/searchWorkerCode.js +0 -85
  137. package/dist/hooks/useAnalyzer.js +0 -91
  138. package/dist/hooks/useIntersectionObserver.js +0 -52
  139. package/dist/hooks/useSearch.js +0 -161
  140. package/dist/hooks/useShopStream.js +0 -85
  141. package/dist/lib/SpriteMapper.js +0 -48
  142. package/dist/lib/cardParser.js +0 -67
  143. package/dist/lib/classes/BuyMetaData.js +0 -1
  144. package/dist/lib/config.js +0 -15
  145. package/dist/lib/const.js +0 -521
  146. package/dist/lib/data/constants.js +0 -14
  147. package/dist/lib/hooks/useDragScroll.js +0 -48
  148. package/dist/lib/hooks/useJamlFilter.js +0 -219
  149. package/dist/lib/hooks/useSeedAnalyzer.js +0 -50
  150. package/dist/lib/jaml/jamlCompletion.js +0 -13
  151. package/dist/lib/jaml/jamlData.js +0 -6
  152. package/dist/lib/jaml/jamlObjectives.js +0 -97
  153. package/dist/lib/jaml/jamlParser.js +0 -47
  154. package/dist/lib/jaml/jamlPresets.js +0 -61
  155. package/dist/lib/jaml/jamlSchema.js +0 -91
  156. package/dist/lib/parseDailyRitual.js +0 -70
  157. package/dist/lib/tts/getRevealPos.js +0 -16
  158. package/dist/lib/tts/splitTtsDisplay.js +0 -35
  159. package/dist/lib/types.js +0 -1
  160. package/dist/lib/utils.js +0 -5
  161. package/dist/motelyDisplay.js +0 -59
  162. package/dist/r3f/Card3D.js +0 -72
  163. package/dist/r3f/JimboBillboard.js +0 -32
  164. package/dist/r3f/JimboText3D.js +0 -8
  165. package/dist/render/CanvasRenderer.js +0 -11
  166. package/dist/render/Layer.js +0 -18
  167. package/dist/sprites/spriteData.js +0 -100
  168. package/dist/sprites/spriteMapper.js +0 -75
  169. package/dist/stories/Button.d.ts +0 -15
  170. package/dist/stories/Button.js +0 -7
  171. package/dist/stories/Button.stories.d.ts +0 -24
  172. package/dist/stories/Button.stories.js +0 -50
  173. package/dist/stories/Header.d.ts +0 -12
  174. package/dist/stories/Header.js +0 -4
  175. package/dist/stories/Header.stories.d.ts +0 -18
  176. package/dist/stories/Header.stories.js +0 -26
  177. package/dist/stories/Page.d.ts +0 -3
  178. package/dist/stories/Page.js +0 -8
  179. package/dist/stories/Page.stories.d.ts +0 -12
  180. package/dist/stories/Page.stories.js +0 -24
  181. package/dist/ui/Jimbo.stories.d.ts +0 -7
  182. package/dist/ui/Jimbo.stories.js +0 -28
  183. package/dist/ui/JimboBadge.js +0 -8
  184. package/dist/ui/JimboFloating.js +0 -17
  185. package/dist/ui/JimboIconButton.js +0 -28
  186. package/dist/ui/JimboInputModal.js +0 -66
  187. package/dist/ui/JimboSelect.js +0 -43
  188. package/dist/ui/JimboToggleList.js +0 -5
  189. package/dist/ui/PanelSplitter.js +0 -78
  190. package/dist/ui/codeBlock.js +0 -14
  191. package/dist/ui/footer.js +0 -20
  192. package/dist/ui/hooks.js +0 -634
  193. package/dist/ui/ide/AgnosticSeedCard.d.ts +0 -19
  194. package/dist/ui/ide/AgnosticSeedCard.js +0 -48
  195. package/dist/ui/ide/DeckSprite.js +0 -2
  196. package/dist/ui/ide/JamlBuilder.d.ts +0 -1
  197. package/dist/ui/ide/JamlBuilder.js +0 -112
  198. package/dist/ui/ide/JamlEditor.js +0 -486
  199. package/dist/ui/ide/JamlEditorMonaco.d.ts +0 -8
  200. package/dist/ui/ide/JamlEditorMonaco.js +0 -78
  201. package/dist/ui/ide/WasmStatus.d.ts +0 -1
  202. package/dist/ui/ide/WasmStatus.js +0 -42
  203. package/dist/ui/jimboApp.js +0 -15
  204. package/dist/ui/jimboBackground.js +0 -26
  205. package/dist/ui/jimboCopyRow.js +0 -18
  206. package/dist/ui/jimboFilterBar.js +0 -16
  207. package/dist/ui/jimboFlankNav.js +0 -18
  208. package/dist/ui/jimboInfoCard.js +0 -26
  209. package/dist/ui/jimboInset.js +0 -9
  210. package/dist/ui/jimboSectionHeader.js +0 -9
  211. package/dist/ui/jimboStatGrid.js +0 -9
  212. package/dist/ui/jimboTabs.js +0 -22
  213. package/dist/ui/jimboText.js +0 -33
  214. package/dist/ui/jimboTooltip.js +0 -39
  215. package/dist/ui/jimboWordmark.js +0 -9
  216. package/dist/ui/mascot/JammySpeechBox.js +0 -30
  217. package/dist/ui/mascot/SeedMascot.js +0 -17
  218. package/dist/ui/mascot/index.js +0 -3
  219. package/dist/ui/mascot/menuConfig.js +0 -12
  220. package/dist/ui/panel.js +0 -24
  221. package/dist/ui/radial/RadialBadge.js +0 -43
  222. package/dist/ui/radial/RadialBreadcrumb.js +0 -18
  223. package/dist/ui/radial/RadialButton.js +0 -102
  224. package/dist/ui/radial/RadialMenu.js +0 -168
  225. package/dist/ui/radial/RadialPill.js +0 -15
  226. package/dist/ui/radial/index.js +0 -18
  227. package/dist/ui/radial/radialMenuStore.js +0 -122
  228. package/dist/ui/radial/radialMenuViewport.js +0 -59
  229. package/dist/ui/radial/useRadialMenu.js +0 -107
  230. package/dist/ui/showcase.js +0 -20
  231. package/dist/ui/sprites.js +0 -77
  232. package/dist/ui/tokens.js +0 -64
  233. package/dist/utils/gameCardUtils.js +0 -15
  234. package/dist/utils/jamlMapPreview.js +0 -106
  235. package/dist/utils/jamlVisualFilter.js +0 -210
@@ -1,52 +0,0 @@
1
- import { useEffect, useLayoutEffect, useRef, useState, useCallback } from "react";
2
- /**
3
- * Encapsulates IntersectionObserver logic.
4
- */
5
- export function useIntersectionObserver(options = {}) {
6
- const [entry, setEntry] = useState(null);
7
- const [node, setNode] = useState(null);
8
- const observer = useRef(null);
9
- const ref = useCallback((node) => {
10
- setNode(node);
11
- }, []);
12
- useEffect(() => {
13
- if (!node)
14
- return;
15
- if (observer.current)
16
- observer.current.disconnect();
17
- const { freezeOnceVisible, ...init } = options;
18
- observer.current = new IntersectionObserver(([entry]) => {
19
- setEntry(entry);
20
- if (freezeOnceVisible && entry.isIntersecting && observer.current) {
21
- observer.current.disconnect();
22
- }
23
- }, init);
24
- observer.current.observe(node);
25
- return () => {
26
- if (observer.current)
27
- observer.current.disconnect();
28
- };
29
- }, [node, options, options.root, options.rootMargin, options.threshold, options.freezeOnceVisible]);
30
- return { ref, entry };
31
- }
32
- /**
33
- * Specialization for infinite scroll / sentinel patterns.
34
- */
35
- export function useInfiniteScroll(onVisible, options = {}, active = true) {
36
- const onVisibleRef = useRef(onVisible);
37
- useLayoutEffect(() => {
38
- onVisibleRef.current = onVisible;
39
- });
40
- const { ref, entry } = useIntersectionObserver({
41
- ...options,
42
- threshold: options.threshold ?? 0.1,
43
- });
44
- useEffect(() => {
45
- if (!active || !entry)
46
- return;
47
- if (entry.isIntersecting) {
48
- onVisibleRef.current();
49
- }
50
- }, [entry, active]);
51
- return ref;
52
- }
@@ -1,161 +0,0 @@
1
- "use client";
2
- import { useState, useCallback, useRef, useEffect } from "react";
3
- const INITIAL_STATE = {
4
- results: [],
5
- totalSearched: 0n,
6
- matchingSeeds: 0n,
7
- status: "idle",
8
- error: null,
9
- seedsPerSecond: 0,
10
- tallyLabels: [],
11
- };
12
- function createWorker() {
13
- return new Worker(new URL("./searchWorker.js", import.meta.url), { type: "module" });
14
- }
15
- export function useSearch(motelyWasmUrl) {
16
- const [state, setState] = useState(INITIAL_STATE);
17
- const workerRef = useRef(null);
18
- const readyRef = useRef(false); // Worker is NOT implicitly ready, must wait for 'ready' message
19
- const speedRef = useRef({ lastSearched: 0n, lastTime: 0, ema: 0 });
20
- const [prevUrl, setPrevUrl] = useState(motelyWasmUrl);
21
- if (motelyWasmUrl !== prevUrl) {
22
- setPrevUrl(motelyWasmUrl);
23
- setState((s) => ({ ...s, status: "idle" }));
24
- }
25
- useEffect(() => {
26
- const worker = createWorker();
27
- workerRef.current = worker;
28
- if (motelyWasmUrl) {
29
- worker.postMessage({ type: 'init', url: motelyWasmUrl });
30
- }
31
- worker.onmessage = (e) => {
32
- const msg = e.data;
33
- if (msg.type === "ready") {
34
- readyRef.current = true;
35
- setState((s) => s.status === "booting" ? { ...s, status: "idle" } : s);
36
- }
37
- else if (msg.type === "result") {
38
- setState((s) => ({
39
- ...s,
40
- results: [...s.results, {
41
- seed: msg.seed,
42
- score: msg.score,
43
- tallyColumns: msg.tallyColumns,
44
- }],
45
- }));
46
- }
47
- else if (msg.type === "progress") {
48
- const searched = BigInt(msg.searched);
49
- const matching = BigInt(msg.matching);
50
- const now = performance.now();
51
- const ref = speedRef.current;
52
- let sps = ref.ema;
53
- if (ref.lastTime > 0) {
54
- const dtMs = now - ref.lastTime;
55
- if (dtMs > 0) {
56
- const delta = Number(searched - ref.lastSearched);
57
- const instantSps = delta / (dtMs / 1000);
58
- sps = ref.ema === 0 ? instantSps : ref.ema * 0.7 + instantSps * 0.3;
59
- }
60
- }
61
- ref.lastSearched = searched;
62
- ref.lastTime = now;
63
- ref.ema = sps;
64
- setState((s) => ({ ...s, totalSearched: searched, matchingSeeds: matching, seedsPerSecond: Math.round(sps) }));
65
- }
66
- else if (msg.type === "complete") {
67
- speedRef.current = { lastSearched: 0n, lastTime: 0, ema: 0 };
68
- setState((s) => ({
69
- ...s,
70
- status: msg.status === "Completed"
71
- ? "completed"
72
- : msg.status === "Cancelled"
73
- ? "cancelled"
74
- : "error",
75
- error: msg.status === "Completed" || msg.status === "Cancelled"
76
- ? null
77
- : msg.status,
78
- totalSearched: BigInt(msg.searched),
79
- matchingSeeds: BigInt(msg.matched),
80
- seedsPerSecond: 0,
81
- }));
82
- }
83
- else if (msg.type === "cancelled") {
84
- speedRef.current = { lastSearched: 0n, lastTime: 0, ema: 0 };
85
- setState((s) => ({ ...s, status: "cancelled", seedsPerSecond: 0 }));
86
- }
87
- else if (msg.type === "tally_labels") {
88
- setState((s) => ({ ...s, tallyLabels: msg.labels }));
89
- }
90
- else if (msg.type === "error") {
91
- setState((s) => ({ ...s, status: "error", error: msg.message }));
92
- }
93
- };
94
- return () => {
95
- worker.terminate();
96
- workerRef.current = null;
97
- };
98
- }, [motelyWasmUrl]);
99
- const sendStart = useCallback((payload) => {
100
- const worker = workerRef.current;
101
- if (!worker)
102
- return;
103
- if (!motelyWasmUrl) {
104
- setState((s) => ({ ...s, status: "error", error: "motelyWasmUrl is required to start search" }));
105
- return;
106
- }
107
- speedRef.current = { lastSearched: 0n, lastTime: 0, ema: 0 };
108
- setState({ ...INITIAL_STATE, status: "running", tallyLabels: state.tallyLabels });
109
- const send = () => worker.postMessage(payload);
110
- if (readyRef.current) {
111
- send();
112
- }
113
- else {
114
- const orig = worker.onmessage;
115
- worker.onmessage = (e) => {
116
- orig?.call(worker, e);
117
- if (e.data.type === "ready") {
118
- worker.onmessage = orig;
119
- send();
120
- }
121
- };
122
- }
123
- }, [motelyWasmUrl, state.tallyLabels]);
124
- const start = useCallback((jaml, count) => {
125
- sendStart({ type: "start", mode: "random", jaml, count });
126
- }, [sendStart]);
127
- const startAesthetic = useCallback((jaml, aesthetic) => {
128
- sendStart({ type: "start", mode: "aesthetic", jaml, aesthetic });
129
- }, [sendStart]);
130
- const startSeedList = useCallback((jaml, seeds) => {
131
- sendStart({ type: "start", mode: "seedList", jaml, seeds });
132
- }, [sendStart]);
133
- const startKeyword = useCallback((jaml, keywords, padding) => {
134
- sendStart({ type: "start", mode: "keyword", jaml, keywords, padding });
135
- }, [sendStart]);
136
- const startSequential = useCallback((jaml, startSeed, endSeed) => {
137
- // Sequential search: single-threaded, deterministic order.
138
- // batchCharCount = length of start seed, startBatch/endBatch = numeric range.
139
- const charCount = startSeed.length || 1;
140
- const startNum = parseInt(startSeed, 36) || 0;
141
- const endNum = endSeed ? parseInt(endSeed, 36) : startNum + 10_000_000;
142
- sendStart({
143
- type: "start",
144
- mode: "sequential",
145
- jaml,
146
- batchCharCount: charCount,
147
- startBatch: startNum.toString(),
148
- endBatch: endNum.toString(),
149
- });
150
- }, [sendStart]);
151
- const cancel = useCallback(() => {
152
- workerRef.current?.postMessage({ type: "stop" });
153
- }, []);
154
- const clearError = useCallback(() => {
155
- setState((s) => (s.error || s.status === "error" ? { ...s, error: null, status: "idle" } : s));
156
- }, []);
157
- const fetchTallyLabels = useCallback((jaml) => {
158
- workerRef.current?.postMessage({ type: "get_tally_labels", jaml });
159
- }, []);
160
- return { ...state, start, startAesthetic, startSeedList, startKeyword, startSequential, cancel, clearError, fetchTallyLabels };
161
- }
@@ -1,85 +0,0 @@
1
- "use client";
2
- import { useState, useEffect, useRef, useCallback, useLayoutEffect } from "react";
3
- const DEFAULT_PULL = 12;
4
- /**
5
- * Generic stream hook for iterating any motely-wasm analyzer stream.
6
- *
7
- * @param initStream - called once to initialize the stream (e.g. analyzer.initShop(ante))
8
- * @param nextItem - called to get the next item from the stream (e.g. analyzer.nextShopItem())
9
- * @param deps - dependency array that triggers stream re-initialization
10
- * @param initialItems - items already visible (cursor advances past them)
11
- */
12
- export function useMotelyStream(initStream, nextItem, deps, initialItems = []) {
13
- const [items, setItems] = useState(() => initialItems.map(i => ({ ...i })));
14
- const [error, setError] = useState(null);
15
- const [ready, setReady] = useState(false);
16
- const [loading, setLoading] = useState(true);
17
- const [loadingMore, setLoadingMore] = useState(false);
18
- const nextRef = useRef(nextItem);
19
- useLayoutEffect(() => {
20
- nextRef.current = nextItem;
21
- });
22
- const busyRef = useRef(false);
23
- const genRef = useRef(0);
24
- useEffect(() => {
25
- const gen = ++genRef.current;
26
- const base = initialItems.map(i => ({ ...i }));
27
- // eslint-disable-next-line react-hooks/set-state-in-effect
28
- setItems(base);
29
- setError(null);
30
- setReady(false);
31
- setLoading(true);
32
- setLoadingMore(false);
33
- if (!initStream || !nextItem) {
34
- setLoading(false);
35
- return;
36
- }
37
- try {
38
- initStream();
39
- // Advance past already-visible items
40
- for (let i = 0; i < base.length; i++)
41
- nextItem();
42
- if (base.length === 0) {
43
- const prefetch = [];
44
- for (let i = 0; i < DEFAULT_PULL; i++)
45
- prefetch.push(nextItem());
46
- if (gen !== genRef.current)
47
- return;
48
- setItems(prefetch);
49
- }
50
- setReady(true);
51
- }
52
- catch (err) {
53
- if (gen !== genRef.current)
54
- return;
55
- setError(err instanceof Error ? err.message : String(err));
56
- }
57
- finally {
58
- if (gen === genRef.current)
59
- setLoading(false);
60
- }
61
- // eslint-disable-next-line react-hooks/exhaustive-deps
62
- }, deps);
63
- const pullMore = useCallback((count = DEFAULT_PULL) => {
64
- const next = nextRef.current;
65
- if (!next || count <= 0 || busyRef.current)
66
- return;
67
- busyRef.current = true;
68
- setLoadingMore(true);
69
- setError(null);
70
- try {
71
- const batch = [];
72
- for (let i = 0; i < count; i++)
73
- batch.push(next());
74
- setItems(prev => [...prev, ...batch]);
75
- }
76
- catch (err) {
77
- setError(err instanceof Error ? err.message : String(err));
78
- }
79
- finally {
80
- busyRef.current = false;
81
- setLoadingMore(false);
82
- }
83
- }, []);
84
- return { items, ready, loading, loadingMore, error, pullMore };
85
- }
@@ -1,48 +0,0 @@
1
- import { jokers, tarotsAndPlanets, vouchers, boosterPacks, jokerFaces, consumablesFaces, bosses, tags } from './const';
2
- // Consolidate all item arrays into a single map for O(1) lookup
3
- const ITEM_MAP = new Map();
4
- function addToMap(items, type) {
5
- items.forEach(item => {
6
- if (item.name && item.pos) {
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
- }
15
- // Populate the map with explicit types
16
- addToMap(jokers, 'Jokers');
17
- addToMap(tarotsAndPlanets, 'Tarots');
18
- addToMap(vouchers, 'Vouchers');
19
- addToMap(boosterPacks, 'Boosters');
20
- addToMap(bosses, 'BlindChips');
21
- addToMap(tags, 'tags');
22
- // Explicit overrides/faces
23
- addToMap(jokerFaces, 'Jokers');
24
- addToMap(consumablesFaces, 'Tarots');
25
- export function getSpriteData(name) {
26
- // 1. Try stripping common prefixes used by some analyzers (e.g., "Planet | Venus")
27
- const cleanedName = name.replace(/^(Joker|Tarot|Planet|Voucher|Pack|Edition|Tag) [|:] /i, "").trim();
28
- // 2. Precise lookup
29
- if (ITEM_MAP.has(cleanedName))
30
- return ITEM_MAP.get(cleanedName);
31
- if (ITEM_MAP.has(name))
32
- return ITEM_MAP.get(name);
33
- // 3. Normalized lookups
34
- const variants = [
35
- cleanedName.toLowerCase(),
36
- cleanedName.replace(/ /g, ''),
37
- cleanedName.replace(/ /g, '').toLowerCase(),
38
- name.toLowerCase(),
39
- name.replace(/ /g, ''),
40
- name.replace(/ /g, '').toLowerCase()
41
- ];
42
- for (const v of variants) {
43
- if (ITEM_MAP.has(v))
44
- return ITEM_MAP.get(v);
45
- }
46
- // Default Fallback
47
- return { pos: { x: 0, y: 0 }, type: 'Jokers' };
48
- }
@@ -1,67 +0,0 @@
1
- const ENHANCEMENTS = ["Bonus", "Mult", "Wild", "Lucky", "Glass", "Steel", "Stone", "Gold"];
2
- const SEALS = ["Gold", "Purple", "Red", "Blue"];
3
- const EDITIONS = ["Foil", "Holographic", "Polychrome", "Negative"];
4
- // Internal Balatro short codes
5
- const RANK_MAP = {
6
- "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8", "9": "9", "10": "10",
7
- "T": "10", "J": "Jack", "Q": "Queen", "K": "King", "A": "Ace"
8
- };
9
- const SUIT_MAP = {
10
- "H": "Hearts", "C": "Clubs", "D": "Diamonds", "S": "Spades"
11
- };
12
- export function parseCardToken(item) {
13
- if (!item)
14
- return null;
15
- // 1. If it's already an object with rank/suit
16
- if (typeof item === 'object') {
17
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
- const obj = item;
19
- if (obj.rank || obj.base) {
20
- let rank = obj.rank || obj.base?.[2] || obj.base?.[0]; // Handle different analyzer versions
21
- let suit = obj.suit || obj.base?.[0];
22
- // Normalize
23
- rank = RANK_MAP[rank] || rank;
24
- suit = SUIT_MAP[suit] || suit;
25
- if (suit && !suit.endsWith('s'))
26
- suit += 's';
27
- return {
28
- rank: rank || "Ace",
29
- suit: suit || "Spades",
30
- enhancement: obj.enhancement || obj.modifier || null,
31
- seal: obj.seal || null,
32
- edition: obj.edition || null
33
- };
34
- }
35
- }
36
- // 2. If it's a string token
37
- if (typeof item === 'string') {
38
- const str = item.trim();
39
- // Handle rank_suit format e.g. "2_C"
40
- if (str.includes('_')) {
41
- const [r, s] = str.split('_');
42
- const rank = RANK_MAP[r.toUpperCase()] || r;
43
- const suit = SUIT_MAP[s.toUpperCase()] || s;
44
- return { rank, suit, enhancement: null, seal: null, edition: null };
45
- }
46
- // Handle "Rank of Suit" format
47
- const parts = str.toLowerCase().split(' ');
48
- const ofIndex = parts.indexOf('of');
49
- if (ofIndex > 0 && ofIndex < parts.length - 1) {
50
- let rank = parts[ofIndex - 1];
51
- let suit = parts[ofIndex + 1];
52
- // Normalize
53
- rank = rank.charAt(0).toUpperCase() + rank.slice(1);
54
- suit = suit.charAt(0).toUpperCase() + suit.slice(1);
55
- if (!suit.endsWith('s'))
56
- suit += 's';
57
- return {
58
- rank: RANK_MAP[rank.toUpperCase()] || rank,
59
- suit: SUIT_MAP[suit.toUpperCase()] || suit,
60
- enhancement: parts.find(p => ENHANCEMENTS.some(e => e.toLowerCase() === p)) || null,
61
- seal: parts.find(p => SEALS.some(s => s.toLowerCase() === p)) || null,
62
- edition: parts.find(p => EDITIONS.some(e => e.toLowerCase() === p)) || null
63
- };
64
- }
65
- }
66
- return null;
67
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,15 +0,0 @@
1
- export const ritualConfig = {
2
- title: "The Daily Wee",
3
- tagline: "A curated daily Balatro ritual",
4
- id: "TheDailyWee",
5
- defaultObjective: "Wee Joker",
6
- /**
7
- * The Weepoch (Jan 30, 2026)
8
- * This is the canonical start date for Day 1.
9
- */
10
- epochDate: "2026-02-02T00:00:00Z",
11
- get epoch() {
12
- return new Date(this.epochDate).getTime();
13
- }
14
- };
15
- export const EPOCH = ritualConfig.epoch;