@almadar/ui 5.21.11 → 5.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +939 -638
- package/dist/avl/index.js +939 -638
- 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 +2036 -1675
- package/dist/components/index.js +1148 -787
- 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 +932 -631
- package/dist/providers/index.js +932 -631
- package/dist/runtime/index.cjs +934 -633
- package/dist/runtime/index.js +934 -633
- package/package.json +2 -2
package/dist/providers/index.js
CHANGED
|
@@ -2718,7 +2718,7 @@ var init_SvgGrid = __esm({
|
|
|
2718
2718
|
x,
|
|
2719
2719
|
y,
|
|
2720
2720
|
cols = 4,
|
|
2721
|
-
rows = 3,
|
|
2721
|
+
rows: rows2 = 3,
|
|
2722
2722
|
spacing = 20,
|
|
2723
2723
|
nodeRadius = 3,
|
|
2724
2724
|
color = "var(--color-primary)",
|
|
@@ -2727,7 +2727,7 @@ var init_SvgGrid = __esm({
|
|
|
2727
2727
|
highlights = []
|
|
2728
2728
|
}) => {
|
|
2729
2729
|
const highlightSet = new Set(highlights);
|
|
2730
|
-
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length:
|
|
2730
|
+
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
|
|
2731
2731
|
(_, row) => Array.from({ length: cols }).map((_2, col) => {
|
|
2732
2732
|
const index = row * cols + col;
|
|
2733
2733
|
const isHighlighted = highlightSet.has(index);
|
|
@@ -3387,7 +3387,7 @@ var init_Input = __esm({
|
|
|
3387
3387
|
onClear,
|
|
3388
3388
|
value,
|
|
3389
3389
|
options,
|
|
3390
|
-
rows = 3,
|
|
3390
|
+
rows: rows2 = 3,
|
|
3391
3391
|
onChange,
|
|
3392
3392
|
...props
|
|
3393
3393
|
}, ref) => {
|
|
@@ -3437,7 +3437,7 @@ var init_Input = __esm({
|
|
|
3437
3437
|
ref,
|
|
3438
3438
|
value,
|
|
3439
3439
|
onChange,
|
|
3440
|
-
rows,
|
|
3440
|
+
rows: rows2,
|
|
3441
3441
|
className: baseClassName,
|
|
3442
3442
|
...props
|
|
3443
3443
|
}
|
|
@@ -5518,66 +5518,6 @@ var init_RangeSlider = __esm({
|
|
|
5518
5518
|
RangeSlider.displayName = "RangeSlider";
|
|
5519
5519
|
}
|
|
5520
5520
|
});
|
|
5521
|
-
function easeOut(t) {
|
|
5522
|
-
return t * (2 - t);
|
|
5523
|
-
}
|
|
5524
|
-
var AnimatedCounter;
|
|
5525
|
-
var init_AnimatedCounter = __esm({
|
|
5526
|
-
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
5527
|
-
"use client";
|
|
5528
|
-
init_cn();
|
|
5529
|
-
init_Typography();
|
|
5530
|
-
AnimatedCounter = ({
|
|
5531
|
-
value: rawValue,
|
|
5532
|
-
duration = 600,
|
|
5533
|
-
prefix,
|
|
5534
|
-
suffix,
|
|
5535
|
-
className
|
|
5536
|
-
}) => {
|
|
5537
|
-
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
5538
|
-
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
5539
|
-
const [displayValue, setDisplayValue] = useState(value);
|
|
5540
|
-
const previousValueRef = useRef(value);
|
|
5541
|
-
const animationFrameRef = useRef(null);
|
|
5542
|
-
useEffect(() => {
|
|
5543
|
-
const from = previousValueRef.current;
|
|
5544
|
-
const to = value;
|
|
5545
|
-
previousValueRef.current = value;
|
|
5546
|
-
if (from === to) {
|
|
5547
|
-
setDisplayValue(to);
|
|
5548
|
-
return;
|
|
5549
|
-
}
|
|
5550
|
-
const startTime = performance.now();
|
|
5551
|
-
const diff = to - from;
|
|
5552
|
-
function animate(currentTime) {
|
|
5553
|
-
const elapsed = currentTime - startTime;
|
|
5554
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
5555
|
-
const easedProgress = easeOut(progress);
|
|
5556
|
-
setDisplayValue(from + diff * easedProgress);
|
|
5557
|
-
if (progress < 1) {
|
|
5558
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5559
|
-
} else {
|
|
5560
|
-
setDisplayValue(to);
|
|
5561
|
-
}
|
|
5562
|
-
}
|
|
5563
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5564
|
-
return () => {
|
|
5565
|
-
if (animationFrameRef.current !== null) {
|
|
5566
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
5567
|
-
}
|
|
5568
|
-
};
|
|
5569
|
-
}, [value, duration]);
|
|
5570
|
-
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
5571
|
-
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
5572
|
-
return /* @__PURE__ */ jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
5573
|
-
prefix,
|
|
5574
|
-
formattedValue,
|
|
5575
|
-
suffix
|
|
5576
|
-
] });
|
|
5577
|
-
};
|
|
5578
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
5579
|
-
}
|
|
5580
|
-
});
|
|
5581
5521
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
5582
5522
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
5583
5523
|
const observerRef = useRef(null);
|
|
@@ -8059,15 +7999,15 @@ function HeaderSkeleton({ className }) {
|
|
|
8059
7999
|
] })
|
|
8060
8000
|
] });
|
|
8061
8001
|
}
|
|
8062
|
-
function TableSkeleton({ rows = 5, columns = 4, className }) {
|
|
8002
|
+
function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
|
|
8063
8003
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
|
|
8064
8004
|
/* @__PURE__ */ jsx(HStack, { className: "px-4 py-3 bg-muted/30 border-b border-border", children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx(SkeletonBlock, { className: "h-4 flex-1 mx-2" }, i)) }),
|
|
8065
|
-
Array.from({ length:
|
|
8005
|
+
Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsx(
|
|
8066
8006
|
HStack,
|
|
8067
8007
|
{
|
|
8068
8008
|
className: cn(
|
|
8069
8009
|
"px-4 py-3",
|
|
8070
|
-
rowIdx <
|
|
8010
|
+
rowIdx < rows2 - 1 && "border-b border-border"
|
|
8071
8011
|
),
|
|
8072
8012
|
children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
|
|
8073
8013
|
},
|
|
@@ -8115,18 +8055,18 @@ function CardSkeleton({ className }) {
|
|
|
8115
8055
|
}
|
|
8116
8056
|
);
|
|
8117
8057
|
}
|
|
8118
|
-
function TextSkeleton({ rows = 3, className }) {
|
|
8119
|
-
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length:
|
|
8058
|
+
function TextSkeleton({ rows: rows2 = 3, className }) {
|
|
8059
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsx(
|
|
8120
8060
|
SkeletonLine,
|
|
8121
8061
|
{
|
|
8122
|
-
className: i ===
|
|
8062
|
+
className: i === rows2 - 1 ? "w-2/3" : "w-full"
|
|
8123
8063
|
},
|
|
8124
8064
|
i
|
|
8125
8065
|
)) });
|
|
8126
8066
|
}
|
|
8127
8067
|
function Skeleton({
|
|
8128
8068
|
variant = "text",
|
|
8129
|
-
rows,
|
|
8069
|
+
rows: rows2,
|
|
8130
8070
|
columns,
|
|
8131
8071
|
fields,
|
|
8132
8072
|
className
|
|
@@ -8136,15 +8076,15 @@ function Skeleton({
|
|
|
8136
8076
|
case "header":
|
|
8137
8077
|
return /* @__PURE__ */ jsx(HeaderSkeleton, { className });
|
|
8138
8078
|
case "table":
|
|
8139
|
-
return /* @__PURE__ */ jsx(TableSkeleton, { rows, columns, className });
|
|
8079
|
+
return /* @__PURE__ */ jsx(TableSkeleton, { rows: rows2, columns, className });
|
|
8140
8080
|
case "form":
|
|
8141
8081
|
return /* @__PURE__ */ jsx(FormSkeleton, { fields, className });
|
|
8142
8082
|
case "card":
|
|
8143
8083
|
return /* @__PURE__ */ jsx(CardSkeleton, { className });
|
|
8144
8084
|
case "text":
|
|
8145
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
8085
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
8146
8086
|
default:
|
|
8147
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
8087
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
8148
8088
|
}
|
|
8149
8089
|
}
|
|
8150
8090
|
var pulseClass;
|
|
@@ -9654,7 +9594,7 @@ var init_Menu = __esm({
|
|
|
9654
9594
|
className
|
|
9655
9595
|
}) => {
|
|
9656
9596
|
const eventBus = useEventBus();
|
|
9657
|
-
const { t } = useTranslate();
|
|
9597
|
+
const { t, direction } = useTranslate();
|
|
9658
9598
|
const [isOpen, setIsOpen] = useState(false);
|
|
9659
9599
|
const [activeSubMenu, setActiveSubMenu] = useState(null);
|
|
9660
9600
|
const [triggerRect, setTriggerRect] = useState(null);
|
|
@@ -9708,6 +9648,18 @@ var init_Menu = __esm({
|
|
|
9708
9648
|
"bottom-start": "top-full left-0 mt-2",
|
|
9709
9649
|
"bottom-end": "top-full right-0 mt-2"
|
|
9710
9650
|
};
|
|
9651
|
+
const rtlMirror = {
|
|
9652
|
+
"top-left": "top-right",
|
|
9653
|
+
"top-right": "top-left",
|
|
9654
|
+
"bottom-left": "bottom-right",
|
|
9655
|
+
"bottom-right": "bottom-left",
|
|
9656
|
+
"top-start": "top-end",
|
|
9657
|
+
"top-end": "top-start",
|
|
9658
|
+
"bottom-start": "bottom-end",
|
|
9659
|
+
"bottom-end": "bottom-start"
|
|
9660
|
+
};
|
|
9661
|
+
const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
|
|
9662
|
+
const subMenuSideClass = direction === "rtl" ? "right-full mr-2" : "left-full ml-2";
|
|
9711
9663
|
const triggerChild = React85__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
|
|
9712
9664
|
const triggerElement = React85__default.cloneElement(
|
|
9713
9665
|
triggerChild,
|
|
@@ -9735,7 +9687,7 @@ var init_Menu = __esm({
|
|
|
9735
9687
|
onMouseEnter: () => hasSubMenu && setActiveSubMenu(itemId),
|
|
9736
9688
|
"data-testid": item.event ? `action-${item.event}` : void 0,
|
|
9737
9689
|
className: cn(
|
|
9738
|
-
"w-full flex items-center justify-between gap-3 px-4 py-2 text-
|
|
9690
|
+
"w-full flex items-center justify-between gap-3 px-4 py-2 text-start",
|
|
9739
9691
|
"text-sm transition-colors",
|
|
9740
9692
|
"hover:bg-muted",
|
|
9741
9693
|
"focus:outline-none focus:bg-muted",
|
|
@@ -9754,7 +9706,7 @@ var init_Menu = __esm({
|
|
|
9754
9706
|
}
|
|
9755
9707
|
),
|
|
9756
9708
|
item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge }),
|
|
9757
|
-
hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: "sm", className: "flex-shrink-0" })
|
|
9709
|
+
hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: direction === "rtl" ? "chevron-left" : "chevron-right", size: "sm", className: "flex-shrink-0" })
|
|
9758
9710
|
] })
|
|
9759
9711
|
},
|
|
9760
9712
|
itemId
|
|
@@ -9774,7 +9726,8 @@ var init_Menu = __esm({
|
|
|
9774
9726
|
Box,
|
|
9775
9727
|
{
|
|
9776
9728
|
className: cn(
|
|
9777
|
-
"absolute
|
|
9729
|
+
"absolute top-0 z-50",
|
|
9730
|
+
subMenuSideClass,
|
|
9778
9731
|
menuContainerStyles
|
|
9779
9732
|
),
|
|
9780
9733
|
children: renderMenuItems(item.subMenu)
|
|
@@ -9792,12 +9745,12 @@ var init_Menu = __esm({
|
|
|
9792
9745
|
className: cn(
|
|
9793
9746
|
"absolute z-50",
|
|
9794
9747
|
menuContainerStyles,
|
|
9795
|
-
positionClasses3[
|
|
9748
|
+
positionClasses3[effectivePosition],
|
|
9796
9749
|
className
|
|
9797
9750
|
),
|
|
9798
9751
|
style: {
|
|
9799
|
-
left:
|
|
9800
|
-
right:
|
|
9752
|
+
left: effectivePosition.includes("left") ? 0 : "auto",
|
|
9753
|
+
right: effectivePosition.includes("right") ? 0 : "auto"
|
|
9801
9754
|
},
|
|
9802
9755
|
role: "menu",
|
|
9803
9756
|
children: renderMenuItems(items)
|
|
@@ -10115,7 +10068,7 @@ var init_MapView = __esm({
|
|
|
10115
10068
|
shadowSize: [41, 41]
|
|
10116
10069
|
});
|
|
10117
10070
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
10118
|
-
const { useEffect: useEffect70, useRef: useRef66, useCallback:
|
|
10071
|
+
const { useEffect: useEffect70, useRef: useRef66, useCallback: useCallback114, useState: useState100 } = React85__default;
|
|
10119
10072
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
10120
10073
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
10121
10074
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -10161,7 +10114,7 @@ var init_MapView = __esm({
|
|
|
10161
10114
|
}) {
|
|
10162
10115
|
const eventBus = useEventBus2();
|
|
10163
10116
|
const [clickedPosition, setClickedPosition] = useState100(null);
|
|
10164
|
-
const handleMapClick =
|
|
10117
|
+
const handleMapClick = useCallback114((lat, lng) => {
|
|
10165
10118
|
if (showClickedPin) {
|
|
10166
10119
|
setClickedPosition({ lat, lng });
|
|
10167
10120
|
}
|
|
@@ -10170,7 +10123,7 @@ var init_MapView = __esm({
|
|
|
10170
10123
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
10171
10124
|
}
|
|
10172
10125
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
10173
|
-
const handleMarkerClick =
|
|
10126
|
+
const handleMarkerClick = useCallback114((marker) => {
|
|
10174
10127
|
onMarkerClick?.(marker);
|
|
10175
10128
|
if (markerClickEvent) {
|
|
10176
10129
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -10391,7 +10344,7 @@ function InputPattern({
|
|
|
10391
10344
|
function TextareaPattern({
|
|
10392
10345
|
value = "",
|
|
10393
10346
|
placeholder,
|
|
10394
|
-
rows = 4,
|
|
10347
|
+
rows: rows2 = 4,
|
|
10395
10348
|
disabled = false,
|
|
10396
10349
|
fieldError,
|
|
10397
10350
|
onChange,
|
|
@@ -10411,7 +10364,7 @@ function TextareaPattern({
|
|
|
10411
10364
|
{
|
|
10412
10365
|
value: localValue,
|
|
10413
10366
|
placeholder,
|
|
10414
|
-
rows,
|
|
10367
|
+
rows: rows2,
|
|
10415
10368
|
disabled,
|
|
10416
10369
|
error: fieldError,
|
|
10417
10370
|
onChange: handleChange,
|
|
@@ -10896,6 +10849,91 @@ var init_ActionPalette = __esm({
|
|
|
10896
10849
|
ActionPalette.displayName = "ActionPalette";
|
|
10897
10850
|
}
|
|
10898
10851
|
});
|
|
10852
|
+
function parseValue(value) {
|
|
10853
|
+
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
10854
|
+
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
10855
|
+
if (!match) {
|
|
10856
|
+
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
10857
|
+
}
|
|
10858
|
+
const numStr = match[2];
|
|
10859
|
+
const decimalIdx = numStr.indexOf(".");
|
|
10860
|
+
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
10861
|
+
return {
|
|
10862
|
+
prefix: match[1],
|
|
10863
|
+
num: parseFloat(numStr),
|
|
10864
|
+
suffix: match[3],
|
|
10865
|
+
decimals
|
|
10866
|
+
};
|
|
10867
|
+
}
|
|
10868
|
+
var AnimatedCounter;
|
|
10869
|
+
var init_AnimatedCounter = __esm({
|
|
10870
|
+
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
10871
|
+
"use client";
|
|
10872
|
+
init_cn();
|
|
10873
|
+
init_Box();
|
|
10874
|
+
init_Typography();
|
|
10875
|
+
AnimatedCounter = ({
|
|
10876
|
+
value,
|
|
10877
|
+
label,
|
|
10878
|
+
duration = 1500,
|
|
10879
|
+
className
|
|
10880
|
+
}) => {
|
|
10881
|
+
const ref = useRef(null);
|
|
10882
|
+
const [displayValue, setDisplayValue] = useState("0");
|
|
10883
|
+
const [hasAnimated, setHasAnimated] = useState(false);
|
|
10884
|
+
const animate = useCallback(() => {
|
|
10885
|
+
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
10886
|
+
if (num2 === 0) {
|
|
10887
|
+
setDisplayValue(String(value));
|
|
10888
|
+
return;
|
|
10889
|
+
}
|
|
10890
|
+
const startTime = performance.now();
|
|
10891
|
+
const tick = (now) => {
|
|
10892
|
+
const elapsed = now - startTime;
|
|
10893
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
10894
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
10895
|
+
const current = eased * num2;
|
|
10896
|
+
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
10897
|
+
if (progress < 1) {
|
|
10898
|
+
requestAnimationFrame(tick);
|
|
10899
|
+
} else {
|
|
10900
|
+
setDisplayValue(String(value));
|
|
10901
|
+
}
|
|
10902
|
+
};
|
|
10903
|
+
requestAnimationFrame(tick);
|
|
10904
|
+
}, [value, duration]);
|
|
10905
|
+
useEffect(() => {
|
|
10906
|
+
if (hasAnimated) return;
|
|
10907
|
+
const el = ref.current;
|
|
10908
|
+
if (!el) return;
|
|
10909
|
+
const observer2 = new IntersectionObserver(
|
|
10910
|
+
(entries) => {
|
|
10911
|
+
if (entries[0].isIntersecting) {
|
|
10912
|
+
setHasAnimated(true);
|
|
10913
|
+
animate();
|
|
10914
|
+
observer2.disconnect();
|
|
10915
|
+
}
|
|
10916
|
+
},
|
|
10917
|
+
{ threshold: 0.3 }
|
|
10918
|
+
);
|
|
10919
|
+
observer2.observe(el);
|
|
10920
|
+
return () => observer2.disconnect();
|
|
10921
|
+
}, [hasAnimated, animate]);
|
|
10922
|
+
return /* @__PURE__ */ jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
10923
|
+
/* @__PURE__ */ jsx(
|
|
10924
|
+
Typography,
|
|
10925
|
+
{
|
|
10926
|
+
variant: "h2",
|
|
10927
|
+
className: "text-primary font-bold tabular-nums",
|
|
10928
|
+
children: hasAnimated ? displayValue : "0"
|
|
10929
|
+
}
|
|
10930
|
+
),
|
|
10931
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
10932
|
+
] });
|
|
10933
|
+
};
|
|
10934
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
10935
|
+
}
|
|
10936
|
+
});
|
|
10899
10937
|
var AuthLayout;
|
|
10900
10938
|
var init_AuthLayout = __esm({
|
|
10901
10939
|
"components/core/templates/AuthLayout.tsx"() {
|
|
@@ -12237,6 +12275,39 @@ var init_IsometricCanvas2 = __esm({
|
|
|
12237
12275
|
init_IsometricCanvas();
|
|
12238
12276
|
}
|
|
12239
12277
|
});
|
|
12278
|
+
|
|
12279
|
+
// components/game/organisms/boardEntity.ts
|
|
12280
|
+
function boardEntity(entity) {
|
|
12281
|
+
if (!entity) return void 0;
|
|
12282
|
+
return Array.isArray(entity) ? entity[0] : entity;
|
|
12283
|
+
}
|
|
12284
|
+
function str(v) {
|
|
12285
|
+
return v == null ? "" : String(v);
|
|
12286
|
+
}
|
|
12287
|
+
function num(v, fallback = 0) {
|
|
12288
|
+
const n = Number(v);
|
|
12289
|
+
return Number.isFinite(n) ? n : fallback;
|
|
12290
|
+
}
|
|
12291
|
+
function rows(v) {
|
|
12292
|
+
return Array.isArray(v) ? v : [];
|
|
12293
|
+
}
|
|
12294
|
+
function vec2(v) {
|
|
12295
|
+
const o = v ?? {};
|
|
12296
|
+
return { x: num(o.x), y: num(o.y) };
|
|
12297
|
+
}
|
|
12298
|
+
function unitPosition(u) {
|
|
12299
|
+
return vec2(u.position);
|
|
12300
|
+
}
|
|
12301
|
+
function unitTeam(u) {
|
|
12302
|
+
return str(u.team);
|
|
12303
|
+
}
|
|
12304
|
+
function unitHealth(u) {
|
|
12305
|
+
return num(u.health);
|
|
12306
|
+
}
|
|
12307
|
+
var init_boardEntity = __esm({
|
|
12308
|
+
"components/game/organisms/boardEntity.ts"() {
|
|
12309
|
+
}
|
|
12310
|
+
});
|
|
12240
12311
|
function BattleBoard({
|
|
12241
12312
|
entity,
|
|
12242
12313
|
scale = 0.45,
|
|
@@ -12263,43 +12334,49 @@ function BattleBoard({
|
|
|
12263
12334
|
attackEvent,
|
|
12264
12335
|
className
|
|
12265
12336
|
}) {
|
|
12266
|
-
const
|
|
12267
|
-
const
|
|
12268
|
-
const
|
|
12269
|
-
const
|
|
12270
|
-
const
|
|
12271
|
-
const
|
|
12272
|
-
const
|
|
12273
|
-
const
|
|
12274
|
-
const
|
|
12275
|
-
const
|
|
12276
|
-
const
|
|
12337
|
+
const board = boardEntity(entity) ?? {};
|
|
12338
|
+
const tiles = Array.isArray(board.tiles) ? board.tiles : [];
|
|
12339
|
+
const features = Array.isArray(board.features) ? board.features : [];
|
|
12340
|
+
const boardWidth = num(board.boardWidth, 8);
|
|
12341
|
+
const boardHeight = num(board.boardHeight, 6);
|
|
12342
|
+
const assetManifest = board.assetManifest;
|
|
12343
|
+
const backgroundImage = board.backgroundImage;
|
|
12344
|
+
const units = rows(board.units);
|
|
12345
|
+
const selectedUnitId = board.selectedUnitId ?? null;
|
|
12346
|
+
const currentPhase = str(board.phase) || "observation";
|
|
12347
|
+
const currentTurn = num(board.turn, 1);
|
|
12348
|
+
const gameResult = board.gameResult ?? null;
|
|
12277
12349
|
const eventBus = useEventBus();
|
|
12278
12350
|
const { t } = useTranslate();
|
|
12279
12351
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
12280
12352
|
const [isShaking, setIsShaking] = useState(false);
|
|
12281
12353
|
const selectedUnit = useMemo(
|
|
12282
|
-
() => units.find((u) => u.id === selectedUnitId) ?? null,
|
|
12354
|
+
() => units.find((u) => str(u.id) === selectedUnitId) ?? null,
|
|
12283
12355
|
[units, selectedUnitId]
|
|
12284
12356
|
);
|
|
12285
12357
|
const hoveredUnit = useMemo(() => {
|
|
12286
12358
|
if (!hoveredTile) return null;
|
|
12287
|
-
return units.find(
|
|
12288
|
-
|
|
12289
|
-
|
|
12359
|
+
return units.find((u) => {
|
|
12360
|
+
const p2 = unitPosition(u);
|
|
12361
|
+
return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
|
|
12362
|
+
}) ?? null;
|
|
12290
12363
|
}, [hoveredTile, units]);
|
|
12291
|
-
const playerUnits = useMemo(() => units.filter((u) => u
|
|
12292
|
-
const enemyUnits = useMemo(() => units.filter((u) => u
|
|
12364
|
+
const playerUnits = useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
|
|
12365
|
+
const enemyUnits = useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
|
|
12293
12366
|
const validMoves = useMemo(() => {
|
|
12294
12367
|
if (!selectedUnit || currentPhase !== "movement") return [];
|
|
12295
12368
|
const moves = [];
|
|
12296
|
-
const range = selectedUnit.movement;
|
|
12369
|
+
const range = num(selectedUnit.movement);
|
|
12370
|
+
const origin = unitPosition(selectedUnit);
|
|
12297
12371
|
for (let dy = -range; dy <= range; dy++) {
|
|
12298
12372
|
for (let dx = -range; dx <= range; dx++) {
|
|
12299
|
-
const nx =
|
|
12300
|
-
const ny =
|
|
12373
|
+
const nx = origin.x + dx;
|
|
12374
|
+
const ny = origin.y + dy;
|
|
12301
12375
|
const dist = Math.abs(dx) + Math.abs(dy);
|
|
12302
|
-
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) =>
|
|
12376
|
+
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
|
|
12377
|
+
const p2 = unitPosition(u);
|
|
12378
|
+
return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
|
|
12379
|
+
})) {
|
|
12303
12380
|
moves.push({ x: nx, y: ny });
|
|
12304
12381
|
}
|
|
12305
12382
|
}
|
|
@@ -12308,11 +12385,14 @@ function BattleBoard({
|
|
|
12308
12385
|
}, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
|
|
12309
12386
|
const attackTargets = useMemo(() => {
|
|
12310
12387
|
if (!selectedUnit || currentPhase !== "action") return [];
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
|
|
12388
|
+
const sp = unitPosition(selectedUnit);
|
|
12389
|
+
const sTeam = unitTeam(selectedUnit);
|
|
12390
|
+
return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
|
|
12391
|
+
const p2 = unitPosition(u);
|
|
12392
|
+
const dx = Math.abs(p2.x - sp.x);
|
|
12393
|
+
const dy = Math.abs(p2.y - sp.y);
|
|
12314
12394
|
return dx <= 1 && dy <= 1 && dx + dy > 0;
|
|
12315
|
-
}).map((u) => u
|
|
12395
|
+
}).map((u) => unitPosition(u));
|
|
12316
12396
|
}, [selectedUnit, currentPhase, units]);
|
|
12317
12397
|
const MOVE_SPEED_MS_PER_TILE = 300;
|
|
12318
12398
|
const movementAnimRef = useRef(null);
|
|
@@ -12352,23 +12432,25 @@ function BattleBoard({
|
|
|
12352
12432
|
return () => clearInterval(interval);
|
|
12353
12433
|
}, []);
|
|
12354
12434
|
const isoUnits = useMemo(() => {
|
|
12355
|
-
return units.filter((u) => u
|
|
12356
|
-
const
|
|
12435
|
+
return units.filter((u) => unitHealth(u) > 0).map((unit) => {
|
|
12436
|
+
const id = str(unit.id);
|
|
12437
|
+
const pos = movingPositions.get(id) ?? unitPosition(unit);
|
|
12438
|
+
const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
|
|
12357
12439
|
return {
|
|
12358
|
-
id
|
|
12440
|
+
id,
|
|
12359
12441
|
position: pos,
|
|
12360
|
-
name: unit.name,
|
|
12361
|
-
team: unit
|
|
12362
|
-
health: unit
|
|
12363
|
-
maxHealth: unit.maxHealth,
|
|
12364
|
-
unitType: unit.unitType,
|
|
12365
|
-
heroId: unit.heroId,
|
|
12366
|
-
sprite: unit.sprite,
|
|
12367
|
-
traits:
|
|
12368
|
-
name:
|
|
12369
|
-
currentState:
|
|
12370
|
-
states:
|
|
12371
|
-
cooldown:
|
|
12442
|
+
name: str(unit.name),
|
|
12443
|
+
team: unitTeam(unit),
|
|
12444
|
+
health: unitHealth(unit),
|
|
12445
|
+
maxHealth: num(unit.maxHealth),
|
|
12446
|
+
unitType: unit.unitType == null ? void 0 : str(unit.unitType),
|
|
12447
|
+
heroId: unit.heroId == null ? void 0 : str(unit.heroId),
|
|
12448
|
+
sprite: unit.sprite == null ? void 0 : str(unit.sprite),
|
|
12449
|
+
traits: unitTraits?.map((tr) => ({
|
|
12450
|
+
name: tr.name,
|
|
12451
|
+
currentState: tr.currentState,
|
|
12452
|
+
states: tr.states,
|
|
12453
|
+
cooldown: tr.cooldown ?? 0
|
|
12372
12454
|
}))
|
|
12373
12455
|
};
|
|
12374
12456
|
});
|
|
@@ -12380,8 +12462,8 @@ function BattleBoard({
|
|
|
12380
12462
|
[scale, baseOffsetX]
|
|
12381
12463
|
);
|
|
12382
12464
|
const checkGameEnd = useCallback(() => {
|
|
12383
|
-
const pa = units.filter((u) => u
|
|
12384
|
-
const ea = units.filter((u) => u
|
|
12465
|
+
const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
12466
|
+
const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
12385
12467
|
if (pa.length === 0) {
|
|
12386
12468
|
onGameEnd?.("defeat");
|
|
12387
12469
|
if (gameEndEvent) {
|
|
@@ -12395,21 +12477,22 @@ function BattleBoard({
|
|
|
12395
12477
|
}
|
|
12396
12478
|
}, [units, onGameEnd, gameEndEvent, eventBus]);
|
|
12397
12479
|
const handleUnitClick = useCallback((unitId) => {
|
|
12398
|
-
const unit = units.find((u) => u.id === unitId);
|
|
12480
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
12399
12481
|
if (!unit) return;
|
|
12400
12482
|
if (unitClickEvent) {
|
|
12401
12483
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
12402
12484
|
}
|
|
12403
12485
|
if (currentPhase === "action" && selectedUnit) {
|
|
12404
|
-
|
|
12405
|
-
|
|
12486
|
+
const up = unitPosition(unit);
|
|
12487
|
+
if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
|
|
12488
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
12406
12489
|
setIsShaking(true);
|
|
12407
12490
|
setTimeout(() => setIsShaking(false), 300);
|
|
12408
12491
|
onAttack?.(selectedUnit, unit, damage);
|
|
12409
12492
|
if (attackEvent) {
|
|
12410
12493
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
12411
|
-
attackerId: selectedUnit.id,
|
|
12412
|
-
targetId: unit.id,
|
|
12494
|
+
attackerId: str(selectedUnit.id),
|
|
12495
|
+
targetId: str(unit.id),
|
|
12413
12496
|
damage
|
|
12414
12497
|
});
|
|
12415
12498
|
}
|
|
@@ -12424,9 +12507,9 @@ function BattleBoard({
|
|
|
12424
12507
|
if (currentPhase === "movement" && selectedUnit) {
|
|
12425
12508
|
if (movementAnimRef.current) return;
|
|
12426
12509
|
if (validMoves.some((m) => m.x === x && m.y === y)) {
|
|
12427
|
-
const from = { ...selectedUnit
|
|
12510
|
+
const from = { ...unitPosition(selectedUnit) };
|
|
12428
12511
|
const to = { x, y };
|
|
12429
|
-
startMoveAnimation(selectedUnit.id, from, to, () => {
|
|
12512
|
+
startMoveAnimation(str(selectedUnit.id), from, to, () => {
|
|
12430
12513
|
onUnitMove?.(selectedUnit, to);
|
|
12431
12514
|
});
|
|
12432
12515
|
}
|
|
@@ -12584,6 +12667,7 @@ var init_BattleBoard = __esm({
|
|
|
12584
12667
|
init_Typography();
|
|
12585
12668
|
init_Stack();
|
|
12586
12669
|
init_IsometricCanvas2();
|
|
12670
|
+
init_boardEntity();
|
|
12587
12671
|
init_isometric();
|
|
12588
12672
|
BattleBoard.displayName = "BattleBoard";
|
|
12589
12673
|
}
|
|
@@ -13806,24 +13890,24 @@ var init_CodeBlock = __esm({
|
|
|
13806
13890
|
return;
|
|
13807
13891
|
}
|
|
13808
13892
|
lineEls.forEach((el) => {
|
|
13809
|
-
const
|
|
13810
|
-
if (hiddenLines.has(
|
|
13893
|
+
const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
|
|
13894
|
+
if (hiddenLines.has(num2)) {
|
|
13811
13895
|
el.style.display = "none";
|
|
13812
13896
|
return;
|
|
13813
13897
|
}
|
|
13814
13898
|
el.style.display = "";
|
|
13815
13899
|
el.style.position = "relative";
|
|
13816
13900
|
el.style.paddingLeft = "1.2em";
|
|
13817
|
-
const region = foldStartMap.get(
|
|
13901
|
+
const region = foldStartMap.get(num2);
|
|
13818
13902
|
if (!region) return;
|
|
13819
|
-
const isCollapsed = collapsed.has(
|
|
13903
|
+
const isCollapsed = collapsed.has(num2);
|
|
13820
13904
|
const toggle = document.createElement("span");
|
|
13821
13905
|
toggle.className = "fold-toggle";
|
|
13822
13906
|
toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
|
|
13823
13907
|
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%";
|
|
13824
13908
|
toggle.addEventListener("click", (e) => {
|
|
13825
13909
|
e.stopPropagation();
|
|
13826
|
-
toggleFoldRef.current(
|
|
13910
|
+
toggleFoldRef.current(num2);
|
|
13827
13911
|
});
|
|
13828
13912
|
el.insertBefore(toggle, el.firstChild);
|
|
13829
13913
|
if (isCollapsed) {
|
|
@@ -16076,10 +16160,13 @@ var init_BookChapterView = __esm({
|
|
|
16076
16160
|
init_cn();
|
|
16077
16161
|
BookChapterView = ({
|
|
16078
16162
|
chapter,
|
|
16163
|
+
orbitalSchema,
|
|
16079
16164
|
direction,
|
|
16080
16165
|
className
|
|
16081
16166
|
}) => {
|
|
16082
16167
|
const { t: _t } = useTranslate();
|
|
16168
|
+
const title = String(chapter.title ?? "");
|
|
16169
|
+
const content = String(chapter.content ?? "");
|
|
16083
16170
|
return /* @__PURE__ */ jsxs(
|
|
16084
16171
|
VStack,
|
|
16085
16172
|
{
|
|
@@ -16087,16 +16174,16 @@ var init_BookChapterView = __esm({
|
|
|
16087
16174
|
className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
|
|
16088
16175
|
style: { direction },
|
|
16089
16176
|
children: [
|
|
16090
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children:
|
|
16177
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
|
|
16091
16178
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
16092
|
-
!!
|
|
16179
|
+
!!orbitalSchema && /* @__PURE__ */ jsx(ScaledDiagram, { children: /* @__PURE__ */ jsx(
|
|
16093
16180
|
JazariStateMachine,
|
|
16094
16181
|
{
|
|
16095
|
-
schema:
|
|
16182
|
+
schema: orbitalSchema,
|
|
16096
16183
|
direction
|
|
16097
16184
|
}
|
|
16098
16185
|
) }),
|
|
16099
|
-
/* @__PURE__ */ jsx(ContentRenderer, { content
|
|
16186
|
+
/* @__PURE__ */ jsx(ContentRenderer, { content, direction })
|
|
16100
16187
|
]
|
|
16101
16188
|
}
|
|
16102
16189
|
);
|
|
@@ -16194,7 +16281,7 @@ var init_BookNavBar = __esm({
|
|
|
16194
16281
|
BookNavBar = ({
|
|
16195
16282
|
currentPage,
|
|
16196
16283
|
totalPages,
|
|
16197
|
-
chapterTitle,
|
|
16284
|
+
chapterTitle: chapterTitle2,
|
|
16198
16285
|
direction,
|
|
16199
16286
|
className
|
|
16200
16287
|
}) => {
|
|
@@ -16235,12 +16322,12 @@ var init_BookNavBar = __esm({
|
|
|
16235
16322
|
)
|
|
16236
16323
|
] }),
|
|
16237
16324
|
/* @__PURE__ */ jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
|
|
16238
|
-
|
|
16325
|
+
chapterTitle2 && /* @__PURE__ */ jsx(
|
|
16239
16326
|
Typography,
|
|
16240
16327
|
{
|
|
16241
16328
|
variant: "caption",
|
|
16242
16329
|
className: "text-center block truncate text-muted-foreground",
|
|
16243
|
-
children:
|
|
16330
|
+
children: chapterTitle2
|
|
16244
16331
|
}
|
|
16245
16332
|
),
|
|
16246
16333
|
/* @__PURE__ */ jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
|
|
@@ -16307,31 +16394,35 @@ var init_BookTableOfContents = __esm({
|
|
|
16307
16394
|
style: { direction },
|
|
16308
16395
|
children: [
|
|
16309
16396
|
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
|
|
16310
|
-
parts.map((part, partIdx) =>
|
|
16311
|
-
|
|
16312
|
-
|
|
16313
|
-
/* @__PURE__ */
|
|
16314
|
-
|
|
16315
|
-
|
|
16316
|
-
|
|
16317
|
-
|
|
16318
|
-
|
|
16319
|
-
|
|
16320
|
-
|
|
16321
|
-
|
|
16322
|
-
|
|
16323
|
-
|
|
16324
|
-
|
|
16325
|
-
|
|
16326
|
-
|
|
16327
|
-
|
|
16328
|
-
|
|
16329
|
-
|
|
16330
|
-
|
|
16331
|
-
|
|
16332
|
-
|
|
16333
|
-
|
|
16334
|
-
|
|
16397
|
+
parts.map((part, partIdx) => {
|
|
16398
|
+
const chapters = Array.isArray(part.chapters) ? part.chapters : [];
|
|
16399
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
16400
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
|
|
16401
|
+
/* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
|
|
16402
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
|
|
16403
|
+
] }),
|
|
16404
|
+
/* @__PURE__ */ jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
|
|
16405
|
+
const id = chapter.id == null ? "" : String(chapter.id);
|
|
16406
|
+
const isCurrent = id === currentChapterId;
|
|
16407
|
+
return /* @__PURE__ */ jsx(
|
|
16408
|
+
Button,
|
|
16409
|
+
{
|
|
16410
|
+
variant: "ghost",
|
|
16411
|
+
size: "sm",
|
|
16412
|
+
action: "BOOK_NAVIGATE",
|
|
16413
|
+
actionPayload: { chapterId: id },
|
|
16414
|
+
className: cn(
|
|
16415
|
+
"justify-start text-left w-full",
|
|
16416
|
+
direction === "rtl" && "text-right",
|
|
16417
|
+
isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
|
|
16418
|
+
),
|
|
16419
|
+
children: /* @__PURE__ */ jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
|
|
16420
|
+
},
|
|
16421
|
+
id
|
|
16422
|
+
);
|
|
16423
|
+
}) })
|
|
16424
|
+
] }, partIdx);
|
|
16425
|
+
})
|
|
16335
16426
|
]
|
|
16336
16427
|
}
|
|
16337
16428
|
);
|
|
@@ -16453,27 +16544,41 @@ function resolveFieldMap(fieldMap) {
|
|
|
16453
16544
|
function get(obj, key) {
|
|
16454
16545
|
return obj[key];
|
|
16455
16546
|
}
|
|
16547
|
+
function asStr(v) {
|
|
16548
|
+
return v == null ? "" : String(v);
|
|
16549
|
+
}
|
|
16456
16550
|
function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
|
|
16457
16551
|
const rawParts = get(raw, fields.parts) ?? [];
|
|
16458
|
-
|
|
16459
|
-
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16466
|
-
return {
|
|
16467
|
-
title: get(part, fields.partTitle) ?? "",
|
|
16468
|
-
chapters: rawChapters.map((ch) => ({
|
|
16469
|
-
id: get(ch, fields.chapterId) ?? "",
|
|
16470
|
-
title: get(ch, fields.chapterTitle) ?? "",
|
|
16471
|
-
content: get(ch, fields.chapterContent) ?? "",
|
|
16472
|
-
orbitalSchema: get(ch, fields.chapterOrbitalSchema)
|
|
16473
|
-
}))
|
|
16474
|
-
};
|
|
16475
|
-
})
|
|
16552
|
+
const direction = get(raw, fields.direction) ?? "ltr";
|
|
16553
|
+
const cover = {
|
|
16554
|
+
title: asStr(get(raw, fields.title)),
|
|
16555
|
+
subtitle: asStr(get(raw, fields.subtitle)),
|
|
16556
|
+
author: asStr(get(raw, fields.author)),
|
|
16557
|
+
coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
|
|
16558
|
+
direction
|
|
16476
16559
|
};
|
|
16560
|
+
const schemaByChapterId = {};
|
|
16561
|
+
const chapters = [];
|
|
16562
|
+
const parts = rawParts.map((part) => {
|
|
16563
|
+
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16564
|
+
const chapterRows = rawChapters.map((ch) => {
|
|
16565
|
+
const id = asStr(get(ch, fields.chapterId));
|
|
16566
|
+
const schema = get(ch, fields.chapterOrbitalSchema);
|
|
16567
|
+
if (schema) schemaByChapterId[id] = schema;
|
|
16568
|
+
const row = {
|
|
16569
|
+
id,
|
|
16570
|
+
title: asStr(get(ch, fields.chapterTitle)),
|
|
16571
|
+
content: asStr(get(ch, fields.chapterContent))
|
|
16572
|
+
};
|
|
16573
|
+
chapters.push(row);
|
|
16574
|
+
return row;
|
|
16575
|
+
});
|
|
16576
|
+
return {
|
|
16577
|
+
title: asStr(get(part, fields.partTitle)),
|
|
16578
|
+
chapters: chapterRows
|
|
16579
|
+
};
|
|
16580
|
+
});
|
|
16581
|
+
return { cover, direction, parts, chapters, schemaByChapterId };
|
|
16477
16582
|
}
|
|
16478
16583
|
var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
|
|
16479
16584
|
var init_types2 = __esm({
|
|
@@ -16511,10 +16616,7 @@ var init_types2 = __esm({
|
|
|
16511
16616
|
};
|
|
16512
16617
|
}
|
|
16513
16618
|
});
|
|
16514
|
-
|
|
16515
|
-
return book.parts.flatMap((part) => part.chapters);
|
|
16516
|
-
}
|
|
16517
|
-
var PRINT_STYLES, BookViewer;
|
|
16619
|
+
var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
|
|
16518
16620
|
var init_BookViewer = __esm({
|
|
16519
16621
|
"components/marketing/organisms/book/BookViewer.tsx"() {
|
|
16520
16622
|
init_Box();
|
|
@@ -16527,6 +16629,8 @@ var init_BookViewer = __esm({
|
|
|
16527
16629
|
init_BookNavBar();
|
|
16528
16630
|
init_EmptyState();
|
|
16529
16631
|
init_types2();
|
|
16632
|
+
chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
|
|
16633
|
+
chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
|
|
16530
16634
|
PRINT_STYLES = `
|
|
16531
16635
|
@media print {
|
|
16532
16636
|
.book-viewer-page {
|
|
@@ -16555,14 +16659,14 @@ var init_BookViewer = __esm({
|
|
|
16555
16659
|
return mapBookData(raw, resolvedFieldMap);
|
|
16556
16660
|
}, [entity, resolvedFieldMap]);
|
|
16557
16661
|
const direction = book?.direction ?? "ltr";
|
|
16558
|
-
const chapters = useMemo(() => book ?
|
|
16662
|
+
const chapters = useMemo(() => book ? book.chapters : [], [book]);
|
|
16559
16663
|
const totalPages = 2 + chapters.length;
|
|
16560
16664
|
const navigateTo = useCallback(
|
|
16561
16665
|
(page) => {
|
|
16562
16666
|
const clamped = Math.max(0, Math.min(page, totalPages - 1));
|
|
16563
16667
|
setCurrentPage(clamped);
|
|
16564
|
-
const
|
|
16565
|
-
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
|
|
16668
|
+
const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
|
|
16669
|
+
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
|
|
16566
16670
|
},
|
|
16567
16671
|
[totalPages, chapters, eventBus]
|
|
16568
16672
|
);
|
|
@@ -16574,8 +16678,8 @@ var init_BookViewer = __esm({
|
|
|
16574
16678
|
eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
|
|
16575
16679
|
eventBus.on("UI:BOOK_PRINT", () => window.print()),
|
|
16576
16680
|
eventBus.on("UI:BOOK_NAVIGATE", (event) => {
|
|
16577
|
-
const
|
|
16578
|
-
const idx = chapters.findIndex((ch) => ch
|
|
16681
|
+
const targetId = event.payload?.chapterId;
|
|
16682
|
+
const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
|
|
16579
16683
|
if (idx >= 0) navigateTo(idx + 2);
|
|
16580
16684
|
})
|
|
16581
16685
|
];
|
|
@@ -16592,9 +16696,11 @@ var init_BookViewer = __esm({
|
|
|
16592
16696
|
style.remove();
|
|
16593
16697
|
};
|
|
16594
16698
|
}, []);
|
|
16595
|
-
const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16596
|
-
const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16699
|
+
const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
|
|
16700
|
+
const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
|
|
16597
16701
|
if (!book) return /* @__PURE__ */ jsx(EmptyState, { message: t("book.noData") });
|
|
16702
|
+
const cover = book.cover;
|
|
16703
|
+
const coverTitle = String(cover.title ?? "");
|
|
16598
16704
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
|
|
16599
16705
|
/* @__PURE__ */ jsxs(
|
|
16600
16706
|
Box,
|
|
@@ -16606,10 +16712,10 @@ var init_BookViewer = __esm({
|
|
|
16606
16712
|
/* @__PURE__ */ jsx(
|
|
16607
16713
|
BookCoverPage,
|
|
16608
16714
|
{
|
|
16609
|
-
title:
|
|
16610
|
-
subtitle:
|
|
16611
|
-
author:
|
|
16612
|
-
coverImageUrl:
|
|
16715
|
+
title: coverTitle,
|
|
16716
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16717
|
+
author: String(cover.author ?? "") || void 0,
|
|
16718
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16613
16719
|
direction
|
|
16614
16720
|
}
|
|
16615
16721
|
),
|
|
@@ -16620,23 +16726,27 @@ var init_BookViewer = __esm({
|
|
|
16620
16726
|
direction
|
|
16621
16727
|
}
|
|
16622
16728
|
),
|
|
16623
|
-
chapters.map((chapter) =>
|
|
16624
|
-
|
|
16625
|
-
|
|
16626
|
-
|
|
16627
|
-
|
|
16628
|
-
|
|
16629
|
-
|
|
16630
|
-
|
|
16729
|
+
chapters.map((chapter) => {
|
|
16730
|
+
const id = chapterId(chapter);
|
|
16731
|
+
return /* @__PURE__ */ jsx(
|
|
16732
|
+
BookChapterView,
|
|
16733
|
+
{
|
|
16734
|
+
chapter,
|
|
16735
|
+
orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
|
|
16736
|
+
direction
|
|
16737
|
+
},
|
|
16738
|
+
id
|
|
16739
|
+
);
|
|
16740
|
+
})
|
|
16631
16741
|
] }),
|
|
16632
16742
|
/* @__PURE__ */ jsxs(Box, { className: "print:hidden", children: [
|
|
16633
16743
|
currentPage === 0 && /* @__PURE__ */ jsx(
|
|
16634
16744
|
BookCoverPage,
|
|
16635
16745
|
{
|
|
16636
|
-
title:
|
|
16637
|
-
subtitle:
|
|
16638
|
-
author:
|
|
16639
|
-
coverImageUrl:
|
|
16746
|
+
title: coverTitle,
|
|
16747
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16748
|
+
author: String(cover.author ?? "") || void 0,
|
|
16749
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16640
16750
|
direction
|
|
16641
16751
|
}
|
|
16642
16752
|
),
|
|
@@ -16652,6 +16762,7 @@ var init_BookViewer = __esm({
|
|
|
16652
16762
|
BookChapterView,
|
|
16653
16763
|
{
|
|
16654
16764
|
chapter: chapters[currentPage - 2],
|
|
16765
|
+
orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
|
|
16655
16766
|
direction
|
|
16656
16767
|
}
|
|
16657
16768
|
)
|
|
@@ -16664,7 +16775,7 @@ var init_BookViewer = __esm({
|
|
|
16664
16775
|
{
|
|
16665
16776
|
currentPage,
|
|
16666
16777
|
totalPages,
|
|
16667
|
-
chapterTitle: currentPage === 0 ?
|
|
16778
|
+
chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
|
|
16668
16779
|
direction
|
|
16669
16780
|
}
|
|
16670
16781
|
)
|
|
@@ -16762,7 +16873,7 @@ var init_Grid = __esm({
|
|
|
16762
16873
|
};
|
|
16763
16874
|
Grid = ({
|
|
16764
16875
|
cols = 1,
|
|
16765
|
-
rows,
|
|
16876
|
+
rows: rows2,
|
|
16766
16877
|
gap = "md",
|
|
16767
16878
|
rowGap,
|
|
16768
16879
|
colGap,
|
|
@@ -16774,7 +16885,7 @@ var init_Grid = __esm({
|
|
|
16774
16885
|
children,
|
|
16775
16886
|
as: Component = "div"
|
|
16776
16887
|
}) => {
|
|
16777
|
-
const mergedStyle =
|
|
16888
|
+
const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
|
|
16778
16889
|
return React85__default.createElement(
|
|
16779
16890
|
Component,
|
|
16780
16891
|
{
|
|
@@ -17490,14 +17601,14 @@ function BuilderBoard({
|
|
|
17490
17601
|
}) {
|
|
17491
17602
|
const { emit } = useEventBus();
|
|
17492
17603
|
const { t } = useTranslate();
|
|
17493
|
-
const resolved =
|
|
17604
|
+
const resolved = boardEntity(entity);
|
|
17494
17605
|
const [placements, setPlacements] = useState({});
|
|
17495
17606
|
const [headerError, setHeaderError] = useState(false);
|
|
17496
17607
|
const [submitted, setSubmitted] = useState(false);
|
|
17497
17608
|
const [attempts, setAttempts] = useState(0);
|
|
17498
17609
|
const [showHint, setShowHint] = useState(false);
|
|
17499
|
-
const components = resolved?.components
|
|
17500
|
-
const slots = resolved?.slots
|
|
17610
|
+
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
17611
|
+
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
17501
17612
|
const usedComponentIds = new Set(Object.values(placements));
|
|
17502
17613
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
17503
17614
|
const [selectedComponent, setSelectedComponent] = useState(null);
|
|
@@ -17531,7 +17642,7 @@ function BuilderBoard({
|
|
|
17531
17642
|
}, [slots, placements, attempts, completeEvent, emit]);
|
|
17532
17643
|
const handleReset = () => {
|
|
17533
17644
|
setSubmitted(false);
|
|
17534
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
17645
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
17535
17646
|
setShowHint(true);
|
|
17536
17647
|
}
|
|
17537
17648
|
};
|
|
@@ -17544,20 +17655,24 @@ function BuilderBoard({
|
|
|
17544
17655
|
};
|
|
17545
17656
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
17546
17657
|
if (!resolved) return null;
|
|
17658
|
+
const theme = resolved.theme ?? void 0;
|
|
17659
|
+
const themeBackground = theme?.background;
|
|
17660
|
+
const headerImage = str(resolved.headerImage);
|
|
17661
|
+
const hint = str(resolved.hint);
|
|
17547
17662
|
return /* @__PURE__ */ jsx(
|
|
17548
17663
|
Box,
|
|
17549
17664
|
{
|
|
17550
17665
|
className,
|
|
17551
17666
|
style: {
|
|
17552
|
-
backgroundImage:
|
|
17667
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
17553
17668
|
backgroundSize: "cover",
|
|
17554
17669
|
backgroundPosition: "center"
|
|
17555
17670
|
},
|
|
17556
17671
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
17557
|
-
|
|
17672
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
17558
17673
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
17559
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
17560
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
17674
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
17675
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
17561
17676
|
] }) }),
|
|
17562
17677
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
17563
17678
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
|
|
@@ -17617,9 +17732,9 @@ function BuilderBoard({
|
|
|
17617
17732
|
] }) }),
|
|
17618
17733
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
17619
17734
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
17620
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
17735
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
|
|
17621
17736
|
] }) }),
|
|
17622
|
-
showHint &&
|
|
17737
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
17623
17738
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
17624
17739
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
17625
17740
|
/* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
|
|
@@ -17638,6 +17753,7 @@ var init_BuilderBoard = __esm({
|
|
|
17638
17753
|
"components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
|
|
17639
17754
|
init_atoms2();
|
|
17640
17755
|
init_useEventBus();
|
|
17756
|
+
init_boardEntity();
|
|
17641
17757
|
BuilderBoard.displayName = "BuilderBoard";
|
|
17642
17758
|
}
|
|
17643
17759
|
});
|
|
@@ -17975,21 +18091,24 @@ function CalendarGrid({
|
|
|
17975
18091
|
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
17976
18092
|
}, 500);
|
|
17977
18093
|
}, [longPressEvent, longPressPayload, eventBus]);
|
|
17978
|
-
const renderEvent = (event) =>
|
|
17979
|
-
|
|
17980
|
-
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17984
|
-
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
|
|
18094
|
+
const renderEvent = (event) => {
|
|
18095
|
+
const color = event.color;
|
|
18096
|
+
return /* @__PURE__ */ jsx(
|
|
18097
|
+
Box,
|
|
18098
|
+
{
|
|
18099
|
+
rounded: "md",
|
|
18100
|
+
padding: "xs",
|
|
18101
|
+
border: true,
|
|
18102
|
+
className: cn(
|
|
18103
|
+
"cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
|
|
18104
|
+
color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
|
|
18105
|
+
),
|
|
18106
|
+
onClick: (e) => handleEventClick(event, e),
|
|
18107
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
|
|
18108
|
+
},
|
|
18109
|
+
event.id
|
|
18110
|
+
);
|
|
18111
|
+
};
|
|
17993
18112
|
return /* @__PURE__ */ jsxs(
|
|
17994
18113
|
Box,
|
|
17995
18114
|
{
|
|
@@ -19653,7 +19772,6 @@ var init_CardGrid = __esm({
|
|
|
19653
19772
|
alignItems = "stretch",
|
|
19654
19773
|
className,
|
|
19655
19774
|
children,
|
|
19656
|
-
// EntityDisplayProps
|
|
19657
19775
|
entity,
|
|
19658
19776
|
isLoading = false,
|
|
19659
19777
|
error = null,
|
|
@@ -20125,14 +20243,14 @@ var init_CaseStudyOrganism = __esm({
|
|
|
20125
20243
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsx(
|
|
20126
20244
|
CaseStudyCard,
|
|
20127
20245
|
{
|
|
20128
|
-
title: study.title,
|
|
20129
|
-
description: study.description,
|
|
20130
|
-
category: study.category,
|
|
20131
|
-
categoryColor: study.categoryColor,
|
|
20132
|
-
href: study.href,
|
|
20133
|
-
linkLabel: study.linkLabel
|
|
20246
|
+
title: String(study.title ?? ""),
|
|
20247
|
+
description: String(study.description ?? ""),
|
|
20248
|
+
category: String(study.category ?? ""),
|
|
20249
|
+
categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
|
|
20250
|
+
href: String(study.href ?? ""),
|
|
20251
|
+
linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
|
|
20134
20252
|
},
|
|
20135
|
-
study.id
|
|
20253
|
+
String(study.id ?? "")
|
|
20136
20254
|
)) })
|
|
20137
20255
|
] });
|
|
20138
20256
|
};
|
|
@@ -20155,10 +20273,10 @@ function CastleBoard({
|
|
|
20155
20273
|
className
|
|
20156
20274
|
}) {
|
|
20157
20275
|
const eventBus = useEventBus();
|
|
20158
|
-
const resolved =
|
|
20159
|
-
const tiles = resolved?.tiles
|
|
20160
|
-
const features = resolved?.features
|
|
20161
|
-
const units = resolved?.units
|
|
20276
|
+
const resolved = boardEntity(entity);
|
|
20277
|
+
const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
|
|
20278
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
20279
|
+
const units = Array.isArray(resolved?.units) ? resolved.units : [];
|
|
20162
20280
|
const assetManifest = resolved?.assetManifest;
|
|
20163
20281
|
const backgroundImage = resolved?.backgroundImage;
|
|
20164
20282
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
@@ -20186,7 +20304,7 @@ function CastleBoard({
|
|
|
20186
20304
|
onFeatureClick?.(feature);
|
|
20187
20305
|
if (featureClickEvent) {
|
|
20188
20306
|
eventBus.emit(`UI:${featureClickEvent}`, {
|
|
20189
|
-
featureId: feature.id,
|
|
20307
|
+
featureId: feature.id ?? "",
|
|
20190
20308
|
featureType: feature.type,
|
|
20191
20309
|
x: feature.x,
|
|
20192
20310
|
y: feature.y
|
|
@@ -20254,6 +20372,7 @@ var init_CastleBoard = __esm({
|
|
|
20254
20372
|
init_cn();
|
|
20255
20373
|
init_useEventBus();
|
|
20256
20374
|
init_IsometricCanvas2();
|
|
20375
|
+
init_boardEntity();
|
|
20257
20376
|
init_isometric();
|
|
20258
20377
|
CastleBoard.displayName = "CastleBoard";
|
|
20259
20378
|
}
|
|
@@ -21064,14 +21183,14 @@ function ClassifierBoard({
|
|
|
21064
21183
|
}) {
|
|
21065
21184
|
const { emit } = useEventBus();
|
|
21066
21185
|
const { t } = useTranslate();
|
|
21067
|
-
const resolved =
|
|
21186
|
+
const resolved = boardEntity(entity);
|
|
21068
21187
|
const [assignments, setAssignments] = useState({});
|
|
21069
21188
|
const [headerError, setHeaderError] = useState(false);
|
|
21070
21189
|
const [submitted, setSubmitted] = useState(false);
|
|
21071
21190
|
const [attempts, setAttempts] = useState(0);
|
|
21072
21191
|
const [showHint, setShowHint] = useState(false);
|
|
21073
|
-
const items = resolved?.items
|
|
21074
|
-
const categories = resolved?.categories
|
|
21192
|
+
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
21193
|
+
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
21075
21194
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
21076
21195
|
const allAssigned = Object.keys(assignments).length === items.length;
|
|
21077
21196
|
const results = submitted ? items.map((item) => ({
|
|
@@ -21103,7 +21222,7 @@ function ClassifierBoard({
|
|
|
21103
21222
|
}, [items, assignments, attempts, completeEvent, emit]);
|
|
21104
21223
|
const handleReset = () => {
|
|
21105
21224
|
setSubmitted(false);
|
|
21106
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
21225
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
21107
21226
|
setShowHint(true);
|
|
21108
21227
|
}
|
|
21109
21228
|
};
|
|
@@ -21114,20 +21233,25 @@ function ClassifierBoard({
|
|
|
21114
21233
|
setShowHint(false);
|
|
21115
21234
|
};
|
|
21116
21235
|
if (!resolved) return null;
|
|
21236
|
+
const theme = resolved.theme ?? void 0;
|
|
21237
|
+
const themeBackground = theme?.background;
|
|
21238
|
+
const headerImage = str(resolved.headerImage);
|
|
21239
|
+
const hint = str(resolved.hint);
|
|
21240
|
+
const failMessage = str(resolved.failMessage);
|
|
21117
21241
|
return /* @__PURE__ */ jsx(
|
|
21118
21242
|
Box,
|
|
21119
21243
|
{
|
|
21120
21244
|
className,
|
|
21121
21245
|
style: {
|
|
21122
|
-
backgroundImage:
|
|
21246
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
21123
21247
|
backgroundSize: "cover",
|
|
21124
21248
|
backgroundPosition: "center"
|
|
21125
21249
|
},
|
|
21126
21250
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
21127
|
-
|
|
21251
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
21128
21252
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
21129
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
21130
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
21253
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
21254
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
21131
21255
|
] }) }),
|
|
21132
21256
|
unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
21133
21257
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
|
|
@@ -21179,10 +21303,10 @@ function ClassifierBoard({
|
|
|
21179
21303
|
}) }),
|
|
21180
21304
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
21181
21305
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
21182
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
21183
|
-
!allCorrect &&
|
|
21306
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
|
|
21307
|
+
!allCorrect && failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
|
|
21184
21308
|
] }) }),
|
|
21185
|
-
showHint &&
|
|
21309
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
21186
21310
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
21187
21311
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
21188
21312
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -21201,6 +21325,7 @@ var init_ClassifierBoard = __esm({
|
|
|
21201
21325
|
"components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
|
|
21202
21326
|
init_atoms2();
|
|
21203
21327
|
init_useEventBus();
|
|
21328
|
+
init_boardEntity();
|
|
21204
21329
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
21205
21330
|
}
|
|
21206
21331
|
});
|
|
@@ -27571,7 +27696,7 @@ function InventoryPanel({
|
|
|
27571
27696
|
const slotArray = Array.from({ length: safeSlots }, (_, index) => {
|
|
27572
27697
|
return safeItems[index] ?? null;
|
|
27573
27698
|
});
|
|
27574
|
-
const
|
|
27699
|
+
const rows2 = Math.ceil(safeSlots / safeColumns);
|
|
27575
27700
|
const handleSlotClick = useCallback((index) => {
|
|
27576
27701
|
if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
|
|
27577
27702
|
onSelectSlot?.(index);
|
|
@@ -27640,7 +27765,7 @@ function InventoryPanel({
|
|
|
27640
27765
|
className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
|
|
27641
27766
|
style: {
|
|
27642
27767
|
gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
|
|
27643
|
-
gridTemplateRows: `repeat(${
|
|
27768
|
+
gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
|
|
27644
27769
|
},
|
|
27645
27770
|
children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
|
|
27646
27771
|
"button",
|
|
@@ -31604,11 +31729,11 @@ function LatticeSVG({
|
|
|
31604
31729
|
}) {
|
|
31605
31730
|
const paths = [];
|
|
31606
31731
|
const cols = 5;
|
|
31607
|
-
const
|
|
31732
|
+
const rows2 = Math.ceil(h / (w / cols));
|
|
31608
31733
|
const cellW = w / cols;
|
|
31609
31734
|
const cellH = cellW;
|
|
31610
31735
|
const bulge = cellW * 0.3;
|
|
31611
|
-
for (let row = 0; row <
|
|
31736
|
+
for (let row = 0; row < rows2; row++) {
|
|
31612
31737
|
for (let col = 0; col < cols; col++) {
|
|
31613
31738
|
const cx = col * cellW + cellW / 2;
|
|
31614
31739
|
const cy = row * cellH + cellH / 2;
|
|
@@ -32020,7 +32145,7 @@ var init_MatrixQuestion = __esm({
|
|
|
32020
32145
|
};
|
|
32021
32146
|
MatrixQuestion = ({
|
|
32022
32147
|
title,
|
|
32023
|
-
rows,
|
|
32148
|
+
rows: rows2,
|
|
32024
32149
|
columns = DEFAULT_MATRIX_COLUMNS,
|
|
32025
32150
|
values,
|
|
32026
32151
|
onChange,
|
|
@@ -32030,7 +32155,7 @@ var init_MatrixQuestion = __esm({
|
|
|
32030
32155
|
className
|
|
32031
32156
|
}) => {
|
|
32032
32157
|
const styles = sizeStyles13[size];
|
|
32033
|
-
const safeRows =
|
|
32158
|
+
const safeRows = rows2 ?? [];
|
|
32034
32159
|
const safeValues = values ?? {};
|
|
32035
32160
|
const eventBus = useEventBus();
|
|
32036
32161
|
const handleChange = useCallback(
|
|
@@ -32658,7 +32783,8 @@ var init_PositionedCanvas = __esm({
|
|
|
32658
32783
|
dragRef.current = null;
|
|
32659
32784
|
setDraggingId(null);
|
|
32660
32785
|
if (!wasDrag) {
|
|
32661
|
-
const
|
|
32786
|
+
const itemId = item.id;
|
|
32787
|
+
const next = selectedId === itemId ? null : itemId;
|
|
32662
32788
|
onSelect?.(next);
|
|
32663
32789
|
if (selectEvent) {
|
|
32664
32790
|
eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
@@ -32693,15 +32819,22 @@ var init_PositionedCanvas = __esm({
|
|
|
32693
32819
|
style: { width, height },
|
|
32694
32820
|
onClick: handleContainerClick,
|
|
32695
32821
|
children: items.map((item) => {
|
|
32822
|
+
const itemId = item.id;
|
|
32823
|
+
const label = item.label;
|
|
32824
|
+
const x = item.x;
|
|
32825
|
+
const y = item.y;
|
|
32826
|
+
const capacity = item.capacity;
|
|
32827
|
+
const partySize = item.partySize;
|
|
32828
|
+
const serverName = item.serverName;
|
|
32696
32829
|
const status = item.status ?? "empty";
|
|
32697
32830
|
const shape = item.shape ?? "round";
|
|
32698
|
-
const isSelected = selectedId ===
|
|
32699
|
-
const isDragging = draggingId ===
|
|
32831
|
+
const isSelected = selectedId === itemId;
|
|
32832
|
+
const isDragging = draggingId === itemId;
|
|
32700
32833
|
const statusBadge = STATUS_BADGE[status];
|
|
32701
32834
|
return /* @__PURE__ */ jsxs(
|
|
32702
32835
|
Box,
|
|
32703
32836
|
{
|
|
32704
|
-
"data-testid": `item-node-${
|
|
32837
|
+
"data-testid": `item-node-${itemId}`,
|
|
32705
32838
|
"data-status": status,
|
|
32706
32839
|
className: cn(
|
|
32707
32840
|
"absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
|
|
@@ -32712,7 +32845,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32712
32845
|
isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
|
|
32713
32846
|
isDragging && "shadow-lg z-10"
|
|
32714
32847
|
),
|
|
32715
|
-
style: { left:
|
|
32848
|
+
style: { left: x, top: y, touchAction: "none" },
|
|
32716
32849
|
onPointerDown: (e) => handlePointerDown(e, item),
|
|
32717
32850
|
onPointerMove: handlePointerMove,
|
|
32718
32851
|
onPointerUp: (e) => handlePointerUp(e, item),
|
|
@@ -32720,10 +32853,10 @@ var init_PositionedCanvas = __esm({
|
|
|
32720
32853
|
children: [
|
|
32721
32854
|
/* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", children: [
|
|
32722
32855
|
getStatusIcon(status),
|
|
32723
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children:
|
|
32856
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children: label })
|
|
32724
32857
|
] }),
|
|
32725
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
32726
|
-
status === "seated" &&
|
|
32858
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
|
|
32859
|
+
status === "seated" && serverName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
|
|
32727
32860
|
isSelected && /* @__PURE__ */ jsx(
|
|
32728
32861
|
Badge,
|
|
32729
32862
|
{
|
|
@@ -32735,7 +32868,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32735
32868
|
)
|
|
32736
32869
|
]
|
|
32737
32870
|
},
|
|
32738
|
-
|
|
32871
|
+
itemId
|
|
32739
32872
|
);
|
|
32740
32873
|
})
|
|
32741
32874
|
}
|
|
@@ -33507,9 +33640,10 @@ var init_RichBlockEditor = __esm({
|
|
|
33507
33640
|
});
|
|
33508
33641
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
33509
33642
|
for (const n of nodes) {
|
|
33643
|
+
const replies = n.replies;
|
|
33510
33644
|
if (n.collapsed) acc.add(n.id);
|
|
33511
|
-
if (
|
|
33512
|
-
collectInitiallyCollapsed(
|
|
33645
|
+
if (replies && replies.length > 0) {
|
|
33646
|
+
collectInitiallyCollapsed(replies, acc);
|
|
33513
33647
|
}
|
|
33514
33648
|
}
|
|
33515
33649
|
}
|
|
@@ -33539,44 +33673,52 @@ var init_ReplyTree = __esm({
|
|
|
33539
33673
|
}) => {
|
|
33540
33674
|
const eventBus = useEventBus();
|
|
33541
33675
|
const { t } = useTranslate();
|
|
33542
|
-
const
|
|
33543
|
-
const
|
|
33676
|
+
const nodeId = node.id;
|
|
33677
|
+
const authorName = node.authorName;
|
|
33678
|
+
const authorAvatarUrl = node.authorAvatarUrl;
|
|
33679
|
+
const content = node.content;
|
|
33680
|
+
const postedAt = node.postedAt;
|
|
33681
|
+
const voteCount = node.voteCount;
|
|
33682
|
+
const userVote = node.userVote;
|
|
33683
|
+
const replies = node.replies;
|
|
33684
|
+
const hasReplies = !!replies && replies.length > 0;
|
|
33685
|
+
const isCollapsed = collapsedSet.has(nodeId);
|
|
33544
33686
|
const atMaxDepth = depth >= maxDepth;
|
|
33545
33687
|
const [replyOpen, setReplyOpen] = useState(false);
|
|
33546
33688
|
const [draft, setDraft] = useState("");
|
|
33547
33689
|
const handleVote = useCallback(
|
|
33548
33690
|
(next) => {
|
|
33549
|
-
onVote?.(
|
|
33550
|
-
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId
|
|
33691
|
+
onVote?.(nodeId, next);
|
|
33692
|
+
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
|
|
33551
33693
|
},
|
|
33552
|
-
[
|
|
33694
|
+
[nodeId, onVote, voteEvent, eventBus]
|
|
33553
33695
|
);
|
|
33554
33696
|
const handleReply = useCallback(() => {
|
|
33555
|
-
onReply?.(
|
|
33697
|
+
onReply?.(nodeId);
|
|
33556
33698
|
setReplyOpen((open) => !open);
|
|
33557
|
-
}, [
|
|
33699
|
+
}, [nodeId, onReply]);
|
|
33558
33700
|
const handleSubmitReply = useCallback(() => {
|
|
33559
|
-
const
|
|
33560
|
-
if (!
|
|
33561
|
-
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId:
|
|
33701
|
+
const text = draft.trim();
|
|
33702
|
+
if (!text) return;
|
|
33703
|
+
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
|
|
33562
33704
|
setDraft("");
|
|
33563
33705
|
setReplyOpen(false);
|
|
33564
|
-
}, [
|
|
33706
|
+
}, [nodeId, draft, replyEvent, eventBus]);
|
|
33565
33707
|
const handleCancelReply = useCallback(() => {
|
|
33566
33708
|
setDraft("");
|
|
33567
33709
|
setReplyOpen(false);
|
|
33568
33710
|
}, []);
|
|
33569
33711
|
const handleFlag = useCallback(() => {
|
|
33570
|
-
onFlag?.(
|
|
33571
|
-
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId
|
|
33572
|
-
}, [
|
|
33712
|
+
onFlag?.(nodeId);
|
|
33713
|
+
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
|
|
33714
|
+
}, [nodeId, onFlag, flagEvent, eventBus]);
|
|
33573
33715
|
const handleContinue = useCallback(() => {
|
|
33574
|
-
onContinueThread?.(
|
|
33575
|
-
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId
|
|
33576
|
-
}, [
|
|
33716
|
+
onContinueThread?.(nodeId);
|
|
33717
|
+
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
|
|
33718
|
+
}, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
|
|
33577
33719
|
const handleToggle = useCallback(() => {
|
|
33578
|
-
toggleCollapse(
|
|
33579
|
-
}, [
|
|
33720
|
+
toggleCollapse(nodeId);
|
|
33721
|
+
}, [nodeId, toggleCollapse]);
|
|
33580
33722
|
return /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
|
|
33581
33723
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
|
|
33582
33724
|
hasReplies ? /* @__PURE__ */ jsx(
|
|
@@ -33608,25 +33750,25 @@ var init_ReplyTree = __esm({
|
|
|
33608
33750
|
/* @__PURE__ */ jsx(
|
|
33609
33751
|
Avatar,
|
|
33610
33752
|
{
|
|
33611
|
-
src:
|
|
33612
|
-
name:
|
|
33753
|
+
src: authorAvatarUrl,
|
|
33754
|
+
name: authorName,
|
|
33613
33755
|
size: "sm"
|
|
33614
33756
|
}
|
|
33615
33757
|
),
|
|
33616
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children:
|
|
33617
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
33758
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
|
|
33759
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
|
|
33618
33760
|
] }),
|
|
33619
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children:
|
|
33761
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
|
|
33620
33762
|
showActions && /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
33621
33763
|
/* @__PURE__ */ jsx(
|
|
33622
33764
|
VoteStack,
|
|
33623
33765
|
{
|
|
33624
|
-
count:
|
|
33625
|
-
userVote:
|
|
33766
|
+
count: voteCount ?? 0,
|
|
33767
|
+
userVote: userVote ?? null,
|
|
33626
33768
|
onVote: handleVote,
|
|
33627
33769
|
size: "sm",
|
|
33628
33770
|
variant: "horizontal",
|
|
33629
|
-
label: t("replyTree.voteOnReplyBy", { author:
|
|
33771
|
+
label: t("replyTree.voteOnReplyBy", { author: authorName })
|
|
33630
33772
|
}
|
|
33631
33773
|
),
|
|
33632
33774
|
/* @__PURE__ */ jsx(
|
|
@@ -33636,7 +33778,7 @@ var init_ReplyTree = __esm({
|
|
|
33636
33778
|
size: "sm",
|
|
33637
33779
|
leftIcon: "message-square",
|
|
33638
33780
|
onClick: handleReply,
|
|
33639
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33781
|
+
"aria-label": t("replyTree.replyTo", { author: authorName }),
|
|
33640
33782
|
children: t("replyTree.reply")
|
|
33641
33783
|
}
|
|
33642
33784
|
),
|
|
@@ -33647,7 +33789,7 @@ var init_ReplyTree = __esm({
|
|
|
33647
33789
|
size: "sm",
|
|
33648
33790
|
leftIcon: "flag",
|
|
33649
33791
|
onClick: handleFlag,
|
|
33650
|
-
"aria-label": t("replyTree.flagReplyBy", { author:
|
|
33792
|
+
"aria-label": t("replyTree.flagReplyBy", { author: authorName }),
|
|
33651
33793
|
children: t("replyTree.flag")
|
|
33652
33794
|
}
|
|
33653
33795
|
)
|
|
@@ -33659,9 +33801,9 @@ var init_ReplyTree = __esm({
|
|
|
33659
33801
|
inputType: "textarea",
|
|
33660
33802
|
rows: 2,
|
|
33661
33803
|
value: draft,
|
|
33662
|
-
placeholder: t("replyTree.replyToPlaceholder", { author:
|
|
33804
|
+
placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
|
|
33663
33805
|
onChange: (e) => setDraft(e.target.value),
|
|
33664
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33806
|
+
"aria-label": t("replyTree.replyTo", { author: authorName })
|
|
33665
33807
|
}
|
|
33666
33808
|
),
|
|
33667
33809
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
@@ -33692,7 +33834,7 @@ var init_ReplyTree = __esm({
|
|
|
33692
33834
|
),
|
|
33693
33835
|
children: t("replyTree.continueThread")
|
|
33694
33836
|
}
|
|
33695
|
-
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children:
|
|
33837
|
+
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsx(
|
|
33696
33838
|
ReplyTreeNode,
|
|
33697
33839
|
{
|
|
33698
33840
|
node: child,
|
|
@@ -36012,8 +36154,8 @@ var init_WizardContainer = __esm({
|
|
|
36012
36154
|
return void 0;
|
|
36013
36155
|
if (typeof controlledStep === "number") return controlledStep;
|
|
36014
36156
|
if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
|
|
36015
|
-
const
|
|
36016
|
-
return isNaN(
|
|
36157
|
+
const num2 = Number(controlledStep);
|
|
36158
|
+
return isNaN(num2) ? void 0 : num2;
|
|
36017
36159
|
})();
|
|
36018
36160
|
const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
|
|
36019
36161
|
const totalSteps = steps.length;
|
|
@@ -37718,7 +37860,7 @@ function DebuggerBoard({
|
|
|
37718
37860
|
}) {
|
|
37719
37861
|
const { emit } = useEventBus();
|
|
37720
37862
|
const { t } = useTranslate();
|
|
37721
|
-
const resolved =
|
|
37863
|
+
const resolved = boardEntity(entity);
|
|
37722
37864
|
const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
|
|
37723
37865
|
const [headerError, setHeaderError] = useState(false);
|
|
37724
37866
|
const [submitted, setSubmitted] = useState(false);
|
|
@@ -37736,7 +37878,7 @@ function DebuggerBoard({
|
|
|
37736
37878
|
return next;
|
|
37737
37879
|
});
|
|
37738
37880
|
};
|
|
37739
|
-
const lines = resolved?.lines
|
|
37881
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
37740
37882
|
const bugLines = lines.filter((l) => l.isBug);
|
|
37741
37883
|
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
37742
37884
|
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
@@ -37751,7 +37893,7 @@ function DebuggerBoard({
|
|
|
37751
37893
|
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
37752
37894
|
const handleReset = () => {
|
|
37753
37895
|
setSubmitted(false);
|
|
37754
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
37896
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
37755
37897
|
setShowHint(true);
|
|
37756
37898
|
}
|
|
37757
37899
|
};
|
|
@@ -37762,24 +37904,28 @@ function DebuggerBoard({
|
|
|
37762
37904
|
setShowHint(false);
|
|
37763
37905
|
};
|
|
37764
37906
|
if (!resolved) return null;
|
|
37907
|
+
const theme = resolved.theme ?? void 0;
|
|
37908
|
+
const themeBackground = theme?.background;
|
|
37909
|
+
const headerImage = str(resolved.headerImage);
|
|
37910
|
+
const hint = str(resolved.hint);
|
|
37765
37911
|
return /* @__PURE__ */ jsx(
|
|
37766
37912
|
Box,
|
|
37767
37913
|
{
|
|
37768
37914
|
className,
|
|
37769
37915
|
style: {
|
|
37770
|
-
backgroundImage:
|
|
37916
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
37771
37917
|
backgroundSize: "cover",
|
|
37772
37918
|
backgroundPosition: "center"
|
|
37773
37919
|
},
|
|
37774
37920
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
37775
|
-
|
|
37921
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
37776
37922
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
37777
37923
|
/* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
37778
37924
|
/* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
|
|
37779
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
|
|
37925
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
|
|
37780
37926
|
] }),
|
|
37781
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
37782
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
|
|
37927
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
37928
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
37783
37929
|
] }) }),
|
|
37784
37930
|
/* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
37785
37931
|
const isFlagged = flaggedLines.has(line.id);
|
|
@@ -37811,7 +37957,7 @@ function DebuggerBoard({
|
|
|
37811
37957
|
);
|
|
37812
37958
|
}) }) }),
|
|
37813
37959
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
37814
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
37960
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
37815
37961
|
bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
37816
37962
|
/* @__PURE__ */ jsx(
|
|
37817
37963
|
Icon,
|
|
@@ -37827,7 +37973,7 @@ function DebuggerBoard({
|
|
|
37827
37973
|
] })
|
|
37828
37974
|
] }, line.id))
|
|
37829
37975
|
] }) }),
|
|
37830
|
-
showHint &&
|
|
37976
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
37831
37977
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
37832
37978
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
37833
37979
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -37846,6 +37992,7 @@ var init_DebuggerBoard = __esm({
|
|
|
37846
37992
|
"components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
|
|
37847
37993
|
init_atoms2();
|
|
37848
37994
|
init_useEventBus();
|
|
37995
|
+
init_boardEntity();
|
|
37849
37996
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
37850
37997
|
}
|
|
37851
37998
|
});
|
|
@@ -37883,7 +38030,7 @@ function getBadgeVariant(fieldName, value) {
|
|
|
37883
38030
|
return "default";
|
|
37884
38031
|
}
|
|
37885
38032
|
function formatFieldLabel(fieldName) {
|
|
37886
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
38033
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
|
|
37887
38034
|
}
|
|
37888
38035
|
function formatFieldValue(value, fieldName) {
|
|
37889
38036
|
if (typeof value === "number") {
|
|
@@ -37902,26 +38049,26 @@ function formatFieldValue(value, fieldName) {
|
|
|
37902
38049
|
}
|
|
37903
38050
|
function renderRichFieldValue(value, fieldName, fieldType) {
|
|
37904
38051
|
if (value === void 0 || value === null) return "\u2014";
|
|
37905
|
-
const
|
|
38052
|
+
const str2 = String(value);
|
|
37906
38053
|
switch (fieldType) {
|
|
37907
38054
|
case "image":
|
|
37908
38055
|
case "url": {
|
|
37909
|
-
if (
|
|
38056
|
+
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
37910
38057
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
37911
38058
|
"img",
|
|
37912
38059
|
{
|
|
37913
|
-
src:
|
|
38060
|
+
src: str2,
|
|
37914
38061
|
alt: formatFieldLabel(fieldName),
|
|
37915
38062
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
37916
38063
|
loading: "lazy"
|
|
37917
38064
|
}
|
|
37918
38065
|
) });
|
|
37919
38066
|
}
|
|
37920
|
-
return
|
|
38067
|
+
return str2;
|
|
37921
38068
|
}
|
|
37922
38069
|
case "markdown":
|
|
37923
38070
|
case "richtext":
|
|
37924
|
-
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children:
|
|
38071
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsx(
|
|
37925
38072
|
Box,
|
|
37926
38073
|
{
|
|
37927
38074
|
className: "prose prose-sm max-w-none",
|
|
@@ -37939,11 +38086,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37939
38086
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37940
38087
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37941
38088
|
},
|
|
37942
|
-
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children:
|
|
38089
|
+
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children: str2 })
|
|
37943
38090
|
}
|
|
37944
38091
|
) });
|
|
37945
38092
|
case "code":
|
|
37946
|
-
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children:
|
|
38093
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children: str2 }) }) });
|
|
37947
38094
|
case "html":
|
|
37948
38095
|
return /* @__PURE__ */ jsx(
|
|
37949
38096
|
Box,
|
|
@@ -37963,12 +38110,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37963
38110
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37964
38111
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37965
38112
|
},
|
|
37966
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children:
|
|
38113
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: str2 })
|
|
37967
38114
|
}
|
|
37968
38115
|
);
|
|
37969
38116
|
case "date":
|
|
37970
38117
|
case "datetime": {
|
|
37971
|
-
const d = new Date(
|
|
38118
|
+
const d = new Date(str2);
|
|
37972
38119
|
if (!isNaN(d.getTime())) {
|
|
37973
38120
|
return d.toLocaleDateString(void 0, {
|
|
37974
38121
|
year: "numeric",
|
|
@@ -37977,7 +38124,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37977
38124
|
...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
|
|
37978
38125
|
});
|
|
37979
38126
|
}
|
|
37980
|
-
return
|
|
38127
|
+
return str2;
|
|
37981
38128
|
}
|
|
37982
38129
|
default:
|
|
37983
38130
|
return formatFieldValue(value, fieldName);
|
|
@@ -38655,6 +38802,40 @@ var init_RuleEditor = __esm({
|
|
|
38655
38802
|
RuleEditor.displayName = "RuleEditor";
|
|
38656
38803
|
}
|
|
38657
38804
|
});
|
|
38805
|
+
|
|
38806
|
+
// components/game/organisms/puzzles/event-handler/puzzleObject.ts
|
|
38807
|
+
function objId(o) {
|
|
38808
|
+
return o.id == null ? "" : String(o.id);
|
|
38809
|
+
}
|
|
38810
|
+
function objName(o) {
|
|
38811
|
+
return o.name == null ? "" : String(o.name);
|
|
38812
|
+
}
|
|
38813
|
+
function objIcon(o) {
|
|
38814
|
+
return o.icon == null ? "" : String(o.icon);
|
|
38815
|
+
}
|
|
38816
|
+
function objStates(o) {
|
|
38817
|
+
return Array.isArray(o.states) ? o.states : [];
|
|
38818
|
+
}
|
|
38819
|
+
function objCurrentState(o) {
|
|
38820
|
+
return o.currentState == null ? "" : String(o.currentState);
|
|
38821
|
+
}
|
|
38822
|
+
function objAvailableEvents(o) {
|
|
38823
|
+
return Array.isArray(o.availableEvents) ? o.availableEvents : [];
|
|
38824
|
+
}
|
|
38825
|
+
function objAvailableActions(o) {
|
|
38826
|
+
return Array.isArray(o.availableActions) ? o.availableActions : [];
|
|
38827
|
+
}
|
|
38828
|
+
function objRules(o) {
|
|
38829
|
+
return Array.isArray(o.rules) ? o.rules : [];
|
|
38830
|
+
}
|
|
38831
|
+
function objMaxRules(o) {
|
|
38832
|
+
const n = Number(o.maxRules);
|
|
38833
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
38834
|
+
}
|
|
38835
|
+
var init_puzzleObject = __esm({
|
|
38836
|
+
"components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
|
|
38837
|
+
}
|
|
38838
|
+
});
|
|
38658
38839
|
function ObjectRulePanel({
|
|
38659
38840
|
object,
|
|
38660
38841
|
onRulesChange,
|
|
@@ -38662,55 +38843,63 @@ function ObjectRulePanel({
|
|
|
38662
38843
|
className
|
|
38663
38844
|
}) {
|
|
38664
38845
|
const { t } = useTranslate();
|
|
38665
|
-
const
|
|
38666
|
-
const
|
|
38846
|
+
const id = objId(object);
|
|
38847
|
+
const name = objName(object);
|
|
38848
|
+
const icon = objIcon(object);
|
|
38849
|
+
const states = objStates(object);
|
|
38850
|
+
const currentState = objCurrentState(object);
|
|
38851
|
+
const availableEvents = objAvailableEvents(object);
|
|
38852
|
+
const availableActions = objAvailableActions(object);
|
|
38853
|
+
const rules = objRules(object);
|
|
38854
|
+
const maxRules = objMaxRules(object);
|
|
38855
|
+
const canAdd = rules.length < maxRules;
|
|
38667
38856
|
const handleRuleChange = useCallback((index, updatedRule) => {
|
|
38668
|
-
const newRules = [...
|
|
38857
|
+
const newRules = [...rules];
|
|
38669
38858
|
newRules[index] = updatedRule;
|
|
38670
|
-
onRulesChange(
|
|
38671
|
-
}, [
|
|
38859
|
+
onRulesChange(id, newRules);
|
|
38860
|
+
}, [id, rules, onRulesChange]);
|
|
38672
38861
|
const handleRuleRemove = useCallback((index) => {
|
|
38673
|
-
const newRules =
|
|
38674
|
-
onRulesChange(
|
|
38675
|
-
}, [
|
|
38862
|
+
const newRules = rules.filter((_, i) => i !== index);
|
|
38863
|
+
onRulesChange(id, newRules);
|
|
38864
|
+
}, [id, rules, onRulesChange]);
|
|
38676
38865
|
const handleAddRule = useCallback(() => {
|
|
38677
38866
|
if (!canAdd || disabled) return;
|
|
38678
|
-
const firstEvent =
|
|
38679
|
-
const firstAction =
|
|
38867
|
+
const firstEvent = availableEvents[0]?.value || "";
|
|
38868
|
+
const firstAction = availableActions[0]?.value || "";
|
|
38680
38869
|
const newRule = {
|
|
38681
38870
|
id: `rule-${nextRuleId++}`,
|
|
38682
38871
|
whenEvent: firstEvent,
|
|
38683
38872
|
thenAction: firstAction
|
|
38684
38873
|
};
|
|
38685
|
-
onRulesChange(
|
|
38686
|
-
}, [canAdd, disabled,
|
|
38874
|
+
onRulesChange(id, [...rules, newRule]);
|
|
38875
|
+
}, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
|
|
38687
38876
|
const machine = {
|
|
38688
|
-
name
|
|
38689
|
-
states
|
|
38690
|
-
currentState
|
|
38691
|
-
transitions:
|
|
38692
|
-
from:
|
|
38693
|
-
to:
|
|
38877
|
+
name,
|
|
38878
|
+
states,
|
|
38879
|
+
currentState,
|
|
38880
|
+
transitions: rules.map((r) => ({
|
|
38881
|
+
from: currentState,
|
|
38882
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38694
38883
|
event: r.whenEvent
|
|
38695
38884
|
}))
|
|
38696
38885
|
};
|
|
38697
38886
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
38698
38887
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center", gap: "sm", children: [
|
|
38699
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h5", children:
|
|
38888
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: icon }),
|
|
38700
38889
|
/* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
38701
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children:
|
|
38702
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " +
|
|
38890
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
|
|
38891
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
|
|
38703
38892
|
] })
|
|
38704
38893
|
] }),
|
|
38705
38894
|
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
|
|
38706
38895
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
38707
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count:
|
|
38708
|
-
|
|
38896
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
|
|
38897
|
+
rules.map((rule, i) => /* @__PURE__ */ jsx(
|
|
38709
38898
|
RuleEditor,
|
|
38710
38899
|
{
|
|
38711
38900
|
rule,
|
|
38712
|
-
availableEvents
|
|
38713
|
-
availableActions
|
|
38901
|
+
availableEvents,
|
|
38902
|
+
availableActions,
|
|
38714
38903
|
onChange: (r) => handleRuleChange(i, r),
|
|
38715
38904
|
onRemove: () => handleRuleRemove(i),
|
|
38716
38905
|
disabled
|
|
@@ -38728,6 +38917,7 @@ var init_ObjectRulePanel = __esm({
|
|
|
38728
38917
|
init_cn();
|
|
38729
38918
|
init_TraitStateViewer();
|
|
38730
38919
|
init_RuleEditor();
|
|
38920
|
+
init_puzzleObject();
|
|
38731
38921
|
nextRuleId = 1;
|
|
38732
38922
|
ObjectRulePanel.displayName = "ObjectRulePanel";
|
|
38733
38923
|
}
|
|
@@ -38794,11 +38984,11 @@ function EventHandlerBoard({
|
|
|
38794
38984
|
}) {
|
|
38795
38985
|
const { emit } = useEventBus();
|
|
38796
38986
|
const { t } = useTranslate();
|
|
38797
|
-
const resolved =
|
|
38798
|
-
const entityObjects = resolved?.objects
|
|
38799
|
-
const [objects, setObjects] = useState(entityObjects);
|
|
38987
|
+
const resolved = boardEntity(entity);
|
|
38988
|
+
const entityObjects = rows(resolved?.objects);
|
|
38989
|
+
const [objects, setObjects] = useState(() => [...entityObjects]);
|
|
38800
38990
|
const [selectedObjectId, setSelectedObjectId] = useState(
|
|
38801
|
-
entityObjects[0]
|
|
38991
|
+
entityObjects[0] ? objId(entityObjects[0]) : null
|
|
38802
38992
|
);
|
|
38803
38993
|
const [headerError, setHeaderError] = useState(false);
|
|
38804
38994
|
const [playState, setPlayState] = useState("editing");
|
|
@@ -38809,10 +38999,10 @@ function EventHandlerBoard({
|
|
|
38809
38999
|
useEffect(() => () => {
|
|
38810
39000
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38811
39001
|
}, []);
|
|
38812
|
-
const selectedObject = objects.find((o) => o
|
|
39002
|
+
const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
|
|
38813
39003
|
const handleRulesChange = useCallback((objectId, rules) => {
|
|
38814
39004
|
setObjects((prev) => prev.map(
|
|
38815
|
-
(o) => o
|
|
39005
|
+
(o) => objId(o) === objectId ? { ...o, rules } : o
|
|
38816
39006
|
));
|
|
38817
39007
|
}, []);
|
|
38818
39008
|
const addLogEntry = useCallback((icon, message, status = "done") => {
|
|
@@ -38826,11 +39016,12 @@ function EventHandlerBoard({
|
|
|
38826
39016
|
setEventLog([]);
|
|
38827
39017
|
const allRules = [];
|
|
38828
39018
|
objects.forEach((obj) => {
|
|
38829
|
-
obj.
|
|
39019
|
+
objRules(obj).forEach((rule) => {
|
|
38830
39020
|
allRules.push({ object: obj, rule });
|
|
38831
39021
|
});
|
|
38832
39022
|
});
|
|
38833
|
-
const triggers = resolved?.triggerEvents
|
|
39023
|
+
const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
|
|
39024
|
+
const goalEvent = str(resolved?.goalEvent);
|
|
38834
39025
|
const eventQueue = [...triggers];
|
|
38835
39026
|
const firedEvents = /* @__PURE__ */ new Set();
|
|
38836
39027
|
let stepIdx = 0;
|
|
@@ -38859,14 +39050,14 @@ function EventHandlerBoard({
|
|
|
38859
39050
|
addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
|
|
38860
39051
|
} else {
|
|
38861
39052
|
matching.forEach(({ object, rule }) => {
|
|
38862
|
-
addLogEntry(object
|
|
39053
|
+
addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
|
|
38863
39054
|
eventQueue.push(rule.thenAction);
|
|
38864
|
-
if (rule.thenAction ===
|
|
39055
|
+
if (rule.thenAction === goalEvent) {
|
|
38865
39056
|
goalReached = true;
|
|
38866
39057
|
}
|
|
38867
39058
|
});
|
|
38868
39059
|
}
|
|
38869
|
-
if (currentEvent ===
|
|
39060
|
+
if (currentEvent === goalEvent) {
|
|
38870
39061
|
goalReached = true;
|
|
38871
39062
|
}
|
|
38872
39063
|
stepIdx++;
|
|
@@ -38884,65 +39075,75 @@ function EventHandlerBoard({
|
|
|
38884
39075
|
}, []);
|
|
38885
39076
|
const handleReset = useCallback(() => {
|
|
38886
39077
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38887
|
-
|
|
39078
|
+
const resetObjects = rows(resolved?.objects);
|
|
39079
|
+
setObjects([...resetObjects]);
|
|
38888
39080
|
setPlayState("editing");
|
|
38889
39081
|
setEventLog([]);
|
|
38890
|
-
setSelectedObjectId(
|
|
39082
|
+
setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
|
|
38891
39083
|
setAttempts(0);
|
|
38892
39084
|
}, [resolved?.objects]);
|
|
38893
39085
|
if (!resolved) return null;
|
|
38894
39086
|
const objectViewers = objects.map((obj) => {
|
|
39087
|
+
const states = objStates(obj);
|
|
39088
|
+
const currentState = objCurrentState(obj);
|
|
38895
39089
|
const machine = {
|
|
38896
|
-
name: obj
|
|
38897
|
-
states
|
|
38898
|
-
currentState
|
|
38899
|
-
transitions: obj.
|
|
38900
|
-
from:
|
|
38901
|
-
to:
|
|
39090
|
+
name: objName(obj),
|
|
39091
|
+
states,
|
|
39092
|
+
currentState,
|
|
39093
|
+
transitions: objRules(obj).map((r) => ({
|
|
39094
|
+
from: currentState,
|
|
39095
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38902
39096
|
event: r.whenEvent
|
|
38903
39097
|
}))
|
|
38904
39098
|
};
|
|
38905
39099
|
return { obj, machine };
|
|
38906
39100
|
});
|
|
38907
|
-
const
|
|
39101
|
+
const hint = str(resolved.hint);
|
|
39102
|
+
const showHint = attempts >= 3 && hint;
|
|
39103
|
+
const theme = resolved.theme ?? void 0;
|
|
39104
|
+
const themeBackground = theme?.background;
|
|
39105
|
+
const headerImage = str(resolved.headerImage);
|
|
38908
39106
|
const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
|
|
38909
39107
|
return /* @__PURE__ */ jsxs(
|
|
38910
39108
|
VStack,
|
|
38911
39109
|
{
|
|
38912
39110
|
className: cn("p-4 gap-6", className),
|
|
38913
39111
|
style: {
|
|
38914
|
-
backgroundImage:
|
|
39112
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
38915
39113
|
backgroundSize: "cover",
|
|
38916
39114
|
backgroundPosition: "center"
|
|
38917
39115
|
},
|
|
38918
39116
|
children: [
|
|
38919
|
-
|
|
39117
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
38920
39118
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
38921
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
38922
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
39119
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
39120
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
38923
39121
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
38924
39122
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
38925
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
|
|
39123
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
|
|
38926
39124
|
] })
|
|
38927
39125
|
] }),
|
|
38928
39126
|
/* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
38929
39127
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
38930
|
-
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) =>
|
|
38931
|
-
|
|
38932
|
-
|
|
38933
|
-
|
|
38934
|
-
|
|
38935
|
-
|
|
38936
|
-
|
|
38937
|
-
|
|
38938
|
-
|
|
38939
|
-
|
|
38940
|
-
/* @__PURE__ */
|
|
38941
|
-
|
|
38942
|
-
|
|
38943
|
-
|
|
38944
|
-
|
|
38945
|
-
|
|
39128
|
+
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
|
|
39129
|
+
const oid = objId(obj);
|
|
39130
|
+
return /* @__PURE__ */ jsx(
|
|
39131
|
+
Box,
|
|
39132
|
+
{
|
|
39133
|
+
className: cn(
|
|
39134
|
+
"p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
|
|
39135
|
+
selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
39136
|
+
),
|
|
39137
|
+
onClick: () => setSelectedObjectId(oid),
|
|
39138
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
39139
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: objIcon(obj) }),
|
|
39140
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
|
|
39141
|
+
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
39142
|
+
] })
|
|
39143
|
+
},
|
|
39144
|
+
oid
|
|
39145
|
+
);
|
|
39146
|
+
}) })
|
|
38946
39147
|
] }),
|
|
38947
39148
|
selectedObject && /* @__PURE__ */ jsx(
|
|
38948
39149
|
ObjectRulePanel,
|
|
@@ -38953,12 +39154,12 @@ function EventHandlerBoard({
|
|
|
38953
39154
|
}
|
|
38954
39155
|
),
|
|
38955
39156
|
eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
|
|
38956
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("eventHandler.chainComplete") }) }),
|
|
39157
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("eventHandler.chainComplete") }) }),
|
|
38957
39158
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
38958
39159
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
|
|
38959
39160
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
38960
39161
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
38961
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
39162
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
38962
39163
|
] }) })
|
|
38963
39164
|
] }),
|
|
38964
39165
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -38986,6 +39187,8 @@ var init_EventHandlerBoard = __esm({
|
|
|
38986
39187
|
init_TraitStateViewer();
|
|
38987
39188
|
init_ObjectRulePanel();
|
|
38988
39189
|
init_EventLog();
|
|
39190
|
+
init_puzzleObject();
|
|
39191
|
+
init_boardEntity();
|
|
38989
39192
|
ENCOURAGEMENT_KEYS = [
|
|
38990
39193
|
"puzzle.tryAgain1",
|
|
38991
39194
|
"puzzle.tryAgain2",
|
|
@@ -39074,7 +39277,10 @@ var init_FeatureGridOrganism = __esm({
|
|
|
39074
39277
|
);
|
|
39075
39278
|
useCallback(
|
|
39076
39279
|
(feature) => {
|
|
39077
|
-
eventBus.emit("UI:FEATURE_CLICK", {
|
|
39280
|
+
eventBus.emit("UI:FEATURE_CLICK", {
|
|
39281
|
+
id: String(feature.id ?? ""),
|
|
39282
|
+
href: String(feature.href ?? "")
|
|
39283
|
+
});
|
|
39078
39284
|
},
|
|
39079
39285
|
[eventBus]
|
|
39080
39286
|
);
|
|
@@ -39084,14 +39290,17 @@ var init_FeatureGridOrganism = __esm({
|
|
|
39084
39290
|
if (error) {
|
|
39085
39291
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
39086
39292
|
}
|
|
39087
|
-
const featureCards = items.map((feature) =>
|
|
39088
|
-
|
|
39089
|
-
|
|
39090
|
-
|
|
39091
|
-
|
|
39092
|
-
|
|
39093
|
-
|
|
39094
|
-
|
|
39293
|
+
const featureCards = items.map((feature) => {
|
|
39294
|
+
const href = feature.href != null ? String(feature.href) : void 0;
|
|
39295
|
+
return {
|
|
39296
|
+
icon: feature.icon != null ? String(feature.icon) : void 0,
|
|
39297
|
+
title: String(feature.title ?? ""),
|
|
39298
|
+
description: String(feature.description ?? ""),
|
|
39299
|
+
href,
|
|
39300
|
+
linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
|
|
39301
|
+
variant: href ? "interactive" : "bordered"
|
|
39302
|
+
};
|
|
39303
|
+
});
|
|
39095
39304
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
39096
39305
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
39097
39306
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
@@ -40409,22 +40618,24 @@ var init_HeroOrganism = __esm({
|
|
|
40409
40618
|
() => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
|
|
40410
40619
|
[entity]
|
|
40411
40620
|
);
|
|
40621
|
+
const primaryAction = resolved?.primaryAction;
|
|
40622
|
+
const secondaryAction = resolved?.secondaryAction;
|
|
40412
40623
|
const handlePrimaryClick = useCallback(() => {
|
|
40413
|
-
if (
|
|
40624
|
+
if (primaryAction) {
|
|
40414
40625
|
eventBus.emit("UI:CTA_PRIMARY", {
|
|
40415
|
-
label:
|
|
40416
|
-
href:
|
|
40626
|
+
label: String(primaryAction.label ?? ""),
|
|
40627
|
+
href: String(primaryAction.href ?? "")
|
|
40417
40628
|
});
|
|
40418
40629
|
}
|
|
40419
|
-
}, [eventBus,
|
|
40630
|
+
}, [eventBus, primaryAction]);
|
|
40420
40631
|
const handleSecondaryClick = useCallback(() => {
|
|
40421
|
-
if (
|
|
40632
|
+
if (secondaryAction) {
|
|
40422
40633
|
eventBus.emit("UI:CTA_SECONDARY", {
|
|
40423
|
-
label:
|
|
40424
|
-
href:
|
|
40634
|
+
label: String(secondaryAction.label ?? ""),
|
|
40635
|
+
href: String(secondaryAction.href ?? "")
|
|
40425
40636
|
});
|
|
40426
40637
|
}
|
|
40427
|
-
}, [eventBus,
|
|
40638
|
+
}, [eventBus, secondaryAction]);
|
|
40428
40639
|
if (isLoading) {
|
|
40429
40640
|
return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
|
|
40430
40641
|
}
|
|
@@ -40434,17 +40645,19 @@ var init_HeroOrganism = __esm({
|
|
|
40434
40645
|
if (!resolved) {
|
|
40435
40646
|
return null;
|
|
40436
40647
|
}
|
|
40648
|
+
const imageRaw = resolved.image;
|
|
40649
|
+
const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
|
|
40437
40650
|
return /* @__PURE__ */ jsxs(
|
|
40438
40651
|
HeroSection,
|
|
40439
40652
|
{
|
|
40440
|
-
tag: resolved.tag,
|
|
40441
|
-
title: resolved.title,
|
|
40442
|
-
titleAccent: resolved.titleAccent,
|
|
40443
|
-
subtitle: resolved.subtitle,
|
|
40444
|
-
primaryAction:
|
|
40445
|
-
secondaryAction:
|
|
40446
|
-
installCommand: resolved.installCommand,
|
|
40447
|
-
image
|
|
40653
|
+
tag: resolved.tag != null ? String(resolved.tag) : void 0,
|
|
40654
|
+
title: String(resolved.title ?? ""),
|
|
40655
|
+
titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
|
|
40656
|
+
subtitle: String(resolved.subtitle ?? ""),
|
|
40657
|
+
primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
|
|
40658
|
+
secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
|
|
40659
|
+
installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
|
|
40660
|
+
image,
|
|
40448
40661
|
imagePosition: resolved.imagePosition,
|
|
40449
40662
|
background: resolved.background,
|
|
40450
40663
|
className: cn(className),
|
|
@@ -40453,8 +40666,8 @@ var init_HeroOrganism = __esm({
|
|
|
40453
40666
|
/* @__PURE__ */ jsx(
|
|
40454
40667
|
_HeroClickInterceptor,
|
|
40455
40668
|
{
|
|
40456
|
-
hasPrimary: !!
|
|
40457
|
-
hasSecondary: !!
|
|
40669
|
+
hasPrimary: !!primaryAction,
|
|
40670
|
+
hasSecondary: !!secondaryAction,
|
|
40458
40671
|
onPrimaryClick: handlePrimaryClick,
|
|
40459
40672
|
onSecondaryClick: handleSecondaryClick
|
|
40460
40673
|
}
|
|
@@ -40683,7 +40896,7 @@ function formatValue3(value, fieldName) {
|
|
|
40683
40896
|
return String(value);
|
|
40684
40897
|
}
|
|
40685
40898
|
function formatFieldLabel2(fieldName) {
|
|
40686
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
40899
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
|
|
40687
40900
|
}
|
|
40688
40901
|
var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
|
|
40689
40902
|
var init_List = __esm({
|
|
@@ -41530,20 +41743,22 @@ function NegotiatorBoard({
|
|
|
41530
41743
|
}) {
|
|
41531
41744
|
const { emit } = useEventBus();
|
|
41532
41745
|
const { t } = useTranslate();
|
|
41533
|
-
const resolved =
|
|
41746
|
+
const resolved = boardEntity(entity);
|
|
41534
41747
|
const [history, setHistory] = useState([]);
|
|
41535
41748
|
const [headerError, setHeaderError] = useState(false);
|
|
41536
41749
|
const [showHint, setShowHint] = useState(false);
|
|
41750
|
+
const totalRounds = num(resolved?.totalRounds);
|
|
41751
|
+
const targetScore = num(resolved?.targetScore);
|
|
41537
41752
|
const currentRound = history.length;
|
|
41538
|
-
const isComplete = currentRound >=
|
|
41753
|
+
const isComplete = currentRound >= totalRounds;
|
|
41539
41754
|
const playerTotal = history.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41540
41755
|
const opponentTotal = history.reduce((s, r) => s + r.opponentPayoff, 0);
|
|
41541
|
-
const won = isComplete && playerTotal >=
|
|
41542
|
-
const actions = resolved?.actions
|
|
41543
|
-
const payoffMatrix = resolved?.payoffMatrix
|
|
41756
|
+
const won = isComplete && playerTotal >= targetScore;
|
|
41757
|
+
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
41758
|
+
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
41544
41759
|
const handleAction = useCallback((actionId) => {
|
|
41545
41760
|
if (isComplete) return;
|
|
41546
|
-
const opponentAction = getOpponentAction(resolved?.opponentStrategy
|
|
41761
|
+
const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
|
|
41547
41762
|
const payoff = payoffMatrix.find(
|
|
41548
41763
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
41549
41764
|
);
|
|
@@ -41556,42 +41771,46 @@ function NegotiatorBoard({
|
|
|
41556
41771
|
};
|
|
41557
41772
|
const newHistory = [...history, result];
|
|
41558
41773
|
setHistory(newHistory);
|
|
41559
|
-
if (newHistory.length >=
|
|
41774
|
+
if (newHistory.length >= totalRounds) {
|
|
41560
41775
|
const total = newHistory.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41561
|
-
if (total >=
|
|
41776
|
+
if (total >= targetScore) {
|
|
41562
41777
|
emit(`UI:${completeEvent}`, { success: true, score: total });
|
|
41563
41778
|
}
|
|
41564
|
-
if (newHistory.length >= 3 && resolved?.hint) {
|
|
41779
|
+
if (newHistory.length >= 3 && str(resolved?.hint)) {
|
|
41565
41780
|
setShowHint(true);
|
|
41566
41781
|
}
|
|
41567
41782
|
}
|
|
41568
|
-
}, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41783
|
+
}, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41569
41784
|
const handleReset = () => {
|
|
41570
41785
|
setHistory([]);
|
|
41571
41786
|
setShowHint(false);
|
|
41572
41787
|
};
|
|
41573
41788
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
41574
41789
|
if (!resolved) return null;
|
|
41790
|
+
const theme = resolved.theme ?? void 0;
|
|
41791
|
+
const themeBackground = theme?.background;
|
|
41792
|
+
const headerImage = str(resolved.headerImage);
|
|
41793
|
+
const hint = str(resolved.hint);
|
|
41575
41794
|
return /* @__PURE__ */ jsx(
|
|
41576
41795
|
Box,
|
|
41577
41796
|
{
|
|
41578
41797
|
className,
|
|
41579
41798
|
style: {
|
|
41580
|
-
backgroundImage:
|
|
41799
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
41581
41800
|
backgroundSize: "cover",
|
|
41582
41801
|
backgroundPosition: "center"
|
|
41583
41802
|
},
|
|
41584
41803
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
41585
|
-
|
|
41804
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
41586
41805
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
41587
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
41588
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
41806
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
41807
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
41589
41808
|
/* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
|
|
41590
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(
|
|
41809
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
|
|
41591
41810
|
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
41592
41811
|
t("negotiator.target"),
|
|
41593
41812
|
": ",
|
|
41594
|
-
|
|
41813
|
+
targetScore
|
|
41595
41814
|
] })
|
|
41596
41815
|
] })
|
|
41597
41816
|
] }) }),
|
|
@@ -41640,16 +41859,16 @@ function NegotiatorBoard({
|
|
|
41640
41859
|
] }) }),
|
|
41641
41860
|
isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
41642
41861
|
/* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
|
|
41643
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage
|
|
41862
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
|
|
41644
41863
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
41645
41864
|
t("negotiator.finalScore"),
|
|
41646
41865
|
": ",
|
|
41647
41866
|
playerTotal,
|
|
41648
41867
|
"/",
|
|
41649
|
-
|
|
41868
|
+
targetScore
|
|
41650
41869
|
] })
|
|
41651
41870
|
] }) }),
|
|
41652
|
-
showHint &&
|
|
41871
|
+
showHint && hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
41653
41872
|
isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
41654
41873
|
] })
|
|
41655
41874
|
}
|
|
@@ -41659,6 +41878,7 @@ var init_NegotiatorBoard = __esm({
|
|
|
41659
41878
|
"components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
|
|
41660
41879
|
init_atoms2();
|
|
41661
41880
|
init_useEventBus();
|
|
41881
|
+
init_boardEntity();
|
|
41662
41882
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
41663
41883
|
}
|
|
41664
41884
|
});
|
|
@@ -41694,13 +41914,13 @@ var init_PricingOrganism = __esm({
|
|
|
41694
41914
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
41695
41915
|
}
|
|
41696
41916
|
const plans = items.map((plan) => ({
|
|
41697
|
-
name: plan.name,
|
|
41698
|
-
price: plan.price,
|
|
41699
|
-
description: plan.description,
|
|
41700
|
-
features: plan.features,
|
|
41701
|
-
action: { label: plan.actionLabel, href: plan.actionHref },
|
|
41702
|
-
highlighted: plan.highlighted,
|
|
41703
|
-
badge: plan.badge
|
|
41917
|
+
name: String(plan.name ?? ""),
|
|
41918
|
+
price: String(plan.price ?? ""),
|
|
41919
|
+
description: plan.description != null ? String(plan.description) : void 0,
|
|
41920
|
+
features: (plan.features ?? []).map((f3) => String(f3)),
|
|
41921
|
+
action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
|
|
41922
|
+
highlighted: Boolean(plan.highlighted),
|
|
41923
|
+
badge: plan.badge != null ? String(plan.badge) : void 0
|
|
41704
41924
|
}));
|
|
41705
41925
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
41706
41926
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -43771,16 +43991,20 @@ function SequencerBoard({
|
|
|
43771
43991
|
}) {
|
|
43772
43992
|
const { emit } = useEventBus();
|
|
43773
43993
|
const { t } = useTranslate();
|
|
43774
|
-
const resolved =
|
|
43994
|
+
const resolved = boardEntity(entity);
|
|
43995
|
+
const maxSlots = num(resolved?.maxSlots);
|
|
43996
|
+
const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
|
|
43997
|
+
const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
|
|
43998
|
+
const allowDuplicates = resolved?.allowDuplicates !== false;
|
|
43775
43999
|
const [headerError, setHeaderError] = useState(false);
|
|
43776
44000
|
const [slots, setSlots] = useState(
|
|
43777
|
-
() => Array.from({ length:
|
|
44001
|
+
() => Array.from({ length: maxSlots }, () => void 0)
|
|
43778
44002
|
);
|
|
43779
44003
|
const [playState, setPlayState] = useState("idle");
|
|
43780
44004
|
const [currentStep, setCurrentStep] = useState(-1);
|
|
43781
44005
|
const [attempts, setAttempts] = useState(0);
|
|
43782
44006
|
const [slotFeedback, setSlotFeedback] = useState(
|
|
43783
|
-
() => Array.from({ length:
|
|
44007
|
+
() => Array.from({ length: maxSlots }, () => null)
|
|
43784
44008
|
);
|
|
43785
44009
|
const timerRef = useRef(null);
|
|
43786
44010
|
useEffect(() => () => {
|
|
@@ -43814,17 +44038,17 @@ function SequencerBoard({
|
|
|
43814
44038
|
}, [emit]);
|
|
43815
44039
|
const handleReset = useCallback(() => {
|
|
43816
44040
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
43817
|
-
setSlots(Array.from({ length:
|
|
44041
|
+
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
43818
44042
|
setPlayState("idle");
|
|
43819
44043
|
setCurrentStep(-1);
|
|
43820
44044
|
setAttempts(0);
|
|
43821
|
-
setSlotFeedback(Array.from({ length:
|
|
43822
|
-
}, [
|
|
44045
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
44046
|
+
}, [maxSlots]);
|
|
43823
44047
|
const filledSlots = slots.filter((s) => !!s);
|
|
43824
44048
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
43825
44049
|
const handlePlay = useCallback(() => {
|
|
43826
44050
|
if (!canPlay) return;
|
|
43827
|
-
setSlotFeedback(Array.from({ length:
|
|
44051
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
43828
44052
|
emit("UI:PLAY_SOUND", { key: "confirm" });
|
|
43829
44053
|
const sequence = slots.map((s) => s?.id || "");
|
|
43830
44054
|
if (playEvent) {
|
|
@@ -43835,10 +44059,10 @@ function SequencerBoard({
|
|
|
43835
44059
|
let step = 0;
|
|
43836
44060
|
const advance = () => {
|
|
43837
44061
|
step++;
|
|
43838
|
-
if (step >=
|
|
44062
|
+
if (step >= maxSlots) {
|
|
43839
44063
|
const playerSeq = slots.map((s) => s?.id);
|
|
43840
44064
|
const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
|
|
43841
|
-
const success =
|
|
44065
|
+
const success = solutions.some(
|
|
43842
44066
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
43843
44067
|
);
|
|
43844
44068
|
if (success) {
|
|
@@ -43850,7 +44074,7 @@ function SequencerBoard({
|
|
|
43850
44074
|
}
|
|
43851
44075
|
} else {
|
|
43852
44076
|
setAttempts((prev) => prev + 1);
|
|
43853
|
-
const feedback = computeSlotFeedback(playerSeq,
|
|
44077
|
+
const feedback = computeSlotFeedback(playerSeq, solutions);
|
|
43854
44078
|
setSlotFeedback(feedback);
|
|
43855
44079
|
setPlayState("idle");
|
|
43856
44080
|
setCurrentStep(-1);
|
|
@@ -43868,10 +44092,10 @@ function SequencerBoard({
|
|
|
43868
44092
|
}
|
|
43869
44093
|
};
|
|
43870
44094
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
43871
|
-
}, [canPlay, slots,
|
|
44095
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
43872
44096
|
const machine = {
|
|
43873
|
-
name: resolved?.title
|
|
43874
|
-
description: resolved?.description
|
|
44097
|
+
name: str(resolved?.title),
|
|
44098
|
+
description: str(resolved?.description),
|
|
43875
44099
|
states: slots.map((s, i) => stepLabel(s, i)),
|
|
43876
44100
|
currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
|
|
43877
44101
|
transitions: slots.slice(0, -1).map((s, i) => ({
|
|
@@ -43880,37 +44104,41 @@ function SequencerBoard({
|
|
|
43880
44104
|
event: "NEXT"
|
|
43881
44105
|
}))
|
|
43882
44106
|
};
|
|
43883
|
-
const usedIds =
|
|
43884
|
-
const
|
|
44107
|
+
const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
|
|
44108
|
+
const hint = str(resolved?.hint);
|
|
44109
|
+
const showHint = attempts >= 3 && !!hint;
|
|
43885
44110
|
const hasFeedback = slotFeedback.some((f3) => f3 !== null);
|
|
43886
44111
|
const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
|
|
43887
44112
|
const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
|
|
43888
44113
|
if (!resolved) return null;
|
|
44114
|
+
const theme = resolved.theme ?? void 0;
|
|
44115
|
+
const themeBackground = theme?.background;
|
|
44116
|
+
const headerImage = str(resolved.headerImage);
|
|
43889
44117
|
return /* @__PURE__ */ jsxs(
|
|
43890
44118
|
VStack,
|
|
43891
44119
|
{
|
|
43892
44120
|
className: cn("p-4 gap-6", className),
|
|
43893
44121
|
style: {
|
|
43894
|
-
backgroundImage:
|
|
44122
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
43895
44123
|
backgroundSize: "cover",
|
|
43896
44124
|
backgroundPosition: "center"
|
|
43897
44125
|
},
|
|
43898
44126
|
children: [
|
|
43899
|
-
|
|
44127
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
43900
44128
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
43901
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
43902
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
|
|
44129
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
44130
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
|
|
43903
44131
|
] }),
|
|
43904
44132
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
43905
44133
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
43906
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
44134
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
43907
44135
|
] }) }),
|
|
43908
44136
|
filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
43909
44137
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
43910
44138
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
43911
44139
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
43912
44140
|
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
43913
|
-
`${correctCount}/${
|
|
44141
|
+
`${correctCount}/${maxSlots} `,
|
|
43914
44142
|
"\u2705"
|
|
43915
44143
|
] })
|
|
43916
44144
|
] }),
|
|
@@ -43918,7 +44146,7 @@ function SequencerBoard({
|
|
|
43918
44146
|
SequenceBar,
|
|
43919
44147
|
{
|
|
43920
44148
|
slots,
|
|
43921
|
-
maxSlots
|
|
44149
|
+
maxSlots,
|
|
43922
44150
|
onSlotDrop: handleSlotDrop,
|
|
43923
44151
|
onSlotRemove: handleSlotRemove,
|
|
43924
44152
|
playing: playState === "playing",
|
|
@@ -43932,15 +44160,15 @@ function SequencerBoard({
|
|
|
43932
44160
|
playState !== "playing" && /* @__PURE__ */ jsx(
|
|
43933
44161
|
ActionPalette,
|
|
43934
44162
|
{
|
|
43935
|
-
actions:
|
|
44163
|
+
actions: availableActions,
|
|
43936
44164
|
usedActionIds: usedIds,
|
|
43937
|
-
allowDuplicates
|
|
44165
|
+
allowDuplicates,
|
|
43938
44166
|
categoryColors,
|
|
43939
44167
|
label: t("sequencer.dragActions")
|
|
43940
44168
|
}
|
|
43941
44169
|
),
|
|
43942
44170
|
hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
|
|
43943
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("sequencer.levelComplete") }) }),
|
|
44171
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("sequencer.levelComplete") }) }),
|
|
43944
44172
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
43945
44173
|
/* @__PURE__ */ jsx(
|
|
43946
44174
|
Button,
|
|
@@ -43964,6 +44192,7 @@ var init_SequencerBoard = __esm({
|
|
|
43964
44192
|
init_cn();
|
|
43965
44193
|
init_useEventBus();
|
|
43966
44194
|
init_TraitStateViewer();
|
|
44195
|
+
init_boardEntity();
|
|
43967
44196
|
init_SequenceBar();
|
|
43968
44197
|
init_ActionPalette();
|
|
43969
44198
|
ENCOURAGEMENT_KEYS2 = [
|
|
@@ -44013,18 +44242,21 @@ var init_ShowcaseOrganism = __esm({
|
|
|
44013
44242
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
44014
44243
|
subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
|
|
44015
44244
|
] }),
|
|
44016
|
-
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) =>
|
|
44017
|
-
|
|
44018
|
-
|
|
44019
|
-
|
|
44020
|
-
|
|
44021
|
-
|
|
44022
|
-
|
|
44023
|
-
|
|
44024
|
-
|
|
44025
|
-
|
|
44026
|
-
|
|
44027
|
-
|
|
44245
|
+
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
|
|
44246
|
+
const imageRaw = item.image;
|
|
44247
|
+
return /* @__PURE__ */ jsx(
|
|
44248
|
+
ShowcaseCard,
|
|
44249
|
+
{
|
|
44250
|
+
title: String(item.title ?? ""),
|
|
44251
|
+
description: item.description != null ? String(item.description) : void 0,
|
|
44252
|
+
image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
|
|
44253
|
+
href: item.href != null ? String(item.href) : void 0,
|
|
44254
|
+
badge: item.badge != null ? String(item.badge) : void 0,
|
|
44255
|
+
accentColor: item.accentColor != null ? String(item.accentColor) : void 0
|
|
44256
|
+
},
|
|
44257
|
+
String(item.id ?? "")
|
|
44258
|
+
);
|
|
44259
|
+
}) })
|
|
44028
44260
|
] });
|
|
44029
44261
|
};
|
|
44030
44262
|
ShowcaseOrganism.displayName = "ShowcaseOrganism";
|
|
@@ -44392,8 +44624,8 @@ function SimulatorBoard({
|
|
|
44392
44624
|
}) {
|
|
44393
44625
|
const { emit } = useEventBus();
|
|
44394
44626
|
const { t } = useTranslate();
|
|
44395
|
-
const resolved =
|
|
44396
|
-
const parameters = resolved?.parameters
|
|
44627
|
+
const resolved = boardEntity(entity);
|
|
44628
|
+
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
44397
44629
|
const [values, setValues] = useState(() => {
|
|
44398
44630
|
const init = {};
|
|
44399
44631
|
for (const p2 of parameters) {
|
|
@@ -44407,15 +44639,15 @@ function SimulatorBoard({
|
|
|
44407
44639
|
const [showHint, setShowHint] = useState(false);
|
|
44408
44640
|
const computeOutput = useCallback((params) => {
|
|
44409
44641
|
try {
|
|
44410
|
-
const fn = new Function("params", `return (${resolved?.computeExpression})`);
|
|
44642
|
+
const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
|
|
44411
44643
|
return fn(params);
|
|
44412
44644
|
} catch {
|
|
44413
44645
|
return 0;
|
|
44414
44646
|
}
|
|
44415
44647
|
}, [resolved?.computeExpression]);
|
|
44416
44648
|
const output = useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
|
|
44417
|
-
const targetValue = resolved?.targetValue
|
|
44418
|
-
const targetTolerance = resolved?.targetTolerance
|
|
44649
|
+
const targetValue = num(resolved?.targetValue);
|
|
44650
|
+
const targetTolerance = num(resolved?.targetTolerance);
|
|
44419
44651
|
const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
|
|
44420
44652
|
const handleParameterChange = (id, value) => {
|
|
44421
44653
|
if (submitted) return;
|
|
@@ -44430,7 +44662,7 @@ function SimulatorBoard({
|
|
|
44430
44662
|
};
|
|
44431
44663
|
const handleReset = () => {
|
|
44432
44664
|
setSubmitted(false);
|
|
44433
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
44665
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
44434
44666
|
setShowHint(true);
|
|
44435
44667
|
}
|
|
44436
44668
|
};
|
|
@@ -44445,20 +44677,26 @@ function SimulatorBoard({
|
|
|
44445
44677
|
setShowHint(false);
|
|
44446
44678
|
};
|
|
44447
44679
|
if (!resolved) return null;
|
|
44680
|
+
const theme = resolved.theme ?? void 0;
|
|
44681
|
+
const themeBackground = theme?.background;
|
|
44682
|
+
const headerImage = str(resolved.headerImage);
|
|
44683
|
+
const hint = str(resolved.hint);
|
|
44684
|
+
const outputLabel = str(resolved.outputLabel);
|
|
44685
|
+
const outputUnit = str(resolved.outputUnit);
|
|
44448
44686
|
return /* @__PURE__ */ jsx(
|
|
44449
44687
|
Box,
|
|
44450
44688
|
{
|
|
44451
44689
|
className,
|
|
44452
44690
|
style: {
|
|
44453
|
-
backgroundImage:
|
|
44691
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44454
44692
|
backgroundSize: "cover",
|
|
44455
44693
|
backgroundPosition: "center"
|
|
44456
44694
|
},
|
|
44457
44695
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
44458
|
-
|
|
44696
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44459
44697
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44460
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
44461
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
44698
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
44699
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
44462
44700
|
] }) }),
|
|
44463
44701
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
44464
44702
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
@@ -44499,28 +44737,28 @@ function SimulatorBoard({
|
|
|
44499
44737
|
] }, param.id))
|
|
44500
44738
|
] }) }),
|
|
44501
44739
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
44502
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children:
|
|
44740
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
44503
44741
|
/* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
44504
44742
|
output.toFixed(2),
|
|
44505
44743
|
" ",
|
|
44506
|
-
|
|
44744
|
+
outputUnit
|
|
44507
44745
|
] }),
|
|
44508
44746
|
submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
44509
44747
|
/* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
|
|
44510
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage
|
|
44748
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
44511
44749
|
] }),
|
|
44512
44750
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
44513
44751
|
t("simulator.target"),
|
|
44514
44752
|
": ",
|
|
44515
44753
|
targetValue,
|
|
44516
44754
|
" ",
|
|
44517
|
-
|
|
44755
|
+
outputUnit,
|
|
44518
44756
|
" (\xB1",
|
|
44519
44757
|
targetTolerance,
|
|
44520
44758
|
")"
|
|
44521
44759
|
] })
|
|
44522
44760
|
] }) }),
|
|
44523
|
-
showHint &&
|
|
44761
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
44524
44762
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
44525
44763
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
44526
44764
|
/* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
|
|
@@ -44539,6 +44777,7 @@ var init_SimulatorBoard = __esm({
|
|
|
44539
44777
|
"components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
|
|
44540
44778
|
init_atoms2();
|
|
44541
44779
|
init_useEventBus();
|
|
44780
|
+
init_boardEntity();
|
|
44542
44781
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
44543
44782
|
}
|
|
44544
44783
|
});
|
|
@@ -44964,22 +45203,25 @@ function VariablePanel({
|
|
|
44964
45203
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
44965
45204
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
|
|
44966
45205
|
variables.map((v) => {
|
|
44967
|
-
const
|
|
44968
|
-
const
|
|
44969
|
-
const
|
|
45206
|
+
const name = v.name == null ? "" : String(v.name);
|
|
45207
|
+
const value = numField(v.value);
|
|
45208
|
+
const max = numField(v.max, 100);
|
|
45209
|
+
const min = numField(v.min, 0);
|
|
45210
|
+
const unit = v.unit == null ? "" : String(v.unit);
|
|
45211
|
+
const pct = Math.round((value - min) / (max - min) * 100);
|
|
44970
45212
|
const isHigh = pct > 80;
|
|
44971
45213
|
const isLow = pct < 20;
|
|
44972
45214
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
44973
45215
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
44974
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children:
|
|
45216
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
|
|
44975
45217
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: cn(
|
|
44976
45218
|
isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
|
|
44977
45219
|
), children: [
|
|
44978
|
-
|
|
44979
|
-
|
|
45220
|
+
value,
|
|
45221
|
+
unit,
|
|
44980
45222
|
" / ",
|
|
44981
45223
|
max,
|
|
44982
|
-
|
|
45224
|
+
unit
|
|
44983
45225
|
] })
|
|
44984
45226
|
] }),
|
|
44985
45227
|
/* @__PURE__ */ jsx(
|
|
@@ -44990,14 +45232,19 @@ function VariablePanel({
|
|
|
44990
45232
|
size: "sm"
|
|
44991
45233
|
}
|
|
44992
45234
|
)
|
|
44993
|
-
] },
|
|
45235
|
+
] }, name);
|
|
44994
45236
|
})
|
|
44995
45237
|
] });
|
|
44996
45238
|
}
|
|
45239
|
+
var numField;
|
|
44997
45240
|
var init_VariablePanel = __esm({
|
|
44998
45241
|
"components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
|
|
44999
45242
|
init_atoms2();
|
|
45000
45243
|
init_cn();
|
|
45244
|
+
numField = (v, fallback = 0) => {
|
|
45245
|
+
const n = Number(v);
|
|
45246
|
+
return Number.isFinite(n) ? n : fallback;
|
|
45247
|
+
};
|
|
45001
45248
|
VariablePanel.displayName = "VariablePanel";
|
|
45002
45249
|
}
|
|
45003
45250
|
});
|
|
@@ -45024,14 +45271,21 @@ function StateArchitectBoard({
|
|
|
45024
45271
|
}) {
|
|
45025
45272
|
const { emit } = useEventBus();
|
|
45026
45273
|
const { t } = useTranslate();
|
|
45027
|
-
const resolved =
|
|
45028
|
-
const
|
|
45274
|
+
const resolved = boardEntity(entity);
|
|
45275
|
+
const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
|
|
45276
|
+
const initialState = str(resolved?.initialState);
|
|
45277
|
+
const entityName = str(resolved?.entityName);
|
|
45278
|
+
const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
|
|
45279
|
+
const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
|
|
45280
|
+
const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
|
|
45281
|
+
const entityVariables = rows(resolved?.variables);
|
|
45282
|
+
const [transitions, setTransitions] = useState(entityTransitions);
|
|
45029
45283
|
const [headerError, setHeaderError] = useState(false);
|
|
45030
45284
|
const [playState, setPlayState] = useState("editing");
|
|
45031
|
-
const [currentState, setCurrentState] = useState(
|
|
45285
|
+
const [currentState, setCurrentState] = useState(initialState);
|
|
45032
45286
|
const [selectedState, setSelectedState] = useState(null);
|
|
45033
45287
|
const [testResults, setTestResults] = useState([]);
|
|
45034
|
-
const [variables, setVariables] = useState(
|
|
45288
|
+
const [variables, setVariables] = useState(() => [...entityVariables]);
|
|
45035
45289
|
const [attempts, setAttempts] = useState(0);
|
|
45036
45290
|
const timerRef = useRef(null);
|
|
45037
45291
|
const [addingFrom, setAddingFrom] = useState(null);
|
|
@@ -45040,12 +45294,12 @@ function StateArchitectBoard({
|
|
|
45040
45294
|
}, []);
|
|
45041
45295
|
const GRAPH_W = 500;
|
|
45042
45296
|
const GRAPH_H = 400;
|
|
45043
|
-
const positions = useMemo(() => layoutStates(
|
|
45297
|
+
const positions = useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
|
|
45044
45298
|
const handleStateClick = useCallback((state) => {
|
|
45045
45299
|
if (playState !== "editing") return;
|
|
45046
45300
|
if (addingFrom) {
|
|
45047
45301
|
if (addingFrom !== state) {
|
|
45048
|
-
const event =
|
|
45302
|
+
const event = availableEvents[0] || "EVENT";
|
|
45049
45303
|
const newTrans = {
|
|
45050
45304
|
id: `t-${nextTransId++}`,
|
|
45051
45305
|
from: addingFrom,
|
|
@@ -45058,7 +45312,7 @@ function StateArchitectBoard({
|
|
|
45058
45312
|
} else {
|
|
45059
45313
|
setSelectedState(state);
|
|
45060
45314
|
}
|
|
45061
|
-
}, [playState, addingFrom,
|
|
45315
|
+
}, [playState, addingFrom, availableEvents]);
|
|
45062
45316
|
const handleStartAddTransition = useCallback(() => {
|
|
45063
45317
|
if (!selectedState) return;
|
|
45064
45318
|
setAddingFrom(selectedState);
|
|
@@ -45067,9 +45321,9 @@ function StateArchitectBoard({
|
|
|
45067
45321
|
setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
|
|
45068
45322
|
}, []);
|
|
45069
45323
|
const machine = useMemo(() => ({
|
|
45070
|
-
name:
|
|
45071
|
-
description: resolved?.description
|
|
45072
|
-
states:
|
|
45324
|
+
name: entityName,
|
|
45325
|
+
description: str(resolved?.description),
|
|
45326
|
+
states: entityStates,
|
|
45073
45327
|
currentState,
|
|
45074
45328
|
transitions: transitions.map((t2) => ({
|
|
45075
45329
|
from: t2.from,
|
|
@@ -45077,7 +45331,7 @@ function StateArchitectBoard({
|
|
|
45077
45331
|
event: t2.event,
|
|
45078
45332
|
guardHint: t2.guardHint
|
|
45079
45333
|
}))
|
|
45080
|
-
}), [resolved, currentState, transitions]);
|
|
45334
|
+
}), [entityName, resolved, entityStates, currentState, transitions]);
|
|
45081
45335
|
const handleTest = useCallback(() => {
|
|
45082
45336
|
if (playState !== "editing") return;
|
|
45083
45337
|
if (testEvent) emit(`UI:${testEvent}`, {});
|
|
@@ -45086,7 +45340,7 @@ function StateArchitectBoard({
|
|
|
45086
45340
|
const results = [];
|
|
45087
45341
|
let testIdx = 0;
|
|
45088
45342
|
const runNextTest = () => {
|
|
45089
|
-
if (testIdx >=
|
|
45343
|
+
if (testIdx >= testCases.length) {
|
|
45090
45344
|
const allPassed = results.every((r) => r.passed);
|
|
45091
45345
|
setPlayState(allPassed ? "success" : "fail");
|
|
45092
45346
|
setTestResults(results);
|
|
@@ -45101,9 +45355,9 @@ function StateArchitectBoard({
|
|
|
45101
45355
|
}
|
|
45102
45356
|
return;
|
|
45103
45357
|
}
|
|
45104
|
-
const testCase =
|
|
45358
|
+
const testCase = testCases[testIdx];
|
|
45105
45359
|
if (!testCase) return;
|
|
45106
|
-
let state =
|
|
45360
|
+
let state = initialState;
|
|
45107
45361
|
for (const event of testCase.events) {
|
|
45108
45362
|
const trans = transitions.find((t2) => t2.from === state && t2.event === event);
|
|
45109
45363
|
if (trans) {
|
|
@@ -45121,53 +45375,57 @@ function StateArchitectBoard({
|
|
|
45121
45375
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
45122
45376
|
};
|
|
45123
45377
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
45124
|
-
}, [playState, transitions,
|
|
45378
|
+
}, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
|
|
45125
45379
|
const handleTryAgain = useCallback(() => {
|
|
45126
45380
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
45127
45381
|
setPlayState("editing");
|
|
45128
|
-
setCurrentState(
|
|
45382
|
+
setCurrentState(initialState);
|
|
45129
45383
|
setTestResults([]);
|
|
45130
|
-
}, [
|
|
45384
|
+
}, [initialState]);
|
|
45131
45385
|
const handleReset = useCallback(() => {
|
|
45132
45386
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
45133
|
-
setTransitions(
|
|
45387
|
+
setTransitions(entityTransitions);
|
|
45134
45388
|
setPlayState("editing");
|
|
45135
|
-
setCurrentState(
|
|
45389
|
+
setCurrentState(initialState);
|
|
45136
45390
|
setTestResults([]);
|
|
45137
|
-
setVariables(
|
|
45391
|
+
setVariables([...entityVariables]);
|
|
45138
45392
|
setSelectedState(null);
|
|
45139
45393
|
setAddingFrom(null);
|
|
45140
45394
|
setAttempts(0);
|
|
45141
|
-
}, [
|
|
45395
|
+
}, [entityTransitions, initialState, entityVariables]);
|
|
45142
45396
|
const codeData = useMemo(() => ({
|
|
45143
|
-
name:
|
|
45144
|
-
states:
|
|
45145
|
-
initialState
|
|
45397
|
+
name: entityName,
|
|
45398
|
+
states: entityStates,
|
|
45399
|
+
initialState,
|
|
45146
45400
|
transitions: transitions.map((t2) => ({
|
|
45147
45401
|
from: t2.from,
|
|
45148
45402
|
to: t2.to,
|
|
45149
45403
|
event: t2.event,
|
|
45150
45404
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
45151
45405
|
}))
|
|
45152
|
-
}), [
|
|
45406
|
+
}), [entityName, entityStates, initialState, transitions]);
|
|
45153
45407
|
if (!resolved) return null;
|
|
45408
|
+
const theme = resolved.theme ?? void 0;
|
|
45409
|
+
const themeBackground = theme?.background;
|
|
45410
|
+
const headerImage = str(resolved.headerImage);
|
|
45411
|
+
const hint = str(resolved.hint);
|
|
45154
45412
|
return /* @__PURE__ */ jsxs(
|
|
45155
45413
|
VStack,
|
|
45156
45414
|
{
|
|
45157
45415
|
className: cn("p-4 gap-6", className),
|
|
45158
45416
|
style: {
|
|
45159
|
-
backgroundImage:
|
|
45417
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
45160
45418
|
backgroundSize: "cover",
|
|
45161
45419
|
backgroundPosition: "center"
|
|
45162
45420
|
},
|
|
45163
45421
|
children: [
|
|
45164
|
-
|
|
45422
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
45165
45423
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
45166
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
45167
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
45424
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
45425
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
45168
45426
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
45169
45427
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
45170
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children:
|
|
45428
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
|
|
45171
45429
|
] })
|
|
45172
45430
|
] }),
|
|
45173
45431
|
/* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
@@ -45215,14 +45473,14 @@ function StateArchitectBoard({
|
|
|
45215
45473
|
]
|
|
45216
45474
|
}
|
|
45217
45475
|
),
|
|
45218
|
-
|
|
45476
|
+
entityStates.map((state) => /* @__PURE__ */ jsx(
|
|
45219
45477
|
StateNode2,
|
|
45220
45478
|
{
|
|
45221
45479
|
name: state,
|
|
45222
45480
|
position: positions[state],
|
|
45223
45481
|
isCurrent: state === currentState,
|
|
45224
45482
|
isSelected: state === selectedState,
|
|
45225
|
-
isInitial: state ===
|
|
45483
|
+
isInitial: state === initialState,
|
|
45226
45484
|
onClick: () => handleStateClick(state)
|
|
45227
45485
|
},
|
|
45228
45486
|
state
|
|
@@ -45269,7 +45527,7 @@ function StateArchitectBoard({
|
|
|
45269
45527
|
/* @__PURE__ */ jsx(
|
|
45270
45528
|
VariablePanel,
|
|
45271
45529
|
{
|
|
45272
|
-
entityName
|
|
45530
|
+
entityName,
|
|
45273
45531
|
variables
|
|
45274
45532
|
}
|
|
45275
45533
|
),
|
|
@@ -45284,12 +45542,12 @@ function StateArchitectBoard({
|
|
|
45284
45542
|
resolved.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
|
|
45285
45543
|
] })
|
|
45286
45544
|
] }),
|
|
45287
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("stateArchitect.allPassed") }) }),
|
|
45545
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
|
|
45288
45546
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
45289
45547
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(ENCOURAGEMENT_KEYS3[Math.min(attempts - 1, ENCOURAGEMENT_KEYS3.length - 1)] ?? ENCOURAGEMENT_KEYS3[0]) }) }),
|
|
45290
|
-
attempts >= 3 &&
|
|
45548
|
+
attempts >= 3 && hint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
45291
45549
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
45292
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
45550
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
45293
45551
|
] }) })
|
|
45294
45552
|
] }),
|
|
45295
45553
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -45319,6 +45577,7 @@ var init_StateArchitectBoard = __esm({
|
|
|
45319
45577
|
init_TransitionArrow();
|
|
45320
45578
|
init_VariablePanel();
|
|
45321
45579
|
init_CodeView();
|
|
45580
|
+
init_boardEntity();
|
|
45322
45581
|
ENCOURAGEMENT_KEYS3 = [
|
|
45323
45582
|
"puzzle.tryAgain1",
|
|
45324
45583
|
"puzzle.tryAgain2",
|
|
@@ -45355,8 +45614,8 @@ var init_StatsOrganism = __esm({
|
|
|
45355
45614
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
45356
45615
|
}
|
|
45357
45616
|
const stats = items.map((item) => ({
|
|
45358
|
-
value: item.value,
|
|
45359
|
-
label: item.label
|
|
45617
|
+
value: String(item.value ?? ""),
|
|
45618
|
+
label: String(item.label ?? "")
|
|
45360
45619
|
}));
|
|
45361
45620
|
return /* @__PURE__ */ jsx(
|
|
45362
45621
|
StatsGrid,
|
|
@@ -45402,10 +45661,10 @@ var init_StepFlowOrganism = __esm({
|
|
|
45402
45661
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
45403
45662
|
}
|
|
45404
45663
|
const steps = items.map((item) => ({
|
|
45405
|
-
number: item.number,
|
|
45406
|
-
title: item.title,
|
|
45407
|
-
description: item.description,
|
|
45408
|
-
icon: item.icon
|
|
45664
|
+
number: item.number != null ? Number(item.number) : void 0,
|
|
45665
|
+
title: String(item.title ?? ""),
|
|
45666
|
+
description: String(item.description ?? ""),
|
|
45667
|
+
icon: item.icon != null ? String(item.icon) : void 0
|
|
45409
45668
|
}));
|
|
45410
45669
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
45411
45670
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -45578,13 +45837,13 @@ var init_TeamOrganism = __esm({
|
|
|
45578
45837
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsx(
|
|
45579
45838
|
TeamCard,
|
|
45580
45839
|
{
|
|
45581
|
-
name: member.name,
|
|
45582
|
-
nameAr: member.nameAr,
|
|
45583
|
-
role: member.role,
|
|
45584
|
-
bio: member.bio,
|
|
45585
|
-
avatar: member.avatar
|
|
45840
|
+
name: String(member.name ?? ""),
|
|
45841
|
+
nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
|
|
45842
|
+
role: String(member.role ?? ""),
|
|
45843
|
+
bio: String(member.bio ?? ""),
|
|
45844
|
+
avatar: member.avatar != null ? String(member.avatar) : void 0
|
|
45586
45845
|
},
|
|
45587
|
-
member.id
|
|
45846
|
+
String(member.id ?? "")
|
|
45588
45847
|
)) })
|
|
45589
45848
|
] });
|
|
45590
45849
|
};
|
|
@@ -45821,8 +46080,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45821
46080
|
const [turn, setTurn] = useState(1);
|
|
45822
46081
|
const [gameResult, setGameResult] = useState(null);
|
|
45823
46082
|
const checkGameEnd = useCallback((currentUnits) => {
|
|
45824
|
-
const pa = currentUnits.filter((u) => u
|
|
45825
|
-
const ea = currentUnits.filter((u) => u
|
|
46083
|
+
const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
46084
|
+
const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
45826
46085
|
if (pa.length === 0) {
|
|
45827
46086
|
setGameResult("defeat");
|
|
45828
46087
|
setPhase("game_over");
|
|
@@ -45840,34 +46099,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45840
46099
|
}
|
|
45841
46100
|
}, [onGameEnd, gameEndEvent, eventBus]);
|
|
45842
46101
|
const handleUnitClick = useCallback((unitId) => {
|
|
45843
|
-
const unit = units.find((u) => u.id === unitId);
|
|
46102
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
45844
46103
|
if (!unit) return;
|
|
45845
46104
|
if (unitClickEvent) {
|
|
45846
46105
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
45847
46106
|
}
|
|
45848
46107
|
if (phase === "observation" || phase === "selection") {
|
|
45849
|
-
if (unit
|
|
46108
|
+
if (unitTeam(unit) === "player") {
|
|
45850
46109
|
setSelectedUnitId(unitId);
|
|
45851
46110
|
setPhase("movement");
|
|
45852
46111
|
}
|
|
45853
46112
|
} else if (phase === "action") {
|
|
45854
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
46113
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45855
46114
|
if (!selectedUnit) return;
|
|
45856
|
-
if (unit
|
|
45857
|
-
const
|
|
45858
|
-
const
|
|
46115
|
+
if (unitTeam(unit) === "enemy") {
|
|
46116
|
+
const up = unitPosition(unit);
|
|
46117
|
+
const sp = unitPosition(selectedUnit);
|
|
46118
|
+
const dx = Math.abs(up.x - sp.x);
|
|
46119
|
+
const dy = Math.abs(up.y - sp.y);
|
|
45859
46120
|
if (dx <= 1 && dy <= 1 && dx + dy > 0) {
|
|
45860
|
-
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
45861
|
-
const newHealth = Math.max(0, unit
|
|
46121
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
46122
|
+
const newHealth = Math.max(0, unitHealth(unit) - damage);
|
|
45862
46123
|
const updatedUnits = units.map(
|
|
45863
|
-
(u) => u.id === unit.id ? { ...u, health: newHealth } : u
|
|
46124
|
+
(u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
|
|
45864
46125
|
);
|
|
45865
46126
|
setUnits(updatedUnits);
|
|
45866
46127
|
onAttack?.(selectedUnit, unit, damage);
|
|
45867
46128
|
if (attackEvent) {
|
|
45868
46129
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
45869
|
-
attackerId: selectedUnit.id,
|
|
45870
|
-
targetId: unit.id,
|
|
46130
|
+
attackerId: str(selectedUnit.id),
|
|
46131
|
+
targetId: str(unit.id),
|
|
45871
46132
|
damage
|
|
45872
46133
|
});
|
|
45873
46134
|
}
|
|
@@ -45884,16 +46145,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45884
46145
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
45885
46146
|
}
|
|
45886
46147
|
if (phase === "movement" && selectedUnitId) {
|
|
45887
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
46148
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45888
46149
|
if (!selectedUnit) return;
|
|
45889
|
-
const
|
|
45890
|
-
const
|
|
46150
|
+
const sp = unitPosition(selectedUnit);
|
|
46151
|
+
const dx = Math.abs(x - sp.x);
|
|
46152
|
+
const dy = Math.abs(y - sp.y);
|
|
45891
46153
|
const dist = dx + dy;
|
|
45892
|
-
if (dist > 0 && dist <= selectedUnit.movement) {
|
|
45893
|
-
if (!units.some((u) =>
|
|
46154
|
+
if (dist > 0 && dist <= num(selectedUnit.movement)) {
|
|
46155
|
+
if (!units.some((u) => {
|
|
46156
|
+
const p2 = unitPosition(u);
|
|
46157
|
+
return p2.x === x && p2.y === y && unitHealth(u) > 0;
|
|
46158
|
+
})) {
|
|
45894
46159
|
setUnits(
|
|
45895
46160
|
(prev) => prev.map(
|
|
45896
|
-
(u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
46161
|
+
(u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
45897
46162
|
)
|
|
45898
46163
|
);
|
|
45899
46164
|
setPhase("action");
|
|
@@ -45936,12 +46201,13 @@ var init_useBattleState = __esm({
|
|
|
45936
46201
|
"components/game/organisms/hooks/useBattleState.ts"() {
|
|
45937
46202
|
"use client";
|
|
45938
46203
|
init_useEventBus();
|
|
46204
|
+
init_boardEntity();
|
|
45939
46205
|
}
|
|
45940
46206
|
});
|
|
45941
46207
|
function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
45942
|
-
const resolved =
|
|
46208
|
+
const resolved = boardEntity(entity);
|
|
45943
46209
|
const battleState = useBattleState(
|
|
45944
|
-
resolved?.initialUnits
|
|
46210
|
+
rows(resolved?.initialUnits),
|
|
45945
46211
|
{
|
|
45946
46212
|
tileClickEvent: rest.tileClickEvent,
|
|
45947
46213
|
unitClickEvent: rest.unitClickEvent,
|
|
@@ -45977,10 +46243,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
|
45977
46243
|
var init_UncontrolledBattleBoard = __esm({
|
|
45978
46244
|
"components/game/organisms/UncontrolledBattleBoard.tsx"() {
|
|
45979
46245
|
init_BattleBoard();
|
|
46246
|
+
init_boardEntity();
|
|
45980
46247
|
init_useBattleState();
|
|
45981
46248
|
UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
|
|
45982
46249
|
}
|
|
45983
46250
|
});
|
|
46251
|
+
function heroPosition(h) {
|
|
46252
|
+
return vec2(h.position);
|
|
46253
|
+
}
|
|
46254
|
+
function heroOwner(h) {
|
|
46255
|
+
return str(h.owner);
|
|
46256
|
+
}
|
|
46257
|
+
function heroMovement(h) {
|
|
46258
|
+
return num(h.movement);
|
|
46259
|
+
}
|
|
46260
|
+
function hexPassable(h) {
|
|
46261
|
+
return h.passable !== false;
|
|
46262
|
+
}
|
|
45984
46263
|
function defaultIsInRange(from, to, range) {
|
|
45985
46264
|
return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
|
|
45986
46265
|
}
|
|
@@ -46011,36 +46290,36 @@ function WorldMapBoard({
|
|
|
46011
46290
|
className
|
|
46012
46291
|
}) {
|
|
46013
46292
|
const eventBus = useEventBus();
|
|
46014
|
-
const resolved =
|
|
46015
|
-
const hexes = resolved?.hexes
|
|
46016
|
-
const heroes = resolved?.heroes
|
|
46017
|
-
const features = resolved?.features
|
|
46018
|
-
const selectedHeroId = resolved?.selectedHeroId;
|
|
46293
|
+
const resolved = boardEntity(entity);
|
|
46294
|
+
const hexes = rows(resolved?.hexes);
|
|
46295
|
+
const heroes = rows(resolved?.heroes);
|
|
46296
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
46297
|
+
const selectedHeroId = resolved?.selectedHeroId ?? null;
|
|
46019
46298
|
const assetManifest = resolved?.assetManifest;
|
|
46020
46299
|
const backgroundImage = resolved?.backgroundImage;
|
|
46021
46300
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
46022
46301
|
const selectedHero = useMemo(
|
|
46023
|
-
() => heroes.find((h) => h.id === selectedHeroId) ?? null,
|
|
46302
|
+
() => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
|
|
46024
46303
|
[heroes, selectedHeroId]
|
|
46025
46304
|
);
|
|
46026
46305
|
const tiles = useMemo(
|
|
46027
46306
|
() => hexes.map((hex) => ({
|
|
46028
|
-
x: hex.x,
|
|
46029
|
-
y: hex.y,
|
|
46030
|
-
terrain: hex.terrain,
|
|
46031
|
-
terrainSprite: hex.terrainSprite
|
|
46307
|
+
x: num(hex.x),
|
|
46308
|
+
y: num(hex.y),
|
|
46309
|
+
terrain: str(hex.terrain),
|
|
46310
|
+
terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
|
|
46032
46311
|
})),
|
|
46033
46312
|
[hexes]
|
|
46034
46313
|
);
|
|
46035
46314
|
const baseUnits = useMemo(
|
|
46036
46315
|
() => heroes.map((hero) => ({
|
|
46037
|
-
id: hero.id,
|
|
46038
|
-
position: hero
|
|
46039
|
-
name: hero.name,
|
|
46040
|
-
team: hero
|
|
46316
|
+
id: str(hero.id),
|
|
46317
|
+
position: heroPosition(hero),
|
|
46318
|
+
name: str(hero.name),
|
|
46319
|
+
team: heroOwner(hero) === "enemy" ? "enemy" : "player",
|
|
46041
46320
|
health: 100,
|
|
46042
46321
|
maxHealth: 100,
|
|
46043
|
-
sprite: hero.sprite
|
|
46322
|
+
sprite: hero.sprite == null ? void 0 : str(hero.sprite)
|
|
46044
46323
|
})),
|
|
46045
46324
|
[heroes]
|
|
46046
46325
|
);
|
|
@@ -46081,73 +46360,94 @@ function WorldMapBoard({
|
|
|
46081
46360
|
const isoUnits = useMemo(() => {
|
|
46082
46361
|
if (movingPositions.size === 0) return baseUnits;
|
|
46083
46362
|
return baseUnits.map((u) => {
|
|
46084
|
-
const pos = movingPositions.get(u.id);
|
|
46363
|
+
const pos = u.id == null ? void 0 : movingPositions.get(u.id);
|
|
46085
46364
|
return pos ? { ...u, position: pos } : u;
|
|
46086
46365
|
});
|
|
46087
46366
|
}, [baseUnits, movingPositions]);
|
|
46088
46367
|
const validMoves = useMemo(() => {
|
|
46089
|
-
if (!selectedHero || selectedHero
|
|
46368
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
46369
|
+
const sp = heroPosition(selectedHero);
|
|
46370
|
+
const sOwner = heroOwner(selectedHero);
|
|
46371
|
+
const range = heroMovement(selectedHero);
|
|
46090
46372
|
const moves = [];
|
|
46091
46373
|
hexes.forEach((hex) => {
|
|
46092
|
-
|
|
46093
|
-
|
|
46094
|
-
if (!
|
|
46095
|
-
if (
|
|
46096
|
-
|
|
46374
|
+
const hx = num(hex.x);
|
|
46375
|
+
const hy = num(hex.y);
|
|
46376
|
+
if (!hexPassable(hex)) return;
|
|
46377
|
+
if (hx === sp.x && hy === sp.y) return;
|
|
46378
|
+
if (!isInRange(sp, { x: hx, y: hy }, range)) return;
|
|
46379
|
+
if (heroes.some((h) => {
|
|
46380
|
+
const hp = heroPosition(h);
|
|
46381
|
+
return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
|
|
46382
|
+
})) return;
|
|
46383
|
+
moves.push({ x: hx, y: hy });
|
|
46097
46384
|
});
|
|
46098
46385
|
return moves;
|
|
46099
46386
|
}, [selectedHero, hexes, heroes, isInRange]);
|
|
46100
46387
|
const attackTargets = useMemo(() => {
|
|
46101
|
-
if (!selectedHero || selectedHero
|
|
46102
|
-
|
|
46388
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
46389
|
+
const sp = heroPosition(selectedHero);
|
|
46390
|
+
const sOwner = heroOwner(selectedHero);
|
|
46391
|
+
const range = heroMovement(selectedHero);
|
|
46392
|
+
return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
|
|
46103
46393
|
}, [selectedHero, heroes, isInRange]);
|
|
46104
|
-
const maxY = Math.max(...hexes.map((h) => h.y), 0);
|
|
46394
|
+
const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
|
|
46105
46395
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
46106
46396
|
const tileToScreen = useCallback(
|
|
46107
46397
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
46108
46398
|
[scale, baseOffsetX]
|
|
46109
46399
|
);
|
|
46110
46400
|
const hoveredHex = useMemo(
|
|
46111
|
-
() => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
|
|
46401
|
+
() => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
|
|
46112
46402
|
[hoveredTile, hexes]
|
|
46113
46403
|
);
|
|
46114
46404
|
const hoveredHero = useMemo(
|
|
46115
|
-
() => hoveredTile ? heroes.find((h) =>
|
|
46405
|
+
() => hoveredTile ? heroes.find((h) => {
|
|
46406
|
+
const hp = heroPosition(h);
|
|
46407
|
+
return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
|
|
46408
|
+
}) ?? null : null,
|
|
46116
46409
|
[hoveredTile, heroes]
|
|
46117
46410
|
);
|
|
46118
46411
|
const handleTileClick = useCallback((x, y) => {
|
|
46119
46412
|
if (movementAnimRef.current) return;
|
|
46120
|
-
const hex = hexes.find((h) => h.x === x && h.y === y);
|
|
46413
|
+
const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
|
|
46121
46414
|
if (!hex) return;
|
|
46122
46415
|
if (tileClickEvent) {
|
|
46123
46416
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
46124
46417
|
}
|
|
46125
46418
|
if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
|
|
46126
|
-
|
|
46127
|
-
|
|
46419
|
+
const heroId = str(selectedHero.id);
|
|
46420
|
+
startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
|
|
46421
|
+
onHeroMove?.(heroId, x, y);
|
|
46128
46422
|
if (heroMoveEvent) {
|
|
46129
|
-
eventBus.emit(`UI:${heroMoveEvent}`, { heroId
|
|
46423
|
+
eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
|
|
46130
46424
|
}
|
|
46131
|
-
|
|
46132
|
-
|
|
46425
|
+
const feature = str(hex.feature);
|
|
46426
|
+
if (feature && feature !== "none") {
|
|
46427
|
+
onFeatureEnter?.(heroId, hex);
|
|
46133
46428
|
if (featureEnterEvent) {
|
|
46134
|
-
eventBus.emit(`UI:${featureEnterEvent}`, { heroId
|
|
46429
|
+
eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
|
|
46135
46430
|
}
|
|
46136
46431
|
}
|
|
46137
46432
|
});
|
|
46138
46433
|
return;
|
|
46139
46434
|
}
|
|
46140
|
-
const enemy = heroes.find((h) =>
|
|
46435
|
+
const enemy = heroes.find((h) => {
|
|
46436
|
+
const hp = heroPosition(h);
|
|
46437
|
+
return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
|
|
46438
|
+
});
|
|
46141
46439
|
if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
|
|
46142
|
-
|
|
46440
|
+
const attackerId = str(selectedHero.id);
|
|
46441
|
+
const defenderId = str(enemy.id);
|
|
46442
|
+
onBattleEncounter?.(attackerId, defenderId);
|
|
46143
46443
|
if (battleEncounterEvent) {
|
|
46144
|
-
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId
|
|
46444
|
+
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
|
|
46145
46445
|
}
|
|
46146
46446
|
}
|
|
46147
46447
|
}, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
|
|
46148
46448
|
const handleUnitClick = useCallback((unitId) => {
|
|
46149
|
-
const hero = heroes.find((h) => h.id === unitId);
|
|
46150
|
-
if (hero && (hero
|
|
46449
|
+
const hero = heroes.find((h) => str(h.id) === unitId);
|
|
46450
|
+
if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
|
|
46151
46451
|
onHeroSelect?.(unitId);
|
|
46152
46452
|
if (heroSelectEvent) {
|
|
46153
46453
|
eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
|
|
@@ -46220,6 +46520,7 @@ var init_WorldMapBoard = __esm({
|
|
|
46220
46520
|
init_Stack();
|
|
46221
46521
|
init_LoadingState();
|
|
46222
46522
|
init_IsometricCanvas2();
|
|
46523
|
+
init_boardEntity();
|
|
46223
46524
|
init_isometric();
|
|
46224
46525
|
WorldMapBoard.displayName = "WorldMapBoard";
|
|
46225
46526
|
}
|