jaml-ui 0.24.18 → 0.24.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/DESIGN.md CHANGED
@@ -197,13 +197,13 @@ Panels sit on a dark south-shadow (`0 3px 0 rgba(0,0,0,0.55)`). Translucent pane
197
197
 
198
198
  JAML-hit items get a GlowRing: `box-shadow: 0 0 0 2px [color], 0 0 10px [color]` with a 1.6s pulse animation. Must = blue glow, should = gold/green glow.
199
199
 
200
- **Button:** Chunky 3D press. DO NOT ADD A COLORED EDGE/BORDER. Buttons rely entirely on a solid `box-shadow` to create the colored "underside" depth. Hover brightness bump. Press sinks +2-3px and the box-shadow collapses to 0. Variants: primary (red), secondary (blue), back (orange), default (grey). NO GOLD BUTTONS. Sizes via padding, not font-size. Easing: `cubic-bezier(0.34, 1.56, 0.64, 1)`.
200
+ **Button:** Chunky 3D press. DO NOT ADD A COLORED EDGE/BORDER. Buttons rely entirely on a solid `box-shadow` to create the colored "underside" depth. Hover = dark variant of the button color. Press sinks +2-3px and the box-shadow collapses to 0. Variants: primary (red), secondary (blue), back (orange), default (grey). NO GOLD BUTTONS. Sizes via padding, not font-size. Easing: `cubic-bezier(0.34, 1.56, 0.64, 1)`.
201
201
 
202
202
  **Badge (JimboBadge):** Badges indicate status and DO NOT CLICK. They are strictly flat. They have a colored background and flat borders, but NO 3D BOX-SHADOW and NO PRESS ANIMATIONS. Variants: dark, blue, red, green, orange, purple, grey. NO GOLD BADGES.
203
203
 
204
204
  **Panel:** Dark grey (#3a5055) background, 2px solid border (silver top/sides, south bottom), border-radius 6px. Inner highlight: `inset 0 0 0 1px rgba(255,255,255,0.04)`. Drop: `0 2px 0 #000`.
205
205
 
206
- **Tabs (JimboTabs):** Active tab = gold background + black text. Inactive = transparent + grey text. No bold. Small radius (4px). Tabs are the ONLY navigation — no hamburger menus, no sidebars on mobile.
206
+ **Tabs (JimboTabs):** All tabs are red. Active tab has the bouncing triangle indicator above it. Hover and press = dark red. No opacity changes, no dimming, no gold. Small radius (4px). Tabs are the ONLY navigation — no hamburger menus, no sidebars on mobile.
207
207
 
208
208
  **ScoreCol:** Must-clauses show as blue-framed boxes with checkmark/cross badge. Should-clauses show as bare sprites with a red corner count badge (x2, x3...). Unlit = 40% opacity + grayscale.
209
209
 
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export { useMotelyStream, type StreamItem, type StreamState } from "./hooks/useS
24
24
  export { useSearch, type SearchResult, type SearchStatus, type UseSearchState, } from "./hooks/useSearch.js";
25
25
  export { useAnalyzer, type AnalyzerStatus, type AnalyzerLive, type MotelyJsRunState, } from "./hooks/useAnalyzer.js";
26
26
  export { setMotelyEnums as setMotelyDisplayEnums } from "./motelyDisplay.js";
27
- export { setMotelyEnums as setMotelyDecoderEnums } from "./decode/motelyItemDecoder.js";
27
+ export { setMotelyEnums as setMotelyDecoderEnums, motelyItemRenderCategory, } from "./decode/motelyItemDecoder.js";
28
28
  export { PaginatedFilterBrowser, type PaginatedFilterBrowserProps, type FilterItem, } from "./components/PaginatedFilterBrowser.js";
29
29
  export { JamlAestheticSelector, type JamlAestheticSelectorProps, type JamlAestheticOption, } from "./components/JamlAestheticSelector.js";
30
30
  export { JamlSeedInput, type JamlSeedInputProps, } from "./components/JamlSeedInput.js";
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ export { useAnalyzer, } from "./hooks/useAnalyzer.js";
28
28
  // and call setMotelyEnums(Motely) once after boot so display/decoder helpers
29
29
  // can resolve enum keys without statically importing motely-wasm.
30
30
  export { setMotelyEnums as setMotelyDisplayEnums } from "./motelyDisplay.js";
31
- export { setMotelyEnums as setMotelyDecoderEnums } from "./decode/motelyItemDecoder.js";
31
+ export { setMotelyEnums as setMotelyDecoderEnums, motelyItemRenderCategory, } from "./decode/motelyItemDecoder.js";
32
32
  export { PaginatedFilterBrowser, } from "./components/PaginatedFilterBrowser.js";
33
33
  export { JamlAestheticSelector, } from "./components/JamlAestheticSelector.js";
34
34
  export { JamlSeedInput, } from "./components/JamlSeedInput.js";
package/dist/ui/jimbo.css CHANGED
@@ -6,7 +6,8 @@
6
6
 
7
7
  @font-face {
8
8
  font-family: 'm6x11plus';
9
- src: url('/fonts/m6x11plus.otf') format('opentype');
9
+ src: local('m6x11plus'), local('m6x11plusplus'),
10
+ url('../../assets/fonts/m6x11plusplus.otf') format('opentype');
10
11
  font-weight: normal;
11
12
  font-style: normal;
12
13
  font-display: swap;
@@ -324,7 +325,7 @@
324
325
  }
325
326
 
326
327
  .j-btn:not(.j-btn--disabled):hover .j-btn__face {
327
- filter: brightness(1.1);
328
+ background: var(--j-btn-hover-color, var(--j-btn-face-color));
328
329
  }
329
330
 
330
331
  /* Sizes */
@@ -351,30 +352,37 @@
351
352
  /* Tone colors — set via CSS custom properties */
352
353
  .j-btn--orange {
353
354
  --j-btn-face-color: var(--j-orange);
355
+ --j-btn-hover-color: var(--j-dark-orange);
354
356
  }
355
357
 
356
358
  .j-btn--red {
357
359
  --j-btn-face-color: var(--j-red);
360
+ --j-btn-hover-color: var(--j-dark-red);
358
361
  }
359
362
 
360
363
  .j-btn--blue {
361
364
  --j-btn-face-color: var(--j-blue);
365
+ --j-btn-hover-color: var(--j-dark-blue);
362
366
  }
363
367
 
364
368
  .j-btn--green {
365
369
  --j-btn-face-color: var(--j-green);
370
+ --j-btn-hover-color: var(--j-dark-green);
366
371
  }
367
372
 
368
373
  .j-btn--tarot {
369
374
  --j-btn-face-color: var(--j-tarot-btn);
375
+ --j-btn-hover-color: var(--j-tarot-btn-dark);
370
376
  }
371
377
 
372
378
  .j-btn--planet {
373
379
  --j-btn-face-color: var(--j-planet-btn);
380
+ --j-btn-hover-color: var(--j-planet-btn-dark);
374
381
  }
375
382
 
376
383
  .j-btn--spectral {
377
384
  --j-btn-face-color: var(--j-spectral-btn);
385
+ --j-btn-hover-color: var(--j-spectral-btn-dark);
378
386
  }
379
387
 
380
388
 
@@ -470,7 +478,7 @@
470
478
  }
471
479
 
472
480
  .j-tab__indicator[data-active="true"] {
473
- animation: jimbo-bounce 0.6s ease-in-out infinite;
481
+ animation: jimbo-bounce 0.7s ease-in-out infinite;
474
482
  }
475
483
 
476
484
  .j-tab__indicator[data-active="false"] {
@@ -482,7 +490,7 @@
482
490
  -webkit-appearance: none;
483
491
  border: none;
484
492
  cursor: pointer;
485
- border-radius: var(--j-radius-md);
493
+ border-radius: var(--j-radius-sm);
486
494
  padding: 6px 14px;
487
495
  min-height: 28px;
488
496
  background: var(--j-red);
@@ -490,33 +498,35 @@
490
498
  color: var(--j-white);
491
499
  text-align: center;
492
500
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.8);
493
- transition: filter 80ms linear, opacity 80ms linear;
501
+ transition: background var(--j-press-speed) linear;
494
502
  outline: none;
495
503
  }
496
504
 
497
- .j-tab__btn[data-active="true"] {
498
- opacity: 1;
505
+ .j-tab__btn .j-text {
506
+ color: inherit;
507
+ text-shadow: inherit;
499
508
  }
500
509
 
501
- .j-tab__btn[data-active="true"]:hover {
502
- background: var(--j-red);
510
+ .j-tab__btn:hover {
511
+ background: var(--j-dark-red);
503
512
  }
504
513
 
505
- .j-tab__btn[data-active="false"]:hover {
506
- background: var(--j-red);
507
- filter: brightness(1.08);
514
+ .j-tab__btn:active {
515
+ background: var(--j-dark-red);
508
516
  }
509
517
 
510
518
 
511
519
  @keyframes jimbo-bounce {
512
-
513
- 0%,
514
- 100% {
520
+ 0% {
515
521
  transform: translateY(0);
522
+ animation-timing-function: ease-out;
516
523
  }
517
-
518
- 50% {
519
- transform: translateY(-3px);
524
+ 45% {
525
+ transform: translateY(-5px);
526
+ animation-timing-function: ease-in;
527
+ }
528
+ 100% {
529
+ transform: translateY(0);
520
530
  }
521
531
  }
522
532
 
@@ -991,7 +1001,11 @@
991
1001
  /* ── Footer ───────────────────────────────────────────────────────────── */
992
1002
 
993
1003
  .j-footer {
994
- width: 100%;
1004
+ position: fixed;
1005
+ bottom: 0;
1006
+ left: 0;
1007
+ right: 0;
1008
+ z-index: 100;
995
1009
  transition: opacity 200ms;
996
1010
  }
997
1011
 
@@ -1248,6 +1262,11 @@
1248
1262
  padding: var(--j-space-lg) var(--j-space-lg) var(--j-space-md);
1249
1263
  scrollbar-width: none;
1250
1264
  -ms-overflow-style: none;
1265
+ scroll-snap-type: y mandatory;
1266
+ }
1267
+
1268
+ .j-app__scroll > * {
1269
+ scroll-snap-align: start;
1251
1270
  }
1252
1271
 
1253
1272
  .j-app__scroll::-webkit-scrollbar {
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Fullscreen WebGL CRT/spin background — the authentic Balatro hypnotic
3
- * swirl, pixelated and animated. Ported from weejoker.app's
4
- * BackgroundShader.tsx; no config required.
3
+ * swirl, pixelated and animated. Also renders the attribution footer at the
4
+ * bottom of the viewport (position: fixed) so it is always present and no
5
+ * consumer can accidentally omit it.
5
6
  *
6
- * Renders a fixed-position canvas at z-index: -10 that fills the viewport
7
- * and ignores pointer events. Drop it once at the root of your page:
7
+ * Drop it once at the root of your page:
8
8
  *
9
9
  * <JimboBackground />
10
10
  * <YourAppContent />
@@ -1,12 +1,13 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useBalatroBackground } from './hooks.js';
3
+ import { JimboBalatroFooter } from './footer.js';
3
4
  /**
4
5
  * Fullscreen WebGL CRT/spin background — the authentic Balatro hypnotic
5
- * swirl, pixelated and animated. Ported from weejoker.app's
6
- * BackgroundShader.tsx; no config required.
6
+ * swirl, pixelated and animated. Also renders the attribution footer at the
7
+ * bottom of the viewport (position: fixed) so it is always present and no
8
+ * consumer can accidentally omit it.
7
9
  *
8
- * Renders a fixed-position canvas at z-index: -10 that fills the viewport
9
- * and ignores pointer events. Drop it once at the root of your page:
10
+ * Drop it once at the root of your page:
10
11
  *
11
12
  * <JimboBackground />
12
13
  * <YourAppContent />
@@ -15,12 +16,12 @@ import { useBalatroBackground } from './hooks.js';
15
16
  */
16
17
  export function JimboBackground() {
17
18
  const canvasRef = useBalatroBackground();
18
- return (_jsx("canvas", { ref: canvasRef, "aria-hidden": true, style: {
19
- position: 'fixed',
20
- inset: 0,
21
- width: '100%',
22
- height: '100%',
23
- zIndex: -10,
24
- pointerEvents: 'none',
25
- } }));
19
+ return (_jsxs(_Fragment, { children: [_jsx("canvas", { ref: canvasRef, "aria-hidden": true, style: {
20
+ position: 'fixed',
21
+ inset: 0,
22
+ width: '100%',
23
+ height: '100%',
24
+ zIndex: -10,
25
+ pointerEvents: 'none',
26
+ } }), _jsx(JimboBalatroFooter, {})] }));
26
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaml-ui",
3
- "version": "0.24.18",
3
+ "version": "0.24.20",
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",
@@ -56,18 +56,9 @@
56
56
  "DESIGN.md",
57
57
  "LICENSE"
58
58
  ],
59
- "scripts": {
60
- "build": "tsc --pretty false && node -e \"const fs=require('fs');fs.mkdirSync('dist/ui',{recursive:true});fs.copyFileSync('src/ui/jimbo.css','dist/ui/jimbo.css');\"",
61
- "dev": "tsc --watch",
62
- "demo": "vite --config demo/vite.config.ts",
63
- "typecheck": "tsc --noEmit --pretty false",
64
- "prepack": "npm run build",
65
- "storybook": "storybook dev -p 6006",
66
- "build-storybook": "storybook build",
67
- "lint": "eslint ."
68
- },
69
59
  "engines": {
70
- "node": ">=18"
60
+ "node": ">=18",
61
+ "pnpm": ">=10"
71
62
  },
72
63
  "publishConfig": {
73
64
  "access": "public"
@@ -124,10 +115,9 @@
124
115
  "devDependencies": {
125
116
  "@chromatic-com/storybook": "^5.1.2",
126
117
  "@eslint/js": "^10.0.1",
127
- "@google/design.md": "^0.1.1",
128
118
  "@react-spring/three": "^10.0.3",
129
- "@react-three/drei": ">=9.0.0",
130
- "@react-three/fiber": "^9.6.0",
119
+ "@react-three/drei": "^10.7.7",
120
+ "@react-three/fiber": "^9.6.1",
131
121
  "@storybook/addon-a11y": "^10.3.6",
132
122
  "@storybook/addon-docs": "^10.3.6",
133
123
  "@storybook/addon-onboarding": "^10.3.6",
@@ -137,7 +127,7 @@
137
127
  "@types/react": "^19.2.14",
138
128
  "@types/react-dom": "^19.2.3",
139
129
  "@types/three": "^0.184.0",
140
- "@vitejs/plugin-react": "^5.0.4",
130
+ "@vitejs/plugin-react": "^5.2.0",
141
131
  "@vitest/browser-playwright": "^4.1.5",
142
132
  "@vitest/coverage-v8": "^4.1.5",
143
133
  "eslint": "^10.3.0",
@@ -146,23 +136,23 @@
146
136
  "globals": "^17.6.0",
147
137
  "motely-wasm": "^15.1.3",
148
138
  "playwright": "^1.59.1",
149
- "react": "^19.2.4",
150
- "react-dom": "^19.2.4",
139
+ "react": "^19.2.6",
140
+ "react-dom": "^19.2.6",
151
141
  "react-icons": "^5.6.0",
152
142
  "storybook": "^10.3.6",
153
143
  "three": "^0.184.0",
154
144
  "typescript": "^5.9.3",
155
145
  "typescript-eslint": "^8.59.2",
156
- "vite": "^8.0.9",
146
+ "vite": "^8.0.10",
157
147
  "vitest": "^4.1.5"
158
148
  },
159
149
  "dependencies": {
160
- "@codemirror/autocomplete": "^6.20.1",
150
+ "@codemirror/autocomplete": "^6.20.2",
161
151
  "@codemirror/commands": "^6.10.3",
162
152
  "@codemirror/lang-yaml": "^6.1.3",
163
153
  "@codemirror/language": "^6.12.3",
164
154
  "@codemirror/state": "^6.6.0",
165
- "@codemirror/view": "^6.41.1",
155
+ "@codemirror/view": "^6.42.0",
166
156
  "@json-render/core": "^0.18.0",
167
157
  "@lezer/highlight": "^1.2.3",
168
158
  "@types/js-yaml": "^4.0.9",
@@ -170,6 +160,15 @@
170
160
  "js-yaml": "^4.1.1",
171
161
  "lucide-react": "^1.14.0",
172
162
  "tailwind-merge": "^2.6.1",
173
- "zustand": "^5.0.0"
163
+ "zustand": "^5.0.13"
164
+ },
165
+ "scripts": {
166
+ "build": "tsc --pretty false && node -e \"const fs=require('fs');fs.mkdirSync('dist/ui',{recursive:true});fs.copyFileSync('src/ui/jimbo.css','dist/ui/jimbo.css');\"",
167
+ "dev": "tsc --watch",
168
+ "demo": "vite --config demo/vite.config.ts",
169
+ "typecheck": "tsc --noEmit --pretty false",
170
+ "storybook": "storybook dev -p 6006",
171
+ "build-storybook": "storybook build",
172
+ "lint": "eslint ."
174
173
  }
175
- }
174
+ }