@almadar/ui 5.21.12 → 5.22.3
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 +2432 -3173
- package/dist/avl/index.js +1373 -2114
- 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.cjs
CHANGED
|
@@ -2503,7 +2503,7 @@ var init_SvgGrid = __esm({
|
|
|
2503
2503
|
x,
|
|
2504
2504
|
y,
|
|
2505
2505
|
cols = 4,
|
|
2506
|
-
rows = 3,
|
|
2506
|
+
rows: rows2 = 3,
|
|
2507
2507
|
spacing = 20,
|
|
2508
2508
|
nodeRadius = 3,
|
|
2509
2509
|
color = "var(--color-primary)",
|
|
@@ -2512,7 +2512,7 @@ var init_SvgGrid = __esm({
|
|
|
2512
2512
|
highlights = []
|
|
2513
2513
|
}) => {
|
|
2514
2514
|
const highlightSet = new Set(highlights);
|
|
2515
|
-
return /* @__PURE__ */ jsxRuntime.jsx("g", { className, opacity, children: Array.from({ length:
|
|
2515
|
+
return /* @__PURE__ */ jsxRuntime.jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
|
|
2516
2516
|
(_, row) => Array.from({ length: cols }).map((_2, col) => {
|
|
2517
2517
|
const index = row * cols + col;
|
|
2518
2518
|
const isHighlighted = highlightSet.has(index);
|
|
@@ -3172,7 +3172,7 @@ var init_Input = __esm({
|
|
|
3172
3172
|
onClear,
|
|
3173
3173
|
value,
|
|
3174
3174
|
options,
|
|
3175
|
-
rows = 3,
|
|
3175
|
+
rows: rows2 = 3,
|
|
3176
3176
|
onChange,
|
|
3177
3177
|
...props
|
|
3178
3178
|
}, ref) => {
|
|
@@ -3222,7 +3222,7 @@ var init_Input = __esm({
|
|
|
3222
3222
|
ref,
|
|
3223
3223
|
value,
|
|
3224
3224
|
onChange,
|
|
3225
|
-
rows,
|
|
3225
|
+
rows: rows2,
|
|
3226
3226
|
className: baseClassName,
|
|
3227
3227
|
...props
|
|
3228
3228
|
}
|
|
@@ -5478,66 +5478,6 @@ var init_RangeSlider = __esm({
|
|
|
5478
5478
|
RangeSlider.displayName = "RangeSlider";
|
|
5479
5479
|
}
|
|
5480
5480
|
});
|
|
5481
|
-
function easeOut(t) {
|
|
5482
|
-
return t * (2 - t);
|
|
5483
|
-
}
|
|
5484
|
-
var AnimatedCounter;
|
|
5485
|
-
var init_AnimatedCounter = __esm({
|
|
5486
|
-
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
5487
|
-
"use client";
|
|
5488
|
-
init_cn();
|
|
5489
|
-
init_Typography();
|
|
5490
|
-
AnimatedCounter = ({
|
|
5491
|
-
value: rawValue,
|
|
5492
|
-
duration = 600,
|
|
5493
|
-
prefix,
|
|
5494
|
-
suffix,
|
|
5495
|
-
className
|
|
5496
|
-
}) => {
|
|
5497
|
-
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
5498
|
-
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
5499
|
-
const [displayValue, setDisplayValue] = React84.useState(value);
|
|
5500
|
-
const previousValueRef = React84.useRef(value);
|
|
5501
|
-
const animationFrameRef = React84.useRef(null);
|
|
5502
|
-
React84.useEffect(() => {
|
|
5503
|
-
const from = previousValueRef.current;
|
|
5504
|
-
const to = value;
|
|
5505
|
-
previousValueRef.current = value;
|
|
5506
|
-
if (from === to) {
|
|
5507
|
-
setDisplayValue(to);
|
|
5508
|
-
return;
|
|
5509
|
-
}
|
|
5510
|
-
const startTime = performance.now();
|
|
5511
|
-
const diff = to - from;
|
|
5512
|
-
function animate(currentTime) {
|
|
5513
|
-
const elapsed = currentTime - startTime;
|
|
5514
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
5515
|
-
const easedProgress = easeOut(progress);
|
|
5516
|
-
setDisplayValue(from + diff * easedProgress);
|
|
5517
|
-
if (progress < 1) {
|
|
5518
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5519
|
-
} else {
|
|
5520
|
-
setDisplayValue(to);
|
|
5521
|
-
}
|
|
5522
|
-
}
|
|
5523
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5524
|
-
return () => {
|
|
5525
|
-
if (animationFrameRef.current !== null) {
|
|
5526
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
5527
|
-
}
|
|
5528
|
-
};
|
|
5529
|
-
}, [value, duration]);
|
|
5530
|
-
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
5531
|
-
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
5532
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
5533
|
-
prefix,
|
|
5534
|
-
formattedValue,
|
|
5535
|
-
suffix
|
|
5536
|
-
] });
|
|
5537
|
-
};
|
|
5538
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
5539
|
-
}
|
|
5540
|
-
});
|
|
5541
5481
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
5542
5482
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
5543
5483
|
const observerRef = React84.useRef(null);
|
|
@@ -8019,15 +7959,15 @@ function HeaderSkeleton({ className }) {
|
|
|
8019
7959
|
] })
|
|
8020
7960
|
] });
|
|
8021
7961
|
}
|
|
8022
|
-
function TableSkeleton({ rows = 5, columns = 4, className }) {
|
|
7962
|
+
function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
|
|
8023
7963
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
|
|
8024
7964
|
/* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "px-4 py-3 bg-muted/30 border-b border-border", children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonBlock, { className: "h-4 flex-1 mx-2" }, i)) }),
|
|
8025
|
-
Array.from({ length:
|
|
7965
|
+
Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8026
7966
|
HStack,
|
|
8027
7967
|
{
|
|
8028
7968
|
className: cn(
|
|
8029
7969
|
"px-4 py-3",
|
|
8030
|
-
rowIdx <
|
|
7970
|
+
rowIdx < rows2 - 1 && "border-b border-border"
|
|
8031
7971
|
),
|
|
8032
7972
|
children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
|
|
8033
7973
|
},
|
|
@@ -8075,18 +8015,18 @@ function CardSkeleton({ className }) {
|
|
|
8075
8015
|
}
|
|
8076
8016
|
);
|
|
8077
8017
|
}
|
|
8078
|
-
function TextSkeleton({ rows = 3, className }) {
|
|
8079
|
-
return /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", className, children: Array.from({ length:
|
|
8018
|
+
function TextSkeleton({ rows: rows2 = 3, className }) {
|
|
8019
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8080
8020
|
SkeletonLine,
|
|
8081
8021
|
{
|
|
8082
|
-
className: i ===
|
|
8022
|
+
className: i === rows2 - 1 ? "w-2/3" : "w-full"
|
|
8083
8023
|
},
|
|
8084
8024
|
i
|
|
8085
8025
|
)) });
|
|
8086
8026
|
}
|
|
8087
8027
|
function Skeleton({
|
|
8088
8028
|
variant = "text",
|
|
8089
|
-
rows,
|
|
8029
|
+
rows: rows2,
|
|
8090
8030
|
columns,
|
|
8091
8031
|
fields,
|
|
8092
8032
|
className
|
|
@@ -8096,15 +8036,15 @@ function Skeleton({
|
|
|
8096
8036
|
case "header":
|
|
8097
8037
|
return /* @__PURE__ */ jsxRuntime.jsx(HeaderSkeleton, { className });
|
|
8098
8038
|
case "table":
|
|
8099
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TableSkeleton, { rows, columns, className });
|
|
8039
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TableSkeleton, { rows: rows2, columns, className });
|
|
8100
8040
|
case "form":
|
|
8101
8041
|
return /* @__PURE__ */ jsxRuntime.jsx(FormSkeleton, { fields, className });
|
|
8102
8042
|
case "card":
|
|
8103
8043
|
return /* @__PURE__ */ jsxRuntime.jsx(CardSkeleton, { className });
|
|
8104
8044
|
case "text":
|
|
8105
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows, className });
|
|
8045
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows: rows2, className });
|
|
8106
8046
|
default:
|
|
8107
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows, className });
|
|
8047
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TextSkeleton, { rows: rows2, className });
|
|
8108
8048
|
}
|
|
8109
8049
|
}
|
|
8110
8050
|
var pulseClass;
|
|
@@ -9732,7 +9672,7 @@ var init_MapView = __esm({
|
|
|
9732
9672
|
shadowSize: [41, 41]
|
|
9733
9673
|
});
|
|
9734
9674
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
9735
|
-
const { useEffect: useEffect71, useRef: useRef66, useCallback:
|
|
9675
|
+
const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback114, useState: useState103 } = React84__namespace.default;
|
|
9736
9676
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
9737
9677
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
9738
9678
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -9778,7 +9718,7 @@ var init_MapView = __esm({
|
|
|
9778
9718
|
}) {
|
|
9779
9719
|
const eventBus = useEventBus3();
|
|
9780
9720
|
const [clickedPosition, setClickedPosition] = useState103(null);
|
|
9781
|
-
const handleMapClick =
|
|
9721
|
+
const handleMapClick = useCallback114((lat, lng) => {
|
|
9782
9722
|
if (showClickedPin) {
|
|
9783
9723
|
setClickedPosition({ lat, lng });
|
|
9784
9724
|
}
|
|
@@ -9787,7 +9727,7 @@ var init_MapView = __esm({
|
|
|
9787
9727
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
9788
9728
|
}
|
|
9789
9729
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
9790
|
-
const handleMarkerClick =
|
|
9730
|
+
const handleMarkerClick = useCallback114((marker) => {
|
|
9791
9731
|
onMarkerClick?.(marker);
|
|
9792
9732
|
if (markerClickEvent) {
|
|
9793
9733
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -10008,7 +9948,7 @@ function InputPattern({
|
|
|
10008
9948
|
function TextareaPattern({
|
|
10009
9949
|
value = "",
|
|
10010
9950
|
placeholder,
|
|
10011
|
-
rows = 4,
|
|
9951
|
+
rows: rows2 = 4,
|
|
10012
9952
|
disabled = false,
|
|
10013
9953
|
fieldError,
|
|
10014
9954
|
onChange,
|
|
@@ -10028,7 +9968,7 @@ function TextareaPattern({
|
|
|
10028
9968
|
{
|
|
10029
9969
|
value: localValue,
|
|
10030
9970
|
placeholder,
|
|
10031
|
-
rows,
|
|
9971
|
+
rows: rows2,
|
|
10032
9972
|
disabled,
|
|
10033
9973
|
error: fieldError,
|
|
10034
9974
|
onChange: handleChange,
|
|
@@ -10513,6 +10453,91 @@ var init_ActionPalette = __esm({
|
|
|
10513
10453
|
ActionPalette.displayName = "ActionPalette";
|
|
10514
10454
|
}
|
|
10515
10455
|
});
|
|
10456
|
+
function parseValue(value) {
|
|
10457
|
+
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
10458
|
+
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
10459
|
+
if (!match) {
|
|
10460
|
+
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
10461
|
+
}
|
|
10462
|
+
const numStr = match[2];
|
|
10463
|
+
const decimalIdx = numStr.indexOf(".");
|
|
10464
|
+
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
10465
|
+
return {
|
|
10466
|
+
prefix: match[1],
|
|
10467
|
+
num: parseFloat(numStr),
|
|
10468
|
+
suffix: match[3],
|
|
10469
|
+
decimals
|
|
10470
|
+
};
|
|
10471
|
+
}
|
|
10472
|
+
var AnimatedCounter;
|
|
10473
|
+
var init_AnimatedCounter = __esm({
|
|
10474
|
+
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
10475
|
+
"use client";
|
|
10476
|
+
init_cn();
|
|
10477
|
+
init_Box();
|
|
10478
|
+
init_Typography();
|
|
10479
|
+
AnimatedCounter = ({
|
|
10480
|
+
value,
|
|
10481
|
+
label,
|
|
10482
|
+
duration = 1500,
|
|
10483
|
+
className
|
|
10484
|
+
}) => {
|
|
10485
|
+
const ref = React84.useRef(null);
|
|
10486
|
+
const [displayValue, setDisplayValue] = React84.useState("0");
|
|
10487
|
+
const [hasAnimated, setHasAnimated] = React84.useState(false);
|
|
10488
|
+
const animate = React84.useCallback(() => {
|
|
10489
|
+
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
10490
|
+
if (num2 === 0) {
|
|
10491
|
+
setDisplayValue(String(value));
|
|
10492
|
+
return;
|
|
10493
|
+
}
|
|
10494
|
+
const startTime = performance.now();
|
|
10495
|
+
const tick = (now2) => {
|
|
10496
|
+
const elapsed = now2 - startTime;
|
|
10497
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
10498
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
10499
|
+
const current = eased * num2;
|
|
10500
|
+
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
10501
|
+
if (progress < 1) {
|
|
10502
|
+
requestAnimationFrame(tick);
|
|
10503
|
+
} else {
|
|
10504
|
+
setDisplayValue(String(value));
|
|
10505
|
+
}
|
|
10506
|
+
};
|
|
10507
|
+
requestAnimationFrame(tick);
|
|
10508
|
+
}, [value, duration]);
|
|
10509
|
+
React84.useEffect(() => {
|
|
10510
|
+
if (hasAnimated) return;
|
|
10511
|
+
const el = ref.current;
|
|
10512
|
+
if (!el) return;
|
|
10513
|
+
const observer2 = new IntersectionObserver(
|
|
10514
|
+
(entries) => {
|
|
10515
|
+
if (entries[0].isIntersecting) {
|
|
10516
|
+
setHasAnimated(true);
|
|
10517
|
+
animate();
|
|
10518
|
+
observer2.disconnect();
|
|
10519
|
+
}
|
|
10520
|
+
},
|
|
10521
|
+
{ threshold: 0.3 }
|
|
10522
|
+
);
|
|
10523
|
+
observer2.observe(el);
|
|
10524
|
+
return () => observer2.disconnect();
|
|
10525
|
+
}, [hasAnimated, animate]);
|
|
10526
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
10527
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10528
|
+
Typography,
|
|
10529
|
+
{
|
|
10530
|
+
variant: "h2",
|
|
10531
|
+
className: "text-primary font-bold tabular-nums",
|
|
10532
|
+
children: hasAnimated ? displayValue : "0"
|
|
10533
|
+
}
|
|
10534
|
+
),
|
|
10535
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
10536
|
+
] });
|
|
10537
|
+
};
|
|
10538
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
10539
|
+
}
|
|
10540
|
+
});
|
|
10516
10541
|
var AuthLayout;
|
|
10517
10542
|
var init_AuthLayout = __esm({
|
|
10518
10543
|
"components/core/templates/AuthLayout.tsx"() {
|
|
@@ -11866,6 +11891,39 @@ var init_IsometricCanvas2 = __esm({
|
|
|
11866
11891
|
init_IsometricCanvas();
|
|
11867
11892
|
}
|
|
11868
11893
|
});
|
|
11894
|
+
|
|
11895
|
+
// components/game/organisms/boardEntity.ts
|
|
11896
|
+
function boardEntity(entity) {
|
|
11897
|
+
if (!entity) return void 0;
|
|
11898
|
+
return Array.isArray(entity) ? entity[0] : entity;
|
|
11899
|
+
}
|
|
11900
|
+
function str(v) {
|
|
11901
|
+
return v == null ? "" : String(v);
|
|
11902
|
+
}
|
|
11903
|
+
function num(v, fallback = 0) {
|
|
11904
|
+
const n = Number(v);
|
|
11905
|
+
return Number.isFinite(n) ? n : fallback;
|
|
11906
|
+
}
|
|
11907
|
+
function rows(v) {
|
|
11908
|
+
return Array.isArray(v) ? v : [];
|
|
11909
|
+
}
|
|
11910
|
+
function vec2(v) {
|
|
11911
|
+
const o = v ?? {};
|
|
11912
|
+
return { x: num(o.x), y: num(o.y) };
|
|
11913
|
+
}
|
|
11914
|
+
function unitPosition(u) {
|
|
11915
|
+
return vec2(u.position);
|
|
11916
|
+
}
|
|
11917
|
+
function unitTeam(u) {
|
|
11918
|
+
return str(u.team);
|
|
11919
|
+
}
|
|
11920
|
+
function unitHealth(u) {
|
|
11921
|
+
return num(u.health);
|
|
11922
|
+
}
|
|
11923
|
+
var init_boardEntity = __esm({
|
|
11924
|
+
"components/game/organisms/boardEntity.ts"() {
|
|
11925
|
+
}
|
|
11926
|
+
});
|
|
11869
11927
|
function BattleBoard({
|
|
11870
11928
|
entity,
|
|
11871
11929
|
scale = 0.45,
|
|
@@ -11892,43 +11950,49 @@ function BattleBoard({
|
|
|
11892
11950
|
attackEvent,
|
|
11893
11951
|
className
|
|
11894
11952
|
}) {
|
|
11895
|
-
const
|
|
11896
|
-
const
|
|
11897
|
-
const
|
|
11898
|
-
const
|
|
11899
|
-
const
|
|
11900
|
-
const
|
|
11901
|
-
const
|
|
11902
|
-
const
|
|
11903
|
-
const
|
|
11904
|
-
const
|
|
11905
|
-
const
|
|
11953
|
+
const board = boardEntity(entity) ?? {};
|
|
11954
|
+
const tiles = Array.isArray(board.tiles) ? board.tiles : [];
|
|
11955
|
+
const features = Array.isArray(board.features) ? board.features : [];
|
|
11956
|
+
const boardWidth = num(board.boardWidth, 8);
|
|
11957
|
+
const boardHeight = num(board.boardHeight, 6);
|
|
11958
|
+
const assetManifest = board.assetManifest;
|
|
11959
|
+
const backgroundImage = board.backgroundImage;
|
|
11960
|
+
const units = rows(board.units);
|
|
11961
|
+
const selectedUnitId = board.selectedUnitId ?? null;
|
|
11962
|
+
const currentPhase = str(board.phase) || "observation";
|
|
11963
|
+
const currentTurn = num(board.turn, 1);
|
|
11964
|
+
const gameResult = board.gameResult ?? null;
|
|
11906
11965
|
const eventBus = useEventBus();
|
|
11907
11966
|
const { t } = hooks.useTranslate();
|
|
11908
11967
|
const [hoveredTile, setHoveredTile] = React84.useState(null);
|
|
11909
11968
|
const [isShaking, setIsShaking] = React84.useState(false);
|
|
11910
11969
|
const selectedUnit = React84.useMemo(
|
|
11911
|
-
() => units.find((u) => u.id === selectedUnitId) ?? null,
|
|
11970
|
+
() => units.find((u) => str(u.id) === selectedUnitId) ?? null,
|
|
11912
11971
|
[units, selectedUnitId]
|
|
11913
11972
|
);
|
|
11914
11973
|
const hoveredUnit = React84.useMemo(() => {
|
|
11915
11974
|
if (!hoveredTile) return null;
|
|
11916
|
-
return units.find(
|
|
11917
|
-
|
|
11918
|
-
|
|
11975
|
+
return units.find((u) => {
|
|
11976
|
+
const p2 = unitPosition(u);
|
|
11977
|
+
return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
|
|
11978
|
+
}) ?? null;
|
|
11919
11979
|
}, [hoveredTile, units]);
|
|
11920
|
-
const playerUnits = React84.useMemo(() => units.filter((u) => u
|
|
11921
|
-
const enemyUnits = React84.useMemo(() => units.filter((u) => u
|
|
11980
|
+
const playerUnits = React84.useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
|
|
11981
|
+
const enemyUnits = React84.useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
|
|
11922
11982
|
const validMoves = React84.useMemo(() => {
|
|
11923
11983
|
if (!selectedUnit || currentPhase !== "movement") return [];
|
|
11924
11984
|
const moves = [];
|
|
11925
|
-
const range = selectedUnit.movement;
|
|
11985
|
+
const range = num(selectedUnit.movement);
|
|
11986
|
+
const origin = unitPosition(selectedUnit);
|
|
11926
11987
|
for (let dy = -range; dy <= range; dy++) {
|
|
11927
11988
|
for (let dx = -range; dx <= range; dx++) {
|
|
11928
|
-
const nx =
|
|
11929
|
-
const ny =
|
|
11989
|
+
const nx = origin.x + dx;
|
|
11990
|
+
const ny = origin.y + dy;
|
|
11930
11991
|
const dist = Math.abs(dx) + Math.abs(dy);
|
|
11931
|
-
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) =>
|
|
11992
|
+
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
|
|
11993
|
+
const p2 = unitPosition(u);
|
|
11994
|
+
return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
|
|
11995
|
+
})) {
|
|
11932
11996
|
moves.push({ x: nx, y: ny });
|
|
11933
11997
|
}
|
|
11934
11998
|
}
|
|
@@ -11937,11 +12001,14 @@ function BattleBoard({
|
|
|
11937
12001
|
}, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
|
|
11938
12002
|
const attackTargets = React84.useMemo(() => {
|
|
11939
12003
|
if (!selectedUnit || currentPhase !== "action") return [];
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
12004
|
+
const sp = unitPosition(selectedUnit);
|
|
12005
|
+
const sTeam = unitTeam(selectedUnit);
|
|
12006
|
+
return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
|
|
12007
|
+
const p2 = unitPosition(u);
|
|
12008
|
+
const dx = Math.abs(p2.x - sp.x);
|
|
12009
|
+
const dy = Math.abs(p2.y - sp.y);
|
|
11943
12010
|
return dx <= 1 && dy <= 1 && dx + dy > 0;
|
|
11944
|
-
}).map((u) => u
|
|
12011
|
+
}).map((u) => unitPosition(u));
|
|
11945
12012
|
}, [selectedUnit, currentPhase, units]);
|
|
11946
12013
|
const MOVE_SPEED_MS_PER_TILE = 300;
|
|
11947
12014
|
const movementAnimRef = React84.useRef(null);
|
|
@@ -11981,23 +12048,25 @@ function BattleBoard({
|
|
|
11981
12048
|
return () => clearInterval(interval);
|
|
11982
12049
|
}, []);
|
|
11983
12050
|
const isoUnits = React84.useMemo(() => {
|
|
11984
|
-
return units.filter((u) => u
|
|
11985
|
-
const
|
|
12051
|
+
return units.filter((u) => unitHealth(u) > 0).map((unit) => {
|
|
12052
|
+
const id = str(unit.id);
|
|
12053
|
+
const pos = movingPositions.get(id) ?? unitPosition(unit);
|
|
12054
|
+
const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
|
|
11986
12055
|
return {
|
|
11987
|
-
id
|
|
12056
|
+
id,
|
|
11988
12057
|
position: pos,
|
|
11989
|
-
name: unit.name,
|
|
11990
|
-
team: unit
|
|
11991
|
-
health: unit
|
|
11992
|
-
maxHealth: unit.maxHealth,
|
|
11993
|
-
unitType: unit.unitType,
|
|
11994
|
-
heroId: unit.heroId,
|
|
11995
|
-
sprite: unit.sprite,
|
|
11996
|
-
traits:
|
|
11997
|
-
name:
|
|
11998
|
-
currentState:
|
|
11999
|
-
states:
|
|
12000
|
-
cooldown:
|
|
12058
|
+
name: str(unit.name),
|
|
12059
|
+
team: unitTeam(unit),
|
|
12060
|
+
health: unitHealth(unit),
|
|
12061
|
+
maxHealth: num(unit.maxHealth),
|
|
12062
|
+
unitType: unit.unitType == null ? void 0 : str(unit.unitType),
|
|
12063
|
+
heroId: unit.heroId == null ? void 0 : str(unit.heroId),
|
|
12064
|
+
sprite: unit.sprite == null ? void 0 : str(unit.sprite),
|
|
12065
|
+
traits: unitTraits?.map((tr) => ({
|
|
12066
|
+
name: tr.name,
|
|
12067
|
+
currentState: tr.currentState,
|
|
12068
|
+
states: tr.states,
|
|
12069
|
+
cooldown: tr.cooldown ?? 0
|
|
12001
12070
|
}))
|
|
12002
12071
|
};
|
|
12003
12072
|
});
|
|
@@ -12009,8 +12078,8 @@ function BattleBoard({
|
|
|
12009
12078
|
[scale, baseOffsetX]
|
|
12010
12079
|
);
|
|
12011
12080
|
const checkGameEnd = React84.useCallback(() => {
|
|
12012
|
-
const pa = units.filter((u) => u
|
|
12013
|
-
const ea = units.filter((u) => u
|
|
12081
|
+
const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
12082
|
+
const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
12014
12083
|
if (pa.length === 0) {
|
|
12015
12084
|
onGameEnd?.("defeat");
|
|
12016
12085
|
if (gameEndEvent) {
|
|
@@ -12024,21 +12093,22 @@ function BattleBoard({
|
|
|
12024
12093
|
}
|
|
12025
12094
|
}, [units, onGameEnd, gameEndEvent, eventBus]);
|
|
12026
12095
|
const handleUnitClick = React84.useCallback((unitId) => {
|
|
12027
|
-
const unit = units.find((u) => u.id === unitId);
|
|
12096
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
12028
12097
|
if (!unit) return;
|
|
12029
12098
|
if (unitClickEvent) {
|
|
12030
12099
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
12031
12100
|
}
|
|
12032
12101
|
if (currentPhase === "action" && selectedUnit) {
|
|
12033
|
-
|
|
12034
|
-
|
|
12102
|
+
const up = unitPosition(unit);
|
|
12103
|
+
if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
|
|
12104
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
12035
12105
|
setIsShaking(true);
|
|
12036
12106
|
setTimeout(() => setIsShaking(false), 300);
|
|
12037
12107
|
onAttack?.(selectedUnit, unit, damage);
|
|
12038
12108
|
if (attackEvent) {
|
|
12039
12109
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
12040
|
-
attackerId: selectedUnit.id,
|
|
12041
|
-
targetId: unit.id,
|
|
12110
|
+
attackerId: str(selectedUnit.id),
|
|
12111
|
+
targetId: str(unit.id),
|
|
12042
12112
|
damage
|
|
12043
12113
|
});
|
|
12044
12114
|
}
|
|
@@ -12053,9 +12123,9 @@ function BattleBoard({
|
|
|
12053
12123
|
if (currentPhase === "movement" && selectedUnit) {
|
|
12054
12124
|
if (movementAnimRef.current) return;
|
|
12055
12125
|
if (validMoves.some((m) => m.x === x && m.y === y)) {
|
|
12056
|
-
const from = { ...selectedUnit
|
|
12126
|
+
const from = { ...unitPosition(selectedUnit) };
|
|
12057
12127
|
const to = { x, y };
|
|
12058
|
-
startMoveAnimation(selectedUnit.id, from, to, () => {
|
|
12128
|
+
startMoveAnimation(str(selectedUnit.id), from, to, () => {
|
|
12059
12129
|
onUnitMove?.(selectedUnit, to);
|
|
12060
12130
|
});
|
|
12061
12131
|
}
|
|
@@ -12213,6 +12283,7 @@ var init_BattleBoard = __esm({
|
|
|
12213
12283
|
init_Typography();
|
|
12214
12284
|
init_Stack();
|
|
12215
12285
|
init_IsometricCanvas2();
|
|
12286
|
+
init_boardEntity();
|
|
12216
12287
|
init_isometric();
|
|
12217
12288
|
BattleBoard.displayName = "BattleBoard";
|
|
12218
12289
|
}
|
|
@@ -13435,24 +13506,24 @@ var init_CodeBlock = __esm({
|
|
|
13435
13506
|
return;
|
|
13436
13507
|
}
|
|
13437
13508
|
lineEls.forEach((el) => {
|
|
13438
|
-
const
|
|
13439
|
-
if (hiddenLines.has(
|
|
13509
|
+
const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
|
|
13510
|
+
if (hiddenLines.has(num2)) {
|
|
13440
13511
|
el.style.display = "none";
|
|
13441
13512
|
return;
|
|
13442
13513
|
}
|
|
13443
13514
|
el.style.display = "";
|
|
13444
13515
|
el.style.position = "relative";
|
|
13445
13516
|
el.style.paddingLeft = "1.2em";
|
|
13446
|
-
const region = foldStartMap.get(
|
|
13517
|
+
const region = foldStartMap.get(num2);
|
|
13447
13518
|
if (!region) return;
|
|
13448
|
-
const isCollapsed = collapsed.has(
|
|
13519
|
+
const isCollapsed = collapsed.has(num2);
|
|
13449
13520
|
const toggle = document.createElement("span");
|
|
13450
13521
|
toggle.className = "fold-toggle";
|
|
13451
13522
|
toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
|
|
13452
13523
|
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%";
|
|
13453
13524
|
toggle.addEventListener("click", (e) => {
|
|
13454
13525
|
e.stopPropagation();
|
|
13455
|
-
toggleFoldRef.current(
|
|
13526
|
+
toggleFoldRef.current(num2);
|
|
13456
13527
|
});
|
|
13457
13528
|
el.insertBefore(toggle, el.firstChild);
|
|
13458
13529
|
if (isCollapsed) {
|
|
@@ -15705,10 +15776,13 @@ var init_BookChapterView = __esm({
|
|
|
15705
15776
|
init_cn();
|
|
15706
15777
|
BookChapterView = ({
|
|
15707
15778
|
chapter,
|
|
15779
|
+
orbitalSchema,
|
|
15708
15780
|
direction,
|
|
15709
15781
|
className
|
|
15710
15782
|
}) => {
|
|
15711
15783
|
const { t: _t } = hooks.useTranslate();
|
|
15784
|
+
const title = String(chapter.title ?? "");
|
|
15785
|
+
const content = String(chapter.content ?? "");
|
|
15712
15786
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15713
15787
|
VStack,
|
|
15714
15788
|
{
|
|
@@ -15716,16 +15790,16 @@ var init_BookChapterView = __esm({
|
|
|
15716
15790
|
className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
|
|
15717
15791
|
style: { direction },
|
|
15718
15792
|
children: [
|
|
15719
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children:
|
|
15793
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
|
|
15720
15794
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
15721
|
-
!!
|
|
15795
|
+
!!orbitalSchema && /* @__PURE__ */ jsxRuntime.jsx(ScaledDiagram, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15722
15796
|
JazariStateMachine,
|
|
15723
15797
|
{
|
|
15724
|
-
schema:
|
|
15798
|
+
schema: orbitalSchema,
|
|
15725
15799
|
direction
|
|
15726
15800
|
}
|
|
15727
15801
|
) }),
|
|
15728
|
-
/* @__PURE__ */ jsxRuntime.jsx(ContentRenderer, { content
|
|
15802
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContentRenderer, { content, direction })
|
|
15729
15803
|
]
|
|
15730
15804
|
}
|
|
15731
15805
|
);
|
|
@@ -15823,7 +15897,7 @@ var init_BookNavBar = __esm({
|
|
|
15823
15897
|
BookNavBar = ({
|
|
15824
15898
|
currentPage,
|
|
15825
15899
|
totalPages,
|
|
15826
|
-
chapterTitle,
|
|
15900
|
+
chapterTitle: chapterTitle2,
|
|
15827
15901
|
direction,
|
|
15828
15902
|
className
|
|
15829
15903
|
}) => {
|
|
@@ -15864,12 +15938,12 @@ var init_BookNavBar = __esm({
|
|
|
15864
15938
|
)
|
|
15865
15939
|
] }),
|
|
15866
15940
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
|
|
15867
|
-
|
|
15941
|
+
chapterTitle2 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15868
15942
|
Typography,
|
|
15869
15943
|
{
|
|
15870
15944
|
variant: "caption",
|
|
15871
15945
|
className: "text-center block truncate text-muted-foreground",
|
|
15872
|
-
children:
|
|
15946
|
+
children: chapterTitle2
|
|
15873
15947
|
}
|
|
15874
15948
|
),
|
|
15875
15949
|
/* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
|
|
@@ -15936,31 +16010,35 @@ var init_BookTableOfContents = __esm({
|
|
|
15936
16010
|
style: { direction },
|
|
15937
16011
|
children: [
|
|
15938
16012
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
|
|
15939
|
-
parts.map((part, partIdx) =>
|
|
15940
|
-
|
|
15941
|
-
|
|
15942
|
-
/* @__PURE__ */ jsxRuntime.
|
|
15943
|
-
|
|
15944
|
-
|
|
15945
|
-
|
|
15946
|
-
|
|
15947
|
-
|
|
15948
|
-
|
|
15949
|
-
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
|
|
15953
|
-
|
|
15954
|
-
|
|
15955
|
-
|
|
15956
|
-
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
|
|
15960
|
-
|
|
15961
|
-
|
|
15962
|
-
|
|
15963
|
-
|
|
16013
|
+
parts.map((part, partIdx) => {
|
|
16014
|
+
const chapters = Array.isArray(part.chapters) ? part.chapters : [];
|
|
16015
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
16016
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "center", children: [
|
|
16017
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
|
|
16018
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
|
|
16019
|
+
] }),
|
|
16020
|
+
/* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
|
|
16021
|
+
const id = chapter.id == null ? "" : String(chapter.id);
|
|
16022
|
+
const isCurrent = id === currentChapterId;
|
|
16023
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16024
|
+
Button,
|
|
16025
|
+
{
|
|
16026
|
+
variant: "ghost",
|
|
16027
|
+
size: "sm",
|
|
16028
|
+
action: "BOOK_NAVIGATE",
|
|
16029
|
+
actionPayload: { chapterId: id },
|
|
16030
|
+
className: cn(
|
|
16031
|
+
"justify-start text-left w-full",
|
|
16032
|
+
direction === "rtl" && "text-right",
|
|
16033
|
+
isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
|
|
16034
|
+
),
|
|
16035
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
|
|
16036
|
+
},
|
|
16037
|
+
id
|
|
16038
|
+
);
|
|
16039
|
+
}) })
|
|
16040
|
+
] }, partIdx);
|
|
16041
|
+
})
|
|
15964
16042
|
]
|
|
15965
16043
|
}
|
|
15966
16044
|
);
|
|
@@ -16082,27 +16160,41 @@ function resolveFieldMap(fieldMap) {
|
|
|
16082
16160
|
function get(obj, key) {
|
|
16083
16161
|
return obj[key];
|
|
16084
16162
|
}
|
|
16163
|
+
function asStr(v) {
|
|
16164
|
+
return v == null ? "" : String(v);
|
|
16165
|
+
}
|
|
16085
16166
|
function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
|
|
16086
16167
|
const rawParts = get(raw, fields.parts) ?? [];
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16095
|
-
return {
|
|
16096
|
-
title: get(part, fields.partTitle) ?? "",
|
|
16097
|
-
chapters: rawChapters.map((ch) => ({
|
|
16098
|
-
id: get(ch, fields.chapterId) ?? "",
|
|
16099
|
-
title: get(ch, fields.chapterTitle) ?? "",
|
|
16100
|
-
content: get(ch, fields.chapterContent) ?? "",
|
|
16101
|
-
orbitalSchema: get(ch, fields.chapterOrbitalSchema)
|
|
16102
|
-
}))
|
|
16103
|
-
};
|
|
16104
|
-
})
|
|
16168
|
+
const direction = get(raw, fields.direction) ?? "ltr";
|
|
16169
|
+
const cover = {
|
|
16170
|
+
title: asStr(get(raw, fields.title)),
|
|
16171
|
+
subtitle: asStr(get(raw, fields.subtitle)),
|
|
16172
|
+
author: asStr(get(raw, fields.author)),
|
|
16173
|
+
coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
|
|
16174
|
+
direction
|
|
16105
16175
|
};
|
|
16176
|
+
const schemaByChapterId = {};
|
|
16177
|
+
const chapters = [];
|
|
16178
|
+
const parts = rawParts.map((part) => {
|
|
16179
|
+
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16180
|
+
const chapterRows = rawChapters.map((ch) => {
|
|
16181
|
+
const id = asStr(get(ch, fields.chapterId));
|
|
16182
|
+
const schema = get(ch, fields.chapterOrbitalSchema);
|
|
16183
|
+
if (schema) schemaByChapterId[id] = schema;
|
|
16184
|
+
const row = {
|
|
16185
|
+
id,
|
|
16186
|
+
title: asStr(get(ch, fields.chapterTitle)),
|
|
16187
|
+
content: asStr(get(ch, fields.chapterContent))
|
|
16188
|
+
};
|
|
16189
|
+
chapters.push(row);
|
|
16190
|
+
return row;
|
|
16191
|
+
});
|
|
16192
|
+
return {
|
|
16193
|
+
title: asStr(get(part, fields.partTitle)),
|
|
16194
|
+
chapters: chapterRows
|
|
16195
|
+
};
|
|
16196
|
+
});
|
|
16197
|
+
return { cover, direction, parts, chapters, schemaByChapterId };
|
|
16106
16198
|
}
|
|
16107
16199
|
var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
|
|
16108
16200
|
var init_types2 = __esm({
|
|
@@ -16140,10 +16232,7 @@ var init_types2 = __esm({
|
|
|
16140
16232
|
};
|
|
16141
16233
|
}
|
|
16142
16234
|
});
|
|
16143
|
-
|
|
16144
|
-
return book.parts.flatMap((part) => part.chapters);
|
|
16145
|
-
}
|
|
16146
|
-
var PRINT_STYLES, BookViewer;
|
|
16235
|
+
var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
|
|
16147
16236
|
var init_BookViewer = __esm({
|
|
16148
16237
|
"components/marketing/organisms/book/BookViewer.tsx"() {
|
|
16149
16238
|
init_Box();
|
|
@@ -16156,6 +16245,8 @@ var init_BookViewer = __esm({
|
|
|
16156
16245
|
init_BookNavBar();
|
|
16157
16246
|
init_EmptyState();
|
|
16158
16247
|
init_types2();
|
|
16248
|
+
chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
|
|
16249
|
+
chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
|
|
16159
16250
|
PRINT_STYLES = `
|
|
16160
16251
|
@media print {
|
|
16161
16252
|
.book-viewer-page {
|
|
@@ -16184,14 +16275,14 @@ var init_BookViewer = __esm({
|
|
|
16184
16275
|
return mapBookData(raw, resolvedFieldMap);
|
|
16185
16276
|
}, [entity, resolvedFieldMap]);
|
|
16186
16277
|
const direction = book?.direction ?? "ltr";
|
|
16187
|
-
const chapters = React84.useMemo(() => book ?
|
|
16278
|
+
const chapters = React84.useMemo(() => book ? book.chapters : [], [book]);
|
|
16188
16279
|
const totalPages = 2 + chapters.length;
|
|
16189
16280
|
const navigateTo = React84.useCallback(
|
|
16190
16281
|
(page) => {
|
|
16191
16282
|
const clamped = Math.max(0, Math.min(page, totalPages - 1));
|
|
16192
16283
|
setCurrentPage(clamped);
|
|
16193
|
-
const
|
|
16194
|
-
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
|
|
16284
|
+
const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
|
|
16285
|
+
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
|
|
16195
16286
|
},
|
|
16196
16287
|
[totalPages, chapters, eventBus]
|
|
16197
16288
|
);
|
|
@@ -16203,8 +16294,8 @@ var init_BookViewer = __esm({
|
|
|
16203
16294
|
eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
|
|
16204
16295
|
eventBus.on("UI:BOOK_PRINT", () => window.print()),
|
|
16205
16296
|
eventBus.on("UI:BOOK_NAVIGATE", (event) => {
|
|
16206
|
-
const
|
|
16207
|
-
const idx = chapters.findIndex((ch) => ch
|
|
16297
|
+
const targetId = event.payload?.chapterId;
|
|
16298
|
+
const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
|
|
16208
16299
|
if (idx >= 0) navigateTo(idx + 2);
|
|
16209
16300
|
})
|
|
16210
16301
|
];
|
|
@@ -16221,9 +16312,11 @@ var init_BookViewer = __esm({
|
|
|
16221
16312
|
style.remove();
|
|
16222
16313
|
};
|
|
16223
16314
|
}, []);
|
|
16224
|
-
const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16225
|
-
const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16315
|
+
const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
|
|
16316
|
+
const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
|
|
16226
16317
|
if (!book) return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { message: t("book.noData") });
|
|
16318
|
+
const cover = book.cover;
|
|
16319
|
+
const coverTitle = String(cover.title ?? "");
|
|
16227
16320
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
|
|
16228
16321
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
16229
16322
|
Box,
|
|
@@ -16235,10 +16328,10 @@ var init_BookViewer = __esm({
|
|
|
16235
16328
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16236
16329
|
BookCoverPage,
|
|
16237
16330
|
{
|
|
16238
|
-
title:
|
|
16239
|
-
subtitle:
|
|
16240
|
-
author:
|
|
16241
|
-
coverImageUrl:
|
|
16331
|
+
title: coverTitle,
|
|
16332
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16333
|
+
author: String(cover.author ?? "") || void 0,
|
|
16334
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16242
16335
|
direction
|
|
16243
16336
|
}
|
|
16244
16337
|
),
|
|
@@ -16249,23 +16342,27 @@ var init_BookViewer = __esm({
|
|
|
16249
16342
|
direction
|
|
16250
16343
|
}
|
|
16251
16344
|
),
|
|
16252
|
-
chapters.map((chapter) =>
|
|
16253
|
-
|
|
16254
|
-
|
|
16255
|
-
|
|
16256
|
-
|
|
16257
|
-
|
|
16258
|
-
|
|
16259
|
-
|
|
16345
|
+
chapters.map((chapter) => {
|
|
16346
|
+
const id = chapterId(chapter);
|
|
16347
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16348
|
+
BookChapterView,
|
|
16349
|
+
{
|
|
16350
|
+
chapter,
|
|
16351
|
+
orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
|
|
16352
|
+
direction
|
|
16353
|
+
},
|
|
16354
|
+
id
|
|
16355
|
+
);
|
|
16356
|
+
})
|
|
16260
16357
|
] }),
|
|
16261
16358
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "print:hidden", children: [
|
|
16262
16359
|
currentPage === 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16263
16360
|
BookCoverPage,
|
|
16264
16361
|
{
|
|
16265
|
-
title:
|
|
16266
|
-
subtitle:
|
|
16267
|
-
author:
|
|
16268
|
-
coverImageUrl:
|
|
16362
|
+
title: coverTitle,
|
|
16363
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16364
|
+
author: String(cover.author ?? "") || void 0,
|
|
16365
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16269
16366
|
direction
|
|
16270
16367
|
}
|
|
16271
16368
|
),
|
|
@@ -16281,6 +16378,7 @@ var init_BookViewer = __esm({
|
|
|
16281
16378
|
BookChapterView,
|
|
16282
16379
|
{
|
|
16283
16380
|
chapter: chapters[currentPage - 2],
|
|
16381
|
+
orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
|
|
16284
16382
|
direction
|
|
16285
16383
|
}
|
|
16286
16384
|
)
|
|
@@ -16293,7 +16391,7 @@ var init_BookViewer = __esm({
|
|
|
16293
16391
|
{
|
|
16294
16392
|
currentPage,
|
|
16295
16393
|
totalPages,
|
|
16296
|
-
chapterTitle: currentPage === 0 ?
|
|
16394
|
+
chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
|
|
16297
16395
|
direction
|
|
16298
16396
|
}
|
|
16299
16397
|
)
|
|
@@ -16391,7 +16489,7 @@ var init_Grid = __esm({
|
|
|
16391
16489
|
};
|
|
16392
16490
|
Grid = ({
|
|
16393
16491
|
cols = 1,
|
|
16394
|
-
rows,
|
|
16492
|
+
rows: rows2,
|
|
16395
16493
|
gap = "md",
|
|
16396
16494
|
rowGap,
|
|
16397
16495
|
colGap,
|
|
@@ -16403,7 +16501,7 @@ var init_Grid = __esm({
|
|
|
16403
16501
|
children,
|
|
16404
16502
|
as: Component = "div"
|
|
16405
16503
|
}) => {
|
|
16406
|
-
const mergedStyle =
|
|
16504
|
+
const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
|
|
16407
16505
|
return React84__namespace.default.createElement(
|
|
16408
16506
|
Component,
|
|
16409
16507
|
{
|
|
@@ -17119,14 +17217,14 @@ function BuilderBoard({
|
|
|
17119
17217
|
}) {
|
|
17120
17218
|
const { emit } = useEventBus();
|
|
17121
17219
|
const { t } = hooks.useTranslate();
|
|
17122
|
-
const resolved =
|
|
17220
|
+
const resolved = boardEntity(entity);
|
|
17123
17221
|
const [placements, setPlacements] = React84.useState({});
|
|
17124
17222
|
const [headerError, setHeaderError] = React84.useState(false);
|
|
17125
17223
|
const [submitted, setSubmitted] = React84.useState(false);
|
|
17126
17224
|
const [attempts, setAttempts] = React84.useState(0);
|
|
17127
17225
|
const [showHint, setShowHint] = React84.useState(false);
|
|
17128
|
-
const components = resolved?.components
|
|
17129
|
-
const slots = resolved?.slots
|
|
17226
|
+
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
17227
|
+
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
17130
17228
|
const usedComponentIds = new Set(Object.values(placements));
|
|
17131
17229
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
17132
17230
|
const [selectedComponent, setSelectedComponent] = React84.useState(null);
|
|
@@ -17160,7 +17258,7 @@ function BuilderBoard({
|
|
|
17160
17258
|
}, [slots, placements, attempts, completeEvent, emit]);
|
|
17161
17259
|
const handleReset = () => {
|
|
17162
17260
|
setSubmitted(false);
|
|
17163
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
17261
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
17164
17262
|
setShowHint(true);
|
|
17165
17263
|
}
|
|
17166
17264
|
};
|
|
@@ -17173,20 +17271,24 @@ function BuilderBoard({
|
|
|
17173
17271
|
};
|
|
17174
17272
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
17175
17273
|
if (!resolved) return null;
|
|
17274
|
+
const theme = resolved.theme ?? void 0;
|
|
17275
|
+
const themeBackground = theme?.background;
|
|
17276
|
+
const headerImage = str(resolved.headerImage);
|
|
17277
|
+
const hint = str(resolved.hint);
|
|
17176
17278
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17177
17279
|
Box,
|
|
17178
17280
|
{
|
|
17179
17281
|
className,
|
|
17180
17282
|
style: {
|
|
17181
|
-
backgroundImage:
|
|
17283
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
17182
17284
|
backgroundSize: "cover",
|
|
17183
17285
|
backgroundPosition: "center"
|
|
17184
17286
|
},
|
|
17185
17287
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
17186
|
-
|
|
17288
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
17187
17289
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
17188
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
17189
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description })
|
|
17290
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
17291
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
17190
17292
|
] }) }),
|
|
17191
17293
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
17192
17294
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
|
|
@@ -17246,9 +17348,9 @@ function BuilderBoard({
|
|
|
17246
17348
|
] }) }),
|
|
17247
17349
|
submitted && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
17248
17350
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: allCorrect ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
17249
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
17351
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
|
|
17250
17352
|
] }) }),
|
|
17251
|
-
showHint &&
|
|
17353
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
17252
17354
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
17253
17355
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
17254
17356
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Wrench, size: "sm" }),
|
|
@@ -17267,6 +17369,7 @@ var init_BuilderBoard = __esm({
|
|
|
17267
17369
|
"components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
|
|
17268
17370
|
init_atoms2();
|
|
17269
17371
|
init_useEventBus();
|
|
17372
|
+
init_boardEntity();
|
|
17270
17373
|
BuilderBoard.displayName = "BuilderBoard";
|
|
17271
17374
|
}
|
|
17272
17375
|
});
|
|
@@ -17604,21 +17707,24 @@ function CalendarGrid({
|
|
|
17604
17707
|
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
17605
17708
|
}, 500);
|
|
17606
17709
|
}, [longPressEvent, longPressPayload, eventBus]);
|
|
17607
|
-
const renderEvent = (event) =>
|
|
17608
|
-
|
|
17609
|
-
|
|
17610
|
-
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
|
|
17614
|
-
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
|
|
17619
|
-
|
|
17620
|
-
|
|
17621
|
-
|
|
17710
|
+
const renderEvent = (event) => {
|
|
17711
|
+
const color = event.color;
|
|
17712
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17713
|
+
Box,
|
|
17714
|
+
{
|
|
17715
|
+
rounded: "md",
|
|
17716
|
+
padding: "xs",
|
|
17717
|
+
border: true,
|
|
17718
|
+
className: cn(
|
|
17719
|
+
"cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
|
|
17720
|
+
color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
|
|
17721
|
+
),
|
|
17722
|
+
onClick: (e) => handleEventClick(event, e),
|
|
17723
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
|
|
17724
|
+
},
|
|
17725
|
+
event.id
|
|
17726
|
+
);
|
|
17727
|
+
};
|
|
17622
17728
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17623
17729
|
Box,
|
|
17624
17730
|
{
|
|
@@ -19282,7 +19388,6 @@ var init_CardGrid = __esm({
|
|
|
19282
19388
|
alignItems = "stretch",
|
|
19283
19389
|
className,
|
|
19284
19390
|
children,
|
|
19285
|
-
// EntityDisplayProps
|
|
19286
19391
|
entity,
|
|
19287
19392
|
isLoading = false,
|
|
19288
19393
|
error = null,
|
|
@@ -19754,14 +19859,14 @@ var init_CaseStudyOrganism = __esm({
|
|
|
19754
19859
|
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
19755
19860
|
CaseStudyCard,
|
|
19756
19861
|
{
|
|
19757
|
-
title: study.title,
|
|
19758
|
-
description: study.description,
|
|
19759
|
-
category: study.category,
|
|
19760
|
-
categoryColor: study.categoryColor,
|
|
19761
|
-
href: study.href,
|
|
19762
|
-
linkLabel: study.linkLabel
|
|
19862
|
+
title: String(study.title ?? ""),
|
|
19863
|
+
description: String(study.description ?? ""),
|
|
19864
|
+
category: String(study.category ?? ""),
|
|
19865
|
+
categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
|
|
19866
|
+
href: String(study.href ?? ""),
|
|
19867
|
+
linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
|
|
19763
19868
|
},
|
|
19764
|
-
study.id
|
|
19869
|
+
String(study.id ?? "")
|
|
19765
19870
|
)) })
|
|
19766
19871
|
] });
|
|
19767
19872
|
};
|
|
@@ -19784,10 +19889,10 @@ function CastleBoard({
|
|
|
19784
19889
|
className
|
|
19785
19890
|
}) {
|
|
19786
19891
|
const eventBus = useEventBus();
|
|
19787
|
-
const resolved =
|
|
19788
|
-
const tiles = resolved?.tiles
|
|
19789
|
-
const features = resolved?.features
|
|
19790
|
-
const units = resolved?.units
|
|
19892
|
+
const resolved = boardEntity(entity);
|
|
19893
|
+
const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
|
|
19894
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
19895
|
+
const units = Array.isArray(resolved?.units) ? resolved.units : [];
|
|
19791
19896
|
const assetManifest = resolved?.assetManifest;
|
|
19792
19897
|
const backgroundImage = resolved?.backgroundImage;
|
|
19793
19898
|
const [hoveredTile, setHoveredTile] = React84.useState(null);
|
|
@@ -19815,7 +19920,7 @@ function CastleBoard({
|
|
|
19815
19920
|
onFeatureClick?.(feature);
|
|
19816
19921
|
if (featureClickEvent) {
|
|
19817
19922
|
eventBus.emit(`UI:${featureClickEvent}`, {
|
|
19818
|
-
featureId: feature.id,
|
|
19923
|
+
featureId: feature.id ?? "",
|
|
19819
19924
|
featureType: feature.type,
|
|
19820
19925
|
x: feature.x,
|
|
19821
19926
|
y: feature.y
|
|
@@ -19883,6 +19988,7 @@ var init_CastleBoard = __esm({
|
|
|
19883
19988
|
init_cn();
|
|
19884
19989
|
init_useEventBus();
|
|
19885
19990
|
init_IsometricCanvas2();
|
|
19991
|
+
init_boardEntity();
|
|
19886
19992
|
init_isometric();
|
|
19887
19993
|
CastleBoard.displayName = "CastleBoard";
|
|
19888
19994
|
}
|
|
@@ -20693,14 +20799,14 @@ function ClassifierBoard({
|
|
|
20693
20799
|
}) {
|
|
20694
20800
|
const { emit } = useEventBus();
|
|
20695
20801
|
const { t } = hooks.useTranslate();
|
|
20696
|
-
const resolved =
|
|
20802
|
+
const resolved = boardEntity(entity);
|
|
20697
20803
|
const [assignments, setAssignments] = React84.useState({});
|
|
20698
20804
|
const [headerError, setHeaderError] = React84.useState(false);
|
|
20699
20805
|
const [submitted, setSubmitted] = React84.useState(false);
|
|
20700
20806
|
const [attempts, setAttempts] = React84.useState(0);
|
|
20701
20807
|
const [showHint, setShowHint] = React84.useState(false);
|
|
20702
|
-
const items = resolved?.items
|
|
20703
|
-
const categories = resolved?.categories
|
|
20808
|
+
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
20809
|
+
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
20704
20810
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
20705
20811
|
const allAssigned = Object.keys(assignments).length === items.length;
|
|
20706
20812
|
const results = submitted ? items.map((item) => ({
|
|
@@ -20732,7 +20838,7 @@ function ClassifierBoard({
|
|
|
20732
20838
|
}, [items, assignments, attempts, completeEvent, emit]);
|
|
20733
20839
|
const handleReset = () => {
|
|
20734
20840
|
setSubmitted(false);
|
|
20735
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
20841
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
20736
20842
|
setShowHint(true);
|
|
20737
20843
|
}
|
|
20738
20844
|
};
|
|
@@ -20743,20 +20849,25 @@ function ClassifierBoard({
|
|
|
20743
20849
|
setShowHint(false);
|
|
20744
20850
|
};
|
|
20745
20851
|
if (!resolved) return null;
|
|
20852
|
+
const theme = resolved.theme ?? void 0;
|
|
20853
|
+
const themeBackground = theme?.background;
|
|
20854
|
+
const headerImage = str(resolved.headerImage);
|
|
20855
|
+
const hint = str(resolved.hint);
|
|
20856
|
+
const failMessage = str(resolved.failMessage);
|
|
20746
20857
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20747
20858
|
Box,
|
|
20748
20859
|
{
|
|
20749
20860
|
className,
|
|
20750
20861
|
style: {
|
|
20751
|
-
backgroundImage:
|
|
20862
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
20752
20863
|
backgroundSize: "cover",
|
|
20753
20864
|
backgroundPosition: "center"
|
|
20754
20865
|
},
|
|
20755
20866
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
20756
|
-
|
|
20867
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
20757
20868
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
20758
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
20759
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description })
|
|
20869
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
20870
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
20760
20871
|
] }) }),
|
|
20761
20872
|
unassignedItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
20762
20873
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
|
|
@@ -20808,10 +20919,10 @@ function ClassifierBoard({
|
|
|
20808
20919
|
}) }),
|
|
20809
20920
|
submitted && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
20810
20921
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: allCorrect ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
20811
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
20812
|
-
!allCorrect &&
|
|
20922
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
|
|
20923
|
+
!allCorrect && failMessage && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
|
|
20813
20924
|
] }) }),
|
|
20814
|
-
showHint &&
|
|
20925
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
20815
20926
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
20816
20927
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
20817
20928
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Send, size: "sm" }),
|
|
@@ -20830,6 +20941,7 @@ var init_ClassifierBoard = __esm({
|
|
|
20830
20941
|
"components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
|
|
20831
20942
|
init_atoms2();
|
|
20832
20943
|
init_useEventBus();
|
|
20944
|
+
init_boardEntity();
|
|
20833
20945
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
20834
20946
|
}
|
|
20835
20947
|
});
|
|
@@ -27200,7 +27312,7 @@ function InventoryPanel({
|
|
|
27200
27312
|
const slotArray = Array.from({ length: safeSlots }, (_, index) => {
|
|
27201
27313
|
return safeItems[index] ?? null;
|
|
27202
27314
|
});
|
|
27203
|
-
const
|
|
27315
|
+
const rows2 = Math.ceil(safeSlots / safeColumns);
|
|
27204
27316
|
const handleSlotClick = React84.useCallback((index) => {
|
|
27205
27317
|
if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
|
|
27206
27318
|
onSelectSlot?.(index);
|
|
@@ -27269,7 +27381,7 @@ function InventoryPanel({
|
|
|
27269
27381
|
className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
|
|
27270
27382
|
style: {
|
|
27271
27383
|
gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
|
|
27272
|
-
gridTemplateRows: `repeat(${
|
|
27384
|
+
gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
|
|
27273
27385
|
},
|
|
27274
27386
|
children: slotArray.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
27275
27387
|
"button",
|
|
@@ -31233,11 +31345,11 @@ function LatticeSVG({
|
|
|
31233
31345
|
}) {
|
|
31234
31346
|
const paths = [];
|
|
31235
31347
|
const cols = 5;
|
|
31236
|
-
const
|
|
31348
|
+
const rows2 = Math.ceil(h / (w / cols));
|
|
31237
31349
|
const cellW = w / cols;
|
|
31238
31350
|
const cellH = cellW;
|
|
31239
31351
|
const bulge = cellW * 0.3;
|
|
31240
|
-
for (let row = 0; row <
|
|
31352
|
+
for (let row = 0; row < rows2; row++) {
|
|
31241
31353
|
for (let col = 0; col < cols; col++) {
|
|
31242
31354
|
const cx = col * cellW + cellW / 2;
|
|
31243
31355
|
const cy = row * cellH + cellH / 2;
|
|
@@ -31649,7 +31761,7 @@ var init_MatrixQuestion = __esm({
|
|
|
31649
31761
|
};
|
|
31650
31762
|
MatrixQuestion = ({
|
|
31651
31763
|
title,
|
|
31652
|
-
rows,
|
|
31764
|
+
rows: rows2,
|
|
31653
31765
|
columns = DEFAULT_MATRIX_COLUMNS,
|
|
31654
31766
|
values,
|
|
31655
31767
|
onChange,
|
|
@@ -31659,7 +31771,7 @@ var init_MatrixQuestion = __esm({
|
|
|
31659
31771
|
className
|
|
31660
31772
|
}) => {
|
|
31661
31773
|
const styles = sizeStyles13[size];
|
|
31662
|
-
const safeRows =
|
|
31774
|
+
const safeRows = rows2 ?? [];
|
|
31663
31775
|
const safeValues = values ?? {};
|
|
31664
31776
|
const eventBus = useEventBus();
|
|
31665
31777
|
const handleChange = React84.useCallback(
|
|
@@ -32287,7 +32399,8 @@ var init_PositionedCanvas = __esm({
|
|
|
32287
32399
|
dragRef.current = null;
|
|
32288
32400
|
setDraggingId(null);
|
|
32289
32401
|
if (!wasDrag) {
|
|
32290
|
-
const
|
|
32402
|
+
const itemId = item.id;
|
|
32403
|
+
const next = selectedId === itemId ? null : itemId;
|
|
32291
32404
|
onSelect?.(next);
|
|
32292
32405
|
if (selectEvent) {
|
|
32293
32406
|
eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
@@ -32322,15 +32435,22 @@ var init_PositionedCanvas = __esm({
|
|
|
32322
32435
|
style: { width, height },
|
|
32323
32436
|
onClick: handleContainerClick,
|
|
32324
32437
|
children: items.map((item) => {
|
|
32438
|
+
const itemId = item.id;
|
|
32439
|
+
const label = item.label;
|
|
32440
|
+
const x = item.x;
|
|
32441
|
+
const y = item.y;
|
|
32442
|
+
const capacity = item.capacity;
|
|
32443
|
+
const partySize = item.partySize;
|
|
32444
|
+
const serverName = item.serverName;
|
|
32325
32445
|
const status = item.status ?? "empty";
|
|
32326
32446
|
const shape = item.shape ?? "round";
|
|
32327
|
-
const isSelected = selectedId ===
|
|
32328
|
-
const isDragging = draggingId ===
|
|
32447
|
+
const isSelected = selectedId === itemId;
|
|
32448
|
+
const isDragging = draggingId === itemId;
|
|
32329
32449
|
const statusBadge = STATUS_BADGE[status];
|
|
32330
32450
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
32331
32451
|
Box,
|
|
32332
32452
|
{
|
|
32333
|
-
"data-testid": `item-node-${
|
|
32453
|
+
"data-testid": `item-node-${itemId}`,
|
|
32334
32454
|
"data-status": status,
|
|
32335
32455
|
className: cn(
|
|
32336
32456
|
"absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
|
|
@@ -32341,7 +32461,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32341
32461
|
isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
|
|
32342
32462
|
isDragging && "shadow-lg z-10"
|
|
32343
32463
|
),
|
|
32344
|
-
style: { left:
|
|
32464
|
+
style: { left: x, top: y, touchAction: "none" },
|
|
32345
32465
|
onPointerDown: (e) => handlePointerDown(e, item),
|
|
32346
32466
|
onPointerMove: handlePointerMove,
|
|
32347
32467
|
onPointerUp: (e) => handlePointerUp(e, item),
|
|
@@ -32349,10 +32469,10 @@ var init_PositionedCanvas = __esm({
|
|
|
32349
32469
|
children: [
|
|
32350
32470
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-1", children: [
|
|
32351
32471
|
getStatusIcon(status),
|
|
32352
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", weight: "semibold", children:
|
|
32472
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", weight: "semibold", children: label })
|
|
32353
32473
|
] }),
|
|
32354
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
32355
|
-
status === "seated" &&
|
|
32474
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
|
|
32475
|
+
status === "seated" && serverName && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
|
|
32356
32476
|
isSelected && /* @__PURE__ */ jsxRuntime.jsx(
|
|
32357
32477
|
Badge,
|
|
32358
32478
|
{
|
|
@@ -32364,7 +32484,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32364
32484
|
)
|
|
32365
32485
|
]
|
|
32366
32486
|
},
|
|
32367
|
-
|
|
32487
|
+
itemId
|
|
32368
32488
|
);
|
|
32369
32489
|
})
|
|
32370
32490
|
}
|
|
@@ -33136,9 +33256,10 @@ var init_RichBlockEditor = __esm({
|
|
|
33136
33256
|
});
|
|
33137
33257
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
33138
33258
|
for (const n of nodes) {
|
|
33259
|
+
const replies = n.replies;
|
|
33139
33260
|
if (n.collapsed) acc.add(n.id);
|
|
33140
|
-
if (
|
|
33141
|
-
collectInitiallyCollapsed(
|
|
33261
|
+
if (replies && replies.length > 0) {
|
|
33262
|
+
collectInitiallyCollapsed(replies, acc);
|
|
33142
33263
|
}
|
|
33143
33264
|
}
|
|
33144
33265
|
}
|
|
@@ -33168,44 +33289,52 @@ var init_ReplyTree = __esm({
|
|
|
33168
33289
|
}) => {
|
|
33169
33290
|
const eventBus = useEventBus();
|
|
33170
33291
|
const { t } = hooks.useTranslate();
|
|
33171
|
-
const
|
|
33172
|
-
const
|
|
33292
|
+
const nodeId = node.id;
|
|
33293
|
+
const authorName = node.authorName;
|
|
33294
|
+
const authorAvatarUrl = node.authorAvatarUrl;
|
|
33295
|
+
const content = node.content;
|
|
33296
|
+
const postedAt = node.postedAt;
|
|
33297
|
+
const voteCount = node.voteCount;
|
|
33298
|
+
const userVote = node.userVote;
|
|
33299
|
+
const replies = node.replies;
|
|
33300
|
+
const hasReplies = !!replies && replies.length > 0;
|
|
33301
|
+
const isCollapsed = collapsedSet.has(nodeId);
|
|
33173
33302
|
const atMaxDepth = depth >= maxDepth;
|
|
33174
33303
|
const [replyOpen, setReplyOpen] = React84.useState(false);
|
|
33175
33304
|
const [draft, setDraft] = React84.useState("");
|
|
33176
33305
|
const handleVote = React84.useCallback(
|
|
33177
33306
|
(next) => {
|
|
33178
|
-
onVote?.(
|
|
33179
|
-
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId
|
|
33307
|
+
onVote?.(nodeId, next);
|
|
33308
|
+
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
|
|
33180
33309
|
},
|
|
33181
|
-
[
|
|
33310
|
+
[nodeId, onVote, voteEvent, eventBus]
|
|
33182
33311
|
);
|
|
33183
33312
|
const handleReply = React84.useCallback(() => {
|
|
33184
|
-
onReply?.(
|
|
33313
|
+
onReply?.(nodeId);
|
|
33185
33314
|
setReplyOpen((open) => !open);
|
|
33186
|
-
}, [
|
|
33315
|
+
}, [nodeId, onReply]);
|
|
33187
33316
|
const handleSubmitReply = React84.useCallback(() => {
|
|
33188
|
-
const
|
|
33189
|
-
if (!
|
|
33190
|
-
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId:
|
|
33317
|
+
const text = draft.trim();
|
|
33318
|
+
if (!text) return;
|
|
33319
|
+
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
|
|
33191
33320
|
setDraft("");
|
|
33192
33321
|
setReplyOpen(false);
|
|
33193
|
-
}, [
|
|
33322
|
+
}, [nodeId, draft, replyEvent, eventBus]);
|
|
33194
33323
|
const handleCancelReply = React84.useCallback(() => {
|
|
33195
33324
|
setDraft("");
|
|
33196
33325
|
setReplyOpen(false);
|
|
33197
33326
|
}, []);
|
|
33198
33327
|
const handleFlag = React84.useCallback(() => {
|
|
33199
|
-
onFlag?.(
|
|
33200
|
-
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId
|
|
33201
|
-
}, [
|
|
33328
|
+
onFlag?.(nodeId);
|
|
33329
|
+
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
|
|
33330
|
+
}, [nodeId, onFlag, flagEvent, eventBus]);
|
|
33202
33331
|
const handleContinue = React84.useCallback(() => {
|
|
33203
|
-
onContinueThread?.(
|
|
33204
|
-
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId
|
|
33205
|
-
}, [
|
|
33332
|
+
onContinueThread?.(nodeId);
|
|
33333
|
+
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
|
|
33334
|
+
}, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
|
|
33206
33335
|
const handleToggle = React84.useCallback(() => {
|
|
33207
|
-
toggleCollapse(
|
|
33208
|
-
}, [
|
|
33336
|
+
toggleCollapse(nodeId);
|
|
33337
|
+
}, [nodeId, toggleCollapse]);
|
|
33209
33338
|
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
|
|
33210
33339
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
|
|
33211
33340
|
hasReplies ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -33237,25 +33366,25 @@ var init_ReplyTree = __esm({
|
|
|
33237
33366
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
33238
33367
|
Avatar,
|
|
33239
33368
|
{
|
|
33240
|
-
src:
|
|
33241
|
-
name:
|
|
33369
|
+
src: authorAvatarUrl,
|
|
33370
|
+
name: authorName,
|
|
33242
33371
|
size: "sm"
|
|
33243
33372
|
}
|
|
33244
33373
|
),
|
|
33245
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "semibold", children:
|
|
33246
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
33374
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
|
|
33375
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
|
|
33247
33376
|
] }),
|
|
33248
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children:
|
|
33377
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
|
|
33249
33378
|
showActions && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
33250
33379
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
33251
33380
|
VoteStack,
|
|
33252
33381
|
{
|
|
33253
|
-
count:
|
|
33254
|
-
userVote:
|
|
33382
|
+
count: voteCount ?? 0,
|
|
33383
|
+
userVote: userVote ?? null,
|
|
33255
33384
|
onVote: handleVote,
|
|
33256
33385
|
size: "sm",
|
|
33257
33386
|
variant: "horizontal",
|
|
33258
|
-
label: t("replyTree.voteOnReplyBy", { author:
|
|
33387
|
+
label: t("replyTree.voteOnReplyBy", { author: authorName })
|
|
33259
33388
|
}
|
|
33260
33389
|
),
|
|
33261
33390
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -33265,7 +33394,7 @@ var init_ReplyTree = __esm({
|
|
|
33265
33394
|
size: "sm",
|
|
33266
33395
|
leftIcon: "message-square",
|
|
33267
33396
|
onClick: handleReply,
|
|
33268
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33397
|
+
"aria-label": t("replyTree.replyTo", { author: authorName }),
|
|
33269
33398
|
children: t("replyTree.reply")
|
|
33270
33399
|
}
|
|
33271
33400
|
),
|
|
@@ -33276,7 +33405,7 @@ var init_ReplyTree = __esm({
|
|
|
33276
33405
|
size: "sm",
|
|
33277
33406
|
leftIcon: "flag",
|
|
33278
33407
|
onClick: handleFlag,
|
|
33279
|
-
"aria-label": t("replyTree.flagReplyBy", { author:
|
|
33408
|
+
"aria-label": t("replyTree.flagReplyBy", { author: authorName }),
|
|
33280
33409
|
children: t("replyTree.flag")
|
|
33281
33410
|
}
|
|
33282
33411
|
)
|
|
@@ -33288,9 +33417,9 @@ var init_ReplyTree = __esm({
|
|
|
33288
33417
|
inputType: "textarea",
|
|
33289
33418
|
rows: 2,
|
|
33290
33419
|
value: draft,
|
|
33291
|
-
placeholder: t("replyTree.replyToPlaceholder", { author:
|
|
33420
|
+
placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
|
|
33292
33421
|
onChange: (e) => setDraft(e.target.value),
|
|
33293
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33422
|
+
"aria-label": t("replyTree.replyTo", { author: authorName })
|
|
33294
33423
|
}
|
|
33295
33424
|
),
|
|
33296
33425
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
@@ -33321,7 +33450,7 @@ var init_ReplyTree = __esm({
|
|
|
33321
33450
|
),
|
|
33322
33451
|
children: t("replyTree.continueThread")
|
|
33323
33452
|
}
|
|
33324
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-2 mt-1", children:
|
|
33453
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
33325
33454
|
ReplyTreeNode,
|
|
33326
33455
|
{
|
|
33327
33456
|
node: child,
|
|
@@ -35641,8 +35770,8 @@ var init_WizardContainer = __esm({
|
|
|
35641
35770
|
return void 0;
|
|
35642
35771
|
if (typeof controlledStep === "number") return controlledStep;
|
|
35643
35772
|
if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
|
|
35644
|
-
const
|
|
35645
|
-
return isNaN(
|
|
35773
|
+
const num2 = Number(controlledStep);
|
|
35774
|
+
return isNaN(num2) ? void 0 : num2;
|
|
35646
35775
|
})();
|
|
35647
35776
|
const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
|
|
35648
35777
|
const totalSteps = steps.length;
|
|
@@ -37347,7 +37476,7 @@ function DebuggerBoard({
|
|
|
37347
37476
|
}) {
|
|
37348
37477
|
const { emit } = useEventBus();
|
|
37349
37478
|
const { t } = hooks.useTranslate();
|
|
37350
|
-
const resolved =
|
|
37479
|
+
const resolved = boardEntity(entity);
|
|
37351
37480
|
const [flaggedLines, setFlaggedLines] = React84.useState(/* @__PURE__ */ new Set());
|
|
37352
37481
|
const [headerError, setHeaderError] = React84.useState(false);
|
|
37353
37482
|
const [submitted, setSubmitted] = React84.useState(false);
|
|
@@ -37365,7 +37494,7 @@ function DebuggerBoard({
|
|
|
37365
37494
|
return next;
|
|
37366
37495
|
});
|
|
37367
37496
|
};
|
|
37368
|
-
const lines = resolved?.lines
|
|
37497
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
37369
37498
|
const bugLines = lines.filter((l) => l.isBug);
|
|
37370
37499
|
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
37371
37500
|
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
@@ -37380,7 +37509,7 @@ function DebuggerBoard({
|
|
|
37380
37509
|
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
37381
37510
|
const handleReset = () => {
|
|
37382
37511
|
setSubmitted(false);
|
|
37383
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
37512
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
37384
37513
|
setShowHint(true);
|
|
37385
37514
|
}
|
|
37386
37515
|
};
|
|
@@ -37391,24 +37520,28 @@ function DebuggerBoard({
|
|
|
37391
37520
|
setShowHint(false);
|
|
37392
37521
|
};
|
|
37393
37522
|
if (!resolved) return null;
|
|
37523
|
+
const theme = resolved.theme ?? void 0;
|
|
37524
|
+
const themeBackground = theme?.background;
|
|
37525
|
+
const headerImage = str(resolved.headerImage);
|
|
37526
|
+
const hint = str(resolved.hint);
|
|
37394
37527
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
37395
37528
|
Box,
|
|
37396
37529
|
{
|
|
37397
37530
|
className,
|
|
37398
37531
|
style: {
|
|
37399
|
-
backgroundImage:
|
|
37532
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
37400
37533
|
backgroundSize: "cover",
|
|
37401
37534
|
backgroundPosition: "center"
|
|
37402
37535
|
},
|
|
37403
37536
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
37404
|
-
|
|
37537
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
37405
37538
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
37406
37539
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
37407
37540
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Bug, size: "sm" }),
|
|
37408
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
|
|
37541
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
|
|
37409
37542
|
] }),
|
|
37410
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description }),
|
|
37411
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
|
|
37543
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
37544
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
37412
37545
|
] }) }),
|
|
37413
37546
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
37414
37547
|
const isFlagged = flaggedLines.has(line.id);
|
|
@@ -37440,7 +37573,7 @@ function DebuggerBoard({
|
|
|
37440
37573
|
);
|
|
37441
37574
|
}) }) }),
|
|
37442
37575
|
submitted && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
37443
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
37576
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
37444
37577
|
bugLines.map((line) => /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
37445
37578
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
37446
37579
|
Icon,
|
|
@@ -37456,7 +37589,7 @@ function DebuggerBoard({
|
|
|
37456
37589
|
] })
|
|
37457
37590
|
] }, line.id))
|
|
37458
37591
|
] }) }),
|
|
37459
|
-
showHint &&
|
|
37592
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
37460
37593
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
37461
37594
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
37462
37595
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Send, size: "sm" }),
|
|
@@ -37475,6 +37608,7 @@ var init_DebuggerBoard = __esm({
|
|
|
37475
37608
|
"components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
|
|
37476
37609
|
init_atoms2();
|
|
37477
37610
|
init_useEventBus();
|
|
37611
|
+
init_boardEntity();
|
|
37478
37612
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
37479
37613
|
}
|
|
37480
37614
|
});
|
|
@@ -37512,7 +37646,7 @@ function getBadgeVariant(fieldName, value) {
|
|
|
37512
37646
|
return "default";
|
|
37513
37647
|
}
|
|
37514
37648
|
function formatFieldLabel(fieldName) {
|
|
37515
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
37649
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
|
|
37516
37650
|
}
|
|
37517
37651
|
function formatFieldValue(value, fieldName) {
|
|
37518
37652
|
if (typeof value === "number") {
|
|
@@ -37531,26 +37665,26 @@ function formatFieldValue(value, fieldName) {
|
|
|
37531
37665
|
}
|
|
37532
37666
|
function renderRichFieldValue(value, fieldName, fieldType) {
|
|
37533
37667
|
if (value === void 0 || value === null) return "\u2014";
|
|
37534
|
-
const
|
|
37668
|
+
const str2 = String(value);
|
|
37535
37669
|
switch (fieldType) {
|
|
37536
37670
|
case "image":
|
|
37537
37671
|
case "url": {
|
|
37538
|
-
if (
|
|
37672
|
+
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
37539
37673
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
37540
37674
|
"img",
|
|
37541
37675
|
{
|
|
37542
|
-
src:
|
|
37676
|
+
src: str2,
|
|
37543
37677
|
alt: formatFieldLabel(fieldName),
|
|
37544
37678
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
37545
37679
|
loading: "lazy"
|
|
37546
37680
|
}
|
|
37547
37681
|
) });
|
|
37548
37682
|
}
|
|
37549
|
-
return
|
|
37683
|
+
return str2;
|
|
37550
37684
|
}
|
|
37551
37685
|
case "markdown":
|
|
37552
37686
|
case "richtext":
|
|
37553
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React84.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "break-words", children:
|
|
37687
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React84.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
37554
37688
|
Box,
|
|
37555
37689
|
{
|
|
37556
37690
|
className: "prose prose-sm max-w-none",
|
|
@@ -37568,11 +37702,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37568
37702
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37569
37703
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37570
37704
|
},
|
|
37571
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown2, { children:
|
|
37705
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown2, { children: str2 })
|
|
37572
37706
|
}
|
|
37573
37707
|
) });
|
|
37574
37708
|
case "code":
|
|
37575
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children:
|
|
37709
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: str2 }) }) });
|
|
37576
37710
|
case "html":
|
|
37577
37711
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
37578
37712
|
Box,
|
|
@@ -37592,12 +37726,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37592
37726
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37593
37727
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37594
37728
|
},
|
|
37595
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children:
|
|
37729
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str2 })
|
|
37596
37730
|
}
|
|
37597
37731
|
);
|
|
37598
37732
|
case "date":
|
|
37599
37733
|
case "datetime": {
|
|
37600
|
-
const d = new Date(
|
|
37734
|
+
const d = new Date(str2);
|
|
37601
37735
|
if (!isNaN(d.getTime())) {
|
|
37602
37736
|
return d.toLocaleDateString(void 0, {
|
|
37603
37737
|
year: "numeric",
|
|
@@ -37606,7 +37740,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37606
37740
|
...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
|
|
37607
37741
|
});
|
|
37608
37742
|
}
|
|
37609
|
-
return
|
|
37743
|
+
return str2;
|
|
37610
37744
|
}
|
|
37611
37745
|
default:
|
|
37612
37746
|
return formatFieldValue(value, fieldName);
|
|
@@ -38284,6 +38418,40 @@ var init_RuleEditor = __esm({
|
|
|
38284
38418
|
RuleEditor.displayName = "RuleEditor";
|
|
38285
38419
|
}
|
|
38286
38420
|
});
|
|
38421
|
+
|
|
38422
|
+
// components/game/organisms/puzzles/event-handler/puzzleObject.ts
|
|
38423
|
+
function objId(o) {
|
|
38424
|
+
return o.id == null ? "" : String(o.id);
|
|
38425
|
+
}
|
|
38426
|
+
function objName(o) {
|
|
38427
|
+
return o.name == null ? "" : String(o.name);
|
|
38428
|
+
}
|
|
38429
|
+
function objIcon(o) {
|
|
38430
|
+
return o.icon == null ? "" : String(o.icon);
|
|
38431
|
+
}
|
|
38432
|
+
function objStates(o) {
|
|
38433
|
+
return Array.isArray(o.states) ? o.states : [];
|
|
38434
|
+
}
|
|
38435
|
+
function objCurrentState(o) {
|
|
38436
|
+
return o.currentState == null ? "" : String(o.currentState);
|
|
38437
|
+
}
|
|
38438
|
+
function objAvailableEvents(o) {
|
|
38439
|
+
return Array.isArray(o.availableEvents) ? o.availableEvents : [];
|
|
38440
|
+
}
|
|
38441
|
+
function objAvailableActions(o) {
|
|
38442
|
+
return Array.isArray(o.availableActions) ? o.availableActions : [];
|
|
38443
|
+
}
|
|
38444
|
+
function objRules(o) {
|
|
38445
|
+
return Array.isArray(o.rules) ? o.rules : [];
|
|
38446
|
+
}
|
|
38447
|
+
function objMaxRules(o) {
|
|
38448
|
+
const n = Number(o.maxRules);
|
|
38449
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
38450
|
+
}
|
|
38451
|
+
var init_puzzleObject = __esm({
|
|
38452
|
+
"components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
|
|
38453
|
+
}
|
|
38454
|
+
});
|
|
38287
38455
|
function ObjectRulePanel({
|
|
38288
38456
|
object,
|
|
38289
38457
|
onRulesChange,
|
|
@@ -38291,55 +38459,63 @@ function ObjectRulePanel({
|
|
|
38291
38459
|
className
|
|
38292
38460
|
}) {
|
|
38293
38461
|
const { t } = hooks.useTranslate();
|
|
38294
|
-
const
|
|
38295
|
-
const
|
|
38462
|
+
const id = objId(object);
|
|
38463
|
+
const name = objName(object);
|
|
38464
|
+
const icon = objIcon(object);
|
|
38465
|
+
const states = objStates(object);
|
|
38466
|
+
const currentState = objCurrentState(object);
|
|
38467
|
+
const availableEvents = objAvailableEvents(object);
|
|
38468
|
+
const availableActions = objAvailableActions(object);
|
|
38469
|
+
const rules = objRules(object);
|
|
38470
|
+
const maxRules = objMaxRules(object);
|
|
38471
|
+
const canAdd = rules.length < maxRules;
|
|
38296
38472
|
const handleRuleChange = React84.useCallback((index, updatedRule) => {
|
|
38297
|
-
const newRules = [...
|
|
38473
|
+
const newRules = [...rules];
|
|
38298
38474
|
newRules[index] = updatedRule;
|
|
38299
|
-
onRulesChange(
|
|
38300
|
-
}, [
|
|
38475
|
+
onRulesChange(id, newRules);
|
|
38476
|
+
}, [id, rules, onRulesChange]);
|
|
38301
38477
|
const handleRuleRemove = React84.useCallback((index) => {
|
|
38302
|
-
const newRules =
|
|
38303
|
-
onRulesChange(
|
|
38304
|
-
}, [
|
|
38478
|
+
const newRules = rules.filter((_, i) => i !== index);
|
|
38479
|
+
onRulesChange(id, newRules);
|
|
38480
|
+
}, [id, rules, onRulesChange]);
|
|
38305
38481
|
const handleAddRule = React84.useCallback(() => {
|
|
38306
38482
|
if (!canAdd || disabled) return;
|
|
38307
|
-
const firstEvent =
|
|
38308
|
-
const firstAction =
|
|
38483
|
+
const firstEvent = availableEvents[0]?.value || "";
|
|
38484
|
+
const firstAction = availableActions[0]?.value || "";
|
|
38309
38485
|
const newRule = {
|
|
38310
38486
|
id: `rule-${nextRuleId++}`,
|
|
38311
38487
|
whenEvent: firstEvent,
|
|
38312
38488
|
thenAction: firstAction
|
|
38313
38489
|
};
|
|
38314
|
-
onRulesChange(
|
|
38315
|
-
}, [canAdd, disabled,
|
|
38490
|
+
onRulesChange(id, [...rules, newRule]);
|
|
38491
|
+
}, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
|
|
38316
38492
|
const machine = {
|
|
38317
|
-
name
|
|
38318
|
-
states
|
|
38319
|
-
currentState
|
|
38320
|
-
transitions:
|
|
38321
|
-
from:
|
|
38322
|
-
to:
|
|
38493
|
+
name,
|
|
38494
|
+
states,
|
|
38495
|
+
currentState,
|
|
38496
|
+
transitions: rules.map((r) => ({
|
|
38497
|
+
from: currentState,
|
|
38498
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38323
38499
|
event: r.whenEvent
|
|
38324
38500
|
}))
|
|
38325
38501
|
};
|
|
38326
38502
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
38327
38503
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center", gap: "sm", children: [
|
|
38328
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", children:
|
|
38504
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", children: icon }),
|
|
38329
38505
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", children: [
|
|
38330
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children:
|
|
38331
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " +
|
|
38506
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
|
|
38507
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
|
|
38332
38508
|
] })
|
|
38333
38509
|
] }),
|
|
38334
38510
|
/* @__PURE__ */ jsxRuntime.jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
|
|
38335
38511
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
38336
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count:
|
|
38337
|
-
|
|
38512
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
|
|
38513
|
+
rules.map((rule, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
38338
38514
|
RuleEditor,
|
|
38339
38515
|
{
|
|
38340
38516
|
rule,
|
|
38341
|
-
availableEvents
|
|
38342
|
-
availableActions
|
|
38517
|
+
availableEvents,
|
|
38518
|
+
availableActions,
|
|
38343
38519
|
onChange: (r) => handleRuleChange(i, r),
|
|
38344
38520
|
onRemove: () => handleRuleRemove(i),
|
|
38345
38521
|
disabled
|
|
@@ -38357,6 +38533,7 @@ var init_ObjectRulePanel = __esm({
|
|
|
38357
38533
|
init_cn();
|
|
38358
38534
|
init_TraitStateViewer();
|
|
38359
38535
|
init_RuleEditor();
|
|
38536
|
+
init_puzzleObject();
|
|
38360
38537
|
nextRuleId = 1;
|
|
38361
38538
|
ObjectRulePanel.displayName = "ObjectRulePanel";
|
|
38362
38539
|
}
|
|
@@ -38423,11 +38600,11 @@ function EventHandlerBoard({
|
|
|
38423
38600
|
}) {
|
|
38424
38601
|
const { emit } = useEventBus();
|
|
38425
38602
|
const { t } = hooks.useTranslate();
|
|
38426
|
-
const resolved =
|
|
38427
|
-
const entityObjects = resolved?.objects
|
|
38428
|
-
const [objects, setObjects] = React84.useState(entityObjects);
|
|
38603
|
+
const resolved = boardEntity(entity);
|
|
38604
|
+
const entityObjects = rows(resolved?.objects);
|
|
38605
|
+
const [objects, setObjects] = React84.useState(() => [...entityObjects]);
|
|
38429
38606
|
const [selectedObjectId, setSelectedObjectId] = React84.useState(
|
|
38430
|
-
entityObjects[0]
|
|
38607
|
+
entityObjects[0] ? objId(entityObjects[0]) : null
|
|
38431
38608
|
);
|
|
38432
38609
|
const [headerError, setHeaderError] = React84.useState(false);
|
|
38433
38610
|
const [playState, setPlayState] = React84.useState("editing");
|
|
@@ -38438,10 +38615,10 @@ function EventHandlerBoard({
|
|
|
38438
38615
|
React84.useEffect(() => () => {
|
|
38439
38616
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38440
38617
|
}, []);
|
|
38441
|
-
const selectedObject = objects.find((o) => o
|
|
38618
|
+
const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
|
|
38442
38619
|
const handleRulesChange = React84.useCallback((objectId, rules) => {
|
|
38443
38620
|
setObjects((prev) => prev.map(
|
|
38444
|
-
(o) => o
|
|
38621
|
+
(o) => objId(o) === objectId ? { ...o, rules } : o
|
|
38445
38622
|
));
|
|
38446
38623
|
}, []);
|
|
38447
38624
|
const addLogEntry = React84.useCallback((icon, message, status = "done") => {
|
|
@@ -38455,11 +38632,12 @@ function EventHandlerBoard({
|
|
|
38455
38632
|
setEventLog([]);
|
|
38456
38633
|
const allRules = [];
|
|
38457
38634
|
objects.forEach((obj) => {
|
|
38458
|
-
obj.
|
|
38635
|
+
objRules(obj).forEach((rule) => {
|
|
38459
38636
|
allRules.push({ object: obj, rule });
|
|
38460
38637
|
});
|
|
38461
38638
|
});
|
|
38462
|
-
const triggers = resolved?.triggerEvents
|
|
38639
|
+
const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
|
|
38640
|
+
const goalEvent = str(resolved?.goalEvent);
|
|
38463
38641
|
const eventQueue = [...triggers];
|
|
38464
38642
|
const firedEvents = /* @__PURE__ */ new Set();
|
|
38465
38643
|
let stepIdx = 0;
|
|
@@ -38488,14 +38666,14 @@ function EventHandlerBoard({
|
|
|
38488
38666
|
addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
|
|
38489
38667
|
} else {
|
|
38490
38668
|
matching.forEach(({ object, rule }) => {
|
|
38491
|
-
addLogEntry(object
|
|
38669
|
+
addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
|
|
38492
38670
|
eventQueue.push(rule.thenAction);
|
|
38493
|
-
if (rule.thenAction ===
|
|
38671
|
+
if (rule.thenAction === goalEvent) {
|
|
38494
38672
|
goalReached = true;
|
|
38495
38673
|
}
|
|
38496
38674
|
});
|
|
38497
38675
|
}
|
|
38498
|
-
if (currentEvent ===
|
|
38676
|
+
if (currentEvent === goalEvent) {
|
|
38499
38677
|
goalReached = true;
|
|
38500
38678
|
}
|
|
38501
38679
|
stepIdx++;
|
|
@@ -38513,65 +38691,75 @@ function EventHandlerBoard({
|
|
|
38513
38691
|
}, []);
|
|
38514
38692
|
const handleReset = React84.useCallback(() => {
|
|
38515
38693
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38516
|
-
|
|
38694
|
+
const resetObjects = rows(resolved?.objects);
|
|
38695
|
+
setObjects([...resetObjects]);
|
|
38517
38696
|
setPlayState("editing");
|
|
38518
38697
|
setEventLog([]);
|
|
38519
|
-
setSelectedObjectId(
|
|
38698
|
+
setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
|
|
38520
38699
|
setAttempts(0);
|
|
38521
38700
|
}, [resolved?.objects]);
|
|
38522
38701
|
if (!resolved) return null;
|
|
38523
38702
|
const objectViewers = objects.map((obj) => {
|
|
38703
|
+
const states = objStates(obj);
|
|
38704
|
+
const currentState = objCurrentState(obj);
|
|
38524
38705
|
const machine = {
|
|
38525
|
-
name: obj
|
|
38526
|
-
states
|
|
38527
|
-
currentState
|
|
38528
|
-
transitions: obj.
|
|
38529
|
-
from:
|
|
38530
|
-
to:
|
|
38706
|
+
name: objName(obj),
|
|
38707
|
+
states,
|
|
38708
|
+
currentState,
|
|
38709
|
+
transitions: objRules(obj).map((r) => ({
|
|
38710
|
+
from: currentState,
|
|
38711
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38531
38712
|
event: r.whenEvent
|
|
38532
38713
|
}))
|
|
38533
38714
|
};
|
|
38534
38715
|
return { obj, machine };
|
|
38535
38716
|
});
|
|
38536
|
-
const
|
|
38717
|
+
const hint = str(resolved.hint);
|
|
38718
|
+
const showHint = attempts >= 3 && hint;
|
|
38719
|
+
const theme = resolved.theme ?? void 0;
|
|
38720
|
+
const themeBackground = theme?.background;
|
|
38721
|
+
const headerImage = str(resolved.headerImage);
|
|
38537
38722
|
const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
|
|
38538
38723
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38539
38724
|
VStack,
|
|
38540
38725
|
{
|
|
38541
38726
|
className: cn("p-4 gap-6", className),
|
|
38542
38727
|
style: {
|
|
38543
|
-
backgroundImage:
|
|
38728
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
38544
38729
|
backgroundSize: "cover",
|
|
38545
38730
|
backgroundPosition: "center"
|
|
38546
38731
|
},
|
|
38547
38732
|
children: [
|
|
38548
|
-
|
|
38733
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
38549
38734
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
38550
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
38551
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
38735
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
38736
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
38552
38737
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
38553
38738
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
38554
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
|
|
38739
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
|
|
38555
38740
|
] })
|
|
38556
38741
|
] }),
|
|
38557
38742
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
38558
38743
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
38559
|
-
/* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) =>
|
|
38560
|
-
|
|
38561
|
-
|
|
38562
|
-
|
|
38563
|
-
|
|
38564
|
-
|
|
38565
|
-
|
|
38566
|
-
|
|
38567
|
-
|
|
38568
|
-
|
|
38569
|
-
/* @__PURE__ */ jsxRuntime.
|
|
38570
|
-
|
|
38571
|
-
|
|
38572
|
-
|
|
38573
|
-
|
|
38574
|
-
|
|
38744
|
+
/* @__PURE__ */ jsxRuntime.jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
|
|
38745
|
+
const oid = objId(obj);
|
|
38746
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38747
|
+
Box,
|
|
38748
|
+
{
|
|
38749
|
+
className: cn(
|
|
38750
|
+
"p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
|
|
38751
|
+
selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
38752
|
+
),
|
|
38753
|
+
onClick: () => setSelectedObjectId(oid),
|
|
38754
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
38755
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", children: objIcon(obj) }),
|
|
38756
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
|
|
38757
|
+
/* @__PURE__ */ jsxRuntime.jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
38758
|
+
] })
|
|
38759
|
+
},
|
|
38760
|
+
oid
|
|
38761
|
+
);
|
|
38762
|
+
}) })
|
|
38575
38763
|
] }),
|
|
38576
38764
|
selectedObject && /* @__PURE__ */ jsxRuntime.jsx(
|
|
38577
38765
|
ObjectRulePanel,
|
|
@@ -38582,12 +38770,12 @@ function EventHandlerBoard({
|
|
|
38582
38770
|
}
|
|
38583
38771
|
),
|
|
38584
38772
|
eventLog.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(EventLog, { entries: eventLog }),
|
|
38585
|
-
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("eventHandler.chainComplete") }) }),
|
|
38773
|
+
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("eventHandler.chainComplete") }) }),
|
|
38586
38774
|
playState === "fail" && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
38587
38775
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
|
|
38588
38776
|
showHint && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
38589
38777
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
38590
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
38778
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
38591
38779
|
] }) })
|
|
38592
38780
|
] }),
|
|
38593
38781
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", children: [
|
|
@@ -38615,6 +38803,8 @@ var init_EventHandlerBoard = __esm({
|
|
|
38615
38803
|
init_TraitStateViewer();
|
|
38616
38804
|
init_ObjectRulePanel();
|
|
38617
38805
|
init_EventLog();
|
|
38806
|
+
init_puzzleObject();
|
|
38807
|
+
init_boardEntity();
|
|
38618
38808
|
ENCOURAGEMENT_KEYS = [
|
|
38619
38809
|
"puzzle.tryAgain1",
|
|
38620
38810
|
"puzzle.tryAgain2",
|
|
@@ -38703,7 +38893,10 @@ var init_FeatureGridOrganism = __esm({
|
|
|
38703
38893
|
);
|
|
38704
38894
|
React84.useCallback(
|
|
38705
38895
|
(feature) => {
|
|
38706
|
-
eventBus.emit("UI:FEATURE_CLICK", {
|
|
38896
|
+
eventBus.emit("UI:FEATURE_CLICK", {
|
|
38897
|
+
id: String(feature.id ?? ""),
|
|
38898
|
+
href: String(feature.href ?? "")
|
|
38899
|
+
});
|
|
38707
38900
|
},
|
|
38708
38901
|
[eventBus]
|
|
38709
38902
|
);
|
|
@@ -38713,14 +38906,17 @@ var init_FeatureGridOrganism = __esm({
|
|
|
38713
38906
|
if (error) {
|
|
38714
38907
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
38715
38908
|
}
|
|
38716
|
-
const featureCards = items.map((feature) =>
|
|
38717
|
-
|
|
38718
|
-
|
|
38719
|
-
|
|
38720
|
-
|
|
38721
|
-
|
|
38722
|
-
|
|
38723
|
-
|
|
38909
|
+
const featureCards = items.map((feature) => {
|
|
38910
|
+
const href = feature.href != null ? String(feature.href) : void 0;
|
|
38911
|
+
return {
|
|
38912
|
+
icon: feature.icon != null ? String(feature.icon) : void 0,
|
|
38913
|
+
title: String(feature.title ?? ""),
|
|
38914
|
+
description: String(feature.description ?? ""),
|
|
38915
|
+
href,
|
|
38916
|
+
linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
|
|
38917
|
+
variant: href ? "interactive" : "bordered"
|
|
38918
|
+
};
|
|
38919
|
+
});
|
|
38724
38920
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
38725
38921
|
(heading || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
38726
38922
|
heading && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
@@ -40038,22 +40234,24 @@ var init_HeroOrganism = __esm({
|
|
|
40038
40234
|
() => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
|
|
40039
40235
|
[entity]
|
|
40040
40236
|
);
|
|
40237
|
+
const primaryAction = resolved?.primaryAction;
|
|
40238
|
+
const secondaryAction = resolved?.secondaryAction;
|
|
40041
40239
|
const handlePrimaryClick = React84.useCallback(() => {
|
|
40042
|
-
if (
|
|
40240
|
+
if (primaryAction) {
|
|
40043
40241
|
eventBus.emit("UI:CTA_PRIMARY", {
|
|
40044
|
-
label:
|
|
40045
|
-
href:
|
|
40242
|
+
label: String(primaryAction.label ?? ""),
|
|
40243
|
+
href: String(primaryAction.href ?? "")
|
|
40046
40244
|
});
|
|
40047
40245
|
}
|
|
40048
|
-
}, [eventBus,
|
|
40246
|
+
}, [eventBus, primaryAction]);
|
|
40049
40247
|
const handleSecondaryClick = React84.useCallback(() => {
|
|
40050
|
-
if (
|
|
40248
|
+
if (secondaryAction) {
|
|
40051
40249
|
eventBus.emit("UI:CTA_SECONDARY", {
|
|
40052
|
-
label:
|
|
40053
|
-
href:
|
|
40250
|
+
label: String(secondaryAction.label ?? ""),
|
|
40251
|
+
href: String(secondaryAction.href ?? "")
|
|
40054
40252
|
});
|
|
40055
40253
|
}
|
|
40056
|
-
}, [eventBus,
|
|
40254
|
+
}, [eventBus, secondaryAction]);
|
|
40057
40255
|
if (isLoading) {
|
|
40058
40256
|
return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: t("common.loading"), className });
|
|
40059
40257
|
}
|
|
@@ -40063,17 +40261,19 @@ var init_HeroOrganism = __esm({
|
|
|
40063
40261
|
if (!resolved) {
|
|
40064
40262
|
return null;
|
|
40065
40263
|
}
|
|
40264
|
+
const imageRaw = resolved.image;
|
|
40265
|
+
const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
|
|
40066
40266
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
40067
40267
|
HeroSection,
|
|
40068
40268
|
{
|
|
40069
|
-
tag: resolved.tag,
|
|
40070
|
-
title: resolved.title,
|
|
40071
|
-
titleAccent: resolved.titleAccent,
|
|
40072
|
-
subtitle: resolved.subtitle,
|
|
40073
|
-
primaryAction:
|
|
40074
|
-
secondaryAction:
|
|
40075
|
-
installCommand: resolved.installCommand,
|
|
40076
|
-
image
|
|
40269
|
+
tag: resolved.tag != null ? String(resolved.tag) : void 0,
|
|
40270
|
+
title: String(resolved.title ?? ""),
|
|
40271
|
+
titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
|
|
40272
|
+
subtitle: String(resolved.subtitle ?? ""),
|
|
40273
|
+
primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
|
|
40274
|
+
secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
|
|
40275
|
+
installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
|
|
40276
|
+
image,
|
|
40077
40277
|
imagePosition: resolved.imagePosition,
|
|
40078
40278
|
background: resolved.background,
|
|
40079
40279
|
className: cn(className),
|
|
@@ -40082,8 +40282,8 @@ var init_HeroOrganism = __esm({
|
|
|
40082
40282
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
40083
40283
|
_HeroClickInterceptor,
|
|
40084
40284
|
{
|
|
40085
|
-
hasPrimary: !!
|
|
40086
|
-
hasSecondary: !!
|
|
40285
|
+
hasPrimary: !!primaryAction,
|
|
40286
|
+
hasSecondary: !!secondaryAction,
|
|
40087
40287
|
onPrimaryClick: handlePrimaryClick,
|
|
40088
40288
|
onSecondaryClick: handleSecondaryClick
|
|
40089
40289
|
}
|
|
@@ -40312,7 +40512,7 @@ function formatValue3(value, fieldName) {
|
|
|
40312
40512
|
return String(value);
|
|
40313
40513
|
}
|
|
40314
40514
|
function formatFieldLabel2(fieldName) {
|
|
40315
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
40515
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
|
|
40316
40516
|
}
|
|
40317
40517
|
var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
|
|
40318
40518
|
var init_List = __esm({
|
|
@@ -41159,20 +41359,22 @@ function NegotiatorBoard({
|
|
|
41159
41359
|
}) {
|
|
41160
41360
|
const { emit } = useEventBus();
|
|
41161
41361
|
const { t } = hooks.useTranslate();
|
|
41162
|
-
const resolved =
|
|
41362
|
+
const resolved = boardEntity(entity);
|
|
41163
41363
|
const [history, setHistory] = React84.useState([]);
|
|
41164
41364
|
const [headerError, setHeaderError] = React84.useState(false);
|
|
41165
41365
|
const [showHint, setShowHint] = React84.useState(false);
|
|
41366
|
+
const totalRounds = num(resolved?.totalRounds);
|
|
41367
|
+
const targetScore = num(resolved?.targetScore);
|
|
41166
41368
|
const currentRound = history.length;
|
|
41167
|
-
const isComplete = currentRound >=
|
|
41369
|
+
const isComplete = currentRound >= totalRounds;
|
|
41168
41370
|
const playerTotal = history.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41169
41371
|
const opponentTotal = history.reduce((s, r) => s + r.opponentPayoff, 0);
|
|
41170
|
-
const won = isComplete && playerTotal >=
|
|
41171
|
-
const actions = resolved?.actions
|
|
41172
|
-
const payoffMatrix = resolved?.payoffMatrix
|
|
41372
|
+
const won = isComplete && playerTotal >= targetScore;
|
|
41373
|
+
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
41374
|
+
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
41173
41375
|
const handleAction = React84.useCallback((actionId) => {
|
|
41174
41376
|
if (isComplete) return;
|
|
41175
|
-
const opponentAction = getOpponentAction(resolved?.opponentStrategy
|
|
41377
|
+
const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
|
|
41176
41378
|
const payoff = payoffMatrix.find(
|
|
41177
41379
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
41178
41380
|
);
|
|
@@ -41185,42 +41387,46 @@ function NegotiatorBoard({
|
|
|
41185
41387
|
};
|
|
41186
41388
|
const newHistory = [...history, result];
|
|
41187
41389
|
setHistory(newHistory);
|
|
41188
|
-
if (newHistory.length >=
|
|
41390
|
+
if (newHistory.length >= totalRounds) {
|
|
41189
41391
|
const total = newHistory.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41190
|
-
if (total >=
|
|
41392
|
+
if (total >= targetScore) {
|
|
41191
41393
|
emit(`UI:${completeEvent}`, { success: true, score: total });
|
|
41192
41394
|
}
|
|
41193
|
-
if (newHistory.length >= 3 && resolved?.hint) {
|
|
41395
|
+
if (newHistory.length >= 3 && str(resolved?.hint)) {
|
|
41194
41396
|
setShowHint(true);
|
|
41195
41397
|
}
|
|
41196
41398
|
}
|
|
41197
|
-
}, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41399
|
+
}, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41198
41400
|
const handleReset = () => {
|
|
41199
41401
|
setHistory([]);
|
|
41200
41402
|
setShowHint(false);
|
|
41201
41403
|
};
|
|
41202
41404
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
41203
41405
|
if (!resolved) return null;
|
|
41406
|
+
const theme = resolved.theme ?? void 0;
|
|
41407
|
+
const themeBackground = theme?.background;
|
|
41408
|
+
const headerImage = str(resolved.headerImage);
|
|
41409
|
+
const hint = str(resolved.hint);
|
|
41204
41410
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
41205
41411
|
Box,
|
|
41206
41412
|
{
|
|
41207
41413
|
className,
|
|
41208
41414
|
style: {
|
|
41209
|
-
backgroundImage:
|
|
41415
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
41210
41416
|
backgroundSize: "cover",
|
|
41211
41417
|
backgroundPosition: "center"
|
|
41212
41418
|
},
|
|
41213
41419
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
41214
|
-
|
|
41420
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
41215
41421
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
41216
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
41217
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description }),
|
|
41422
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
41423
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
41218
41424
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", children: [
|
|
41219
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(
|
|
41425
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
|
|
41220
41426
|
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", children: [
|
|
41221
41427
|
t("negotiator.target"),
|
|
41222
41428
|
": ",
|
|
41223
|
-
|
|
41429
|
+
targetScore
|
|
41224
41430
|
] })
|
|
41225
41431
|
] })
|
|
41226
41432
|
] }) }),
|
|
@@ -41269,16 +41475,16 @@ function NegotiatorBoard({
|
|
|
41269
41475
|
] }) }),
|
|
41270
41476
|
isComplete && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
41271
41477
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
|
|
41272
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage
|
|
41478
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
|
|
41273
41479
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
41274
41480
|
t("negotiator.finalScore"),
|
|
41275
41481
|
": ",
|
|
41276
41482
|
playerTotal,
|
|
41277
41483
|
"/",
|
|
41278
|
-
|
|
41484
|
+
targetScore
|
|
41279
41485
|
] })
|
|
41280
41486
|
] }) }),
|
|
41281
|
-
showHint &&
|
|
41487
|
+
showHint && hint && !won && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
41282
41488
|
isComplete && !won && /* @__PURE__ */ jsxRuntime.jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
41283
41489
|
] })
|
|
41284
41490
|
}
|
|
@@ -41288,6 +41494,7 @@ var init_NegotiatorBoard = __esm({
|
|
|
41288
41494
|
"components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
|
|
41289
41495
|
init_atoms2();
|
|
41290
41496
|
init_useEventBus();
|
|
41497
|
+
init_boardEntity();
|
|
41291
41498
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
41292
41499
|
}
|
|
41293
41500
|
});
|
|
@@ -41323,13 +41530,13 @@ var init_PricingOrganism = __esm({
|
|
|
41323
41530
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
41324
41531
|
}
|
|
41325
41532
|
const plans = items.map((plan) => ({
|
|
41326
|
-
name: plan.name,
|
|
41327
|
-
price: plan.price,
|
|
41328
|
-
description: plan.description,
|
|
41329
|
-
features: plan.features,
|
|
41330
|
-
action: { label: plan.actionLabel, href: plan.actionHref },
|
|
41331
|
-
highlighted: plan.highlighted,
|
|
41332
|
-
badge: plan.badge
|
|
41533
|
+
name: String(plan.name ?? ""),
|
|
41534
|
+
price: String(plan.price ?? ""),
|
|
41535
|
+
description: plan.description != null ? String(plan.description) : void 0,
|
|
41536
|
+
features: (plan.features ?? []).map((f3) => String(f3)),
|
|
41537
|
+
action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
|
|
41538
|
+
highlighted: Boolean(plan.highlighted),
|
|
41539
|
+
badge: plan.badge != null ? String(plan.badge) : void 0
|
|
41333
41540
|
}));
|
|
41334
41541
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
41335
41542
|
(heading || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -43419,16 +43626,20 @@ function SequencerBoard({
|
|
|
43419
43626
|
}) {
|
|
43420
43627
|
const { emit } = useEventBus();
|
|
43421
43628
|
const { t } = hooks.useTranslate();
|
|
43422
|
-
const resolved =
|
|
43629
|
+
const resolved = boardEntity(entity);
|
|
43630
|
+
const maxSlots = num(resolved?.maxSlots);
|
|
43631
|
+
const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
|
|
43632
|
+
const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
|
|
43633
|
+
const allowDuplicates = resolved?.allowDuplicates !== false;
|
|
43423
43634
|
const [headerError, setHeaderError] = React84.useState(false);
|
|
43424
43635
|
const [slots, setSlots] = React84.useState(
|
|
43425
|
-
() => Array.from({ length:
|
|
43636
|
+
() => Array.from({ length: maxSlots }, () => void 0)
|
|
43426
43637
|
);
|
|
43427
43638
|
const [playState, setPlayState] = React84.useState("idle");
|
|
43428
43639
|
const [currentStep, setCurrentStep] = React84.useState(-1);
|
|
43429
43640
|
const [attempts, setAttempts] = React84.useState(0);
|
|
43430
43641
|
const [slotFeedback, setSlotFeedback] = React84.useState(
|
|
43431
|
-
() => Array.from({ length:
|
|
43642
|
+
() => Array.from({ length: maxSlots }, () => null)
|
|
43432
43643
|
);
|
|
43433
43644
|
const timerRef = React84.useRef(null);
|
|
43434
43645
|
React84.useEffect(() => () => {
|
|
@@ -43462,17 +43673,17 @@ function SequencerBoard({
|
|
|
43462
43673
|
}, [emit]);
|
|
43463
43674
|
const handleReset = React84.useCallback(() => {
|
|
43464
43675
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
43465
|
-
setSlots(Array.from({ length:
|
|
43676
|
+
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
43466
43677
|
setPlayState("idle");
|
|
43467
43678
|
setCurrentStep(-1);
|
|
43468
43679
|
setAttempts(0);
|
|
43469
|
-
setSlotFeedback(Array.from({ length:
|
|
43470
|
-
}, [
|
|
43680
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
43681
|
+
}, [maxSlots]);
|
|
43471
43682
|
const filledSlots = slots.filter((s) => !!s);
|
|
43472
43683
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
43473
43684
|
const handlePlay = React84.useCallback(() => {
|
|
43474
43685
|
if (!canPlay) return;
|
|
43475
|
-
setSlotFeedback(Array.from({ length:
|
|
43686
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
43476
43687
|
emit("UI:PLAY_SOUND", { key: "confirm" });
|
|
43477
43688
|
const sequence = slots.map((s) => s?.id || "");
|
|
43478
43689
|
if (playEvent) {
|
|
@@ -43483,10 +43694,10 @@ function SequencerBoard({
|
|
|
43483
43694
|
let step = 0;
|
|
43484
43695
|
const advance = () => {
|
|
43485
43696
|
step++;
|
|
43486
|
-
if (step >=
|
|
43697
|
+
if (step >= maxSlots) {
|
|
43487
43698
|
const playerSeq = slots.map((s) => s?.id);
|
|
43488
43699
|
const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
|
|
43489
|
-
const success =
|
|
43700
|
+
const success = solutions.some(
|
|
43490
43701
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
43491
43702
|
);
|
|
43492
43703
|
if (success) {
|
|
@@ -43498,7 +43709,7 @@ function SequencerBoard({
|
|
|
43498
43709
|
}
|
|
43499
43710
|
} else {
|
|
43500
43711
|
setAttempts((prev) => prev + 1);
|
|
43501
|
-
const feedback = computeSlotFeedback(playerSeq,
|
|
43712
|
+
const feedback = computeSlotFeedback(playerSeq, solutions);
|
|
43502
43713
|
setSlotFeedback(feedback);
|
|
43503
43714
|
setPlayState("idle");
|
|
43504
43715
|
setCurrentStep(-1);
|
|
@@ -43516,10 +43727,10 @@ function SequencerBoard({
|
|
|
43516
43727
|
}
|
|
43517
43728
|
};
|
|
43518
43729
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
43519
|
-
}, [canPlay, slots,
|
|
43730
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
43520
43731
|
const machine = {
|
|
43521
|
-
name: resolved?.title
|
|
43522
|
-
description: resolved?.description
|
|
43732
|
+
name: str(resolved?.title),
|
|
43733
|
+
description: str(resolved?.description),
|
|
43523
43734
|
states: slots.map((s, i) => stepLabel(s, i)),
|
|
43524
43735
|
currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
|
|
43525
43736
|
transitions: slots.slice(0, -1).map((s, i) => ({
|
|
@@ -43528,37 +43739,41 @@ function SequencerBoard({
|
|
|
43528
43739
|
event: "NEXT"
|
|
43529
43740
|
}))
|
|
43530
43741
|
};
|
|
43531
|
-
const usedIds =
|
|
43532
|
-
const
|
|
43742
|
+
const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
|
|
43743
|
+
const hint = str(resolved?.hint);
|
|
43744
|
+
const showHint = attempts >= 3 && !!hint;
|
|
43533
43745
|
const hasFeedback = slotFeedback.some((f3) => f3 !== null);
|
|
43534
43746
|
const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
|
|
43535
43747
|
const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
|
|
43536
43748
|
if (!resolved) return null;
|
|
43749
|
+
const theme = resolved.theme ?? void 0;
|
|
43750
|
+
const themeBackground = theme?.background;
|
|
43751
|
+
const headerImage = str(resolved.headerImage);
|
|
43537
43752
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
43538
43753
|
VStack,
|
|
43539
43754
|
{
|
|
43540
43755
|
className: cn("p-4 gap-6", className),
|
|
43541
43756
|
style: {
|
|
43542
|
-
backgroundImage:
|
|
43757
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
43543
43758
|
backgroundSize: "cover",
|
|
43544
43759
|
backgroundPosition: "center"
|
|
43545
43760
|
},
|
|
43546
43761
|
children: [
|
|
43547
|
-
|
|
43762
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
43548
43763
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
43549
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
43550
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
|
|
43764
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
43765
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
|
|
43551
43766
|
] }),
|
|
43552
43767
|
showHint && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
43553
43768
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
43554
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
43769
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
43555
43770
|
] }) }),
|
|
43556
43771
|
filledSlots.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
43557
43772
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
43558
43773
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center justify-between", children: [
|
|
43559
43774
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
43560
43775
|
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
43561
|
-
`${correctCount}/${
|
|
43776
|
+
`${correctCount}/${maxSlots} `,
|
|
43562
43777
|
"\u2705"
|
|
43563
43778
|
] })
|
|
43564
43779
|
] }),
|
|
@@ -43566,7 +43781,7 @@ function SequencerBoard({
|
|
|
43566
43781
|
SequenceBar,
|
|
43567
43782
|
{
|
|
43568
43783
|
slots,
|
|
43569
|
-
maxSlots
|
|
43784
|
+
maxSlots,
|
|
43570
43785
|
onSlotDrop: handleSlotDrop,
|
|
43571
43786
|
onSlotRemove: handleSlotRemove,
|
|
43572
43787
|
playing: playState === "playing",
|
|
@@ -43580,15 +43795,15 @@ function SequencerBoard({
|
|
|
43580
43795
|
playState !== "playing" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
43581
43796
|
ActionPalette,
|
|
43582
43797
|
{
|
|
43583
|
-
actions:
|
|
43798
|
+
actions: availableActions,
|
|
43584
43799
|
usedActionIds: usedIds,
|
|
43585
|
-
allowDuplicates
|
|
43800
|
+
allowDuplicates,
|
|
43586
43801
|
categoryColors,
|
|
43587
43802
|
label: t("sequencer.dragActions")
|
|
43588
43803
|
}
|
|
43589
43804
|
),
|
|
43590
43805
|
hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
|
|
43591
|
-
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("sequencer.levelComplete") }) }),
|
|
43806
|
+
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("sequencer.levelComplete") }) }),
|
|
43592
43807
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", children: [
|
|
43593
43808
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
43594
43809
|
Button,
|
|
@@ -43612,6 +43827,7 @@ var init_SequencerBoard = __esm({
|
|
|
43612
43827
|
init_cn();
|
|
43613
43828
|
init_useEventBus();
|
|
43614
43829
|
init_TraitStateViewer();
|
|
43830
|
+
init_boardEntity();
|
|
43615
43831
|
init_SequenceBar();
|
|
43616
43832
|
init_ActionPalette();
|
|
43617
43833
|
ENCOURAGEMENT_KEYS2 = [
|
|
@@ -43661,18 +43877,21 @@ var init_ShowcaseOrganism = __esm({
|
|
|
43661
43877
|
heading && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
43662
43878
|
subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
|
|
43663
43879
|
] }),
|
|
43664
|
-
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) =>
|
|
43665
|
-
|
|
43666
|
-
|
|
43667
|
-
|
|
43668
|
-
|
|
43669
|
-
|
|
43670
|
-
|
|
43671
|
-
|
|
43672
|
-
|
|
43673
|
-
|
|
43674
|
-
|
|
43675
|
-
|
|
43880
|
+
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
|
|
43881
|
+
const imageRaw = item.image;
|
|
43882
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
43883
|
+
ShowcaseCard,
|
|
43884
|
+
{
|
|
43885
|
+
title: String(item.title ?? ""),
|
|
43886
|
+
description: item.description != null ? String(item.description) : void 0,
|
|
43887
|
+
image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
|
|
43888
|
+
href: item.href != null ? String(item.href) : void 0,
|
|
43889
|
+
badge: item.badge != null ? String(item.badge) : void 0,
|
|
43890
|
+
accentColor: item.accentColor != null ? String(item.accentColor) : void 0
|
|
43891
|
+
},
|
|
43892
|
+
String(item.id ?? "")
|
|
43893
|
+
);
|
|
43894
|
+
}) })
|
|
43676
43895
|
] });
|
|
43677
43896
|
};
|
|
43678
43897
|
ShowcaseOrganism.displayName = "ShowcaseOrganism";
|
|
@@ -44040,8 +44259,8 @@ function SimulatorBoard({
|
|
|
44040
44259
|
}) {
|
|
44041
44260
|
const { emit } = useEventBus();
|
|
44042
44261
|
const { t } = hooks.useTranslate();
|
|
44043
|
-
const resolved =
|
|
44044
|
-
const parameters = resolved?.parameters
|
|
44262
|
+
const resolved = boardEntity(entity);
|
|
44263
|
+
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
44045
44264
|
const [values, setValues] = React84.useState(() => {
|
|
44046
44265
|
const init = {};
|
|
44047
44266
|
for (const p2 of parameters) {
|
|
@@ -44055,15 +44274,15 @@ function SimulatorBoard({
|
|
|
44055
44274
|
const [showHint, setShowHint] = React84.useState(false);
|
|
44056
44275
|
const computeOutput = React84.useCallback((params) => {
|
|
44057
44276
|
try {
|
|
44058
|
-
const fn = new Function("params", `return (${resolved?.computeExpression})`);
|
|
44277
|
+
const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
|
|
44059
44278
|
return fn(params);
|
|
44060
44279
|
} catch {
|
|
44061
44280
|
return 0;
|
|
44062
44281
|
}
|
|
44063
44282
|
}, [resolved?.computeExpression]);
|
|
44064
44283
|
const output = React84.useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
|
|
44065
|
-
const targetValue = resolved?.targetValue
|
|
44066
|
-
const targetTolerance = resolved?.targetTolerance
|
|
44284
|
+
const targetValue = num(resolved?.targetValue);
|
|
44285
|
+
const targetTolerance = num(resolved?.targetTolerance);
|
|
44067
44286
|
const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
|
|
44068
44287
|
const handleParameterChange = (id, value) => {
|
|
44069
44288
|
if (submitted) return;
|
|
@@ -44078,7 +44297,7 @@ function SimulatorBoard({
|
|
|
44078
44297
|
};
|
|
44079
44298
|
const handleReset = () => {
|
|
44080
44299
|
setSubmitted(false);
|
|
44081
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
44300
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
44082
44301
|
setShowHint(true);
|
|
44083
44302
|
}
|
|
44084
44303
|
};
|
|
@@ -44093,20 +44312,26 @@ function SimulatorBoard({
|
|
|
44093
44312
|
setShowHint(false);
|
|
44094
44313
|
};
|
|
44095
44314
|
if (!resolved) return null;
|
|
44315
|
+
const theme = resolved.theme ?? void 0;
|
|
44316
|
+
const themeBackground = theme?.background;
|
|
44317
|
+
const headerImage = str(resolved.headerImage);
|
|
44318
|
+
const hint = str(resolved.hint);
|
|
44319
|
+
const outputLabel = str(resolved.outputLabel);
|
|
44320
|
+
const outputUnit = str(resolved.outputUnit);
|
|
44096
44321
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
44097
44322
|
Box,
|
|
44098
44323
|
{
|
|
44099
44324
|
className,
|
|
44100
44325
|
style: {
|
|
44101
|
-
backgroundImage:
|
|
44326
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44102
44327
|
backgroundSize: "cover",
|
|
44103
44328
|
backgroundPosition: "center"
|
|
44104
44329
|
},
|
|
44105
44330
|
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
44106
|
-
|
|
44331
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44107
44332
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
44108
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
44109
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: resolved.description })
|
|
44333
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
44334
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
44110
44335
|
] }) }),
|
|
44111
44336
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", children: [
|
|
44112
44337
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
@@ -44147,28 +44372,28 @@ function SimulatorBoard({
|
|
|
44147
44372
|
] }, param.id))
|
|
44148
44373
|
] }) }),
|
|
44149
44374
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
44150
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children:
|
|
44375
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
44151
44376
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
44152
44377
|
output.toFixed(2),
|
|
44153
44378
|
" ",
|
|
44154
|
-
|
|
44379
|
+
outputUnit
|
|
44155
44380
|
] }),
|
|
44156
44381
|
submitted && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
44157
44382
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: isCorrect ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
|
|
44158
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage
|
|
44383
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
44159
44384
|
] }),
|
|
44160
44385
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
44161
44386
|
t("simulator.target"),
|
|
44162
44387
|
": ",
|
|
44163
44388
|
targetValue,
|
|
44164
44389
|
" ",
|
|
44165
|
-
|
|
44390
|
+
outputUnit,
|
|
44166
44391
|
" (\xB1",
|
|
44167
44392
|
targetTolerance,
|
|
44168
44393
|
")"
|
|
44169
44394
|
] })
|
|
44170
44395
|
] }) }),
|
|
44171
|
-
showHint &&
|
|
44396
|
+
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
44172
44397
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
44173
44398
|
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
44174
44399
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Play, size: "sm" }),
|
|
@@ -44187,6 +44412,7 @@ var init_SimulatorBoard = __esm({
|
|
|
44187
44412
|
"components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
|
|
44188
44413
|
init_atoms2();
|
|
44189
44414
|
init_useEventBus();
|
|
44415
|
+
init_boardEntity();
|
|
44190
44416
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
44191
44417
|
}
|
|
44192
44418
|
});
|
|
@@ -44612,22 +44838,25 @@ function VariablePanel({
|
|
|
44612
44838
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
44613
44839
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
|
|
44614
44840
|
variables.map((v) => {
|
|
44615
|
-
const
|
|
44616
|
-
const
|
|
44617
|
-
const
|
|
44841
|
+
const name = v.name == null ? "" : String(v.name);
|
|
44842
|
+
const value = numField(v.value);
|
|
44843
|
+
const max = numField(v.max, 100);
|
|
44844
|
+
const min = numField(v.min, 0);
|
|
44845
|
+
const unit = v.unit == null ? "" : String(v.unit);
|
|
44846
|
+
const pct = Math.round((value - min) / (max - min) * 100);
|
|
44618
44847
|
const isHigh = pct > 80;
|
|
44619
44848
|
const isLow = pct < 20;
|
|
44620
44849
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", children: [
|
|
44621
44850
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center justify-between", children: [
|
|
44622
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children:
|
|
44851
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
|
|
44623
44852
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: cn(
|
|
44624
44853
|
isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
|
|
44625
44854
|
), children: [
|
|
44626
|
-
|
|
44627
|
-
|
|
44855
|
+
value,
|
|
44856
|
+
unit,
|
|
44628
44857
|
" / ",
|
|
44629
44858
|
max,
|
|
44630
|
-
|
|
44859
|
+
unit
|
|
44631
44860
|
] })
|
|
44632
44861
|
] }),
|
|
44633
44862
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -44638,14 +44867,19 @@ function VariablePanel({
|
|
|
44638
44867
|
size: "sm"
|
|
44639
44868
|
}
|
|
44640
44869
|
)
|
|
44641
|
-
] },
|
|
44870
|
+
] }, name);
|
|
44642
44871
|
})
|
|
44643
44872
|
] });
|
|
44644
44873
|
}
|
|
44874
|
+
var numField;
|
|
44645
44875
|
var init_VariablePanel = __esm({
|
|
44646
44876
|
"components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
|
|
44647
44877
|
init_atoms2();
|
|
44648
44878
|
init_cn();
|
|
44879
|
+
numField = (v, fallback = 0) => {
|
|
44880
|
+
const n = Number(v);
|
|
44881
|
+
return Number.isFinite(n) ? n : fallback;
|
|
44882
|
+
};
|
|
44649
44883
|
VariablePanel.displayName = "VariablePanel";
|
|
44650
44884
|
}
|
|
44651
44885
|
});
|
|
@@ -44672,14 +44906,21 @@ function StateArchitectBoard({
|
|
|
44672
44906
|
}) {
|
|
44673
44907
|
const { emit } = useEventBus();
|
|
44674
44908
|
const { t } = hooks.useTranslate();
|
|
44675
|
-
const resolved =
|
|
44676
|
-
const
|
|
44909
|
+
const resolved = boardEntity(entity);
|
|
44910
|
+
const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
|
|
44911
|
+
const initialState = str(resolved?.initialState);
|
|
44912
|
+
const entityName = str(resolved?.entityName);
|
|
44913
|
+
const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
|
|
44914
|
+
const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
|
|
44915
|
+
const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
|
|
44916
|
+
const entityVariables = rows(resolved?.variables);
|
|
44917
|
+
const [transitions, setTransitions] = React84.useState(entityTransitions);
|
|
44677
44918
|
const [headerError, setHeaderError] = React84.useState(false);
|
|
44678
44919
|
const [playState, setPlayState] = React84.useState("editing");
|
|
44679
|
-
const [currentState, setCurrentState] = React84.useState(
|
|
44920
|
+
const [currentState, setCurrentState] = React84.useState(initialState);
|
|
44680
44921
|
const [selectedState, setSelectedState] = React84.useState(null);
|
|
44681
44922
|
const [testResults, setTestResults] = React84.useState([]);
|
|
44682
|
-
const [variables, setVariables] = React84.useState(
|
|
44923
|
+
const [variables, setVariables] = React84.useState(() => [...entityVariables]);
|
|
44683
44924
|
const [attempts, setAttempts] = React84.useState(0);
|
|
44684
44925
|
const timerRef = React84.useRef(null);
|
|
44685
44926
|
const [addingFrom, setAddingFrom] = React84.useState(null);
|
|
@@ -44688,12 +44929,12 @@ function StateArchitectBoard({
|
|
|
44688
44929
|
}, []);
|
|
44689
44930
|
const GRAPH_W = 500;
|
|
44690
44931
|
const GRAPH_H = 400;
|
|
44691
|
-
const positions = React84.useMemo(() => layoutStates(
|
|
44932
|
+
const positions = React84.useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
|
|
44692
44933
|
const handleStateClick = React84.useCallback((state) => {
|
|
44693
44934
|
if (playState !== "editing") return;
|
|
44694
44935
|
if (addingFrom) {
|
|
44695
44936
|
if (addingFrom !== state) {
|
|
44696
|
-
const event =
|
|
44937
|
+
const event = availableEvents[0] || "EVENT";
|
|
44697
44938
|
const newTrans = {
|
|
44698
44939
|
id: `t-${nextTransId++}`,
|
|
44699
44940
|
from: addingFrom,
|
|
@@ -44706,7 +44947,7 @@ function StateArchitectBoard({
|
|
|
44706
44947
|
} else {
|
|
44707
44948
|
setSelectedState(state);
|
|
44708
44949
|
}
|
|
44709
|
-
}, [playState, addingFrom,
|
|
44950
|
+
}, [playState, addingFrom, availableEvents]);
|
|
44710
44951
|
const handleStartAddTransition = React84.useCallback(() => {
|
|
44711
44952
|
if (!selectedState) return;
|
|
44712
44953
|
setAddingFrom(selectedState);
|
|
@@ -44715,9 +44956,9 @@ function StateArchitectBoard({
|
|
|
44715
44956
|
setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
|
|
44716
44957
|
}, []);
|
|
44717
44958
|
const machine = React84.useMemo(() => ({
|
|
44718
|
-
name:
|
|
44719
|
-
description: resolved?.description
|
|
44720
|
-
states:
|
|
44959
|
+
name: entityName,
|
|
44960
|
+
description: str(resolved?.description),
|
|
44961
|
+
states: entityStates,
|
|
44721
44962
|
currentState,
|
|
44722
44963
|
transitions: transitions.map((t2) => ({
|
|
44723
44964
|
from: t2.from,
|
|
@@ -44725,7 +44966,7 @@ function StateArchitectBoard({
|
|
|
44725
44966
|
event: t2.event,
|
|
44726
44967
|
guardHint: t2.guardHint
|
|
44727
44968
|
}))
|
|
44728
|
-
}), [resolved, currentState, transitions]);
|
|
44969
|
+
}), [entityName, resolved, entityStates, currentState, transitions]);
|
|
44729
44970
|
const handleTest = React84.useCallback(() => {
|
|
44730
44971
|
if (playState !== "editing") return;
|
|
44731
44972
|
if (testEvent) emit(`UI:${testEvent}`, {});
|
|
@@ -44734,7 +44975,7 @@ function StateArchitectBoard({
|
|
|
44734
44975
|
const results = [];
|
|
44735
44976
|
let testIdx = 0;
|
|
44736
44977
|
const runNextTest = () => {
|
|
44737
|
-
if (testIdx >=
|
|
44978
|
+
if (testIdx >= testCases.length) {
|
|
44738
44979
|
const allPassed = results.every((r) => r.passed);
|
|
44739
44980
|
setPlayState(allPassed ? "success" : "fail");
|
|
44740
44981
|
setTestResults(results);
|
|
@@ -44749,9 +44990,9 @@ function StateArchitectBoard({
|
|
|
44749
44990
|
}
|
|
44750
44991
|
return;
|
|
44751
44992
|
}
|
|
44752
|
-
const testCase =
|
|
44993
|
+
const testCase = testCases[testIdx];
|
|
44753
44994
|
if (!testCase) return;
|
|
44754
|
-
let state =
|
|
44995
|
+
let state = initialState;
|
|
44755
44996
|
for (const event of testCase.events) {
|
|
44756
44997
|
const trans = transitions.find((t2) => t2.from === state && t2.event === event);
|
|
44757
44998
|
if (trans) {
|
|
@@ -44769,53 +45010,57 @@ function StateArchitectBoard({
|
|
|
44769
45010
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
44770
45011
|
};
|
|
44771
45012
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
44772
|
-
}, [playState, transitions,
|
|
45013
|
+
}, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
|
|
44773
45014
|
const handleTryAgain = React84.useCallback(() => {
|
|
44774
45015
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44775
45016
|
setPlayState("editing");
|
|
44776
|
-
setCurrentState(
|
|
45017
|
+
setCurrentState(initialState);
|
|
44777
45018
|
setTestResults([]);
|
|
44778
|
-
}, [
|
|
45019
|
+
}, [initialState]);
|
|
44779
45020
|
const handleReset = React84.useCallback(() => {
|
|
44780
45021
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44781
|
-
setTransitions(
|
|
45022
|
+
setTransitions(entityTransitions);
|
|
44782
45023
|
setPlayState("editing");
|
|
44783
|
-
setCurrentState(
|
|
45024
|
+
setCurrentState(initialState);
|
|
44784
45025
|
setTestResults([]);
|
|
44785
|
-
setVariables(
|
|
45026
|
+
setVariables([...entityVariables]);
|
|
44786
45027
|
setSelectedState(null);
|
|
44787
45028
|
setAddingFrom(null);
|
|
44788
45029
|
setAttempts(0);
|
|
44789
|
-
}, [
|
|
45030
|
+
}, [entityTransitions, initialState, entityVariables]);
|
|
44790
45031
|
const codeData = React84.useMemo(() => ({
|
|
44791
|
-
name:
|
|
44792
|
-
states:
|
|
44793
|
-
initialState
|
|
45032
|
+
name: entityName,
|
|
45033
|
+
states: entityStates,
|
|
45034
|
+
initialState,
|
|
44794
45035
|
transitions: transitions.map((t2) => ({
|
|
44795
45036
|
from: t2.from,
|
|
44796
45037
|
to: t2.to,
|
|
44797
45038
|
event: t2.event,
|
|
44798
45039
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
44799
45040
|
}))
|
|
44800
|
-
}), [
|
|
45041
|
+
}), [entityName, entityStates, initialState, transitions]);
|
|
44801
45042
|
if (!resolved) return null;
|
|
45043
|
+
const theme = resolved.theme ?? void 0;
|
|
45044
|
+
const themeBackground = theme?.background;
|
|
45045
|
+
const headerImage = str(resolved.headerImage);
|
|
45046
|
+
const hint = str(resolved.hint);
|
|
44802
45047
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
44803
45048
|
VStack,
|
|
44804
45049
|
{
|
|
44805
45050
|
className: cn("p-4 gap-6", className),
|
|
44806
45051
|
style: {
|
|
44807
|
-
backgroundImage:
|
|
45052
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44808
45053
|
backgroundSize: "cover",
|
|
44809
45054
|
backgroundPosition: "center"
|
|
44810
45055
|
},
|
|
44811
45056
|
children: [
|
|
44812
|
-
|
|
45057
|
+
headerImage && !headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44813
45058
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
44814
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
44815
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
45059
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
45060
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
44816
45061
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
44817
45062
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
44818
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children:
|
|
45063
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
|
|
44819
45064
|
] })
|
|
44820
45065
|
] }),
|
|
44821
45066
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
@@ -44863,14 +45108,14 @@ function StateArchitectBoard({
|
|
|
44863
45108
|
]
|
|
44864
45109
|
}
|
|
44865
45110
|
),
|
|
44866
|
-
|
|
45111
|
+
entityStates.map((state) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
44867
45112
|
StateNode2,
|
|
44868
45113
|
{
|
|
44869
45114
|
name: state,
|
|
44870
45115
|
position: positions[state],
|
|
44871
45116
|
isCurrent: state === currentState,
|
|
44872
45117
|
isSelected: state === selectedState,
|
|
44873
|
-
isInitial: state ===
|
|
45118
|
+
isInitial: state === initialState,
|
|
44874
45119
|
onClick: () => handleStateClick(state)
|
|
44875
45120
|
},
|
|
44876
45121
|
state
|
|
@@ -44917,7 +45162,7 @@ function StateArchitectBoard({
|
|
|
44917
45162
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
44918
45163
|
VariablePanel,
|
|
44919
45164
|
{
|
|
44920
|
-
entityName
|
|
45165
|
+
entityName,
|
|
44921
45166
|
variables
|
|
44922
45167
|
}
|
|
44923
45168
|
),
|
|
@@ -44932,12 +45177,12 @@ function StateArchitectBoard({
|
|
|
44932
45177
|
resolved.showCodeView !== false && /* @__PURE__ */ jsxRuntime.jsx(CodeView, { data: codeData, label: "View Code" })
|
|
44933
45178
|
] })
|
|
44934
45179
|
] }),
|
|
44935
|
-
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("stateArchitect.allPassed") }) }),
|
|
45180
|
+
playState === "success" && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
|
|
44936
45181
|
playState === "fail" && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", children: [
|
|
44937
45182
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(ENCOURAGEMENT_KEYS3[Math.min(attempts - 1, ENCOURAGEMENT_KEYS3.length - 1)] ?? ENCOURAGEMENT_KEYS3[0]) }) }),
|
|
44938
|
-
attempts >= 3 &&
|
|
45183
|
+
attempts >= 3 && hint && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
44939
45184
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
44940
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
45185
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
44941
45186
|
] }) })
|
|
44942
45187
|
] }),
|
|
44943
45188
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", children: [
|
|
@@ -44967,6 +45212,7 @@ var init_StateArchitectBoard = __esm({
|
|
|
44967
45212
|
init_TransitionArrow();
|
|
44968
45213
|
init_VariablePanel();
|
|
44969
45214
|
init_CodeView();
|
|
45215
|
+
init_boardEntity();
|
|
44970
45216
|
ENCOURAGEMENT_KEYS3 = [
|
|
44971
45217
|
"puzzle.tryAgain1",
|
|
44972
45218
|
"puzzle.tryAgain2",
|
|
@@ -45003,8 +45249,8 @@ var init_StatsOrganism = __esm({
|
|
|
45003
45249
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
45004
45250
|
}
|
|
45005
45251
|
const stats = items.map((item) => ({
|
|
45006
|
-
value: item.value,
|
|
45007
|
-
label: item.label
|
|
45252
|
+
value: String(item.value ?? ""),
|
|
45253
|
+
label: String(item.label ?? "")
|
|
45008
45254
|
}));
|
|
45009
45255
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
45010
45256
|
StatsGrid,
|
|
@@ -45050,10 +45296,10 @@ var init_StepFlowOrganism = __esm({
|
|
|
45050
45296
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { message: error.message, className });
|
|
45051
45297
|
}
|
|
45052
45298
|
const steps = items.map((item) => ({
|
|
45053
|
-
number: item.number,
|
|
45054
|
-
title: item.title,
|
|
45055
|
-
description: item.description,
|
|
45056
|
-
icon: item.icon
|
|
45299
|
+
number: item.number != null ? Number(item.number) : void 0,
|
|
45300
|
+
title: String(item.title ?? ""),
|
|
45301
|
+
description: String(item.description ?? ""),
|
|
45302
|
+
icon: item.icon != null ? String(item.icon) : void 0
|
|
45057
45303
|
}));
|
|
45058
45304
|
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
45059
45305
|
(heading || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -45226,13 +45472,13 @@ var init_TeamOrganism = __esm({
|
|
|
45226
45472
|
/* @__PURE__ */ jsxRuntime.jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
45227
45473
|
TeamCard,
|
|
45228
45474
|
{
|
|
45229
|
-
name: member.name,
|
|
45230
|
-
nameAr: member.nameAr,
|
|
45231
|
-
role: member.role,
|
|
45232
|
-
bio: member.bio,
|
|
45233
|
-
avatar: member.avatar
|
|
45475
|
+
name: String(member.name ?? ""),
|
|
45476
|
+
nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
|
|
45477
|
+
role: String(member.role ?? ""),
|
|
45478
|
+
bio: String(member.bio ?? ""),
|
|
45479
|
+
avatar: member.avatar != null ? String(member.avatar) : void 0
|
|
45234
45480
|
},
|
|
45235
|
-
member.id
|
|
45481
|
+
String(member.id ?? "")
|
|
45236
45482
|
)) })
|
|
45237
45483
|
] });
|
|
45238
45484
|
};
|
|
@@ -45469,8 +45715,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45469
45715
|
const [turn, setTurn] = React84.useState(1);
|
|
45470
45716
|
const [gameResult, setGameResult] = React84.useState(null);
|
|
45471
45717
|
const checkGameEnd = React84.useCallback((currentUnits) => {
|
|
45472
|
-
const pa = currentUnits.filter((u) => u
|
|
45473
|
-
const ea = currentUnits.filter((u) => u
|
|
45718
|
+
const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
45719
|
+
const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
45474
45720
|
if (pa.length === 0) {
|
|
45475
45721
|
setGameResult("defeat");
|
|
45476
45722
|
setPhase("game_over");
|
|
@@ -45488,34 +45734,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45488
45734
|
}
|
|
45489
45735
|
}, [onGameEnd, gameEndEvent, eventBus]);
|
|
45490
45736
|
const handleUnitClick = React84.useCallback((unitId) => {
|
|
45491
|
-
const unit = units.find((u) => u.id === unitId);
|
|
45737
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
45492
45738
|
if (!unit) return;
|
|
45493
45739
|
if (unitClickEvent) {
|
|
45494
45740
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
45495
45741
|
}
|
|
45496
45742
|
if (phase === "observation" || phase === "selection") {
|
|
45497
|
-
if (unit
|
|
45743
|
+
if (unitTeam(unit) === "player") {
|
|
45498
45744
|
setSelectedUnitId(unitId);
|
|
45499
45745
|
setPhase("movement");
|
|
45500
45746
|
}
|
|
45501
45747
|
} else if (phase === "action") {
|
|
45502
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
45748
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45503
45749
|
if (!selectedUnit) return;
|
|
45504
|
-
if (unit
|
|
45505
|
-
const
|
|
45506
|
-
const
|
|
45750
|
+
if (unitTeam(unit) === "enemy") {
|
|
45751
|
+
const up = unitPosition(unit);
|
|
45752
|
+
const sp = unitPosition(selectedUnit);
|
|
45753
|
+
const dx = Math.abs(up.x - sp.x);
|
|
45754
|
+
const dy = Math.abs(up.y - sp.y);
|
|
45507
45755
|
if (dx <= 1 && dy <= 1 && dx + dy > 0) {
|
|
45508
|
-
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
45509
|
-
const newHealth = Math.max(0, unit
|
|
45756
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
45757
|
+
const newHealth = Math.max(0, unitHealth(unit) - damage);
|
|
45510
45758
|
const updatedUnits = units.map(
|
|
45511
|
-
(u) => u.id === unit.id ? { ...u, health: newHealth } : u
|
|
45759
|
+
(u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
|
|
45512
45760
|
);
|
|
45513
45761
|
setUnits(updatedUnits);
|
|
45514
45762
|
onAttack?.(selectedUnit, unit, damage);
|
|
45515
45763
|
if (attackEvent) {
|
|
45516
45764
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
45517
|
-
attackerId: selectedUnit.id,
|
|
45518
|
-
targetId: unit.id,
|
|
45765
|
+
attackerId: str(selectedUnit.id),
|
|
45766
|
+
targetId: str(unit.id),
|
|
45519
45767
|
damage
|
|
45520
45768
|
});
|
|
45521
45769
|
}
|
|
@@ -45532,16 +45780,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45532
45780
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
45533
45781
|
}
|
|
45534
45782
|
if (phase === "movement" && selectedUnitId) {
|
|
45535
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
45783
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45536
45784
|
if (!selectedUnit) return;
|
|
45537
|
-
const
|
|
45538
|
-
const
|
|
45785
|
+
const sp = unitPosition(selectedUnit);
|
|
45786
|
+
const dx = Math.abs(x - sp.x);
|
|
45787
|
+
const dy = Math.abs(y - sp.y);
|
|
45539
45788
|
const dist = dx + dy;
|
|
45540
|
-
if (dist > 0 && dist <= selectedUnit.movement) {
|
|
45541
|
-
if (!units.some((u) =>
|
|
45789
|
+
if (dist > 0 && dist <= num(selectedUnit.movement)) {
|
|
45790
|
+
if (!units.some((u) => {
|
|
45791
|
+
const p2 = unitPosition(u);
|
|
45792
|
+
return p2.x === x && p2.y === y && unitHealth(u) > 0;
|
|
45793
|
+
})) {
|
|
45542
45794
|
setUnits(
|
|
45543
45795
|
(prev) => prev.map(
|
|
45544
|
-
(u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
45796
|
+
(u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
45545
45797
|
)
|
|
45546
45798
|
);
|
|
45547
45799
|
setPhase("action");
|
|
@@ -45584,12 +45836,13 @@ var init_useBattleState = __esm({
|
|
|
45584
45836
|
"components/game/organisms/hooks/useBattleState.ts"() {
|
|
45585
45837
|
"use client";
|
|
45586
45838
|
init_useEventBus();
|
|
45839
|
+
init_boardEntity();
|
|
45587
45840
|
}
|
|
45588
45841
|
});
|
|
45589
45842
|
function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
45590
|
-
const resolved =
|
|
45843
|
+
const resolved = boardEntity(entity);
|
|
45591
45844
|
const battleState = useBattleState(
|
|
45592
|
-
resolved?.initialUnits
|
|
45845
|
+
rows(resolved?.initialUnits),
|
|
45593
45846
|
{
|
|
45594
45847
|
tileClickEvent: rest.tileClickEvent,
|
|
45595
45848
|
unitClickEvent: rest.unitClickEvent,
|
|
@@ -45625,10 +45878,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
|
45625
45878
|
var init_UncontrolledBattleBoard = __esm({
|
|
45626
45879
|
"components/game/organisms/UncontrolledBattleBoard.tsx"() {
|
|
45627
45880
|
init_BattleBoard();
|
|
45881
|
+
init_boardEntity();
|
|
45628
45882
|
init_useBattleState();
|
|
45629
45883
|
UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
|
|
45630
45884
|
}
|
|
45631
45885
|
});
|
|
45886
|
+
function heroPosition(h) {
|
|
45887
|
+
return vec2(h.position);
|
|
45888
|
+
}
|
|
45889
|
+
function heroOwner(h) {
|
|
45890
|
+
return str(h.owner);
|
|
45891
|
+
}
|
|
45892
|
+
function heroMovement(h) {
|
|
45893
|
+
return num(h.movement);
|
|
45894
|
+
}
|
|
45895
|
+
function hexPassable(h) {
|
|
45896
|
+
return h.passable !== false;
|
|
45897
|
+
}
|
|
45632
45898
|
function defaultIsInRange(from, to, range) {
|
|
45633
45899
|
return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
|
|
45634
45900
|
}
|
|
@@ -45659,36 +45925,36 @@ function WorldMapBoard({
|
|
|
45659
45925
|
className
|
|
45660
45926
|
}) {
|
|
45661
45927
|
const eventBus = useEventBus();
|
|
45662
|
-
const resolved =
|
|
45663
|
-
const hexes = resolved?.hexes
|
|
45664
|
-
const heroes = resolved?.heroes
|
|
45665
|
-
const features = resolved?.features
|
|
45666
|
-
const selectedHeroId = resolved?.selectedHeroId;
|
|
45928
|
+
const resolved = boardEntity(entity);
|
|
45929
|
+
const hexes = rows(resolved?.hexes);
|
|
45930
|
+
const heroes = rows(resolved?.heroes);
|
|
45931
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
45932
|
+
const selectedHeroId = resolved?.selectedHeroId ?? null;
|
|
45667
45933
|
const assetManifest = resolved?.assetManifest;
|
|
45668
45934
|
const backgroundImage = resolved?.backgroundImage;
|
|
45669
45935
|
const [hoveredTile, setHoveredTile] = React84.useState(null);
|
|
45670
45936
|
const selectedHero = React84.useMemo(
|
|
45671
|
-
() => heroes.find((h) => h.id === selectedHeroId) ?? null,
|
|
45937
|
+
() => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
|
|
45672
45938
|
[heroes, selectedHeroId]
|
|
45673
45939
|
);
|
|
45674
45940
|
const tiles = React84.useMemo(
|
|
45675
45941
|
() => hexes.map((hex) => ({
|
|
45676
|
-
x: hex.x,
|
|
45677
|
-
y: hex.y,
|
|
45678
|
-
terrain: hex.terrain,
|
|
45679
|
-
terrainSprite: hex.terrainSprite
|
|
45942
|
+
x: num(hex.x),
|
|
45943
|
+
y: num(hex.y),
|
|
45944
|
+
terrain: str(hex.terrain),
|
|
45945
|
+
terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
|
|
45680
45946
|
})),
|
|
45681
45947
|
[hexes]
|
|
45682
45948
|
);
|
|
45683
45949
|
const baseUnits = React84.useMemo(
|
|
45684
45950
|
() => heroes.map((hero) => ({
|
|
45685
|
-
id: hero.id,
|
|
45686
|
-
position: hero
|
|
45687
|
-
name: hero.name,
|
|
45688
|
-
team: hero
|
|
45951
|
+
id: str(hero.id),
|
|
45952
|
+
position: heroPosition(hero),
|
|
45953
|
+
name: str(hero.name),
|
|
45954
|
+
team: heroOwner(hero) === "enemy" ? "enemy" : "player",
|
|
45689
45955
|
health: 100,
|
|
45690
45956
|
maxHealth: 100,
|
|
45691
|
-
sprite: hero.sprite
|
|
45957
|
+
sprite: hero.sprite == null ? void 0 : str(hero.sprite)
|
|
45692
45958
|
})),
|
|
45693
45959
|
[heroes]
|
|
45694
45960
|
);
|
|
@@ -45729,73 +45995,94 @@ function WorldMapBoard({
|
|
|
45729
45995
|
const isoUnits = React84.useMemo(() => {
|
|
45730
45996
|
if (movingPositions.size === 0) return baseUnits;
|
|
45731
45997
|
return baseUnits.map((u) => {
|
|
45732
|
-
const pos = movingPositions.get(u.id);
|
|
45998
|
+
const pos = u.id == null ? void 0 : movingPositions.get(u.id);
|
|
45733
45999
|
return pos ? { ...u, position: pos } : u;
|
|
45734
46000
|
});
|
|
45735
46001
|
}, [baseUnits, movingPositions]);
|
|
45736
46002
|
const validMoves = React84.useMemo(() => {
|
|
45737
|
-
if (!selectedHero || selectedHero
|
|
46003
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
46004
|
+
const sp = heroPosition(selectedHero);
|
|
46005
|
+
const sOwner = heroOwner(selectedHero);
|
|
46006
|
+
const range = heroMovement(selectedHero);
|
|
45738
46007
|
const moves = [];
|
|
45739
46008
|
hexes.forEach((hex) => {
|
|
45740
|
-
|
|
45741
|
-
|
|
45742
|
-
if (!
|
|
45743
|
-
if (
|
|
45744
|
-
|
|
46009
|
+
const hx = num(hex.x);
|
|
46010
|
+
const hy = num(hex.y);
|
|
46011
|
+
if (!hexPassable(hex)) return;
|
|
46012
|
+
if (hx === sp.x && hy === sp.y) return;
|
|
46013
|
+
if (!isInRange(sp, { x: hx, y: hy }, range)) return;
|
|
46014
|
+
if (heroes.some((h) => {
|
|
46015
|
+
const hp = heroPosition(h);
|
|
46016
|
+
return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
|
|
46017
|
+
})) return;
|
|
46018
|
+
moves.push({ x: hx, y: hy });
|
|
45745
46019
|
});
|
|
45746
46020
|
return moves;
|
|
45747
46021
|
}, [selectedHero, hexes, heroes, isInRange]);
|
|
45748
46022
|
const attackTargets = React84.useMemo(() => {
|
|
45749
|
-
if (!selectedHero || selectedHero
|
|
45750
|
-
|
|
46023
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
46024
|
+
const sp = heroPosition(selectedHero);
|
|
46025
|
+
const sOwner = heroOwner(selectedHero);
|
|
46026
|
+
const range = heroMovement(selectedHero);
|
|
46027
|
+
return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
|
|
45751
46028
|
}, [selectedHero, heroes, isInRange]);
|
|
45752
|
-
const maxY = Math.max(...hexes.map((h) => h.y), 0);
|
|
46029
|
+
const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
|
|
45753
46030
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
45754
46031
|
const tileToScreen = React84.useCallback(
|
|
45755
46032
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
45756
46033
|
[scale, baseOffsetX]
|
|
45757
46034
|
);
|
|
45758
46035
|
const hoveredHex = React84.useMemo(
|
|
45759
|
-
() => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
|
|
46036
|
+
() => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
|
|
45760
46037
|
[hoveredTile, hexes]
|
|
45761
46038
|
);
|
|
45762
46039
|
const hoveredHero = React84.useMemo(
|
|
45763
|
-
() => hoveredTile ? heroes.find((h) =>
|
|
46040
|
+
() => hoveredTile ? heroes.find((h) => {
|
|
46041
|
+
const hp = heroPosition(h);
|
|
46042
|
+
return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
|
|
46043
|
+
}) ?? null : null,
|
|
45764
46044
|
[hoveredTile, heroes]
|
|
45765
46045
|
);
|
|
45766
46046
|
const handleTileClick = React84.useCallback((x, y) => {
|
|
45767
46047
|
if (movementAnimRef.current) return;
|
|
45768
|
-
const hex = hexes.find((h) => h.x === x && h.y === y);
|
|
46048
|
+
const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
|
|
45769
46049
|
if (!hex) return;
|
|
45770
46050
|
if (tileClickEvent) {
|
|
45771
46051
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
45772
46052
|
}
|
|
45773
46053
|
if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
|
|
45774
|
-
|
|
45775
|
-
|
|
46054
|
+
const heroId = str(selectedHero.id);
|
|
46055
|
+
startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
|
|
46056
|
+
onHeroMove?.(heroId, x, y);
|
|
45776
46057
|
if (heroMoveEvent) {
|
|
45777
|
-
eventBus.emit(`UI:${heroMoveEvent}`, { heroId
|
|
46058
|
+
eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
|
|
45778
46059
|
}
|
|
45779
|
-
|
|
45780
|
-
|
|
46060
|
+
const feature = str(hex.feature);
|
|
46061
|
+
if (feature && feature !== "none") {
|
|
46062
|
+
onFeatureEnter?.(heroId, hex);
|
|
45781
46063
|
if (featureEnterEvent) {
|
|
45782
|
-
eventBus.emit(`UI:${featureEnterEvent}`, { heroId
|
|
46064
|
+
eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
|
|
45783
46065
|
}
|
|
45784
46066
|
}
|
|
45785
46067
|
});
|
|
45786
46068
|
return;
|
|
45787
46069
|
}
|
|
45788
|
-
const enemy = heroes.find((h) =>
|
|
46070
|
+
const enemy = heroes.find((h) => {
|
|
46071
|
+
const hp = heroPosition(h);
|
|
46072
|
+
return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
|
|
46073
|
+
});
|
|
45789
46074
|
if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
|
|
45790
|
-
|
|
46075
|
+
const attackerId = str(selectedHero.id);
|
|
46076
|
+
const defenderId = str(enemy.id);
|
|
46077
|
+
onBattleEncounter?.(attackerId, defenderId);
|
|
45791
46078
|
if (battleEncounterEvent) {
|
|
45792
|
-
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId
|
|
46079
|
+
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
|
|
45793
46080
|
}
|
|
45794
46081
|
}
|
|
45795
46082
|
}, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
|
|
45796
46083
|
const handleUnitClick = React84.useCallback((unitId) => {
|
|
45797
|
-
const hero = heroes.find((h) => h.id === unitId);
|
|
45798
|
-
if (hero && (hero
|
|
46084
|
+
const hero = heroes.find((h) => str(h.id) === unitId);
|
|
46085
|
+
if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
|
|
45799
46086
|
onHeroSelect?.(unitId);
|
|
45800
46087
|
if (heroSelectEvent) {
|
|
45801
46088
|
eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
|
|
@@ -45868,6 +46155,7 @@ var init_WorldMapBoard = __esm({
|
|
|
45868
46155
|
init_Stack();
|
|
45869
46156
|
init_LoadingState();
|
|
45870
46157
|
init_IsometricCanvas2();
|
|
46158
|
+
init_boardEntity();
|
|
45871
46159
|
init_isometric();
|
|
45872
46160
|
WorldMapBoard.displayName = "WorldMapBoard";
|
|
45873
46161
|
}
|
|
@@ -49096,11 +49384,11 @@ function buildMockData(schema) {
|
|
|
49096
49384
|
result[entityName] = entity.instances;
|
|
49097
49385
|
continue;
|
|
49098
49386
|
}
|
|
49099
|
-
const
|
|
49387
|
+
const rows2 = Array.from(
|
|
49100
49388
|
{ length: 10 },
|
|
49101
49389
|
(_, i) => generateEntityRow(entity, i + 1)
|
|
49102
49390
|
);
|
|
49103
|
-
result[entityName] =
|
|
49391
|
+
result[entityName] = rows2;
|
|
49104
49392
|
}
|
|
49105
49393
|
for (const orbital of schema.orbitals) {
|
|
49106
49394
|
for (const traitRef of orbital.traits ?? []) {
|