@almadar/ui 5.21.12 → 5.22.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.
- package/dist/avl/index.cjs +919 -631
- package/dist/avl/index.js +919 -631
- package/dist/components/core/molecules/CalendarGrid.d.ts +3 -10
- package/dist/components/core/molecules/ContentRenderer.d.ts +2 -2
- package/dist/components/core/molecules/DataGrid.d.ts +11 -20
- package/dist/components/core/molecules/DataList.d.ts +9 -15
- package/dist/components/core/molecules/FormSection.d.ts +4 -4
- package/dist/components/core/molecules/PositionedCanvas.d.ts +4 -17
- package/dist/components/core/molecules/ReplyTree.d.ts +2 -13
- package/dist/components/core/molecules/RichBlockEditor.d.ts +3 -6
- package/dist/components/core/molecules/SortableList.d.ts +7 -5
- package/dist/components/core/molecules/TableView.d.ts +7 -7
- package/dist/components/core/molecules/index.d.ts +3 -3
- package/dist/components/core/molecules/useDataDnd.d.ts +5 -5
- package/dist/components/core/organisms/CardGrid.d.ts +5 -2
- package/dist/components/core/organisms/CaseStudyOrganism.d.ts +4 -3
- package/dist/components/core/organisms/DataTable.d.ts +4 -2
- package/dist/components/core/organisms/DetailPanel.d.ts +6 -6
- package/dist/components/core/organisms/FeatureGridOrganism.d.ts +4 -3
- package/dist/components/core/organisms/HeroOrganism.d.ts +4 -5
- package/dist/components/core/organisms/List.d.ts +5 -2
- package/dist/components/core/organisms/MasterDetail.d.ts +4 -2
- package/dist/components/core/organisms/MediaGallery.d.ts +4 -2
- package/dist/components/core/organisms/ShowcaseOrganism.d.ts +4 -3
- package/dist/components/core/organisms/StatCard.d.ts +5 -2
- package/dist/components/core/organisms/StepFlowOrganism.d.ts +4 -3
- package/dist/components/core/organisms/Timeline.d.ts +2 -2
- package/dist/components/core/organisms/book/index.d.ts +1 -1
- package/dist/components/core/organisms/book/types.d.ts +28 -48
- package/dist/components/core/organisms/index.d.ts +1 -2
- package/dist/components/core/organisms/layout/DashboardGrid.d.ts +2 -2
- package/dist/components/core/organisms/marketing-types.d.ts +5 -94
- package/dist/components/core/organisms/types.d.ts +9 -27
- package/dist/components/core/templates/index.d.ts +6 -6
- package/dist/components/game/organisms/BattleBoard.d.ts +14 -90
- package/dist/components/game/organisms/CastleBoard.d.ts +7 -21
- package/dist/components/game/organisms/UncontrolledBattleBoard.d.ts +2 -7
- package/dist/components/game/organisms/WorldMapBoard.d.ts +13 -59
- package/dist/components/game/organisms/boardEntity.d.ts +44 -0
- package/dist/components/game/organisms/hooks/useBattleState.d.ts +7 -7
- package/dist/components/game/organisms/index.d.ts +3 -3
- package/dist/components/game/organisms/puzzles/builder/BuilderBoard.d.ts +7 -20
- package/dist/components/game/organisms/puzzles/builder/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/classifier/ClassifierBoard.d.ts +7 -20
- package/dist/components/game/organisms/puzzles/classifier/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/debugger/DebuggerBoard.d.ts +6 -22
- package/dist/components/game/organisms/puzzles/debugger/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/event-handler/EventHandlerBoard.d.ts +6 -33
- package/dist/components/game/organisms/puzzles/event-handler/ObjectRulePanel.d.ts +3 -21
- package/dist/components/game/organisms/puzzles/event-handler/index.d.ts +2 -2
- package/dist/components/game/organisms/puzzles/event-handler/puzzleObject.d.ts +21 -0
- package/dist/components/game/organisms/puzzles/negotiator/NegotiatorBoard.d.ts +8 -24
- package/dist/components/game/organisms/puzzles/negotiator/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/sequencer/ActionTile.d.ts +2 -2
- package/dist/components/game/organisms/puzzles/sequencer/SequencerBoard.d.ts +7 -36
- package/dist/components/game/organisms/puzzles/sequencer/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/simulator/SimulatorBoard.d.ts +6 -25
- package/dist/components/game/organisms/puzzles/simulator/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/state-architect/StateArchitectBoard.d.ts +7 -40
- package/dist/components/game/organisms/puzzles/state-architect/VariablePanel.d.ts +3 -9
- package/dist/components/game/organisms/puzzles/state-architect/index.d.ts +2 -2
- package/dist/components/game/organisms/three/index.cjs +35 -21
- package/dist/components/game/organisms/three/index.js +35 -21
- package/dist/components/game/templates/BattleTemplate.d.ts +2 -3
- package/dist/components/game/templates/CastleTemplate.d.ts +2 -3
- package/dist/components/game/templates/GameCanvas3DBattleTemplate.d.ts +1 -16
- package/dist/components/game/templates/GameCanvas3DCastleTemplate.d.ts +1 -18
- package/dist/components/game/templates/GameCanvas3DWorldMapTemplate.d.ts +1 -14
- package/dist/components/game/templates/GameTemplate.d.ts +1 -6
- package/dist/components/game/templates/WorldMapTemplate.d.ts +2 -3
- package/dist/components/index.cjs +2016 -1668
- package/dist/components/index.js +1128 -780
- package/dist/components/marketing/organisms/PricingOrganism.d.ts +4 -3
- package/dist/components/marketing/organisms/StatsOrganism.d.ts +4 -3
- package/dist/components/marketing/organisms/TeamOrganism.d.ts +4 -3
- package/dist/components/marketing/organisms/book/BookChapterView.d.ts +5 -2
- package/dist/components/marketing/organisms/book/BookTableOfContents.d.ts +3 -2
- package/dist/components/marketing/organisms/book/BookViewer.d.ts +4 -4
- package/dist/components/marketing/templates/AboutPageTemplate.d.ts +32 -6
- package/dist/components/marketing/templates/FeatureDetailPageTemplate.d.ts +14 -4
- package/dist/components/marketing/templates/LandingPageTemplate.d.ts +47 -9
- package/dist/components/marketing/templates/PricingPageTemplate.d.ts +23 -5
- package/dist/providers/index.cjs +912 -624
- package/dist/providers/index.js +912 -624
- package/dist/runtime/index.cjs +914 -626
- package/dist/runtime/index.js +914 -626
- package/package.json +2 -2
package/dist/avl/index.cjs
CHANGED
|
@@ -7179,7 +7179,7 @@ var init_SvgGrid = __esm({
|
|
|
7179
7179
|
x,
|
|
7180
7180
|
y,
|
|
7181
7181
|
cols = 4,
|
|
7182
|
-
rows = 3,
|
|
7182
|
+
rows: rows2 = 3,
|
|
7183
7183
|
spacing = 20,
|
|
7184
7184
|
nodeRadius = 3,
|
|
7185
7185
|
color = "var(--color-primary)",
|
|
@@ -7188,7 +7188,7 @@ var init_SvgGrid = __esm({
|
|
|
7188
7188
|
highlights = []
|
|
7189
7189
|
}) => {
|
|
7190
7190
|
const highlightSet = new Set(highlights);
|
|
7191
|
-
return /* @__PURE__ */ jsxRuntime.jsx("g", { className, opacity, children: Array.from({ length:
|
|
7191
|
+
return /* @__PURE__ */ jsxRuntime.jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
|
|
7192
7192
|
(_, row) => Array.from({ length: cols }).map((_2, col) => {
|
|
7193
7193
|
const index = row * cols + col;
|
|
7194
7194
|
const isHighlighted = highlightSet.has(index);
|
|
@@ -7848,7 +7848,7 @@ var init_Input = __esm({
|
|
|
7848
7848
|
onClear,
|
|
7849
7849
|
value,
|
|
7850
7850
|
options,
|
|
7851
|
-
rows = 3,
|
|
7851
|
+
rows: rows2 = 3,
|
|
7852
7852
|
onChange,
|
|
7853
7853
|
...props
|
|
7854
7854
|
}, ref) => {
|
|
@@ -7898,7 +7898,7 @@ var init_Input = __esm({
|
|
|
7898
7898
|
ref,
|
|
7899
7899
|
value,
|
|
7900
7900
|
onChange,
|
|
7901
|
-
rows,
|
|
7901
|
+
rows: rows2,
|
|
7902
7902
|
className: baseClassName,
|
|
7903
7903
|
...props
|
|
7904
7904
|
}
|
|
@@ -9893,66 +9893,6 @@ var init_RangeSlider = __esm({
|
|
|
9893
9893
|
RangeSlider.displayName = "RangeSlider";
|
|
9894
9894
|
}
|
|
9895
9895
|
});
|
|
9896
|
-
function easeOut(t) {
|
|
9897
|
-
return t * (2 - t);
|
|
9898
|
-
}
|
|
9899
|
-
var AnimatedCounter;
|
|
9900
|
-
var init_AnimatedCounter = __esm({
|
|
9901
|
-
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
9902
|
-
"use client";
|
|
9903
|
-
init_cn();
|
|
9904
|
-
init_Typography();
|
|
9905
|
-
AnimatedCounter = ({
|
|
9906
|
-
value: rawValue,
|
|
9907
|
-
duration = 600,
|
|
9908
|
-
prefix,
|
|
9909
|
-
suffix,
|
|
9910
|
-
className
|
|
9911
|
-
}) => {
|
|
9912
|
-
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
9913
|
-
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
9914
|
-
const [displayValue, setDisplayValue] = React97.useState(value);
|
|
9915
|
-
const previousValueRef = React97.useRef(value);
|
|
9916
|
-
const animationFrameRef = React97.useRef(null);
|
|
9917
|
-
React97.useEffect(() => {
|
|
9918
|
-
const from = previousValueRef.current;
|
|
9919
|
-
const to = value;
|
|
9920
|
-
previousValueRef.current = value;
|
|
9921
|
-
if (from === to) {
|
|
9922
|
-
setDisplayValue(to);
|
|
9923
|
-
return;
|
|
9924
|
-
}
|
|
9925
|
-
const startTime = performance.now();
|
|
9926
|
-
const diff = to - from;
|
|
9927
|
-
function animate(currentTime) {
|
|
9928
|
-
const elapsed = currentTime - startTime;
|
|
9929
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
9930
|
-
const easedProgress = easeOut(progress);
|
|
9931
|
-
setDisplayValue(from + diff * easedProgress);
|
|
9932
|
-
if (progress < 1) {
|
|
9933
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9934
|
-
} else {
|
|
9935
|
-
setDisplayValue(to);
|
|
9936
|
-
}
|
|
9937
|
-
}
|
|
9938
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9939
|
-
return () => {
|
|
9940
|
-
if (animationFrameRef.current !== null) {
|
|
9941
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
9942
|
-
}
|
|
9943
|
-
};
|
|
9944
|
-
}, [value, duration]);
|
|
9945
|
-
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
9946
|
-
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
9947
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
9948
|
-
prefix,
|
|
9949
|
-
formattedValue,
|
|
9950
|
-
suffix
|
|
9951
|
-
] });
|
|
9952
|
-
};
|
|
9953
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
9954
|
-
}
|
|
9955
|
-
});
|
|
9956
9896
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
9957
9897
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
9958
9898
|
const observerRef = React97.useRef(null);
|
|
@@ -12436,15 +12376,15 @@ function HeaderSkeleton({ className }) {
|
|
|
12436
12376
|
] })
|
|
12437
12377
|
] });
|
|
12438
12378
|
}
|
|
12439
|
-
function TableSkeleton({ rows = 5, columns = 4, className }) {
|
|
12379
|
+
function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
|
|
12440
12380
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
|
|
12441
12381
|
/* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "px-4 py-3 bg-muted/30 border-b border-border", children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonBlock, { className: "h-4 flex-1 mx-2" }, i)) }),
|
|
12442
|
-
Array.from({ length:
|
|
12382
|
+
Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12443
12383
|
HStack,
|
|
12444
12384
|
{
|
|
12445
12385
|
className: cn(
|
|
12446
12386
|
"px-4 py-3",
|
|
12447
|
-
rowIdx <
|
|
12387
|
+
rowIdx < rows2 - 1 && "border-b border-border"
|
|
12448
12388
|
),
|
|
12449
12389
|
children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
|
|
12450
12390
|
},
|
|
@@ -12492,18 +12432,18 @@ function CardSkeleton({ className }) {
|
|
|
12492
12432
|
}
|
|
12493
12433
|
);
|
|
12494
12434
|
}
|
|
12495
|
-
function TextSkeleton({ rows = 3, className }) {
|
|
12496
|
-
return /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", className, children: Array.from({ length:
|
|
12435
|
+
function TextSkeleton({ rows: rows2 = 3, className }) {
|
|
12436
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12497
12437
|
SkeletonLine,
|
|
12498
12438
|
{
|
|
12499
|
-
className: i ===
|
|
12439
|
+
className: i === rows2 - 1 ? "w-2/3" : "w-full"
|
|
12500
12440
|
},
|
|
12501
12441
|
i
|
|
12502
12442
|
)) });
|
|
12503
12443
|
}
|
|
12504
12444
|
function Skeleton({
|
|
12505
12445
|
variant = "text",
|
|
12506
|
-
rows,
|
|
12446
|
+
rows: rows2,
|
|
12507
12447
|
columns,
|
|
12508
12448
|
fields,
|
|
12509
12449
|
className
|
|
@@ -12513,15 +12453,15 @@ function Skeleton({
|
|
|
12513
12453
|
case "header":
|
|
12514
12454
|
return /* @__PURE__ */ jsxRuntime.jsx(HeaderSkeleton, { className });
|
|
12515
12455
|
case "table":
|
|
12516
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TableSkeleton, { rows, columns, className });
|
|
12456
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TableSkeleton, { rows: rows2, columns, className });
|
|
12517
12457
|
case "form":
|
|
12518
12458
|
return /* @__PURE__ */ jsxRuntime.jsx(FormSkeleton, { fields, className });
|
|
12519
12459
|
case "card":
|
|
12520
12460
|
return /* @__PURE__ */ jsxRuntime.jsx(CardSkeleton, { className });
|
|
12521
12461
|
case "text":
|
|
12522
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows, className });
|
|
12462
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows: rows2, className });
|
|
12523
12463
|
default:
|
|
12524
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows, className });
|
|
12464
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows: rows2, className });
|
|
12525
12465
|
}
|
|
12526
12466
|
}
|
|
12527
12467
|
var pulseClass;
|
|
@@ -14149,7 +14089,7 @@ var init_MapView = __esm({
|
|
|
14149
14089
|
shadowSize: [41, 41]
|
|
14150
14090
|
});
|
|
14151
14091
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
14152
|
-
const { useEffect: useEffect79, useRef: useRef71, useCallback:
|
|
14092
|
+
const { useEffect: useEffect79, useRef: useRef71, useCallback: useCallback123, useState: useState113 } = React97__namespace.default;
|
|
14153
14093
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
14154
14094
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
14155
14095
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -14195,7 +14135,7 @@ var init_MapView = __esm({
|
|
|
14195
14135
|
}) {
|
|
14196
14136
|
const eventBus = useEventBus3();
|
|
14197
14137
|
const [clickedPosition, setClickedPosition] = useState113(null);
|
|
14198
|
-
const handleMapClick =
|
|
14138
|
+
const handleMapClick = useCallback123((lat, lng) => {
|
|
14199
14139
|
if (showClickedPin) {
|
|
14200
14140
|
setClickedPosition({ lat, lng });
|
|
14201
14141
|
}
|
|
@@ -14204,7 +14144,7 @@ var init_MapView = __esm({
|
|
|
14204
14144
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
14205
14145
|
}
|
|
14206
14146
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
14207
|
-
const handleMarkerClick =
|
|
14147
|
+
const handleMarkerClick = useCallback123((marker) => {
|
|
14208
14148
|
onMarkerClick?.(marker);
|
|
14209
14149
|
if (markerClickEvent) {
|
|
14210
14150
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -14425,7 +14365,7 @@ function InputPattern({
|
|
|
14425
14365
|
function TextareaPattern({
|
|
14426
14366
|
value = "",
|
|
14427
14367
|
placeholder,
|
|
14428
|
-
rows = 4,
|
|
14368
|
+
rows: rows2 = 4,
|
|
14429
14369
|
disabled = false,
|
|
14430
14370
|
fieldError,
|
|
14431
14371
|
onChange,
|
|
@@ -14445,7 +14385,7 @@ function TextareaPattern({
|
|
|
14445
14385
|
{
|
|
14446
14386
|
value: localValue,
|
|
14447
14387
|
placeholder,
|
|
14448
|
-
rows,
|
|
14388
|
+
rows: rows2,
|
|
14449
14389
|
disabled,
|
|
14450
14390
|
error: fieldError,
|
|
14451
14391
|
onChange: handleChange,
|
|
@@ -14930,6 +14870,91 @@ var init_ActionPalette = __esm({
|
|
|
14930
14870
|
ActionPalette.displayName = "ActionPalette";
|
|
14931
14871
|
}
|
|
14932
14872
|
});
|
|
14873
|
+
function parseValue(value) {
|
|
14874
|
+
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
14875
|
+
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
14876
|
+
if (!match) {
|
|
14877
|
+
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
14878
|
+
}
|
|
14879
|
+
const numStr = match[2];
|
|
14880
|
+
const decimalIdx = numStr.indexOf(".");
|
|
14881
|
+
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
14882
|
+
return {
|
|
14883
|
+
prefix: match[1],
|
|
14884
|
+
num: parseFloat(numStr),
|
|
14885
|
+
suffix: match[3],
|
|
14886
|
+
decimals
|
|
14887
|
+
};
|
|
14888
|
+
}
|
|
14889
|
+
var AnimatedCounter;
|
|
14890
|
+
var init_AnimatedCounter = __esm({
|
|
14891
|
+
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
14892
|
+
"use client";
|
|
14893
|
+
init_cn();
|
|
14894
|
+
init_Box();
|
|
14895
|
+
init_Typography();
|
|
14896
|
+
AnimatedCounter = ({
|
|
14897
|
+
value,
|
|
14898
|
+
label,
|
|
14899
|
+
duration = 1500,
|
|
14900
|
+
className
|
|
14901
|
+
}) => {
|
|
14902
|
+
const ref = React97.useRef(null);
|
|
14903
|
+
const [displayValue, setDisplayValue] = React97.useState("0");
|
|
14904
|
+
const [hasAnimated, setHasAnimated] = React97.useState(false);
|
|
14905
|
+
const animate = React97.useCallback(() => {
|
|
14906
|
+
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
14907
|
+
if (num2 === 0) {
|
|
14908
|
+
setDisplayValue(String(value));
|
|
14909
|
+
return;
|
|
14910
|
+
}
|
|
14911
|
+
const startTime = performance.now();
|
|
14912
|
+
const tick = (now2) => {
|
|
14913
|
+
const elapsed = now2 - startTime;
|
|
14914
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
14915
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
14916
|
+
const current = eased * num2;
|
|
14917
|
+
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
14918
|
+
if (progress < 1) {
|
|
14919
|
+
requestAnimationFrame(tick);
|
|
14920
|
+
} else {
|
|
14921
|
+
setDisplayValue(String(value));
|
|
14922
|
+
}
|
|
14923
|
+
};
|
|
14924
|
+
requestAnimationFrame(tick);
|
|
14925
|
+
}, [value, duration]);
|
|
14926
|
+
React97.useEffect(() => {
|
|
14927
|
+
if (hasAnimated) return;
|
|
14928
|
+
const el = ref.current;
|
|
14929
|
+
if (!el) return;
|
|
14930
|
+
const observer2 = new IntersectionObserver(
|
|
14931
|
+
(entries) => {
|
|
14932
|
+
if (entries[0].isIntersecting) {
|
|
14933
|
+
setHasAnimated(true);
|
|
14934
|
+
animate();
|
|
14935
|
+
observer2.disconnect();
|
|
14936
|
+
}
|
|
14937
|
+
},
|
|
14938
|
+
{ threshold: 0.3 }
|
|
14939
|
+
);
|
|
14940
|
+
observer2.observe(el);
|
|
14941
|
+
return () => observer2.disconnect();
|
|
14942
|
+
}, [hasAnimated, animate]);
|
|
14943
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
14944
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14945
|
+
Typography,
|
|
14946
|
+
{
|
|
14947
|
+
variant: "h2",
|
|
14948
|
+
className: "text-primary font-bold tabular-nums",
|
|
14949
|
+
children: hasAnimated ? displayValue : "0"
|
|
14950
|
+
}
|
|
14951
|
+
),
|
|
14952
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
14953
|
+
] });
|
|
14954
|
+
};
|
|
14955
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
14956
|
+
}
|
|
14957
|
+
});
|
|
14933
14958
|
var AuthLayout;
|
|
14934
14959
|
var init_AuthLayout = __esm({
|
|
14935
14960
|
"components/core/templates/AuthLayout.tsx"() {
|
|
@@ -16315,6 +16340,39 @@ var init_IsometricCanvas2 = __esm({
|
|
|
16315
16340
|
init_IsometricCanvas();
|
|
16316
16341
|
}
|
|
16317
16342
|
});
|
|
16343
|
+
|
|
16344
|
+
// components/game/organisms/boardEntity.ts
|
|
16345
|
+
function boardEntity(entity) {
|
|
16346
|
+
if (!entity) return void 0;
|
|
16347
|
+
return Array.isArray(entity) ? entity[0] : entity;
|
|
16348
|
+
}
|
|
16349
|
+
function str(v) {
|
|
16350
|
+
return v == null ? "" : String(v);
|
|
16351
|
+
}
|
|
16352
|
+
function num(v, fallback = 0) {
|
|
16353
|
+
const n = Number(v);
|
|
16354
|
+
return Number.isFinite(n) ? n : fallback;
|
|
16355
|
+
}
|
|
16356
|
+
function rows(v) {
|
|
16357
|
+
return Array.isArray(v) ? v : [];
|
|
16358
|
+
}
|
|
16359
|
+
function vec2(v) {
|
|
16360
|
+
const o = v ?? {};
|
|
16361
|
+
return { x: num(o.x), y: num(o.y) };
|
|
16362
|
+
}
|
|
16363
|
+
function unitPosition(u) {
|
|
16364
|
+
return vec2(u.position);
|
|
16365
|
+
}
|
|
16366
|
+
function unitTeam(u) {
|
|
16367
|
+
return str(u.team);
|
|
16368
|
+
}
|
|
16369
|
+
function unitHealth(u) {
|
|
16370
|
+
return num(u.health);
|
|
16371
|
+
}
|
|
16372
|
+
var init_boardEntity = __esm({
|
|
16373
|
+
"components/game/organisms/boardEntity.ts"() {
|
|
16374
|
+
}
|
|
16375
|
+
});
|
|
16318
16376
|
function BattleBoard({
|
|
16319
16377
|
entity,
|
|
16320
16378
|
scale = 0.45,
|
|
@@ -16341,43 +16399,49 @@ function BattleBoard({
|
|
|
16341
16399
|
attackEvent,
|
|
16342
16400
|
className
|
|
16343
16401
|
}) {
|
|
16344
|
-
const
|
|
16345
|
-
const
|
|
16346
|
-
const
|
|
16347
|
-
const
|
|
16348
|
-
const
|
|
16349
|
-
const
|
|
16350
|
-
const
|
|
16351
|
-
const
|
|
16352
|
-
const
|
|
16353
|
-
const
|
|
16354
|
-
const
|
|
16402
|
+
const board = boardEntity(entity) ?? {};
|
|
16403
|
+
const tiles = Array.isArray(board.tiles) ? board.tiles : [];
|
|
16404
|
+
const features = Array.isArray(board.features) ? board.features : [];
|
|
16405
|
+
const boardWidth = num(board.boardWidth, 8);
|
|
16406
|
+
const boardHeight = num(board.boardHeight, 6);
|
|
16407
|
+
const assetManifest = board.assetManifest;
|
|
16408
|
+
const backgroundImage = board.backgroundImage;
|
|
16409
|
+
const units = rows(board.units);
|
|
16410
|
+
const selectedUnitId = board.selectedUnitId ?? null;
|
|
16411
|
+
const currentPhase = str(board.phase) || "observation";
|
|
16412
|
+
const currentTurn = num(board.turn, 1);
|
|
16413
|
+
const gameResult = board.gameResult ?? null;
|
|
16355
16414
|
const eventBus = useEventBus();
|
|
16356
16415
|
const { t } = hooks.useTranslate();
|
|
16357
16416
|
const [hoveredTile, setHoveredTile] = React97.useState(null);
|
|
16358
16417
|
const [isShaking, setIsShaking] = React97.useState(false);
|
|
16359
16418
|
const selectedUnit = React97.useMemo(
|
|
16360
|
-
() => units.find((u) => u.id === selectedUnitId) ?? null,
|
|
16419
|
+
() => units.find((u) => str(u.id) === selectedUnitId) ?? null,
|
|
16361
16420
|
[units, selectedUnitId]
|
|
16362
16421
|
);
|
|
16363
16422
|
const hoveredUnit = React97.useMemo(() => {
|
|
16364
16423
|
if (!hoveredTile) return null;
|
|
16365
|
-
return units.find(
|
|
16366
|
-
|
|
16367
|
-
|
|
16424
|
+
return units.find((u) => {
|
|
16425
|
+
const p2 = unitPosition(u);
|
|
16426
|
+
return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
|
|
16427
|
+
}) ?? null;
|
|
16368
16428
|
}, [hoveredTile, units]);
|
|
16369
|
-
const playerUnits = React97.useMemo(() => units.filter((u) => u
|
|
16370
|
-
const enemyUnits = React97.useMemo(() => units.filter((u) => u
|
|
16429
|
+
const playerUnits = React97.useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
|
|
16430
|
+
const enemyUnits = React97.useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
|
|
16371
16431
|
const validMoves = React97.useMemo(() => {
|
|
16372
16432
|
if (!selectedUnit || currentPhase !== "movement") return [];
|
|
16373
16433
|
const moves = [];
|
|
16374
|
-
const range = selectedUnit.movement;
|
|
16434
|
+
const range = num(selectedUnit.movement);
|
|
16435
|
+
const origin = unitPosition(selectedUnit);
|
|
16375
16436
|
for (let dy = -range; dy <= range; dy++) {
|
|
16376
16437
|
for (let dx = -range; dx <= range; dx++) {
|
|
16377
|
-
const nx =
|
|
16378
|
-
const ny =
|
|
16438
|
+
const nx = origin.x + dx;
|
|
16439
|
+
const ny = origin.y + dy;
|
|
16379
16440
|
const dist = Math.abs(dx) + Math.abs(dy);
|
|
16380
|
-
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) =>
|
|
16441
|
+
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
|
|
16442
|
+
const p2 = unitPosition(u);
|
|
16443
|
+
return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
|
|
16444
|
+
})) {
|
|
16381
16445
|
moves.push({ x: nx, y: ny });
|
|
16382
16446
|
}
|
|
16383
16447
|
}
|
|
@@ -16386,11 +16450,14 @@ function BattleBoard({
|
|
|
16386
16450
|
}, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
|
|
16387
16451
|
const attackTargets = React97.useMemo(() => {
|
|
16388
16452
|
if (!selectedUnit || currentPhase !== "action") return [];
|
|
16389
|
-
|
|
16390
|
-
|
|
16391
|
-
|
|
16453
|
+
const sp = unitPosition(selectedUnit);
|
|
16454
|
+
const sTeam = unitTeam(selectedUnit);
|
|
16455
|
+
return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
|
|
16456
|
+
const p2 = unitPosition(u);
|
|
16457
|
+
const dx = Math.abs(p2.x - sp.x);
|
|
16458
|
+
const dy = Math.abs(p2.y - sp.y);
|
|
16392
16459
|
return dx <= 1 && dy <= 1 && dx + dy > 0;
|
|
16393
|
-
}).map((u) => u
|
|
16460
|
+
}).map((u) => unitPosition(u));
|
|
16394
16461
|
}, [selectedUnit, currentPhase, units]);
|
|
16395
16462
|
const MOVE_SPEED_MS_PER_TILE = 300;
|
|
16396
16463
|
const movementAnimRef = React97.useRef(null);
|
|
@@ -16430,23 +16497,25 @@ function BattleBoard({
|
|
|
16430
16497
|
return () => clearInterval(interval);
|
|
16431
16498
|
}, []);
|
|
16432
16499
|
const isoUnits = React97.useMemo(() => {
|
|
16433
|
-
return units.filter((u) => u
|
|
16434
|
-
const
|
|
16500
|
+
return units.filter((u) => unitHealth(u) > 0).map((unit) => {
|
|
16501
|
+
const id = str(unit.id);
|
|
16502
|
+
const pos = movingPositions.get(id) ?? unitPosition(unit);
|
|
16503
|
+
const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
|
|
16435
16504
|
return {
|
|
16436
|
-
id
|
|
16505
|
+
id,
|
|
16437
16506
|
position: pos,
|
|
16438
|
-
name: unit.name,
|
|
16439
|
-
team: unit
|
|
16440
|
-
health: unit
|
|
16441
|
-
maxHealth: unit.maxHealth,
|
|
16442
|
-
unitType: unit.unitType,
|
|
16443
|
-
heroId: unit.heroId,
|
|
16444
|
-
sprite: unit.sprite,
|
|
16445
|
-
traits:
|
|
16446
|
-
name:
|
|
16447
|
-
currentState:
|
|
16448
|
-
states:
|
|
16449
|
-
cooldown:
|
|
16507
|
+
name: str(unit.name),
|
|
16508
|
+
team: unitTeam(unit),
|
|
16509
|
+
health: unitHealth(unit),
|
|
16510
|
+
maxHealth: num(unit.maxHealth),
|
|
16511
|
+
unitType: unit.unitType == null ? void 0 : str(unit.unitType),
|
|
16512
|
+
heroId: unit.heroId == null ? void 0 : str(unit.heroId),
|
|
16513
|
+
sprite: unit.sprite == null ? void 0 : str(unit.sprite),
|
|
16514
|
+
traits: unitTraits?.map((tr) => ({
|
|
16515
|
+
name: tr.name,
|
|
16516
|
+
currentState: tr.currentState,
|
|
16517
|
+
states: tr.states,
|
|
16518
|
+
cooldown: tr.cooldown ?? 0
|
|
16450
16519
|
}))
|
|
16451
16520
|
};
|
|
16452
16521
|
});
|
|
@@ -16458,8 +16527,8 @@ function BattleBoard({
|
|
|
16458
16527
|
[scale, baseOffsetX]
|
|
16459
16528
|
);
|
|
16460
16529
|
const checkGameEnd = React97.useCallback(() => {
|
|
16461
|
-
const pa = units.filter((u) => u
|
|
16462
|
-
const ea = units.filter((u) => u
|
|
16530
|
+
const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
16531
|
+
const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
16463
16532
|
if (pa.length === 0) {
|
|
16464
16533
|
onGameEnd?.("defeat");
|
|
16465
16534
|
if (gameEndEvent) {
|
|
@@ -16473,21 +16542,22 @@ function BattleBoard({
|
|
|
16473
16542
|
}
|
|
16474
16543
|
}, [units, onGameEnd, gameEndEvent, eventBus]);
|
|
16475
16544
|
const handleUnitClick = React97.useCallback((unitId) => {
|
|
16476
|
-
const unit = units.find((u) => u.id === unitId);
|
|
16545
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
16477
16546
|
if (!unit) return;
|
|
16478
16547
|
if (unitClickEvent) {
|
|
16479
16548
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
16480
16549
|
}
|
|
16481
16550
|
if (currentPhase === "action" && selectedUnit) {
|
|
16482
|
-
|
|
16483
|
-
|
|
16551
|
+
const up = unitPosition(unit);
|
|
16552
|
+
if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
|
|
16553
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
16484
16554
|
setIsShaking(true);
|
|
16485
16555
|
setTimeout(() => setIsShaking(false), 300);
|
|
16486
16556
|
onAttack?.(selectedUnit, unit, damage);
|
|
16487
16557
|
if (attackEvent) {
|
|
16488
16558
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
16489
|
-
attackerId: selectedUnit.id,
|
|
16490
|
-
targetId: unit.id,
|
|
16559
|
+
attackerId: str(selectedUnit.id),
|
|
16560
|
+
targetId: str(unit.id),
|
|
16491
16561
|
damage
|
|
16492
16562
|
});
|
|
16493
16563
|
}
|
|
@@ -16502,9 +16572,9 @@ function BattleBoard({
|
|
|
16502
16572
|
if (currentPhase === "movement" && selectedUnit) {
|
|
16503
16573
|
if (movementAnimRef.current) return;
|
|
16504
16574
|
if (validMoves.some((m) => m.x === x && m.y === y)) {
|
|
16505
|
-
const from = { ...selectedUnit
|
|
16575
|
+
const from = { ...unitPosition(selectedUnit) };
|
|
16506
16576
|
const to = { x, y };
|
|
16507
|
-
startMoveAnimation(selectedUnit.id, from, to, () => {
|
|
16577
|
+
startMoveAnimation(str(selectedUnit.id), from, to, () => {
|
|
16508
16578
|
onUnitMove?.(selectedUnit, to);
|
|
16509
16579
|
});
|
|
16510
16580
|
}
|
|
@@ -16662,6 +16732,7 @@ var init_BattleBoard = __esm({
|
|
|
16662
16732
|
init_Typography();
|
|
16663
16733
|
init_Stack();
|
|
16664
16734
|
init_IsometricCanvas2();
|
|
16735
|
+
init_boardEntity();
|
|
16665
16736
|
init_isometric();
|
|
16666
16737
|
BattleBoard.displayName = "BattleBoard";
|
|
16667
16738
|
}
|
|
@@ -17055,24 +17126,24 @@ var init_CodeBlock = __esm({
|
|
|
17055
17126
|
return;
|
|
17056
17127
|
}
|
|
17057
17128
|
lineEls.forEach((el) => {
|
|
17058
|
-
const
|
|
17059
|
-
if (hiddenLines.has(
|
|
17129
|
+
const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
|
|
17130
|
+
if (hiddenLines.has(num2)) {
|
|
17060
17131
|
el.style.display = "none";
|
|
17061
17132
|
return;
|
|
17062
17133
|
}
|
|
17063
17134
|
el.style.display = "";
|
|
17064
17135
|
el.style.position = "relative";
|
|
17065
17136
|
el.style.paddingLeft = "1.2em";
|
|
17066
|
-
const region = foldStartMap.get(
|
|
17137
|
+
const region = foldStartMap.get(num2);
|
|
17067
17138
|
if (!region) return;
|
|
17068
|
-
const isCollapsed = collapsed.has(
|
|
17139
|
+
const isCollapsed = collapsed.has(num2);
|
|
17069
17140
|
const toggle = document.createElement("span");
|
|
17070
17141
|
toggle.className = "fold-toggle";
|
|
17071
17142
|
toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
|
|
17072
17143
|
toggle.style.cssText = "position:absolute;left:0;top:0;width:1.2em;text-align:center;cursor:pointer;color:#858585;font-size:10px;user-select:none;line-height:inherit;height:100%";
|
|
17073
17144
|
toggle.addEventListener("click", (e) => {
|
|
17074
17145
|
e.stopPropagation();
|
|
17075
|
-
toggleFoldRef.current(
|
|
17146
|
+
toggleFoldRef.current(num2);
|
|
17076
17147
|
});
|
|
17077
17148
|
el.insertBefore(toggle, el.firstChild);
|
|
17078
17149
|
if (isCollapsed) {
|
|
@@ -19325,10 +19396,13 @@ var init_BookChapterView = __esm({
|
|
|
19325
19396
|
init_cn();
|
|
19326
19397
|
BookChapterView = ({
|
|
19327
19398
|
chapter,
|
|
19399
|
+
orbitalSchema,
|
|
19328
19400
|
direction,
|
|
19329
19401
|
className
|
|
19330
19402
|
}) => {
|
|
19331
19403
|
const { t: _t } = hooks.useTranslate();
|
|
19404
|
+
const title = String(chapter.title ?? "");
|
|
19405
|
+
const content = String(chapter.content ?? "");
|
|
19332
19406
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19333
19407
|
VStack,
|
|
19334
19408
|
{
|
|
@@ -19336,16 +19410,16 @@ var init_BookChapterView = __esm({
|
|
|
19336
19410
|
className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
|
|
19337
19411
|
style: { direction },
|
|
19338
19412
|
children: [
|
|
19339
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children:
|
|
19413
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
|
|
19340
19414
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
19341
|
-
!!
|
|
19415
|
+
!!orbitalSchema && /* @__PURE__ */ jsxRuntime.jsx(ScaledDiagram, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19342
19416
|
JazariStateMachine,
|
|
19343
19417
|
{
|
|
19344
|
-
schema:
|
|
19418
|
+
schema: orbitalSchema,
|
|
19345
19419
|
direction
|
|
19346
19420
|
}
|
|
19347
19421
|
) }),
|
|
19348
|
-
/* @__PURE__ */ jsxRuntime.jsx(ContentRenderer, { content
|
|
19422
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContentRenderer, { content, direction })
|
|
19349
19423
|
]
|
|
19350
19424
|
}
|
|
19351
19425
|
);
|
|
@@ -19443,7 +19517,7 @@ var init_BookNavBar = __esm({
|
|
|
19443
19517
|
BookNavBar = ({
|
|
19444
19518
|
currentPage,
|
|
19445
19519
|
totalPages,
|
|
19446
|
-
chapterTitle,
|
|
19520
|
+
chapterTitle: chapterTitle2,
|
|
19447
19521
|
direction,
|
|
19448
19522
|
className
|
|
19449
19523
|
}) => {
|
|
@@ -19484,12 +19558,12 @@ var init_BookNavBar = __esm({
|
|
|
19484
19558
|
)
|
|
19485
19559
|
] }),
|
|
19486
19560
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
|
|
19487
|
-
|
|
19561
|
+
chapterTitle2 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19488
19562
|
Typography,
|
|
19489
19563
|
{
|
|
19490
19564
|
variant: "caption",
|
|
19491
19565
|
className: "text-center block truncate text-muted-foreground",
|
|
19492
|
-
children:
|
|
19566
|
+
children: chapterTitle2
|
|
19493
19567
|
}
|
|
19494
19568
|
),
|
|
19495
19569
|
/* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
|
|
@@ -19556,31 +19630,35 @@ var init_BookTableOfContents = __esm({
|
|
|
19556
19630
|
style: { direction },
|
|
19557
19631
|
children: [
|
|
19558
19632
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
|
|
19559
|
-
parts.map((part, partIdx) =>
|
|
19560
|
-
|
|
19561
|
-
|
|
19562
|
-
/* @__PURE__ */ jsxRuntime.
|
|
19563
|
-
|
|
19564
|
-
|
|
19565
|
-
|
|
19566
|
-
|
|
19567
|
-
|
|
19568
|
-
|
|
19569
|
-
|
|
19570
|
-
|
|
19571
|
-
|
|
19572
|
-
|
|
19573
|
-
|
|
19574
|
-
|
|
19575
|
-
|
|
19576
|
-
|
|
19577
|
-
|
|
19578
|
-
|
|
19579
|
-
|
|
19580
|
-
|
|
19581
|
-
|
|
19582
|
-
|
|
19583
|
-
|
|
19633
|
+
parts.map((part, partIdx) => {
|
|
19634
|
+
const chapters = Array.isArray(part.chapters) ? part.chapters : [];
|
|
19635
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
19636
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "center", children: [
|
|
19637
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
|
|
19638
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
|
|
19639
|
+
] }),
|
|
19640
|
+
/* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
|
|
19641
|
+
const id = chapter.id == null ? "" : String(chapter.id);
|
|
19642
|
+
const isCurrent = id === currentChapterId;
|
|
19643
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19644
|
+
Button,
|
|
19645
|
+
{
|
|
19646
|
+
variant: "ghost",
|
|
19647
|
+
size: "sm",
|
|
19648
|
+
action: "BOOK_NAVIGATE",
|
|
19649
|
+
actionPayload: { chapterId: id },
|
|
19650
|
+
className: cn(
|
|
19651
|
+
"justify-start text-left w-full",
|
|
19652
|
+
direction === "rtl" && "text-right",
|
|
19653
|
+
isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
|
|
19654
|
+
),
|
|
19655
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
|
|
19656
|
+
},
|
|
19657
|
+
id
|
|
19658
|
+
);
|
|
19659
|
+
}) })
|
|
19660
|
+
] }, partIdx);
|
|
19661
|
+
})
|
|
19584
19662
|
]
|
|
19585
19663
|
}
|
|
19586
19664
|
);
|
|
@@ -19702,27 +19780,41 @@ function resolveFieldMap(fieldMap) {
|
|
|
19702
19780
|
function get(obj, key) {
|
|
19703
19781
|
return obj[key];
|
|
19704
19782
|
}
|
|
19783
|
+
function asStr(v) {
|
|
19784
|
+
return v == null ? "" : String(v);
|
|
19785
|
+
}
|
|
19705
19786
|
function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
|
|
19706
19787
|
const rawParts = get(raw, fields.parts) ?? [];
|
|
19707
|
-
|
|
19708
|
-
|
|
19709
|
-
|
|
19710
|
-
|
|
19711
|
-
|
|
19712
|
-
|
|
19713
|
-
|
|
19714
|
-
const rawChapters = get(part, fields.chapters) ?? [];
|
|
19715
|
-
return {
|
|
19716
|
-
title: get(part, fields.partTitle) ?? "",
|
|
19717
|
-
chapters: rawChapters.map((ch) => ({
|
|
19718
|
-
id: get(ch, fields.chapterId) ?? "",
|
|
19719
|
-
title: get(ch, fields.chapterTitle) ?? "",
|
|
19720
|
-
content: get(ch, fields.chapterContent) ?? "",
|
|
19721
|
-
orbitalSchema: get(ch, fields.chapterOrbitalSchema)
|
|
19722
|
-
}))
|
|
19723
|
-
};
|
|
19724
|
-
})
|
|
19788
|
+
const direction = get(raw, fields.direction) ?? "ltr";
|
|
19789
|
+
const cover = {
|
|
19790
|
+
title: asStr(get(raw, fields.title)),
|
|
19791
|
+
subtitle: asStr(get(raw, fields.subtitle)),
|
|
19792
|
+
author: asStr(get(raw, fields.author)),
|
|
19793
|
+
coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
|
|
19794
|
+
direction
|
|
19725
19795
|
};
|
|
19796
|
+
const schemaByChapterId = {};
|
|
19797
|
+
const chapters = [];
|
|
19798
|
+
const parts = rawParts.map((part) => {
|
|
19799
|
+
const rawChapters = get(part, fields.chapters) ?? [];
|
|
19800
|
+
const chapterRows = rawChapters.map((ch) => {
|
|
19801
|
+
const id = asStr(get(ch, fields.chapterId));
|
|
19802
|
+
const schema = get(ch, fields.chapterOrbitalSchema);
|
|
19803
|
+
if (schema) schemaByChapterId[id] = schema;
|
|
19804
|
+
const row = {
|
|
19805
|
+
id,
|
|
19806
|
+
title: asStr(get(ch, fields.chapterTitle)),
|
|
19807
|
+
content: asStr(get(ch, fields.chapterContent))
|
|
19808
|
+
};
|
|
19809
|
+
chapters.push(row);
|
|
19810
|
+
return row;
|
|
19811
|
+
});
|
|
19812
|
+
return {
|
|
19813
|
+
title: asStr(get(part, fields.partTitle)),
|
|
19814
|
+
chapters: chapterRows
|
|
19815
|
+
};
|
|
19816
|
+
});
|
|
19817
|
+
return { cover, direction, parts, chapters, schemaByChapterId };
|
|
19726
19818
|
}
|
|
19727
19819
|
var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
|
|
19728
19820
|
var init_types2 = __esm({
|
|
@@ -19760,10 +19852,7 @@ var init_types2 = __esm({
|
|
|
19760
19852
|
};
|
|
19761
19853
|
}
|
|
19762
19854
|
});
|
|
19763
|
-
|
|
19764
|
-
return book.parts.flatMap((part) => part.chapters);
|
|
19765
|
-
}
|
|
19766
|
-
var PRINT_STYLES, BookViewer;
|
|
19855
|
+
var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
|
|
19767
19856
|
var init_BookViewer = __esm({
|
|
19768
19857
|
"components/marketing/organisms/book/BookViewer.tsx"() {
|
|
19769
19858
|
init_Box();
|
|
@@ -19776,6 +19865,8 @@ var init_BookViewer = __esm({
|
|
|
19776
19865
|
init_BookNavBar();
|
|
19777
19866
|
init_EmptyState();
|
|
19778
19867
|
init_types2();
|
|
19868
|
+
chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
|
|
19869
|
+
chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
|
|
19779
19870
|
PRINT_STYLES = `
|
|
19780
19871
|
@media print {
|
|
19781
19872
|
.book-viewer-page {
|
|
@@ -19804,14 +19895,14 @@ var init_BookViewer = __esm({
|
|
|
19804
19895
|
return mapBookData(raw, resolvedFieldMap);
|
|
19805
19896
|
}, [entity, resolvedFieldMap]);
|
|
19806
19897
|
const direction = book?.direction ?? "ltr";
|
|
19807
|
-
const chapters = React97.useMemo(() => book ?
|
|
19898
|
+
const chapters = React97.useMemo(() => book ? book.chapters : [], [book]);
|
|
19808
19899
|
const totalPages = 2 + chapters.length;
|
|
19809
19900
|
const navigateTo = React97.useCallback(
|
|
19810
19901
|
(page) => {
|
|
19811
19902
|
const clamped = Math.max(0, Math.min(page, totalPages - 1));
|
|
19812
19903
|
setCurrentPage(clamped);
|
|
19813
|
-
const
|
|
19814
|
-
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
|
|
19904
|
+
const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
|
|
19905
|
+
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
|
|
19815
19906
|
},
|
|
19816
19907
|
[totalPages, chapters, eventBus]
|
|
19817
19908
|
);
|
|
@@ -19823,8 +19914,8 @@ var init_BookViewer = __esm({
|
|
|
19823
19914
|
eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
|
|
19824
19915
|
eventBus.on("UI:BOOK_PRINT", () => window.print()),
|
|
19825
19916
|
eventBus.on("UI:BOOK_NAVIGATE", (event) => {
|
|
19826
|
-
const
|
|
19827
|
-
const idx = chapters.findIndex((ch) => ch
|
|
19917
|
+
const targetId = event.payload?.chapterId;
|
|
19918
|
+
const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
|
|
19828
19919
|
if (idx >= 0) navigateTo(idx + 2);
|
|
19829
19920
|
})
|
|
19830
19921
|
];
|
|
@@ -19841,9 +19932,11 @@ var init_BookViewer = __esm({
|
|
|
19841
19932
|
style.remove();
|
|
19842
19933
|
};
|
|
19843
19934
|
}, []);
|
|
19844
|
-
const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]
|
|
19845
|
-
const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]
|
|
19935
|
+
const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
|
|
19936
|
+
const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
|
|
19846
19937
|
if (!book) return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { message: t("book.noData") });
|
|
19938
|
+
const cover = book.cover;
|
|
19939
|
+
const coverTitle = String(cover.title ?? "");
|
|
19847
19940
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
|
|
19848
19941
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19849
19942
|
Box,
|
|
@@ -19855,10 +19948,10 @@ var init_BookViewer = __esm({
|
|
|
19855
19948
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19856
19949
|
BookCoverPage,
|
|
19857
19950
|
{
|
|
19858
|
-
title:
|
|
19859
|
-
subtitle:
|
|
19860
|
-
author:
|
|
19861
|
-
coverImageUrl:
|
|
19951
|
+
title: coverTitle,
|
|
19952
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
19953
|
+
author: String(cover.author ?? "") || void 0,
|
|
19954
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
19862
19955
|
direction
|
|
19863
19956
|
}
|
|
19864
19957
|
),
|
|
@@ -19869,23 +19962,27 @@ var init_BookViewer = __esm({
|
|
|
19869
19962
|
direction
|
|
19870
19963
|
}
|
|
19871
19964
|
),
|
|
19872
|
-
chapters.map((chapter) =>
|
|
19873
|
-
|
|
19874
|
-
|
|
19875
|
-
|
|
19876
|
-
|
|
19877
|
-
|
|
19878
|
-
|
|
19879
|
-
|
|
19965
|
+
chapters.map((chapter) => {
|
|
19966
|
+
const id = chapterId(chapter);
|
|
19967
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19968
|
+
BookChapterView,
|
|
19969
|
+
{
|
|
19970
|
+
chapter,
|
|
19971
|
+
orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
|
|
19972
|
+
direction
|
|
19973
|
+
},
|
|
19974
|
+
id
|
|
19975
|
+
);
|
|
19976
|
+
})
|
|
19880
19977
|
] }),
|
|
19881
19978
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "print:hidden", children: [
|
|
19882
19979
|
currentPage === 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19883
19980
|
BookCoverPage,
|
|
19884
19981
|
{
|
|
19885
|
-
title:
|
|
19886
|
-
subtitle:
|
|
19887
|
-
author:
|
|
19888
|
-
coverImageUrl:
|
|
19982
|
+
title: coverTitle,
|
|
19983
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
19984
|
+
author: String(cover.author ?? "") || void 0,
|
|
19985
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
19889
19986
|
direction
|
|
19890
19987
|
}
|
|
19891
19988
|
),
|
|
@@ -19901,6 +19998,7 @@ var init_BookViewer = __esm({
|
|
|
19901
19998
|
BookChapterView,
|
|
19902
19999
|
{
|
|
19903
20000
|
chapter: chapters[currentPage - 2],
|
|
20001
|
+
orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
|
|
19904
20002
|
direction
|
|
19905
20003
|
}
|
|
19906
20004
|
)
|
|
@@ -19913,7 +20011,7 @@ var init_BookViewer = __esm({
|
|
|
19913
20011
|
{
|
|
19914
20012
|
currentPage,
|
|
19915
20013
|
totalPages,
|
|
19916
|
-
chapterTitle: currentPage === 0 ?
|
|
20014
|
+
chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
|
|
19917
20015
|
direction
|
|
19918
20016
|
}
|
|
19919
20017
|
)
|
|
@@ -20011,7 +20109,7 @@ var init_Grid = __esm({
|
|
|
20011
20109
|
};
|
|
20012
20110
|
Grid = ({
|
|
20013
20111
|
cols = 1,
|
|
20014
|
-
rows,
|
|
20112
|
+
rows: rows2,
|
|
20015
20113
|
gap = "md",
|
|
20016
20114
|
rowGap,
|
|
20017
20115
|
colGap,
|
|
@@ -20023,7 +20121,7 @@ var init_Grid = __esm({
|
|
|
20023
20121
|
children,
|
|
20024
20122
|
as: Component = "div"
|
|
20025
20123
|
}) => {
|
|
20026
|
-
const mergedStyle =
|
|
20124
|
+
const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
|
|
20027
20125
|
return React97__namespace.default.createElement(
|
|
20028
20126
|
Component,
|
|
20029
20127
|
{
|
|
@@ -20739,14 +20837,14 @@ function BuilderBoard({
|
|
|
20739
20837
|
}) {
|
|
20740
20838
|
const { emit } = useEventBus();
|
|
20741
20839
|
const { t } = hooks.useTranslate();
|
|
20742
|
-
const resolved =
|
|
20840
|
+
const resolved = boardEntity(entity);
|
|
20743
20841
|
const [placements, setPlacements] = React97.useState({});
|
|
20744
20842
|
const [headerError, setHeaderError] = React97.useState(false);
|
|
20745
20843
|
const [submitted, setSubmitted] = React97.useState(false);
|
|
20746
20844
|
const [attempts, setAttempts] = React97.useState(0);
|
|
20747
20845
|
const [showHint, setShowHint] = React97.useState(false);
|
|
20748
|
-
const components = resolved?.components
|
|
20749
|
-
const slots = resolved?.slots
|
|
20846
|
+
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
20847
|
+
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
20750
20848
|
const usedComponentIds = new Set(Object.values(placements));
|
|
20751
20849
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
20752
20850
|
const [selectedComponent, setSelectedComponent] = React97.useState(null);
|
|
@@ -20780,7 +20878,7 @@ function BuilderBoard({
|
|
|
20780
20878
|
}, [slots, placements, attempts, completeEvent, emit]);
|
|
20781
20879
|
const handleReset = () => {
|
|
20782
20880
|
setSubmitted(false);
|
|
20783
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
20881
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
20784
20882
|
setShowHint(true);
|
|
20785
20883
|
}
|
|
20786
20884
|
};
|
|
@@ -20793,20 +20891,24 @@ function BuilderBoard({
|
|
|
20793
20891
|
};
|
|
20794
20892
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
20795
20893
|
if (!resolved) return null;
|
|
20894
|
+
const theme = resolved.theme ?? void 0;
|
|
20895
|
+
const themeBackground = theme?.background;
|
|
20896
|
+
const headerImage = str(resolved.headerImage);
|
|
20897
|
+
const hint = str(resolved.hint);
|
|
20796
20898
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20797
20899
|
Box,
|
|
20798
20900
|
{
|
|
20799
20901
|
className,
|
|
20800
20902
|
style: {
|
|
20801
|
-
backgroundImage:
|
|
20903
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
20802
20904
|
backgroundSize: "cover",
|
|
20803
20905
|
backgroundPosition: "center"
|
|
20804
20906
|
},
|
|
20805
20907
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
20806
|
-
|
|
20908
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
20807
20909
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
20808
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
20809
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description })
|
|
20910
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
20911
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
20810
20912
|
] }) }),
|
|
20811
20913
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
20812
20914
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
|
|
@@ -20866,9 +20968,9 @@ function BuilderBoard({
|
|
|
20866
20968
|
] }) }),
|
|
20867
20969
|
submitted && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
20868
20970
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: allCorrect ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
20869
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
20971
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
|
|
20870
20972
|
] }) }),
|
|
20871
|
-
showHint &&
|
|
20973
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
20872
20974
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
20873
20975
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
20874
20976
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Wrench, size: "sm" }),
|
|
@@ -20887,6 +20989,7 @@ var init_BuilderBoard = __esm({
|
|
|
20887
20989
|
"components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
|
|
20888
20990
|
init_atoms2();
|
|
20889
20991
|
init_useEventBus();
|
|
20992
|
+
init_boardEntity();
|
|
20890
20993
|
BuilderBoard.displayName = "BuilderBoard";
|
|
20891
20994
|
}
|
|
20892
20995
|
});
|
|
@@ -21224,21 +21327,24 @@ function CalendarGrid({
|
|
|
21224
21327
|
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
21225
21328
|
}, 500);
|
|
21226
21329
|
}, [longPressEvent, longPressPayload, eventBus]);
|
|
21227
|
-
const renderEvent = (event) =>
|
|
21228
|
-
|
|
21229
|
-
|
|
21230
|
-
|
|
21231
|
-
|
|
21232
|
-
|
|
21233
|
-
|
|
21234
|
-
|
|
21235
|
-
|
|
21236
|
-
|
|
21237
|
-
|
|
21238
|
-
|
|
21239
|
-
|
|
21240
|
-
|
|
21241
|
-
|
|
21330
|
+
const renderEvent = (event) => {
|
|
21331
|
+
const color = event.color;
|
|
21332
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21333
|
+
Box,
|
|
21334
|
+
{
|
|
21335
|
+
rounded: "md",
|
|
21336
|
+
padding: "xs",
|
|
21337
|
+
border: true,
|
|
21338
|
+
className: cn(
|
|
21339
|
+
"cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
|
|
21340
|
+
color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
|
|
21341
|
+
),
|
|
21342
|
+
onClick: (e) => handleEventClick(event, e),
|
|
21343
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
|
|
21344
|
+
},
|
|
21345
|
+
event.id
|
|
21346
|
+
);
|
|
21347
|
+
};
|
|
21242
21348
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21243
21349
|
Box,
|
|
21244
21350
|
{
|
|
@@ -22902,7 +23008,6 @@ var init_CardGrid = __esm({
|
|
|
22902
23008
|
alignItems = "stretch",
|
|
22903
23009
|
className,
|
|
22904
23010
|
children,
|
|
22905
|
-
// EntityDisplayProps
|
|
22906
23011
|
entity,
|
|
22907
23012
|
isLoading = false,
|
|
22908
23013
|
error = null,
|
|
@@ -23374,14 +23479,14 @@ var init_CaseStudyOrganism = __esm({
|
|
|
23374
23479
|
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23375
23480
|
CaseStudyCard,
|
|
23376
23481
|
{
|
|
23377
|
-
title: study.title,
|
|
23378
|
-
description: study.description,
|
|
23379
|
-
category: study.category,
|
|
23380
|
-
categoryColor: study.categoryColor,
|
|
23381
|
-
href: study.href,
|
|
23382
|
-
linkLabel: study.linkLabel
|
|
23482
|
+
title: String(study.title ?? ""),
|
|
23483
|
+
description: String(study.description ?? ""),
|
|
23484
|
+
category: String(study.category ?? ""),
|
|
23485
|
+
categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
|
|
23486
|
+
href: String(study.href ?? ""),
|
|
23487
|
+
linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
|
|
23383
23488
|
},
|
|
23384
|
-
study.id
|
|
23489
|
+
String(study.id ?? "")
|
|
23385
23490
|
)) })
|
|
23386
23491
|
] });
|
|
23387
23492
|
};
|
|
@@ -23404,10 +23509,10 @@ function CastleBoard({
|
|
|
23404
23509
|
className
|
|
23405
23510
|
}) {
|
|
23406
23511
|
const eventBus = useEventBus();
|
|
23407
|
-
const resolved =
|
|
23408
|
-
const tiles = resolved?.tiles
|
|
23409
|
-
const features = resolved?.features
|
|
23410
|
-
const units = resolved?.units
|
|
23512
|
+
const resolved = boardEntity(entity);
|
|
23513
|
+
const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
|
|
23514
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
23515
|
+
const units = Array.isArray(resolved?.units) ? resolved.units : [];
|
|
23411
23516
|
const assetManifest = resolved?.assetManifest;
|
|
23412
23517
|
const backgroundImage = resolved?.backgroundImage;
|
|
23413
23518
|
const [hoveredTile, setHoveredTile] = React97.useState(null);
|
|
@@ -23435,7 +23540,7 @@ function CastleBoard({
|
|
|
23435
23540
|
onFeatureClick?.(feature);
|
|
23436
23541
|
if (featureClickEvent) {
|
|
23437
23542
|
eventBus.emit(`UI:${featureClickEvent}`, {
|
|
23438
|
-
featureId: feature.id,
|
|
23543
|
+
featureId: feature.id ?? "",
|
|
23439
23544
|
featureType: feature.type,
|
|
23440
23545
|
x: feature.x,
|
|
23441
23546
|
y: feature.y
|
|
@@ -23503,6 +23608,7 @@ var init_CastleBoard = __esm({
|
|
|
23503
23608
|
init_cn();
|
|
23504
23609
|
init_useEventBus();
|
|
23505
23610
|
init_IsometricCanvas2();
|
|
23611
|
+
init_boardEntity();
|
|
23506
23612
|
init_isometric();
|
|
23507
23613
|
CastleBoard.displayName = "CastleBoard";
|
|
23508
23614
|
}
|
|
@@ -24313,14 +24419,14 @@ function ClassifierBoard({
|
|
|
24313
24419
|
}) {
|
|
24314
24420
|
const { emit } = useEventBus();
|
|
24315
24421
|
const { t } = hooks.useTranslate();
|
|
24316
|
-
const resolved =
|
|
24422
|
+
const resolved = boardEntity(entity);
|
|
24317
24423
|
const [assignments, setAssignments] = React97.useState({});
|
|
24318
24424
|
const [headerError, setHeaderError] = React97.useState(false);
|
|
24319
24425
|
const [submitted, setSubmitted] = React97.useState(false);
|
|
24320
24426
|
const [attempts, setAttempts] = React97.useState(0);
|
|
24321
24427
|
const [showHint, setShowHint] = React97.useState(false);
|
|
24322
|
-
const items = resolved?.items
|
|
24323
|
-
const categories = resolved?.categories
|
|
24428
|
+
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
24429
|
+
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
24324
24430
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
24325
24431
|
const allAssigned = Object.keys(assignments).length === items.length;
|
|
24326
24432
|
const results = submitted ? items.map((item) => ({
|
|
@@ -24352,7 +24458,7 @@ function ClassifierBoard({
|
|
|
24352
24458
|
}, [items, assignments, attempts, completeEvent, emit]);
|
|
24353
24459
|
const handleReset = () => {
|
|
24354
24460
|
setSubmitted(false);
|
|
24355
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
24461
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
24356
24462
|
setShowHint(true);
|
|
24357
24463
|
}
|
|
24358
24464
|
};
|
|
@@ -24363,20 +24469,25 @@ function ClassifierBoard({
|
|
|
24363
24469
|
setShowHint(false);
|
|
24364
24470
|
};
|
|
24365
24471
|
if (!resolved) return null;
|
|
24472
|
+
const theme = resolved.theme ?? void 0;
|
|
24473
|
+
const themeBackground = theme?.background;
|
|
24474
|
+
const headerImage = str(resolved.headerImage);
|
|
24475
|
+
const hint = str(resolved.hint);
|
|
24476
|
+
const failMessage = str(resolved.failMessage);
|
|
24366
24477
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
24367
24478
|
Box,
|
|
24368
24479
|
{
|
|
24369
24480
|
className,
|
|
24370
24481
|
style: {
|
|
24371
|
-
backgroundImage:
|
|
24482
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
24372
24483
|
backgroundSize: "cover",
|
|
24373
24484
|
backgroundPosition: "center"
|
|
24374
24485
|
},
|
|
24375
24486
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
24376
|
-
|
|
24487
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
24377
24488
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
24378
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
24379
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description })
|
|
24489
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
24490
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
24380
24491
|
] }) }),
|
|
24381
24492
|
unassignedItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
24382
24493
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
|
|
@@ -24428,10 +24539,10 @@ function ClassifierBoard({
|
|
|
24428
24539
|
}) }),
|
|
24429
24540
|
submitted && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
24430
24541
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: allCorrect ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
24431
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
24432
|
-
!allCorrect &&
|
|
24542
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
|
|
24543
|
+
!allCorrect && failMessage && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
|
|
24433
24544
|
] }) }),
|
|
24434
|
-
showHint &&
|
|
24545
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
24435
24546
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
24436
24547
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
24437
24548
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Send, size: "sm" }),
|
|
@@ -24450,6 +24561,7 @@ var init_ClassifierBoard = __esm({
|
|
|
24450
24561
|
"components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
|
|
24451
24562
|
init_atoms2();
|
|
24452
24563
|
init_useEventBus();
|
|
24564
|
+
init_boardEntity();
|
|
24453
24565
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
24454
24566
|
}
|
|
24455
24567
|
});
|
|
@@ -30820,7 +30932,7 @@ function InventoryPanel({
|
|
|
30820
30932
|
const slotArray = Array.from({ length: safeSlots }, (_, index) => {
|
|
30821
30933
|
return safeItems[index] ?? null;
|
|
30822
30934
|
});
|
|
30823
|
-
const
|
|
30935
|
+
const rows2 = Math.ceil(safeSlots / safeColumns);
|
|
30824
30936
|
const handleSlotClick = React97.useCallback((index) => {
|
|
30825
30937
|
if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
|
|
30826
30938
|
onSelectSlot?.(index);
|
|
@@ -30889,7 +31001,7 @@ function InventoryPanel({
|
|
|
30889
31001
|
className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
|
|
30890
31002
|
style: {
|
|
30891
31003
|
gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
|
|
30892
|
-
gridTemplateRows: `repeat(${
|
|
31004
|
+
gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
|
|
30893
31005
|
},
|
|
30894
31006
|
children: slotArray.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
30895
31007
|
"button",
|
|
@@ -34853,11 +34965,11 @@ function LatticeSVG({
|
|
|
34853
34965
|
}) {
|
|
34854
34966
|
const paths = [];
|
|
34855
34967
|
const cols = 5;
|
|
34856
|
-
const
|
|
34968
|
+
const rows2 = Math.ceil(h / (w / cols));
|
|
34857
34969
|
const cellW = w / cols;
|
|
34858
34970
|
const cellH = cellW;
|
|
34859
34971
|
const bulge = cellW * 0.3;
|
|
34860
|
-
for (let row = 0; row <
|
|
34972
|
+
for (let row = 0; row < rows2; row++) {
|
|
34861
34973
|
for (let col = 0; col < cols; col++) {
|
|
34862
34974
|
const cx = col * cellW + cellW / 2;
|
|
34863
34975
|
const cy = row * cellH + cellH / 2;
|
|
@@ -35269,7 +35381,7 @@ var init_MatrixQuestion = __esm({
|
|
|
35269
35381
|
};
|
|
35270
35382
|
MatrixQuestion = ({
|
|
35271
35383
|
title,
|
|
35272
|
-
rows,
|
|
35384
|
+
rows: rows2,
|
|
35273
35385
|
columns = DEFAULT_MATRIX_COLUMNS,
|
|
35274
35386
|
values,
|
|
35275
35387
|
onChange,
|
|
@@ -35279,7 +35391,7 @@ var init_MatrixQuestion = __esm({
|
|
|
35279
35391
|
className
|
|
35280
35392
|
}) => {
|
|
35281
35393
|
const styles = sizeStyles13[size];
|
|
35282
|
-
const safeRows =
|
|
35394
|
+
const safeRows = rows2 ?? [];
|
|
35283
35395
|
const safeValues = values ?? {};
|
|
35284
35396
|
const eventBus = useEventBus();
|
|
35285
35397
|
const handleChange = React97.useCallback(
|
|
@@ -35907,7 +36019,8 @@ var init_PositionedCanvas = __esm({
|
|
|
35907
36019
|
dragRef.current = null;
|
|
35908
36020
|
setDraggingId(null);
|
|
35909
36021
|
if (!wasDrag) {
|
|
35910
|
-
const
|
|
36022
|
+
const itemId = item.id;
|
|
36023
|
+
const next = selectedId === itemId ? null : itemId;
|
|
35911
36024
|
onSelect?.(next);
|
|
35912
36025
|
if (selectEvent) {
|
|
35913
36026
|
eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
@@ -35942,15 +36055,22 @@ var init_PositionedCanvas = __esm({
|
|
|
35942
36055
|
style: { width, height },
|
|
35943
36056
|
onClick: handleContainerClick,
|
|
35944
36057
|
children: items.map((item) => {
|
|
36058
|
+
const itemId = item.id;
|
|
36059
|
+
const label = item.label;
|
|
36060
|
+
const x = item.x;
|
|
36061
|
+
const y = item.y;
|
|
36062
|
+
const capacity = item.capacity;
|
|
36063
|
+
const partySize = item.partySize;
|
|
36064
|
+
const serverName = item.serverName;
|
|
35945
36065
|
const status = item.status ?? "empty";
|
|
35946
36066
|
const shape = item.shape ?? "round";
|
|
35947
|
-
const isSelected = selectedId ===
|
|
35948
|
-
const isDragging = draggingId ===
|
|
36067
|
+
const isSelected = selectedId === itemId;
|
|
36068
|
+
const isDragging = draggingId === itemId;
|
|
35949
36069
|
const statusBadge = STATUS_BADGE[status];
|
|
35950
36070
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
35951
36071
|
Box,
|
|
35952
36072
|
{
|
|
35953
|
-
"data-testid": `item-node-${
|
|
36073
|
+
"data-testid": `item-node-${itemId}`,
|
|
35954
36074
|
"data-status": status,
|
|
35955
36075
|
className: cn(
|
|
35956
36076
|
"absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
|
|
@@ -35961,7 +36081,7 @@ var init_PositionedCanvas = __esm({
|
|
|
35961
36081
|
isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
|
|
35962
36082
|
isDragging && "shadow-lg z-10"
|
|
35963
36083
|
),
|
|
35964
|
-
style: { left:
|
|
36084
|
+
style: { left: x, top: y, touchAction: "none" },
|
|
35965
36085
|
onPointerDown: (e) => handlePointerDown(e, item),
|
|
35966
36086
|
onPointerMove: handlePointerMove,
|
|
35967
36087
|
onPointerUp: (e) => handlePointerUp(e, item),
|
|
@@ -35969,10 +36089,10 @@ var init_PositionedCanvas = __esm({
|
|
|
35969
36089
|
children: [
|
|
35970
36090
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-1", children: [
|
|
35971
36091
|
getStatusIcon(status),
|
|
35972
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", weight: "semibold", children:
|
|
36092
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", weight: "semibold", children: label })
|
|
35973
36093
|
] }),
|
|
35974
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
35975
|
-
status === "seated" &&
|
|
36094
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
|
|
36095
|
+
status === "seated" && serverName && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
|
|
35976
36096
|
isSelected && /* @__PURE__ */ jsxRuntime.jsx(
|
|
35977
36097
|
Badge,
|
|
35978
36098
|
{
|
|
@@ -35984,7 +36104,7 @@ var init_PositionedCanvas = __esm({
|
|
|
35984
36104
|
)
|
|
35985
36105
|
]
|
|
35986
36106
|
},
|
|
35987
|
-
|
|
36107
|
+
itemId
|
|
35988
36108
|
);
|
|
35989
36109
|
})
|
|
35990
36110
|
}
|
|
@@ -36756,9 +36876,10 @@ var init_RichBlockEditor = __esm({
|
|
|
36756
36876
|
});
|
|
36757
36877
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
36758
36878
|
for (const n of nodes) {
|
|
36879
|
+
const replies = n.replies;
|
|
36759
36880
|
if (n.collapsed) acc.add(n.id);
|
|
36760
|
-
if (
|
|
36761
|
-
collectInitiallyCollapsed(
|
|
36881
|
+
if (replies && replies.length > 0) {
|
|
36882
|
+
collectInitiallyCollapsed(replies, acc);
|
|
36762
36883
|
}
|
|
36763
36884
|
}
|
|
36764
36885
|
}
|
|
@@ -36788,44 +36909,52 @@ var init_ReplyTree = __esm({
|
|
|
36788
36909
|
}) => {
|
|
36789
36910
|
const eventBus = useEventBus();
|
|
36790
36911
|
const { t } = hooks.useTranslate();
|
|
36791
|
-
const
|
|
36792
|
-
const
|
|
36912
|
+
const nodeId = node.id;
|
|
36913
|
+
const authorName = node.authorName;
|
|
36914
|
+
const authorAvatarUrl = node.authorAvatarUrl;
|
|
36915
|
+
const content = node.content;
|
|
36916
|
+
const postedAt = node.postedAt;
|
|
36917
|
+
const voteCount = node.voteCount;
|
|
36918
|
+
const userVote = node.userVote;
|
|
36919
|
+
const replies = node.replies;
|
|
36920
|
+
const hasReplies = !!replies && replies.length > 0;
|
|
36921
|
+
const isCollapsed = collapsedSet.has(nodeId);
|
|
36793
36922
|
const atMaxDepth = depth >= maxDepth;
|
|
36794
36923
|
const [replyOpen, setReplyOpen] = React97.useState(false);
|
|
36795
36924
|
const [draft, setDraft] = React97.useState("");
|
|
36796
36925
|
const handleVote = React97.useCallback(
|
|
36797
36926
|
(next) => {
|
|
36798
|
-
onVote?.(
|
|
36799
|
-
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId
|
|
36927
|
+
onVote?.(nodeId, next);
|
|
36928
|
+
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
|
|
36800
36929
|
},
|
|
36801
|
-
[
|
|
36930
|
+
[nodeId, onVote, voteEvent, eventBus]
|
|
36802
36931
|
);
|
|
36803
36932
|
const handleReply = React97.useCallback(() => {
|
|
36804
|
-
onReply?.(
|
|
36933
|
+
onReply?.(nodeId);
|
|
36805
36934
|
setReplyOpen((open) => !open);
|
|
36806
|
-
}, [
|
|
36935
|
+
}, [nodeId, onReply]);
|
|
36807
36936
|
const handleSubmitReply = React97.useCallback(() => {
|
|
36808
|
-
const
|
|
36809
|
-
if (!
|
|
36810
|
-
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId:
|
|
36937
|
+
const text = draft.trim();
|
|
36938
|
+
if (!text) return;
|
|
36939
|
+
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
|
|
36811
36940
|
setDraft("");
|
|
36812
36941
|
setReplyOpen(false);
|
|
36813
|
-
}, [
|
|
36942
|
+
}, [nodeId, draft, replyEvent, eventBus]);
|
|
36814
36943
|
const handleCancelReply = React97.useCallback(() => {
|
|
36815
36944
|
setDraft("");
|
|
36816
36945
|
setReplyOpen(false);
|
|
36817
36946
|
}, []);
|
|
36818
36947
|
const handleFlag = React97.useCallback(() => {
|
|
36819
|
-
onFlag?.(
|
|
36820
|
-
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId
|
|
36821
|
-
}, [
|
|
36948
|
+
onFlag?.(nodeId);
|
|
36949
|
+
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
|
|
36950
|
+
}, [nodeId, onFlag, flagEvent, eventBus]);
|
|
36822
36951
|
const handleContinue = React97.useCallback(() => {
|
|
36823
|
-
onContinueThread?.(
|
|
36824
|
-
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId
|
|
36825
|
-
}, [
|
|
36952
|
+
onContinueThread?.(nodeId);
|
|
36953
|
+
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
|
|
36954
|
+
}, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
|
|
36826
36955
|
const handleToggle = React97.useCallback(() => {
|
|
36827
|
-
toggleCollapse(
|
|
36828
|
-
}, [
|
|
36956
|
+
toggleCollapse(nodeId);
|
|
36957
|
+
}, [nodeId, toggleCollapse]);
|
|
36829
36958
|
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
|
|
36830
36959
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
|
|
36831
36960
|
hasReplies ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -36857,25 +36986,25 @@ var init_ReplyTree = __esm({
|
|
|
36857
36986
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
36858
36987
|
Avatar,
|
|
36859
36988
|
{
|
|
36860
|
-
src:
|
|
36861
|
-
name:
|
|
36989
|
+
src: authorAvatarUrl,
|
|
36990
|
+
name: authorName,
|
|
36862
36991
|
size: "sm"
|
|
36863
36992
|
}
|
|
36864
36993
|
),
|
|
36865
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "semibold", children:
|
|
36866
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
36994
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
|
|
36995
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
|
|
36867
36996
|
] }),
|
|
36868
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children:
|
|
36997
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
|
|
36869
36998
|
showActions && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
36870
36999
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
36871
37000
|
VoteStack,
|
|
36872
37001
|
{
|
|
36873
|
-
count:
|
|
36874
|
-
userVote:
|
|
37002
|
+
count: voteCount ?? 0,
|
|
37003
|
+
userVote: userVote ?? null,
|
|
36875
37004
|
onVote: handleVote,
|
|
36876
37005
|
size: "sm",
|
|
36877
37006
|
variant: "horizontal",
|
|
36878
|
-
label: t("replyTree.voteOnReplyBy", { author:
|
|
37007
|
+
label: t("replyTree.voteOnReplyBy", { author: authorName })
|
|
36879
37008
|
}
|
|
36880
37009
|
),
|
|
36881
37010
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -36885,7 +37014,7 @@ var init_ReplyTree = __esm({
|
|
|
36885
37014
|
size: "sm",
|
|
36886
37015
|
leftIcon: "message-square",
|
|
36887
37016
|
onClick: handleReply,
|
|
36888
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
37017
|
+
"aria-label": t("replyTree.replyTo", { author: authorName }),
|
|
36889
37018
|
children: t("replyTree.reply")
|
|
36890
37019
|
}
|
|
36891
37020
|
),
|
|
@@ -36896,7 +37025,7 @@ var init_ReplyTree = __esm({
|
|
|
36896
37025
|
size: "sm",
|
|
36897
37026
|
leftIcon: "flag",
|
|
36898
37027
|
onClick: handleFlag,
|
|
36899
|
-
"aria-label": t("replyTree.flagReplyBy", { author:
|
|
37028
|
+
"aria-label": t("replyTree.flagReplyBy", { author: authorName }),
|
|
36900
37029
|
children: t("replyTree.flag")
|
|
36901
37030
|
}
|
|
36902
37031
|
)
|
|
@@ -36908,9 +37037,9 @@ var init_ReplyTree = __esm({
|
|
|
36908
37037
|
inputType: "textarea",
|
|
36909
37038
|
rows: 2,
|
|
36910
37039
|
value: draft,
|
|
36911
|
-
placeholder: t("replyTree.replyToPlaceholder", { author:
|
|
37040
|
+
placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
|
|
36912
37041
|
onChange: (e) => setDraft(e.target.value),
|
|
36913
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
37042
|
+
"aria-label": t("replyTree.replyTo", { author: authorName })
|
|
36914
37043
|
}
|
|
36915
37044
|
),
|
|
36916
37045
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
@@ -36941,7 +37070,7 @@ var init_ReplyTree = __esm({
|
|
|
36941
37070
|
),
|
|
36942
37071
|
children: t("replyTree.continueThread")
|
|
36943
37072
|
}
|
|
36944
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-2 mt-1", children:
|
|
37073
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
36945
37074
|
ReplyTreeNode,
|
|
36946
37075
|
{
|
|
36947
37076
|
node: child,
|
|
@@ -38852,8 +38981,8 @@ var init_WizardContainer = __esm({
|
|
|
38852
38981
|
return void 0;
|
|
38853
38982
|
if (typeof controlledStep === "number") return controlledStep;
|
|
38854
38983
|
if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
|
|
38855
|
-
const
|
|
38856
|
-
return isNaN(
|
|
38984
|
+
const num2 = Number(controlledStep);
|
|
38985
|
+
return isNaN(num2) ? void 0 : num2;
|
|
38857
38986
|
})();
|
|
38858
38987
|
const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
|
|
38859
38988
|
const totalSteps = steps.length;
|
|
@@ -40558,7 +40687,7 @@ function DebuggerBoard({
|
|
|
40558
40687
|
}) {
|
|
40559
40688
|
const { emit } = useEventBus();
|
|
40560
40689
|
const { t } = hooks.useTranslate();
|
|
40561
|
-
const resolved =
|
|
40690
|
+
const resolved = boardEntity(entity);
|
|
40562
40691
|
const [flaggedLines, setFlaggedLines] = React97.useState(/* @__PURE__ */ new Set());
|
|
40563
40692
|
const [headerError, setHeaderError] = React97.useState(false);
|
|
40564
40693
|
const [submitted, setSubmitted] = React97.useState(false);
|
|
@@ -40576,7 +40705,7 @@ function DebuggerBoard({
|
|
|
40576
40705
|
return next;
|
|
40577
40706
|
});
|
|
40578
40707
|
};
|
|
40579
|
-
const lines = resolved?.lines
|
|
40708
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
40580
40709
|
const bugLines = lines.filter((l) => l.isBug);
|
|
40581
40710
|
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
40582
40711
|
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
@@ -40591,7 +40720,7 @@ function DebuggerBoard({
|
|
|
40591
40720
|
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
40592
40721
|
const handleReset = () => {
|
|
40593
40722
|
setSubmitted(false);
|
|
40594
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
40723
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
40595
40724
|
setShowHint(true);
|
|
40596
40725
|
}
|
|
40597
40726
|
};
|
|
@@ -40602,24 +40731,28 @@ function DebuggerBoard({
|
|
|
40602
40731
|
setShowHint(false);
|
|
40603
40732
|
};
|
|
40604
40733
|
if (!resolved) return null;
|
|
40734
|
+
const theme = resolved.theme ?? void 0;
|
|
40735
|
+
const themeBackground = theme?.background;
|
|
40736
|
+
const headerImage = str(resolved.headerImage);
|
|
40737
|
+
const hint = str(resolved.hint);
|
|
40605
40738
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
40606
40739
|
Box,
|
|
40607
40740
|
{
|
|
40608
40741
|
className,
|
|
40609
40742
|
style: {
|
|
40610
|
-
backgroundImage:
|
|
40743
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
40611
40744
|
backgroundSize: "cover",
|
|
40612
40745
|
backgroundPosition: "center"
|
|
40613
40746
|
},
|
|
40614
40747
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
40615
|
-
|
|
40748
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
40616
40749
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
40617
40750
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
40618
40751
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Bug, size: "sm" }),
|
|
40619
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
|
|
40752
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
|
|
40620
40753
|
] }),
|
|
40621
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description }),
|
|
40622
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
|
|
40754
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
40755
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
40623
40756
|
] }) }),
|
|
40624
40757
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
40625
40758
|
const isFlagged = flaggedLines.has(line.id);
|
|
@@ -40651,7 +40784,7 @@ function DebuggerBoard({
|
|
|
40651
40784
|
);
|
|
40652
40785
|
}) }) }),
|
|
40653
40786
|
submitted && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
40654
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
40787
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
40655
40788
|
bugLines.map((line) => /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
40656
40789
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
40657
40790
|
Icon,
|
|
@@ -40667,7 +40800,7 @@ function DebuggerBoard({
|
|
|
40667
40800
|
] })
|
|
40668
40801
|
] }, line.id))
|
|
40669
40802
|
] }) }),
|
|
40670
|
-
showHint &&
|
|
40803
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
40671
40804
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
40672
40805
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
40673
40806
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Send, size: "sm" }),
|
|
@@ -40686,6 +40819,7 @@ var init_DebuggerBoard = __esm({
|
|
|
40686
40819
|
"components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
|
|
40687
40820
|
init_atoms2();
|
|
40688
40821
|
init_useEventBus();
|
|
40822
|
+
init_boardEntity();
|
|
40689
40823
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
40690
40824
|
}
|
|
40691
40825
|
});
|
|
@@ -40723,7 +40857,7 @@ function getBadgeVariant(fieldName, value) {
|
|
|
40723
40857
|
return "default";
|
|
40724
40858
|
}
|
|
40725
40859
|
function formatFieldLabel(fieldName) {
|
|
40726
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
40860
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
|
|
40727
40861
|
}
|
|
40728
40862
|
function formatFieldValue(value, fieldName) {
|
|
40729
40863
|
if (typeof value === "number") {
|
|
@@ -40742,26 +40876,26 @@ function formatFieldValue(value, fieldName) {
|
|
|
40742
40876
|
}
|
|
40743
40877
|
function renderRichFieldValue(value, fieldName, fieldType) {
|
|
40744
40878
|
if (value === void 0 || value === null) return "\u2014";
|
|
40745
|
-
const
|
|
40879
|
+
const str2 = String(value);
|
|
40746
40880
|
switch (fieldType) {
|
|
40747
40881
|
case "image":
|
|
40748
40882
|
case "url": {
|
|
40749
|
-
if (
|
|
40883
|
+
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
40750
40884
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
40751
40885
|
"img",
|
|
40752
40886
|
{
|
|
40753
|
-
src:
|
|
40887
|
+
src: str2,
|
|
40754
40888
|
alt: formatFieldLabel(fieldName),
|
|
40755
40889
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
40756
40890
|
loading: "lazy"
|
|
40757
40891
|
}
|
|
40758
40892
|
) });
|
|
40759
40893
|
}
|
|
40760
|
-
return
|
|
40894
|
+
return str2;
|
|
40761
40895
|
}
|
|
40762
40896
|
case "markdown":
|
|
40763
40897
|
case "richtext":
|
|
40764
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React97.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "break-words", children:
|
|
40898
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React97.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
40765
40899
|
Box,
|
|
40766
40900
|
{
|
|
40767
40901
|
className: "prose prose-sm max-w-none",
|
|
@@ -40779,11 +40913,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40779
40913
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
40780
40914
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
40781
40915
|
},
|
|
40782
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown2, { children:
|
|
40916
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown2, { children: str2 })
|
|
40783
40917
|
}
|
|
40784
40918
|
) });
|
|
40785
40919
|
case "code":
|
|
40786
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children:
|
|
40920
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: str2 }) }) });
|
|
40787
40921
|
case "html":
|
|
40788
40922
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
40789
40923
|
Box,
|
|
@@ -40803,12 +40937,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40803
40937
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
40804
40938
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
40805
40939
|
},
|
|
40806
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children:
|
|
40940
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str2 })
|
|
40807
40941
|
}
|
|
40808
40942
|
);
|
|
40809
40943
|
case "date":
|
|
40810
40944
|
case "datetime": {
|
|
40811
|
-
const d = new Date(
|
|
40945
|
+
const d = new Date(str2);
|
|
40812
40946
|
if (!isNaN(d.getTime())) {
|
|
40813
40947
|
return d.toLocaleDateString(void 0, {
|
|
40814
40948
|
year: "numeric",
|
|
@@ -40817,7 +40951,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40817
40951
|
...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
|
|
40818
40952
|
});
|
|
40819
40953
|
}
|
|
40820
|
-
return
|
|
40954
|
+
return str2;
|
|
40821
40955
|
}
|
|
40822
40956
|
default:
|
|
40823
40957
|
return formatFieldValue(value, fieldName);
|
|
@@ -41495,6 +41629,40 @@ var init_RuleEditor = __esm({
|
|
|
41495
41629
|
RuleEditor.displayName = "RuleEditor";
|
|
41496
41630
|
}
|
|
41497
41631
|
});
|
|
41632
|
+
|
|
41633
|
+
// components/game/organisms/puzzles/event-handler/puzzleObject.ts
|
|
41634
|
+
function objId(o) {
|
|
41635
|
+
return o.id == null ? "" : String(o.id);
|
|
41636
|
+
}
|
|
41637
|
+
function objName(o) {
|
|
41638
|
+
return o.name == null ? "" : String(o.name);
|
|
41639
|
+
}
|
|
41640
|
+
function objIcon(o) {
|
|
41641
|
+
return o.icon == null ? "" : String(o.icon);
|
|
41642
|
+
}
|
|
41643
|
+
function objStates(o) {
|
|
41644
|
+
return Array.isArray(o.states) ? o.states : [];
|
|
41645
|
+
}
|
|
41646
|
+
function objCurrentState(o) {
|
|
41647
|
+
return o.currentState == null ? "" : String(o.currentState);
|
|
41648
|
+
}
|
|
41649
|
+
function objAvailableEvents(o) {
|
|
41650
|
+
return Array.isArray(o.availableEvents) ? o.availableEvents : [];
|
|
41651
|
+
}
|
|
41652
|
+
function objAvailableActions(o) {
|
|
41653
|
+
return Array.isArray(o.availableActions) ? o.availableActions : [];
|
|
41654
|
+
}
|
|
41655
|
+
function objRules(o) {
|
|
41656
|
+
return Array.isArray(o.rules) ? o.rules : [];
|
|
41657
|
+
}
|
|
41658
|
+
function objMaxRules(o) {
|
|
41659
|
+
const n = Number(o.maxRules);
|
|
41660
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
41661
|
+
}
|
|
41662
|
+
var init_puzzleObject = __esm({
|
|
41663
|
+
"components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
|
|
41664
|
+
}
|
|
41665
|
+
});
|
|
41498
41666
|
function ObjectRulePanel({
|
|
41499
41667
|
object,
|
|
41500
41668
|
onRulesChange,
|
|
@@ -41502,55 +41670,63 @@ function ObjectRulePanel({
|
|
|
41502
41670
|
className
|
|
41503
41671
|
}) {
|
|
41504
41672
|
const { t } = hooks.useTranslate();
|
|
41505
|
-
const
|
|
41506
|
-
const
|
|
41673
|
+
const id = objId(object);
|
|
41674
|
+
const name = objName(object);
|
|
41675
|
+
const icon = objIcon(object);
|
|
41676
|
+
const states = objStates(object);
|
|
41677
|
+
const currentState = objCurrentState(object);
|
|
41678
|
+
const availableEvents = objAvailableEvents(object);
|
|
41679
|
+
const availableActions = objAvailableActions(object);
|
|
41680
|
+
const rules = objRules(object);
|
|
41681
|
+
const maxRules = objMaxRules(object);
|
|
41682
|
+
const canAdd = rules.length < maxRules;
|
|
41507
41683
|
const handleRuleChange = React97.useCallback((index, updatedRule) => {
|
|
41508
|
-
const newRules = [...
|
|
41684
|
+
const newRules = [...rules];
|
|
41509
41685
|
newRules[index] = updatedRule;
|
|
41510
|
-
onRulesChange(
|
|
41511
|
-
}, [
|
|
41686
|
+
onRulesChange(id, newRules);
|
|
41687
|
+
}, [id, rules, onRulesChange]);
|
|
41512
41688
|
const handleRuleRemove = React97.useCallback((index) => {
|
|
41513
|
-
const newRules =
|
|
41514
|
-
onRulesChange(
|
|
41515
|
-
}, [
|
|
41689
|
+
const newRules = rules.filter((_, i) => i !== index);
|
|
41690
|
+
onRulesChange(id, newRules);
|
|
41691
|
+
}, [id, rules, onRulesChange]);
|
|
41516
41692
|
const handleAddRule = React97.useCallback(() => {
|
|
41517
41693
|
if (!canAdd || disabled) return;
|
|
41518
|
-
const firstEvent =
|
|
41519
|
-
const firstAction =
|
|
41694
|
+
const firstEvent = availableEvents[0]?.value || "";
|
|
41695
|
+
const firstAction = availableActions[0]?.value || "";
|
|
41520
41696
|
const newRule = {
|
|
41521
41697
|
id: `rule-${nextRuleId++}`,
|
|
41522
41698
|
whenEvent: firstEvent,
|
|
41523
41699
|
thenAction: firstAction
|
|
41524
41700
|
};
|
|
41525
|
-
onRulesChange(
|
|
41526
|
-
}, [canAdd, disabled,
|
|
41701
|
+
onRulesChange(id, [...rules, newRule]);
|
|
41702
|
+
}, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
|
|
41527
41703
|
const machine = {
|
|
41528
|
-
name
|
|
41529
|
-
states
|
|
41530
|
-
currentState
|
|
41531
|
-
transitions:
|
|
41532
|
-
from:
|
|
41533
|
-
to:
|
|
41704
|
+
name,
|
|
41705
|
+
states,
|
|
41706
|
+
currentState,
|
|
41707
|
+
transitions: rules.map((r2) => ({
|
|
41708
|
+
from: currentState,
|
|
41709
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
41534
41710
|
event: r2.whenEvent
|
|
41535
41711
|
}))
|
|
41536
41712
|
};
|
|
41537
41713
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
41538
41714
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center", gap: "sm", children: [
|
|
41539
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", children:
|
|
41715
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", children: icon }),
|
|
41540
41716
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", children: [
|
|
41541
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children:
|
|
41542
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " +
|
|
41717
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
|
|
41718
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
|
|
41543
41719
|
] })
|
|
41544
41720
|
] }),
|
|
41545
41721
|
/* @__PURE__ */ jsxRuntime.jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
|
|
41546
41722
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
41547
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count:
|
|
41548
|
-
|
|
41723
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
|
|
41724
|
+
rules.map((rule, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
41549
41725
|
RuleEditor,
|
|
41550
41726
|
{
|
|
41551
41727
|
rule,
|
|
41552
|
-
availableEvents
|
|
41553
|
-
availableActions
|
|
41728
|
+
availableEvents,
|
|
41729
|
+
availableActions,
|
|
41554
41730
|
onChange: (r2) => handleRuleChange(i, r2),
|
|
41555
41731
|
onRemove: () => handleRuleRemove(i),
|
|
41556
41732
|
disabled
|
|
@@ -41568,6 +41744,7 @@ var init_ObjectRulePanel = __esm({
|
|
|
41568
41744
|
init_cn();
|
|
41569
41745
|
init_TraitStateViewer();
|
|
41570
41746
|
init_RuleEditor();
|
|
41747
|
+
init_puzzleObject();
|
|
41571
41748
|
nextRuleId = 1;
|
|
41572
41749
|
ObjectRulePanel.displayName = "ObjectRulePanel";
|
|
41573
41750
|
}
|
|
@@ -41634,11 +41811,11 @@ function EventHandlerBoard({
|
|
|
41634
41811
|
}) {
|
|
41635
41812
|
const { emit } = useEventBus();
|
|
41636
41813
|
const { t } = hooks.useTranslate();
|
|
41637
|
-
const resolved =
|
|
41638
|
-
const entityObjects = resolved?.objects
|
|
41639
|
-
const [objects, setObjects] = React97.useState(entityObjects);
|
|
41814
|
+
const resolved = boardEntity(entity);
|
|
41815
|
+
const entityObjects = rows(resolved?.objects);
|
|
41816
|
+
const [objects, setObjects] = React97.useState(() => [...entityObjects]);
|
|
41640
41817
|
const [selectedObjectId, setSelectedObjectId] = React97.useState(
|
|
41641
|
-
entityObjects[0]
|
|
41818
|
+
entityObjects[0] ? objId(entityObjects[0]) : null
|
|
41642
41819
|
);
|
|
41643
41820
|
const [headerError, setHeaderError] = React97.useState(false);
|
|
41644
41821
|
const [playState, setPlayState] = React97.useState("editing");
|
|
@@ -41649,10 +41826,10 @@ function EventHandlerBoard({
|
|
|
41649
41826
|
React97.useEffect(() => () => {
|
|
41650
41827
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
41651
41828
|
}, []);
|
|
41652
|
-
const selectedObject = objects.find((o) => o
|
|
41829
|
+
const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
|
|
41653
41830
|
const handleRulesChange = React97.useCallback((objectId, rules) => {
|
|
41654
41831
|
setObjects((prev) => prev.map(
|
|
41655
|
-
(o) => o
|
|
41832
|
+
(o) => objId(o) === objectId ? { ...o, rules } : o
|
|
41656
41833
|
));
|
|
41657
41834
|
}, []);
|
|
41658
41835
|
const addLogEntry = React97.useCallback((icon, message, status = "done") => {
|
|
@@ -41666,11 +41843,12 @@ function EventHandlerBoard({
|
|
|
41666
41843
|
setEventLog([]);
|
|
41667
41844
|
const allRules = [];
|
|
41668
41845
|
objects.forEach((obj) => {
|
|
41669
|
-
obj.
|
|
41846
|
+
objRules(obj).forEach((rule) => {
|
|
41670
41847
|
allRules.push({ object: obj, rule });
|
|
41671
41848
|
});
|
|
41672
41849
|
});
|
|
41673
|
-
const triggers = resolved?.triggerEvents
|
|
41850
|
+
const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
|
|
41851
|
+
const goalEvent = str(resolved?.goalEvent);
|
|
41674
41852
|
const eventQueue = [...triggers];
|
|
41675
41853
|
const firedEvents = /* @__PURE__ */ new Set();
|
|
41676
41854
|
let stepIdx = 0;
|
|
@@ -41699,14 +41877,14 @@ function EventHandlerBoard({
|
|
|
41699
41877
|
addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
|
|
41700
41878
|
} else {
|
|
41701
41879
|
matching.forEach(({ object, rule }) => {
|
|
41702
|
-
addLogEntry(object
|
|
41880
|
+
addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
|
|
41703
41881
|
eventQueue.push(rule.thenAction);
|
|
41704
|
-
if (rule.thenAction ===
|
|
41882
|
+
if (rule.thenAction === goalEvent) {
|
|
41705
41883
|
goalReached = true;
|
|
41706
41884
|
}
|
|
41707
41885
|
});
|
|
41708
41886
|
}
|
|
41709
|
-
if (currentEvent ===
|
|
41887
|
+
if (currentEvent === goalEvent) {
|
|
41710
41888
|
goalReached = true;
|
|
41711
41889
|
}
|
|
41712
41890
|
stepIdx++;
|
|
@@ -41724,65 +41902,75 @@ function EventHandlerBoard({
|
|
|
41724
41902
|
}, []);
|
|
41725
41903
|
const handleReset = React97.useCallback(() => {
|
|
41726
41904
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
41727
|
-
|
|
41905
|
+
const resetObjects = rows(resolved?.objects);
|
|
41906
|
+
setObjects([...resetObjects]);
|
|
41728
41907
|
setPlayState("editing");
|
|
41729
41908
|
setEventLog([]);
|
|
41730
|
-
setSelectedObjectId(
|
|
41909
|
+
setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
|
|
41731
41910
|
setAttempts(0);
|
|
41732
41911
|
}, [resolved?.objects]);
|
|
41733
41912
|
if (!resolved) return null;
|
|
41734
41913
|
const objectViewers = objects.map((obj) => {
|
|
41914
|
+
const states = objStates(obj);
|
|
41915
|
+
const currentState = objCurrentState(obj);
|
|
41735
41916
|
const machine = {
|
|
41736
|
-
name: obj
|
|
41737
|
-
states
|
|
41738
|
-
currentState
|
|
41739
|
-
transitions: obj.
|
|
41740
|
-
from:
|
|
41741
|
-
to:
|
|
41917
|
+
name: objName(obj),
|
|
41918
|
+
states,
|
|
41919
|
+
currentState,
|
|
41920
|
+
transitions: objRules(obj).map((r2) => ({
|
|
41921
|
+
from: currentState,
|
|
41922
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
41742
41923
|
event: r2.whenEvent
|
|
41743
41924
|
}))
|
|
41744
41925
|
};
|
|
41745
41926
|
return { obj, machine };
|
|
41746
41927
|
});
|
|
41747
|
-
const
|
|
41928
|
+
const hint = str(resolved.hint);
|
|
41929
|
+
const showHint = attempts >= 3 && hint;
|
|
41930
|
+
const theme = resolved.theme ?? void 0;
|
|
41931
|
+
const themeBackground = theme?.background;
|
|
41932
|
+
const headerImage = str(resolved.headerImage);
|
|
41748
41933
|
const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
|
|
41749
41934
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
41750
41935
|
VStack,
|
|
41751
41936
|
{
|
|
41752
41937
|
className: cn("p-4 gap-6", className),
|
|
41753
41938
|
style: {
|
|
41754
|
-
backgroundImage:
|
|
41939
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
41755
41940
|
backgroundSize: "cover",
|
|
41756
41941
|
backgroundPosition: "center"
|
|
41757
41942
|
},
|
|
41758
41943
|
children: [
|
|
41759
|
-
|
|
41944
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
41760
41945
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
41761
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
41762
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
41946
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
41947
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
41763
41948
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
41764
41949
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
41765
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
|
|
41950
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
|
|
41766
41951
|
] })
|
|
41767
41952
|
] }),
|
|
41768
41953
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
41769
41954
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
41770
|
-
/* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) =>
|
|
41771
|
-
|
|
41772
|
-
|
|
41773
|
-
|
|
41774
|
-
|
|
41775
|
-
|
|
41776
|
-
|
|
41777
|
-
|
|
41778
|
-
|
|
41779
|
-
|
|
41780
|
-
/* @__PURE__ */ jsxRuntime.
|
|
41781
|
-
|
|
41782
|
-
|
|
41783
|
-
|
|
41784
|
-
|
|
41785
|
-
|
|
41955
|
+
/* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
|
|
41956
|
+
const oid = objId(obj);
|
|
41957
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
41958
|
+
Box,
|
|
41959
|
+
{
|
|
41960
|
+
className: cn(
|
|
41961
|
+
"p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
|
|
41962
|
+
selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
41963
|
+
),
|
|
41964
|
+
onClick: () => setSelectedObjectId(oid),
|
|
41965
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
41966
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", children: objIcon(obj) }),
|
|
41967
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
|
|
41968
|
+
/* @__PURE__ */ jsxRuntime.jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
41969
|
+
] })
|
|
41970
|
+
},
|
|
41971
|
+
oid
|
|
41972
|
+
);
|
|
41973
|
+
}) })
|
|
41786
41974
|
] }),
|
|
41787
41975
|
selectedObject && /* @__PURE__ */ jsxRuntime.jsx(
|
|
41788
41976
|
ObjectRulePanel,
|
|
@@ -41793,12 +41981,12 @@ function EventHandlerBoard({
|
|
|
41793
41981
|
}
|
|
41794
41982
|
),
|
|
41795
41983
|
eventLog.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(EventLog, { entries: eventLog }),
|
|
41796
|
-
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("eventHandler.chainComplete") }) }),
|
|
41984
|
+
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("eventHandler.chainComplete") }) }),
|
|
41797
41985
|
playState === "fail" && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
41798
41986
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
|
|
41799
41987
|
showHint && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
41800
41988
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
41801
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
41989
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
41802
41990
|
] }) })
|
|
41803
41991
|
] }),
|
|
41804
41992
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", children: [
|
|
@@ -41826,6 +42014,8 @@ var init_EventHandlerBoard = __esm({
|
|
|
41826
42014
|
init_TraitStateViewer();
|
|
41827
42015
|
init_ObjectRulePanel();
|
|
41828
42016
|
init_EventLog();
|
|
42017
|
+
init_puzzleObject();
|
|
42018
|
+
init_boardEntity();
|
|
41829
42019
|
ENCOURAGEMENT_KEYS = [
|
|
41830
42020
|
"puzzle.tryAgain1",
|
|
41831
42021
|
"puzzle.tryAgain2",
|
|
@@ -41914,7 +42104,10 @@ var init_FeatureGridOrganism = __esm({
|
|
|
41914
42104
|
);
|
|
41915
42105
|
React97.useCallback(
|
|
41916
42106
|
(feature) => {
|
|
41917
|
-
eventBus.emit("UI:FEATURE_CLICK", {
|
|
42107
|
+
eventBus.emit("UI:FEATURE_CLICK", {
|
|
42108
|
+
id: String(feature.id ?? ""),
|
|
42109
|
+
href: String(feature.href ?? "")
|
|
42110
|
+
});
|
|
41918
42111
|
},
|
|
41919
42112
|
[eventBus]
|
|
41920
42113
|
);
|
|
@@ -41924,14 +42117,17 @@ var init_FeatureGridOrganism = __esm({
|
|
|
41924
42117
|
if (error) {
|
|
41925
42118
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
41926
42119
|
}
|
|
41927
|
-
const featureCards = items.map((feature) =>
|
|
41928
|
-
|
|
41929
|
-
|
|
41930
|
-
|
|
41931
|
-
|
|
41932
|
-
|
|
41933
|
-
|
|
41934
|
-
|
|
42120
|
+
const featureCards = items.map((feature) => {
|
|
42121
|
+
const href = feature.href != null ? String(feature.href) : void 0;
|
|
42122
|
+
return {
|
|
42123
|
+
icon: feature.icon != null ? String(feature.icon) : void 0,
|
|
42124
|
+
title: String(feature.title ?? ""),
|
|
42125
|
+
description: String(feature.description ?? ""),
|
|
42126
|
+
href,
|
|
42127
|
+
linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
|
|
42128
|
+
variant: href ? "interactive" : "bordered"
|
|
42129
|
+
};
|
|
42130
|
+
});
|
|
41935
42131
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
41936
42132
|
(heading || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
41937
42133
|
heading && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
@@ -43249,22 +43445,24 @@ var init_HeroOrganism = __esm({
|
|
|
43249
43445
|
() => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
|
|
43250
43446
|
[entity]
|
|
43251
43447
|
);
|
|
43448
|
+
const primaryAction = resolved?.primaryAction;
|
|
43449
|
+
const secondaryAction = resolved?.secondaryAction;
|
|
43252
43450
|
const handlePrimaryClick = React97.useCallback(() => {
|
|
43253
|
-
if (
|
|
43451
|
+
if (primaryAction) {
|
|
43254
43452
|
eventBus.emit("UI:CTA_PRIMARY", {
|
|
43255
|
-
label:
|
|
43256
|
-
href:
|
|
43453
|
+
label: String(primaryAction.label ?? ""),
|
|
43454
|
+
href: String(primaryAction.href ?? "")
|
|
43257
43455
|
});
|
|
43258
43456
|
}
|
|
43259
|
-
}, [eventBus,
|
|
43457
|
+
}, [eventBus, primaryAction]);
|
|
43260
43458
|
const handleSecondaryClick = React97.useCallback(() => {
|
|
43261
|
-
if (
|
|
43459
|
+
if (secondaryAction) {
|
|
43262
43460
|
eventBus.emit("UI:CTA_SECONDARY", {
|
|
43263
|
-
label:
|
|
43264
|
-
href:
|
|
43461
|
+
label: String(secondaryAction.label ?? ""),
|
|
43462
|
+
href: String(secondaryAction.href ?? "")
|
|
43265
43463
|
});
|
|
43266
43464
|
}
|
|
43267
|
-
}, [eventBus,
|
|
43465
|
+
}, [eventBus, secondaryAction]);
|
|
43268
43466
|
if (isLoading) {
|
|
43269
43467
|
return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: t("common.loading"), className });
|
|
43270
43468
|
}
|
|
@@ -43274,17 +43472,19 @@ var init_HeroOrganism = __esm({
|
|
|
43274
43472
|
if (!resolved) {
|
|
43275
43473
|
return null;
|
|
43276
43474
|
}
|
|
43475
|
+
const imageRaw = resolved.image;
|
|
43476
|
+
const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
|
|
43277
43477
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
43278
43478
|
HeroSection,
|
|
43279
43479
|
{
|
|
43280
|
-
tag: resolved.tag,
|
|
43281
|
-
title: resolved.title,
|
|
43282
|
-
titleAccent: resolved.titleAccent,
|
|
43283
|
-
subtitle: resolved.subtitle,
|
|
43284
|
-
primaryAction:
|
|
43285
|
-
secondaryAction:
|
|
43286
|
-
installCommand: resolved.installCommand,
|
|
43287
|
-
image
|
|
43480
|
+
tag: resolved.tag != null ? String(resolved.tag) : void 0,
|
|
43481
|
+
title: String(resolved.title ?? ""),
|
|
43482
|
+
titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
|
|
43483
|
+
subtitle: String(resolved.subtitle ?? ""),
|
|
43484
|
+
primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
|
|
43485
|
+
secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
|
|
43486
|
+
installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
|
|
43487
|
+
image,
|
|
43288
43488
|
imagePosition: resolved.imagePosition,
|
|
43289
43489
|
background: resolved.background,
|
|
43290
43490
|
className: cn(className),
|
|
@@ -43293,8 +43493,8 @@ var init_HeroOrganism = __esm({
|
|
|
43293
43493
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
43294
43494
|
_HeroClickInterceptor,
|
|
43295
43495
|
{
|
|
43296
|
-
hasPrimary: !!
|
|
43297
|
-
hasSecondary: !!
|
|
43496
|
+
hasPrimary: !!primaryAction,
|
|
43497
|
+
hasSecondary: !!secondaryAction,
|
|
43298
43498
|
onPrimaryClick: handlePrimaryClick,
|
|
43299
43499
|
onSecondaryClick: handleSecondaryClick
|
|
43300
43500
|
}
|
|
@@ -43523,7 +43723,7 @@ function formatValue3(value, fieldName) {
|
|
|
43523
43723
|
return String(value);
|
|
43524
43724
|
}
|
|
43525
43725
|
function formatFieldLabel2(fieldName) {
|
|
43526
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
43726
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
|
|
43527
43727
|
}
|
|
43528
43728
|
var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
|
|
43529
43729
|
var init_List = __esm({
|
|
@@ -44370,20 +44570,22 @@ function NegotiatorBoard({
|
|
|
44370
44570
|
}) {
|
|
44371
44571
|
const { emit } = useEventBus();
|
|
44372
44572
|
const { t } = hooks.useTranslate();
|
|
44373
|
-
const resolved =
|
|
44573
|
+
const resolved = boardEntity(entity);
|
|
44374
44574
|
const [history, setHistory] = React97.useState([]);
|
|
44375
44575
|
const [headerError, setHeaderError] = React97.useState(false);
|
|
44376
44576
|
const [showHint, setShowHint] = React97.useState(false);
|
|
44577
|
+
const totalRounds = num(resolved?.totalRounds);
|
|
44578
|
+
const targetScore = num(resolved?.targetScore);
|
|
44377
44579
|
const currentRound = history.length;
|
|
44378
|
-
const isComplete = currentRound >=
|
|
44580
|
+
const isComplete = currentRound >= totalRounds;
|
|
44379
44581
|
const playerTotal = history.reduce((s, r2) => s + r2.playerPayoff, 0);
|
|
44380
44582
|
const opponentTotal = history.reduce((s, r2) => s + r2.opponentPayoff, 0);
|
|
44381
|
-
const won = isComplete && playerTotal >=
|
|
44382
|
-
const actions = resolved?.actions
|
|
44383
|
-
const payoffMatrix = resolved?.payoffMatrix
|
|
44583
|
+
const won = isComplete && playerTotal >= targetScore;
|
|
44584
|
+
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
44585
|
+
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
44384
44586
|
const handleAction = React97.useCallback((actionId) => {
|
|
44385
44587
|
if (isComplete) return;
|
|
44386
|
-
const opponentAction = getOpponentAction(resolved?.opponentStrategy
|
|
44588
|
+
const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
|
|
44387
44589
|
const payoff = payoffMatrix.find(
|
|
44388
44590
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
44389
44591
|
);
|
|
@@ -44396,42 +44598,46 @@ function NegotiatorBoard({
|
|
|
44396
44598
|
};
|
|
44397
44599
|
const newHistory = [...history, result];
|
|
44398
44600
|
setHistory(newHistory);
|
|
44399
|
-
if (newHistory.length >=
|
|
44601
|
+
if (newHistory.length >= totalRounds) {
|
|
44400
44602
|
const total = newHistory.reduce((s, r2) => s + r2.playerPayoff, 0);
|
|
44401
|
-
if (total >=
|
|
44603
|
+
if (total >= targetScore) {
|
|
44402
44604
|
emit(`UI:${completeEvent}`, { success: true, score: total });
|
|
44403
44605
|
}
|
|
44404
|
-
if (newHistory.length >= 3 && resolved?.hint) {
|
|
44606
|
+
if (newHistory.length >= 3 && str(resolved?.hint)) {
|
|
44405
44607
|
setShowHint(true);
|
|
44406
44608
|
}
|
|
44407
44609
|
}
|
|
44408
|
-
}, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
44610
|
+
}, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
44409
44611
|
const handleReset = () => {
|
|
44410
44612
|
setHistory([]);
|
|
44411
44613
|
setShowHint(false);
|
|
44412
44614
|
};
|
|
44413
44615
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
44414
44616
|
if (!resolved) return null;
|
|
44617
|
+
const theme = resolved.theme ?? void 0;
|
|
44618
|
+
const themeBackground = theme?.background;
|
|
44619
|
+
const headerImage = str(resolved.headerImage);
|
|
44620
|
+
const hint = str(resolved.hint);
|
|
44415
44621
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
44416
44622
|
Box,
|
|
44417
44623
|
{
|
|
44418
44624
|
className,
|
|
44419
44625
|
style: {
|
|
44420
|
-
backgroundImage:
|
|
44626
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44421
44627
|
backgroundSize: "cover",
|
|
44422
44628
|
backgroundPosition: "center"
|
|
44423
44629
|
},
|
|
44424
44630
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
44425
|
-
|
|
44631
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44426
44632
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
44427
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
44428
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description }),
|
|
44633
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
44634
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
44429
44635
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", children: [
|
|
44430
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(
|
|
44636
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
|
|
44431
44637
|
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", children: [
|
|
44432
44638
|
t("negotiator.target"),
|
|
44433
44639
|
": ",
|
|
44434
|
-
|
|
44640
|
+
targetScore
|
|
44435
44641
|
] })
|
|
44436
44642
|
] })
|
|
44437
44643
|
] }) }),
|
|
@@ -44480,16 +44686,16 @@ function NegotiatorBoard({
|
|
|
44480
44686
|
] }) }),
|
|
44481
44687
|
isComplete && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
44482
44688
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
|
|
44483
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage
|
|
44689
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
|
|
44484
44690
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
44485
44691
|
t("negotiator.finalScore"),
|
|
44486
44692
|
": ",
|
|
44487
44693
|
playerTotal,
|
|
44488
44694
|
"/",
|
|
44489
|
-
|
|
44695
|
+
targetScore
|
|
44490
44696
|
] })
|
|
44491
44697
|
] }) }),
|
|
44492
|
-
showHint &&
|
|
44698
|
+
showHint && hint && !won && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
44493
44699
|
isComplete && !won && /* @__PURE__ */ jsxRuntime.jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
44494
44700
|
] })
|
|
44495
44701
|
}
|
|
@@ -44499,6 +44705,7 @@ var init_NegotiatorBoard = __esm({
|
|
|
44499
44705
|
"components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
|
|
44500
44706
|
init_atoms2();
|
|
44501
44707
|
init_useEventBus();
|
|
44708
|
+
init_boardEntity();
|
|
44502
44709
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
44503
44710
|
}
|
|
44504
44711
|
});
|
|
@@ -44534,13 +44741,13 @@ var init_PricingOrganism = __esm({
|
|
|
44534
44741
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
44535
44742
|
}
|
|
44536
44743
|
const plans = items.map((plan) => ({
|
|
44537
|
-
name: plan.name,
|
|
44538
|
-
price: plan.price,
|
|
44539
|
-
description: plan.description,
|
|
44540
|
-
features: plan.features,
|
|
44541
|
-
action: { label: plan.actionLabel, href: plan.actionHref },
|
|
44542
|
-
highlighted: plan.highlighted,
|
|
44543
|
-
badge: plan.badge
|
|
44744
|
+
name: String(plan.name ?? ""),
|
|
44745
|
+
price: String(plan.price ?? ""),
|
|
44746
|
+
description: plan.description != null ? String(plan.description) : void 0,
|
|
44747
|
+
features: (plan.features ?? []).map((f3) => String(f3)),
|
|
44748
|
+
action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
|
|
44749
|
+
highlighted: Boolean(plan.highlighted),
|
|
44750
|
+
badge: plan.badge != null ? String(plan.badge) : void 0
|
|
44544
44751
|
}));
|
|
44545
44752
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
44546
44753
|
(heading || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -46630,16 +46837,20 @@ function SequencerBoard({
|
|
|
46630
46837
|
}) {
|
|
46631
46838
|
const { emit } = useEventBus();
|
|
46632
46839
|
const { t } = hooks.useTranslate();
|
|
46633
|
-
const resolved =
|
|
46840
|
+
const resolved = boardEntity(entity);
|
|
46841
|
+
const maxSlots = num(resolved?.maxSlots);
|
|
46842
|
+
const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
|
|
46843
|
+
const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
|
|
46844
|
+
const allowDuplicates = resolved?.allowDuplicates !== false;
|
|
46634
46845
|
const [headerError, setHeaderError] = React97.useState(false);
|
|
46635
46846
|
const [slots, setSlots] = React97.useState(
|
|
46636
|
-
() => Array.from({ length:
|
|
46847
|
+
() => Array.from({ length: maxSlots }, () => void 0)
|
|
46637
46848
|
);
|
|
46638
46849
|
const [playState, setPlayState] = React97.useState("idle");
|
|
46639
46850
|
const [currentStep, setCurrentStep] = React97.useState(-1);
|
|
46640
46851
|
const [attempts, setAttempts] = React97.useState(0);
|
|
46641
46852
|
const [slotFeedback, setSlotFeedback] = React97.useState(
|
|
46642
|
-
() => Array.from({ length:
|
|
46853
|
+
() => Array.from({ length: maxSlots }, () => null)
|
|
46643
46854
|
);
|
|
46644
46855
|
const timerRef = React97.useRef(null);
|
|
46645
46856
|
React97.useEffect(() => () => {
|
|
@@ -46673,17 +46884,17 @@ function SequencerBoard({
|
|
|
46673
46884
|
}, [emit]);
|
|
46674
46885
|
const handleReset = React97.useCallback(() => {
|
|
46675
46886
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
46676
|
-
setSlots(Array.from({ length:
|
|
46887
|
+
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
46677
46888
|
setPlayState("idle");
|
|
46678
46889
|
setCurrentStep(-1);
|
|
46679
46890
|
setAttempts(0);
|
|
46680
|
-
setSlotFeedback(Array.from({ length:
|
|
46681
|
-
}, [
|
|
46891
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
46892
|
+
}, [maxSlots]);
|
|
46682
46893
|
const filledSlots = slots.filter((s) => !!s);
|
|
46683
46894
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
46684
46895
|
const handlePlay = React97.useCallback(() => {
|
|
46685
46896
|
if (!canPlay) return;
|
|
46686
|
-
setSlotFeedback(Array.from({ length:
|
|
46897
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
46687
46898
|
emit("UI:PLAY_SOUND", { key: "confirm" });
|
|
46688
46899
|
const sequence = slots.map((s) => s?.id || "");
|
|
46689
46900
|
if (playEvent) {
|
|
@@ -46694,10 +46905,10 @@ function SequencerBoard({
|
|
|
46694
46905
|
let step = 0;
|
|
46695
46906
|
const advance = () => {
|
|
46696
46907
|
step++;
|
|
46697
|
-
if (step >=
|
|
46908
|
+
if (step >= maxSlots) {
|
|
46698
46909
|
const playerSeq = slots.map((s) => s?.id);
|
|
46699
46910
|
const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
|
|
46700
|
-
const success =
|
|
46911
|
+
const success = solutions.some(
|
|
46701
46912
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
46702
46913
|
);
|
|
46703
46914
|
if (success) {
|
|
@@ -46709,7 +46920,7 @@ function SequencerBoard({
|
|
|
46709
46920
|
}
|
|
46710
46921
|
} else {
|
|
46711
46922
|
setAttempts((prev) => prev + 1);
|
|
46712
|
-
const feedback = computeSlotFeedback(playerSeq,
|
|
46923
|
+
const feedback = computeSlotFeedback(playerSeq, solutions);
|
|
46713
46924
|
setSlotFeedback(feedback);
|
|
46714
46925
|
setPlayState("idle");
|
|
46715
46926
|
setCurrentStep(-1);
|
|
@@ -46727,10 +46938,10 @@ function SequencerBoard({
|
|
|
46727
46938
|
}
|
|
46728
46939
|
};
|
|
46729
46940
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
46730
|
-
}, [canPlay, slots,
|
|
46941
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
46731
46942
|
const machine = {
|
|
46732
|
-
name: resolved?.title
|
|
46733
|
-
description: resolved?.description
|
|
46943
|
+
name: str(resolved?.title),
|
|
46944
|
+
description: str(resolved?.description),
|
|
46734
46945
|
states: slots.map((s, i) => stepLabel(s, i)),
|
|
46735
46946
|
currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
|
|
46736
46947
|
transitions: slots.slice(0, -1).map((s, i) => ({
|
|
@@ -46739,37 +46950,41 @@ function SequencerBoard({
|
|
|
46739
46950
|
event: "NEXT"
|
|
46740
46951
|
}))
|
|
46741
46952
|
};
|
|
46742
|
-
const usedIds =
|
|
46743
|
-
const
|
|
46953
|
+
const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
|
|
46954
|
+
const hint = str(resolved?.hint);
|
|
46955
|
+
const showHint = attempts >= 3 && !!hint;
|
|
46744
46956
|
const hasFeedback = slotFeedback.some((f3) => f3 !== null);
|
|
46745
46957
|
const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
|
|
46746
46958
|
const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
|
|
46747
46959
|
if (!resolved) return null;
|
|
46960
|
+
const theme = resolved.theme ?? void 0;
|
|
46961
|
+
const themeBackground = theme?.background;
|
|
46962
|
+
const headerImage = str(resolved.headerImage);
|
|
46748
46963
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
46749
46964
|
VStack,
|
|
46750
46965
|
{
|
|
46751
46966
|
className: cn("p-4 gap-6", className),
|
|
46752
46967
|
style: {
|
|
46753
|
-
backgroundImage:
|
|
46968
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
46754
46969
|
backgroundSize: "cover",
|
|
46755
46970
|
backgroundPosition: "center"
|
|
46756
46971
|
},
|
|
46757
46972
|
children: [
|
|
46758
|
-
|
|
46973
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
46759
46974
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
46760
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
46761
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
|
|
46975
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
46976
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
|
|
46762
46977
|
] }),
|
|
46763
46978
|
showHint && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
46764
46979
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
46765
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
46980
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
46766
46981
|
] }) }),
|
|
46767
46982
|
filledSlots.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
46768
46983
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
46769
46984
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center justify-between", children: [
|
|
46770
46985
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
46771
46986
|
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
46772
|
-
`${correctCount}/${
|
|
46987
|
+
`${correctCount}/${maxSlots} `,
|
|
46773
46988
|
"\u2705"
|
|
46774
46989
|
] })
|
|
46775
46990
|
] }),
|
|
@@ -46777,7 +46992,7 @@ function SequencerBoard({
|
|
|
46777
46992
|
SequenceBar,
|
|
46778
46993
|
{
|
|
46779
46994
|
slots,
|
|
46780
|
-
maxSlots
|
|
46995
|
+
maxSlots,
|
|
46781
46996
|
onSlotDrop: handleSlotDrop,
|
|
46782
46997
|
onSlotRemove: handleSlotRemove,
|
|
46783
46998
|
playing: playState === "playing",
|
|
@@ -46791,15 +47006,15 @@ function SequencerBoard({
|
|
|
46791
47006
|
playState !== "playing" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
46792
47007
|
ActionPalette,
|
|
46793
47008
|
{
|
|
46794
|
-
actions:
|
|
47009
|
+
actions: availableActions,
|
|
46795
47010
|
usedActionIds: usedIds,
|
|
46796
|
-
allowDuplicates
|
|
47011
|
+
allowDuplicates,
|
|
46797
47012
|
categoryColors,
|
|
46798
47013
|
label: t("sequencer.dragActions")
|
|
46799
47014
|
}
|
|
46800
47015
|
),
|
|
46801
47016
|
hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
|
|
46802
|
-
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("sequencer.levelComplete") }) }),
|
|
47017
|
+
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("sequencer.levelComplete") }) }),
|
|
46803
47018
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", children: [
|
|
46804
47019
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
46805
47020
|
Button,
|
|
@@ -46823,6 +47038,7 @@ var init_SequencerBoard = __esm({
|
|
|
46823
47038
|
init_cn();
|
|
46824
47039
|
init_useEventBus();
|
|
46825
47040
|
init_TraitStateViewer();
|
|
47041
|
+
init_boardEntity();
|
|
46826
47042
|
init_SequenceBar();
|
|
46827
47043
|
init_ActionPalette();
|
|
46828
47044
|
ENCOURAGEMENT_KEYS2 = [
|
|
@@ -46872,18 +47088,21 @@ var init_ShowcaseOrganism = __esm({
|
|
|
46872
47088
|
heading && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
46873
47089
|
subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
|
|
46874
47090
|
] }),
|
|
46875
|
-
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) =>
|
|
46876
|
-
|
|
46877
|
-
|
|
46878
|
-
|
|
46879
|
-
|
|
46880
|
-
|
|
46881
|
-
|
|
46882
|
-
|
|
46883
|
-
|
|
46884
|
-
|
|
46885
|
-
|
|
46886
|
-
|
|
47091
|
+
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
|
|
47092
|
+
const imageRaw = item.image;
|
|
47093
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
47094
|
+
ShowcaseCard,
|
|
47095
|
+
{
|
|
47096
|
+
title: String(item.title ?? ""),
|
|
47097
|
+
description: item.description != null ? String(item.description) : void 0,
|
|
47098
|
+
image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
|
|
47099
|
+
href: item.href != null ? String(item.href) : void 0,
|
|
47100
|
+
badge: item.badge != null ? String(item.badge) : void 0,
|
|
47101
|
+
accentColor: item.accentColor != null ? String(item.accentColor) : void 0
|
|
47102
|
+
},
|
|
47103
|
+
String(item.id ?? "")
|
|
47104
|
+
);
|
|
47105
|
+
}) })
|
|
46887
47106
|
] });
|
|
46888
47107
|
};
|
|
46889
47108
|
ShowcaseOrganism.displayName = "ShowcaseOrganism";
|
|
@@ -47251,8 +47470,8 @@ function SimulatorBoard({
|
|
|
47251
47470
|
}) {
|
|
47252
47471
|
const { emit } = useEventBus();
|
|
47253
47472
|
const { t } = hooks.useTranslate();
|
|
47254
|
-
const resolved =
|
|
47255
|
-
const parameters = resolved?.parameters
|
|
47473
|
+
const resolved = boardEntity(entity);
|
|
47474
|
+
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
47256
47475
|
const [values, setValues] = React97.useState(() => {
|
|
47257
47476
|
const init = {};
|
|
47258
47477
|
for (const p2 of parameters) {
|
|
@@ -47266,15 +47485,15 @@ function SimulatorBoard({
|
|
|
47266
47485
|
const [showHint, setShowHint] = React97.useState(false);
|
|
47267
47486
|
const computeOutput = React97.useCallback((params) => {
|
|
47268
47487
|
try {
|
|
47269
|
-
const fn = new Function("params", `return (${resolved?.computeExpression})`);
|
|
47488
|
+
const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
|
|
47270
47489
|
return fn(params);
|
|
47271
47490
|
} catch {
|
|
47272
47491
|
return 0;
|
|
47273
47492
|
}
|
|
47274
47493
|
}, [resolved?.computeExpression]);
|
|
47275
47494
|
const output = React97.useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
|
|
47276
|
-
const targetValue = resolved?.targetValue
|
|
47277
|
-
const targetTolerance = resolved?.targetTolerance
|
|
47495
|
+
const targetValue = num(resolved?.targetValue);
|
|
47496
|
+
const targetTolerance = num(resolved?.targetTolerance);
|
|
47278
47497
|
const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
|
|
47279
47498
|
const handleParameterChange = (id, value) => {
|
|
47280
47499
|
if (submitted) return;
|
|
@@ -47289,7 +47508,7 @@ function SimulatorBoard({
|
|
|
47289
47508
|
};
|
|
47290
47509
|
const handleReset = () => {
|
|
47291
47510
|
setSubmitted(false);
|
|
47292
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
47511
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
47293
47512
|
setShowHint(true);
|
|
47294
47513
|
}
|
|
47295
47514
|
};
|
|
@@ -47304,20 +47523,26 @@ function SimulatorBoard({
|
|
|
47304
47523
|
setShowHint(false);
|
|
47305
47524
|
};
|
|
47306
47525
|
if (!resolved) return null;
|
|
47526
|
+
const theme = resolved.theme ?? void 0;
|
|
47527
|
+
const themeBackground = theme?.background;
|
|
47528
|
+
const headerImage = str(resolved.headerImage);
|
|
47529
|
+
const hint = str(resolved.hint);
|
|
47530
|
+
const outputLabel = str(resolved.outputLabel);
|
|
47531
|
+
const outputUnit = str(resolved.outputUnit);
|
|
47307
47532
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
47308
47533
|
Box,
|
|
47309
47534
|
{
|
|
47310
47535
|
className,
|
|
47311
47536
|
style: {
|
|
47312
|
-
backgroundImage:
|
|
47537
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
47313
47538
|
backgroundSize: "cover",
|
|
47314
47539
|
backgroundPosition: "center"
|
|
47315
47540
|
},
|
|
47316
47541
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
47317
|
-
|
|
47542
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
47318
47543
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
47319
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
47320
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description })
|
|
47544
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
47545
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
47321
47546
|
] }) }),
|
|
47322
47547
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", children: [
|
|
47323
47548
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
@@ -47358,28 +47583,28 @@ function SimulatorBoard({
|
|
|
47358
47583
|
] }, param.id))
|
|
47359
47584
|
] }) }),
|
|
47360
47585
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
47361
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children:
|
|
47586
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
47362
47587
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
47363
47588
|
output.toFixed(2),
|
|
47364
47589
|
" ",
|
|
47365
|
-
|
|
47590
|
+
outputUnit
|
|
47366
47591
|
] }),
|
|
47367
47592
|
submitted && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
47368
47593
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: isCorrect ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
|
|
47369
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage
|
|
47594
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
47370
47595
|
] }),
|
|
47371
47596
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47372
47597
|
t("simulator.target"),
|
|
47373
47598
|
": ",
|
|
47374
47599
|
targetValue,
|
|
47375
47600
|
" ",
|
|
47376
|
-
|
|
47601
|
+
outputUnit,
|
|
47377
47602
|
" (\xB1",
|
|
47378
47603
|
targetTolerance,
|
|
47379
47604
|
")"
|
|
47380
47605
|
] })
|
|
47381
47606
|
] }) }),
|
|
47382
|
-
showHint &&
|
|
47607
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
47383
47608
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
47384
47609
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
47385
47610
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Play, size: "sm" }),
|
|
@@ -47398,6 +47623,7 @@ var init_SimulatorBoard = __esm({
|
|
|
47398
47623
|
"components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
|
|
47399
47624
|
init_atoms2();
|
|
47400
47625
|
init_useEventBus();
|
|
47626
|
+
init_boardEntity();
|
|
47401
47627
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
47402
47628
|
}
|
|
47403
47629
|
});
|
|
@@ -47823,22 +48049,25 @@ function VariablePanel({
|
|
|
47823
48049
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
47824
48050
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
|
|
47825
48051
|
variables.map((v) => {
|
|
47826
|
-
const
|
|
47827
|
-
const
|
|
47828
|
-
const
|
|
48052
|
+
const name = v.name == null ? "" : String(v.name);
|
|
48053
|
+
const value = numField(v.value);
|
|
48054
|
+
const max = numField(v.max, 100);
|
|
48055
|
+
const min = numField(v.min, 0);
|
|
48056
|
+
const unit = v.unit == null ? "" : String(v.unit);
|
|
48057
|
+
const pct = Math.round((value - min) / (max - min) * 100);
|
|
47829
48058
|
const isHigh = pct > 80;
|
|
47830
48059
|
const isLow = pct < 20;
|
|
47831
48060
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", children: [
|
|
47832
48061
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center justify-between", children: [
|
|
47833
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children:
|
|
48062
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
|
|
47834
48063
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: cn(
|
|
47835
48064
|
isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
|
|
47836
48065
|
), children: [
|
|
47837
|
-
|
|
47838
|
-
|
|
48066
|
+
value,
|
|
48067
|
+
unit,
|
|
47839
48068
|
" / ",
|
|
47840
48069
|
max,
|
|
47841
|
-
|
|
48070
|
+
unit
|
|
47842
48071
|
] })
|
|
47843
48072
|
] }),
|
|
47844
48073
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -47849,14 +48078,19 @@ function VariablePanel({
|
|
|
47849
48078
|
size: "sm"
|
|
47850
48079
|
}
|
|
47851
48080
|
)
|
|
47852
|
-
] },
|
|
48081
|
+
] }, name);
|
|
47853
48082
|
})
|
|
47854
48083
|
] });
|
|
47855
48084
|
}
|
|
48085
|
+
var numField;
|
|
47856
48086
|
var init_VariablePanel = __esm({
|
|
47857
48087
|
"components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
|
|
47858
48088
|
init_atoms2();
|
|
47859
48089
|
init_cn();
|
|
48090
|
+
numField = (v, fallback = 0) => {
|
|
48091
|
+
const n = Number(v);
|
|
48092
|
+
return Number.isFinite(n) ? n : fallback;
|
|
48093
|
+
};
|
|
47860
48094
|
VariablePanel.displayName = "VariablePanel";
|
|
47861
48095
|
}
|
|
47862
48096
|
});
|
|
@@ -47883,14 +48117,21 @@ function StateArchitectBoard({
|
|
|
47883
48117
|
}) {
|
|
47884
48118
|
const { emit } = useEventBus();
|
|
47885
48119
|
const { t } = hooks.useTranslate();
|
|
47886
|
-
const resolved =
|
|
47887
|
-
const
|
|
48120
|
+
const resolved = boardEntity(entity);
|
|
48121
|
+
const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
|
|
48122
|
+
const initialState = str(resolved?.initialState);
|
|
48123
|
+
const entityName = str(resolved?.entityName);
|
|
48124
|
+
const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
|
|
48125
|
+
const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
|
|
48126
|
+
const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
|
|
48127
|
+
const entityVariables = rows(resolved?.variables);
|
|
48128
|
+
const [transitions, setTransitions] = React97.useState(entityTransitions);
|
|
47888
48129
|
const [headerError, setHeaderError] = React97.useState(false);
|
|
47889
48130
|
const [playState, setPlayState] = React97.useState("editing");
|
|
47890
|
-
const [currentState, setCurrentState] = React97.useState(
|
|
48131
|
+
const [currentState, setCurrentState] = React97.useState(initialState);
|
|
47891
48132
|
const [selectedState, setSelectedState] = React97.useState(null);
|
|
47892
48133
|
const [testResults, setTestResults] = React97.useState([]);
|
|
47893
|
-
const [variables, setVariables] = React97.useState(
|
|
48134
|
+
const [variables, setVariables] = React97.useState(() => [...entityVariables]);
|
|
47894
48135
|
const [attempts, setAttempts] = React97.useState(0);
|
|
47895
48136
|
const timerRef = React97.useRef(null);
|
|
47896
48137
|
const [addingFrom, setAddingFrom] = React97.useState(null);
|
|
@@ -47899,12 +48140,12 @@ function StateArchitectBoard({
|
|
|
47899
48140
|
}, []);
|
|
47900
48141
|
const GRAPH_W = 500;
|
|
47901
48142
|
const GRAPH_H = 400;
|
|
47902
|
-
const positions = React97.useMemo(() => layoutStates(
|
|
48143
|
+
const positions = React97.useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
|
|
47903
48144
|
const handleStateClick = React97.useCallback((state) => {
|
|
47904
48145
|
if (playState !== "editing") return;
|
|
47905
48146
|
if (addingFrom) {
|
|
47906
48147
|
if (addingFrom !== state) {
|
|
47907
|
-
const event =
|
|
48148
|
+
const event = availableEvents[0] || "EVENT";
|
|
47908
48149
|
const newTrans = {
|
|
47909
48150
|
id: `t-${nextTransId++}`,
|
|
47910
48151
|
from: addingFrom,
|
|
@@ -47917,7 +48158,7 @@ function StateArchitectBoard({
|
|
|
47917
48158
|
} else {
|
|
47918
48159
|
setSelectedState(state);
|
|
47919
48160
|
}
|
|
47920
|
-
}, [playState, addingFrom,
|
|
48161
|
+
}, [playState, addingFrom, availableEvents]);
|
|
47921
48162
|
const handleStartAddTransition = React97.useCallback(() => {
|
|
47922
48163
|
if (!selectedState) return;
|
|
47923
48164
|
setAddingFrom(selectedState);
|
|
@@ -47926,9 +48167,9 @@ function StateArchitectBoard({
|
|
|
47926
48167
|
setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
|
|
47927
48168
|
}, []);
|
|
47928
48169
|
const machine = React97.useMemo(() => ({
|
|
47929
|
-
name:
|
|
47930
|
-
description: resolved?.description
|
|
47931
|
-
states:
|
|
48170
|
+
name: entityName,
|
|
48171
|
+
description: str(resolved?.description),
|
|
48172
|
+
states: entityStates,
|
|
47932
48173
|
currentState,
|
|
47933
48174
|
transitions: transitions.map((t2) => ({
|
|
47934
48175
|
from: t2.from,
|
|
@@ -47936,7 +48177,7 @@ function StateArchitectBoard({
|
|
|
47936
48177
|
event: t2.event,
|
|
47937
48178
|
guardHint: t2.guardHint
|
|
47938
48179
|
}))
|
|
47939
|
-
}), [resolved, currentState, transitions]);
|
|
48180
|
+
}), [entityName, resolved, entityStates, currentState, transitions]);
|
|
47940
48181
|
const handleTest = React97.useCallback(() => {
|
|
47941
48182
|
if (playState !== "editing") return;
|
|
47942
48183
|
if (testEvent) emit(`UI:${testEvent}`, {});
|
|
@@ -47945,7 +48186,7 @@ function StateArchitectBoard({
|
|
|
47945
48186
|
const results = [];
|
|
47946
48187
|
let testIdx = 0;
|
|
47947
48188
|
const runNextTest = () => {
|
|
47948
|
-
if (testIdx >=
|
|
48189
|
+
if (testIdx >= testCases.length) {
|
|
47949
48190
|
const allPassed = results.every((r2) => r2.passed);
|
|
47950
48191
|
setPlayState(allPassed ? "success" : "fail");
|
|
47951
48192
|
setTestResults(results);
|
|
@@ -47960,9 +48201,9 @@ function StateArchitectBoard({
|
|
|
47960
48201
|
}
|
|
47961
48202
|
return;
|
|
47962
48203
|
}
|
|
47963
|
-
const testCase =
|
|
48204
|
+
const testCase = testCases[testIdx];
|
|
47964
48205
|
if (!testCase) return;
|
|
47965
|
-
let state =
|
|
48206
|
+
let state = initialState;
|
|
47966
48207
|
for (const event of testCase.events) {
|
|
47967
48208
|
const trans = transitions.find((t2) => t2.from === state && t2.event === event);
|
|
47968
48209
|
if (trans) {
|
|
@@ -47980,53 +48221,57 @@ function StateArchitectBoard({
|
|
|
47980
48221
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
47981
48222
|
};
|
|
47982
48223
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
47983
|
-
}, [playState, transitions,
|
|
48224
|
+
}, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
|
|
47984
48225
|
const handleTryAgain = React97.useCallback(() => {
|
|
47985
48226
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
47986
48227
|
setPlayState("editing");
|
|
47987
|
-
setCurrentState(
|
|
48228
|
+
setCurrentState(initialState);
|
|
47988
48229
|
setTestResults([]);
|
|
47989
|
-
}, [
|
|
48230
|
+
}, [initialState]);
|
|
47990
48231
|
const handleReset = React97.useCallback(() => {
|
|
47991
48232
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
47992
|
-
setTransitions(
|
|
48233
|
+
setTransitions(entityTransitions);
|
|
47993
48234
|
setPlayState("editing");
|
|
47994
|
-
setCurrentState(
|
|
48235
|
+
setCurrentState(initialState);
|
|
47995
48236
|
setTestResults([]);
|
|
47996
|
-
setVariables(
|
|
48237
|
+
setVariables([...entityVariables]);
|
|
47997
48238
|
setSelectedState(null);
|
|
47998
48239
|
setAddingFrom(null);
|
|
47999
48240
|
setAttempts(0);
|
|
48000
|
-
}, [
|
|
48241
|
+
}, [entityTransitions, initialState, entityVariables]);
|
|
48001
48242
|
const codeData = React97.useMemo(() => ({
|
|
48002
|
-
name:
|
|
48003
|
-
states:
|
|
48004
|
-
initialState
|
|
48243
|
+
name: entityName,
|
|
48244
|
+
states: entityStates,
|
|
48245
|
+
initialState,
|
|
48005
48246
|
transitions: transitions.map((t2) => ({
|
|
48006
48247
|
from: t2.from,
|
|
48007
48248
|
to: t2.to,
|
|
48008
48249
|
event: t2.event,
|
|
48009
48250
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
48010
48251
|
}))
|
|
48011
|
-
}), [
|
|
48252
|
+
}), [entityName, entityStates, initialState, transitions]);
|
|
48012
48253
|
if (!resolved) return null;
|
|
48254
|
+
const theme = resolved.theme ?? void 0;
|
|
48255
|
+
const themeBackground = theme?.background;
|
|
48256
|
+
const headerImage = str(resolved.headerImage);
|
|
48257
|
+
const hint = str(resolved.hint);
|
|
48013
48258
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
48014
48259
|
VStack,
|
|
48015
48260
|
{
|
|
48016
48261
|
className: cn("p-4 gap-6", className),
|
|
48017
48262
|
style: {
|
|
48018
|
-
backgroundImage:
|
|
48263
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
48019
48264
|
backgroundSize: "cover",
|
|
48020
48265
|
backgroundPosition: "center"
|
|
48021
48266
|
},
|
|
48022
48267
|
children: [
|
|
48023
|
-
|
|
48268
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
48024
48269
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
48025
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
48026
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
48270
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
48271
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
48027
48272
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
48028
48273
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
48029
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children:
|
|
48274
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
|
|
48030
48275
|
] })
|
|
48031
48276
|
] }),
|
|
48032
48277
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
@@ -48074,14 +48319,14 @@ function StateArchitectBoard({
|
|
|
48074
48319
|
]
|
|
48075
48320
|
}
|
|
48076
48321
|
),
|
|
48077
|
-
|
|
48322
|
+
entityStates.map((state) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
48078
48323
|
StateNode2,
|
|
48079
48324
|
{
|
|
48080
48325
|
name: state,
|
|
48081
48326
|
position: positions[state],
|
|
48082
48327
|
isCurrent: state === currentState,
|
|
48083
48328
|
isSelected: state === selectedState,
|
|
48084
|
-
isInitial: state ===
|
|
48329
|
+
isInitial: state === initialState,
|
|
48085
48330
|
onClick: () => handleStateClick(state)
|
|
48086
48331
|
},
|
|
48087
48332
|
state
|
|
@@ -48128,7 +48373,7 @@ function StateArchitectBoard({
|
|
|
48128
48373
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
48129
48374
|
VariablePanel,
|
|
48130
48375
|
{
|
|
48131
|
-
entityName
|
|
48376
|
+
entityName,
|
|
48132
48377
|
variables
|
|
48133
48378
|
}
|
|
48134
48379
|
),
|
|
@@ -48143,12 +48388,12 @@ function StateArchitectBoard({
|
|
|
48143
48388
|
resolved.showCodeView !== false && /* @__PURE__ */ jsxRuntime.jsx(CodeView, { data: codeData, label: "View Code" })
|
|
48144
48389
|
] })
|
|
48145
48390
|
] }),
|
|
48146
|
-
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("stateArchitect.allPassed") }) }),
|
|
48391
|
+
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
|
|
48147
48392
|
playState === "fail" && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
48148
48393
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(ENCOURAGEMENT_KEYS3[Math.min(attempts - 1, ENCOURAGEMENT_KEYS3.length - 1)] ?? ENCOURAGEMENT_KEYS3[0]) }) }),
|
|
48149
|
-
attempts >= 3 &&
|
|
48394
|
+
attempts >= 3 && hint && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
48150
48395
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
48151
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
48396
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
48152
48397
|
] }) })
|
|
48153
48398
|
] }),
|
|
48154
48399
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", children: [
|
|
@@ -48178,6 +48423,7 @@ var init_StateArchitectBoard = __esm({
|
|
|
48178
48423
|
init_TransitionArrow();
|
|
48179
48424
|
init_VariablePanel();
|
|
48180
48425
|
init_CodeView();
|
|
48426
|
+
init_boardEntity();
|
|
48181
48427
|
ENCOURAGEMENT_KEYS3 = [
|
|
48182
48428
|
"puzzle.tryAgain1",
|
|
48183
48429
|
"puzzle.tryAgain2",
|
|
@@ -48214,8 +48460,8 @@ var init_StatsOrganism = __esm({
|
|
|
48214
48460
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
48215
48461
|
}
|
|
48216
48462
|
const stats = items.map((item) => ({
|
|
48217
|
-
value: item.value,
|
|
48218
|
-
label: item.label
|
|
48463
|
+
value: String(item.value ?? ""),
|
|
48464
|
+
label: String(item.label ?? "")
|
|
48219
48465
|
}));
|
|
48220
48466
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
48221
48467
|
StatsGrid,
|
|
@@ -48261,10 +48507,10 @@ var init_StepFlowOrganism = __esm({
|
|
|
48261
48507
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
48262
48508
|
}
|
|
48263
48509
|
const steps = items.map((item) => ({
|
|
48264
|
-
number: item.number,
|
|
48265
|
-
title: item.title,
|
|
48266
|
-
description: item.description,
|
|
48267
|
-
icon: item.icon
|
|
48510
|
+
number: item.number != null ? Number(item.number) : void 0,
|
|
48511
|
+
title: String(item.title ?? ""),
|
|
48512
|
+
description: String(item.description ?? ""),
|
|
48513
|
+
icon: item.icon != null ? String(item.icon) : void 0
|
|
48268
48514
|
}));
|
|
48269
48515
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
48270
48516
|
(heading || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -48437,13 +48683,13 @@ var init_TeamOrganism = __esm({
|
|
|
48437
48683
|
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
48438
48684
|
TeamCard,
|
|
48439
48685
|
{
|
|
48440
|
-
name: member.name,
|
|
48441
|
-
nameAr: member.nameAr,
|
|
48442
|
-
role: member.role,
|
|
48443
|
-
bio: member.bio,
|
|
48444
|
-
avatar: member.avatar
|
|
48686
|
+
name: String(member.name ?? ""),
|
|
48687
|
+
nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
|
|
48688
|
+
role: String(member.role ?? ""),
|
|
48689
|
+
bio: String(member.bio ?? ""),
|
|
48690
|
+
avatar: member.avatar != null ? String(member.avatar) : void 0
|
|
48445
48691
|
},
|
|
48446
|
-
member.id
|
|
48692
|
+
String(member.id ?? "")
|
|
48447
48693
|
)) })
|
|
48448
48694
|
] });
|
|
48449
48695
|
};
|
|
@@ -48680,8 +48926,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48680
48926
|
const [turn, setTurn] = React97.useState(1);
|
|
48681
48927
|
const [gameResult, setGameResult] = React97.useState(null);
|
|
48682
48928
|
const checkGameEnd = React97.useCallback((currentUnits) => {
|
|
48683
|
-
const pa = currentUnits.filter((u) => u
|
|
48684
|
-
const ea = currentUnits.filter((u) => u
|
|
48929
|
+
const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
48930
|
+
const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
48685
48931
|
if (pa.length === 0) {
|
|
48686
48932
|
setGameResult("defeat");
|
|
48687
48933
|
setPhase("game_over");
|
|
@@ -48699,34 +48945,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48699
48945
|
}
|
|
48700
48946
|
}, [onGameEnd, gameEndEvent, eventBus]);
|
|
48701
48947
|
const handleUnitClick = React97.useCallback((unitId) => {
|
|
48702
|
-
const unit = units.find((u) => u.id === unitId);
|
|
48948
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
48703
48949
|
if (!unit) return;
|
|
48704
48950
|
if (unitClickEvent) {
|
|
48705
48951
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
48706
48952
|
}
|
|
48707
48953
|
if (phase === "observation" || phase === "selection") {
|
|
48708
|
-
if (unit
|
|
48954
|
+
if (unitTeam(unit) === "player") {
|
|
48709
48955
|
setSelectedUnitId(unitId);
|
|
48710
48956
|
setPhase("movement");
|
|
48711
48957
|
}
|
|
48712
48958
|
} else if (phase === "action") {
|
|
48713
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
48959
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
48714
48960
|
if (!selectedUnit) return;
|
|
48715
|
-
if (unit
|
|
48716
|
-
const
|
|
48717
|
-
const
|
|
48961
|
+
if (unitTeam(unit) === "enemy") {
|
|
48962
|
+
const up = unitPosition(unit);
|
|
48963
|
+
const sp = unitPosition(selectedUnit);
|
|
48964
|
+
const dx = Math.abs(up.x - sp.x);
|
|
48965
|
+
const dy = Math.abs(up.y - sp.y);
|
|
48718
48966
|
if (dx <= 1 && dy <= 1 && dx + dy > 0) {
|
|
48719
|
-
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
48720
|
-
const newHealth = Math.max(0, unit
|
|
48967
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
48968
|
+
const newHealth = Math.max(0, unitHealth(unit) - damage);
|
|
48721
48969
|
const updatedUnits = units.map(
|
|
48722
|
-
(u) => u.id === unit.id ? { ...u, health: newHealth } : u
|
|
48970
|
+
(u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
|
|
48723
48971
|
);
|
|
48724
48972
|
setUnits(updatedUnits);
|
|
48725
48973
|
onAttack?.(selectedUnit, unit, damage);
|
|
48726
48974
|
if (attackEvent) {
|
|
48727
48975
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
48728
|
-
attackerId: selectedUnit.id,
|
|
48729
|
-
targetId: unit.id,
|
|
48976
|
+
attackerId: str(selectedUnit.id),
|
|
48977
|
+
targetId: str(unit.id),
|
|
48730
48978
|
damage
|
|
48731
48979
|
});
|
|
48732
48980
|
}
|
|
@@ -48743,16 +48991,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48743
48991
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
48744
48992
|
}
|
|
48745
48993
|
if (phase === "movement" && selectedUnitId) {
|
|
48746
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
48994
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
48747
48995
|
if (!selectedUnit) return;
|
|
48748
|
-
const
|
|
48749
|
-
const
|
|
48996
|
+
const sp = unitPosition(selectedUnit);
|
|
48997
|
+
const dx = Math.abs(x - sp.x);
|
|
48998
|
+
const dy = Math.abs(y - sp.y);
|
|
48750
48999
|
const dist = dx + dy;
|
|
48751
|
-
if (dist > 0 && dist <= selectedUnit.movement) {
|
|
48752
|
-
if (!units.some((u) =>
|
|
49000
|
+
if (dist > 0 && dist <= num(selectedUnit.movement)) {
|
|
49001
|
+
if (!units.some((u) => {
|
|
49002
|
+
const p2 = unitPosition(u);
|
|
49003
|
+
return p2.x === x && p2.y === y && unitHealth(u) > 0;
|
|
49004
|
+
})) {
|
|
48753
49005
|
setUnits(
|
|
48754
49006
|
(prev) => prev.map(
|
|
48755
|
-
(u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
49007
|
+
(u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
48756
49008
|
)
|
|
48757
49009
|
);
|
|
48758
49010
|
setPhase("action");
|
|
@@ -48795,12 +49047,13 @@ var init_useBattleState = __esm({
|
|
|
48795
49047
|
"components/game/organisms/hooks/useBattleState.ts"() {
|
|
48796
49048
|
"use client";
|
|
48797
49049
|
init_useEventBus();
|
|
49050
|
+
init_boardEntity();
|
|
48798
49051
|
}
|
|
48799
49052
|
});
|
|
48800
49053
|
function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
48801
|
-
const resolved =
|
|
49054
|
+
const resolved = boardEntity(entity);
|
|
48802
49055
|
const battleState = useBattleState(
|
|
48803
|
-
resolved?.initialUnits
|
|
49056
|
+
rows(resolved?.initialUnits),
|
|
48804
49057
|
{
|
|
48805
49058
|
tileClickEvent: rest.tileClickEvent,
|
|
48806
49059
|
unitClickEvent: rest.unitClickEvent,
|
|
@@ -48836,10 +49089,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
|
48836
49089
|
var init_UncontrolledBattleBoard = __esm({
|
|
48837
49090
|
"components/game/organisms/UncontrolledBattleBoard.tsx"() {
|
|
48838
49091
|
init_BattleBoard();
|
|
49092
|
+
init_boardEntity();
|
|
48839
49093
|
init_useBattleState();
|
|
48840
49094
|
UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
|
|
48841
49095
|
}
|
|
48842
49096
|
});
|
|
49097
|
+
function heroPosition(h) {
|
|
49098
|
+
return vec2(h.position);
|
|
49099
|
+
}
|
|
49100
|
+
function heroOwner(h) {
|
|
49101
|
+
return str(h.owner);
|
|
49102
|
+
}
|
|
49103
|
+
function heroMovement(h) {
|
|
49104
|
+
return num(h.movement);
|
|
49105
|
+
}
|
|
49106
|
+
function hexPassable(h) {
|
|
49107
|
+
return h.passable !== false;
|
|
49108
|
+
}
|
|
48843
49109
|
function defaultIsInRange(from, to, range) {
|
|
48844
49110
|
return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
|
|
48845
49111
|
}
|
|
@@ -48870,36 +49136,36 @@ function WorldMapBoard({
|
|
|
48870
49136
|
className
|
|
48871
49137
|
}) {
|
|
48872
49138
|
const eventBus = useEventBus();
|
|
48873
|
-
const resolved =
|
|
48874
|
-
const hexes = resolved?.hexes
|
|
48875
|
-
const heroes = resolved?.heroes
|
|
48876
|
-
const features = resolved?.features
|
|
48877
|
-
const selectedHeroId = resolved?.selectedHeroId;
|
|
49139
|
+
const resolved = boardEntity(entity);
|
|
49140
|
+
const hexes = rows(resolved?.hexes);
|
|
49141
|
+
const heroes = rows(resolved?.heroes);
|
|
49142
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
49143
|
+
const selectedHeroId = resolved?.selectedHeroId ?? null;
|
|
48878
49144
|
const assetManifest = resolved?.assetManifest;
|
|
48879
49145
|
const backgroundImage = resolved?.backgroundImage;
|
|
48880
49146
|
const [hoveredTile, setHoveredTile] = React97.useState(null);
|
|
48881
49147
|
const selectedHero = React97.useMemo(
|
|
48882
|
-
() => heroes.find((h) => h.id === selectedHeroId) ?? null,
|
|
49148
|
+
() => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
|
|
48883
49149
|
[heroes, selectedHeroId]
|
|
48884
49150
|
);
|
|
48885
49151
|
const tiles = React97.useMemo(
|
|
48886
49152
|
() => hexes.map((hex) => ({
|
|
48887
|
-
x: hex.x,
|
|
48888
|
-
y: hex.y,
|
|
48889
|
-
terrain: hex.terrain,
|
|
48890
|
-
terrainSprite: hex.terrainSprite
|
|
49153
|
+
x: num(hex.x),
|
|
49154
|
+
y: num(hex.y),
|
|
49155
|
+
terrain: str(hex.terrain),
|
|
49156
|
+
terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
|
|
48891
49157
|
})),
|
|
48892
49158
|
[hexes]
|
|
48893
49159
|
);
|
|
48894
49160
|
const baseUnits = React97.useMemo(
|
|
48895
49161
|
() => heroes.map((hero) => ({
|
|
48896
|
-
id: hero.id,
|
|
48897
|
-
position: hero
|
|
48898
|
-
name: hero.name,
|
|
48899
|
-
team: hero
|
|
49162
|
+
id: str(hero.id),
|
|
49163
|
+
position: heroPosition(hero),
|
|
49164
|
+
name: str(hero.name),
|
|
49165
|
+
team: heroOwner(hero) === "enemy" ? "enemy" : "player",
|
|
48900
49166
|
health: 100,
|
|
48901
49167
|
maxHealth: 100,
|
|
48902
|
-
sprite: hero.sprite
|
|
49168
|
+
sprite: hero.sprite == null ? void 0 : str(hero.sprite)
|
|
48903
49169
|
})),
|
|
48904
49170
|
[heroes]
|
|
48905
49171
|
);
|
|
@@ -48940,73 +49206,94 @@ function WorldMapBoard({
|
|
|
48940
49206
|
const isoUnits = React97.useMemo(() => {
|
|
48941
49207
|
if (movingPositions.size === 0) return baseUnits;
|
|
48942
49208
|
return baseUnits.map((u) => {
|
|
48943
|
-
const pos = movingPositions.get(u.id);
|
|
49209
|
+
const pos = u.id == null ? void 0 : movingPositions.get(u.id);
|
|
48944
49210
|
return pos ? { ...u, position: pos } : u;
|
|
48945
49211
|
});
|
|
48946
49212
|
}, [baseUnits, movingPositions]);
|
|
48947
49213
|
const validMoves = React97.useMemo(() => {
|
|
48948
|
-
if (!selectedHero || selectedHero
|
|
49214
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
49215
|
+
const sp = heroPosition(selectedHero);
|
|
49216
|
+
const sOwner = heroOwner(selectedHero);
|
|
49217
|
+
const range = heroMovement(selectedHero);
|
|
48949
49218
|
const moves = [];
|
|
48950
49219
|
hexes.forEach((hex) => {
|
|
48951
|
-
|
|
48952
|
-
|
|
48953
|
-
if (!
|
|
48954
|
-
if (
|
|
48955
|
-
|
|
49220
|
+
const hx = num(hex.x);
|
|
49221
|
+
const hy = num(hex.y);
|
|
49222
|
+
if (!hexPassable(hex)) return;
|
|
49223
|
+
if (hx === sp.x && hy === sp.y) return;
|
|
49224
|
+
if (!isInRange(sp, { x: hx, y: hy }, range)) return;
|
|
49225
|
+
if (heroes.some((h) => {
|
|
49226
|
+
const hp = heroPosition(h);
|
|
49227
|
+
return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
|
|
49228
|
+
})) return;
|
|
49229
|
+
moves.push({ x: hx, y: hy });
|
|
48956
49230
|
});
|
|
48957
49231
|
return moves;
|
|
48958
49232
|
}, [selectedHero, hexes, heroes, isInRange]);
|
|
48959
49233
|
const attackTargets = React97.useMemo(() => {
|
|
48960
|
-
if (!selectedHero || selectedHero
|
|
48961
|
-
|
|
49234
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
49235
|
+
const sp = heroPosition(selectedHero);
|
|
49236
|
+
const sOwner = heroOwner(selectedHero);
|
|
49237
|
+
const range = heroMovement(selectedHero);
|
|
49238
|
+
return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
|
|
48962
49239
|
}, [selectedHero, heroes, isInRange]);
|
|
48963
|
-
const maxY = Math.max(...hexes.map((h) => h.y), 0);
|
|
49240
|
+
const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
|
|
48964
49241
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
48965
49242
|
const tileToScreen = React97.useCallback(
|
|
48966
49243
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
48967
49244
|
[scale, baseOffsetX]
|
|
48968
49245
|
);
|
|
48969
49246
|
const hoveredHex = React97.useMemo(
|
|
48970
|
-
() => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
|
|
49247
|
+
() => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
|
|
48971
49248
|
[hoveredTile, hexes]
|
|
48972
49249
|
);
|
|
48973
49250
|
const hoveredHero = React97.useMemo(
|
|
48974
|
-
() => hoveredTile ? heroes.find((h) =>
|
|
49251
|
+
() => hoveredTile ? heroes.find((h) => {
|
|
49252
|
+
const hp = heroPosition(h);
|
|
49253
|
+
return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
|
|
49254
|
+
}) ?? null : null,
|
|
48975
49255
|
[hoveredTile, heroes]
|
|
48976
49256
|
);
|
|
48977
49257
|
const handleTileClick = React97.useCallback((x, y) => {
|
|
48978
49258
|
if (movementAnimRef.current) return;
|
|
48979
|
-
const hex = hexes.find((h) => h.x === x && h.y === y);
|
|
49259
|
+
const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
|
|
48980
49260
|
if (!hex) return;
|
|
48981
49261
|
if (tileClickEvent) {
|
|
48982
49262
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
48983
49263
|
}
|
|
48984
49264
|
if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
|
|
48985
|
-
|
|
48986
|
-
|
|
49265
|
+
const heroId = str(selectedHero.id);
|
|
49266
|
+
startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
|
|
49267
|
+
onHeroMove?.(heroId, x, y);
|
|
48987
49268
|
if (heroMoveEvent) {
|
|
48988
|
-
eventBus.emit(`UI:${heroMoveEvent}`, { heroId
|
|
49269
|
+
eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
|
|
48989
49270
|
}
|
|
48990
|
-
|
|
48991
|
-
|
|
49271
|
+
const feature = str(hex.feature);
|
|
49272
|
+
if (feature && feature !== "none") {
|
|
49273
|
+
onFeatureEnter?.(heroId, hex);
|
|
48992
49274
|
if (featureEnterEvent) {
|
|
48993
|
-
eventBus.emit(`UI:${featureEnterEvent}`, { heroId
|
|
49275
|
+
eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
|
|
48994
49276
|
}
|
|
48995
49277
|
}
|
|
48996
49278
|
});
|
|
48997
49279
|
return;
|
|
48998
49280
|
}
|
|
48999
|
-
const enemy = heroes.find((h) =>
|
|
49281
|
+
const enemy = heroes.find((h) => {
|
|
49282
|
+
const hp = heroPosition(h);
|
|
49283
|
+
return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
|
|
49284
|
+
});
|
|
49000
49285
|
if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
|
|
49001
|
-
|
|
49286
|
+
const attackerId = str(selectedHero.id);
|
|
49287
|
+
const defenderId = str(enemy.id);
|
|
49288
|
+
onBattleEncounter?.(attackerId, defenderId);
|
|
49002
49289
|
if (battleEncounterEvent) {
|
|
49003
|
-
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId
|
|
49290
|
+
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
|
|
49004
49291
|
}
|
|
49005
49292
|
}
|
|
49006
49293
|
}, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
|
|
49007
49294
|
const handleUnitClick = React97.useCallback((unitId) => {
|
|
49008
|
-
const hero = heroes.find((h) => h.id === unitId);
|
|
49009
|
-
if (hero && (hero
|
|
49295
|
+
const hero = heroes.find((h) => str(h.id) === unitId);
|
|
49296
|
+
if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
|
|
49010
49297
|
onHeroSelect?.(unitId);
|
|
49011
49298
|
if (heroSelectEvent) {
|
|
49012
49299
|
eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
|
|
@@ -49079,6 +49366,7 @@ var init_WorldMapBoard = __esm({
|
|
|
49079
49366
|
init_Stack();
|
|
49080
49367
|
init_LoadingState();
|
|
49081
49368
|
init_IsometricCanvas2();
|
|
49369
|
+
init_boardEntity();
|
|
49082
49370
|
init_isometric();
|
|
49083
49371
|
WorldMapBoard.displayName = "WorldMapBoard";
|
|
49084
49372
|
}
|
|
@@ -52642,10 +52930,10 @@ function parseApplicationLevel(schema) {
|
|
|
52642
52930
|
}
|
|
52643
52931
|
const count = schema.orbitals.length;
|
|
52644
52932
|
const cols = Math.ceil(Math.sqrt(count));
|
|
52645
|
-
const
|
|
52933
|
+
const rows2 = Math.ceil(count / cols);
|
|
52646
52934
|
const spacing = 200;
|
|
52647
52935
|
const gridW = cols * spacing;
|
|
52648
|
-
const gridH =
|
|
52936
|
+
const gridH = rows2 * spacing;
|
|
52649
52937
|
const originX = (600 - gridW) / 2 + spacing / 2;
|
|
52650
52938
|
const originY = (400 - gridH) / 2 + spacing / 2;
|
|
52651
52939
|
schema.orbitals.forEach((orbital, i) => {
|
|
@@ -55787,11 +56075,11 @@ function buildMockData(schema) {
|
|
|
55787
56075
|
result[entityName] = entity.instances;
|
|
55788
56076
|
continue;
|
|
55789
56077
|
}
|
|
55790
|
-
const
|
|
56078
|
+
const rows2 = Array.from(
|
|
55791
56079
|
{ length: 10 },
|
|
55792
56080
|
(_, i) => generateEntityRow(entity, i + 1)
|
|
55793
56081
|
);
|
|
55794
|
-
result[entityName] =
|
|
56082
|
+
result[entityName] = rows2;
|
|
55795
56083
|
}
|
|
55796
56084
|
for (const orbital of schema.orbitals) {
|
|
55797
56085
|
for (const traitRef of orbital.traits ?? []) {
|
|
@@ -59290,18 +59578,18 @@ function layoutOrbitals(count, containerW, containerH) {
|
|
|
59290
59578
|
if (count === 0) return [];
|
|
59291
59579
|
if (count === 1) return [{ cx: containerW / 2, cy: containerH / 2 }];
|
|
59292
59580
|
const cols = Math.min(count, Math.ceil(Math.sqrt(count)));
|
|
59293
|
-
const
|
|
59581
|
+
const rows2 = Math.ceil(count / cols);
|
|
59294
59582
|
const edgePad = 24;
|
|
59295
59583
|
const fitMinCx = UNIT_DISPLAY_W / 2 + edgePad;
|
|
59296
59584
|
const fitMinCy = UNIT_DISPLAY_H / 2 + edgePad;
|
|
59297
59585
|
const fitMaxCx = Math.max(fitMinCx, containerW - UNIT_DISPLAY_W / 2 - edgePad);
|
|
59298
59586
|
const fitMaxCy = Math.max(fitMinCy, containerH - UNIT_DISPLAY_H / 2 - edgePad);
|
|
59299
59587
|
const fitStepX = cols > 1 ? (fitMaxCx - fitMinCx) / (cols - 1) : 0;
|
|
59300
|
-
const fitStepY =
|
|
59588
|
+
const fitStepY = rows2 > 1 ? (fitMaxCy - fitMinCy) / (rows2 - 1) : 0;
|
|
59301
59589
|
const stepX = Math.min(fitStepX, UNIT_DISPLAY_W * 3.5);
|
|
59302
59590
|
const stepY = Math.min(fitStepY, UNIT_DISPLAY_H * 3.5);
|
|
59303
59591
|
const gridW = (cols - 1) * stepX;
|
|
59304
|
-
const gridH = (
|
|
59592
|
+
const gridH = (rows2 - 1) * stepY;
|
|
59305
59593
|
const originX = (containerW - gridW) / 2;
|
|
59306
59594
|
const originY = (containerH - gridH) / 2;
|
|
59307
59595
|
return Array.from({ length: count }, (_, i) => ({
|