jaml-ui 2.5.1 → 3.0.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 (162) hide show
  1. package/README.md +38 -225
  2. package/dist/chunks/Layer-B5y9UIAt.js +19 -0
  3. package/dist/chunks/Layer-B5y9UIAt.js.map +1 -0
  4. package/dist/chunks/motelySprite-BYsaes3N.js +753 -0
  5. package/dist/chunks/motelySprite-BYsaes3N.js.map +1 -0
  6. package/dist/chunks/spriteMapper-BiDkbZrD.js +480 -0
  7. package/dist/chunks/spriteMapper-BiDkbZrD.js.map +1 -0
  8. package/dist/components/DeckSprite.d.ts +1 -1
  9. package/dist/components/GameCard.d.ts +5 -4
  10. package/dist/components/JamlyzerView.d.ts +9 -0
  11. package/dist/components/StandardCard.d.ts +4 -3
  12. package/dist/core.d.ts +0 -1
  13. package/dist/core.js +38 -26
  14. package/dist/core.js.map +1 -1
  15. package/dist/decode/motelyItemDecoder.d.ts +5 -0
  16. package/dist/index.d.ts +5 -28
  17. package/dist/index.js +3180 -27606
  18. package/dist/index.js.map +1 -1
  19. package/dist/json-render/catalog.d.ts +26 -1
  20. package/dist/json-render/components/domain.d.ts +8 -8
  21. package/dist/json-render/components/game.d.ts +3 -7
  22. package/dist/json-render/components/jammySeedMascotImage.d.ts +1 -0
  23. package/dist/json-render/components/layout.d.ts +2 -1
  24. package/dist/json-render/components/mascot.d.ts +22 -0
  25. package/dist/json-render/components/reference.d.ts +7 -7
  26. package/dist/json-render/engine.d.ts +4 -4
  27. package/dist/json-render/index.d.ts +2 -0
  28. package/dist/motely.d.ts +2 -5
  29. package/dist/motely.js +22 -173
  30. package/dist/motely.js.map +1 -1
  31. package/dist/render/CanvasRenderer.d.ts +2 -1
  32. package/dist/render/useJamlCardRenderer.d.ts +15 -0
  33. package/dist/ui/jimbo.css +1 -2
  34. package/dist/ui.d.ts +0 -39
  35. package/dist/ui.js +58 -3
  36. package/dist/ui.js.map +1 -0
  37. package/package.json +13 -53
  38. package/dist/assets/searchPoolWorker-DA5uFkl3.js +0 -2
  39. package/dist/assets/searchPoolWorker-DA5uFkl3.js.map +0 -1
  40. package/dist/chunks/jamlSeeds-CRthre97.js +0 -69
  41. package/dist/chunks/jamlSeeds-CRthre97.js.map +0 -1
  42. package/dist/chunks/runtime-D7eHq1kP.js +0 -2060
  43. package/dist/chunks/runtime-D7eHq1kP.js.map +0 -1
  44. package/dist/chunks/searchPoolWorker-649yzf3l.js +0 -11
  45. package/dist/chunks/searchPoolWorker-649yzf3l.js.map +0 -1
  46. package/dist/chunks/spriteMapper-BqG15k6f.js +0 -2496
  47. package/dist/chunks/spriteMapper-BqG15k6f.js.map +0 -1
  48. package/dist/chunks/ui-DwggmAYr.js +0 -3399
  49. package/dist/chunks/ui-DwggmAYr.js.map +0 -1
  50. package/dist/components/CardFan.d.ts +0 -13
  51. package/dist/components/JamlAestheticSelector.d.ts +0 -12
  52. package/dist/components/JamlCodeEditor.d.ts +0 -7
  53. package/dist/components/JamlCurator.d.ts +0 -1
  54. package/dist/components/JamlIde.d.ts +0 -44
  55. package/dist/components/JamlIdeToolbar.d.ts +0 -14
  56. package/dist/components/JamlIdeVisual.d.ts +0 -30
  57. package/dist/components/JamlMapPreview.d.ts +0 -11
  58. package/dist/components/JamlSeedInput.d.ts +0 -24
  59. package/dist/components/JamlSeedSpinner.d.ts +0 -9
  60. package/dist/components/JamlSpeedometer.d.ts +0 -16
  61. package/dist/components/Jamlyzer.d.ts +0 -8
  62. package/dist/components/JimmolateEditor.d.ts +0 -47
  63. package/dist/components/MotelyHello.d.ts +0 -5
  64. package/dist/components/MotelyVersionBadge.d.ts +0 -28
  65. package/dist/components/PaginatedFilterBrowser.d.ts +0 -26
  66. package/dist/components/RunConfigModal.d.ts +0 -8
  67. package/dist/components/SeedFinderApp.d.ts +0 -7
  68. package/dist/components/jamlMap/CategoryPicker.d.ts +0 -32
  69. package/dist/components/jamlMap/JamlMapEditor.d.ts +0 -14
  70. package/dist/components/jamlMap/JokerPicker.d.ts +0 -8
  71. package/dist/components/jamlMap/MysterySlot.d.ts +0 -37
  72. package/dist/components/jamlMap/index.d.ts +0 -4
  73. package/dist/components/jamlMap/jokerRarity.d.ts +0 -6
  74. package/dist/components/jamlSeedUtils.d.ts +0 -1
  75. package/dist/hooks/searchPoolWorker.d.ts +0 -61
  76. package/dist/hooks/searchWorker.d.ts +0 -1
  77. package/dist/hooks/useAnalyzer.d.ts +0 -10
  78. package/dist/hooks/useIntersectionObserver.d.ts +0 -14
  79. package/dist/hooks/useJamlLibrary.d.ts +0 -13
  80. package/dist/hooks/useSearch.d.ts +0 -31
  81. package/dist/hooks/useSearchPool.d.ts +0 -43
  82. package/dist/hooks/useShopStream.d.ts +0 -22
  83. package/dist/lib/SpriteMapper.d.ts +0 -10
  84. package/dist/lib/cardParser.d.ts +0 -8
  85. package/dist/lib/classes/BuyMetaData.d.ts +0 -11
  86. package/dist/lib/config.d.ts +0 -13
  87. package/dist/lib/const.d.ts +0 -70
  88. package/dist/lib/data/constants.d.ts +0 -11
  89. package/dist/lib/hooks/useDragScroll.d.ts +0 -4
  90. package/dist/lib/hooks/useJamlFilter.d.ts +0 -48
  91. package/dist/lib/hooks/useSeedAnalyzer.d.ts +0 -5
  92. package/dist/lib/jaml/jamlCompletion.d.ts +0 -12
  93. package/dist/lib/jaml/jamlData.d.ts +0 -4
  94. package/dist/lib/jaml/jamlLangCodemirror.d.ts +0 -13
  95. package/dist/lib/jaml/jamlObjectives.d.ts +0 -13
  96. package/dist/lib/jaml/jamlParser.d.ts +0 -14
  97. package/dist/lib/jaml/jamlPresets.d.ts +0 -8
  98. package/dist/lib/jaml/jamlSchema.d.ts +0 -19
  99. package/dist/lib/jaml/jamlSeeds.d.ts +0 -7
  100. package/dist/lib/motely/runtime.d.ts +0 -40
  101. package/dist/lib/parseDailyRitual.d.ts +0 -45
  102. package/dist/lib/tts/getRevealPos.d.ts +0 -5
  103. package/dist/lib/tts/splitTtsDisplay.d.ts +0 -19
  104. package/dist/lib/types.d.ts +0 -122
  105. package/dist/lib/utils.d.ts +0 -2
  106. package/dist/motelyDisplay.d.ts +0 -10
  107. package/dist/ui/JimboBadge.d.ts +0 -12
  108. package/dist/ui/JimboBalatroFooter.d.ts +0 -16
  109. package/dist/ui/JimboCopyButton.d.ts +0 -27
  110. package/dist/ui/JimboDeckAndStakeSelectorModal.d.ts +0 -30
  111. package/dist/ui/JimboDualChip.d.ts +0 -17
  112. package/dist/ui/JimboIconButton.d.ts +0 -15
  113. package/dist/ui/JimboInlineEdit.d.ts +0 -16
  114. package/dist/ui/JimboInputModal.d.ts +0 -13
  115. package/dist/ui/JimboListItem.d.ts +0 -11
  116. package/dist/ui/JimboPanelSpinner.d.ts +0 -15
  117. package/dist/ui/JimboPanelSplitter.d.ts +0 -8
  118. package/dist/ui/JimboPicker.d.ts +0 -28
  119. package/dist/ui/JimboSeedCopyChip.d.ts +0 -16
  120. package/dist/ui/JimboSelect.d.ts +0 -30
  121. package/dist/ui/JimboSlider.d.ts +0 -11
  122. package/dist/ui/JimboSpinner.d.ts +0 -18
  123. package/dist/ui/JimboStepper.d.ts +0 -22
  124. package/dist/ui/JimboTextInput.d.ts +0 -5
  125. package/dist/ui/JimboToggleList.d.ts +0 -12
  126. package/dist/ui/JimboValueBadge.d.ts +0 -19
  127. package/dist/ui/codeBlock.d.ts +0 -11
  128. package/dist/ui/hooks.d.ts +0 -126
  129. package/dist/ui/ide/JamlEditor.d.ts +0 -7
  130. package/dist/ui/jimboApp.d.ts +0 -9
  131. package/dist/ui/jimboBackground.d.ts +0 -17
  132. package/dist/ui/jimboCopyRow.d.ts +0 -9
  133. package/dist/ui/jimboFilterBar.d.ts +0 -22
  134. package/dist/ui/jimboFlankNav.d.ts +0 -17
  135. package/dist/ui/jimboInfoCard.d.ts +0 -31
  136. package/dist/ui/jimboInset.d.ts +0 -9
  137. package/dist/ui/jimboLayout.d.ts +0 -25
  138. package/dist/ui/jimboLink.d.ts +0 -12
  139. package/dist/ui/jimboSectionHeader.d.ts +0 -11
  140. package/dist/ui/jimboStatGrid.d.ts +0 -13
  141. package/dist/ui/jimboTabs.d.ts +0 -21
  142. package/dist/ui/jimboText.d.ts +0 -25
  143. package/dist/ui/jimboTooltip.d.ts +0 -33
  144. package/dist/ui/jimboWordmark.d.ts +0 -10
  145. package/dist/ui/mascot/JammySpeechBox.d.ts +0 -9
  146. package/dist/ui/mascot/SeedMascot.d.ts +0 -37
  147. package/dist/ui/mascot/index.d.ts +0 -3
  148. package/dist/ui/mascot/menuConfig.d.ts +0 -102
  149. package/dist/ui/panel.d.ts +0 -32
  150. package/dist/ui/radial/RadialBadge.d.ts +0 -16
  151. package/dist/ui/radial/RadialBreadcrumb.d.ts +0 -12
  152. package/dist/ui/radial/RadialButton.d.ts +0 -60
  153. package/dist/ui/radial/RadialMenu.d.ts +0 -38
  154. package/dist/ui/radial/RadialPill.d.ts +0 -17
  155. package/dist/ui/radial/index.d.ts +0 -16
  156. package/dist/ui/radial/radialMenuStore.d.ts +0 -31
  157. package/dist/ui/radial/radialMenuViewport.d.ts +0 -6
  158. package/dist/ui/radial/useRadialMenu.d.ts +0 -35
  159. package/dist/ui/showcase.d.ts +0 -38
  160. package/dist/ui/sprites.d.ts +0 -25
  161. package/dist/utils/jamlMapPreview.d.ts +0 -12
  162. package/dist/utils/jamlVisualFilter.d.ts +0 -3
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jaml-ui",
3
- "version": "2.5.1",
4
- "description": "Balatro rendering components, sprite metadata, and optional Motely helpers for React apps.",
3
+ "version": "3.0.2",
4
+ "description": "Zero-dependency json-render engine + Balatro card sprites for MCP Apps.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -28,7 +28,6 @@
28
28
  },
29
29
  "sideEffects": [
30
30
  "./fonts.css",
31
- "./dist/ui.js",
32
31
  "./dist/ui/jimbo.css",
33
32
  "./dist/index.js"
34
33
  ],
@@ -37,20 +36,16 @@
37
36
  "assets/*.png",
38
37
  "assets/fonts",
39
38
  "fonts.css",
40
- "dist/ui/jimbo.css",
41
39
  "README.md",
42
- "DESIGN.md",
43
40
  "LICENSE"
44
41
  ],
45
42
  "scripts": {
46
43
  "build": "vite build",
47
44
  "dev": "vite build --watch",
48
- "demo": "vite --config demo/vite.config.ts",
49
45
  "typecheck": "tsc --noEmit --pretty false",
50
46
  "prepack": "npm run build",
51
47
  "storybook": "storybook dev -p 3141",
52
48
  "build-storybook": "storybook build",
53
- "serve:storybook": "npx --yes serve storybook-static -l tcp://0.0.0.0:3141 --cors",
54
49
  "lint": "eslint ."
55
50
  },
56
51
  "engines": {
@@ -74,73 +69,38 @@
74
69
  "seed",
75
70
  "card",
76
71
  "sprite",
77
- "ui"
72
+ "ui",
73
+ "json-render",
74
+ "mcp"
78
75
  ],
79
76
  "author": "pifreak",
80
77
  "license": "MIT",
81
78
  "peerDependencies": {
82
- "motely-wasm": ">=23.0.0",
79
+ "motely-wasm": "^23.3.0",
83
80
  "react": "^18.2.0 || ^19.0.0",
84
- "react-dom": "^18.2.0 || ^19.0.0",
85
- "react-icons": ">=5.0.0"
86
- },
87
- "peerDependenciesMeta": {
88
- "react-icons": {
89
- "optional": true
90
- }
81
+ "react-dom": "^18.2.0 || ^19.0.0"
91
82
  },
92
83
  "devDependencies": {
93
- "@chromatic-com/storybook": "^5.2.1",
94
84
  "@eslint/js": "^10.0.1",
95
- "@storybook/addon-a11y": "^10.4.6",
96
- "@storybook/addon-docs": "^10.4.6",
97
- "@storybook/addon-mcp": "^0.6.0",
98
- "@storybook/addon-vitest": "^10.4.6",
99
- "@storybook/react-vite": "^10.4.6",
100
85
  "@types/node": "^25.9.4",
101
86
  "@types/react": "^19.2.17",
102
87
  "@types/react-dom": "^19.2.3",
88
+ "@storybook/react": "^10.4.6",
89
+ "@storybook/react-vite": "^10.4.6",
103
90
  "@vitejs/plugin-react": "^5.2.0",
104
- "@vitest/browser-playwright": "^4.1.9",
105
- "@vitest/coverage-v8": "^4.1.9",
106
91
  "eslint": "^10.6.0",
107
92
  "eslint-plugin-react-hooks": "^7.1.1",
108
93
  "eslint-plugin-react-refresh": "^0.5.3",
109
- "eslint-plugin-storybook": "^10.4.6",
110
94
  "globals": "^17.7.0",
111
- "motely-wasm": "^23.0.0",
112
- "playwright": "^1.61.1",
95
+ "motely-wasm": "^23.3.0",
113
96
  "react": "^19.2.7",
114
97
  "react-dom": "^19.2.7",
115
- "react-icons": "^5.6.0",
116
98
  "storybook": "^10.4.6",
117
99
  "typescript": "^5.9.3",
118
100
  "typescript-eslint": "^8.62.0",
119
- "vite": "^8.1.0",
101
+ "vite": "^6.0.0",
120
102
  "vite-plugin-dts": "^5.0.3",
121
- "vitest": "^4.1.9"
122
- },
123
- "dependencies": {
124
- "@codemirror/autocomplete": "^6.20.3",
125
- "@codemirror/commands": "^6.10.4",
126
- "@codemirror/lang-javascript": "^6.2.5",
127
- "@codemirror/lang-yaml": "^6.1.3",
128
- "@codemirror/language": "^6.12.4",
129
- "@codemirror/lint": "^6.9.7",
130
- "@codemirror/state": "^6.7.0",
131
- "@codemirror/view": "^6.43.4",
132
- "@lezer/highlight": "^1.2.3",
133
- "@types/js-yaml": "^4.0.9",
134
- "clsx": "^2.1.1",
135
- "jaml-lang": "^0.1.2",
136
- "js-yaml": "^4.3.0",
137
- "lucide-react": "^1.21.0",
138
- "tailwind-merge": "^2.6.1",
139
- "zustand": "^5.0.14"
140
- },
141
- "pnpm": {
142
- "overrides": {
143
- "valibot": "^1.4.1"
144
- }
103
+ "eslint-plugin-storybook": "10.4.6",
104
+ "@storybook/addon-docs": "^10.4.6"
145
105
  }
146
106
  }
@@ -1,2 +0,0 @@
1
- import e,{JamlAesthetic as t,Jimmolate as n,MotelyJaml as r,MotelySearch as i,MotelyUtilities as a}from"motely-wasm";function o(e){let t=r.validate(e);if(t)throw Error(t);return r.fromYaml(e)}let s=()=>!0;n.findSeed=(e,t,n)=>s(e,t,n);function c(e){s=e}function l(e=!0){n.enabled=e}function u(e){switch(e){case t.Gross:return a.grossKeywords();case t.Funny:return a.funnyKeywords();case t.Balatro:return a.balatroKeywords();case t.Palindrome:return a.mirrorPatternKeywords(8);case t.Echo:return a.repeatCharKeywords(8);default:return a.balatroKeywords()}}function d(e,n,r={}){switch(n){case`seedlist`:return r.seeds&&(e.seeds=r.seeds),i.searchList(e);case`random`:return i.searchRandom(e,r.count&&r.count>0?r.count:0);case`sequential`:return i.searchSequential(e,r.startBatchIndex??0n,r.endBatchIndex??0n,r.batchCharacterCount??0);case`aesthetic`:return e.seeds=u(r.aesthetic??t.Balatro),i.searchList(e);default:return i.searchList(e)}}let f=null;async function p(){if(f)return f;if(e.getStatus()===e.BootStatus.Standby)return f=(async()=>{await e.boot()})(),f}const m=globalThis;let h=[],g=0,_=null;function v(){for(let e of h)e();h=[]}function y(){v(),_=null;let e=e=>{m.postMessage({type:`result`,workerIndex:g,seed:e.seed,score:e.score,tallyColumns:[]})};i.onScoredResult.subscribe(e),h.push(()=>i.onScoredResult.unsubscribe(e));let t=e=>{_=e,m.postMessage({type:`progress`,workerIndex:g,searched:Number(e.seedsSearched),matching:Number(e.matchingSeeds),percent:e.percentComplete,seedsPerMs:e.seedsPerMillisecond})};i.onProgress.subscribe(t),h.push(()=>i.onProgress.unsubscribe(t));let n=e=>{m.postMessage({type:`match`,workerIndex:g,seed:e})};i.onSeedMatch.subscribe(n),h.push(()=>i.onSeedMatch.unsubscribe(n))}function b(e,t){return typeof t.deck==`number`&&(e.deck=t.deck),typeof t.stake==`number`&&(e.stake=t.stake),e}function x(e){return d(b(o(e.jaml),e),e.mode,{seeds:e.seeds,count:e.count,aesthetic:e.aesthetic,startBatchIndex:typeof e.startBatchIndex==`string`?BigInt(e.startBatchIndex):void 0,endBatchIndex:typeof e.endBatchIndex==`string`?BigInt(e.endBatchIndex):void 0,batchCharacterCount:typeof e.batchCharacterCount==`number`?e.batchCharacterCount:void 0})}m.onmessage=async e=>{let t=e.data;if(t.type===`stop`){v(),m.postMessage({type:`cancelled`,workerIndex:g});return}if(t.type===`start`){g=t.workerIndex;try{if(await p(),t.predicateStr)try{let e=Function(`seed`,`deck`,`stake`,`return (${t.predicateStr})(seed, deck, stake);`);c((t,n,r)=>e(t,n,r)),l()}catch(e){console.error(`Failed to compile worker Jimmolate predicate:`,e)}y();try{await x(t),m.postMessage({type:`complete`,workerIndex:g,status:`Completed`,total:_?Number(_.seedsSearched):0,matched:_?Number(_.matchingSeeds):0})}finally{v()}}catch(e){v(),m.postMessage({type:`error`,workerIndex:g,message:e instanceof Error?e.message:String(e)})}}},m.postMessage({type:`ready`});
2
- //# sourceMappingURL=searchPoolWorker-DA5uFkl3.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"searchPoolWorker-DA5uFkl3.js","names":[],"sources":["../../src/lib/motely/runtime.ts","../../src/hooks/searchPoolWorker.ts"],"sourcesContent":["import bootsharp, {\n MotelyJaml,\n MotelySearch,\n MotelyJamlyzer,\n MotelyUtilities,\n Jimmolate,\n JamlAesthetic,\n} from \"motely-wasm\";\nimport type { JamlConfig, MotelyJamlyzerSeedResult } from \"motely-wasm\";\n\nexport type MotelyRuntimeStatus = \"idle\" | \"booting\" | \"ready\" | \"error\";\n\n// ── motely-wasm@23 ──\n// The old `Program` namespace (parseJaml / run*Search / jamlyzer / the file-system\n// ops) was removed. v23 splits the surface into top-level namespaces — MotelyJaml,\n// MotelySearch, MotelyJamlyzer, MotelyUtilities, Jimmolate — re-exported from the\n// single package root. The thin adapters below sit on those real exports so the\n// rest of jaml-ui keeps one engine entry point.\n\n// ── Parse / validate ──\n// v23 replaced `Program.parseJaml` (parse-or-throw) with MotelyJaml.validate\n// (returns an error string, or null when valid) + MotelyJaml.fromYaml (the parse).\n// Preserve the parse-or-throw contract every caller relies on.\nexport function parseJaml(jaml: string): JamlConfig {\n const error = MotelyJaml.validate(jaml);\n if (error) throw new Error(error);\n return MotelyJaml.fromYaml(jaml);\n}\n\n/** Column labels for a parsed filter's score tallies (was `MotelyJamlyzerResult.tallyLabels`). */\nexport function tallyLabelsFor(config: JamlConfig): string[] {\n return MotelyJaml.createPlan(config).tallyLabels ?? [];\n}\n\n// ── Jimmolate probe ──\n// v23 exposes `Jimmolate.findSeed` (a settable predicate) + `Jimmolate.enabled`.\n// findSeed is a Bootsharp [Import]: it must be assigned BEFORE boot() or the C#\n// side calls an unbound import. So bind a stable dispatcher at module load (this\n// runs on import, always before any ensureMotelyReady()/boot()) and swap the inner\n// predicate per search via setJimmolateProbe().\ntype JimmolateProbe = (seed: string, deck: number, stake: number) => boolean;\nlet currentProbe: JimmolateProbe = () => true;\nJimmolate.findSeed = (seed: string, deck: number, stake: number) => currentProbe(seed, deck, stake);\n\n/** Swap the active Jimmolate predicate. Safe before or after boot. */\nexport function setJimmolateProbe(pred: JimmolateProbe): void {\n currentProbe = pred;\n}\n\n/** Reset the probe to pass-through (the engine's default: every survivor matches). */\nexport function clearJimmolateProbe(): void {\n currentProbe = () => true;\n}\n\n/** Turn the Jimmolate predicate layer on/off (was `Program.enableJimmolate()`). */\nexport function enableJimmolate(on = true): void {\n Jimmolate.enabled = on;\n}\n\n// ── Search ──\nexport type EngineSearchMode = \"aesthetic\" | \"seedlist\" | \"random\" | \"sequential\";\n\nexport interface RunSearchOptions {\n seeds?: string[];\n count?: number;\n aesthetic?: JamlAesthetic | number;\n startBatchIndex?: bigint;\n endBatchIndex?: bigint;\n batchCharacterCount?: number;\n}\n\n// v23's aesthetics no longer have a dedicated `runAestheticSearch`. They are seed\n// keyword sets generated by MotelyUtilities; an aesthetic search is those seeds\n// run through searchList. This reconstructs the removed entry point; the\n// palindrome/echo lengths mirror Balatro's 8-char seed space.\nexport function aestheticSeeds(aesthetic: JamlAesthetic | number): string[] {\n switch (aesthetic as JamlAesthetic) {\n case JamlAesthetic.Gross:\n return MotelyUtilities.grossKeywords();\n case JamlAesthetic.Funny:\n return MotelyUtilities.funnyKeywords();\n case JamlAesthetic.Balatro:\n return MotelyUtilities.balatroKeywords();\n case JamlAesthetic.Palindrome:\n return MotelyUtilities.mirrorPatternKeywords(8);\n case JamlAesthetic.Echo:\n return MotelyUtilities.repeatCharKeywords(8);\n default:\n return MotelyUtilities.balatroKeywords();\n }\n}\n\n/**\n * Run a search to completion against an already-parsed config.\n *\n * v23 searches are fire-and-forget Promises (no IMotelySearch handle, no\n * mid-search cancel). Subscribe to MotelySearch.onProgress / onScoredResult /\n * onSeedMatch BEFORE calling this; the returned Promise resolves when the engine\n * finishes. Callers cancel by tearing down their runtime (e.g. terminating the\n * worker) — there is no engine-level cancel in v23.\n */\nexport function runSearch(config: JamlConfig, mode: EngineSearchMode, opts: RunSearchOptions = {}): Promise<void> {\n switch (mode) {\n case \"seedlist\":\n if (opts.seeds) config.seeds = opts.seeds;\n return MotelySearch.searchList(config);\n case \"random\":\n return MotelySearch.searchRandom(config, opts.count && opts.count > 0 ? opts.count : 0);\n case \"sequential\":\n return MotelySearch.searchSequential(\n config,\n opts.startBatchIndex ?? 0n,\n opts.endBatchIndex ?? 0n,\n opts.batchCharacterCount ?? 0,\n );\n case \"aesthetic\":\n config.seeds = aestheticSeeds(opts.aesthetic ?? JamlAesthetic.Balatro);\n return MotelySearch.searchList(config);\n default:\n return MotelySearch.searchList(config);\n }\n}\n\n// ── Analyzer ──\n/** Analyze one or more seeds against a parsed config (was `Program.jamlyzer`). */\nexport function analyzeSeeds(config: JamlConfig): MotelyJamlyzerSeedResult[] {\n return MotelyJamlyzer.analyzeSeeds(config);\n}\n\n// Must match the path the host serves motely-wasm's bin/ at. Used by main-thread\n// hooks, workers, and Storybook staticDir alike.\nexport const MOTELY_BIN_PATH = \"/motely-wasm/bin\";\n\n// File System for the JAML library: motely-wasm@23 removed the engine-side ops\n// (IFileMounter / pickRoot / mountRoot / readTextFile / writeTextFile) and the\n// `@rewaffle/bootsharp-file-system` peer. But JAML files are plain text, so the\n// library doesn't need the engine at all — useJamlLibrary now backs the mount\n// directly on the browser File System Access API. These helpers report whether\n// that API is actually available (Chromium-based browser over https), so the\n// \"unsupported\" path is honest rather than faked.\nexport function isFileSystemReady(): boolean {\n return (\n typeof window !== \"undefined\" &&\n window.isSecureContext === true &&\n typeof (window as unknown as { showDirectoryPicker?: unknown }).showDirectoryPicker === \"function\"\n );\n}\n\n/** The reason the File System Access API is unavailable, or null when it's ready. */\nexport function getFileSystemError(): unknown {\n return isFileSystemReady()\n ? null\n : new Error(\"This browser has no File System Access API (needs a Chromium-based browser over https).\");\n}\n\n// Single boot promise: boot() runs exactly once and is awaited by every caller.\nlet bootPromise: Promise<void> | null = null;\n\nexport async function ensureMotelyReady(): Promise<void> {\n if (bootPromise) return bootPromise;\n if (bootsharp.getStatus() !== bootsharp.BootStatus.Standby) return;\n bootPromise = (async () => {\n // motely-wasm is an EMBEDDED build (the runtime is inlined into the JS as\n // base64 — see dist/generated/resources.g.mjs), so boot() takes no args and\n // needs no served binaries.\n await bootsharp.boot();\n })();\n return bootPromise;\n}\n","/// <reference lib=\"webworker\" />\n\n// Pool worker. Each instance boots its own motely-wasm runtime (single-threaded\n// per Bootsharp 0.8 post-#203 — no SAB, no COOP/COEP). The owning `useSearchPool`\n// hook is responsible for partitioning the input space and assigning each worker\n// a disjoint slice via the fields on PoolStartMessage. This worker just runs\n// what it is told.\nimport { MotelySearch } from \"motely-wasm\";\nimport type { MotelyProgress, MotelyScoredSeedResult, MotelyDeck, MotelyStake, JamlConfig } from \"motely-wasm\";\nimport {\n ensureMotelyReady,\n parseJaml,\n runSearch,\n setJimmolateProbe,\n enableJimmolate,\n type EngineSearchMode,\n} from \"../lib/motely/runtime.js\";\n\nconst self = globalThis as typeof globalThis & DedicatedWorkerGlobalScope;\n\nexport type PoolSearchMode = \"random\" | \"seedlist\" | \"sequential\" | \"aesthetic\";\n\nexport interface PoolStartMessage {\n type: \"start\";\n workerIndex: number;\n workerCount: number;\n mode: PoolSearchMode;\n jaml: string;\n count?: number;\n seeds?: string[];\n batchCharacterCount?: number;\n startBatchIndex?: string;\n endBatchIndex?: string;\n aesthetic?: number;\n deck?: number;\n stake?: number;\n predicateStr?: string;\n}\n\nexport interface PoolStopMessage {\n type: \"stop\";\n}\n\nexport type PoolInboundMessage = PoolStartMessage | PoolStopMessage;\n\nexport interface PoolReadyMessage {\n type: \"ready\";\n}\n\nexport interface PoolResultMessage {\n type: \"result\";\n workerIndex: number;\n seed: string;\n score: number;\n tallyColumns: number[];\n}\n\nexport interface PoolMatchMessage {\n type: \"match\";\n workerIndex: number;\n seed: string;\n}\n\nexport interface PoolProgressMessage {\n type: \"progress\";\n workerIndex: number;\n searched: number;\n matching: number;\n percent: number;\n seedsPerMs: number;\n}\n\nexport interface PoolCompleteMessage {\n type: \"complete\";\n workerIndex: number;\n status: \"Completed\" | \"Cancelled\";\n total: number;\n matched: number;\n}\n\nexport interface PoolCancelledMessage {\n type: \"cancelled\";\n workerIndex: number;\n}\n\nexport interface PoolErrorMessage {\n type: \"error\";\n workerIndex: number;\n message: string;\n}\n\nexport type PoolOutboundMessage =\n | PoolReadyMessage\n | PoolResultMessage\n | PoolMatchMessage\n | PoolProgressMessage\n | PoolCompleteMessage\n | PoolCancelledMessage\n | PoolErrorMessage;\n\nlet unsubscribers: Array<() => void> = [];\nlet workerIndex = 0;\n// motely-wasm@23 searches don't return totals; capture them from the last\n// MotelyProgress broadcast before the search Promise resolves.\nlet lastProgress: MotelyProgress | null = null;\n\nfunction detachListeners(): void {\n for (const off of unsubscribers) off();\n unsubscribers = [];\n}\n\nfunction attachListeners(): void {\n detachListeners();\n lastProgress = null;\n\n const onResult = (result: MotelyScoredSeedResult) => {\n self.postMessage({\n type: \"result\",\n workerIndex,\n seed: result.seed,\n score: result.score,\n tallyColumns: [],\n } satisfies PoolResultMessage);\n };\n MotelySearch.onScoredResult.subscribe(onResult);\n unsubscribers.push(() => MotelySearch.onScoredResult.unsubscribe(onResult));\n\n const onProgress = (progress: MotelyProgress) => {\n lastProgress = progress;\n self.postMessage({\n type: \"progress\",\n workerIndex,\n searched: Number(progress.seedsSearched),\n matching: Number(progress.matchingSeeds),\n percent: progress.percentComplete,\n seedsPerMs: progress.seedsPerMillisecond,\n } satisfies PoolProgressMessage);\n };\n MotelySearch.onProgress.subscribe(onProgress);\n unsubscribers.push(() => MotelySearch.onProgress.unsubscribe(onProgress));\n\n const onSeedMatch = (seed: string) => {\n self.postMessage({\n type: \"match\",\n workerIndex,\n seed,\n } satisfies PoolMatchMessage);\n };\n MotelySearch.onSeedMatch.subscribe(onSeedMatch);\n unsubscribers.push(() => MotelySearch.onSeedMatch.unsubscribe(onSeedMatch));\n}\n\n// deck/stake are config fields now; the worker is single-threaded, so the old\n// withThreadCount(1) is dropped (it was a no-op here).\nfunction applyCommonOverrides(config: JamlConfig, message: PoolStartMessage): JamlConfig {\n if (typeof message.deck === \"number\") {\n config.deck = message.deck as MotelyDeck;\n }\n if (typeof message.stake === \"number\") {\n config.stake = message.stake as MotelyStake;\n }\n return config;\n}\n\nfunction startSearchFor(message: PoolStartMessage): Promise<void> {\n const config = applyCommonOverrides(parseJaml(message.jaml), message);\n return runSearch(config, message.mode as EngineSearchMode, {\n seeds: message.seeds,\n count: message.count,\n aesthetic: message.aesthetic,\n startBatchIndex: typeof message.startBatchIndex === \"string\" ? BigInt(message.startBatchIndex) : undefined,\n endBatchIndex: typeof message.endBatchIndex === \"string\" ? BigInt(message.endBatchIndex) : undefined,\n batchCharacterCount: typeof message.batchCharacterCount === \"number\" ? message.batchCharacterCount : undefined,\n });\n}\n\nself.onmessage = async (event: MessageEvent) => {\n const data = event.data as PoolInboundMessage;\n\n if (data.type === \"stop\") {\n // No engine-level cancel in motely-wasm@23: the owning hook terminates this\n // worker to truly stop. Detach + ack so the pool can settle.\n detachListeners();\n self.postMessage({ type: \"cancelled\", workerIndex } satisfies PoolCancelledMessage);\n return;\n }\n\n if (data.type !== \"start\") return;\n\n workerIndex = data.workerIndex;\n\n try {\n await ensureMotelyReady();\n\n if (data.predicateStr) {\n try {\n const pred = new Function(\"seed\", \"deck\", \"stake\", `return (${data.predicateStr})(seed, deck, stake);`) as (seed: string, deck: number, stake: number) => boolean;\n setJimmolateProbe((seed, deck, stake) => pred(seed, deck, stake));\n enableJimmolate();\n } catch (err) {\n console.error(\"Failed to compile worker Jimmolate predicate:\", err);\n }\n }\n\n attachListeners();\n\n try {\n await startSearchFor(data);\n self.postMessage({\n type: \"complete\",\n workerIndex,\n status: \"Completed\",\n total: lastProgress ? Number(lastProgress.seedsSearched) : 0,\n matched: lastProgress ? Number(lastProgress.matchingSeeds) : 0,\n } satisfies PoolCompleteMessage);\n } finally {\n detachListeners();\n }\n } catch (error) {\n detachListeners();\n self.postMessage({\n type: \"error\",\n workerIndex,\n message: error instanceof Error ? error.message : String(error),\n } satisfies PoolErrorMessage);\n }\n};\n\nself.postMessage({ type: \"ready\" } satisfies PoolReadyMessage);\n"],"mappings":"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"}
@@ -1,69 +0,0 @@
1
- import { C as e } from "./spriteMapper-BqG15k6f.js";
2
- //#region src/render/Layer.ts
3
- var t, n = e((() => {
4
- t = class {
5
- pos;
6
- name;
7
- order;
8
- source;
9
- rows;
10
- columns;
11
- animated;
12
- constructor({ pos: e, name: t, order: n, source: r, rows: i, columns: a, animated: o = !1 }) {
13
- this.pos = e, this.name = t, this.order = n, this.source = r, this.rows = i, this.columns = a, this.animated = o;
14
- }
15
- };
16
- }));
17
- //#endregion
18
- //#region src/lib/jaml/jamlSeeds.ts
19
- function r(e) {
20
- let t = e.split(/\r?\n/), n = [], r = !1;
21
- for (let e of t) {
22
- if (/^seeds:\s*$/.test(e)) {
23
- r = !0;
24
- continue;
25
- }
26
- if (!r) continue;
27
- let t = e.match(/^\s+-\s+(\S+)\s*$/);
28
- if (t) {
29
- n.push(t[1]);
30
- continue;
31
- }
32
- if (e.trim() !== "") break;
33
- }
34
- return n;
35
- }
36
- function i(e) {
37
- return e.length === 0 ? ["seeds:"] : ["seeds:", ...e.map((e) => ` - ${e}`)];
38
- }
39
- function a(e, t, n = 1e3) {
40
- let r = i([...new Set(t.map((e) => e.trim()).filter(Boolean))].slice(0, n)), a = e.split(/\r?\n/), o = a.findIndex((e) => /^seeds:\s*$/.test(e));
41
- if (o >= 0) {
42
- let e = o + 1;
43
- for (; e < a.length;) {
44
- let t = a[e];
45
- if (/^\s+-\s+\S+/.test(t)) {
46
- e += 1;
47
- continue;
48
- }
49
- if (t.trim() === "") {
50
- e += 1;
51
- continue;
52
- }
53
- break;
54
- }
55
- let t = a.slice(0, o);
56
- for (; t.length > 0 && t[t.length - 1].trim() === "";) t.pop();
57
- let n = a.slice(e);
58
- return [
59
- ...t,
60
- ...r,
61
- ...n
62
- ].join("\n").replace(/\n+$/, "") + "\n";
63
- }
64
- return `${e.replace(/\n+$/, "")}\n${r.join("\n")}\n`;
65
- }
66
- //#endregion
67
- export { n as i, r as n, t as r, a as t };
68
-
69
- //# sourceMappingURL=jamlSeeds-CRthre97.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jamlSeeds-CRthre97.js","names":[],"sources":["../../src/render/Layer.ts","../../src/lib/jaml/jamlSeeds.ts"],"sourcesContent":["/**\n * Layer class for sprite-based card rendering.\n * Encapsulates the source, position, and dimensions of a sprite layer.\n */\nexport interface LayerOptions {\n pos: { x: number; y: number };\n name: string;\n order: number;\n source: string;\n rows: number;\n columns: number;\n animated?: boolean;\n}\n\nexport class Layer {\n pos: { x: number; y: number };\n name: string;\n order: number;\n source: string;\n rows: number;\n columns: number;\n animated: boolean;\n\n constructor({ pos, name, order, source, rows, columns, animated = false }: LayerOptions) {\n this.pos = pos;\n this.name = name;\n this.order = order;\n this.source = source;\n this.rows = rows;\n this.columns = columns;\n this.animated = animated;\n }\n}\n","/** Read top-level `seeds:` entries from a JAML document. */\nexport function parseJamlSeeds(jaml: string): string[] {\n const lines = jaml.split(/\\r?\\n/);\n const seeds: string[] = [];\n let inSeeds = false;\n\n for (const line of lines) {\n if (/^seeds:\\s*$/.test(line)) {\n inSeeds = true;\n continue;\n }\n if (!inSeeds) continue;\n\n const item = line.match(/^\\s+-\\s+(\\S+)\\s*$/);\n if (item) {\n seeds.push(item[1]);\n continue;\n }\n if (line.trim() === \"\") continue;\n break;\n }\n\n return seeds;\n}\n\nfunction formatSeedsBlock(seeds: string[]): string[] {\n if (seeds.length === 0) return [\"seeds:\"];\n return [\"seeds:\", ...seeds.map((seed) => ` - ${seed}`)];\n}\n\n/**\n * Write seeds into JAML the same way Motely CLI `--save-seeds` does:\n * replace the top-level `seeds:` block (or append one if missing).\n */\nexport function mergeSeedsIntoJaml(jaml: string, seeds: string[], max = 1000): string {\n const capped = [...new Set(seeds.map((s) => s.trim()).filter(Boolean))].slice(0, max);\n const block = formatSeedsBlock(capped);\n const lines = jaml.split(/\\r?\\n/);\n const seedsLineIdx = lines.findIndex((line) => /^seeds:\\s*$/.test(line));\n\n if (seedsLineIdx >= 0) {\n let end = seedsLineIdx + 1;\n while (end < lines.length) {\n const line = lines[end];\n if (/^\\s+-\\s+\\S+/.test(line)) {\n end += 1;\n continue;\n }\n if (line.trim() === \"\") {\n end += 1;\n continue;\n }\n break;\n }\n\n const before = lines.slice(0, seedsLineIdx);\n while (before.length > 0 && before[before.length - 1].trim() === \"\") {\n before.pop();\n }\n const after = lines.slice(end);\n return [...before, ...block, ...after].join(\"\\n\").replace(/\\n+$/, \"\") + \"\\n\";\n }\n\n const trimmed = jaml.replace(/\\n+$/, \"\");\n return `${trimmed}\\n${block.join(\"\\n\")}\\n`;\n}\n"],"mappings":";;;CAca,IAAb,MAAmB;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EAEA,YAAY,EAAE,QAAK,SAAM,UAAO,WAAQ,SAAM,YAAS,cAAW,MAAuB;GAOrF,AANA,KAAK,MAAM,GACX,KAAK,OAAO,GACZ,KAAK,QAAQ,GACb,KAAK,SAAS,GACd,KAAK,OAAO,GACZ,KAAK,UAAU,GACf,KAAK,WAAW;EACpB;CACJ;;;;AC/BA,SAAgB,EAAe,GAAwB;CACrD,IAAM,IAAQ,EAAK,MAAM,OAAO,GAC1B,IAAkB,CAAC,GACrB,IAAU;CAEd,KAAK,IAAM,KAAQ,GAAO;EACxB,IAAI,cAAc,KAAK,CAAI,GAAG;GAC5B,IAAU;GACV;EACF;EACA,IAAI,CAAC,GAAS;EAEd,IAAM,IAAO,EAAK,MAAM,mBAAmB;EAC3C,IAAI,GAAM;GACR,EAAM,KAAK,EAAK,EAAE;GAClB;EACF;EACI,MAAK,KAAK,MAAM,IACpB;CACF;CAEA,OAAO;AACT;AAEA,SAAS,EAAiB,GAA2B;CAEnD,OADI,EAAM,WAAW,IAAU,CAAC,QAAQ,IACjC,CAAC,UAAU,GAAG,EAAM,KAAK,MAAS,OAAO,GAAM,CAAC;AACzD;AAMA,SAAgB,EAAmB,GAAc,GAAiB,IAAM,KAAc;CAEpF,IAAM,IAAQ,EADC,CAAC,GAAG,IAAI,IAAI,EAAM,KAAK,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,CAClD,CAAM,GAC/B,IAAQ,EAAK,MAAM,OAAO,GAC1B,IAAe,EAAM,WAAW,MAAS,cAAc,KAAK,CAAI,CAAC;CAEvE,IAAI,KAAgB,GAAG;EACrB,IAAI,IAAM,IAAe;EACzB,OAAO,IAAM,EAAM,SAAQ;GACzB,IAAM,IAAO,EAAM;GACnB,IAAI,cAAc,KAAK,CAAI,GAAG;IAC5B,KAAO;IACP;GACF;GACA,IAAI,EAAK,KAAK,MAAM,IAAI;IACtB,KAAO;IACP;GACF;GACA;EACF;EAEA,IAAM,IAAS,EAAM,MAAM,GAAG,CAAY;EAC1C,OAAO,EAAO,SAAS,KAAK,EAAO,EAAO,SAAS,GAAG,KAAK,MAAM,KAC/D,EAAO,IAAI;EAEb,IAAM,IAAQ,EAAM,MAAM,CAAG;EAC7B,OAAO;GAAC,GAAG;GAAQ,GAAG;GAAO,GAAG;EAAK,EAAE,KAAK,IAAI,EAAE,QAAQ,QAAQ,EAAE,IAAI;CAC1E;CAGA,OAAO,GADS,EAAK,QAAQ,QAAQ,EAC3B,EAAQ,IAAI,EAAM,KAAK,IAAI,EAAE;AACzC"}