@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/runtime/index.js
CHANGED
|
@@ -2454,7 +2454,7 @@ var init_SvgGrid = __esm({
|
|
|
2454
2454
|
x,
|
|
2455
2455
|
y,
|
|
2456
2456
|
cols = 4,
|
|
2457
|
-
rows = 3,
|
|
2457
|
+
rows: rows2 = 3,
|
|
2458
2458
|
spacing = 20,
|
|
2459
2459
|
nodeRadius = 3,
|
|
2460
2460
|
color = "var(--color-primary)",
|
|
@@ -2463,7 +2463,7 @@ var init_SvgGrid = __esm({
|
|
|
2463
2463
|
highlights = []
|
|
2464
2464
|
}) => {
|
|
2465
2465
|
const highlightSet = new Set(highlights);
|
|
2466
|
-
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length:
|
|
2466
|
+
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
|
|
2467
2467
|
(_, row) => Array.from({ length: cols }).map((_2, col) => {
|
|
2468
2468
|
const index = row * cols + col;
|
|
2469
2469
|
const isHighlighted = highlightSet.has(index);
|
|
@@ -3123,7 +3123,7 @@ var init_Input = __esm({
|
|
|
3123
3123
|
onClear,
|
|
3124
3124
|
value,
|
|
3125
3125
|
options,
|
|
3126
|
-
rows = 3,
|
|
3126
|
+
rows: rows2 = 3,
|
|
3127
3127
|
onChange,
|
|
3128
3128
|
...props
|
|
3129
3129
|
}, ref) => {
|
|
@@ -3173,7 +3173,7 @@ var init_Input = __esm({
|
|
|
3173
3173
|
ref,
|
|
3174
3174
|
value,
|
|
3175
3175
|
onChange,
|
|
3176
|
-
rows,
|
|
3176
|
+
rows: rows2,
|
|
3177
3177
|
className: baseClassName,
|
|
3178
3178
|
...props
|
|
3179
3179
|
}
|
|
@@ -5429,66 +5429,6 @@ var init_RangeSlider = __esm({
|
|
|
5429
5429
|
RangeSlider.displayName = "RangeSlider";
|
|
5430
5430
|
}
|
|
5431
5431
|
});
|
|
5432
|
-
function easeOut(t) {
|
|
5433
|
-
return t * (2 - t);
|
|
5434
|
-
}
|
|
5435
|
-
var AnimatedCounter;
|
|
5436
|
-
var init_AnimatedCounter = __esm({
|
|
5437
|
-
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
5438
|
-
"use client";
|
|
5439
|
-
init_cn();
|
|
5440
|
-
init_Typography();
|
|
5441
|
-
AnimatedCounter = ({
|
|
5442
|
-
value: rawValue,
|
|
5443
|
-
duration = 600,
|
|
5444
|
-
prefix,
|
|
5445
|
-
suffix,
|
|
5446
|
-
className
|
|
5447
|
-
}) => {
|
|
5448
|
-
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
5449
|
-
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
5450
|
-
const [displayValue, setDisplayValue] = useState(value);
|
|
5451
|
-
const previousValueRef = useRef(value);
|
|
5452
|
-
const animationFrameRef = useRef(null);
|
|
5453
|
-
useEffect(() => {
|
|
5454
|
-
const from = previousValueRef.current;
|
|
5455
|
-
const to = value;
|
|
5456
|
-
previousValueRef.current = value;
|
|
5457
|
-
if (from === to) {
|
|
5458
|
-
setDisplayValue(to);
|
|
5459
|
-
return;
|
|
5460
|
-
}
|
|
5461
|
-
const startTime = performance.now();
|
|
5462
|
-
const diff = to - from;
|
|
5463
|
-
function animate(currentTime) {
|
|
5464
|
-
const elapsed = currentTime - startTime;
|
|
5465
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
5466
|
-
const easedProgress = easeOut(progress);
|
|
5467
|
-
setDisplayValue(from + diff * easedProgress);
|
|
5468
|
-
if (progress < 1) {
|
|
5469
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5470
|
-
} else {
|
|
5471
|
-
setDisplayValue(to);
|
|
5472
|
-
}
|
|
5473
|
-
}
|
|
5474
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5475
|
-
return () => {
|
|
5476
|
-
if (animationFrameRef.current !== null) {
|
|
5477
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
5478
|
-
}
|
|
5479
|
-
};
|
|
5480
|
-
}, [value, duration]);
|
|
5481
|
-
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
5482
|
-
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
5483
|
-
return /* @__PURE__ */ jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
5484
|
-
prefix,
|
|
5485
|
-
formattedValue,
|
|
5486
|
-
suffix
|
|
5487
|
-
] });
|
|
5488
|
-
};
|
|
5489
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
5490
|
-
}
|
|
5491
|
-
});
|
|
5492
5432
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
5493
5433
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
5494
5434
|
const observerRef = useRef(null);
|
|
@@ -7970,15 +7910,15 @@ function HeaderSkeleton({ className }) {
|
|
|
7970
7910
|
] })
|
|
7971
7911
|
] });
|
|
7972
7912
|
}
|
|
7973
|
-
function TableSkeleton({ rows = 5, columns = 4, className }) {
|
|
7913
|
+
function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
|
|
7974
7914
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
|
|
7975
7915
|
/* @__PURE__ */ jsx(HStack, { className: "px-4 py-3 bg-muted/30 border-b border-border", children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx(SkeletonBlock, { className: "h-4 flex-1 mx-2" }, i)) }),
|
|
7976
|
-
Array.from({ length:
|
|
7916
|
+
Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsx(
|
|
7977
7917
|
HStack,
|
|
7978
7918
|
{
|
|
7979
7919
|
className: cn(
|
|
7980
7920
|
"px-4 py-3",
|
|
7981
|
-
rowIdx <
|
|
7921
|
+
rowIdx < rows2 - 1 && "border-b border-border"
|
|
7982
7922
|
),
|
|
7983
7923
|
children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
|
|
7984
7924
|
},
|
|
@@ -8026,18 +7966,18 @@ function CardSkeleton({ className }) {
|
|
|
8026
7966
|
}
|
|
8027
7967
|
);
|
|
8028
7968
|
}
|
|
8029
|
-
function TextSkeleton({ rows = 3, className }) {
|
|
8030
|
-
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length:
|
|
7969
|
+
function TextSkeleton({ rows: rows2 = 3, className }) {
|
|
7970
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsx(
|
|
8031
7971
|
SkeletonLine,
|
|
8032
7972
|
{
|
|
8033
|
-
className: i ===
|
|
7973
|
+
className: i === rows2 - 1 ? "w-2/3" : "w-full"
|
|
8034
7974
|
},
|
|
8035
7975
|
i
|
|
8036
7976
|
)) });
|
|
8037
7977
|
}
|
|
8038
7978
|
function Skeleton({
|
|
8039
7979
|
variant = "text",
|
|
8040
|
-
rows,
|
|
7980
|
+
rows: rows2,
|
|
8041
7981
|
columns,
|
|
8042
7982
|
fields,
|
|
8043
7983
|
className
|
|
@@ -8047,15 +7987,15 @@ function Skeleton({
|
|
|
8047
7987
|
case "header":
|
|
8048
7988
|
return /* @__PURE__ */ jsx(HeaderSkeleton, { className });
|
|
8049
7989
|
case "table":
|
|
8050
|
-
return /* @__PURE__ */ jsx(TableSkeleton, { rows, columns, className });
|
|
7990
|
+
return /* @__PURE__ */ jsx(TableSkeleton, { rows: rows2, columns, className });
|
|
8051
7991
|
case "form":
|
|
8052
7992
|
return /* @__PURE__ */ jsx(FormSkeleton, { fields, className });
|
|
8053
7993
|
case "card":
|
|
8054
7994
|
return /* @__PURE__ */ jsx(CardSkeleton, { className });
|
|
8055
7995
|
case "text":
|
|
8056
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
7996
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
8057
7997
|
default:
|
|
8058
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
7998
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
8059
7999
|
}
|
|
8060
8000
|
}
|
|
8061
8001
|
var pulseClass;
|
|
@@ -9683,7 +9623,7 @@ var init_MapView = __esm({
|
|
|
9683
9623
|
shadowSize: [41, 41]
|
|
9684
9624
|
});
|
|
9685
9625
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
9686
|
-
const { useEffect: useEffect71, useRef: useRef66, useCallback:
|
|
9626
|
+
const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback114, useState: useState103 } = React84__default;
|
|
9687
9627
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
9688
9628
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
9689
9629
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -9729,7 +9669,7 @@ var init_MapView = __esm({
|
|
|
9729
9669
|
}) {
|
|
9730
9670
|
const eventBus = useEventBus3();
|
|
9731
9671
|
const [clickedPosition, setClickedPosition] = useState103(null);
|
|
9732
|
-
const handleMapClick =
|
|
9672
|
+
const handleMapClick = useCallback114((lat, lng) => {
|
|
9733
9673
|
if (showClickedPin) {
|
|
9734
9674
|
setClickedPosition({ lat, lng });
|
|
9735
9675
|
}
|
|
@@ -9738,7 +9678,7 @@ var init_MapView = __esm({
|
|
|
9738
9678
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
9739
9679
|
}
|
|
9740
9680
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
9741
|
-
const handleMarkerClick =
|
|
9681
|
+
const handleMarkerClick = useCallback114((marker) => {
|
|
9742
9682
|
onMarkerClick?.(marker);
|
|
9743
9683
|
if (markerClickEvent) {
|
|
9744
9684
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -9959,7 +9899,7 @@ function InputPattern({
|
|
|
9959
9899
|
function TextareaPattern({
|
|
9960
9900
|
value = "",
|
|
9961
9901
|
placeholder,
|
|
9962
|
-
rows = 4,
|
|
9902
|
+
rows: rows2 = 4,
|
|
9963
9903
|
disabled = false,
|
|
9964
9904
|
fieldError,
|
|
9965
9905
|
onChange,
|
|
@@ -9979,7 +9919,7 @@ function TextareaPattern({
|
|
|
9979
9919
|
{
|
|
9980
9920
|
value: localValue,
|
|
9981
9921
|
placeholder,
|
|
9982
|
-
rows,
|
|
9922
|
+
rows: rows2,
|
|
9983
9923
|
disabled,
|
|
9984
9924
|
error: fieldError,
|
|
9985
9925
|
onChange: handleChange,
|
|
@@ -10464,6 +10404,91 @@ var init_ActionPalette = __esm({
|
|
|
10464
10404
|
ActionPalette.displayName = "ActionPalette";
|
|
10465
10405
|
}
|
|
10466
10406
|
});
|
|
10407
|
+
function parseValue(value) {
|
|
10408
|
+
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
10409
|
+
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
10410
|
+
if (!match) {
|
|
10411
|
+
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
10412
|
+
}
|
|
10413
|
+
const numStr = match[2];
|
|
10414
|
+
const decimalIdx = numStr.indexOf(".");
|
|
10415
|
+
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
10416
|
+
return {
|
|
10417
|
+
prefix: match[1],
|
|
10418
|
+
num: parseFloat(numStr),
|
|
10419
|
+
suffix: match[3],
|
|
10420
|
+
decimals
|
|
10421
|
+
};
|
|
10422
|
+
}
|
|
10423
|
+
var AnimatedCounter;
|
|
10424
|
+
var init_AnimatedCounter = __esm({
|
|
10425
|
+
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
10426
|
+
"use client";
|
|
10427
|
+
init_cn();
|
|
10428
|
+
init_Box();
|
|
10429
|
+
init_Typography();
|
|
10430
|
+
AnimatedCounter = ({
|
|
10431
|
+
value,
|
|
10432
|
+
label,
|
|
10433
|
+
duration = 1500,
|
|
10434
|
+
className
|
|
10435
|
+
}) => {
|
|
10436
|
+
const ref = useRef(null);
|
|
10437
|
+
const [displayValue, setDisplayValue] = useState("0");
|
|
10438
|
+
const [hasAnimated, setHasAnimated] = useState(false);
|
|
10439
|
+
const animate = useCallback(() => {
|
|
10440
|
+
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
10441
|
+
if (num2 === 0) {
|
|
10442
|
+
setDisplayValue(String(value));
|
|
10443
|
+
return;
|
|
10444
|
+
}
|
|
10445
|
+
const startTime = performance.now();
|
|
10446
|
+
const tick = (now2) => {
|
|
10447
|
+
const elapsed = now2 - startTime;
|
|
10448
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
10449
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
10450
|
+
const current = eased * num2;
|
|
10451
|
+
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
10452
|
+
if (progress < 1) {
|
|
10453
|
+
requestAnimationFrame(tick);
|
|
10454
|
+
} else {
|
|
10455
|
+
setDisplayValue(String(value));
|
|
10456
|
+
}
|
|
10457
|
+
};
|
|
10458
|
+
requestAnimationFrame(tick);
|
|
10459
|
+
}, [value, duration]);
|
|
10460
|
+
useEffect(() => {
|
|
10461
|
+
if (hasAnimated) return;
|
|
10462
|
+
const el = ref.current;
|
|
10463
|
+
if (!el) return;
|
|
10464
|
+
const observer2 = new IntersectionObserver(
|
|
10465
|
+
(entries) => {
|
|
10466
|
+
if (entries[0].isIntersecting) {
|
|
10467
|
+
setHasAnimated(true);
|
|
10468
|
+
animate();
|
|
10469
|
+
observer2.disconnect();
|
|
10470
|
+
}
|
|
10471
|
+
},
|
|
10472
|
+
{ threshold: 0.3 }
|
|
10473
|
+
);
|
|
10474
|
+
observer2.observe(el);
|
|
10475
|
+
return () => observer2.disconnect();
|
|
10476
|
+
}, [hasAnimated, animate]);
|
|
10477
|
+
return /* @__PURE__ */ jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
10478
|
+
/* @__PURE__ */ jsx(
|
|
10479
|
+
Typography,
|
|
10480
|
+
{
|
|
10481
|
+
variant: "h2",
|
|
10482
|
+
className: "text-primary font-bold tabular-nums",
|
|
10483
|
+
children: hasAnimated ? displayValue : "0"
|
|
10484
|
+
}
|
|
10485
|
+
),
|
|
10486
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
10487
|
+
] });
|
|
10488
|
+
};
|
|
10489
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
10490
|
+
}
|
|
10491
|
+
});
|
|
10467
10492
|
var AuthLayout;
|
|
10468
10493
|
var init_AuthLayout = __esm({
|
|
10469
10494
|
"components/core/templates/AuthLayout.tsx"() {
|
|
@@ -11817,6 +11842,39 @@ var init_IsometricCanvas2 = __esm({
|
|
|
11817
11842
|
init_IsometricCanvas();
|
|
11818
11843
|
}
|
|
11819
11844
|
});
|
|
11845
|
+
|
|
11846
|
+
// components/game/organisms/boardEntity.ts
|
|
11847
|
+
function boardEntity(entity) {
|
|
11848
|
+
if (!entity) return void 0;
|
|
11849
|
+
return Array.isArray(entity) ? entity[0] : entity;
|
|
11850
|
+
}
|
|
11851
|
+
function str(v) {
|
|
11852
|
+
return v == null ? "" : String(v);
|
|
11853
|
+
}
|
|
11854
|
+
function num(v, fallback = 0) {
|
|
11855
|
+
const n = Number(v);
|
|
11856
|
+
return Number.isFinite(n) ? n : fallback;
|
|
11857
|
+
}
|
|
11858
|
+
function rows(v) {
|
|
11859
|
+
return Array.isArray(v) ? v : [];
|
|
11860
|
+
}
|
|
11861
|
+
function vec2(v) {
|
|
11862
|
+
const o = v ?? {};
|
|
11863
|
+
return { x: num(o.x), y: num(o.y) };
|
|
11864
|
+
}
|
|
11865
|
+
function unitPosition(u) {
|
|
11866
|
+
return vec2(u.position);
|
|
11867
|
+
}
|
|
11868
|
+
function unitTeam(u) {
|
|
11869
|
+
return str(u.team);
|
|
11870
|
+
}
|
|
11871
|
+
function unitHealth(u) {
|
|
11872
|
+
return num(u.health);
|
|
11873
|
+
}
|
|
11874
|
+
var init_boardEntity = __esm({
|
|
11875
|
+
"components/game/organisms/boardEntity.ts"() {
|
|
11876
|
+
}
|
|
11877
|
+
});
|
|
11820
11878
|
function BattleBoard({
|
|
11821
11879
|
entity,
|
|
11822
11880
|
scale = 0.45,
|
|
@@ -11843,43 +11901,49 @@ function BattleBoard({
|
|
|
11843
11901
|
attackEvent,
|
|
11844
11902
|
className
|
|
11845
11903
|
}) {
|
|
11846
|
-
const
|
|
11847
|
-
const
|
|
11848
|
-
const
|
|
11849
|
-
const
|
|
11850
|
-
const
|
|
11851
|
-
const
|
|
11852
|
-
const
|
|
11853
|
-
const
|
|
11854
|
-
const
|
|
11855
|
-
const
|
|
11856
|
-
const
|
|
11904
|
+
const board = boardEntity(entity) ?? {};
|
|
11905
|
+
const tiles = Array.isArray(board.tiles) ? board.tiles : [];
|
|
11906
|
+
const features = Array.isArray(board.features) ? board.features : [];
|
|
11907
|
+
const boardWidth = num(board.boardWidth, 8);
|
|
11908
|
+
const boardHeight = num(board.boardHeight, 6);
|
|
11909
|
+
const assetManifest = board.assetManifest;
|
|
11910
|
+
const backgroundImage = board.backgroundImage;
|
|
11911
|
+
const units = rows(board.units);
|
|
11912
|
+
const selectedUnitId = board.selectedUnitId ?? null;
|
|
11913
|
+
const currentPhase = str(board.phase) || "observation";
|
|
11914
|
+
const currentTurn = num(board.turn, 1);
|
|
11915
|
+
const gameResult = board.gameResult ?? null;
|
|
11857
11916
|
const eventBus = useEventBus();
|
|
11858
11917
|
const { t } = useTranslate();
|
|
11859
11918
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
11860
11919
|
const [isShaking, setIsShaking] = useState(false);
|
|
11861
11920
|
const selectedUnit = useMemo(
|
|
11862
|
-
() => units.find((u) => u.id === selectedUnitId) ?? null,
|
|
11921
|
+
() => units.find((u) => str(u.id) === selectedUnitId) ?? null,
|
|
11863
11922
|
[units, selectedUnitId]
|
|
11864
11923
|
);
|
|
11865
11924
|
const hoveredUnit = useMemo(() => {
|
|
11866
11925
|
if (!hoveredTile) return null;
|
|
11867
|
-
return units.find(
|
|
11868
|
-
|
|
11869
|
-
|
|
11926
|
+
return units.find((u) => {
|
|
11927
|
+
const p2 = unitPosition(u);
|
|
11928
|
+
return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
|
|
11929
|
+
}) ?? null;
|
|
11870
11930
|
}, [hoveredTile, units]);
|
|
11871
|
-
const playerUnits = useMemo(() => units.filter((u) => u
|
|
11872
|
-
const enemyUnits = useMemo(() => units.filter((u) => u
|
|
11931
|
+
const playerUnits = useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
|
|
11932
|
+
const enemyUnits = useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
|
|
11873
11933
|
const validMoves = useMemo(() => {
|
|
11874
11934
|
if (!selectedUnit || currentPhase !== "movement") return [];
|
|
11875
11935
|
const moves = [];
|
|
11876
|
-
const range = selectedUnit.movement;
|
|
11936
|
+
const range = num(selectedUnit.movement);
|
|
11937
|
+
const origin = unitPosition(selectedUnit);
|
|
11877
11938
|
for (let dy = -range; dy <= range; dy++) {
|
|
11878
11939
|
for (let dx = -range; dx <= range; dx++) {
|
|
11879
|
-
const nx =
|
|
11880
|
-
const ny =
|
|
11940
|
+
const nx = origin.x + dx;
|
|
11941
|
+
const ny = origin.y + dy;
|
|
11881
11942
|
const dist = Math.abs(dx) + Math.abs(dy);
|
|
11882
|
-
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) =>
|
|
11943
|
+
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
|
|
11944
|
+
const p2 = unitPosition(u);
|
|
11945
|
+
return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
|
|
11946
|
+
})) {
|
|
11883
11947
|
moves.push({ x: nx, y: ny });
|
|
11884
11948
|
}
|
|
11885
11949
|
}
|
|
@@ -11888,11 +11952,14 @@ function BattleBoard({
|
|
|
11888
11952
|
}, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
|
|
11889
11953
|
const attackTargets = useMemo(() => {
|
|
11890
11954
|
if (!selectedUnit || currentPhase !== "action") return [];
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11955
|
+
const sp = unitPosition(selectedUnit);
|
|
11956
|
+
const sTeam = unitTeam(selectedUnit);
|
|
11957
|
+
return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
|
|
11958
|
+
const p2 = unitPosition(u);
|
|
11959
|
+
const dx = Math.abs(p2.x - sp.x);
|
|
11960
|
+
const dy = Math.abs(p2.y - sp.y);
|
|
11894
11961
|
return dx <= 1 && dy <= 1 && dx + dy > 0;
|
|
11895
|
-
}).map((u) => u
|
|
11962
|
+
}).map((u) => unitPosition(u));
|
|
11896
11963
|
}, [selectedUnit, currentPhase, units]);
|
|
11897
11964
|
const MOVE_SPEED_MS_PER_TILE = 300;
|
|
11898
11965
|
const movementAnimRef = useRef(null);
|
|
@@ -11932,23 +11999,25 @@ function BattleBoard({
|
|
|
11932
11999
|
return () => clearInterval(interval);
|
|
11933
12000
|
}, []);
|
|
11934
12001
|
const isoUnits = useMemo(() => {
|
|
11935
|
-
return units.filter((u) => u
|
|
11936
|
-
const
|
|
12002
|
+
return units.filter((u) => unitHealth(u) > 0).map((unit) => {
|
|
12003
|
+
const id = str(unit.id);
|
|
12004
|
+
const pos = movingPositions.get(id) ?? unitPosition(unit);
|
|
12005
|
+
const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
|
|
11937
12006
|
return {
|
|
11938
|
-
id
|
|
12007
|
+
id,
|
|
11939
12008
|
position: pos,
|
|
11940
|
-
name: unit.name,
|
|
11941
|
-
team: unit
|
|
11942
|
-
health: unit
|
|
11943
|
-
maxHealth: unit.maxHealth,
|
|
11944
|
-
unitType: unit.unitType,
|
|
11945
|
-
heroId: unit.heroId,
|
|
11946
|
-
sprite: unit.sprite,
|
|
11947
|
-
traits:
|
|
11948
|
-
name:
|
|
11949
|
-
currentState:
|
|
11950
|
-
states:
|
|
11951
|
-
cooldown:
|
|
12009
|
+
name: str(unit.name),
|
|
12010
|
+
team: unitTeam(unit),
|
|
12011
|
+
health: unitHealth(unit),
|
|
12012
|
+
maxHealth: num(unit.maxHealth),
|
|
12013
|
+
unitType: unit.unitType == null ? void 0 : str(unit.unitType),
|
|
12014
|
+
heroId: unit.heroId == null ? void 0 : str(unit.heroId),
|
|
12015
|
+
sprite: unit.sprite == null ? void 0 : str(unit.sprite),
|
|
12016
|
+
traits: unitTraits?.map((tr) => ({
|
|
12017
|
+
name: tr.name,
|
|
12018
|
+
currentState: tr.currentState,
|
|
12019
|
+
states: tr.states,
|
|
12020
|
+
cooldown: tr.cooldown ?? 0
|
|
11952
12021
|
}))
|
|
11953
12022
|
};
|
|
11954
12023
|
});
|
|
@@ -11960,8 +12029,8 @@ function BattleBoard({
|
|
|
11960
12029
|
[scale, baseOffsetX]
|
|
11961
12030
|
);
|
|
11962
12031
|
const checkGameEnd = useCallback(() => {
|
|
11963
|
-
const pa = units.filter((u) => u
|
|
11964
|
-
const ea = units.filter((u) => u
|
|
12032
|
+
const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
12033
|
+
const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
11965
12034
|
if (pa.length === 0) {
|
|
11966
12035
|
onGameEnd?.("defeat");
|
|
11967
12036
|
if (gameEndEvent) {
|
|
@@ -11975,21 +12044,22 @@ function BattleBoard({
|
|
|
11975
12044
|
}
|
|
11976
12045
|
}, [units, onGameEnd, gameEndEvent, eventBus]);
|
|
11977
12046
|
const handleUnitClick = useCallback((unitId) => {
|
|
11978
|
-
const unit = units.find((u) => u.id === unitId);
|
|
12047
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
11979
12048
|
if (!unit) return;
|
|
11980
12049
|
if (unitClickEvent) {
|
|
11981
12050
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
11982
12051
|
}
|
|
11983
12052
|
if (currentPhase === "action" && selectedUnit) {
|
|
11984
|
-
|
|
11985
|
-
|
|
12053
|
+
const up = unitPosition(unit);
|
|
12054
|
+
if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
|
|
12055
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
11986
12056
|
setIsShaking(true);
|
|
11987
12057
|
setTimeout(() => setIsShaking(false), 300);
|
|
11988
12058
|
onAttack?.(selectedUnit, unit, damage);
|
|
11989
12059
|
if (attackEvent) {
|
|
11990
12060
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
11991
|
-
attackerId: selectedUnit.id,
|
|
11992
|
-
targetId: unit.id,
|
|
12061
|
+
attackerId: str(selectedUnit.id),
|
|
12062
|
+
targetId: str(unit.id),
|
|
11993
12063
|
damage
|
|
11994
12064
|
});
|
|
11995
12065
|
}
|
|
@@ -12004,9 +12074,9 @@ function BattleBoard({
|
|
|
12004
12074
|
if (currentPhase === "movement" && selectedUnit) {
|
|
12005
12075
|
if (movementAnimRef.current) return;
|
|
12006
12076
|
if (validMoves.some((m) => m.x === x && m.y === y)) {
|
|
12007
|
-
const from = { ...selectedUnit
|
|
12077
|
+
const from = { ...unitPosition(selectedUnit) };
|
|
12008
12078
|
const to = { x, y };
|
|
12009
|
-
startMoveAnimation(selectedUnit.id, from, to, () => {
|
|
12079
|
+
startMoveAnimation(str(selectedUnit.id), from, to, () => {
|
|
12010
12080
|
onUnitMove?.(selectedUnit, to);
|
|
12011
12081
|
});
|
|
12012
12082
|
}
|
|
@@ -12164,6 +12234,7 @@ var init_BattleBoard = __esm({
|
|
|
12164
12234
|
init_Typography();
|
|
12165
12235
|
init_Stack();
|
|
12166
12236
|
init_IsometricCanvas2();
|
|
12237
|
+
init_boardEntity();
|
|
12167
12238
|
init_isometric();
|
|
12168
12239
|
BattleBoard.displayName = "BattleBoard";
|
|
12169
12240
|
}
|
|
@@ -13386,24 +13457,24 @@ var init_CodeBlock = __esm({
|
|
|
13386
13457
|
return;
|
|
13387
13458
|
}
|
|
13388
13459
|
lineEls.forEach((el) => {
|
|
13389
|
-
const
|
|
13390
|
-
if (hiddenLines.has(
|
|
13460
|
+
const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
|
|
13461
|
+
if (hiddenLines.has(num2)) {
|
|
13391
13462
|
el.style.display = "none";
|
|
13392
13463
|
return;
|
|
13393
13464
|
}
|
|
13394
13465
|
el.style.display = "";
|
|
13395
13466
|
el.style.position = "relative";
|
|
13396
13467
|
el.style.paddingLeft = "1.2em";
|
|
13397
|
-
const region = foldStartMap.get(
|
|
13468
|
+
const region = foldStartMap.get(num2);
|
|
13398
13469
|
if (!region) return;
|
|
13399
|
-
const isCollapsed = collapsed.has(
|
|
13470
|
+
const isCollapsed = collapsed.has(num2);
|
|
13400
13471
|
const toggle = document.createElement("span");
|
|
13401
13472
|
toggle.className = "fold-toggle";
|
|
13402
13473
|
toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
|
|
13403
13474
|
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%";
|
|
13404
13475
|
toggle.addEventListener("click", (e) => {
|
|
13405
13476
|
e.stopPropagation();
|
|
13406
|
-
toggleFoldRef.current(
|
|
13477
|
+
toggleFoldRef.current(num2);
|
|
13407
13478
|
});
|
|
13408
13479
|
el.insertBefore(toggle, el.firstChild);
|
|
13409
13480
|
if (isCollapsed) {
|
|
@@ -15656,10 +15727,13 @@ var init_BookChapterView = __esm({
|
|
|
15656
15727
|
init_cn();
|
|
15657
15728
|
BookChapterView = ({
|
|
15658
15729
|
chapter,
|
|
15730
|
+
orbitalSchema,
|
|
15659
15731
|
direction,
|
|
15660
15732
|
className
|
|
15661
15733
|
}) => {
|
|
15662
15734
|
const { t: _t } = useTranslate();
|
|
15735
|
+
const title = String(chapter.title ?? "");
|
|
15736
|
+
const content = String(chapter.content ?? "");
|
|
15663
15737
|
return /* @__PURE__ */ jsxs(
|
|
15664
15738
|
VStack,
|
|
15665
15739
|
{
|
|
@@ -15667,16 +15741,16 @@ var init_BookChapterView = __esm({
|
|
|
15667
15741
|
className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
|
|
15668
15742
|
style: { direction },
|
|
15669
15743
|
children: [
|
|
15670
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children:
|
|
15744
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
|
|
15671
15745
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
15672
|
-
!!
|
|
15746
|
+
!!orbitalSchema && /* @__PURE__ */ jsx(ScaledDiagram, { children: /* @__PURE__ */ jsx(
|
|
15673
15747
|
JazariStateMachine,
|
|
15674
15748
|
{
|
|
15675
|
-
schema:
|
|
15749
|
+
schema: orbitalSchema,
|
|
15676
15750
|
direction
|
|
15677
15751
|
}
|
|
15678
15752
|
) }),
|
|
15679
|
-
/* @__PURE__ */ jsx(ContentRenderer, { content
|
|
15753
|
+
/* @__PURE__ */ jsx(ContentRenderer, { content, direction })
|
|
15680
15754
|
]
|
|
15681
15755
|
}
|
|
15682
15756
|
);
|
|
@@ -15774,7 +15848,7 @@ var init_BookNavBar = __esm({
|
|
|
15774
15848
|
BookNavBar = ({
|
|
15775
15849
|
currentPage,
|
|
15776
15850
|
totalPages,
|
|
15777
|
-
chapterTitle,
|
|
15851
|
+
chapterTitle: chapterTitle2,
|
|
15778
15852
|
direction,
|
|
15779
15853
|
className
|
|
15780
15854
|
}) => {
|
|
@@ -15815,12 +15889,12 @@ var init_BookNavBar = __esm({
|
|
|
15815
15889
|
)
|
|
15816
15890
|
] }),
|
|
15817
15891
|
/* @__PURE__ */ jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
|
|
15818
|
-
|
|
15892
|
+
chapterTitle2 && /* @__PURE__ */ jsx(
|
|
15819
15893
|
Typography,
|
|
15820
15894
|
{
|
|
15821
15895
|
variant: "caption",
|
|
15822
15896
|
className: "text-center block truncate text-muted-foreground",
|
|
15823
|
-
children:
|
|
15897
|
+
children: chapterTitle2
|
|
15824
15898
|
}
|
|
15825
15899
|
),
|
|
15826
15900
|
/* @__PURE__ */ jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
|
|
@@ -15887,31 +15961,35 @@ var init_BookTableOfContents = __esm({
|
|
|
15887
15961
|
style: { direction },
|
|
15888
15962
|
children: [
|
|
15889
15963
|
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
|
|
15890
|
-
parts.map((part, partIdx) =>
|
|
15891
|
-
|
|
15892
|
-
|
|
15893
|
-
/* @__PURE__ */
|
|
15894
|
-
|
|
15895
|
-
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
|
|
15900
|
-
|
|
15901
|
-
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
|
|
15907
|
-
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
|
|
15911
|
-
|
|
15912
|
-
|
|
15913
|
-
|
|
15914
|
-
|
|
15964
|
+
parts.map((part, partIdx) => {
|
|
15965
|
+
const chapters = Array.isArray(part.chapters) ? part.chapters : [];
|
|
15966
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
15967
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
|
|
15968
|
+
/* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
|
|
15969
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
|
|
15970
|
+
] }),
|
|
15971
|
+
/* @__PURE__ */ jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
|
|
15972
|
+
const id = chapter.id == null ? "" : String(chapter.id);
|
|
15973
|
+
const isCurrent = id === currentChapterId;
|
|
15974
|
+
return /* @__PURE__ */ jsx(
|
|
15975
|
+
Button,
|
|
15976
|
+
{
|
|
15977
|
+
variant: "ghost",
|
|
15978
|
+
size: "sm",
|
|
15979
|
+
action: "BOOK_NAVIGATE",
|
|
15980
|
+
actionPayload: { chapterId: id },
|
|
15981
|
+
className: cn(
|
|
15982
|
+
"justify-start text-left w-full",
|
|
15983
|
+
direction === "rtl" && "text-right",
|
|
15984
|
+
isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
|
|
15985
|
+
),
|
|
15986
|
+
children: /* @__PURE__ */ jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
|
|
15987
|
+
},
|
|
15988
|
+
id
|
|
15989
|
+
);
|
|
15990
|
+
}) })
|
|
15991
|
+
] }, partIdx);
|
|
15992
|
+
})
|
|
15915
15993
|
]
|
|
15916
15994
|
}
|
|
15917
15995
|
);
|
|
@@ -16033,27 +16111,41 @@ function resolveFieldMap(fieldMap) {
|
|
|
16033
16111
|
function get(obj, key) {
|
|
16034
16112
|
return obj[key];
|
|
16035
16113
|
}
|
|
16114
|
+
function asStr(v) {
|
|
16115
|
+
return v == null ? "" : String(v);
|
|
16116
|
+
}
|
|
16036
16117
|
function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
|
|
16037
16118
|
const rawParts = get(raw, fields.parts) ?? [];
|
|
16038
|
-
|
|
16039
|
-
|
|
16040
|
-
|
|
16041
|
-
|
|
16042
|
-
|
|
16043
|
-
|
|
16044
|
-
|
|
16045
|
-
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16046
|
-
return {
|
|
16047
|
-
title: get(part, fields.partTitle) ?? "",
|
|
16048
|
-
chapters: rawChapters.map((ch) => ({
|
|
16049
|
-
id: get(ch, fields.chapterId) ?? "",
|
|
16050
|
-
title: get(ch, fields.chapterTitle) ?? "",
|
|
16051
|
-
content: get(ch, fields.chapterContent) ?? "",
|
|
16052
|
-
orbitalSchema: get(ch, fields.chapterOrbitalSchema)
|
|
16053
|
-
}))
|
|
16054
|
-
};
|
|
16055
|
-
})
|
|
16119
|
+
const direction = get(raw, fields.direction) ?? "ltr";
|
|
16120
|
+
const cover = {
|
|
16121
|
+
title: asStr(get(raw, fields.title)),
|
|
16122
|
+
subtitle: asStr(get(raw, fields.subtitle)),
|
|
16123
|
+
author: asStr(get(raw, fields.author)),
|
|
16124
|
+
coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
|
|
16125
|
+
direction
|
|
16056
16126
|
};
|
|
16127
|
+
const schemaByChapterId = {};
|
|
16128
|
+
const chapters = [];
|
|
16129
|
+
const parts = rawParts.map((part) => {
|
|
16130
|
+
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16131
|
+
const chapterRows = rawChapters.map((ch) => {
|
|
16132
|
+
const id = asStr(get(ch, fields.chapterId));
|
|
16133
|
+
const schema = get(ch, fields.chapterOrbitalSchema);
|
|
16134
|
+
if (schema) schemaByChapterId[id] = schema;
|
|
16135
|
+
const row = {
|
|
16136
|
+
id,
|
|
16137
|
+
title: asStr(get(ch, fields.chapterTitle)),
|
|
16138
|
+
content: asStr(get(ch, fields.chapterContent))
|
|
16139
|
+
};
|
|
16140
|
+
chapters.push(row);
|
|
16141
|
+
return row;
|
|
16142
|
+
});
|
|
16143
|
+
return {
|
|
16144
|
+
title: asStr(get(part, fields.partTitle)),
|
|
16145
|
+
chapters: chapterRows
|
|
16146
|
+
};
|
|
16147
|
+
});
|
|
16148
|
+
return { cover, direction, parts, chapters, schemaByChapterId };
|
|
16057
16149
|
}
|
|
16058
16150
|
var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
|
|
16059
16151
|
var init_types2 = __esm({
|
|
@@ -16091,10 +16183,7 @@ var init_types2 = __esm({
|
|
|
16091
16183
|
};
|
|
16092
16184
|
}
|
|
16093
16185
|
});
|
|
16094
|
-
|
|
16095
|
-
return book.parts.flatMap((part) => part.chapters);
|
|
16096
|
-
}
|
|
16097
|
-
var PRINT_STYLES, BookViewer;
|
|
16186
|
+
var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
|
|
16098
16187
|
var init_BookViewer = __esm({
|
|
16099
16188
|
"components/marketing/organisms/book/BookViewer.tsx"() {
|
|
16100
16189
|
init_Box();
|
|
@@ -16107,6 +16196,8 @@ var init_BookViewer = __esm({
|
|
|
16107
16196
|
init_BookNavBar();
|
|
16108
16197
|
init_EmptyState();
|
|
16109
16198
|
init_types2();
|
|
16199
|
+
chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
|
|
16200
|
+
chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
|
|
16110
16201
|
PRINT_STYLES = `
|
|
16111
16202
|
@media print {
|
|
16112
16203
|
.book-viewer-page {
|
|
@@ -16135,14 +16226,14 @@ var init_BookViewer = __esm({
|
|
|
16135
16226
|
return mapBookData(raw, resolvedFieldMap);
|
|
16136
16227
|
}, [entity, resolvedFieldMap]);
|
|
16137
16228
|
const direction = book?.direction ?? "ltr";
|
|
16138
|
-
const chapters = useMemo(() => book ?
|
|
16229
|
+
const chapters = useMemo(() => book ? book.chapters : [], [book]);
|
|
16139
16230
|
const totalPages = 2 + chapters.length;
|
|
16140
16231
|
const navigateTo = useCallback(
|
|
16141
16232
|
(page) => {
|
|
16142
16233
|
const clamped = Math.max(0, Math.min(page, totalPages - 1));
|
|
16143
16234
|
setCurrentPage(clamped);
|
|
16144
|
-
const
|
|
16145
|
-
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
|
|
16235
|
+
const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
|
|
16236
|
+
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
|
|
16146
16237
|
},
|
|
16147
16238
|
[totalPages, chapters, eventBus]
|
|
16148
16239
|
);
|
|
@@ -16154,8 +16245,8 @@ var init_BookViewer = __esm({
|
|
|
16154
16245
|
eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
|
|
16155
16246
|
eventBus.on("UI:BOOK_PRINT", () => window.print()),
|
|
16156
16247
|
eventBus.on("UI:BOOK_NAVIGATE", (event) => {
|
|
16157
|
-
const
|
|
16158
|
-
const idx = chapters.findIndex((ch) => ch
|
|
16248
|
+
const targetId = event.payload?.chapterId;
|
|
16249
|
+
const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
|
|
16159
16250
|
if (idx >= 0) navigateTo(idx + 2);
|
|
16160
16251
|
})
|
|
16161
16252
|
];
|
|
@@ -16172,9 +16263,11 @@ var init_BookViewer = __esm({
|
|
|
16172
16263
|
style.remove();
|
|
16173
16264
|
};
|
|
16174
16265
|
}, []);
|
|
16175
|
-
const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16176
|
-
const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16266
|
+
const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
|
|
16267
|
+
const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
|
|
16177
16268
|
if (!book) return /* @__PURE__ */ jsx(EmptyState, { message: t("book.noData") });
|
|
16269
|
+
const cover = book.cover;
|
|
16270
|
+
const coverTitle = String(cover.title ?? "");
|
|
16178
16271
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
|
|
16179
16272
|
/* @__PURE__ */ jsxs(
|
|
16180
16273
|
Box,
|
|
@@ -16186,10 +16279,10 @@ var init_BookViewer = __esm({
|
|
|
16186
16279
|
/* @__PURE__ */ jsx(
|
|
16187
16280
|
BookCoverPage,
|
|
16188
16281
|
{
|
|
16189
|
-
title:
|
|
16190
|
-
subtitle:
|
|
16191
|
-
author:
|
|
16192
|
-
coverImageUrl:
|
|
16282
|
+
title: coverTitle,
|
|
16283
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16284
|
+
author: String(cover.author ?? "") || void 0,
|
|
16285
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16193
16286
|
direction
|
|
16194
16287
|
}
|
|
16195
16288
|
),
|
|
@@ -16200,23 +16293,27 @@ var init_BookViewer = __esm({
|
|
|
16200
16293
|
direction
|
|
16201
16294
|
}
|
|
16202
16295
|
),
|
|
16203
|
-
chapters.map((chapter) =>
|
|
16204
|
-
|
|
16205
|
-
|
|
16206
|
-
|
|
16207
|
-
|
|
16208
|
-
|
|
16209
|
-
|
|
16210
|
-
|
|
16296
|
+
chapters.map((chapter) => {
|
|
16297
|
+
const id = chapterId(chapter);
|
|
16298
|
+
return /* @__PURE__ */ jsx(
|
|
16299
|
+
BookChapterView,
|
|
16300
|
+
{
|
|
16301
|
+
chapter,
|
|
16302
|
+
orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
|
|
16303
|
+
direction
|
|
16304
|
+
},
|
|
16305
|
+
id
|
|
16306
|
+
);
|
|
16307
|
+
})
|
|
16211
16308
|
] }),
|
|
16212
16309
|
/* @__PURE__ */ jsxs(Box, { className: "print:hidden", children: [
|
|
16213
16310
|
currentPage === 0 && /* @__PURE__ */ jsx(
|
|
16214
16311
|
BookCoverPage,
|
|
16215
16312
|
{
|
|
16216
|
-
title:
|
|
16217
|
-
subtitle:
|
|
16218
|
-
author:
|
|
16219
|
-
coverImageUrl:
|
|
16313
|
+
title: coverTitle,
|
|
16314
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16315
|
+
author: String(cover.author ?? "") || void 0,
|
|
16316
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16220
16317
|
direction
|
|
16221
16318
|
}
|
|
16222
16319
|
),
|
|
@@ -16232,6 +16329,7 @@ var init_BookViewer = __esm({
|
|
|
16232
16329
|
BookChapterView,
|
|
16233
16330
|
{
|
|
16234
16331
|
chapter: chapters[currentPage - 2],
|
|
16332
|
+
orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
|
|
16235
16333
|
direction
|
|
16236
16334
|
}
|
|
16237
16335
|
)
|
|
@@ -16244,7 +16342,7 @@ var init_BookViewer = __esm({
|
|
|
16244
16342
|
{
|
|
16245
16343
|
currentPage,
|
|
16246
16344
|
totalPages,
|
|
16247
|
-
chapterTitle: currentPage === 0 ?
|
|
16345
|
+
chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
|
|
16248
16346
|
direction
|
|
16249
16347
|
}
|
|
16250
16348
|
)
|
|
@@ -16342,7 +16440,7 @@ var init_Grid = __esm({
|
|
|
16342
16440
|
};
|
|
16343
16441
|
Grid = ({
|
|
16344
16442
|
cols = 1,
|
|
16345
|
-
rows,
|
|
16443
|
+
rows: rows2,
|
|
16346
16444
|
gap = "md",
|
|
16347
16445
|
rowGap,
|
|
16348
16446
|
colGap,
|
|
@@ -16354,7 +16452,7 @@ var init_Grid = __esm({
|
|
|
16354
16452
|
children,
|
|
16355
16453
|
as: Component = "div"
|
|
16356
16454
|
}) => {
|
|
16357
|
-
const mergedStyle =
|
|
16455
|
+
const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
|
|
16358
16456
|
return React84__default.createElement(
|
|
16359
16457
|
Component,
|
|
16360
16458
|
{
|
|
@@ -17070,14 +17168,14 @@ function BuilderBoard({
|
|
|
17070
17168
|
}) {
|
|
17071
17169
|
const { emit } = useEventBus();
|
|
17072
17170
|
const { t } = useTranslate();
|
|
17073
|
-
const resolved =
|
|
17171
|
+
const resolved = boardEntity(entity);
|
|
17074
17172
|
const [placements, setPlacements] = useState({});
|
|
17075
17173
|
const [headerError, setHeaderError] = useState(false);
|
|
17076
17174
|
const [submitted, setSubmitted] = useState(false);
|
|
17077
17175
|
const [attempts, setAttempts] = useState(0);
|
|
17078
17176
|
const [showHint, setShowHint] = useState(false);
|
|
17079
|
-
const components = resolved?.components
|
|
17080
|
-
const slots = resolved?.slots
|
|
17177
|
+
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
17178
|
+
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
17081
17179
|
const usedComponentIds = new Set(Object.values(placements));
|
|
17082
17180
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
17083
17181
|
const [selectedComponent, setSelectedComponent] = useState(null);
|
|
@@ -17111,7 +17209,7 @@ function BuilderBoard({
|
|
|
17111
17209
|
}, [slots, placements, attempts, completeEvent, emit]);
|
|
17112
17210
|
const handleReset = () => {
|
|
17113
17211
|
setSubmitted(false);
|
|
17114
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
17212
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
17115
17213
|
setShowHint(true);
|
|
17116
17214
|
}
|
|
17117
17215
|
};
|
|
@@ -17124,20 +17222,24 @@ function BuilderBoard({
|
|
|
17124
17222
|
};
|
|
17125
17223
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
17126
17224
|
if (!resolved) return null;
|
|
17225
|
+
const theme = resolved.theme ?? void 0;
|
|
17226
|
+
const themeBackground = theme?.background;
|
|
17227
|
+
const headerImage = str(resolved.headerImage);
|
|
17228
|
+
const hint = str(resolved.hint);
|
|
17127
17229
|
return /* @__PURE__ */ jsx(
|
|
17128
17230
|
Box,
|
|
17129
17231
|
{
|
|
17130
17232
|
className,
|
|
17131
17233
|
style: {
|
|
17132
|
-
backgroundImage:
|
|
17234
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
17133
17235
|
backgroundSize: "cover",
|
|
17134
17236
|
backgroundPosition: "center"
|
|
17135
17237
|
},
|
|
17136
17238
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
17137
|
-
|
|
17239
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
17138
17240
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
17139
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
17140
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
17241
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
17242
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
17141
17243
|
] }) }),
|
|
17142
17244
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
17143
17245
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
|
|
@@ -17197,9 +17299,9 @@ function BuilderBoard({
|
|
|
17197
17299
|
] }) }),
|
|
17198
17300
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
17199
17301
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
17200
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
17302
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
|
|
17201
17303
|
] }) }),
|
|
17202
|
-
showHint &&
|
|
17304
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
17203
17305
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
17204
17306
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
17205
17307
|
/* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
|
|
@@ -17218,6 +17320,7 @@ var init_BuilderBoard = __esm({
|
|
|
17218
17320
|
"components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
|
|
17219
17321
|
init_atoms2();
|
|
17220
17322
|
init_useEventBus();
|
|
17323
|
+
init_boardEntity();
|
|
17221
17324
|
BuilderBoard.displayName = "BuilderBoard";
|
|
17222
17325
|
}
|
|
17223
17326
|
});
|
|
@@ -17555,21 +17658,24 @@ function CalendarGrid({
|
|
|
17555
17658
|
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
17556
17659
|
}, 500);
|
|
17557
17660
|
}, [longPressEvent, longPressPayload, eventBus]);
|
|
17558
|
-
const renderEvent = (event) =>
|
|
17559
|
-
|
|
17560
|
-
|
|
17561
|
-
|
|
17562
|
-
|
|
17563
|
-
|
|
17564
|
-
|
|
17565
|
-
|
|
17566
|
-
|
|
17567
|
-
|
|
17568
|
-
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
17661
|
+
const renderEvent = (event) => {
|
|
17662
|
+
const color = event.color;
|
|
17663
|
+
return /* @__PURE__ */ jsx(
|
|
17664
|
+
Box,
|
|
17665
|
+
{
|
|
17666
|
+
rounded: "md",
|
|
17667
|
+
padding: "xs",
|
|
17668
|
+
border: true,
|
|
17669
|
+
className: cn(
|
|
17670
|
+
"cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
|
|
17671
|
+
color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
|
|
17672
|
+
),
|
|
17673
|
+
onClick: (e) => handleEventClick(event, e),
|
|
17674
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
|
|
17675
|
+
},
|
|
17676
|
+
event.id
|
|
17677
|
+
);
|
|
17678
|
+
};
|
|
17573
17679
|
return /* @__PURE__ */ jsxs(
|
|
17574
17680
|
Box,
|
|
17575
17681
|
{
|
|
@@ -19233,7 +19339,6 @@ var init_CardGrid = __esm({
|
|
|
19233
19339
|
alignItems = "stretch",
|
|
19234
19340
|
className,
|
|
19235
19341
|
children,
|
|
19236
|
-
// EntityDisplayProps
|
|
19237
19342
|
entity,
|
|
19238
19343
|
isLoading = false,
|
|
19239
19344
|
error = null,
|
|
@@ -19705,14 +19810,14 @@ var init_CaseStudyOrganism = __esm({
|
|
|
19705
19810
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsx(
|
|
19706
19811
|
CaseStudyCard,
|
|
19707
19812
|
{
|
|
19708
|
-
title: study.title,
|
|
19709
|
-
description: study.description,
|
|
19710
|
-
category: study.category,
|
|
19711
|
-
categoryColor: study.categoryColor,
|
|
19712
|
-
href: study.href,
|
|
19713
|
-
linkLabel: study.linkLabel
|
|
19813
|
+
title: String(study.title ?? ""),
|
|
19814
|
+
description: String(study.description ?? ""),
|
|
19815
|
+
category: String(study.category ?? ""),
|
|
19816
|
+
categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
|
|
19817
|
+
href: String(study.href ?? ""),
|
|
19818
|
+
linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
|
|
19714
19819
|
},
|
|
19715
|
-
study.id
|
|
19820
|
+
String(study.id ?? "")
|
|
19716
19821
|
)) })
|
|
19717
19822
|
] });
|
|
19718
19823
|
};
|
|
@@ -19735,10 +19840,10 @@ function CastleBoard({
|
|
|
19735
19840
|
className
|
|
19736
19841
|
}) {
|
|
19737
19842
|
const eventBus = useEventBus();
|
|
19738
|
-
const resolved =
|
|
19739
|
-
const tiles = resolved?.tiles
|
|
19740
|
-
const features = resolved?.features
|
|
19741
|
-
const units = resolved?.units
|
|
19843
|
+
const resolved = boardEntity(entity);
|
|
19844
|
+
const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
|
|
19845
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
19846
|
+
const units = Array.isArray(resolved?.units) ? resolved.units : [];
|
|
19742
19847
|
const assetManifest = resolved?.assetManifest;
|
|
19743
19848
|
const backgroundImage = resolved?.backgroundImage;
|
|
19744
19849
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
@@ -19766,7 +19871,7 @@ function CastleBoard({
|
|
|
19766
19871
|
onFeatureClick?.(feature);
|
|
19767
19872
|
if (featureClickEvent) {
|
|
19768
19873
|
eventBus.emit(`UI:${featureClickEvent}`, {
|
|
19769
|
-
featureId: feature.id,
|
|
19874
|
+
featureId: feature.id ?? "",
|
|
19770
19875
|
featureType: feature.type,
|
|
19771
19876
|
x: feature.x,
|
|
19772
19877
|
y: feature.y
|
|
@@ -19834,6 +19939,7 @@ var init_CastleBoard = __esm({
|
|
|
19834
19939
|
init_cn();
|
|
19835
19940
|
init_useEventBus();
|
|
19836
19941
|
init_IsometricCanvas2();
|
|
19942
|
+
init_boardEntity();
|
|
19837
19943
|
init_isometric();
|
|
19838
19944
|
CastleBoard.displayName = "CastleBoard";
|
|
19839
19945
|
}
|
|
@@ -20644,14 +20750,14 @@ function ClassifierBoard({
|
|
|
20644
20750
|
}) {
|
|
20645
20751
|
const { emit } = useEventBus();
|
|
20646
20752
|
const { t } = useTranslate();
|
|
20647
|
-
const resolved =
|
|
20753
|
+
const resolved = boardEntity(entity);
|
|
20648
20754
|
const [assignments, setAssignments] = useState({});
|
|
20649
20755
|
const [headerError, setHeaderError] = useState(false);
|
|
20650
20756
|
const [submitted, setSubmitted] = useState(false);
|
|
20651
20757
|
const [attempts, setAttempts] = useState(0);
|
|
20652
20758
|
const [showHint, setShowHint] = useState(false);
|
|
20653
|
-
const items = resolved?.items
|
|
20654
|
-
const categories = resolved?.categories
|
|
20759
|
+
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
20760
|
+
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
20655
20761
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
20656
20762
|
const allAssigned = Object.keys(assignments).length === items.length;
|
|
20657
20763
|
const results = submitted ? items.map((item) => ({
|
|
@@ -20683,7 +20789,7 @@ function ClassifierBoard({
|
|
|
20683
20789
|
}, [items, assignments, attempts, completeEvent, emit]);
|
|
20684
20790
|
const handleReset = () => {
|
|
20685
20791
|
setSubmitted(false);
|
|
20686
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
20792
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
20687
20793
|
setShowHint(true);
|
|
20688
20794
|
}
|
|
20689
20795
|
};
|
|
@@ -20694,20 +20800,25 @@ function ClassifierBoard({
|
|
|
20694
20800
|
setShowHint(false);
|
|
20695
20801
|
};
|
|
20696
20802
|
if (!resolved) return null;
|
|
20803
|
+
const theme = resolved.theme ?? void 0;
|
|
20804
|
+
const themeBackground = theme?.background;
|
|
20805
|
+
const headerImage = str(resolved.headerImage);
|
|
20806
|
+
const hint = str(resolved.hint);
|
|
20807
|
+
const failMessage = str(resolved.failMessage);
|
|
20697
20808
|
return /* @__PURE__ */ jsx(
|
|
20698
20809
|
Box,
|
|
20699
20810
|
{
|
|
20700
20811
|
className,
|
|
20701
20812
|
style: {
|
|
20702
|
-
backgroundImage:
|
|
20813
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
20703
20814
|
backgroundSize: "cover",
|
|
20704
20815
|
backgroundPosition: "center"
|
|
20705
20816
|
},
|
|
20706
20817
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
20707
|
-
|
|
20818
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
20708
20819
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20709
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
20710
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
20820
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
20821
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
20711
20822
|
] }) }),
|
|
20712
20823
|
unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20713
20824
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
|
|
@@ -20759,10 +20870,10 @@ function ClassifierBoard({
|
|
|
20759
20870
|
}) }),
|
|
20760
20871
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
20761
20872
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
20762
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
20763
|
-
!allCorrect &&
|
|
20873
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
|
|
20874
|
+
!allCorrect && failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
|
|
20764
20875
|
] }) }),
|
|
20765
|
-
showHint &&
|
|
20876
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
20766
20877
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
20767
20878
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
20768
20879
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -20781,6 +20892,7 @@ var init_ClassifierBoard = __esm({
|
|
|
20781
20892
|
"components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
|
|
20782
20893
|
init_atoms2();
|
|
20783
20894
|
init_useEventBus();
|
|
20895
|
+
init_boardEntity();
|
|
20784
20896
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
20785
20897
|
}
|
|
20786
20898
|
});
|
|
@@ -27151,7 +27263,7 @@ function InventoryPanel({
|
|
|
27151
27263
|
const slotArray = Array.from({ length: safeSlots }, (_, index) => {
|
|
27152
27264
|
return safeItems[index] ?? null;
|
|
27153
27265
|
});
|
|
27154
|
-
const
|
|
27266
|
+
const rows2 = Math.ceil(safeSlots / safeColumns);
|
|
27155
27267
|
const handleSlotClick = useCallback((index) => {
|
|
27156
27268
|
if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
|
|
27157
27269
|
onSelectSlot?.(index);
|
|
@@ -27220,7 +27332,7 @@ function InventoryPanel({
|
|
|
27220
27332
|
className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
|
|
27221
27333
|
style: {
|
|
27222
27334
|
gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
|
|
27223
|
-
gridTemplateRows: `repeat(${
|
|
27335
|
+
gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
|
|
27224
27336
|
},
|
|
27225
27337
|
children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
|
|
27226
27338
|
"button",
|
|
@@ -31184,11 +31296,11 @@ function LatticeSVG({
|
|
|
31184
31296
|
}) {
|
|
31185
31297
|
const paths = [];
|
|
31186
31298
|
const cols = 5;
|
|
31187
|
-
const
|
|
31299
|
+
const rows2 = Math.ceil(h / (w / cols));
|
|
31188
31300
|
const cellW = w / cols;
|
|
31189
31301
|
const cellH = cellW;
|
|
31190
31302
|
const bulge = cellW * 0.3;
|
|
31191
|
-
for (let row = 0; row <
|
|
31303
|
+
for (let row = 0; row < rows2; row++) {
|
|
31192
31304
|
for (let col = 0; col < cols; col++) {
|
|
31193
31305
|
const cx = col * cellW + cellW / 2;
|
|
31194
31306
|
const cy = row * cellH + cellH / 2;
|
|
@@ -31600,7 +31712,7 @@ var init_MatrixQuestion = __esm({
|
|
|
31600
31712
|
};
|
|
31601
31713
|
MatrixQuestion = ({
|
|
31602
31714
|
title,
|
|
31603
|
-
rows,
|
|
31715
|
+
rows: rows2,
|
|
31604
31716
|
columns = DEFAULT_MATRIX_COLUMNS,
|
|
31605
31717
|
values,
|
|
31606
31718
|
onChange,
|
|
@@ -31610,7 +31722,7 @@ var init_MatrixQuestion = __esm({
|
|
|
31610
31722
|
className
|
|
31611
31723
|
}) => {
|
|
31612
31724
|
const styles = sizeStyles13[size];
|
|
31613
|
-
const safeRows =
|
|
31725
|
+
const safeRows = rows2 ?? [];
|
|
31614
31726
|
const safeValues = values ?? {};
|
|
31615
31727
|
const eventBus = useEventBus();
|
|
31616
31728
|
const handleChange = useCallback(
|
|
@@ -32238,7 +32350,8 @@ var init_PositionedCanvas = __esm({
|
|
|
32238
32350
|
dragRef.current = null;
|
|
32239
32351
|
setDraggingId(null);
|
|
32240
32352
|
if (!wasDrag) {
|
|
32241
|
-
const
|
|
32353
|
+
const itemId = item.id;
|
|
32354
|
+
const next = selectedId === itemId ? null : itemId;
|
|
32242
32355
|
onSelect?.(next);
|
|
32243
32356
|
if (selectEvent) {
|
|
32244
32357
|
eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
@@ -32273,15 +32386,22 @@ var init_PositionedCanvas = __esm({
|
|
|
32273
32386
|
style: { width, height },
|
|
32274
32387
|
onClick: handleContainerClick,
|
|
32275
32388
|
children: items.map((item) => {
|
|
32389
|
+
const itemId = item.id;
|
|
32390
|
+
const label = item.label;
|
|
32391
|
+
const x = item.x;
|
|
32392
|
+
const y = item.y;
|
|
32393
|
+
const capacity = item.capacity;
|
|
32394
|
+
const partySize = item.partySize;
|
|
32395
|
+
const serverName = item.serverName;
|
|
32276
32396
|
const status = item.status ?? "empty";
|
|
32277
32397
|
const shape = item.shape ?? "round";
|
|
32278
|
-
const isSelected = selectedId ===
|
|
32279
|
-
const isDragging = draggingId ===
|
|
32398
|
+
const isSelected = selectedId === itemId;
|
|
32399
|
+
const isDragging = draggingId === itemId;
|
|
32280
32400
|
const statusBadge = STATUS_BADGE[status];
|
|
32281
32401
|
return /* @__PURE__ */ jsxs(
|
|
32282
32402
|
Box,
|
|
32283
32403
|
{
|
|
32284
|
-
"data-testid": `item-node-${
|
|
32404
|
+
"data-testid": `item-node-${itemId}`,
|
|
32285
32405
|
"data-status": status,
|
|
32286
32406
|
className: cn(
|
|
32287
32407
|
"absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
|
|
@@ -32292,7 +32412,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32292
32412
|
isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
|
|
32293
32413
|
isDragging && "shadow-lg z-10"
|
|
32294
32414
|
),
|
|
32295
|
-
style: { left:
|
|
32415
|
+
style: { left: x, top: y, touchAction: "none" },
|
|
32296
32416
|
onPointerDown: (e) => handlePointerDown(e, item),
|
|
32297
32417
|
onPointerMove: handlePointerMove,
|
|
32298
32418
|
onPointerUp: (e) => handlePointerUp(e, item),
|
|
@@ -32300,10 +32420,10 @@ var init_PositionedCanvas = __esm({
|
|
|
32300
32420
|
children: [
|
|
32301
32421
|
/* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", children: [
|
|
32302
32422
|
getStatusIcon(status),
|
|
32303
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children:
|
|
32423
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children: label })
|
|
32304
32424
|
] }),
|
|
32305
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
32306
|
-
status === "seated" &&
|
|
32425
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
|
|
32426
|
+
status === "seated" && serverName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
|
|
32307
32427
|
isSelected && /* @__PURE__ */ jsx(
|
|
32308
32428
|
Badge,
|
|
32309
32429
|
{
|
|
@@ -32315,7 +32435,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32315
32435
|
)
|
|
32316
32436
|
]
|
|
32317
32437
|
},
|
|
32318
|
-
|
|
32438
|
+
itemId
|
|
32319
32439
|
);
|
|
32320
32440
|
})
|
|
32321
32441
|
}
|
|
@@ -33087,9 +33207,10 @@ var init_RichBlockEditor = __esm({
|
|
|
33087
33207
|
});
|
|
33088
33208
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
33089
33209
|
for (const n of nodes) {
|
|
33210
|
+
const replies = n.replies;
|
|
33090
33211
|
if (n.collapsed) acc.add(n.id);
|
|
33091
|
-
if (
|
|
33092
|
-
collectInitiallyCollapsed(
|
|
33212
|
+
if (replies && replies.length > 0) {
|
|
33213
|
+
collectInitiallyCollapsed(replies, acc);
|
|
33093
33214
|
}
|
|
33094
33215
|
}
|
|
33095
33216
|
}
|
|
@@ -33119,44 +33240,52 @@ var init_ReplyTree = __esm({
|
|
|
33119
33240
|
}) => {
|
|
33120
33241
|
const eventBus = useEventBus();
|
|
33121
33242
|
const { t } = useTranslate();
|
|
33122
|
-
const
|
|
33123
|
-
const
|
|
33243
|
+
const nodeId = node.id;
|
|
33244
|
+
const authorName = node.authorName;
|
|
33245
|
+
const authorAvatarUrl = node.authorAvatarUrl;
|
|
33246
|
+
const content = node.content;
|
|
33247
|
+
const postedAt = node.postedAt;
|
|
33248
|
+
const voteCount = node.voteCount;
|
|
33249
|
+
const userVote = node.userVote;
|
|
33250
|
+
const replies = node.replies;
|
|
33251
|
+
const hasReplies = !!replies && replies.length > 0;
|
|
33252
|
+
const isCollapsed = collapsedSet.has(nodeId);
|
|
33124
33253
|
const atMaxDepth = depth >= maxDepth;
|
|
33125
33254
|
const [replyOpen, setReplyOpen] = useState(false);
|
|
33126
33255
|
const [draft, setDraft] = useState("");
|
|
33127
33256
|
const handleVote = useCallback(
|
|
33128
33257
|
(next) => {
|
|
33129
|
-
onVote?.(
|
|
33130
|
-
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId
|
|
33258
|
+
onVote?.(nodeId, next);
|
|
33259
|
+
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
|
|
33131
33260
|
},
|
|
33132
|
-
[
|
|
33261
|
+
[nodeId, onVote, voteEvent, eventBus]
|
|
33133
33262
|
);
|
|
33134
33263
|
const handleReply = useCallback(() => {
|
|
33135
|
-
onReply?.(
|
|
33264
|
+
onReply?.(nodeId);
|
|
33136
33265
|
setReplyOpen((open) => !open);
|
|
33137
|
-
}, [
|
|
33266
|
+
}, [nodeId, onReply]);
|
|
33138
33267
|
const handleSubmitReply = useCallback(() => {
|
|
33139
|
-
const
|
|
33140
|
-
if (!
|
|
33141
|
-
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId:
|
|
33268
|
+
const text = draft.trim();
|
|
33269
|
+
if (!text) return;
|
|
33270
|
+
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
|
|
33142
33271
|
setDraft("");
|
|
33143
33272
|
setReplyOpen(false);
|
|
33144
|
-
}, [
|
|
33273
|
+
}, [nodeId, draft, replyEvent, eventBus]);
|
|
33145
33274
|
const handleCancelReply = useCallback(() => {
|
|
33146
33275
|
setDraft("");
|
|
33147
33276
|
setReplyOpen(false);
|
|
33148
33277
|
}, []);
|
|
33149
33278
|
const handleFlag = useCallback(() => {
|
|
33150
|
-
onFlag?.(
|
|
33151
|
-
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId
|
|
33152
|
-
}, [
|
|
33279
|
+
onFlag?.(nodeId);
|
|
33280
|
+
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
|
|
33281
|
+
}, [nodeId, onFlag, flagEvent, eventBus]);
|
|
33153
33282
|
const handleContinue = useCallback(() => {
|
|
33154
|
-
onContinueThread?.(
|
|
33155
|
-
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId
|
|
33156
|
-
}, [
|
|
33283
|
+
onContinueThread?.(nodeId);
|
|
33284
|
+
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
|
|
33285
|
+
}, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
|
|
33157
33286
|
const handleToggle = useCallback(() => {
|
|
33158
|
-
toggleCollapse(
|
|
33159
|
-
}, [
|
|
33287
|
+
toggleCollapse(nodeId);
|
|
33288
|
+
}, [nodeId, toggleCollapse]);
|
|
33160
33289
|
return /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
|
|
33161
33290
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
|
|
33162
33291
|
hasReplies ? /* @__PURE__ */ jsx(
|
|
@@ -33188,25 +33317,25 @@ var init_ReplyTree = __esm({
|
|
|
33188
33317
|
/* @__PURE__ */ jsx(
|
|
33189
33318
|
Avatar,
|
|
33190
33319
|
{
|
|
33191
|
-
src:
|
|
33192
|
-
name:
|
|
33320
|
+
src: authorAvatarUrl,
|
|
33321
|
+
name: authorName,
|
|
33193
33322
|
size: "sm"
|
|
33194
33323
|
}
|
|
33195
33324
|
),
|
|
33196
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children:
|
|
33197
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
33325
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
|
|
33326
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
|
|
33198
33327
|
] }),
|
|
33199
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children:
|
|
33328
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
|
|
33200
33329
|
showActions && /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
33201
33330
|
/* @__PURE__ */ jsx(
|
|
33202
33331
|
VoteStack,
|
|
33203
33332
|
{
|
|
33204
|
-
count:
|
|
33205
|
-
userVote:
|
|
33333
|
+
count: voteCount ?? 0,
|
|
33334
|
+
userVote: userVote ?? null,
|
|
33206
33335
|
onVote: handleVote,
|
|
33207
33336
|
size: "sm",
|
|
33208
33337
|
variant: "horizontal",
|
|
33209
|
-
label: t("replyTree.voteOnReplyBy", { author:
|
|
33338
|
+
label: t("replyTree.voteOnReplyBy", { author: authorName })
|
|
33210
33339
|
}
|
|
33211
33340
|
),
|
|
33212
33341
|
/* @__PURE__ */ jsx(
|
|
@@ -33216,7 +33345,7 @@ var init_ReplyTree = __esm({
|
|
|
33216
33345
|
size: "sm",
|
|
33217
33346
|
leftIcon: "message-square",
|
|
33218
33347
|
onClick: handleReply,
|
|
33219
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33348
|
+
"aria-label": t("replyTree.replyTo", { author: authorName }),
|
|
33220
33349
|
children: t("replyTree.reply")
|
|
33221
33350
|
}
|
|
33222
33351
|
),
|
|
@@ -33227,7 +33356,7 @@ var init_ReplyTree = __esm({
|
|
|
33227
33356
|
size: "sm",
|
|
33228
33357
|
leftIcon: "flag",
|
|
33229
33358
|
onClick: handleFlag,
|
|
33230
|
-
"aria-label": t("replyTree.flagReplyBy", { author:
|
|
33359
|
+
"aria-label": t("replyTree.flagReplyBy", { author: authorName }),
|
|
33231
33360
|
children: t("replyTree.flag")
|
|
33232
33361
|
}
|
|
33233
33362
|
)
|
|
@@ -33239,9 +33368,9 @@ var init_ReplyTree = __esm({
|
|
|
33239
33368
|
inputType: "textarea",
|
|
33240
33369
|
rows: 2,
|
|
33241
33370
|
value: draft,
|
|
33242
|
-
placeholder: t("replyTree.replyToPlaceholder", { author:
|
|
33371
|
+
placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
|
|
33243
33372
|
onChange: (e) => setDraft(e.target.value),
|
|
33244
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33373
|
+
"aria-label": t("replyTree.replyTo", { author: authorName })
|
|
33245
33374
|
}
|
|
33246
33375
|
),
|
|
33247
33376
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
@@ -33272,7 +33401,7 @@ var init_ReplyTree = __esm({
|
|
|
33272
33401
|
),
|
|
33273
33402
|
children: t("replyTree.continueThread")
|
|
33274
33403
|
}
|
|
33275
|
-
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children:
|
|
33404
|
+
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsx(
|
|
33276
33405
|
ReplyTreeNode,
|
|
33277
33406
|
{
|
|
33278
33407
|
node: child,
|
|
@@ -35592,8 +35721,8 @@ var init_WizardContainer = __esm({
|
|
|
35592
35721
|
return void 0;
|
|
35593
35722
|
if (typeof controlledStep === "number") return controlledStep;
|
|
35594
35723
|
if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
|
|
35595
|
-
const
|
|
35596
|
-
return isNaN(
|
|
35724
|
+
const num2 = Number(controlledStep);
|
|
35725
|
+
return isNaN(num2) ? void 0 : num2;
|
|
35597
35726
|
})();
|
|
35598
35727
|
const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
|
|
35599
35728
|
const totalSteps = steps.length;
|
|
@@ -37298,7 +37427,7 @@ function DebuggerBoard({
|
|
|
37298
37427
|
}) {
|
|
37299
37428
|
const { emit } = useEventBus();
|
|
37300
37429
|
const { t } = useTranslate();
|
|
37301
|
-
const resolved =
|
|
37430
|
+
const resolved = boardEntity(entity);
|
|
37302
37431
|
const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
|
|
37303
37432
|
const [headerError, setHeaderError] = useState(false);
|
|
37304
37433
|
const [submitted, setSubmitted] = useState(false);
|
|
@@ -37316,7 +37445,7 @@ function DebuggerBoard({
|
|
|
37316
37445
|
return next;
|
|
37317
37446
|
});
|
|
37318
37447
|
};
|
|
37319
|
-
const lines = resolved?.lines
|
|
37448
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
37320
37449
|
const bugLines = lines.filter((l) => l.isBug);
|
|
37321
37450
|
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
37322
37451
|
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
@@ -37331,7 +37460,7 @@ function DebuggerBoard({
|
|
|
37331
37460
|
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
37332
37461
|
const handleReset = () => {
|
|
37333
37462
|
setSubmitted(false);
|
|
37334
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
37463
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
37335
37464
|
setShowHint(true);
|
|
37336
37465
|
}
|
|
37337
37466
|
};
|
|
@@ -37342,24 +37471,28 @@ function DebuggerBoard({
|
|
|
37342
37471
|
setShowHint(false);
|
|
37343
37472
|
};
|
|
37344
37473
|
if (!resolved) return null;
|
|
37474
|
+
const theme = resolved.theme ?? void 0;
|
|
37475
|
+
const themeBackground = theme?.background;
|
|
37476
|
+
const headerImage = str(resolved.headerImage);
|
|
37477
|
+
const hint = str(resolved.hint);
|
|
37345
37478
|
return /* @__PURE__ */ jsx(
|
|
37346
37479
|
Box,
|
|
37347
37480
|
{
|
|
37348
37481
|
className,
|
|
37349
37482
|
style: {
|
|
37350
|
-
backgroundImage:
|
|
37483
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
37351
37484
|
backgroundSize: "cover",
|
|
37352
37485
|
backgroundPosition: "center"
|
|
37353
37486
|
},
|
|
37354
37487
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
37355
|
-
|
|
37488
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
37356
37489
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
37357
37490
|
/* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
37358
37491
|
/* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
|
|
37359
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
|
|
37492
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
|
|
37360
37493
|
] }),
|
|
37361
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
37362
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
|
|
37494
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
37495
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
37363
37496
|
] }) }),
|
|
37364
37497
|
/* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
37365
37498
|
const isFlagged = flaggedLines.has(line.id);
|
|
@@ -37391,7 +37524,7 @@ function DebuggerBoard({
|
|
|
37391
37524
|
);
|
|
37392
37525
|
}) }) }),
|
|
37393
37526
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
37394
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
37527
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
37395
37528
|
bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
37396
37529
|
/* @__PURE__ */ jsx(
|
|
37397
37530
|
Icon,
|
|
@@ -37407,7 +37540,7 @@ function DebuggerBoard({
|
|
|
37407
37540
|
] })
|
|
37408
37541
|
] }, line.id))
|
|
37409
37542
|
] }) }),
|
|
37410
|
-
showHint &&
|
|
37543
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
37411
37544
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
37412
37545
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
37413
37546
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -37426,6 +37559,7 @@ var init_DebuggerBoard = __esm({
|
|
|
37426
37559
|
"components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
|
|
37427
37560
|
init_atoms2();
|
|
37428
37561
|
init_useEventBus();
|
|
37562
|
+
init_boardEntity();
|
|
37429
37563
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
37430
37564
|
}
|
|
37431
37565
|
});
|
|
@@ -37463,7 +37597,7 @@ function getBadgeVariant(fieldName, value) {
|
|
|
37463
37597
|
return "default";
|
|
37464
37598
|
}
|
|
37465
37599
|
function formatFieldLabel(fieldName) {
|
|
37466
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
37600
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
|
|
37467
37601
|
}
|
|
37468
37602
|
function formatFieldValue(value, fieldName) {
|
|
37469
37603
|
if (typeof value === "number") {
|
|
@@ -37482,26 +37616,26 @@ function formatFieldValue(value, fieldName) {
|
|
|
37482
37616
|
}
|
|
37483
37617
|
function renderRichFieldValue(value, fieldName, fieldType) {
|
|
37484
37618
|
if (value === void 0 || value === null) return "\u2014";
|
|
37485
|
-
const
|
|
37619
|
+
const str2 = String(value);
|
|
37486
37620
|
switch (fieldType) {
|
|
37487
37621
|
case "image":
|
|
37488
37622
|
case "url": {
|
|
37489
|
-
if (
|
|
37623
|
+
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
37490
37624
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
37491
37625
|
"img",
|
|
37492
37626
|
{
|
|
37493
|
-
src:
|
|
37627
|
+
src: str2,
|
|
37494
37628
|
alt: formatFieldLabel(fieldName),
|
|
37495
37629
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
37496
37630
|
loading: "lazy"
|
|
37497
37631
|
}
|
|
37498
37632
|
) });
|
|
37499
37633
|
}
|
|
37500
|
-
return
|
|
37634
|
+
return str2;
|
|
37501
37635
|
}
|
|
37502
37636
|
case "markdown":
|
|
37503
37637
|
case "richtext":
|
|
37504
|
-
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children:
|
|
37638
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsx(
|
|
37505
37639
|
Box,
|
|
37506
37640
|
{
|
|
37507
37641
|
className: "prose prose-sm max-w-none",
|
|
@@ -37519,11 +37653,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37519
37653
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37520
37654
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37521
37655
|
},
|
|
37522
|
-
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children:
|
|
37656
|
+
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children: str2 })
|
|
37523
37657
|
}
|
|
37524
37658
|
) });
|
|
37525
37659
|
case "code":
|
|
37526
|
-
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children:
|
|
37660
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children: str2 }) }) });
|
|
37527
37661
|
case "html":
|
|
37528
37662
|
return /* @__PURE__ */ jsx(
|
|
37529
37663
|
Box,
|
|
@@ -37543,12 +37677,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37543
37677
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37544
37678
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37545
37679
|
},
|
|
37546
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children:
|
|
37680
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: str2 })
|
|
37547
37681
|
}
|
|
37548
37682
|
);
|
|
37549
37683
|
case "date":
|
|
37550
37684
|
case "datetime": {
|
|
37551
|
-
const d = new Date(
|
|
37685
|
+
const d = new Date(str2);
|
|
37552
37686
|
if (!isNaN(d.getTime())) {
|
|
37553
37687
|
return d.toLocaleDateString(void 0, {
|
|
37554
37688
|
year: "numeric",
|
|
@@ -37557,7 +37691,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37557
37691
|
...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
|
|
37558
37692
|
});
|
|
37559
37693
|
}
|
|
37560
|
-
return
|
|
37694
|
+
return str2;
|
|
37561
37695
|
}
|
|
37562
37696
|
default:
|
|
37563
37697
|
return formatFieldValue(value, fieldName);
|
|
@@ -38235,6 +38369,40 @@ var init_RuleEditor = __esm({
|
|
|
38235
38369
|
RuleEditor.displayName = "RuleEditor";
|
|
38236
38370
|
}
|
|
38237
38371
|
});
|
|
38372
|
+
|
|
38373
|
+
// components/game/organisms/puzzles/event-handler/puzzleObject.ts
|
|
38374
|
+
function objId(o) {
|
|
38375
|
+
return o.id == null ? "" : String(o.id);
|
|
38376
|
+
}
|
|
38377
|
+
function objName(o) {
|
|
38378
|
+
return o.name == null ? "" : String(o.name);
|
|
38379
|
+
}
|
|
38380
|
+
function objIcon(o) {
|
|
38381
|
+
return o.icon == null ? "" : String(o.icon);
|
|
38382
|
+
}
|
|
38383
|
+
function objStates(o) {
|
|
38384
|
+
return Array.isArray(o.states) ? o.states : [];
|
|
38385
|
+
}
|
|
38386
|
+
function objCurrentState(o) {
|
|
38387
|
+
return o.currentState == null ? "" : String(o.currentState);
|
|
38388
|
+
}
|
|
38389
|
+
function objAvailableEvents(o) {
|
|
38390
|
+
return Array.isArray(o.availableEvents) ? o.availableEvents : [];
|
|
38391
|
+
}
|
|
38392
|
+
function objAvailableActions(o) {
|
|
38393
|
+
return Array.isArray(o.availableActions) ? o.availableActions : [];
|
|
38394
|
+
}
|
|
38395
|
+
function objRules(o) {
|
|
38396
|
+
return Array.isArray(o.rules) ? o.rules : [];
|
|
38397
|
+
}
|
|
38398
|
+
function objMaxRules(o) {
|
|
38399
|
+
const n = Number(o.maxRules);
|
|
38400
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
38401
|
+
}
|
|
38402
|
+
var init_puzzleObject = __esm({
|
|
38403
|
+
"components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
|
|
38404
|
+
}
|
|
38405
|
+
});
|
|
38238
38406
|
function ObjectRulePanel({
|
|
38239
38407
|
object,
|
|
38240
38408
|
onRulesChange,
|
|
@@ -38242,55 +38410,63 @@ function ObjectRulePanel({
|
|
|
38242
38410
|
className
|
|
38243
38411
|
}) {
|
|
38244
38412
|
const { t } = useTranslate();
|
|
38245
|
-
const
|
|
38246
|
-
const
|
|
38413
|
+
const id = objId(object);
|
|
38414
|
+
const name = objName(object);
|
|
38415
|
+
const icon = objIcon(object);
|
|
38416
|
+
const states = objStates(object);
|
|
38417
|
+
const currentState = objCurrentState(object);
|
|
38418
|
+
const availableEvents = objAvailableEvents(object);
|
|
38419
|
+
const availableActions = objAvailableActions(object);
|
|
38420
|
+
const rules = objRules(object);
|
|
38421
|
+
const maxRules = objMaxRules(object);
|
|
38422
|
+
const canAdd = rules.length < maxRules;
|
|
38247
38423
|
const handleRuleChange = useCallback((index, updatedRule) => {
|
|
38248
|
-
const newRules = [...
|
|
38424
|
+
const newRules = [...rules];
|
|
38249
38425
|
newRules[index] = updatedRule;
|
|
38250
|
-
onRulesChange(
|
|
38251
|
-
}, [
|
|
38426
|
+
onRulesChange(id, newRules);
|
|
38427
|
+
}, [id, rules, onRulesChange]);
|
|
38252
38428
|
const handleRuleRemove = useCallback((index) => {
|
|
38253
|
-
const newRules =
|
|
38254
|
-
onRulesChange(
|
|
38255
|
-
}, [
|
|
38429
|
+
const newRules = rules.filter((_, i) => i !== index);
|
|
38430
|
+
onRulesChange(id, newRules);
|
|
38431
|
+
}, [id, rules, onRulesChange]);
|
|
38256
38432
|
const handleAddRule = useCallback(() => {
|
|
38257
38433
|
if (!canAdd || disabled) return;
|
|
38258
|
-
const firstEvent =
|
|
38259
|
-
const firstAction =
|
|
38434
|
+
const firstEvent = availableEvents[0]?.value || "";
|
|
38435
|
+
const firstAction = availableActions[0]?.value || "";
|
|
38260
38436
|
const newRule = {
|
|
38261
38437
|
id: `rule-${nextRuleId++}`,
|
|
38262
38438
|
whenEvent: firstEvent,
|
|
38263
38439
|
thenAction: firstAction
|
|
38264
38440
|
};
|
|
38265
|
-
onRulesChange(
|
|
38266
|
-
}, [canAdd, disabled,
|
|
38441
|
+
onRulesChange(id, [...rules, newRule]);
|
|
38442
|
+
}, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
|
|
38267
38443
|
const machine = {
|
|
38268
|
-
name
|
|
38269
|
-
states
|
|
38270
|
-
currentState
|
|
38271
|
-
transitions:
|
|
38272
|
-
from:
|
|
38273
|
-
to:
|
|
38444
|
+
name,
|
|
38445
|
+
states,
|
|
38446
|
+
currentState,
|
|
38447
|
+
transitions: rules.map((r) => ({
|
|
38448
|
+
from: currentState,
|
|
38449
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38274
38450
|
event: r.whenEvent
|
|
38275
38451
|
}))
|
|
38276
38452
|
};
|
|
38277
38453
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
38278
38454
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center", gap: "sm", children: [
|
|
38279
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h5", children:
|
|
38455
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: icon }),
|
|
38280
38456
|
/* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
38281
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children:
|
|
38282
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " +
|
|
38457
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
|
|
38458
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
|
|
38283
38459
|
] })
|
|
38284
38460
|
] }),
|
|
38285
38461
|
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
|
|
38286
38462
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
38287
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count:
|
|
38288
|
-
|
|
38463
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
|
|
38464
|
+
rules.map((rule, i) => /* @__PURE__ */ jsx(
|
|
38289
38465
|
RuleEditor,
|
|
38290
38466
|
{
|
|
38291
38467
|
rule,
|
|
38292
|
-
availableEvents
|
|
38293
|
-
availableActions
|
|
38468
|
+
availableEvents,
|
|
38469
|
+
availableActions,
|
|
38294
38470
|
onChange: (r) => handleRuleChange(i, r),
|
|
38295
38471
|
onRemove: () => handleRuleRemove(i),
|
|
38296
38472
|
disabled
|
|
@@ -38308,6 +38484,7 @@ var init_ObjectRulePanel = __esm({
|
|
|
38308
38484
|
init_cn();
|
|
38309
38485
|
init_TraitStateViewer();
|
|
38310
38486
|
init_RuleEditor();
|
|
38487
|
+
init_puzzleObject();
|
|
38311
38488
|
nextRuleId = 1;
|
|
38312
38489
|
ObjectRulePanel.displayName = "ObjectRulePanel";
|
|
38313
38490
|
}
|
|
@@ -38374,11 +38551,11 @@ function EventHandlerBoard({
|
|
|
38374
38551
|
}) {
|
|
38375
38552
|
const { emit } = useEventBus();
|
|
38376
38553
|
const { t } = useTranslate();
|
|
38377
|
-
const resolved =
|
|
38378
|
-
const entityObjects = resolved?.objects
|
|
38379
|
-
const [objects, setObjects] = useState(entityObjects);
|
|
38554
|
+
const resolved = boardEntity(entity);
|
|
38555
|
+
const entityObjects = rows(resolved?.objects);
|
|
38556
|
+
const [objects, setObjects] = useState(() => [...entityObjects]);
|
|
38380
38557
|
const [selectedObjectId, setSelectedObjectId] = useState(
|
|
38381
|
-
entityObjects[0]
|
|
38558
|
+
entityObjects[0] ? objId(entityObjects[0]) : null
|
|
38382
38559
|
);
|
|
38383
38560
|
const [headerError, setHeaderError] = useState(false);
|
|
38384
38561
|
const [playState, setPlayState] = useState("editing");
|
|
@@ -38389,10 +38566,10 @@ function EventHandlerBoard({
|
|
|
38389
38566
|
useEffect(() => () => {
|
|
38390
38567
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38391
38568
|
}, []);
|
|
38392
|
-
const selectedObject = objects.find((o) => o
|
|
38569
|
+
const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
|
|
38393
38570
|
const handleRulesChange = useCallback((objectId, rules) => {
|
|
38394
38571
|
setObjects((prev) => prev.map(
|
|
38395
|
-
(o) => o
|
|
38572
|
+
(o) => objId(o) === objectId ? { ...o, rules } : o
|
|
38396
38573
|
));
|
|
38397
38574
|
}, []);
|
|
38398
38575
|
const addLogEntry = useCallback((icon, message, status = "done") => {
|
|
@@ -38406,11 +38583,12 @@ function EventHandlerBoard({
|
|
|
38406
38583
|
setEventLog([]);
|
|
38407
38584
|
const allRules = [];
|
|
38408
38585
|
objects.forEach((obj) => {
|
|
38409
|
-
obj.
|
|
38586
|
+
objRules(obj).forEach((rule) => {
|
|
38410
38587
|
allRules.push({ object: obj, rule });
|
|
38411
38588
|
});
|
|
38412
38589
|
});
|
|
38413
|
-
const triggers = resolved?.triggerEvents
|
|
38590
|
+
const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
|
|
38591
|
+
const goalEvent = str(resolved?.goalEvent);
|
|
38414
38592
|
const eventQueue = [...triggers];
|
|
38415
38593
|
const firedEvents = /* @__PURE__ */ new Set();
|
|
38416
38594
|
let stepIdx = 0;
|
|
@@ -38439,14 +38617,14 @@ function EventHandlerBoard({
|
|
|
38439
38617
|
addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
|
|
38440
38618
|
} else {
|
|
38441
38619
|
matching.forEach(({ object, rule }) => {
|
|
38442
|
-
addLogEntry(object
|
|
38620
|
+
addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
|
|
38443
38621
|
eventQueue.push(rule.thenAction);
|
|
38444
|
-
if (rule.thenAction ===
|
|
38622
|
+
if (rule.thenAction === goalEvent) {
|
|
38445
38623
|
goalReached = true;
|
|
38446
38624
|
}
|
|
38447
38625
|
});
|
|
38448
38626
|
}
|
|
38449
|
-
if (currentEvent ===
|
|
38627
|
+
if (currentEvent === goalEvent) {
|
|
38450
38628
|
goalReached = true;
|
|
38451
38629
|
}
|
|
38452
38630
|
stepIdx++;
|
|
@@ -38464,65 +38642,75 @@ function EventHandlerBoard({
|
|
|
38464
38642
|
}, []);
|
|
38465
38643
|
const handleReset = useCallback(() => {
|
|
38466
38644
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38467
|
-
|
|
38645
|
+
const resetObjects = rows(resolved?.objects);
|
|
38646
|
+
setObjects([...resetObjects]);
|
|
38468
38647
|
setPlayState("editing");
|
|
38469
38648
|
setEventLog([]);
|
|
38470
|
-
setSelectedObjectId(
|
|
38649
|
+
setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
|
|
38471
38650
|
setAttempts(0);
|
|
38472
38651
|
}, [resolved?.objects]);
|
|
38473
38652
|
if (!resolved) return null;
|
|
38474
38653
|
const objectViewers = objects.map((obj) => {
|
|
38654
|
+
const states = objStates(obj);
|
|
38655
|
+
const currentState = objCurrentState(obj);
|
|
38475
38656
|
const machine = {
|
|
38476
|
-
name: obj
|
|
38477
|
-
states
|
|
38478
|
-
currentState
|
|
38479
|
-
transitions: obj.
|
|
38480
|
-
from:
|
|
38481
|
-
to:
|
|
38657
|
+
name: objName(obj),
|
|
38658
|
+
states,
|
|
38659
|
+
currentState,
|
|
38660
|
+
transitions: objRules(obj).map((r) => ({
|
|
38661
|
+
from: currentState,
|
|
38662
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38482
38663
|
event: r.whenEvent
|
|
38483
38664
|
}))
|
|
38484
38665
|
};
|
|
38485
38666
|
return { obj, machine };
|
|
38486
38667
|
});
|
|
38487
|
-
const
|
|
38668
|
+
const hint = str(resolved.hint);
|
|
38669
|
+
const showHint = attempts >= 3 && hint;
|
|
38670
|
+
const theme = resolved.theme ?? void 0;
|
|
38671
|
+
const themeBackground = theme?.background;
|
|
38672
|
+
const headerImage = str(resolved.headerImage);
|
|
38488
38673
|
const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
|
|
38489
38674
|
return /* @__PURE__ */ jsxs(
|
|
38490
38675
|
VStack,
|
|
38491
38676
|
{
|
|
38492
38677
|
className: cn("p-4 gap-6", className),
|
|
38493
38678
|
style: {
|
|
38494
|
-
backgroundImage:
|
|
38679
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
38495
38680
|
backgroundSize: "cover",
|
|
38496
38681
|
backgroundPosition: "center"
|
|
38497
38682
|
},
|
|
38498
38683
|
children: [
|
|
38499
|
-
|
|
38684
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
38500
38685
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
38501
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
38502
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
38686
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
38687
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
38503
38688
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
38504
38689
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
38505
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
|
|
38690
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
|
|
38506
38691
|
] })
|
|
38507
38692
|
] }),
|
|
38508
38693
|
/* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
38509
38694
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
38510
|
-
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) =>
|
|
38511
|
-
|
|
38512
|
-
|
|
38513
|
-
|
|
38514
|
-
|
|
38515
|
-
|
|
38516
|
-
|
|
38517
|
-
|
|
38518
|
-
|
|
38519
|
-
|
|
38520
|
-
/* @__PURE__ */
|
|
38521
|
-
|
|
38522
|
-
|
|
38523
|
-
|
|
38524
|
-
|
|
38525
|
-
|
|
38695
|
+
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
|
|
38696
|
+
const oid = objId(obj);
|
|
38697
|
+
return /* @__PURE__ */ jsx(
|
|
38698
|
+
Box,
|
|
38699
|
+
{
|
|
38700
|
+
className: cn(
|
|
38701
|
+
"p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
|
|
38702
|
+
selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
38703
|
+
),
|
|
38704
|
+
onClick: () => setSelectedObjectId(oid),
|
|
38705
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
38706
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: objIcon(obj) }),
|
|
38707
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
|
|
38708
|
+
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
38709
|
+
] })
|
|
38710
|
+
},
|
|
38711
|
+
oid
|
|
38712
|
+
);
|
|
38713
|
+
}) })
|
|
38526
38714
|
] }),
|
|
38527
38715
|
selectedObject && /* @__PURE__ */ jsx(
|
|
38528
38716
|
ObjectRulePanel,
|
|
@@ -38533,12 +38721,12 @@ function EventHandlerBoard({
|
|
|
38533
38721
|
}
|
|
38534
38722
|
),
|
|
38535
38723
|
eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
|
|
38536
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("eventHandler.chainComplete") }) }),
|
|
38724
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("eventHandler.chainComplete") }) }),
|
|
38537
38725
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
38538
38726
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
|
|
38539
38727
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
38540
38728
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
38541
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
38729
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
38542
38730
|
] }) })
|
|
38543
38731
|
] }),
|
|
38544
38732
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -38566,6 +38754,8 @@ var init_EventHandlerBoard = __esm({
|
|
|
38566
38754
|
init_TraitStateViewer();
|
|
38567
38755
|
init_ObjectRulePanel();
|
|
38568
38756
|
init_EventLog();
|
|
38757
|
+
init_puzzleObject();
|
|
38758
|
+
init_boardEntity();
|
|
38569
38759
|
ENCOURAGEMENT_KEYS = [
|
|
38570
38760
|
"puzzle.tryAgain1",
|
|
38571
38761
|
"puzzle.tryAgain2",
|
|
@@ -38654,7 +38844,10 @@ var init_FeatureGridOrganism = __esm({
|
|
|
38654
38844
|
);
|
|
38655
38845
|
useCallback(
|
|
38656
38846
|
(feature) => {
|
|
38657
|
-
eventBus.emit("UI:FEATURE_CLICK", {
|
|
38847
|
+
eventBus.emit("UI:FEATURE_CLICK", {
|
|
38848
|
+
id: String(feature.id ?? ""),
|
|
38849
|
+
href: String(feature.href ?? "")
|
|
38850
|
+
});
|
|
38658
38851
|
},
|
|
38659
38852
|
[eventBus]
|
|
38660
38853
|
);
|
|
@@ -38664,14 +38857,17 @@ var init_FeatureGridOrganism = __esm({
|
|
|
38664
38857
|
if (error) {
|
|
38665
38858
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
38666
38859
|
}
|
|
38667
|
-
const featureCards = items.map((feature) =>
|
|
38668
|
-
|
|
38669
|
-
|
|
38670
|
-
|
|
38671
|
-
|
|
38672
|
-
|
|
38673
|
-
|
|
38674
|
-
|
|
38860
|
+
const featureCards = items.map((feature) => {
|
|
38861
|
+
const href = feature.href != null ? String(feature.href) : void 0;
|
|
38862
|
+
return {
|
|
38863
|
+
icon: feature.icon != null ? String(feature.icon) : void 0,
|
|
38864
|
+
title: String(feature.title ?? ""),
|
|
38865
|
+
description: String(feature.description ?? ""),
|
|
38866
|
+
href,
|
|
38867
|
+
linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
|
|
38868
|
+
variant: href ? "interactive" : "bordered"
|
|
38869
|
+
};
|
|
38870
|
+
});
|
|
38675
38871
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
38676
38872
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
38677
38873
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
@@ -39989,22 +40185,24 @@ var init_HeroOrganism = __esm({
|
|
|
39989
40185
|
() => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
|
|
39990
40186
|
[entity]
|
|
39991
40187
|
);
|
|
40188
|
+
const primaryAction = resolved?.primaryAction;
|
|
40189
|
+
const secondaryAction = resolved?.secondaryAction;
|
|
39992
40190
|
const handlePrimaryClick = useCallback(() => {
|
|
39993
|
-
if (
|
|
40191
|
+
if (primaryAction) {
|
|
39994
40192
|
eventBus.emit("UI:CTA_PRIMARY", {
|
|
39995
|
-
label:
|
|
39996
|
-
href:
|
|
40193
|
+
label: String(primaryAction.label ?? ""),
|
|
40194
|
+
href: String(primaryAction.href ?? "")
|
|
39997
40195
|
});
|
|
39998
40196
|
}
|
|
39999
|
-
}, [eventBus,
|
|
40197
|
+
}, [eventBus, primaryAction]);
|
|
40000
40198
|
const handleSecondaryClick = useCallback(() => {
|
|
40001
|
-
if (
|
|
40199
|
+
if (secondaryAction) {
|
|
40002
40200
|
eventBus.emit("UI:CTA_SECONDARY", {
|
|
40003
|
-
label:
|
|
40004
|
-
href:
|
|
40201
|
+
label: String(secondaryAction.label ?? ""),
|
|
40202
|
+
href: String(secondaryAction.href ?? "")
|
|
40005
40203
|
});
|
|
40006
40204
|
}
|
|
40007
|
-
}, [eventBus,
|
|
40205
|
+
}, [eventBus, secondaryAction]);
|
|
40008
40206
|
if (isLoading) {
|
|
40009
40207
|
return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
|
|
40010
40208
|
}
|
|
@@ -40014,17 +40212,19 @@ var init_HeroOrganism = __esm({
|
|
|
40014
40212
|
if (!resolved) {
|
|
40015
40213
|
return null;
|
|
40016
40214
|
}
|
|
40215
|
+
const imageRaw = resolved.image;
|
|
40216
|
+
const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
|
|
40017
40217
|
return /* @__PURE__ */ jsxs(
|
|
40018
40218
|
HeroSection,
|
|
40019
40219
|
{
|
|
40020
|
-
tag: resolved.tag,
|
|
40021
|
-
title: resolved.title,
|
|
40022
|
-
titleAccent: resolved.titleAccent,
|
|
40023
|
-
subtitle: resolved.subtitle,
|
|
40024
|
-
primaryAction:
|
|
40025
|
-
secondaryAction:
|
|
40026
|
-
installCommand: resolved.installCommand,
|
|
40027
|
-
image
|
|
40220
|
+
tag: resolved.tag != null ? String(resolved.tag) : void 0,
|
|
40221
|
+
title: String(resolved.title ?? ""),
|
|
40222
|
+
titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
|
|
40223
|
+
subtitle: String(resolved.subtitle ?? ""),
|
|
40224
|
+
primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
|
|
40225
|
+
secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
|
|
40226
|
+
installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
|
|
40227
|
+
image,
|
|
40028
40228
|
imagePosition: resolved.imagePosition,
|
|
40029
40229
|
background: resolved.background,
|
|
40030
40230
|
className: cn(className),
|
|
@@ -40033,8 +40233,8 @@ var init_HeroOrganism = __esm({
|
|
|
40033
40233
|
/* @__PURE__ */ jsx(
|
|
40034
40234
|
_HeroClickInterceptor,
|
|
40035
40235
|
{
|
|
40036
|
-
hasPrimary: !!
|
|
40037
|
-
hasSecondary: !!
|
|
40236
|
+
hasPrimary: !!primaryAction,
|
|
40237
|
+
hasSecondary: !!secondaryAction,
|
|
40038
40238
|
onPrimaryClick: handlePrimaryClick,
|
|
40039
40239
|
onSecondaryClick: handleSecondaryClick
|
|
40040
40240
|
}
|
|
@@ -40263,7 +40463,7 @@ function formatValue3(value, fieldName) {
|
|
|
40263
40463
|
return String(value);
|
|
40264
40464
|
}
|
|
40265
40465
|
function formatFieldLabel2(fieldName) {
|
|
40266
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
40466
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
|
|
40267
40467
|
}
|
|
40268
40468
|
var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
|
|
40269
40469
|
var init_List = __esm({
|
|
@@ -41110,20 +41310,22 @@ function NegotiatorBoard({
|
|
|
41110
41310
|
}) {
|
|
41111
41311
|
const { emit } = useEventBus();
|
|
41112
41312
|
const { t } = useTranslate();
|
|
41113
|
-
const resolved =
|
|
41313
|
+
const resolved = boardEntity(entity);
|
|
41114
41314
|
const [history, setHistory] = useState([]);
|
|
41115
41315
|
const [headerError, setHeaderError] = useState(false);
|
|
41116
41316
|
const [showHint, setShowHint] = useState(false);
|
|
41317
|
+
const totalRounds = num(resolved?.totalRounds);
|
|
41318
|
+
const targetScore = num(resolved?.targetScore);
|
|
41117
41319
|
const currentRound = history.length;
|
|
41118
|
-
const isComplete = currentRound >=
|
|
41320
|
+
const isComplete = currentRound >= totalRounds;
|
|
41119
41321
|
const playerTotal = history.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41120
41322
|
const opponentTotal = history.reduce((s, r) => s + r.opponentPayoff, 0);
|
|
41121
|
-
const won = isComplete && playerTotal >=
|
|
41122
|
-
const actions = resolved?.actions
|
|
41123
|
-
const payoffMatrix = resolved?.payoffMatrix
|
|
41323
|
+
const won = isComplete && playerTotal >= targetScore;
|
|
41324
|
+
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
41325
|
+
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
41124
41326
|
const handleAction = useCallback((actionId) => {
|
|
41125
41327
|
if (isComplete) return;
|
|
41126
|
-
const opponentAction = getOpponentAction(resolved?.opponentStrategy
|
|
41328
|
+
const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
|
|
41127
41329
|
const payoff = payoffMatrix.find(
|
|
41128
41330
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
41129
41331
|
);
|
|
@@ -41136,42 +41338,46 @@ function NegotiatorBoard({
|
|
|
41136
41338
|
};
|
|
41137
41339
|
const newHistory = [...history, result];
|
|
41138
41340
|
setHistory(newHistory);
|
|
41139
|
-
if (newHistory.length >=
|
|
41341
|
+
if (newHistory.length >= totalRounds) {
|
|
41140
41342
|
const total = newHistory.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41141
|
-
if (total >=
|
|
41343
|
+
if (total >= targetScore) {
|
|
41142
41344
|
emit(`UI:${completeEvent}`, { success: true, score: total });
|
|
41143
41345
|
}
|
|
41144
|
-
if (newHistory.length >= 3 && resolved?.hint) {
|
|
41346
|
+
if (newHistory.length >= 3 && str(resolved?.hint)) {
|
|
41145
41347
|
setShowHint(true);
|
|
41146
41348
|
}
|
|
41147
41349
|
}
|
|
41148
|
-
}, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41350
|
+
}, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41149
41351
|
const handleReset = () => {
|
|
41150
41352
|
setHistory([]);
|
|
41151
41353
|
setShowHint(false);
|
|
41152
41354
|
};
|
|
41153
41355
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
41154
41356
|
if (!resolved) return null;
|
|
41357
|
+
const theme = resolved.theme ?? void 0;
|
|
41358
|
+
const themeBackground = theme?.background;
|
|
41359
|
+
const headerImage = str(resolved.headerImage);
|
|
41360
|
+
const hint = str(resolved.hint);
|
|
41155
41361
|
return /* @__PURE__ */ jsx(
|
|
41156
41362
|
Box,
|
|
41157
41363
|
{
|
|
41158
41364
|
className,
|
|
41159
41365
|
style: {
|
|
41160
|
-
backgroundImage:
|
|
41366
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
41161
41367
|
backgroundSize: "cover",
|
|
41162
41368
|
backgroundPosition: "center"
|
|
41163
41369
|
},
|
|
41164
41370
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
41165
|
-
|
|
41371
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
41166
41372
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
41167
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
41168
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
41373
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
41374
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
41169
41375
|
/* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
|
|
41170
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(
|
|
41376
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
|
|
41171
41377
|
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
41172
41378
|
t("negotiator.target"),
|
|
41173
41379
|
": ",
|
|
41174
|
-
|
|
41380
|
+
targetScore
|
|
41175
41381
|
] })
|
|
41176
41382
|
] })
|
|
41177
41383
|
] }) }),
|
|
@@ -41220,16 +41426,16 @@ function NegotiatorBoard({
|
|
|
41220
41426
|
] }) }),
|
|
41221
41427
|
isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
41222
41428
|
/* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
|
|
41223
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage
|
|
41429
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
|
|
41224
41430
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
41225
41431
|
t("negotiator.finalScore"),
|
|
41226
41432
|
": ",
|
|
41227
41433
|
playerTotal,
|
|
41228
41434
|
"/",
|
|
41229
|
-
|
|
41435
|
+
targetScore
|
|
41230
41436
|
] })
|
|
41231
41437
|
] }) }),
|
|
41232
|
-
showHint &&
|
|
41438
|
+
showHint && hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
41233
41439
|
isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
41234
41440
|
] })
|
|
41235
41441
|
}
|
|
@@ -41239,6 +41445,7 @@ var init_NegotiatorBoard = __esm({
|
|
|
41239
41445
|
"components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
|
|
41240
41446
|
init_atoms2();
|
|
41241
41447
|
init_useEventBus();
|
|
41448
|
+
init_boardEntity();
|
|
41242
41449
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
41243
41450
|
}
|
|
41244
41451
|
});
|
|
@@ -41274,13 +41481,13 @@ var init_PricingOrganism = __esm({
|
|
|
41274
41481
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
41275
41482
|
}
|
|
41276
41483
|
const plans = items.map((plan) => ({
|
|
41277
|
-
name: plan.name,
|
|
41278
|
-
price: plan.price,
|
|
41279
|
-
description: plan.description,
|
|
41280
|
-
features: plan.features,
|
|
41281
|
-
action: { label: plan.actionLabel, href: plan.actionHref },
|
|
41282
|
-
highlighted: plan.highlighted,
|
|
41283
|
-
badge: plan.badge
|
|
41484
|
+
name: String(plan.name ?? ""),
|
|
41485
|
+
price: String(plan.price ?? ""),
|
|
41486
|
+
description: plan.description != null ? String(plan.description) : void 0,
|
|
41487
|
+
features: (plan.features ?? []).map((f3) => String(f3)),
|
|
41488
|
+
action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
|
|
41489
|
+
highlighted: Boolean(plan.highlighted),
|
|
41490
|
+
badge: plan.badge != null ? String(plan.badge) : void 0
|
|
41284
41491
|
}));
|
|
41285
41492
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
41286
41493
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -43370,16 +43577,20 @@ function SequencerBoard({
|
|
|
43370
43577
|
}) {
|
|
43371
43578
|
const { emit } = useEventBus();
|
|
43372
43579
|
const { t } = useTranslate();
|
|
43373
|
-
const resolved =
|
|
43580
|
+
const resolved = boardEntity(entity);
|
|
43581
|
+
const maxSlots = num(resolved?.maxSlots);
|
|
43582
|
+
const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
|
|
43583
|
+
const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
|
|
43584
|
+
const allowDuplicates = resolved?.allowDuplicates !== false;
|
|
43374
43585
|
const [headerError, setHeaderError] = useState(false);
|
|
43375
43586
|
const [slots, setSlots] = useState(
|
|
43376
|
-
() => Array.from({ length:
|
|
43587
|
+
() => Array.from({ length: maxSlots }, () => void 0)
|
|
43377
43588
|
);
|
|
43378
43589
|
const [playState, setPlayState] = useState("idle");
|
|
43379
43590
|
const [currentStep, setCurrentStep] = useState(-1);
|
|
43380
43591
|
const [attempts, setAttempts] = useState(0);
|
|
43381
43592
|
const [slotFeedback, setSlotFeedback] = useState(
|
|
43382
|
-
() => Array.from({ length:
|
|
43593
|
+
() => Array.from({ length: maxSlots }, () => null)
|
|
43383
43594
|
);
|
|
43384
43595
|
const timerRef = useRef(null);
|
|
43385
43596
|
useEffect(() => () => {
|
|
@@ -43413,17 +43624,17 @@ function SequencerBoard({
|
|
|
43413
43624
|
}, [emit]);
|
|
43414
43625
|
const handleReset = useCallback(() => {
|
|
43415
43626
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
43416
|
-
setSlots(Array.from({ length:
|
|
43627
|
+
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
43417
43628
|
setPlayState("idle");
|
|
43418
43629
|
setCurrentStep(-1);
|
|
43419
43630
|
setAttempts(0);
|
|
43420
|
-
setSlotFeedback(Array.from({ length:
|
|
43421
|
-
}, [
|
|
43631
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
43632
|
+
}, [maxSlots]);
|
|
43422
43633
|
const filledSlots = slots.filter((s) => !!s);
|
|
43423
43634
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
43424
43635
|
const handlePlay = useCallback(() => {
|
|
43425
43636
|
if (!canPlay) return;
|
|
43426
|
-
setSlotFeedback(Array.from({ length:
|
|
43637
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
43427
43638
|
emit("UI:PLAY_SOUND", { key: "confirm" });
|
|
43428
43639
|
const sequence = slots.map((s) => s?.id || "");
|
|
43429
43640
|
if (playEvent) {
|
|
@@ -43434,10 +43645,10 @@ function SequencerBoard({
|
|
|
43434
43645
|
let step = 0;
|
|
43435
43646
|
const advance = () => {
|
|
43436
43647
|
step++;
|
|
43437
|
-
if (step >=
|
|
43648
|
+
if (step >= maxSlots) {
|
|
43438
43649
|
const playerSeq = slots.map((s) => s?.id);
|
|
43439
43650
|
const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
|
|
43440
|
-
const success =
|
|
43651
|
+
const success = solutions.some(
|
|
43441
43652
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
43442
43653
|
);
|
|
43443
43654
|
if (success) {
|
|
@@ -43449,7 +43660,7 @@ function SequencerBoard({
|
|
|
43449
43660
|
}
|
|
43450
43661
|
} else {
|
|
43451
43662
|
setAttempts((prev) => prev + 1);
|
|
43452
|
-
const feedback = computeSlotFeedback(playerSeq,
|
|
43663
|
+
const feedback = computeSlotFeedback(playerSeq, solutions);
|
|
43453
43664
|
setSlotFeedback(feedback);
|
|
43454
43665
|
setPlayState("idle");
|
|
43455
43666
|
setCurrentStep(-1);
|
|
@@ -43467,10 +43678,10 @@ function SequencerBoard({
|
|
|
43467
43678
|
}
|
|
43468
43679
|
};
|
|
43469
43680
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
43470
|
-
}, [canPlay, slots,
|
|
43681
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
43471
43682
|
const machine = {
|
|
43472
|
-
name: resolved?.title
|
|
43473
|
-
description: resolved?.description
|
|
43683
|
+
name: str(resolved?.title),
|
|
43684
|
+
description: str(resolved?.description),
|
|
43474
43685
|
states: slots.map((s, i) => stepLabel(s, i)),
|
|
43475
43686
|
currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
|
|
43476
43687
|
transitions: slots.slice(0, -1).map((s, i) => ({
|
|
@@ -43479,37 +43690,41 @@ function SequencerBoard({
|
|
|
43479
43690
|
event: "NEXT"
|
|
43480
43691
|
}))
|
|
43481
43692
|
};
|
|
43482
|
-
const usedIds =
|
|
43483
|
-
const
|
|
43693
|
+
const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
|
|
43694
|
+
const hint = str(resolved?.hint);
|
|
43695
|
+
const showHint = attempts >= 3 && !!hint;
|
|
43484
43696
|
const hasFeedback = slotFeedback.some((f3) => f3 !== null);
|
|
43485
43697
|
const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
|
|
43486
43698
|
const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
|
|
43487
43699
|
if (!resolved) return null;
|
|
43700
|
+
const theme = resolved.theme ?? void 0;
|
|
43701
|
+
const themeBackground = theme?.background;
|
|
43702
|
+
const headerImage = str(resolved.headerImage);
|
|
43488
43703
|
return /* @__PURE__ */ jsxs(
|
|
43489
43704
|
VStack,
|
|
43490
43705
|
{
|
|
43491
43706
|
className: cn("p-4 gap-6", className),
|
|
43492
43707
|
style: {
|
|
43493
|
-
backgroundImage:
|
|
43708
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
43494
43709
|
backgroundSize: "cover",
|
|
43495
43710
|
backgroundPosition: "center"
|
|
43496
43711
|
},
|
|
43497
43712
|
children: [
|
|
43498
|
-
|
|
43713
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
43499
43714
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
43500
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
43501
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
|
|
43715
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
43716
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
|
|
43502
43717
|
] }),
|
|
43503
43718
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
43504
43719
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
43505
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
43720
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
43506
43721
|
] }) }),
|
|
43507
43722
|
filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
43508
43723
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
43509
43724
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
43510
43725
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
43511
43726
|
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
43512
|
-
`${correctCount}/${
|
|
43727
|
+
`${correctCount}/${maxSlots} `,
|
|
43513
43728
|
"\u2705"
|
|
43514
43729
|
] })
|
|
43515
43730
|
] }),
|
|
@@ -43517,7 +43732,7 @@ function SequencerBoard({
|
|
|
43517
43732
|
SequenceBar,
|
|
43518
43733
|
{
|
|
43519
43734
|
slots,
|
|
43520
|
-
maxSlots
|
|
43735
|
+
maxSlots,
|
|
43521
43736
|
onSlotDrop: handleSlotDrop,
|
|
43522
43737
|
onSlotRemove: handleSlotRemove,
|
|
43523
43738
|
playing: playState === "playing",
|
|
@@ -43531,15 +43746,15 @@ function SequencerBoard({
|
|
|
43531
43746
|
playState !== "playing" && /* @__PURE__ */ jsx(
|
|
43532
43747
|
ActionPalette,
|
|
43533
43748
|
{
|
|
43534
|
-
actions:
|
|
43749
|
+
actions: availableActions,
|
|
43535
43750
|
usedActionIds: usedIds,
|
|
43536
|
-
allowDuplicates
|
|
43751
|
+
allowDuplicates,
|
|
43537
43752
|
categoryColors,
|
|
43538
43753
|
label: t("sequencer.dragActions")
|
|
43539
43754
|
}
|
|
43540
43755
|
),
|
|
43541
43756
|
hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
|
|
43542
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("sequencer.levelComplete") }) }),
|
|
43757
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("sequencer.levelComplete") }) }),
|
|
43543
43758
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
43544
43759
|
/* @__PURE__ */ jsx(
|
|
43545
43760
|
Button,
|
|
@@ -43563,6 +43778,7 @@ var init_SequencerBoard = __esm({
|
|
|
43563
43778
|
init_cn();
|
|
43564
43779
|
init_useEventBus();
|
|
43565
43780
|
init_TraitStateViewer();
|
|
43781
|
+
init_boardEntity();
|
|
43566
43782
|
init_SequenceBar();
|
|
43567
43783
|
init_ActionPalette();
|
|
43568
43784
|
ENCOURAGEMENT_KEYS2 = [
|
|
@@ -43612,18 +43828,21 @@ var init_ShowcaseOrganism = __esm({
|
|
|
43612
43828
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
43613
43829
|
subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
|
|
43614
43830
|
] }),
|
|
43615
|
-
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) =>
|
|
43616
|
-
|
|
43617
|
-
|
|
43618
|
-
|
|
43619
|
-
|
|
43620
|
-
|
|
43621
|
-
|
|
43622
|
-
|
|
43623
|
-
|
|
43624
|
-
|
|
43625
|
-
|
|
43626
|
-
|
|
43831
|
+
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
|
|
43832
|
+
const imageRaw = item.image;
|
|
43833
|
+
return /* @__PURE__ */ jsx(
|
|
43834
|
+
ShowcaseCard,
|
|
43835
|
+
{
|
|
43836
|
+
title: String(item.title ?? ""),
|
|
43837
|
+
description: item.description != null ? String(item.description) : void 0,
|
|
43838
|
+
image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
|
|
43839
|
+
href: item.href != null ? String(item.href) : void 0,
|
|
43840
|
+
badge: item.badge != null ? String(item.badge) : void 0,
|
|
43841
|
+
accentColor: item.accentColor != null ? String(item.accentColor) : void 0
|
|
43842
|
+
},
|
|
43843
|
+
String(item.id ?? "")
|
|
43844
|
+
);
|
|
43845
|
+
}) })
|
|
43627
43846
|
] });
|
|
43628
43847
|
};
|
|
43629
43848
|
ShowcaseOrganism.displayName = "ShowcaseOrganism";
|
|
@@ -43991,8 +44210,8 @@ function SimulatorBoard({
|
|
|
43991
44210
|
}) {
|
|
43992
44211
|
const { emit } = useEventBus();
|
|
43993
44212
|
const { t } = useTranslate();
|
|
43994
|
-
const resolved =
|
|
43995
|
-
const parameters = resolved?.parameters
|
|
44213
|
+
const resolved = boardEntity(entity);
|
|
44214
|
+
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
43996
44215
|
const [values, setValues] = useState(() => {
|
|
43997
44216
|
const init = {};
|
|
43998
44217
|
for (const p2 of parameters) {
|
|
@@ -44006,15 +44225,15 @@ function SimulatorBoard({
|
|
|
44006
44225
|
const [showHint, setShowHint] = useState(false);
|
|
44007
44226
|
const computeOutput = useCallback((params) => {
|
|
44008
44227
|
try {
|
|
44009
|
-
const fn = new Function("params", `return (${resolved?.computeExpression})`);
|
|
44228
|
+
const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
|
|
44010
44229
|
return fn(params);
|
|
44011
44230
|
} catch {
|
|
44012
44231
|
return 0;
|
|
44013
44232
|
}
|
|
44014
44233
|
}, [resolved?.computeExpression]);
|
|
44015
44234
|
const output = useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
|
|
44016
|
-
const targetValue = resolved?.targetValue
|
|
44017
|
-
const targetTolerance = resolved?.targetTolerance
|
|
44235
|
+
const targetValue = num(resolved?.targetValue);
|
|
44236
|
+
const targetTolerance = num(resolved?.targetTolerance);
|
|
44018
44237
|
const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
|
|
44019
44238
|
const handleParameterChange = (id, value) => {
|
|
44020
44239
|
if (submitted) return;
|
|
@@ -44029,7 +44248,7 @@ function SimulatorBoard({
|
|
|
44029
44248
|
};
|
|
44030
44249
|
const handleReset = () => {
|
|
44031
44250
|
setSubmitted(false);
|
|
44032
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
44251
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
44033
44252
|
setShowHint(true);
|
|
44034
44253
|
}
|
|
44035
44254
|
};
|
|
@@ -44044,20 +44263,26 @@ function SimulatorBoard({
|
|
|
44044
44263
|
setShowHint(false);
|
|
44045
44264
|
};
|
|
44046
44265
|
if (!resolved) return null;
|
|
44266
|
+
const theme = resolved.theme ?? void 0;
|
|
44267
|
+
const themeBackground = theme?.background;
|
|
44268
|
+
const headerImage = str(resolved.headerImage);
|
|
44269
|
+
const hint = str(resolved.hint);
|
|
44270
|
+
const outputLabel = str(resolved.outputLabel);
|
|
44271
|
+
const outputUnit = str(resolved.outputUnit);
|
|
44047
44272
|
return /* @__PURE__ */ jsx(
|
|
44048
44273
|
Box,
|
|
44049
44274
|
{
|
|
44050
44275
|
className,
|
|
44051
44276
|
style: {
|
|
44052
|
-
backgroundImage:
|
|
44277
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44053
44278
|
backgroundSize: "cover",
|
|
44054
44279
|
backgroundPosition: "center"
|
|
44055
44280
|
},
|
|
44056
44281
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
44057
|
-
|
|
44282
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44058
44283
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44059
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
44060
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
44284
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
44285
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
44061
44286
|
] }) }),
|
|
44062
44287
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
44063
44288
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
@@ -44098,28 +44323,28 @@ function SimulatorBoard({
|
|
|
44098
44323
|
] }, param.id))
|
|
44099
44324
|
] }) }),
|
|
44100
44325
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
44101
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children:
|
|
44326
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
44102
44327
|
/* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
44103
44328
|
output.toFixed(2),
|
|
44104
44329
|
" ",
|
|
44105
|
-
|
|
44330
|
+
outputUnit
|
|
44106
44331
|
] }),
|
|
44107
44332
|
submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
44108
44333
|
/* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
|
|
44109
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage
|
|
44334
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
44110
44335
|
] }),
|
|
44111
44336
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
44112
44337
|
t("simulator.target"),
|
|
44113
44338
|
": ",
|
|
44114
44339
|
targetValue,
|
|
44115
44340
|
" ",
|
|
44116
|
-
|
|
44341
|
+
outputUnit,
|
|
44117
44342
|
" (\xB1",
|
|
44118
44343
|
targetTolerance,
|
|
44119
44344
|
")"
|
|
44120
44345
|
] })
|
|
44121
44346
|
] }) }),
|
|
44122
|
-
showHint &&
|
|
44347
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
44123
44348
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
44124
44349
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
44125
44350
|
/* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
|
|
@@ -44138,6 +44363,7 @@ var init_SimulatorBoard = __esm({
|
|
|
44138
44363
|
"components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
|
|
44139
44364
|
init_atoms2();
|
|
44140
44365
|
init_useEventBus();
|
|
44366
|
+
init_boardEntity();
|
|
44141
44367
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
44142
44368
|
}
|
|
44143
44369
|
});
|
|
@@ -44563,22 +44789,25 @@ function VariablePanel({
|
|
|
44563
44789
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
44564
44790
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
|
|
44565
44791
|
variables.map((v) => {
|
|
44566
|
-
const
|
|
44567
|
-
const
|
|
44568
|
-
const
|
|
44792
|
+
const name = v.name == null ? "" : String(v.name);
|
|
44793
|
+
const value = numField(v.value);
|
|
44794
|
+
const max = numField(v.max, 100);
|
|
44795
|
+
const min = numField(v.min, 0);
|
|
44796
|
+
const unit = v.unit == null ? "" : String(v.unit);
|
|
44797
|
+
const pct = Math.round((value - min) / (max - min) * 100);
|
|
44569
44798
|
const isHigh = pct > 80;
|
|
44570
44799
|
const isLow = pct < 20;
|
|
44571
44800
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
44572
44801
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
44573
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children:
|
|
44802
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
|
|
44574
44803
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: cn(
|
|
44575
44804
|
isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
|
|
44576
44805
|
), children: [
|
|
44577
|
-
|
|
44578
|
-
|
|
44806
|
+
value,
|
|
44807
|
+
unit,
|
|
44579
44808
|
" / ",
|
|
44580
44809
|
max,
|
|
44581
|
-
|
|
44810
|
+
unit
|
|
44582
44811
|
] })
|
|
44583
44812
|
] }),
|
|
44584
44813
|
/* @__PURE__ */ jsx(
|
|
@@ -44589,14 +44818,19 @@ function VariablePanel({
|
|
|
44589
44818
|
size: "sm"
|
|
44590
44819
|
}
|
|
44591
44820
|
)
|
|
44592
|
-
] },
|
|
44821
|
+
] }, name);
|
|
44593
44822
|
})
|
|
44594
44823
|
] });
|
|
44595
44824
|
}
|
|
44825
|
+
var numField;
|
|
44596
44826
|
var init_VariablePanel = __esm({
|
|
44597
44827
|
"components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
|
|
44598
44828
|
init_atoms2();
|
|
44599
44829
|
init_cn();
|
|
44830
|
+
numField = (v, fallback = 0) => {
|
|
44831
|
+
const n = Number(v);
|
|
44832
|
+
return Number.isFinite(n) ? n : fallback;
|
|
44833
|
+
};
|
|
44600
44834
|
VariablePanel.displayName = "VariablePanel";
|
|
44601
44835
|
}
|
|
44602
44836
|
});
|
|
@@ -44623,14 +44857,21 @@ function StateArchitectBoard({
|
|
|
44623
44857
|
}) {
|
|
44624
44858
|
const { emit } = useEventBus();
|
|
44625
44859
|
const { t } = useTranslate();
|
|
44626
|
-
const resolved =
|
|
44627
|
-
const
|
|
44860
|
+
const resolved = boardEntity(entity);
|
|
44861
|
+
const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
|
|
44862
|
+
const initialState = str(resolved?.initialState);
|
|
44863
|
+
const entityName = str(resolved?.entityName);
|
|
44864
|
+
const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
|
|
44865
|
+
const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
|
|
44866
|
+
const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
|
|
44867
|
+
const entityVariables = rows(resolved?.variables);
|
|
44868
|
+
const [transitions, setTransitions] = useState(entityTransitions);
|
|
44628
44869
|
const [headerError, setHeaderError] = useState(false);
|
|
44629
44870
|
const [playState, setPlayState] = useState("editing");
|
|
44630
|
-
const [currentState, setCurrentState] = useState(
|
|
44871
|
+
const [currentState, setCurrentState] = useState(initialState);
|
|
44631
44872
|
const [selectedState, setSelectedState] = useState(null);
|
|
44632
44873
|
const [testResults, setTestResults] = useState([]);
|
|
44633
|
-
const [variables, setVariables] = useState(
|
|
44874
|
+
const [variables, setVariables] = useState(() => [...entityVariables]);
|
|
44634
44875
|
const [attempts, setAttempts] = useState(0);
|
|
44635
44876
|
const timerRef = useRef(null);
|
|
44636
44877
|
const [addingFrom, setAddingFrom] = useState(null);
|
|
@@ -44639,12 +44880,12 @@ function StateArchitectBoard({
|
|
|
44639
44880
|
}, []);
|
|
44640
44881
|
const GRAPH_W = 500;
|
|
44641
44882
|
const GRAPH_H = 400;
|
|
44642
|
-
const positions = useMemo(() => layoutStates(
|
|
44883
|
+
const positions = useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
|
|
44643
44884
|
const handleStateClick = useCallback((state) => {
|
|
44644
44885
|
if (playState !== "editing") return;
|
|
44645
44886
|
if (addingFrom) {
|
|
44646
44887
|
if (addingFrom !== state) {
|
|
44647
|
-
const event =
|
|
44888
|
+
const event = availableEvents[0] || "EVENT";
|
|
44648
44889
|
const newTrans = {
|
|
44649
44890
|
id: `t-${nextTransId++}`,
|
|
44650
44891
|
from: addingFrom,
|
|
@@ -44657,7 +44898,7 @@ function StateArchitectBoard({
|
|
|
44657
44898
|
} else {
|
|
44658
44899
|
setSelectedState(state);
|
|
44659
44900
|
}
|
|
44660
|
-
}, [playState, addingFrom,
|
|
44901
|
+
}, [playState, addingFrom, availableEvents]);
|
|
44661
44902
|
const handleStartAddTransition = useCallback(() => {
|
|
44662
44903
|
if (!selectedState) return;
|
|
44663
44904
|
setAddingFrom(selectedState);
|
|
@@ -44666,9 +44907,9 @@ function StateArchitectBoard({
|
|
|
44666
44907
|
setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
|
|
44667
44908
|
}, []);
|
|
44668
44909
|
const machine = useMemo(() => ({
|
|
44669
|
-
name:
|
|
44670
|
-
description: resolved?.description
|
|
44671
|
-
states:
|
|
44910
|
+
name: entityName,
|
|
44911
|
+
description: str(resolved?.description),
|
|
44912
|
+
states: entityStates,
|
|
44672
44913
|
currentState,
|
|
44673
44914
|
transitions: transitions.map((t2) => ({
|
|
44674
44915
|
from: t2.from,
|
|
@@ -44676,7 +44917,7 @@ function StateArchitectBoard({
|
|
|
44676
44917
|
event: t2.event,
|
|
44677
44918
|
guardHint: t2.guardHint
|
|
44678
44919
|
}))
|
|
44679
|
-
}), [resolved, currentState, transitions]);
|
|
44920
|
+
}), [entityName, resolved, entityStates, currentState, transitions]);
|
|
44680
44921
|
const handleTest = useCallback(() => {
|
|
44681
44922
|
if (playState !== "editing") return;
|
|
44682
44923
|
if (testEvent) emit(`UI:${testEvent}`, {});
|
|
@@ -44685,7 +44926,7 @@ function StateArchitectBoard({
|
|
|
44685
44926
|
const results = [];
|
|
44686
44927
|
let testIdx = 0;
|
|
44687
44928
|
const runNextTest = () => {
|
|
44688
|
-
if (testIdx >=
|
|
44929
|
+
if (testIdx >= testCases.length) {
|
|
44689
44930
|
const allPassed = results.every((r) => r.passed);
|
|
44690
44931
|
setPlayState(allPassed ? "success" : "fail");
|
|
44691
44932
|
setTestResults(results);
|
|
@@ -44700,9 +44941,9 @@ function StateArchitectBoard({
|
|
|
44700
44941
|
}
|
|
44701
44942
|
return;
|
|
44702
44943
|
}
|
|
44703
|
-
const testCase =
|
|
44944
|
+
const testCase = testCases[testIdx];
|
|
44704
44945
|
if (!testCase) return;
|
|
44705
|
-
let state =
|
|
44946
|
+
let state = initialState;
|
|
44706
44947
|
for (const event of testCase.events) {
|
|
44707
44948
|
const trans = transitions.find((t2) => t2.from === state && t2.event === event);
|
|
44708
44949
|
if (trans) {
|
|
@@ -44720,53 +44961,57 @@ function StateArchitectBoard({
|
|
|
44720
44961
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
44721
44962
|
};
|
|
44722
44963
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
44723
|
-
}, [playState, transitions,
|
|
44964
|
+
}, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
|
|
44724
44965
|
const handleTryAgain = useCallback(() => {
|
|
44725
44966
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44726
44967
|
setPlayState("editing");
|
|
44727
|
-
setCurrentState(
|
|
44968
|
+
setCurrentState(initialState);
|
|
44728
44969
|
setTestResults([]);
|
|
44729
|
-
}, [
|
|
44970
|
+
}, [initialState]);
|
|
44730
44971
|
const handleReset = useCallback(() => {
|
|
44731
44972
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44732
|
-
setTransitions(
|
|
44973
|
+
setTransitions(entityTransitions);
|
|
44733
44974
|
setPlayState("editing");
|
|
44734
|
-
setCurrentState(
|
|
44975
|
+
setCurrentState(initialState);
|
|
44735
44976
|
setTestResults([]);
|
|
44736
|
-
setVariables(
|
|
44977
|
+
setVariables([...entityVariables]);
|
|
44737
44978
|
setSelectedState(null);
|
|
44738
44979
|
setAddingFrom(null);
|
|
44739
44980
|
setAttempts(0);
|
|
44740
|
-
}, [
|
|
44981
|
+
}, [entityTransitions, initialState, entityVariables]);
|
|
44741
44982
|
const codeData = useMemo(() => ({
|
|
44742
|
-
name:
|
|
44743
|
-
states:
|
|
44744
|
-
initialState
|
|
44983
|
+
name: entityName,
|
|
44984
|
+
states: entityStates,
|
|
44985
|
+
initialState,
|
|
44745
44986
|
transitions: transitions.map((t2) => ({
|
|
44746
44987
|
from: t2.from,
|
|
44747
44988
|
to: t2.to,
|
|
44748
44989
|
event: t2.event,
|
|
44749
44990
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
44750
44991
|
}))
|
|
44751
|
-
}), [
|
|
44992
|
+
}), [entityName, entityStates, initialState, transitions]);
|
|
44752
44993
|
if (!resolved) return null;
|
|
44994
|
+
const theme = resolved.theme ?? void 0;
|
|
44995
|
+
const themeBackground = theme?.background;
|
|
44996
|
+
const headerImage = str(resolved.headerImage);
|
|
44997
|
+
const hint = str(resolved.hint);
|
|
44753
44998
|
return /* @__PURE__ */ jsxs(
|
|
44754
44999
|
VStack,
|
|
44755
45000
|
{
|
|
44756
45001
|
className: cn("p-4 gap-6", className),
|
|
44757
45002
|
style: {
|
|
44758
|
-
backgroundImage:
|
|
45003
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44759
45004
|
backgroundSize: "cover",
|
|
44760
45005
|
backgroundPosition: "center"
|
|
44761
45006
|
},
|
|
44762
45007
|
children: [
|
|
44763
|
-
|
|
45008
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44764
45009
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
44765
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
44766
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
45010
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
45011
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
44767
45012
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
44768
45013
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
44769
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children:
|
|
45014
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
|
|
44770
45015
|
] })
|
|
44771
45016
|
] }),
|
|
44772
45017
|
/* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
@@ -44814,14 +45059,14 @@ function StateArchitectBoard({
|
|
|
44814
45059
|
]
|
|
44815
45060
|
}
|
|
44816
45061
|
),
|
|
44817
|
-
|
|
45062
|
+
entityStates.map((state) => /* @__PURE__ */ jsx(
|
|
44818
45063
|
StateNode2,
|
|
44819
45064
|
{
|
|
44820
45065
|
name: state,
|
|
44821
45066
|
position: positions[state],
|
|
44822
45067
|
isCurrent: state === currentState,
|
|
44823
45068
|
isSelected: state === selectedState,
|
|
44824
|
-
isInitial: state ===
|
|
45069
|
+
isInitial: state === initialState,
|
|
44825
45070
|
onClick: () => handleStateClick(state)
|
|
44826
45071
|
},
|
|
44827
45072
|
state
|
|
@@ -44868,7 +45113,7 @@ function StateArchitectBoard({
|
|
|
44868
45113
|
/* @__PURE__ */ jsx(
|
|
44869
45114
|
VariablePanel,
|
|
44870
45115
|
{
|
|
44871
|
-
entityName
|
|
45116
|
+
entityName,
|
|
44872
45117
|
variables
|
|
44873
45118
|
}
|
|
44874
45119
|
),
|
|
@@ -44883,12 +45128,12 @@ function StateArchitectBoard({
|
|
|
44883
45128
|
resolved.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
|
|
44884
45129
|
] })
|
|
44885
45130
|
] }),
|
|
44886
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("stateArchitect.allPassed") }) }),
|
|
45131
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
|
|
44887
45132
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44888
45133
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(ENCOURAGEMENT_KEYS3[Math.min(attempts - 1, ENCOURAGEMENT_KEYS3.length - 1)] ?? ENCOURAGEMENT_KEYS3[0]) }) }),
|
|
44889
|
-
attempts >= 3 &&
|
|
45134
|
+
attempts >= 3 && hint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
44890
45135
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
44891
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
45136
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
44892
45137
|
] }) })
|
|
44893
45138
|
] }),
|
|
44894
45139
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -44918,6 +45163,7 @@ var init_StateArchitectBoard = __esm({
|
|
|
44918
45163
|
init_TransitionArrow();
|
|
44919
45164
|
init_VariablePanel();
|
|
44920
45165
|
init_CodeView();
|
|
45166
|
+
init_boardEntity();
|
|
44921
45167
|
ENCOURAGEMENT_KEYS3 = [
|
|
44922
45168
|
"puzzle.tryAgain1",
|
|
44923
45169
|
"puzzle.tryAgain2",
|
|
@@ -44954,8 +45200,8 @@ var init_StatsOrganism = __esm({
|
|
|
44954
45200
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
44955
45201
|
}
|
|
44956
45202
|
const stats = items.map((item) => ({
|
|
44957
|
-
value: item.value,
|
|
44958
|
-
label: item.label
|
|
45203
|
+
value: String(item.value ?? ""),
|
|
45204
|
+
label: String(item.label ?? "")
|
|
44959
45205
|
}));
|
|
44960
45206
|
return /* @__PURE__ */ jsx(
|
|
44961
45207
|
StatsGrid,
|
|
@@ -45001,10 +45247,10 @@ var init_StepFlowOrganism = __esm({
|
|
|
45001
45247
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
45002
45248
|
}
|
|
45003
45249
|
const steps = items.map((item) => ({
|
|
45004
|
-
number: item.number,
|
|
45005
|
-
title: item.title,
|
|
45006
|
-
description: item.description,
|
|
45007
|
-
icon: item.icon
|
|
45250
|
+
number: item.number != null ? Number(item.number) : void 0,
|
|
45251
|
+
title: String(item.title ?? ""),
|
|
45252
|
+
description: String(item.description ?? ""),
|
|
45253
|
+
icon: item.icon != null ? String(item.icon) : void 0
|
|
45008
45254
|
}));
|
|
45009
45255
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
45010
45256
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -45177,13 +45423,13 @@ var init_TeamOrganism = __esm({
|
|
|
45177
45423
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsx(
|
|
45178
45424
|
TeamCard,
|
|
45179
45425
|
{
|
|
45180
|
-
name: member.name,
|
|
45181
|
-
nameAr: member.nameAr,
|
|
45182
|
-
role: member.role,
|
|
45183
|
-
bio: member.bio,
|
|
45184
|
-
avatar: member.avatar
|
|
45426
|
+
name: String(member.name ?? ""),
|
|
45427
|
+
nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
|
|
45428
|
+
role: String(member.role ?? ""),
|
|
45429
|
+
bio: String(member.bio ?? ""),
|
|
45430
|
+
avatar: member.avatar != null ? String(member.avatar) : void 0
|
|
45185
45431
|
},
|
|
45186
|
-
member.id
|
|
45432
|
+
String(member.id ?? "")
|
|
45187
45433
|
)) })
|
|
45188
45434
|
] });
|
|
45189
45435
|
};
|
|
@@ -45420,8 +45666,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45420
45666
|
const [turn, setTurn] = useState(1);
|
|
45421
45667
|
const [gameResult, setGameResult] = useState(null);
|
|
45422
45668
|
const checkGameEnd = useCallback((currentUnits) => {
|
|
45423
|
-
const pa = currentUnits.filter((u) => u
|
|
45424
|
-
const ea = currentUnits.filter((u) => u
|
|
45669
|
+
const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
45670
|
+
const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
45425
45671
|
if (pa.length === 0) {
|
|
45426
45672
|
setGameResult("defeat");
|
|
45427
45673
|
setPhase("game_over");
|
|
@@ -45439,34 +45685,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45439
45685
|
}
|
|
45440
45686
|
}, [onGameEnd, gameEndEvent, eventBus]);
|
|
45441
45687
|
const handleUnitClick = useCallback((unitId) => {
|
|
45442
|
-
const unit = units.find((u) => u.id === unitId);
|
|
45688
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
45443
45689
|
if (!unit) return;
|
|
45444
45690
|
if (unitClickEvent) {
|
|
45445
45691
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
45446
45692
|
}
|
|
45447
45693
|
if (phase === "observation" || phase === "selection") {
|
|
45448
|
-
if (unit
|
|
45694
|
+
if (unitTeam(unit) === "player") {
|
|
45449
45695
|
setSelectedUnitId(unitId);
|
|
45450
45696
|
setPhase("movement");
|
|
45451
45697
|
}
|
|
45452
45698
|
} else if (phase === "action") {
|
|
45453
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
45699
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45454
45700
|
if (!selectedUnit) return;
|
|
45455
|
-
if (unit
|
|
45456
|
-
const
|
|
45457
|
-
const
|
|
45701
|
+
if (unitTeam(unit) === "enemy") {
|
|
45702
|
+
const up = unitPosition(unit);
|
|
45703
|
+
const sp = unitPosition(selectedUnit);
|
|
45704
|
+
const dx = Math.abs(up.x - sp.x);
|
|
45705
|
+
const dy = Math.abs(up.y - sp.y);
|
|
45458
45706
|
if (dx <= 1 && dy <= 1 && dx + dy > 0) {
|
|
45459
|
-
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
45460
|
-
const newHealth = Math.max(0, unit
|
|
45707
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
45708
|
+
const newHealth = Math.max(0, unitHealth(unit) - damage);
|
|
45461
45709
|
const updatedUnits = units.map(
|
|
45462
|
-
(u) => u.id === unit.id ? { ...u, health: newHealth } : u
|
|
45710
|
+
(u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
|
|
45463
45711
|
);
|
|
45464
45712
|
setUnits(updatedUnits);
|
|
45465
45713
|
onAttack?.(selectedUnit, unit, damage);
|
|
45466
45714
|
if (attackEvent) {
|
|
45467
45715
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
45468
|
-
attackerId: selectedUnit.id,
|
|
45469
|
-
targetId: unit.id,
|
|
45716
|
+
attackerId: str(selectedUnit.id),
|
|
45717
|
+
targetId: str(unit.id),
|
|
45470
45718
|
damage
|
|
45471
45719
|
});
|
|
45472
45720
|
}
|
|
@@ -45483,16 +45731,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45483
45731
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
45484
45732
|
}
|
|
45485
45733
|
if (phase === "movement" && selectedUnitId) {
|
|
45486
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
45734
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45487
45735
|
if (!selectedUnit) return;
|
|
45488
|
-
const
|
|
45489
|
-
const
|
|
45736
|
+
const sp = unitPosition(selectedUnit);
|
|
45737
|
+
const dx = Math.abs(x - sp.x);
|
|
45738
|
+
const dy = Math.abs(y - sp.y);
|
|
45490
45739
|
const dist = dx + dy;
|
|
45491
|
-
if (dist > 0 && dist <= selectedUnit.movement) {
|
|
45492
|
-
if (!units.some((u) =>
|
|
45740
|
+
if (dist > 0 && dist <= num(selectedUnit.movement)) {
|
|
45741
|
+
if (!units.some((u) => {
|
|
45742
|
+
const p2 = unitPosition(u);
|
|
45743
|
+
return p2.x === x && p2.y === y && unitHealth(u) > 0;
|
|
45744
|
+
})) {
|
|
45493
45745
|
setUnits(
|
|
45494
45746
|
(prev) => prev.map(
|
|
45495
|
-
(u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
45747
|
+
(u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
45496
45748
|
)
|
|
45497
45749
|
);
|
|
45498
45750
|
setPhase("action");
|
|
@@ -45535,12 +45787,13 @@ var init_useBattleState = __esm({
|
|
|
45535
45787
|
"components/game/organisms/hooks/useBattleState.ts"() {
|
|
45536
45788
|
"use client";
|
|
45537
45789
|
init_useEventBus();
|
|
45790
|
+
init_boardEntity();
|
|
45538
45791
|
}
|
|
45539
45792
|
});
|
|
45540
45793
|
function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
45541
|
-
const resolved =
|
|
45794
|
+
const resolved = boardEntity(entity);
|
|
45542
45795
|
const battleState = useBattleState(
|
|
45543
|
-
resolved?.initialUnits
|
|
45796
|
+
rows(resolved?.initialUnits),
|
|
45544
45797
|
{
|
|
45545
45798
|
tileClickEvent: rest.tileClickEvent,
|
|
45546
45799
|
unitClickEvent: rest.unitClickEvent,
|
|
@@ -45576,10 +45829,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
|
45576
45829
|
var init_UncontrolledBattleBoard = __esm({
|
|
45577
45830
|
"components/game/organisms/UncontrolledBattleBoard.tsx"() {
|
|
45578
45831
|
init_BattleBoard();
|
|
45832
|
+
init_boardEntity();
|
|
45579
45833
|
init_useBattleState();
|
|
45580
45834
|
UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
|
|
45581
45835
|
}
|
|
45582
45836
|
});
|
|
45837
|
+
function heroPosition(h) {
|
|
45838
|
+
return vec2(h.position);
|
|
45839
|
+
}
|
|
45840
|
+
function heroOwner(h) {
|
|
45841
|
+
return str(h.owner);
|
|
45842
|
+
}
|
|
45843
|
+
function heroMovement(h) {
|
|
45844
|
+
return num(h.movement);
|
|
45845
|
+
}
|
|
45846
|
+
function hexPassable(h) {
|
|
45847
|
+
return h.passable !== false;
|
|
45848
|
+
}
|
|
45583
45849
|
function defaultIsInRange(from, to, range) {
|
|
45584
45850
|
return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
|
|
45585
45851
|
}
|
|
@@ -45610,36 +45876,36 @@ function WorldMapBoard({
|
|
|
45610
45876
|
className
|
|
45611
45877
|
}) {
|
|
45612
45878
|
const eventBus = useEventBus();
|
|
45613
|
-
const resolved =
|
|
45614
|
-
const hexes = resolved?.hexes
|
|
45615
|
-
const heroes = resolved?.heroes
|
|
45616
|
-
const features = resolved?.features
|
|
45617
|
-
const selectedHeroId = resolved?.selectedHeroId;
|
|
45879
|
+
const resolved = boardEntity(entity);
|
|
45880
|
+
const hexes = rows(resolved?.hexes);
|
|
45881
|
+
const heroes = rows(resolved?.heroes);
|
|
45882
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
45883
|
+
const selectedHeroId = resolved?.selectedHeroId ?? null;
|
|
45618
45884
|
const assetManifest = resolved?.assetManifest;
|
|
45619
45885
|
const backgroundImage = resolved?.backgroundImage;
|
|
45620
45886
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
45621
45887
|
const selectedHero = useMemo(
|
|
45622
|
-
() => heroes.find((h) => h.id === selectedHeroId) ?? null,
|
|
45888
|
+
() => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
|
|
45623
45889
|
[heroes, selectedHeroId]
|
|
45624
45890
|
);
|
|
45625
45891
|
const tiles = useMemo(
|
|
45626
45892
|
() => hexes.map((hex) => ({
|
|
45627
|
-
x: hex.x,
|
|
45628
|
-
y: hex.y,
|
|
45629
|
-
terrain: hex.terrain,
|
|
45630
|
-
terrainSprite: hex.terrainSprite
|
|
45893
|
+
x: num(hex.x),
|
|
45894
|
+
y: num(hex.y),
|
|
45895
|
+
terrain: str(hex.terrain),
|
|
45896
|
+
terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
|
|
45631
45897
|
})),
|
|
45632
45898
|
[hexes]
|
|
45633
45899
|
);
|
|
45634
45900
|
const baseUnits = useMemo(
|
|
45635
45901
|
() => heroes.map((hero) => ({
|
|
45636
|
-
id: hero.id,
|
|
45637
|
-
position: hero
|
|
45638
|
-
name: hero.name,
|
|
45639
|
-
team: hero
|
|
45902
|
+
id: str(hero.id),
|
|
45903
|
+
position: heroPosition(hero),
|
|
45904
|
+
name: str(hero.name),
|
|
45905
|
+
team: heroOwner(hero) === "enemy" ? "enemy" : "player",
|
|
45640
45906
|
health: 100,
|
|
45641
45907
|
maxHealth: 100,
|
|
45642
|
-
sprite: hero.sprite
|
|
45908
|
+
sprite: hero.sprite == null ? void 0 : str(hero.sprite)
|
|
45643
45909
|
})),
|
|
45644
45910
|
[heroes]
|
|
45645
45911
|
);
|
|
@@ -45680,73 +45946,94 @@ function WorldMapBoard({
|
|
|
45680
45946
|
const isoUnits = useMemo(() => {
|
|
45681
45947
|
if (movingPositions.size === 0) return baseUnits;
|
|
45682
45948
|
return baseUnits.map((u) => {
|
|
45683
|
-
const pos = movingPositions.get(u.id);
|
|
45949
|
+
const pos = u.id == null ? void 0 : movingPositions.get(u.id);
|
|
45684
45950
|
return pos ? { ...u, position: pos } : u;
|
|
45685
45951
|
});
|
|
45686
45952
|
}, [baseUnits, movingPositions]);
|
|
45687
45953
|
const validMoves = useMemo(() => {
|
|
45688
|
-
if (!selectedHero || selectedHero
|
|
45954
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
45955
|
+
const sp = heroPosition(selectedHero);
|
|
45956
|
+
const sOwner = heroOwner(selectedHero);
|
|
45957
|
+
const range = heroMovement(selectedHero);
|
|
45689
45958
|
const moves = [];
|
|
45690
45959
|
hexes.forEach((hex) => {
|
|
45691
|
-
|
|
45692
|
-
|
|
45693
|
-
if (!
|
|
45694
|
-
if (
|
|
45695
|
-
|
|
45960
|
+
const hx = num(hex.x);
|
|
45961
|
+
const hy = num(hex.y);
|
|
45962
|
+
if (!hexPassable(hex)) return;
|
|
45963
|
+
if (hx === sp.x && hy === sp.y) return;
|
|
45964
|
+
if (!isInRange(sp, { x: hx, y: hy }, range)) return;
|
|
45965
|
+
if (heroes.some((h) => {
|
|
45966
|
+
const hp = heroPosition(h);
|
|
45967
|
+
return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
|
|
45968
|
+
})) return;
|
|
45969
|
+
moves.push({ x: hx, y: hy });
|
|
45696
45970
|
});
|
|
45697
45971
|
return moves;
|
|
45698
45972
|
}, [selectedHero, hexes, heroes, isInRange]);
|
|
45699
45973
|
const attackTargets = useMemo(() => {
|
|
45700
|
-
if (!selectedHero || selectedHero
|
|
45701
|
-
|
|
45974
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
45975
|
+
const sp = heroPosition(selectedHero);
|
|
45976
|
+
const sOwner = heroOwner(selectedHero);
|
|
45977
|
+
const range = heroMovement(selectedHero);
|
|
45978
|
+
return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
|
|
45702
45979
|
}, [selectedHero, heroes, isInRange]);
|
|
45703
|
-
const maxY = Math.max(...hexes.map((h) => h.y), 0);
|
|
45980
|
+
const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
|
|
45704
45981
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
45705
45982
|
const tileToScreen = useCallback(
|
|
45706
45983
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
45707
45984
|
[scale, baseOffsetX]
|
|
45708
45985
|
);
|
|
45709
45986
|
const hoveredHex = useMemo(
|
|
45710
|
-
() => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
|
|
45987
|
+
() => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
|
|
45711
45988
|
[hoveredTile, hexes]
|
|
45712
45989
|
);
|
|
45713
45990
|
const hoveredHero = useMemo(
|
|
45714
|
-
() => hoveredTile ? heroes.find((h) =>
|
|
45991
|
+
() => hoveredTile ? heroes.find((h) => {
|
|
45992
|
+
const hp = heroPosition(h);
|
|
45993
|
+
return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
|
|
45994
|
+
}) ?? null : null,
|
|
45715
45995
|
[hoveredTile, heroes]
|
|
45716
45996
|
);
|
|
45717
45997
|
const handleTileClick = useCallback((x, y) => {
|
|
45718
45998
|
if (movementAnimRef.current) return;
|
|
45719
|
-
const hex = hexes.find((h) => h.x === x && h.y === y);
|
|
45999
|
+
const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
|
|
45720
46000
|
if (!hex) return;
|
|
45721
46001
|
if (tileClickEvent) {
|
|
45722
46002
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
45723
46003
|
}
|
|
45724
46004
|
if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
|
|
45725
|
-
|
|
45726
|
-
|
|
46005
|
+
const heroId = str(selectedHero.id);
|
|
46006
|
+
startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
|
|
46007
|
+
onHeroMove?.(heroId, x, y);
|
|
45727
46008
|
if (heroMoveEvent) {
|
|
45728
|
-
eventBus.emit(`UI:${heroMoveEvent}`, { heroId
|
|
46009
|
+
eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
|
|
45729
46010
|
}
|
|
45730
|
-
|
|
45731
|
-
|
|
46011
|
+
const feature = str(hex.feature);
|
|
46012
|
+
if (feature && feature !== "none") {
|
|
46013
|
+
onFeatureEnter?.(heroId, hex);
|
|
45732
46014
|
if (featureEnterEvent) {
|
|
45733
|
-
eventBus.emit(`UI:${featureEnterEvent}`, { heroId
|
|
46015
|
+
eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
|
|
45734
46016
|
}
|
|
45735
46017
|
}
|
|
45736
46018
|
});
|
|
45737
46019
|
return;
|
|
45738
46020
|
}
|
|
45739
|
-
const enemy = heroes.find((h) =>
|
|
46021
|
+
const enemy = heroes.find((h) => {
|
|
46022
|
+
const hp = heroPosition(h);
|
|
46023
|
+
return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
|
|
46024
|
+
});
|
|
45740
46025
|
if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
|
|
45741
|
-
|
|
46026
|
+
const attackerId = str(selectedHero.id);
|
|
46027
|
+
const defenderId = str(enemy.id);
|
|
46028
|
+
onBattleEncounter?.(attackerId, defenderId);
|
|
45742
46029
|
if (battleEncounterEvent) {
|
|
45743
|
-
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId
|
|
46030
|
+
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
|
|
45744
46031
|
}
|
|
45745
46032
|
}
|
|
45746
46033
|
}, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
|
|
45747
46034
|
const handleUnitClick = useCallback((unitId) => {
|
|
45748
|
-
const hero = heroes.find((h) => h.id === unitId);
|
|
45749
|
-
if (hero && (hero
|
|
46035
|
+
const hero = heroes.find((h) => str(h.id) === unitId);
|
|
46036
|
+
if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
|
|
45750
46037
|
onHeroSelect?.(unitId);
|
|
45751
46038
|
if (heroSelectEvent) {
|
|
45752
46039
|
eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
|
|
@@ -45819,6 +46106,7 @@ var init_WorldMapBoard = __esm({
|
|
|
45819
46106
|
init_Stack();
|
|
45820
46107
|
init_LoadingState();
|
|
45821
46108
|
init_IsometricCanvas2();
|
|
46109
|
+
init_boardEntity();
|
|
45822
46110
|
init_isometric();
|
|
45823
46111
|
WorldMapBoard.displayName = "WorldMapBoard";
|
|
45824
46112
|
}
|
|
@@ -49047,11 +49335,11 @@ function buildMockData(schema) {
|
|
|
49047
49335
|
result[entityName] = entity.instances;
|
|
49048
49336
|
continue;
|
|
49049
49337
|
}
|
|
49050
|
-
const
|
|
49338
|
+
const rows2 = Array.from(
|
|
49051
49339
|
{ length: 10 },
|
|
49052
49340
|
(_, i) => generateEntityRow(entity, i + 1)
|
|
49053
49341
|
);
|
|
49054
|
-
result[entityName] =
|
|
49342
|
+
result[entityName] = rows2;
|
|
49055
49343
|
}
|
|
49056
49344
|
for (const orbital of schema.orbitals) {
|
|
49057
49345
|
for (const traitRef of orbital.traits ?? []) {
|