jaml-ui 0.24.20 → 0.25.2

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 (233) hide show
  1. package/README.md +0 -13
  2. package/assets/WeeJokerExampleDAilyGame.png +0 -0
  3. package/assets/balatro-stake-chips.png +0 -0
  4. package/dist/assets.d.ts +1 -2
  5. package/dist/chunks/Layer-BBPJFHfs.js +17 -0
  6. package/dist/chunks/Layer-BBPJFHfs.js.map +1 -0
  7. package/dist/chunks/assets-RWUiFSTc.js +37 -0
  8. package/dist/chunks/assets-RWUiFSTc.js.map +1 -0
  9. package/dist/chunks/motelyItemDecoder-CueyZ0XD.js +6039 -0
  10. package/dist/chunks/motelyItemDecoder-CueyZ0XD.js.map +1 -0
  11. package/dist/chunks/spriteMapper-CFjN0_TV.js +2415 -0
  12. package/dist/chunks/spriteMapper-CFjN0_TV.js.map +1 -0
  13. package/dist/chunks/tokens-B65Fzble.js +57 -0
  14. package/dist/chunks/tokens-B65Fzble.js.map +1 -0
  15. package/dist/chunks/ui-5cBy3zAm.js +1387 -0
  16. package/dist/chunks/ui-5cBy3zAm.js.map +1 -0
  17. package/dist/components/AnalyzerExplorer.d.ts +1 -1
  18. package/dist/components/CardFan.d.ts +1 -1
  19. package/dist/components/CardList.d.ts +1 -1
  20. package/dist/components/DeckSprite.d.ts +1 -1
  21. package/dist/components/JamlAestheticSelector.d.ts +1 -1
  22. package/dist/components/JamlAnalyzerFullscreen.d.ts +5 -5
  23. package/dist/components/JamlCurator.d.ts +1 -6
  24. package/dist/components/JamlIde.d.ts +5 -5
  25. package/dist/components/JamlSeedInput.d.ts +1 -1
  26. package/dist/components/JamlSpeedometer.d.ts +1 -1
  27. package/dist/components/MotelyVersionBadge.d.ts +1 -1
  28. package/dist/components/Standardcard.d.ts +1 -1
  29. package/dist/components/jamlMap/CategoryPicker.d.ts +3 -3
  30. package/dist/components/jamlMap/JamlMapEditor.d.ts +1 -1
  31. package/dist/components/jamlMap/JokerPicker.d.ts +1 -1
  32. package/dist/components/jamlMap/MysterySlot.d.ts +2 -2
  33. package/dist/components/jamlMap/index.d.ts +4 -4
  34. package/dist/core.d.ts +5 -5
  35. package/dist/core.js +27 -5
  36. package/dist/core.js.map +1 -0
  37. package/dist/decode/motelyItemDecoder.d.ts +0 -10
  38. package/dist/decode/motelySprite.d.ts +1 -1
  39. package/dist/fonts/m6x11plus.otf +0 -0
  40. package/dist/hooks/analyzerStreamRegistry.d.ts +2 -2
  41. package/dist/hooks/useAnalyzer.d.ts +3 -3
  42. package/dist/hooks/useSearch.d.ts +2 -2
  43. package/dist/index.d.ts +29 -31
  44. package/dist/index.js +16721 -34
  45. package/dist/index.js.map +1 -0
  46. package/dist/lib/const.d.ts +2 -2
  47. package/dist/lib/hooks/useDragScroll.d.ts +1 -1
  48. package/dist/lib/hooks/useJamlFilter.d.ts +2 -2
  49. package/dist/lib/hooks/useSeedAnalyzer.d.ts +2 -2
  50. package/dist/lib/utils.d.ts +1 -1
  51. package/dist/motely.d.ts +4 -3
  52. package/dist/motely.js +65 -3
  53. package/dist/motely.js.map +1 -0
  54. package/dist/motelyBoot.d.ts +2 -0
  55. package/dist/motelyDisplay.d.ts +0 -2
  56. package/dist/r3f/Card3D.d.ts +2 -2
  57. package/dist/r3f/JimboBillboard.d.ts +1 -1
  58. package/dist/r3f.js +235 -3
  59. package/dist/r3f.js.map +1 -0
  60. package/dist/render/CanvasRenderer.d.ts +1 -1
  61. package/dist/sprites/spriteData.d.ts +1 -6
  62. package/dist/sprites/spriteMapper.d.ts +1 -1
  63. package/dist/ui/JimboBadge.d.ts +1 -1
  64. package/dist/ui/JimboFloating.d.ts +1 -1
  65. package/dist/ui/JimboIconButton.d.ts +1 -1
  66. package/dist/ui/JimboSelect.d.ts +1 -1
  67. package/dist/ui/footer.d.ts +2 -3
  68. package/dist/ui/hooks.d.ts +1 -1
  69. package/dist/ui/ide/DeckSprite.d.ts +1 -1
  70. package/dist/ui/jimbo.css +2 -1856
  71. package/dist/ui/jimboApp.d.ts +1 -1
  72. package/dist/ui/jimboFilterBar.d.ts +1 -1
  73. package/dist/ui/jimboFlankNav.d.ts +1 -1
  74. package/dist/ui/jimboInfoCard.d.ts +1 -1
  75. package/dist/ui/jimboInset.d.ts +1 -1
  76. package/dist/ui/jimboStatGrid.d.ts +1 -1
  77. package/dist/ui/jimboText.d.ts +1 -1
  78. package/dist/ui/jimboTooltip.d.ts +2 -2
  79. package/dist/ui/mascot/SeedMascot.d.ts +2 -2
  80. package/dist/ui/panel.d.ts +1 -1
  81. package/dist/ui/radial/RadialBadge.d.ts +1 -2
  82. package/dist/ui/radial/RadialButton.d.ts +1 -2
  83. package/dist/ui/radial/RadialMenu.d.ts +2 -2
  84. package/dist/ui/radial/RadialPill.d.ts +1 -2
  85. package/dist/ui/radial/index.d.ts +16 -16
  86. package/dist/ui/radial/radialMenuStore.d.ts +1 -1
  87. package/dist/ui/showcase.d.ts +1 -1
  88. package/dist/ui/sprites.d.ts +2 -2
  89. package/dist/ui.d.ts +0 -1
  90. package/dist/ui.js +3 -36
  91. package/dist/utils/gameCardUtils.d.ts +1 -1
  92. package/dist/utils/jamlVisualFilter.d.ts +1 -7
  93. package/package.json +13 -25
  94. package/dist/assets.js +0 -48
  95. package/dist/components/AnalyzerExplorer.js +0 -391
  96. package/dist/components/CardFan.js +0 -80
  97. package/dist/components/CardList.js +0 -5
  98. package/dist/components/DeckSprite.js +0 -75
  99. package/dist/components/GameCard.js +0 -355
  100. package/dist/components/JamlAestheticSelector.js +0 -22
  101. package/dist/components/JamlAnalyzerFullscreen.js +0 -263
  102. package/dist/components/JamlCodeEditor.js +0 -137
  103. package/dist/components/JamlCurator.js +0 -64
  104. package/dist/components/JamlCurator.stories.d.ts +0 -6
  105. package/dist/components/JamlCurator.stories.js +0 -14
  106. package/dist/components/JamlIde.js +0 -193
  107. package/dist/components/JamlIdeToolbar.js +0 -23
  108. package/dist/components/JamlIdeVisual.js +0 -218
  109. package/dist/components/JamlMapPreview.js +0 -121
  110. package/dist/components/JamlSeedInput.js +0 -26
  111. package/dist/components/JamlSpeedometer.js +0 -70
  112. package/dist/components/Jimbolate.js +0 -17
  113. package/dist/components/MotelyVersionBadge.js +0 -19
  114. package/dist/components/PaginatedFilterBrowser.js +0 -54
  115. package/dist/components/RunConfigModal.js +0 -59
  116. package/dist/components/Standardcard.js +0 -80
  117. package/dist/components/jamlMap/CategoryPicker.js +0 -135
  118. package/dist/components/jamlMap/JamlMapEditor.js +0 -304
  119. package/dist/components/jamlMap/JamlMapEditor.stories.d.ts +0 -7
  120. package/dist/components/jamlMap/JamlMapEditor.stories.js +0 -26
  121. package/dist/components/jamlMap/JamlMapEditorDemo.d.ts +0 -8
  122. package/dist/components/jamlMap/JamlMapEditorDemo.js +0 -323
  123. package/dist/components/jamlMap/JokerPicker.js +0 -113
  124. package/dist/components/jamlMap/MysterySlot.js +0 -128
  125. package/dist/components/jamlMap/MysterySlot.stories.d.ts +0 -7
  126. package/dist/components/jamlMap/MysterySlot.stories.js +0 -31
  127. package/dist/components/jamlMap/index.js +0 -4
  128. package/dist/decode/motelyItemDecoder.js +0 -164
  129. package/dist/decode/motelySprite.js +0 -84
  130. package/dist/hooks/analyzerStreamRegistry.js +0 -96
  131. package/dist/hooks/searchWorker.d.ts +0 -1
  132. package/dist/hooks/searchWorker.js +0 -119
  133. package/dist/hooks/searchWorkerCode.d.ts +0 -1
  134. package/dist/hooks/searchWorkerCode.js +0 -85
  135. package/dist/hooks/useAnalyzer.js +0 -91
  136. package/dist/hooks/useIntersectionObserver.js +0 -52
  137. package/dist/hooks/useSearch.js +0 -161
  138. package/dist/hooks/useShopStream.js +0 -85
  139. package/dist/lib/SpriteMapper.js +0 -48
  140. package/dist/lib/cardParser.js +0 -67
  141. package/dist/lib/classes/BuyMetaData.js +0 -1
  142. package/dist/lib/config.js +0 -15
  143. package/dist/lib/const.js +0 -521
  144. package/dist/lib/data/constants.js +0 -14
  145. package/dist/lib/hooks/useDragScroll.js +0 -48
  146. package/dist/lib/hooks/useJamlFilter.js +0 -219
  147. package/dist/lib/hooks/useSeedAnalyzer.js +0 -50
  148. package/dist/lib/jaml/jamlCompletion.js +0 -13
  149. package/dist/lib/jaml/jamlData.js +0 -6
  150. package/dist/lib/jaml/jamlObjectives.js +0 -97
  151. package/dist/lib/jaml/jamlParser.js +0 -47
  152. package/dist/lib/jaml/jamlPresets.js +0 -61
  153. package/dist/lib/jaml/jamlSchema.js +0 -91
  154. package/dist/lib/parseDailyRitual.js +0 -70
  155. package/dist/lib/tts/getRevealPos.js +0 -16
  156. package/dist/lib/tts/splitTtsDisplay.js +0 -35
  157. package/dist/lib/types.js +0 -1
  158. package/dist/lib/utils.js +0 -5
  159. package/dist/motelyDisplay.js +0 -59
  160. package/dist/r3f/Card3D.js +0 -72
  161. package/dist/r3f/JimboBillboard.js +0 -32
  162. package/dist/r3f/JimboText3D.js +0 -8
  163. package/dist/render/CanvasRenderer.js +0 -11
  164. package/dist/render/Layer.js +0 -18
  165. package/dist/sprites/spriteData.js +0 -100
  166. package/dist/sprites/spriteMapper.js +0 -75
  167. package/dist/stories/Button.d.ts +0 -15
  168. package/dist/stories/Button.js +0 -7
  169. package/dist/stories/Button.stories.d.ts +0 -24
  170. package/dist/stories/Button.stories.js +0 -50
  171. package/dist/stories/Header.d.ts +0 -12
  172. package/dist/stories/Header.js +0 -4
  173. package/dist/stories/Header.stories.d.ts +0 -18
  174. package/dist/stories/Header.stories.js +0 -26
  175. package/dist/stories/Page.d.ts +0 -3
  176. package/dist/stories/Page.js +0 -8
  177. package/dist/stories/Page.stories.d.ts +0 -12
  178. package/dist/stories/Page.stories.js +0 -24
  179. package/dist/ui/Jimbo.stories.d.ts +0 -7
  180. package/dist/ui/Jimbo.stories.js +0 -28
  181. package/dist/ui/JimboBadge.js +0 -8
  182. package/dist/ui/JimboFloating.js +0 -17
  183. package/dist/ui/JimboIconButton.js +0 -28
  184. package/dist/ui/JimboInputModal.js +0 -66
  185. package/dist/ui/JimboSelect.js +0 -43
  186. package/dist/ui/JimboToggleList.js +0 -5
  187. package/dist/ui/PanelSplitter.js +0 -78
  188. package/dist/ui/codeBlock.js +0 -14
  189. package/dist/ui/footer.js +0 -20
  190. package/dist/ui/hooks.js +0 -634
  191. package/dist/ui/ide/AgnosticSeedCard.d.ts +0 -19
  192. package/dist/ui/ide/AgnosticSeedCard.js +0 -48
  193. package/dist/ui/ide/DeckSprite.js +0 -2
  194. package/dist/ui/ide/JamlBuilder.d.ts +0 -1
  195. package/dist/ui/ide/JamlBuilder.js +0 -112
  196. package/dist/ui/ide/JamlEditor.js +0 -486
  197. package/dist/ui/ide/JamlEditorMonaco.d.ts +0 -8
  198. package/dist/ui/ide/JamlEditorMonaco.js +0 -78
  199. package/dist/ui/ide/WasmStatus.d.ts +0 -1
  200. package/dist/ui/ide/WasmStatus.js +0 -42
  201. package/dist/ui/jimboApp.js +0 -15
  202. package/dist/ui/jimboBackground.js +0 -27
  203. package/dist/ui/jimboCopyRow.js +0 -18
  204. package/dist/ui/jimboFilterBar.js +0 -16
  205. package/dist/ui/jimboFlankNav.js +0 -18
  206. package/dist/ui/jimboInfoCard.js +0 -26
  207. package/dist/ui/jimboInset.js +0 -9
  208. package/dist/ui/jimboSectionHeader.js +0 -9
  209. package/dist/ui/jimboStatGrid.js +0 -9
  210. package/dist/ui/jimboTabs.js +0 -22
  211. package/dist/ui/jimboText.js +0 -33
  212. package/dist/ui/jimboTooltip.js +0 -39
  213. package/dist/ui/jimboWordmark.js +0 -9
  214. package/dist/ui/mascot/JammySpeechBox.js +0 -30
  215. package/dist/ui/mascot/SeedMascot.js +0 -17
  216. package/dist/ui/mascot/index.js +0 -3
  217. package/dist/ui/mascot/menuConfig.js +0 -12
  218. package/dist/ui/panel.js +0 -24
  219. package/dist/ui/radial/RadialBadge.js +0 -43
  220. package/dist/ui/radial/RadialBreadcrumb.js +0 -18
  221. package/dist/ui/radial/RadialButton.js +0 -102
  222. package/dist/ui/radial/RadialMenu.js +0 -168
  223. package/dist/ui/radial/RadialPill.js +0 -15
  224. package/dist/ui/radial/index.js +0 -18
  225. package/dist/ui/radial/radialMenuStore.js +0 -122
  226. package/dist/ui/radial/radialMenuViewport.js +0 -59
  227. package/dist/ui/radial/useRadialMenu.js +0 -107
  228. package/dist/ui/showcase.js +0 -20
  229. package/dist/ui/sprites.js +0 -77
  230. package/dist/ui/tokens.js +0 -64
  231. package/dist/utils/gameCardUtils.js +0 -15
  232. package/dist/utils/jamlMapPreview.js +0 -106
  233. 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;