jaml-ui 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/components/GameCard.d.ts +8 -4
- package/dist/components/GameCard.js +8 -8
- package/dist/components/JamlIde.d.ts +17 -0
- package/dist/components/JamlIde.js +61 -0
- package/dist/components/JamlIdeToolbar.d.ts +8 -0
- package/dist/components/JamlIdeToolbar.js +36 -0
- package/dist/components/JamlMapPreview.d.ts +10 -0
- package/dist/components/JamlMapPreview.js +117 -0
- package/dist/data/balatro-jokers.json +1241 -0
- package/dist/decode/motelyItemDecoder.d.ts +49 -5
- package/dist/decode/motelyItemDecoder.js +227 -8
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/motely.d.ts +1 -1
- package/dist/motely.js +1 -1
- package/dist/r3f/BalatroJokerMesh3D.d.ts +8 -0
- package/dist/r3f/BalatroJokerMesh3D.js +98 -0
- package/dist/r3f/BalatroJokerPreview3D.d.ts +14 -0
- package/dist/r3f/BalatroJokerPreview3D.js +30 -0
- package/dist/r3f/BalatroPlayingCard3D.d.ts +22 -0
- package/dist/r3f/BalatroPlayingCard3D.js +62 -0
- package/dist/r3f/cardConstants.d.ts +16 -0
- package/dist/r3f/cardConstants.js +14 -0
- package/dist/r3f/compositedAtlas.d.ts +5 -0
- package/dist/r3f/compositedAtlas.js +56 -0
- package/dist/r3f/gridUV.d.ts +22 -0
- package/dist/r3f/gridUV.js +30 -0
- package/dist/r3f/index.d.ts +12 -0
- package/dist/r3f/index.js +13 -0
- package/dist/r3f/jokerRegistry.d.ts +28 -0
- package/dist/r3f/jokerRegistry.js +40 -0
- package/dist/r3f/jokerTilt.d.ts +8 -0
- package/dist/r3f/jokerTilt.js +41 -0
- package/dist/r3f/magneticTilt.d.ts +18 -0
- package/dist/r3f/magneticTilt.js +34 -0
- package/dist/r3f/playingCardTypes.d.ts +24 -0
- package/dist/r3f/playingCardTypes.js +32 -0
- package/dist/r3f/playingCardVisuals.d.ts +7 -0
- package/dist/r3f/playingCardVisuals.js +45 -0
- package/dist/r3f/usePlayingCardTexture.d.ts +7 -0
- package/dist/r3f/usePlayingCardTexture.js +92 -0
- package/dist/render/CanvasRenderer.d.ts +2 -1
- package/dist/render/CanvasRenderer.js +31 -3
- package/dist/utils/jamlMapPreview.d.ts +12 -0
- package/dist/utils/jamlMapPreview.js +105 -0
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Balatro rendering components, sprite metadata, and optional Motely helpers for React apps.
|
|
4
4
|
|
|
5
|
+
`jaml-ui` is the shared UI layer for Balatro/JAML surfaces: low-level renderers, asset helpers, visual JAML previews, and a lightweight browser-first JAML IDE shell.
|
|
6
|
+
|
|
5
7
|
## Package shape
|
|
6
8
|
|
|
7
9
|
- `jaml-ui`
|
|
@@ -45,6 +47,39 @@ export function Example() {
|
|
|
45
47
|
}
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
## JAML preview
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
"use client";
|
|
54
|
+
|
|
55
|
+
import { JamlMapPreview } from "jaml-ui";
|
|
56
|
+
|
|
57
|
+
export function PreviewExample({ jaml }: { jaml: string }) {
|
|
58
|
+
return <JamlMapPreview jaml={jaml} title="JAML Intent Preview" />;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Lightweight JAML IDE shell
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
"use client";
|
|
66
|
+
|
|
67
|
+
import { useState } from "react";
|
|
68
|
+
import { JamlIde } from "jaml-ui";
|
|
69
|
+
|
|
70
|
+
export function IdeExample() {
|
|
71
|
+
const [jaml, setJaml] = useState("must:\n joker: Blueprint");
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<JamlIde
|
|
75
|
+
jaml={jaml}
|
|
76
|
+
onChange={setJaml}
|
|
77
|
+
results={[]}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
48
83
|
## Asset handling
|
|
49
84
|
|
|
50
85
|
By default, `jaml-ui` resolves its packaged sprite assets from the package `assets/` directory using `import.meta.url`.
|
|
@@ -108,3 +143,5 @@ export default nextConfig;
|
|
|
108
143
|
## Browser-first runtime direction
|
|
109
144
|
|
|
110
145
|
`jaml-ui` is designed for browser/React consumers. The optional `jaml-ui/motely` entry targets plain `motely-wasm` and does not assume threaded WASM, SAB, or COEP setup.
|
|
146
|
+
|
|
147
|
+
The built-in `JamlIde` intentionally stays lightweight. Rich editor integrations like Monaco, custom language servers, or extension-host-specific tooling should live in app-level packages on top of `jaml-ui`, not in the base renderer package.
|
|
@@ -13,6 +13,7 @@ export interface JamlGameCardProps {
|
|
|
13
13
|
};
|
|
14
14
|
type: "joker" | "consumable" | "playing";
|
|
15
15
|
className?: string;
|
|
16
|
+
hoverTilt?: boolean;
|
|
16
17
|
}
|
|
17
18
|
export type AnalyzerShopItem = {
|
|
18
19
|
id: string;
|
|
@@ -31,22 +32,25 @@ export type AnalyzerResolvedItem = {
|
|
|
31
32
|
label: string;
|
|
32
33
|
};
|
|
33
34
|
export declare function resolveAnalyzerShopItem(item: AnalyzerShopItem, scale?: number): AnalyzerResolvedItem;
|
|
34
|
-
export declare function JamlGameCard({ card, type, className }: JamlGameCardProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
export declare function JamlGameCard({ card, type, className, hoverTilt }: JamlGameCardProps): import("react/jsx-runtime").JSX.Element;
|
|
35
36
|
export interface VoucherProps {
|
|
36
37
|
voucherName: string;
|
|
37
38
|
scale?: number;
|
|
38
39
|
className?: string;
|
|
40
|
+
hoverTilt?: boolean;
|
|
39
41
|
}
|
|
40
|
-
export declare function JamlVoucher({ voucherName, scale, className }: VoucherProps): import("react/jsx-runtime").JSX.Element | null;
|
|
42
|
+
export declare function JamlVoucher({ voucherName, scale, className, hoverTilt }: VoucherProps): import("react/jsx-runtime").JSX.Element | null;
|
|
41
43
|
export interface TagProps {
|
|
42
44
|
tagName: string;
|
|
43
45
|
scale?: number;
|
|
44
46
|
className?: string;
|
|
47
|
+
hoverTilt?: boolean;
|
|
45
48
|
}
|
|
46
|
-
export declare function JamlTag({ tagName, scale, className }: TagProps): import("react/jsx-runtime").JSX.Element | null;
|
|
49
|
+
export declare function JamlTag({ tagName, scale, className, hoverTilt }: TagProps): import("react/jsx-runtime").JSX.Element | null;
|
|
47
50
|
export interface BossProps {
|
|
48
51
|
bossName: string;
|
|
49
52
|
scale?: number;
|
|
50
53
|
className?: string;
|
|
54
|
+
hoverTilt?: boolean;
|
|
51
55
|
}
|
|
52
|
-
export declare function JamlBoss({ bossName, scale, className }: BossProps): import("react/jsx-runtime").JSX.Element | null;
|
|
56
|
+
export declare function JamlBoss({ bossName, scale, className, hoverTilt }: BossProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -198,7 +198,7 @@ export function resolveAnalyzerShopItem(item, scale = 1) {
|
|
|
198
198
|
}
|
|
199
199
|
return packedResolved ?? { kind: "unknown", label: displayName };
|
|
200
200
|
}
|
|
201
|
-
export function JamlGameCard({ card, type, className = "" }) {
|
|
201
|
+
export function JamlGameCard({ card, type, className = "", hoverTilt = false }) {
|
|
202
202
|
const { name, edition, isEternal, isPerishable, isRental, rank, suit, enhancements, seal, scale = 1 } = card;
|
|
203
203
|
const layers = [];
|
|
204
204
|
if (type === "joker") {
|
|
@@ -299,9 +299,9 @@ export function JamlGameCard({ card, type, className = "" }) {
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
const wrapperStyle = { width: `${71 * scale}px` };
|
|
302
|
-
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { invert: edition === "Negative", layers: layers }) }));
|
|
302
|
+
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { invert: edition === "Negative", layers: layers, hoverTilt: hoverTilt }) }));
|
|
303
303
|
}
|
|
304
|
-
export function JamlVoucher({ voucherName, scale = 1, className = "" }) {
|
|
304
|
+
export function JamlVoucher({ voucherName, scale = 1, className = "", hoverTilt = false }) {
|
|
305
305
|
const voucherData = VOUCHERS.find((v) => v.name === voucherName);
|
|
306
306
|
if (!voucherData)
|
|
307
307
|
return null;
|
|
@@ -315,9 +315,9 @@ export function JamlVoucher({ voucherName, scale = 1, className = "" }) {
|
|
|
315
315
|
}),
|
|
316
316
|
];
|
|
317
317
|
const wrapperStyle = { width: `${71 * scale}px` };
|
|
318
|
-
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { layers: layers }) }));
|
|
318
|
+
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { layers: layers, hoverTilt: hoverTilt }) }));
|
|
319
319
|
}
|
|
320
|
-
export function JamlTag({ tagName, scale = 1, className = "" }) {
|
|
320
|
+
export function JamlTag({ tagName, scale = 1, className = "", hoverTilt = false }) {
|
|
321
321
|
const tagData = TAGS.find((t) => t.name === tagName);
|
|
322
322
|
if (!tagData)
|
|
323
323
|
return null;
|
|
@@ -331,9 +331,9 @@ export function JamlTag({ tagName, scale = 1, className = "" }) {
|
|
|
331
331
|
}),
|
|
332
332
|
];
|
|
333
333
|
const wrapperStyle = { width: `${71 * scale}px` };
|
|
334
|
-
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { layers: layers }) }));
|
|
334
|
+
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { layers: layers, hoverTilt: hoverTilt }) }));
|
|
335
335
|
}
|
|
336
|
-
export function JamlBoss({ bossName, scale = 1, className = "" }) {
|
|
336
|
+
export function JamlBoss({ bossName, scale = 1, className = "", hoverTilt = false }) {
|
|
337
337
|
const bossData = BOSSES.find((b) => b.name === bossName);
|
|
338
338
|
if (!bossData)
|
|
339
339
|
return null;
|
|
@@ -347,5 +347,5 @@ export function JamlBoss({ bossName, scale = 1, className = "" }) {
|
|
|
347
347
|
}),
|
|
348
348
|
];
|
|
349
349
|
const wrapperStyle = { width: `${71 * scale}px` };
|
|
350
|
-
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { layers: layers }) }));
|
|
350
|
+
return (_jsx("div", { style: wrapperStyle, className: className, children: _jsx(JamlCardRenderer, { layers: layers, hoverTilt: hoverTilt }) }));
|
|
351
351
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type JamlIdeMode } from "./JamlIdeToolbar.js";
|
|
3
|
+
export interface JamlIdeSearchResult {
|
|
4
|
+
seed: string;
|
|
5
|
+
score?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface JamlIdeProps {
|
|
8
|
+
jaml: string;
|
|
9
|
+
onChange: (jaml: string) => void;
|
|
10
|
+
defaultMode?: JamlIdeMode;
|
|
11
|
+
searchResults?: JamlIdeSearchResult[];
|
|
12
|
+
className?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
actions?: React.ReactNode;
|
|
15
|
+
codePlaceholder?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function JamlIde({ jaml, onChange, defaultMode, searchResults, className, title, actions, codePlaceholder, }: JamlIdeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import { JamlMapPreview } from "./JamlMapPreview.js";
|
|
5
|
+
import { JamlIdeToolbar } from "./JamlIdeToolbar.js";
|
|
6
|
+
function ResultsView({ results }) {
|
|
7
|
+
if (results.length === 0) {
|
|
8
|
+
return (_jsx("div", { style: {
|
|
9
|
+
border: "1px dashed rgba(255,255,255,0.18)",
|
|
10
|
+
borderRadius: 12,
|
|
11
|
+
padding: 14,
|
|
12
|
+
fontSize: 12,
|
|
13
|
+
opacity: 0.72,
|
|
14
|
+
background: "rgba(255,255,255,0.03)",
|
|
15
|
+
}, children: "No results yet." }));
|
|
16
|
+
}
|
|
17
|
+
return (_jsx("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: results.map((result, index) => (_jsxs("div", { style: {
|
|
18
|
+
display: "flex",
|
|
19
|
+
alignItems: "center",
|
|
20
|
+
justifyContent: "space-between",
|
|
21
|
+
gap: 12,
|
|
22
|
+
borderRadius: 12,
|
|
23
|
+
border: "1px solid rgba(255,255,255,0.08)",
|
|
24
|
+
background: "rgba(255,255,255,0.03)",
|
|
25
|
+
padding: "10px 12px",
|
|
26
|
+
}, children: [_jsx("div", { style: { fontWeight: 700, letterSpacing: 0.4 }, children: result.seed }), _jsx("div", { style: { fontSize: 12, opacity: 0.7 }, children: result.score !== undefined ? result.score : "-" })] }, `${result.seed}-${index}`))) }));
|
|
27
|
+
}
|
|
28
|
+
export function JamlIde({ jaml, onChange, defaultMode = "code", searchResults = [], className = "", title = "JAML IDE", actions, codePlaceholder = "Enter JAML...", }) {
|
|
29
|
+
const [mode, setMode] = useState(defaultMode);
|
|
30
|
+
const results = useMemo(() => searchResults, [searchResults]);
|
|
31
|
+
return (_jsxs("div", { className: className, style: {
|
|
32
|
+
display: "flex",
|
|
33
|
+
flexDirection: "column",
|
|
34
|
+
minHeight: 420,
|
|
35
|
+
borderRadius: 16,
|
|
36
|
+
overflow: "hidden",
|
|
37
|
+
border: "1px solid rgba(255,255,255,0.08)",
|
|
38
|
+
background: "#17181c",
|
|
39
|
+
color: "#f5f5f5",
|
|
40
|
+
}, children: [_jsxs("div", { style: {
|
|
41
|
+
display: "flex",
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
justifyContent: "space-between",
|
|
44
|
+
gap: 12,
|
|
45
|
+
padding: "12px 14px",
|
|
46
|
+
borderBottom: "1px solid rgba(255,255,255,0.08)",
|
|
47
|
+
background: "rgba(255,255,255,0.03)",
|
|
48
|
+
}, children: [_jsxs("div", { children: [_jsx("div", { style: { fontSize: 16, fontWeight: 800 }, children: title }), _jsx("div", { style: { fontSize: 11, opacity: 0.66 }, children: "Reusable JAML authoring and preview surface." })] }), actions ? _jsx("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: actions }) : null] }), _jsx(JamlIdeToolbar, { mode: mode, onModeChange: setMode, resultCount: results.length }), _jsxs("div", { style: { flex: 1, minHeight: 0, overflow: "auto" }, children: [mode === "code" ? (_jsx("textarea", { title: "JAML IDE Editor", value: jaml, onChange: (event) => onChange(event.target.value), placeholder: codePlaceholder, spellCheck: false, autoCapitalize: "off", autoCorrect: "off", style: {
|
|
49
|
+
width: "100%",
|
|
50
|
+
minHeight: 320,
|
|
51
|
+
resize: "vertical",
|
|
52
|
+
border: 0,
|
|
53
|
+
outline: 0,
|
|
54
|
+
padding: 16,
|
|
55
|
+
background: "transparent",
|
|
56
|
+
color: "inherit",
|
|
57
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
|
|
58
|
+
fontSize: 13,
|
|
59
|
+
lineHeight: 1.7,
|
|
60
|
+
} })) : null, mode === "map" ? _jsx(JamlMapPreview, { jaml: jaml }) : null, mode === "results" ? _jsx("div", { style: { padding: 16 }, children: _jsx(ResultsView, { results: results }) }) : null] })] }));
|
|
61
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type JamlIdeMode = "code" | "map" | "results";
|
|
2
|
+
export interface JamlIdeToolbarProps {
|
|
3
|
+
mode: JamlIdeMode;
|
|
4
|
+
onModeChange: (mode: JamlIdeMode) => void;
|
|
5
|
+
resultCount?: number;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function JamlIdeToolbar({ mode, onModeChange, resultCount, className }: JamlIdeToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
const TABS = [
|
|
4
|
+
{ id: "code", label: "Code" },
|
|
5
|
+
{ id: "map", label: "Map" },
|
|
6
|
+
{ id: "results", label: "Results" },
|
|
7
|
+
];
|
|
8
|
+
export function JamlIdeToolbar({ mode, onModeChange, resultCount = 0, className = "" }) {
|
|
9
|
+
return (_jsx("div", { className: className, style: {
|
|
10
|
+
display: "flex",
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
justifyContent: "space-between",
|
|
13
|
+
gap: 8,
|
|
14
|
+
padding: "8px 10px",
|
|
15
|
+
borderBottom: "1px solid rgba(255,255,255,0.08)",
|
|
16
|
+
background: "rgba(255,255,255,0.04)",
|
|
17
|
+
}, children: _jsx("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: TABS.map((tab) => {
|
|
18
|
+
const selected = mode === tab.id;
|
|
19
|
+
return (_jsxs("button", { type: "button", onClick: () => onModeChange(tab.id), style: {
|
|
20
|
+
cursor: "pointer",
|
|
21
|
+
borderRadius: 8,
|
|
22
|
+
border: selected ? "1px solid rgba(247,185,85,0.55)" : "1px solid transparent",
|
|
23
|
+
background: selected ? "rgba(247,185,85,0.16)" : "transparent",
|
|
24
|
+
color: selected ? "#f7b955" : "rgba(255,255,255,0.58)",
|
|
25
|
+
padding: "6px 10px",
|
|
26
|
+
fontSize: 11,
|
|
27
|
+
fontWeight: 600,
|
|
28
|
+
}, children: [tab.label, tab.id === "results" && resultCount > 0 ? (_jsx("span", { style: {
|
|
29
|
+
marginLeft: 6,
|
|
30
|
+
borderRadius: 999,
|
|
31
|
+
background: "rgba(0,0,0,0.25)",
|
|
32
|
+
padding: "1px 6px",
|
|
33
|
+
fontSize: 10,
|
|
34
|
+
}, children: resultCount })) : null] }, tab.id));
|
|
35
|
+
}) }) }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface JamlMapPreviewProps {
|
|
2
|
+
jaml: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
emptyMessage?: string;
|
|
6
|
+
cardScale?: number;
|
|
7
|
+
tagScale?: number;
|
|
8
|
+
bossScale?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function JamlMapPreview({ jaml, className, title, emptyMessage, cardScale, tagScale, bossScale, }: JamlMapPreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { JamlBoss, JamlGameCard, JamlTag, JamlVoucher } from "./GameCard.js";
|
|
5
|
+
import { extractVisualJamlItems } from "../utils/jamlMapPreview.js";
|
|
6
|
+
const SECTION_ORDER = ["must", "should", "mustNot"];
|
|
7
|
+
const SECTION_LABELS = {
|
|
8
|
+
must: "Must Requirements",
|
|
9
|
+
should: "Should Requirements",
|
|
10
|
+
mustNot: "Must Not Requirements",
|
|
11
|
+
};
|
|
12
|
+
const SECTION_ACCENTS = {
|
|
13
|
+
must: { color: "#ff6b6b", border: "rgba(255,107,107,0.35)", panel: "rgba(255,107,107,0.08)" },
|
|
14
|
+
should: { color: "#f7b955", border: "rgba(247,185,85,0.35)", panel: "rgba(247,185,85,0.08)" },
|
|
15
|
+
mustNot: { color: "#8d7dff", border: "rgba(141,125,255,0.35)", panel: "rgba(141,125,255,0.08)" },
|
|
16
|
+
};
|
|
17
|
+
function renderPreviewItem(item, cardScale, tagScale, bossScale) {
|
|
18
|
+
switch (item.visualType) {
|
|
19
|
+
case "joker":
|
|
20
|
+
return _jsx(JamlGameCard, { card: { name: item.value, scale: cardScale }, type: "joker" });
|
|
21
|
+
case "consumable":
|
|
22
|
+
return _jsx(JamlGameCard, { card: { name: item.value, scale: cardScale }, type: "consumable" });
|
|
23
|
+
case "voucher":
|
|
24
|
+
return _jsx(JamlVoucher, { voucherName: item.value, scale: cardScale });
|
|
25
|
+
case "tag":
|
|
26
|
+
return _jsx(JamlTag, { tagName: item.value, scale: tagScale });
|
|
27
|
+
case "boss":
|
|
28
|
+
return _jsx(JamlBoss, { bossName: item.value, scale: bossScale });
|
|
29
|
+
default:
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function JamlMapPreview({ jaml, className = "", title = "JAML Map Preview", emptyMessage = "No visual JAML clauses found yet.", cardScale = 0.8, tagScale = 1.1, bossScale = 1.1, }) {
|
|
34
|
+
const groups = useMemo(() => extractVisualJamlItems(jaml), [jaml]);
|
|
35
|
+
const totalItems = SECTION_ORDER.reduce((sum, section) => sum + groups[section].length, 0);
|
|
36
|
+
return (_jsxs("div", { className: className, style: {
|
|
37
|
+
display: "flex",
|
|
38
|
+
flexDirection: "column",
|
|
39
|
+
gap: 16,
|
|
40
|
+
padding: 16,
|
|
41
|
+
color: "#f5f5f5",
|
|
42
|
+
borderRadius: 20,
|
|
43
|
+
border: "1px solid rgba(152,152,192,0.18)",
|
|
44
|
+
background: "linear-gradient(180deg, rgba(28,26,52,0.96) 0%, rgba(18,16,36,0.96) 100%)",
|
|
45
|
+
boxShadow: "0 14px 32px rgba(0,0,0,0.16)",
|
|
46
|
+
}, children: [_jsxs("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 12, flexWrap: "wrap" }, children: [_jsxs("div", { children: [_jsx("div", { style: { fontSize: 14, fontWeight: 700, marginBottom: 4 }, children: title }), _jsx("div", { style: { fontSize: 12, opacity: 0.74, maxWidth: 520 }, children: "Preview the visual targets described directly in your JAML without running a full search." })] }), _jsxs("div", { style: {
|
|
47
|
+
display: "inline-flex",
|
|
48
|
+
alignItems: "center",
|
|
49
|
+
gap: 6,
|
|
50
|
+
borderRadius: 999,
|
|
51
|
+
border: "1px solid rgba(141,125,255,0.3)",
|
|
52
|
+
background: "rgba(141,125,255,0.12)",
|
|
53
|
+
padding: "6px 10px",
|
|
54
|
+
fontSize: 11,
|
|
55
|
+
fontWeight: 700,
|
|
56
|
+
color: "#c8bcff",
|
|
57
|
+
letterSpacing: "0.04em",
|
|
58
|
+
textTransform: "uppercase",
|
|
59
|
+
}, children: [_jsx("span", { children: totalItems }), _jsx("span", { children: totalItems === 1 ? "visual target" : "visual targets" })] })] }), totalItems === 0 ? (_jsx("div", { style: {
|
|
60
|
+
border: "1px dashed rgba(152,152,192,0.28)",
|
|
61
|
+
borderRadius: 16,
|
|
62
|
+
padding: 16,
|
|
63
|
+
fontSize: 12,
|
|
64
|
+
opacity: 0.72,
|
|
65
|
+
background: "rgba(255,255,255,0.035)",
|
|
66
|
+
}, children: emptyMessage })) : null, SECTION_ORDER.map((section) => {
|
|
67
|
+
const items = groups[section];
|
|
68
|
+
if (items.length === 0)
|
|
69
|
+
return null;
|
|
70
|
+
const accent = SECTION_ACCENTS[section];
|
|
71
|
+
return (_jsxs("section", { style: {
|
|
72
|
+
display: "flex",
|
|
73
|
+
flexDirection: "column",
|
|
74
|
+
gap: 10,
|
|
75
|
+
borderRadius: 18,
|
|
76
|
+
border: `1px solid ${accent.border}`,
|
|
77
|
+
background: `linear-gradient(180deg, ${accent.panel} 0%, rgba(255,255,255,0.02) 100%)`,
|
|
78
|
+
padding: 12,
|
|
79
|
+
}, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [_jsx("div", { style: {
|
|
80
|
+
width: 6,
|
|
81
|
+
height: 18,
|
|
82
|
+
borderRadius: 999,
|
|
83
|
+
background: accent.color,
|
|
84
|
+
} }), _jsx("div", { style: { fontSize: 12, fontWeight: 700, color: accent.color }, children: SECTION_LABELS[section] }), _jsx("div", { style: {
|
|
85
|
+
marginLeft: "auto",
|
|
86
|
+
borderRadius: 999,
|
|
87
|
+
padding: "3px 8px",
|
|
88
|
+
fontSize: 10,
|
|
89
|
+
fontWeight: 700,
|
|
90
|
+
color: accent.color,
|
|
91
|
+
background: "rgba(255,255,255,0.04)",
|
|
92
|
+
}, children: items.length })] }), _jsx("div", { style: {
|
|
93
|
+
display: "flex",
|
|
94
|
+
flexWrap: "wrap",
|
|
95
|
+
gap: 12,
|
|
96
|
+
}, children: items.map((item) => (_jsxs("div", { style: {
|
|
97
|
+
display: "flex",
|
|
98
|
+
flexDirection: "column",
|
|
99
|
+
alignItems: "center",
|
|
100
|
+
gap: 8,
|
|
101
|
+
minWidth: 96,
|
|
102
|
+
padding: 12,
|
|
103
|
+
borderRadius: 16,
|
|
104
|
+
border: `1px solid ${accent.border}`,
|
|
105
|
+
background: "rgba(10,10,20,0.24)",
|
|
106
|
+
boxShadow: "inset 0 1px 0 rgba(255,255,255,0.04)",
|
|
107
|
+
}, title: `${item.clauseKey}: ${item.value}`, children: [_jsx("div", { style: { minHeight: 72, display: "flex", alignItems: "center", justifyContent: "center" }, children: renderPreviewItem(item, cardScale, tagScale, bossScale) }), _jsx("div", { style: { fontSize: 11, textAlign: "center", lineHeight: 1.35, fontWeight: 600 }, children: item.value }), _jsx("div", { style: { fontSize: 10, opacity: 0.62, textTransform: "uppercase", letterSpacing: "0.06em" }, children: item.clauseKey })] }, item.id))) })] }, section));
|
|
108
|
+
}), _jsx("div", { style: {
|
|
109
|
+
borderRadius: 16,
|
|
110
|
+
border: "1px dashed rgba(141,125,255,0.28)",
|
|
111
|
+
background: "rgba(141,125,255,0.08)",
|
|
112
|
+
padding: 14,
|
|
113
|
+
fontSize: 11,
|
|
114
|
+
lineHeight: 1.5,
|
|
115
|
+
opacity: 0.84,
|
|
116
|
+
}, children: "This preview shows direct visual targets that can be read from the JAML text itself. Advanced scoring logic, positional constraints, nested groups, and runtime-only search behavior are not fully represented here yet." })] }));
|
|
117
|
+
}
|