@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/avl/index.js
CHANGED
|
@@ -7130,7 +7130,7 @@ var init_SvgGrid = __esm({
|
|
|
7130
7130
|
x,
|
|
7131
7131
|
y,
|
|
7132
7132
|
cols = 4,
|
|
7133
|
-
rows = 3,
|
|
7133
|
+
rows: rows2 = 3,
|
|
7134
7134
|
spacing = 20,
|
|
7135
7135
|
nodeRadius = 3,
|
|
7136
7136
|
color = "var(--color-primary)",
|
|
@@ -7139,7 +7139,7 @@ var init_SvgGrid = __esm({
|
|
|
7139
7139
|
highlights = []
|
|
7140
7140
|
}) => {
|
|
7141
7141
|
const highlightSet = new Set(highlights);
|
|
7142
|
-
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length:
|
|
7142
|
+
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
|
|
7143
7143
|
(_, row) => Array.from({ length: cols }).map((_2, col) => {
|
|
7144
7144
|
const index = row * cols + col;
|
|
7145
7145
|
const isHighlighted = highlightSet.has(index);
|
|
@@ -7799,7 +7799,7 @@ var init_Input = __esm({
|
|
|
7799
7799
|
onClear,
|
|
7800
7800
|
value,
|
|
7801
7801
|
options,
|
|
7802
|
-
rows = 3,
|
|
7802
|
+
rows: rows2 = 3,
|
|
7803
7803
|
onChange,
|
|
7804
7804
|
...props
|
|
7805
7805
|
}, ref) => {
|
|
@@ -7849,7 +7849,7 @@ var init_Input = __esm({
|
|
|
7849
7849
|
ref,
|
|
7850
7850
|
value,
|
|
7851
7851
|
onChange,
|
|
7852
|
-
rows,
|
|
7852
|
+
rows: rows2,
|
|
7853
7853
|
className: baseClassName,
|
|
7854
7854
|
...props
|
|
7855
7855
|
}
|
|
@@ -9844,66 +9844,6 @@ var init_RangeSlider = __esm({
|
|
|
9844
9844
|
RangeSlider.displayName = "RangeSlider";
|
|
9845
9845
|
}
|
|
9846
9846
|
});
|
|
9847
|
-
function easeOut(t) {
|
|
9848
|
-
return t * (2 - t);
|
|
9849
|
-
}
|
|
9850
|
-
var AnimatedCounter;
|
|
9851
|
-
var init_AnimatedCounter = __esm({
|
|
9852
|
-
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
9853
|
-
"use client";
|
|
9854
|
-
init_cn();
|
|
9855
|
-
init_Typography();
|
|
9856
|
-
AnimatedCounter = ({
|
|
9857
|
-
value: rawValue,
|
|
9858
|
-
duration = 600,
|
|
9859
|
-
prefix,
|
|
9860
|
-
suffix,
|
|
9861
|
-
className
|
|
9862
|
-
}) => {
|
|
9863
|
-
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
9864
|
-
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
9865
|
-
const [displayValue, setDisplayValue] = useState(value);
|
|
9866
|
-
const previousValueRef = useRef(value);
|
|
9867
|
-
const animationFrameRef = useRef(null);
|
|
9868
|
-
useEffect(() => {
|
|
9869
|
-
const from = previousValueRef.current;
|
|
9870
|
-
const to = value;
|
|
9871
|
-
previousValueRef.current = value;
|
|
9872
|
-
if (from === to) {
|
|
9873
|
-
setDisplayValue(to);
|
|
9874
|
-
return;
|
|
9875
|
-
}
|
|
9876
|
-
const startTime = performance.now();
|
|
9877
|
-
const diff = to - from;
|
|
9878
|
-
function animate(currentTime) {
|
|
9879
|
-
const elapsed = currentTime - startTime;
|
|
9880
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
9881
|
-
const easedProgress = easeOut(progress);
|
|
9882
|
-
setDisplayValue(from + diff * easedProgress);
|
|
9883
|
-
if (progress < 1) {
|
|
9884
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9885
|
-
} else {
|
|
9886
|
-
setDisplayValue(to);
|
|
9887
|
-
}
|
|
9888
|
-
}
|
|
9889
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9890
|
-
return () => {
|
|
9891
|
-
if (animationFrameRef.current !== null) {
|
|
9892
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
9893
|
-
}
|
|
9894
|
-
};
|
|
9895
|
-
}, [value, duration]);
|
|
9896
|
-
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
9897
|
-
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
9898
|
-
return /* @__PURE__ */ jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
9899
|
-
prefix,
|
|
9900
|
-
formattedValue,
|
|
9901
|
-
suffix
|
|
9902
|
-
] });
|
|
9903
|
-
};
|
|
9904
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
9905
|
-
}
|
|
9906
|
-
});
|
|
9907
9847
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
9908
9848
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
9909
9849
|
const observerRef = useRef(null);
|
|
@@ -12387,15 +12327,15 @@ function HeaderSkeleton({ className }) {
|
|
|
12387
12327
|
] })
|
|
12388
12328
|
] });
|
|
12389
12329
|
}
|
|
12390
|
-
function TableSkeleton({ rows = 5, columns = 4, className }) {
|
|
12330
|
+
function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
|
|
12391
12331
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
|
|
12392
12332
|
/* @__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)) }),
|
|
12393
|
-
Array.from({ length:
|
|
12333
|
+
Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsx(
|
|
12394
12334
|
HStack,
|
|
12395
12335
|
{
|
|
12396
12336
|
className: cn(
|
|
12397
12337
|
"px-4 py-3",
|
|
12398
|
-
rowIdx <
|
|
12338
|
+
rowIdx < rows2 - 1 && "border-b border-border"
|
|
12399
12339
|
),
|
|
12400
12340
|
children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
|
|
12401
12341
|
},
|
|
@@ -12443,18 +12383,18 @@ function CardSkeleton({ className }) {
|
|
|
12443
12383
|
}
|
|
12444
12384
|
);
|
|
12445
12385
|
}
|
|
12446
|
-
function TextSkeleton({ rows = 3, className }) {
|
|
12447
|
-
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length:
|
|
12386
|
+
function TextSkeleton({ rows: rows2 = 3, className }) {
|
|
12387
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsx(
|
|
12448
12388
|
SkeletonLine,
|
|
12449
12389
|
{
|
|
12450
|
-
className: i ===
|
|
12390
|
+
className: i === rows2 - 1 ? "w-2/3" : "w-full"
|
|
12451
12391
|
},
|
|
12452
12392
|
i
|
|
12453
12393
|
)) });
|
|
12454
12394
|
}
|
|
12455
12395
|
function Skeleton({
|
|
12456
12396
|
variant = "text",
|
|
12457
|
-
rows,
|
|
12397
|
+
rows: rows2,
|
|
12458
12398
|
columns,
|
|
12459
12399
|
fields,
|
|
12460
12400
|
className
|
|
@@ -12464,15 +12404,15 @@ function Skeleton({
|
|
|
12464
12404
|
case "header":
|
|
12465
12405
|
return /* @__PURE__ */ jsx(HeaderSkeleton, { className });
|
|
12466
12406
|
case "table":
|
|
12467
|
-
return /* @__PURE__ */ jsx(TableSkeleton, { rows, columns, className });
|
|
12407
|
+
return /* @__PURE__ */ jsx(TableSkeleton, { rows: rows2, columns, className });
|
|
12468
12408
|
case "form":
|
|
12469
12409
|
return /* @__PURE__ */ jsx(FormSkeleton, { fields, className });
|
|
12470
12410
|
case "card":
|
|
12471
12411
|
return /* @__PURE__ */ jsx(CardSkeleton, { className });
|
|
12472
12412
|
case "text":
|
|
12473
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
12413
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
12474
12414
|
default:
|
|
12475
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
12415
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
12476
12416
|
}
|
|
12477
12417
|
}
|
|
12478
12418
|
var pulseClass;
|
|
@@ -13626,7 +13566,7 @@ var init_Menu = __esm({
|
|
|
13626
13566
|
className
|
|
13627
13567
|
}) => {
|
|
13628
13568
|
const eventBus = useEventBus();
|
|
13629
|
-
const { t } = useTranslate();
|
|
13569
|
+
const { t, direction } = useTranslate();
|
|
13630
13570
|
const [isOpen, setIsOpen] = useState(false);
|
|
13631
13571
|
const [activeSubMenu, setActiveSubMenu] = useState(null);
|
|
13632
13572
|
const [triggerRect, setTriggerRect] = useState(null);
|
|
@@ -13680,6 +13620,18 @@ var init_Menu = __esm({
|
|
|
13680
13620
|
"bottom-start": "top-full left-0 mt-2",
|
|
13681
13621
|
"bottom-end": "top-full right-0 mt-2"
|
|
13682
13622
|
};
|
|
13623
|
+
const rtlMirror = {
|
|
13624
|
+
"top-left": "top-right",
|
|
13625
|
+
"top-right": "top-left",
|
|
13626
|
+
"bottom-left": "bottom-right",
|
|
13627
|
+
"bottom-right": "bottom-left",
|
|
13628
|
+
"top-start": "top-end",
|
|
13629
|
+
"top-end": "top-start",
|
|
13630
|
+
"bottom-start": "bottom-end",
|
|
13631
|
+
"bottom-end": "bottom-start"
|
|
13632
|
+
};
|
|
13633
|
+
const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
|
|
13634
|
+
const subMenuSideClass = direction === "rtl" ? "right-full mr-2" : "left-full ml-2";
|
|
13683
13635
|
const triggerChild = React97__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
|
|
13684
13636
|
const triggerElement = React97__default.cloneElement(
|
|
13685
13637
|
triggerChild,
|
|
@@ -13707,7 +13659,7 @@ var init_Menu = __esm({
|
|
|
13707
13659
|
onMouseEnter: () => hasSubMenu && setActiveSubMenu(itemId),
|
|
13708
13660
|
"data-testid": item.event ? `action-${item.event}` : void 0,
|
|
13709
13661
|
className: cn(
|
|
13710
|
-
"w-full flex items-center justify-between gap-3 px-4 py-2 text-
|
|
13662
|
+
"w-full flex items-center justify-between gap-3 px-4 py-2 text-start",
|
|
13711
13663
|
"text-sm transition-colors",
|
|
13712
13664
|
"hover:bg-muted",
|
|
13713
13665
|
"focus:outline-none focus:bg-muted",
|
|
@@ -13726,7 +13678,7 @@ var init_Menu = __esm({
|
|
|
13726
13678
|
}
|
|
13727
13679
|
),
|
|
13728
13680
|
item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge }),
|
|
13729
|
-
hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: "sm", className: "flex-shrink-0" })
|
|
13681
|
+
hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: direction === "rtl" ? "chevron-left" : "chevron-right", size: "sm", className: "flex-shrink-0" })
|
|
13730
13682
|
] })
|
|
13731
13683
|
},
|
|
13732
13684
|
itemId
|
|
@@ -13746,7 +13698,8 @@ var init_Menu = __esm({
|
|
|
13746
13698
|
Box,
|
|
13747
13699
|
{
|
|
13748
13700
|
className: cn(
|
|
13749
|
-
"absolute
|
|
13701
|
+
"absolute top-0 z-50",
|
|
13702
|
+
subMenuSideClass,
|
|
13750
13703
|
menuContainerStyles
|
|
13751
13704
|
),
|
|
13752
13705
|
children: renderMenuItems(item.subMenu)
|
|
@@ -13764,12 +13717,12 @@ var init_Menu = __esm({
|
|
|
13764
13717
|
className: cn(
|
|
13765
13718
|
"absolute z-50",
|
|
13766
13719
|
menuContainerStyles,
|
|
13767
|
-
positionClasses3[
|
|
13720
|
+
positionClasses3[effectivePosition],
|
|
13768
13721
|
className
|
|
13769
13722
|
),
|
|
13770
13723
|
style: {
|
|
13771
|
-
left:
|
|
13772
|
-
right:
|
|
13724
|
+
left: effectivePosition.includes("left") ? 0 : "auto",
|
|
13725
|
+
right: effectivePosition.includes("right") ? 0 : "auto"
|
|
13773
13726
|
},
|
|
13774
13727
|
role: "menu",
|
|
13775
13728
|
children: renderMenuItems(items)
|
|
@@ -14087,7 +14040,7 @@ var init_MapView = __esm({
|
|
|
14087
14040
|
shadowSize: [41, 41]
|
|
14088
14041
|
});
|
|
14089
14042
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
14090
|
-
const { useEffect: useEffect79, useRef: useRef71, useCallback:
|
|
14043
|
+
const { useEffect: useEffect79, useRef: useRef71, useCallback: useCallback123, useState: useState113 } = React97__default;
|
|
14091
14044
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
14092
14045
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
14093
14046
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -14133,7 +14086,7 @@ var init_MapView = __esm({
|
|
|
14133
14086
|
}) {
|
|
14134
14087
|
const eventBus = useEventBus3();
|
|
14135
14088
|
const [clickedPosition, setClickedPosition] = useState113(null);
|
|
14136
|
-
const handleMapClick =
|
|
14089
|
+
const handleMapClick = useCallback123((lat, lng) => {
|
|
14137
14090
|
if (showClickedPin) {
|
|
14138
14091
|
setClickedPosition({ lat, lng });
|
|
14139
14092
|
}
|
|
@@ -14142,7 +14095,7 @@ var init_MapView = __esm({
|
|
|
14142
14095
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
14143
14096
|
}
|
|
14144
14097
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
14145
|
-
const handleMarkerClick =
|
|
14098
|
+
const handleMarkerClick = useCallback123((marker) => {
|
|
14146
14099
|
onMarkerClick?.(marker);
|
|
14147
14100
|
if (markerClickEvent) {
|
|
14148
14101
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -14363,7 +14316,7 @@ function InputPattern({
|
|
|
14363
14316
|
function TextareaPattern({
|
|
14364
14317
|
value = "",
|
|
14365
14318
|
placeholder,
|
|
14366
|
-
rows = 4,
|
|
14319
|
+
rows: rows2 = 4,
|
|
14367
14320
|
disabled = false,
|
|
14368
14321
|
fieldError,
|
|
14369
14322
|
onChange,
|
|
@@ -14383,7 +14336,7 @@ function TextareaPattern({
|
|
|
14383
14336
|
{
|
|
14384
14337
|
value: localValue,
|
|
14385
14338
|
placeholder,
|
|
14386
|
-
rows,
|
|
14339
|
+
rows: rows2,
|
|
14387
14340
|
disabled,
|
|
14388
14341
|
error: fieldError,
|
|
14389
14342
|
onChange: handleChange,
|
|
@@ -14868,6 +14821,91 @@ var init_ActionPalette = __esm({
|
|
|
14868
14821
|
ActionPalette.displayName = "ActionPalette";
|
|
14869
14822
|
}
|
|
14870
14823
|
});
|
|
14824
|
+
function parseValue(value) {
|
|
14825
|
+
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
14826
|
+
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
14827
|
+
if (!match) {
|
|
14828
|
+
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
14829
|
+
}
|
|
14830
|
+
const numStr = match[2];
|
|
14831
|
+
const decimalIdx = numStr.indexOf(".");
|
|
14832
|
+
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
14833
|
+
return {
|
|
14834
|
+
prefix: match[1],
|
|
14835
|
+
num: parseFloat(numStr),
|
|
14836
|
+
suffix: match[3],
|
|
14837
|
+
decimals
|
|
14838
|
+
};
|
|
14839
|
+
}
|
|
14840
|
+
var AnimatedCounter;
|
|
14841
|
+
var init_AnimatedCounter = __esm({
|
|
14842
|
+
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
14843
|
+
"use client";
|
|
14844
|
+
init_cn();
|
|
14845
|
+
init_Box();
|
|
14846
|
+
init_Typography();
|
|
14847
|
+
AnimatedCounter = ({
|
|
14848
|
+
value,
|
|
14849
|
+
label,
|
|
14850
|
+
duration = 1500,
|
|
14851
|
+
className
|
|
14852
|
+
}) => {
|
|
14853
|
+
const ref = useRef(null);
|
|
14854
|
+
const [displayValue, setDisplayValue] = useState("0");
|
|
14855
|
+
const [hasAnimated, setHasAnimated] = useState(false);
|
|
14856
|
+
const animate = useCallback(() => {
|
|
14857
|
+
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
14858
|
+
if (num2 === 0) {
|
|
14859
|
+
setDisplayValue(String(value));
|
|
14860
|
+
return;
|
|
14861
|
+
}
|
|
14862
|
+
const startTime = performance.now();
|
|
14863
|
+
const tick = (now2) => {
|
|
14864
|
+
const elapsed = now2 - startTime;
|
|
14865
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
14866
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
14867
|
+
const current = eased * num2;
|
|
14868
|
+
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
14869
|
+
if (progress < 1) {
|
|
14870
|
+
requestAnimationFrame(tick);
|
|
14871
|
+
} else {
|
|
14872
|
+
setDisplayValue(String(value));
|
|
14873
|
+
}
|
|
14874
|
+
};
|
|
14875
|
+
requestAnimationFrame(tick);
|
|
14876
|
+
}, [value, duration]);
|
|
14877
|
+
useEffect(() => {
|
|
14878
|
+
if (hasAnimated) return;
|
|
14879
|
+
const el = ref.current;
|
|
14880
|
+
if (!el) return;
|
|
14881
|
+
const observer2 = new IntersectionObserver(
|
|
14882
|
+
(entries) => {
|
|
14883
|
+
if (entries[0].isIntersecting) {
|
|
14884
|
+
setHasAnimated(true);
|
|
14885
|
+
animate();
|
|
14886
|
+
observer2.disconnect();
|
|
14887
|
+
}
|
|
14888
|
+
},
|
|
14889
|
+
{ threshold: 0.3 }
|
|
14890
|
+
);
|
|
14891
|
+
observer2.observe(el);
|
|
14892
|
+
return () => observer2.disconnect();
|
|
14893
|
+
}, [hasAnimated, animate]);
|
|
14894
|
+
return /* @__PURE__ */ jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
14895
|
+
/* @__PURE__ */ jsx(
|
|
14896
|
+
Typography,
|
|
14897
|
+
{
|
|
14898
|
+
variant: "h2",
|
|
14899
|
+
className: "text-primary font-bold tabular-nums",
|
|
14900
|
+
children: hasAnimated ? displayValue : "0"
|
|
14901
|
+
}
|
|
14902
|
+
),
|
|
14903
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
14904
|
+
] });
|
|
14905
|
+
};
|
|
14906
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
14907
|
+
}
|
|
14908
|
+
});
|
|
14871
14909
|
var AuthLayout;
|
|
14872
14910
|
var init_AuthLayout = __esm({
|
|
14873
14911
|
"components/core/templates/AuthLayout.tsx"() {
|
|
@@ -16253,6 +16291,39 @@ var init_IsometricCanvas2 = __esm({
|
|
|
16253
16291
|
init_IsometricCanvas();
|
|
16254
16292
|
}
|
|
16255
16293
|
});
|
|
16294
|
+
|
|
16295
|
+
// components/game/organisms/boardEntity.ts
|
|
16296
|
+
function boardEntity(entity) {
|
|
16297
|
+
if (!entity) return void 0;
|
|
16298
|
+
return Array.isArray(entity) ? entity[0] : entity;
|
|
16299
|
+
}
|
|
16300
|
+
function str(v) {
|
|
16301
|
+
return v == null ? "" : String(v);
|
|
16302
|
+
}
|
|
16303
|
+
function num(v, fallback = 0) {
|
|
16304
|
+
const n = Number(v);
|
|
16305
|
+
return Number.isFinite(n) ? n : fallback;
|
|
16306
|
+
}
|
|
16307
|
+
function rows(v) {
|
|
16308
|
+
return Array.isArray(v) ? v : [];
|
|
16309
|
+
}
|
|
16310
|
+
function vec2(v) {
|
|
16311
|
+
const o = v ?? {};
|
|
16312
|
+
return { x: num(o.x), y: num(o.y) };
|
|
16313
|
+
}
|
|
16314
|
+
function unitPosition(u) {
|
|
16315
|
+
return vec2(u.position);
|
|
16316
|
+
}
|
|
16317
|
+
function unitTeam(u) {
|
|
16318
|
+
return str(u.team);
|
|
16319
|
+
}
|
|
16320
|
+
function unitHealth(u) {
|
|
16321
|
+
return num(u.health);
|
|
16322
|
+
}
|
|
16323
|
+
var init_boardEntity = __esm({
|
|
16324
|
+
"components/game/organisms/boardEntity.ts"() {
|
|
16325
|
+
}
|
|
16326
|
+
});
|
|
16256
16327
|
function BattleBoard({
|
|
16257
16328
|
entity,
|
|
16258
16329
|
scale = 0.45,
|
|
@@ -16279,43 +16350,49 @@ function BattleBoard({
|
|
|
16279
16350
|
attackEvent,
|
|
16280
16351
|
className
|
|
16281
16352
|
}) {
|
|
16282
|
-
const
|
|
16283
|
-
const
|
|
16284
|
-
const
|
|
16285
|
-
const
|
|
16286
|
-
const
|
|
16287
|
-
const
|
|
16288
|
-
const
|
|
16289
|
-
const
|
|
16290
|
-
const
|
|
16291
|
-
const
|
|
16292
|
-
const
|
|
16353
|
+
const board = boardEntity(entity) ?? {};
|
|
16354
|
+
const tiles = Array.isArray(board.tiles) ? board.tiles : [];
|
|
16355
|
+
const features = Array.isArray(board.features) ? board.features : [];
|
|
16356
|
+
const boardWidth = num(board.boardWidth, 8);
|
|
16357
|
+
const boardHeight = num(board.boardHeight, 6);
|
|
16358
|
+
const assetManifest = board.assetManifest;
|
|
16359
|
+
const backgroundImage = board.backgroundImage;
|
|
16360
|
+
const units = rows(board.units);
|
|
16361
|
+
const selectedUnitId = board.selectedUnitId ?? null;
|
|
16362
|
+
const currentPhase = str(board.phase) || "observation";
|
|
16363
|
+
const currentTurn = num(board.turn, 1);
|
|
16364
|
+
const gameResult = board.gameResult ?? null;
|
|
16293
16365
|
const eventBus = useEventBus();
|
|
16294
16366
|
const { t } = useTranslate();
|
|
16295
16367
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
16296
16368
|
const [isShaking, setIsShaking] = useState(false);
|
|
16297
16369
|
const selectedUnit = useMemo(
|
|
16298
|
-
() => units.find((u) => u.id === selectedUnitId) ?? null,
|
|
16370
|
+
() => units.find((u) => str(u.id) === selectedUnitId) ?? null,
|
|
16299
16371
|
[units, selectedUnitId]
|
|
16300
16372
|
);
|
|
16301
16373
|
const hoveredUnit = useMemo(() => {
|
|
16302
16374
|
if (!hoveredTile) return null;
|
|
16303
|
-
return units.find(
|
|
16304
|
-
|
|
16305
|
-
|
|
16375
|
+
return units.find((u) => {
|
|
16376
|
+
const p2 = unitPosition(u);
|
|
16377
|
+
return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
|
|
16378
|
+
}) ?? null;
|
|
16306
16379
|
}, [hoveredTile, units]);
|
|
16307
|
-
const playerUnits = useMemo(() => units.filter((u) => u
|
|
16308
|
-
const enemyUnits = useMemo(() => units.filter((u) => u
|
|
16380
|
+
const playerUnits = useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
|
|
16381
|
+
const enemyUnits = useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
|
|
16309
16382
|
const validMoves = useMemo(() => {
|
|
16310
16383
|
if (!selectedUnit || currentPhase !== "movement") return [];
|
|
16311
16384
|
const moves = [];
|
|
16312
|
-
const range = selectedUnit.movement;
|
|
16385
|
+
const range = num(selectedUnit.movement);
|
|
16386
|
+
const origin = unitPosition(selectedUnit);
|
|
16313
16387
|
for (let dy = -range; dy <= range; dy++) {
|
|
16314
16388
|
for (let dx = -range; dx <= range; dx++) {
|
|
16315
|
-
const nx =
|
|
16316
|
-
const ny =
|
|
16389
|
+
const nx = origin.x + dx;
|
|
16390
|
+
const ny = origin.y + dy;
|
|
16317
16391
|
const dist = Math.abs(dx) + Math.abs(dy);
|
|
16318
|
-
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) =>
|
|
16392
|
+
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
|
|
16393
|
+
const p2 = unitPosition(u);
|
|
16394
|
+
return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
|
|
16395
|
+
})) {
|
|
16319
16396
|
moves.push({ x: nx, y: ny });
|
|
16320
16397
|
}
|
|
16321
16398
|
}
|
|
@@ -16324,11 +16401,14 @@ function BattleBoard({
|
|
|
16324
16401
|
}, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
|
|
16325
16402
|
const attackTargets = useMemo(() => {
|
|
16326
16403
|
if (!selectedUnit || currentPhase !== "action") return [];
|
|
16327
|
-
|
|
16328
|
-
|
|
16329
|
-
|
|
16404
|
+
const sp = unitPosition(selectedUnit);
|
|
16405
|
+
const sTeam = unitTeam(selectedUnit);
|
|
16406
|
+
return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
|
|
16407
|
+
const p2 = unitPosition(u);
|
|
16408
|
+
const dx = Math.abs(p2.x - sp.x);
|
|
16409
|
+
const dy = Math.abs(p2.y - sp.y);
|
|
16330
16410
|
return dx <= 1 && dy <= 1 && dx + dy > 0;
|
|
16331
|
-
}).map((u) => u
|
|
16411
|
+
}).map((u) => unitPosition(u));
|
|
16332
16412
|
}, [selectedUnit, currentPhase, units]);
|
|
16333
16413
|
const MOVE_SPEED_MS_PER_TILE = 300;
|
|
16334
16414
|
const movementAnimRef = useRef(null);
|
|
@@ -16368,23 +16448,25 @@ function BattleBoard({
|
|
|
16368
16448
|
return () => clearInterval(interval);
|
|
16369
16449
|
}, []);
|
|
16370
16450
|
const isoUnits = useMemo(() => {
|
|
16371
|
-
return units.filter((u) => u
|
|
16372
|
-
const
|
|
16451
|
+
return units.filter((u) => unitHealth(u) > 0).map((unit) => {
|
|
16452
|
+
const id = str(unit.id);
|
|
16453
|
+
const pos = movingPositions.get(id) ?? unitPosition(unit);
|
|
16454
|
+
const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
|
|
16373
16455
|
return {
|
|
16374
|
-
id
|
|
16456
|
+
id,
|
|
16375
16457
|
position: pos,
|
|
16376
|
-
name: unit.name,
|
|
16377
|
-
team: unit
|
|
16378
|
-
health: unit
|
|
16379
|
-
maxHealth: unit.maxHealth,
|
|
16380
|
-
unitType: unit.unitType,
|
|
16381
|
-
heroId: unit.heroId,
|
|
16382
|
-
sprite: unit.sprite,
|
|
16383
|
-
traits:
|
|
16384
|
-
name:
|
|
16385
|
-
currentState:
|
|
16386
|
-
states:
|
|
16387
|
-
cooldown:
|
|
16458
|
+
name: str(unit.name),
|
|
16459
|
+
team: unitTeam(unit),
|
|
16460
|
+
health: unitHealth(unit),
|
|
16461
|
+
maxHealth: num(unit.maxHealth),
|
|
16462
|
+
unitType: unit.unitType == null ? void 0 : str(unit.unitType),
|
|
16463
|
+
heroId: unit.heroId == null ? void 0 : str(unit.heroId),
|
|
16464
|
+
sprite: unit.sprite == null ? void 0 : str(unit.sprite),
|
|
16465
|
+
traits: unitTraits?.map((tr) => ({
|
|
16466
|
+
name: tr.name,
|
|
16467
|
+
currentState: tr.currentState,
|
|
16468
|
+
states: tr.states,
|
|
16469
|
+
cooldown: tr.cooldown ?? 0
|
|
16388
16470
|
}))
|
|
16389
16471
|
};
|
|
16390
16472
|
});
|
|
@@ -16396,8 +16478,8 @@ function BattleBoard({
|
|
|
16396
16478
|
[scale, baseOffsetX]
|
|
16397
16479
|
);
|
|
16398
16480
|
const checkGameEnd = useCallback(() => {
|
|
16399
|
-
const pa = units.filter((u) => u
|
|
16400
|
-
const ea = units.filter((u) => u
|
|
16481
|
+
const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
16482
|
+
const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
16401
16483
|
if (pa.length === 0) {
|
|
16402
16484
|
onGameEnd?.("defeat");
|
|
16403
16485
|
if (gameEndEvent) {
|
|
@@ -16411,21 +16493,22 @@ function BattleBoard({
|
|
|
16411
16493
|
}
|
|
16412
16494
|
}, [units, onGameEnd, gameEndEvent, eventBus]);
|
|
16413
16495
|
const handleUnitClick = useCallback((unitId) => {
|
|
16414
|
-
const unit = units.find((u) => u.id === unitId);
|
|
16496
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
16415
16497
|
if (!unit) return;
|
|
16416
16498
|
if (unitClickEvent) {
|
|
16417
16499
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
16418
16500
|
}
|
|
16419
16501
|
if (currentPhase === "action" && selectedUnit) {
|
|
16420
|
-
|
|
16421
|
-
|
|
16502
|
+
const up = unitPosition(unit);
|
|
16503
|
+
if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
|
|
16504
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
16422
16505
|
setIsShaking(true);
|
|
16423
16506
|
setTimeout(() => setIsShaking(false), 300);
|
|
16424
16507
|
onAttack?.(selectedUnit, unit, damage);
|
|
16425
16508
|
if (attackEvent) {
|
|
16426
16509
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
16427
|
-
attackerId: selectedUnit.id,
|
|
16428
|
-
targetId: unit.id,
|
|
16510
|
+
attackerId: str(selectedUnit.id),
|
|
16511
|
+
targetId: str(unit.id),
|
|
16429
16512
|
damage
|
|
16430
16513
|
});
|
|
16431
16514
|
}
|
|
@@ -16440,9 +16523,9 @@ function BattleBoard({
|
|
|
16440
16523
|
if (currentPhase === "movement" && selectedUnit) {
|
|
16441
16524
|
if (movementAnimRef.current) return;
|
|
16442
16525
|
if (validMoves.some((m) => m.x === x && m.y === y)) {
|
|
16443
|
-
const from = { ...selectedUnit
|
|
16526
|
+
const from = { ...unitPosition(selectedUnit) };
|
|
16444
16527
|
const to = { x, y };
|
|
16445
|
-
startMoveAnimation(selectedUnit.id, from, to, () => {
|
|
16528
|
+
startMoveAnimation(str(selectedUnit.id), from, to, () => {
|
|
16446
16529
|
onUnitMove?.(selectedUnit, to);
|
|
16447
16530
|
});
|
|
16448
16531
|
}
|
|
@@ -16600,6 +16683,7 @@ var init_BattleBoard = __esm({
|
|
|
16600
16683
|
init_Typography();
|
|
16601
16684
|
init_Stack();
|
|
16602
16685
|
init_IsometricCanvas2();
|
|
16686
|
+
init_boardEntity();
|
|
16603
16687
|
init_isometric();
|
|
16604
16688
|
BattleBoard.displayName = "BattleBoard";
|
|
16605
16689
|
}
|
|
@@ -16993,24 +17077,24 @@ var init_CodeBlock = __esm({
|
|
|
16993
17077
|
return;
|
|
16994
17078
|
}
|
|
16995
17079
|
lineEls.forEach((el) => {
|
|
16996
|
-
const
|
|
16997
|
-
if (hiddenLines.has(
|
|
17080
|
+
const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
|
|
17081
|
+
if (hiddenLines.has(num2)) {
|
|
16998
17082
|
el.style.display = "none";
|
|
16999
17083
|
return;
|
|
17000
17084
|
}
|
|
17001
17085
|
el.style.display = "";
|
|
17002
17086
|
el.style.position = "relative";
|
|
17003
17087
|
el.style.paddingLeft = "1.2em";
|
|
17004
|
-
const region = foldStartMap.get(
|
|
17088
|
+
const region = foldStartMap.get(num2);
|
|
17005
17089
|
if (!region) return;
|
|
17006
|
-
const isCollapsed = collapsed.has(
|
|
17090
|
+
const isCollapsed = collapsed.has(num2);
|
|
17007
17091
|
const toggle = document.createElement("span");
|
|
17008
17092
|
toggle.className = "fold-toggle";
|
|
17009
17093
|
toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
|
|
17010
17094
|
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%";
|
|
17011
17095
|
toggle.addEventListener("click", (e) => {
|
|
17012
17096
|
e.stopPropagation();
|
|
17013
|
-
toggleFoldRef.current(
|
|
17097
|
+
toggleFoldRef.current(num2);
|
|
17014
17098
|
});
|
|
17015
17099
|
el.insertBefore(toggle, el.firstChild);
|
|
17016
17100
|
if (isCollapsed) {
|
|
@@ -19263,10 +19347,13 @@ var init_BookChapterView = __esm({
|
|
|
19263
19347
|
init_cn();
|
|
19264
19348
|
BookChapterView = ({
|
|
19265
19349
|
chapter,
|
|
19350
|
+
orbitalSchema,
|
|
19266
19351
|
direction,
|
|
19267
19352
|
className
|
|
19268
19353
|
}) => {
|
|
19269
19354
|
const { t: _t } = useTranslate();
|
|
19355
|
+
const title = String(chapter.title ?? "");
|
|
19356
|
+
const content = String(chapter.content ?? "");
|
|
19270
19357
|
return /* @__PURE__ */ jsxs(
|
|
19271
19358
|
VStack,
|
|
19272
19359
|
{
|
|
@@ -19274,16 +19361,16 @@ var init_BookChapterView = __esm({
|
|
|
19274
19361
|
className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
|
|
19275
19362
|
style: { direction },
|
|
19276
19363
|
children: [
|
|
19277
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children:
|
|
19364
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
|
|
19278
19365
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
19279
|
-
!!
|
|
19366
|
+
!!orbitalSchema && /* @__PURE__ */ jsx(ScaledDiagram, { children: /* @__PURE__ */ jsx(
|
|
19280
19367
|
JazariStateMachine,
|
|
19281
19368
|
{
|
|
19282
|
-
schema:
|
|
19369
|
+
schema: orbitalSchema,
|
|
19283
19370
|
direction
|
|
19284
19371
|
}
|
|
19285
19372
|
) }),
|
|
19286
|
-
/* @__PURE__ */ jsx(ContentRenderer, { content
|
|
19373
|
+
/* @__PURE__ */ jsx(ContentRenderer, { content, direction })
|
|
19287
19374
|
]
|
|
19288
19375
|
}
|
|
19289
19376
|
);
|
|
@@ -19381,7 +19468,7 @@ var init_BookNavBar = __esm({
|
|
|
19381
19468
|
BookNavBar = ({
|
|
19382
19469
|
currentPage,
|
|
19383
19470
|
totalPages,
|
|
19384
|
-
chapterTitle,
|
|
19471
|
+
chapterTitle: chapterTitle2,
|
|
19385
19472
|
direction,
|
|
19386
19473
|
className
|
|
19387
19474
|
}) => {
|
|
@@ -19422,12 +19509,12 @@ var init_BookNavBar = __esm({
|
|
|
19422
19509
|
)
|
|
19423
19510
|
] }),
|
|
19424
19511
|
/* @__PURE__ */ jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
|
|
19425
|
-
|
|
19512
|
+
chapterTitle2 && /* @__PURE__ */ jsx(
|
|
19426
19513
|
Typography,
|
|
19427
19514
|
{
|
|
19428
19515
|
variant: "caption",
|
|
19429
19516
|
className: "text-center block truncate text-muted-foreground",
|
|
19430
|
-
children:
|
|
19517
|
+
children: chapterTitle2
|
|
19431
19518
|
}
|
|
19432
19519
|
),
|
|
19433
19520
|
/* @__PURE__ */ jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
|
|
@@ -19494,31 +19581,35 @@ var init_BookTableOfContents = __esm({
|
|
|
19494
19581
|
style: { direction },
|
|
19495
19582
|
children: [
|
|
19496
19583
|
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
|
|
19497
|
-
parts.map((part, partIdx) =>
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
/* @__PURE__ */
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19520
|
-
|
|
19521
|
-
|
|
19584
|
+
parts.map((part, partIdx) => {
|
|
19585
|
+
const chapters = Array.isArray(part.chapters) ? part.chapters : [];
|
|
19586
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
19587
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
|
|
19588
|
+
/* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
|
|
19589
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
|
|
19590
|
+
] }),
|
|
19591
|
+
/* @__PURE__ */ jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
|
|
19592
|
+
const id = chapter.id == null ? "" : String(chapter.id);
|
|
19593
|
+
const isCurrent = id === currentChapterId;
|
|
19594
|
+
return /* @__PURE__ */ jsx(
|
|
19595
|
+
Button,
|
|
19596
|
+
{
|
|
19597
|
+
variant: "ghost",
|
|
19598
|
+
size: "sm",
|
|
19599
|
+
action: "BOOK_NAVIGATE",
|
|
19600
|
+
actionPayload: { chapterId: id },
|
|
19601
|
+
className: cn(
|
|
19602
|
+
"justify-start text-left w-full",
|
|
19603
|
+
direction === "rtl" && "text-right",
|
|
19604
|
+
isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
|
|
19605
|
+
),
|
|
19606
|
+
children: /* @__PURE__ */ jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
|
|
19607
|
+
},
|
|
19608
|
+
id
|
|
19609
|
+
);
|
|
19610
|
+
}) })
|
|
19611
|
+
] }, partIdx);
|
|
19612
|
+
})
|
|
19522
19613
|
]
|
|
19523
19614
|
}
|
|
19524
19615
|
);
|
|
@@ -19640,27 +19731,41 @@ function resolveFieldMap(fieldMap) {
|
|
|
19640
19731
|
function get(obj, key) {
|
|
19641
19732
|
return obj[key];
|
|
19642
19733
|
}
|
|
19734
|
+
function asStr(v) {
|
|
19735
|
+
return v == null ? "" : String(v);
|
|
19736
|
+
}
|
|
19643
19737
|
function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
|
|
19644
19738
|
const rawParts = get(raw, fields.parts) ?? [];
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
19648
|
-
|
|
19649
|
-
|
|
19650
|
-
|
|
19651
|
-
|
|
19652
|
-
const rawChapters = get(part, fields.chapters) ?? [];
|
|
19653
|
-
return {
|
|
19654
|
-
title: get(part, fields.partTitle) ?? "",
|
|
19655
|
-
chapters: rawChapters.map((ch) => ({
|
|
19656
|
-
id: get(ch, fields.chapterId) ?? "",
|
|
19657
|
-
title: get(ch, fields.chapterTitle) ?? "",
|
|
19658
|
-
content: get(ch, fields.chapterContent) ?? "",
|
|
19659
|
-
orbitalSchema: get(ch, fields.chapterOrbitalSchema)
|
|
19660
|
-
}))
|
|
19661
|
-
};
|
|
19662
|
-
})
|
|
19739
|
+
const direction = get(raw, fields.direction) ?? "ltr";
|
|
19740
|
+
const cover = {
|
|
19741
|
+
title: asStr(get(raw, fields.title)),
|
|
19742
|
+
subtitle: asStr(get(raw, fields.subtitle)),
|
|
19743
|
+
author: asStr(get(raw, fields.author)),
|
|
19744
|
+
coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
|
|
19745
|
+
direction
|
|
19663
19746
|
};
|
|
19747
|
+
const schemaByChapterId = {};
|
|
19748
|
+
const chapters = [];
|
|
19749
|
+
const parts = rawParts.map((part) => {
|
|
19750
|
+
const rawChapters = get(part, fields.chapters) ?? [];
|
|
19751
|
+
const chapterRows = rawChapters.map((ch) => {
|
|
19752
|
+
const id = asStr(get(ch, fields.chapterId));
|
|
19753
|
+
const schema = get(ch, fields.chapterOrbitalSchema);
|
|
19754
|
+
if (schema) schemaByChapterId[id] = schema;
|
|
19755
|
+
const row = {
|
|
19756
|
+
id,
|
|
19757
|
+
title: asStr(get(ch, fields.chapterTitle)),
|
|
19758
|
+
content: asStr(get(ch, fields.chapterContent))
|
|
19759
|
+
};
|
|
19760
|
+
chapters.push(row);
|
|
19761
|
+
return row;
|
|
19762
|
+
});
|
|
19763
|
+
return {
|
|
19764
|
+
title: asStr(get(part, fields.partTitle)),
|
|
19765
|
+
chapters: chapterRows
|
|
19766
|
+
};
|
|
19767
|
+
});
|
|
19768
|
+
return { cover, direction, parts, chapters, schemaByChapterId };
|
|
19664
19769
|
}
|
|
19665
19770
|
var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
|
|
19666
19771
|
var init_types2 = __esm({
|
|
@@ -19698,10 +19803,7 @@ var init_types2 = __esm({
|
|
|
19698
19803
|
};
|
|
19699
19804
|
}
|
|
19700
19805
|
});
|
|
19701
|
-
|
|
19702
|
-
return book.parts.flatMap((part) => part.chapters);
|
|
19703
|
-
}
|
|
19704
|
-
var PRINT_STYLES, BookViewer;
|
|
19806
|
+
var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
|
|
19705
19807
|
var init_BookViewer = __esm({
|
|
19706
19808
|
"components/marketing/organisms/book/BookViewer.tsx"() {
|
|
19707
19809
|
init_Box();
|
|
@@ -19714,6 +19816,8 @@ var init_BookViewer = __esm({
|
|
|
19714
19816
|
init_BookNavBar();
|
|
19715
19817
|
init_EmptyState();
|
|
19716
19818
|
init_types2();
|
|
19819
|
+
chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
|
|
19820
|
+
chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
|
|
19717
19821
|
PRINT_STYLES = `
|
|
19718
19822
|
@media print {
|
|
19719
19823
|
.book-viewer-page {
|
|
@@ -19742,14 +19846,14 @@ var init_BookViewer = __esm({
|
|
|
19742
19846
|
return mapBookData(raw, resolvedFieldMap);
|
|
19743
19847
|
}, [entity, resolvedFieldMap]);
|
|
19744
19848
|
const direction = book?.direction ?? "ltr";
|
|
19745
|
-
const chapters = useMemo(() => book ?
|
|
19849
|
+
const chapters = useMemo(() => book ? book.chapters : [], [book]);
|
|
19746
19850
|
const totalPages = 2 + chapters.length;
|
|
19747
19851
|
const navigateTo = useCallback(
|
|
19748
19852
|
(page) => {
|
|
19749
19853
|
const clamped = Math.max(0, Math.min(page, totalPages - 1));
|
|
19750
19854
|
setCurrentPage(clamped);
|
|
19751
|
-
const
|
|
19752
|
-
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
|
|
19855
|
+
const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
|
|
19856
|
+
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
|
|
19753
19857
|
},
|
|
19754
19858
|
[totalPages, chapters, eventBus]
|
|
19755
19859
|
);
|
|
@@ -19761,8 +19865,8 @@ var init_BookViewer = __esm({
|
|
|
19761
19865
|
eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
|
|
19762
19866
|
eventBus.on("UI:BOOK_PRINT", () => window.print()),
|
|
19763
19867
|
eventBus.on("UI:BOOK_NAVIGATE", (event) => {
|
|
19764
|
-
const
|
|
19765
|
-
const idx = chapters.findIndex((ch) => ch
|
|
19868
|
+
const targetId = event.payload?.chapterId;
|
|
19869
|
+
const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
|
|
19766
19870
|
if (idx >= 0) navigateTo(idx + 2);
|
|
19767
19871
|
})
|
|
19768
19872
|
];
|
|
@@ -19779,9 +19883,11 @@ var init_BookViewer = __esm({
|
|
|
19779
19883
|
style.remove();
|
|
19780
19884
|
};
|
|
19781
19885
|
}, []);
|
|
19782
|
-
const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]
|
|
19783
|
-
const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]
|
|
19886
|
+
const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
|
|
19887
|
+
const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
|
|
19784
19888
|
if (!book) return /* @__PURE__ */ jsx(EmptyState, { message: t("book.noData") });
|
|
19889
|
+
const cover = book.cover;
|
|
19890
|
+
const coverTitle = String(cover.title ?? "");
|
|
19785
19891
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
|
|
19786
19892
|
/* @__PURE__ */ jsxs(
|
|
19787
19893
|
Box,
|
|
@@ -19793,10 +19899,10 @@ var init_BookViewer = __esm({
|
|
|
19793
19899
|
/* @__PURE__ */ jsx(
|
|
19794
19900
|
BookCoverPage,
|
|
19795
19901
|
{
|
|
19796
|
-
title:
|
|
19797
|
-
subtitle:
|
|
19798
|
-
author:
|
|
19799
|
-
coverImageUrl:
|
|
19902
|
+
title: coverTitle,
|
|
19903
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
19904
|
+
author: String(cover.author ?? "") || void 0,
|
|
19905
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
19800
19906
|
direction
|
|
19801
19907
|
}
|
|
19802
19908
|
),
|
|
@@ -19807,23 +19913,27 @@ var init_BookViewer = __esm({
|
|
|
19807
19913
|
direction
|
|
19808
19914
|
}
|
|
19809
19915
|
),
|
|
19810
|
-
chapters.map((chapter) =>
|
|
19811
|
-
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
|
|
19916
|
+
chapters.map((chapter) => {
|
|
19917
|
+
const id = chapterId(chapter);
|
|
19918
|
+
return /* @__PURE__ */ jsx(
|
|
19919
|
+
BookChapterView,
|
|
19920
|
+
{
|
|
19921
|
+
chapter,
|
|
19922
|
+
orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
|
|
19923
|
+
direction
|
|
19924
|
+
},
|
|
19925
|
+
id
|
|
19926
|
+
);
|
|
19927
|
+
})
|
|
19818
19928
|
] }),
|
|
19819
19929
|
/* @__PURE__ */ jsxs(Box, { className: "print:hidden", children: [
|
|
19820
19930
|
currentPage === 0 && /* @__PURE__ */ jsx(
|
|
19821
19931
|
BookCoverPage,
|
|
19822
19932
|
{
|
|
19823
|
-
title:
|
|
19824
|
-
subtitle:
|
|
19825
|
-
author:
|
|
19826
|
-
coverImageUrl:
|
|
19933
|
+
title: coverTitle,
|
|
19934
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
19935
|
+
author: String(cover.author ?? "") || void 0,
|
|
19936
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
19827
19937
|
direction
|
|
19828
19938
|
}
|
|
19829
19939
|
),
|
|
@@ -19839,6 +19949,7 @@ var init_BookViewer = __esm({
|
|
|
19839
19949
|
BookChapterView,
|
|
19840
19950
|
{
|
|
19841
19951
|
chapter: chapters[currentPage - 2],
|
|
19952
|
+
orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
|
|
19842
19953
|
direction
|
|
19843
19954
|
}
|
|
19844
19955
|
)
|
|
@@ -19851,7 +19962,7 @@ var init_BookViewer = __esm({
|
|
|
19851
19962
|
{
|
|
19852
19963
|
currentPage,
|
|
19853
19964
|
totalPages,
|
|
19854
|
-
chapterTitle: currentPage === 0 ?
|
|
19965
|
+
chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
|
|
19855
19966
|
direction
|
|
19856
19967
|
}
|
|
19857
19968
|
)
|
|
@@ -19949,7 +20060,7 @@ var init_Grid = __esm({
|
|
|
19949
20060
|
};
|
|
19950
20061
|
Grid = ({
|
|
19951
20062
|
cols = 1,
|
|
19952
|
-
rows,
|
|
20063
|
+
rows: rows2,
|
|
19953
20064
|
gap = "md",
|
|
19954
20065
|
rowGap,
|
|
19955
20066
|
colGap,
|
|
@@ -19961,7 +20072,7 @@ var init_Grid = __esm({
|
|
|
19961
20072
|
children,
|
|
19962
20073
|
as: Component = "div"
|
|
19963
20074
|
}) => {
|
|
19964
|
-
const mergedStyle =
|
|
20075
|
+
const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
|
|
19965
20076
|
return React97__default.createElement(
|
|
19966
20077
|
Component,
|
|
19967
20078
|
{
|
|
@@ -20677,14 +20788,14 @@ function BuilderBoard({
|
|
|
20677
20788
|
}) {
|
|
20678
20789
|
const { emit } = useEventBus();
|
|
20679
20790
|
const { t } = useTranslate();
|
|
20680
|
-
const resolved =
|
|
20791
|
+
const resolved = boardEntity(entity);
|
|
20681
20792
|
const [placements, setPlacements] = useState({});
|
|
20682
20793
|
const [headerError, setHeaderError] = useState(false);
|
|
20683
20794
|
const [submitted, setSubmitted] = useState(false);
|
|
20684
20795
|
const [attempts, setAttempts] = useState(0);
|
|
20685
20796
|
const [showHint, setShowHint] = useState(false);
|
|
20686
|
-
const components = resolved?.components
|
|
20687
|
-
const slots = resolved?.slots
|
|
20797
|
+
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
20798
|
+
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
20688
20799
|
const usedComponentIds = new Set(Object.values(placements));
|
|
20689
20800
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
20690
20801
|
const [selectedComponent, setSelectedComponent] = useState(null);
|
|
@@ -20718,7 +20829,7 @@ function BuilderBoard({
|
|
|
20718
20829
|
}, [slots, placements, attempts, completeEvent, emit]);
|
|
20719
20830
|
const handleReset = () => {
|
|
20720
20831
|
setSubmitted(false);
|
|
20721
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
20832
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
20722
20833
|
setShowHint(true);
|
|
20723
20834
|
}
|
|
20724
20835
|
};
|
|
@@ -20731,20 +20842,24 @@ function BuilderBoard({
|
|
|
20731
20842
|
};
|
|
20732
20843
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
20733
20844
|
if (!resolved) return null;
|
|
20845
|
+
const theme = resolved.theme ?? void 0;
|
|
20846
|
+
const themeBackground = theme?.background;
|
|
20847
|
+
const headerImage = str(resolved.headerImage);
|
|
20848
|
+
const hint = str(resolved.hint);
|
|
20734
20849
|
return /* @__PURE__ */ jsx(
|
|
20735
20850
|
Box,
|
|
20736
20851
|
{
|
|
20737
20852
|
className,
|
|
20738
20853
|
style: {
|
|
20739
|
-
backgroundImage:
|
|
20854
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
20740
20855
|
backgroundSize: "cover",
|
|
20741
20856
|
backgroundPosition: "center"
|
|
20742
20857
|
},
|
|
20743
20858
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
20744
|
-
|
|
20859
|
+
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,
|
|
20745
20860
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20746
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
20747
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
20861
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
20862
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
20748
20863
|
] }) }),
|
|
20749
20864
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20750
20865
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
|
|
@@ -20804,9 +20919,9 @@ function BuilderBoard({
|
|
|
20804
20919
|
] }) }),
|
|
20805
20920
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
20806
20921
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
20807
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
20922
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
|
|
20808
20923
|
] }) }),
|
|
20809
|
-
showHint &&
|
|
20924
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
20810
20925
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
20811
20926
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
20812
20927
|
/* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
|
|
@@ -20825,6 +20940,7 @@ var init_BuilderBoard = __esm({
|
|
|
20825
20940
|
"components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
|
|
20826
20941
|
init_atoms2();
|
|
20827
20942
|
init_useEventBus();
|
|
20943
|
+
init_boardEntity();
|
|
20828
20944
|
BuilderBoard.displayName = "BuilderBoard";
|
|
20829
20945
|
}
|
|
20830
20946
|
});
|
|
@@ -21162,21 +21278,24 @@ function CalendarGrid({
|
|
|
21162
21278
|
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
21163
21279
|
}, 500);
|
|
21164
21280
|
}, [longPressEvent, longPressPayload, eventBus]);
|
|
21165
|
-
const renderEvent = (event) =>
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
|
|
21170
|
-
|
|
21171
|
-
|
|
21172
|
-
|
|
21173
|
-
|
|
21174
|
-
|
|
21175
|
-
|
|
21176
|
-
|
|
21177
|
-
|
|
21178
|
-
|
|
21179
|
-
|
|
21281
|
+
const renderEvent = (event) => {
|
|
21282
|
+
const color = event.color;
|
|
21283
|
+
return /* @__PURE__ */ jsx(
|
|
21284
|
+
Box,
|
|
21285
|
+
{
|
|
21286
|
+
rounded: "md",
|
|
21287
|
+
padding: "xs",
|
|
21288
|
+
border: true,
|
|
21289
|
+
className: cn(
|
|
21290
|
+
"cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
|
|
21291
|
+
color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
|
|
21292
|
+
),
|
|
21293
|
+
onClick: (e) => handleEventClick(event, e),
|
|
21294
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
|
|
21295
|
+
},
|
|
21296
|
+
event.id
|
|
21297
|
+
);
|
|
21298
|
+
};
|
|
21180
21299
|
return /* @__PURE__ */ jsxs(
|
|
21181
21300
|
Box,
|
|
21182
21301
|
{
|
|
@@ -22840,7 +22959,6 @@ var init_CardGrid = __esm({
|
|
|
22840
22959
|
alignItems = "stretch",
|
|
22841
22960
|
className,
|
|
22842
22961
|
children,
|
|
22843
|
-
// EntityDisplayProps
|
|
22844
22962
|
entity,
|
|
22845
22963
|
isLoading = false,
|
|
22846
22964
|
error = null,
|
|
@@ -23312,14 +23430,14 @@ var init_CaseStudyOrganism = __esm({
|
|
|
23312
23430
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsx(
|
|
23313
23431
|
CaseStudyCard,
|
|
23314
23432
|
{
|
|
23315
|
-
title: study.title,
|
|
23316
|
-
description: study.description,
|
|
23317
|
-
category: study.category,
|
|
23318
|
-
categoryColor: study.categoryColor,
|
|
23319
|
-
href: study.href,
|
|
23320
|
-
linkLabel: study.linkLabel
|
|
23433
|
+
title: String(study.title ?? ""),
|
|
23434
|
+
description: String(study.description ?? ""),
|
|
23435
|
+
category: String(study.category ?? ""),
|
|
23436
|
+
categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
|
|
23437
|
+
href: String(study.href ?? ""),
|
|
23438
|
+
linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
|
|
23321
23439
|
},
|
|
23322
|
-
study.id
|
|
23440
|
+
String(study.id ?? "")
|
|
23323
23441
|
)) })
|
|
23324
23442
|
] });
|
|
23325
23443
|
};
|
|
@@ -23342,10 +23460,10 @@ function CastleBoard({
|
|
|
23342
23460
|
className
|
|
23343
23461
|
}) {
|
|
23344
23462
|
const eventBus = useEventBus();
|
|
23345
|
-
const resolved =
|
|
23346
|
-
const tiles = resolved?.tiles
|
|
23347
|
-
const features = resolved?.features
|
|
23348
|
-
const units = resolved?.units
|
|
23463
|
+
const resolved = boardEntity(entity);
|
|
23464
|
+
const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
|
|
23465
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
23466
|
+
const units = Array.isArray(resolved?.units) ? resolved.units : [];
|
|
23349
23467
|
const assetManifest = resolved?.assetManifest;
|
|
23350
23468
|
const backgroundImage = resolved?.backgroundImage;
|
|
23351
23469
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
@@ -23373,7 +23491,7 @@ function CastleBoard({
|
|
|
23373
23491
|
onFeatureClick?.(feature);
|
|
23374
23492
|
if (featureClickEvent) {
|
|
23375
23493
|
eventBus.emit(`UI:${featureClickEvent}`, {
|
|
23376
|
-
featureId: feature.id,
|
|
23494
|
+
featureId: feature.id ?? "",
|
|
23377
23495
|
featureType: feature.type,
|
|
23378
23496
|
x: feature.x,
|
|
23379
23497
|
y: feature.y
|
|
@@ -23441,6 +23559,7 @@ var init_CastleBoard = __esm({
|
|
|
23441
23559
|
init_cn();
|
|
23442
23560
|
init_useEventBus();
|
|
23443
23561
|
init_IsometricCanvas2();
|
|
23562
|
+
init_boardEntity();
|
|
23444
23563
|
init_isometric();
|
|
23445
23564
|
CastleBoard.displayName = "CastleBoard";
|
|
23446
23565
|
}
|
|
@@ -24251,14 +24370,14 @@ function ClassifierBoard({
|
|
|
24251
24370
|
}) {
|
|
24252
24371
|
const { emit } = useEventBus();
|
|
24253
24372
|
const { t } = useTranslate();
|
|
24254
|
-
const resolved =
|
|
24373
|
+
const resolved = boardEntity(entity);
|
|
24255
24374
|
const [assignments, setAssignments] = useState({});
|
|
24256
24375
|
const [headerError, setHeaderError] = useState(false);
|
|
24257
24376
|
const [submitted, setSubmitted] = useState(false);
|
|
24258
24377
|
const [attempts, setAttempts] = useState(0);
|
|
24259
24378
|
const [showHint, setShowHint] = useState(false);
|
|
24260
|
-
const items = resolved?.items
|
|
24261
|
-
const categories = resolved?.categories
|
|
24379
|
+
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
24380
|
+
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
24262
24381
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
24263
24382
|
const allAssigned = Object.keys(assignments).length === items.length;
|
|
24264
24383
|
const results = submitted ? items.map((item) => ({
|
|
@@ -24290,7 +24409,7 @@ function ClassifierBoard({
|
|
|
24290
24409
|
}, [items, assignments, attempts, completeEvent, emit]);
|
|
24291
24410
|
const handleReset = () => {
|
|
24292
24411
|
setSubmitted(false);
|
|
24293
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
24412
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
24294
24413
|
setShowHint(true);
|
|
24295
24414
|
}
|
|
24296
24415
|
};
|
|
@@ -24301,20 +24420,25 @@ function ClassifierBoard({
|
|
|
24301
24420
|
setShowHint(false);
|
|
24302
24421
|
};
|
|
24303
24422
|
if (!resolved) return null;
|
|
24423
|
+
const theme = resolved.theme ?? void 0;
|
|
24424
|
+
const themeBackground = theme?.background;
|
|
24425
|
+
const headerImage = str(resolved.headerImage);
|
|
24426
|
+
const hint = str(resolved.hint);
|
|
24427
|
+
const failMessage = str(resolved.failMessage);
|
|
24304
24428
|
return /* @__PURE__ */ jsx(
|
|
24305
24429
|
Box,
|
|
24306
24430
|
{
|
|
24307
24431
|
className,
|
|
24308
24432
|
style: {
|
|
24309
|
-
backgroundImage:
|
|
24433
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
24310
24434
|
backgroundSize: "cover",
|
|
24311
24435
|
backgroundPosition: "center"
|
|
24312
24436
|
},
|
|
24313
24437
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
24314
|
-
|
|
24438
|
+
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,
|
|
24315
24439
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
24316
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
24317
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
24440
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
24441
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
24318
24442
|
] }) }),
|
|
24319
24443
|
unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
24320
24444
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
|
|
@@ -24366,10 +24490,10 @@ function ClassifierBoard({
|
|
|
24366
24490
|
}) }),
|
|
24367
24491
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
24368
24492
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
24369
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
24370
|
-
!allCorrect &&
|
|
24493
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
|
|
24494
|
+
!allCorrect && failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
|
|
24371
24495
|
] }) }),
|
|
24372
|
-
showHint &&
|
|
24496
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
24373
24497
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
24374
24498
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
24375
24499
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -24388,6 +24512,7 @@ var init_ClassifierBoard = __esm({
|
|
|
24388
24512
|
"components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
|
|
24389
24513
|
init_atoms2();
|
|
24390
24514
|
init_useEventBus();
|
|
24515
|
+
init_boardEntity();
|
|
24391
24516
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
24392
24517
|
}
|
|
24393
24518
|
});
|
|
@@ -30758,7 +30883,7 @@ function InventoryPanel({
|
|
|
30758
30883
|
const slotArray = Array.from({ length: safeSlots }, (_, index) => {
|
|
30759
30884
|
return safeItems[index] ?? null;
|
|
30760
30885
|
});
|
|
30761
|
-
const
|
|
30886
|
+
const rows2 = Math.ceil(safeSlots / safeColumns);
|
|
30762
30887
|
const handleSlotClick = useCallback((index) => {
|
|
30763
30888
|
if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
|
|
30764
30889
|
onSelectSlot?.(index);
|
|
@@ -30827,7 +30952,7 @@ function InventoryPanel({
|
|
|
30827
30952
|
className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
|
|
30828
30953
|
style: {
|
|
30829
30954
|
gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
|
|
30830
|
-
gridTemplateRows: `repeat(${
|
|
30955
|
+
gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
|
|
30831
30956
|
},
|
|
30832
30957
|
children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
|
|
30833
30958
|
"button",
|
|
@@ -34791,11 +34916,11 @@ function LatticeSVG({
|
|
|
34791
34916
|
}) {
|
|
34792
34917
|
const paths = [];
|
|
34793
34918
|
const cols = 5;
|
|
34794
|
-
const
|
|
34919
|
+
const rows2 = Math.ceil(h / (w / cols));
|
|
34795
34920
|
const cellW = w / cols;
|
|
34796
34921
|
const cellH = cellW;
|
|
34797
34922
|
const bulge = cellW * 0.3;
|
|
34798
|
-
for (let row = 0; row <
|
|
34923
|
+
for (let row = 0; row < rows2; row++) {
|
|
34799
34924
|
for (let col = 0; col < cols; col++) {
|
|
34800
34925
|
const cx = col * cellW + cellW / 2;
|
|
34801
34926
|
const cy = row * cellH + cellH / 2;
|
|
@@ -35207,7 +35332,7 @@ var init_MatrixQuestion = __esm({
|
|
|
35207
35332
|
};
|
|
35208
35333
|
MatrixQuestion = ({
|
|
35209
35334
|
title,
|
|
35210
|
-
rows,
|
|
35335
|
+
rows: rows2,
|
|
35211
35336
|
columns = DEFAULT_MATRIX_COLUMNS,
|
|
35212
35337
|
values,
|
|
35213
35338
|
onChange,
|
|
@@ -35217,7 +35342,7 @@ var init_MatrixQuestion = __esm({
|
|
|
35217
35342
|
className
|
|
35218
35343
|
}) => {
|
|
35219
35344
|
const styles = sizeStyles13[size];
|
|
35220
|
-
const safeRows =
|
|
35345
|
+
const safeRows = rows2 ?? [];
|
|
35221
35346
|
const safeValues = values ?? {};
|
|
35222
35347
|
const eventBus = useEventBus();
|
|
35223
35348
|
const handleChange = useCallback(
|
|
@@ -35845,7 +35970,8 @@ var init_PositionedCanvas = __esm({
|
|
|
35845
35970
|
dragRef.current = null;
|
|
35846
35971
|
setDraggingId(null);
|
|
35847
35972
|
if (!wasDrag) {
|
|
35848
|
-
const
|
|
35973
|
+
const itemId = item.id;
|
|
35974
|
+
const next = selectedId === itemId ? null : itemId;
|
|
35849
35975
|
onSelect?.(next);
|
|
35850
35976
|
if (selectEvent) {
|
|
35851
35977
|
eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
@@ -35880,15 +36006,22 @@ var init_PositionedCanvas = __esm({
|
|
|
35880
36006
|
style: { width, height },
|
|
35881
36007
|
onClick: handleContainerClick,
|
|
35882
36008
|
children: items.map((item) => {
|
|
36009
|
+
const itemId = item.id;
|
|
36010
|
+
const label = item.label;
|
|
36011
|
+
const x = item.x;
|
|
36012
|
+
const y = item.y;
|
|
36013
|
+
const capacity = item.capacity;
|
|
36014
|
+
const partySize = item.partySize;
|
|
36015
|
+
const serverName = item.serverName;
|
|
35883
36016
|
const status = item.status ?? "empty";
|
|
35884
36017
|
const shape = item.shape ?? "round";
|
|
35885
|
-
const isSelected = selectedId ===
|
|
35886
|
-
const isDragging = draggingId ===
|
|
36018
|
+
const isSelected = selectedId === itemId;
|
|
36019
|
+
const isDragging = draggingId === itemId;
|
|
35887
36020
|
const statusBadge = STATUS_BADGE[status];
|
|
35888
36021
|
return /* @__PURE__ */ jsxs(
|
|
35889
36022
|
Box,
|
|
35890
36023
|
{
|
|
35891
|
-
"data-testid": `item-node-${
|
|
36024
|
+
"data-testid": `item-node-${itemId}`,
|
|
35892
36025
|
"data-status": status,
|
|
35893
36026
|
className: cn(
|
|
35894
36027
|
"absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
|
|
@@ -35899,7 +36032,7 @@ var init_PositionedCanvas = __esm({
|
|
|
35899
36032
|
isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
|
|
35900
36033
|
isDragging && "shadow-lg z-10"
|
|
35901
36034
|
),
|
|
35902
|
-
style: { left:
|
|
36035
|
+
style: { left: x, top: y, touchAction: "none" },
|
|
35903
36036
|
onPointerDown: (e) => handlePointerDown(e, item),
|
|
35904
36037
|
onPointerMove: handlePointerMove,
|
|
35905
36038
|
onPointerUp: (e) => handlePointerUp(e, item),
|
|
@@ -35907,10 +36040,10 @@ var init_PositionedCanvas = __esm({
|
|
|
35907
36040
|
children: [
|
|
35908
36041
|
/* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", children: [
|
|
35909
36042
|
getStatusIcon(status),
|
|
35910
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children:
|
|
36043
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children: label })
|
|
35911
36044
|
] }),
|
|
35912
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
35913
|
-
status === "seated" &&
|
|
36045
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
|
|
36046
|
+
status === "seated" && serverName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
|
|
35914
36047
|
isSelected && /* @__PURE__ */ jsx(
|
|
35915
36048
|
Badge,
|
|
35916
36049
|
{
|
|
@@ -35922,7 +36055,7 @@ var init_PositionedCanvas = __esm({
|
|
|
35922
36055
|
)
|
|
35923
36056
|
]
|
|
35924
36057
|
},
|
|
35925
|
-
|
|
36058
|
+
itemId
|
|
35926
36059
|
);
|
|
35927
36060
|
})
|
|
35928
36061
|
}
|
|
@@ -36694,9 +36827,10 @@ var init_RichBlockEditor = __esm({
|
|
|
36694
36827
|
});
|
|
36695
36828
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
36696
36829
|
for (const n of nodes) {
|
|
36830
|
+
const replies = n.replies;
|
|
36697
36831
|
if (n.collapsed) acc.add(n.id);
|
|
36698
|
-
if (
|
|
36699
|
-
collectInitiallyCollapsed(
|
|
36832
|
+
if (replies && replies.length > 0) {
|
|
36833
|
+
collectInitiallyCollapsed(replies, acc);
|
|
36700
36834
|
}
|
|
36701
36835
|
}
|
|
36702
36836
|
}
|
|
@@ -36726,44 +36860,52 @@ var init_ReplyTree = __esm({
|
|
|
36726
36860
|
}) => {
|
|
36727
36861
|
const eventBus = useEventBus();
|
|
36728
36862
|
const { t } = useTranslate();
|
|
36729
|
-
const
|
|
36730
|
-
const
|
|
36863
|
+
const nodeId = node.id;
|
|
36864
|
+
const authorName = node.authorName;
|
|
36865
|
+
const authorAvatarUrl = node.authorAvatarUrl;
|
|
36866
|
+
const content = node.content;
|
|
36867
|
+
const postedAt = node.postedAt;
|
|
36868
|
+
const voteCount = node.voteCount;
|
|
36869
|
+
const userVote = node.userVote;
|
|
36870
|
+
const replies = node.replies;
|
|
36871
|
+
const hasReplies = !!replies && replies.length > 0;
|
|
36872
|
+
const isCollapsed = collapsedSet.has(nodeId);
|
|
36731
36873
|
const atMaxDepth = depth >= maxDepth;
|
|
36732
36874
|
const [replyOpen, setReplyOpen] = useState(false);
|
|
36733
36875
|
const [draft, setDraft] = useState("");
|
|
36734
36876
|
const handleVote = useCallback(
|
|
36735
36877
|
(next) => {
|
|
36736
|
-
onVote?.(
|
|
36737
|
-
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId
|
|
36878
|
+
onVote?.(nodeId, next);
|
|
36879
|
+
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
|
|
36738
36880
|
},
|
|
36739
|
-
[
|
|
36881
|
+
[nodeId, onVote, voteEvent, eventBus]
|
|
36740
36882
|
);
|
|
36741
36883
|
const handleReply = useCallback(() => {
|
|
36742
|
-
onReply?.(
|
|
36884
|
+
onReply?.(nodeId);
|
|
36743
36885
|
setReplyOpen((open) => !open);
|
|
36744
|
-
}, [
|
|
36886
|
+
}, [nodeId, onReply]);
|
|
36745
36887
|
const handleSubmitReply = useCallback(() => {
|
|
36746
|
-
const
|
|
36747
|
-
if (!
|
|
36748
|
-
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId:
|
|
36888
|
+
const text = draft.trim();
|
|
36889
|
+
if (!text) return;
|
|
36890
|
+
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
|
|
36749
36891
|
setDraft("");
|
|
36750
36892
|
setReplyOpen(false);
|
|
36751
|
-
}, [
|
|
36893
|
+
}, [nodeId, draft, replyEvent, eventBus]);
|
|
36752
36894
|
const handleCancelReply = useCallback(() => {
|
|
36753
36895
|
setDraft("");
|
|
36754
36896
|
setReplyOpen(false);
|
|
36755
36897
|
}, []);
|
|
36756
36898
|
const handleFlag = useCallback(() => {
|
|
36757
|
-
onFlag?.(
|
|
36758
|
-
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId
|
|
36759
|
-
}, [
|
|
36899
|
+
onFlag?.(nodeId);
|
|
36900
|
+
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
|
|
36901
|
+
}, [nodeId, onFlag, flagEvent, eventBus]);
|
|
36760
36902
|
const handleContinue = useCallback(() => {
|
|
36761
|
-
onContinueThread?.(
|
|
36762
|
-
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId
|
|
36763
|
-
}, [
|
|
36903
|
+
onContinueThread?.(nodeId);
|
|
36904
|
+
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
|
|
36905
|
+
}, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
|
|
36764
36906
|
const handleToggle = useCallback(() => {
|
|
36765
|
-
toggleCollapse(
|
|
36766
|
-
}, [
|
|
36907
|
+
toggleCollapse(nodeId);
|
|
36908
|
+
}, [nodeId, toggleCollapse]);
|
|
36767
36909
|
return /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
|
|
36768
36910
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
|
|
36769
36911
|
hasReplies ? /* @__PURE__ */ jsx(
|
|
@@ -36795,25 +36937,25 @@ var init_ReplyTree = __esm({
|
|
|
36795
36937
|
/* @__PURE__ */ jsx(
|
|
36796
36938
|
Avatar,
|
|
36797
36939
|
{
|
|
36798
|
-
src:
|
|
36799
|
-
name:
|
|
36940
|
+
src: authorAvatarUrl,
|
|
36941
|
+
name: authorName,
|
|
36800
36942
|
size: "sm"
|
|
36801
36943
|
}
|
|
36802
36944
|
),
|
|
36803
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children:
|
|
36804
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
36945
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
|
|
36946
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
|
|
36805
36947
|
] }),
|
|
36806
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children:
|
|
36948
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
|
|
36807
36949
|
showActions && /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
36808
36950
|
/* @__PURE__ */ jsx(
|
|
36809
36951
|
VoteStack,
|
|
36810
36952
|
{
|
|
36811
|
-
count:
|
|
36812
|
-
userVote:
|
|
36953
|
+
count: voteCount ?? 0,
|
|
36954
|
+
userVote: userVote ?? null,
|
|
36813
36955
|
onVote: handleVote,
|
|
36814
36956
|
size: "sm",
|
|
36815
36957
|
variant: "horizontal",
|
|
36816
|
-
label: t("replyTree.voteOnReplyBy", { author:
|
|
36958
|
+
label: t("replyTree.voteOnReplyBy", { author: authorName })
|
|
36817
36959
|
}
|
|
36818
36960
|
),
|
|
36819
36961
|
/* @__PURE__ */ jsx(
|
|
@@ -36823,7 +36965,7 @@ var init_ReplyTree = __esm({
|
|
|
36823
36965
|
size: "sm",
|
|
36824
36966
|
leftIcon: "message-square",
|
|
36825
36967
|
onClick: handleReply,
|
|
36826
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
36968
|
+
"aria-label": t("replyTree.replyTo", { author: authorName }),
|
|
36827
36969
|
children: t("replyTree.reply")
|
|
36828
36970
|
}
|
|
36829
36971
|
),
|
|
@@ -36834,7 +36976,7 @@ var init_ReplyTree = __esm({
|
|
|
36834
36976
|
size: "sm",
|
|
36835
36977
|
leftIcon: "flag",
|
|
36836
36978
|
onClick: handleFlag,
|
|
36837
|
-
"aria-label": t("replyTree.flagReplyBy", { author:
|
|
36979
|
+
"aria-label": t("replyTree.flagReplyBy", { author: authorName }),
|
|
36838
36980
|
children: t("replyTree.flag")
|
|
36839
36981
|
}
|
|
36840
36982
|
)
|
|
@@ -36846,9 +36988,9 @@ var init_ReplyTree = __esm({
|
|
|
36846
36988
|
inputType: "textarea",
|
|
36847
36989
|
rows: 2,
|
|
36848
36990
|
value: draft,
|
|
36849
|
-
placeholder: t("replyTree.replyToPlaceholder", { author:
|
|
36991
|
+
placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
|
|
36850
36992
|
onChange: (e) => setDraft(e.target.value),
|
|
36851
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
36993
|
+
"aria-label": t("replyTree.replyTo", { author: authorName })
|
|
36852
36994
|
}
|
|
36853
36995
|
),
|
|
36854
36996
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
@@ -36879,7 +37021,7 @@ var init_ReplyTree = __esm({
|
|
|
36879
37021
|
),
|
|
36880
37022
|
children: t("replyTree.continueThread")
|
|
36881
37023
|
}
|
|
36882
|
-
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children:
|
|
37024
|
+
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsx(
|
|
36883
37025
|
ReplyTreeNode,
|
|
36884
37026
|
{
|
|
36885
37027
|
node: child,
|
|
@@ -38790,8 +38932,8 @@ var init_WizardContainer = __esm({
|
|
|
38790
38932
|
return void 0;
|
|
38791
38933
|
if (typeof controlledStep === "number") return controlledStep;
|
|
38792
38934
|
if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
|
|
38793
|
-
const
|
|
38794
|
-
return isNaN(
|
|
38935
|
+
const num2 = Number(controlledStep);
|
|
38936
|
+
return isNaN(num2) ? void 0 : num2;
|
|
38795
38937
|
})();
|
|
38796
38938
|
const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
|
|
38797
38939
|
const totalSteps = steps.length;
|
|
@@ -40496,7 +40638,7 @@ function DebuggerBoard({
|
|
|
40496
40638
|
}) {
|
|
40497
40639
|
const { emit } = useEventBus();
|
|
40498
40640
|
const { t } = useTranslate();
|
|
40499
|
-
const resolved =
|
|
40641
|
+
const resolved = boardEntity(entity);
|
|
40500
40642
|
const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
|
|
40501
40643
|
const [headerError, setHeaderError] = useState(false);
|
|
40502
40644
|
const [submitted, setSubmitted] = useState(false);
|
|
@@ -40514,7 +40656,7 @@ function DebuggerBoard({
|
|
|
40514
40656
|
return next;
|
|
40515
40657
|
});
|
|
40516
40658
|
};
|
|
40517
|
-
const lines = resolved?.lines
|
|
40659
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
40518
40660
|
const bugLines = lines.filter((l) => l.isBug);
|
|
40519
40661
|
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
40520
40662
|
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
@@ -40529,7 +40671,7 @@ function DebuggerBoard({
|
|
|
40529
40671
|
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
40530
40672
|
const handleReset = () => {
|
|
40531
40673
|
setSubmitted(false);
|
|
40532
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
40674
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
40533
40675
|
setShowHint(true);
|
|
40534
40676
|
}
|
|
40535
40677
|
};
|
|
@@ -40540,24 +40682,28 @@ function DebuggerBoard({
|
|
|
40540
40682
|
setShowHint(false);
|
|
40541
40683
|
};
|
|
40542
40684
|
if (!resolved) return null;
|
|
40685
|
+
const theme = resolved.theme ?? void 0;
|
|
40686
|
+
const themeBackground = theme?.background;
|
|
40687
|
+
const headerImage = str(resolved.headerImage);
|
|
40688
|
+
const hint = str(resolved.hint);
|
|
40543
40689
|
return /* @__PURE__ */ jsx(
|
|
40544
40690
|
Box,
|
|
40545
40691
|
{
|
|
40546
40692
|
className,
|
|
40547
40693
|
style: {
|
|
40548
|
-
backgroundImage:
|
|
40694
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
40549
40695
|
backgroundSize: "cover",
|
|
40550
40696
|
backgroundPosition: "center"
|
|
40551
40697
|
},
|
|
40552
40698
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
40553
|
-
|
|
40699
|
+
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,
|
|
40554
40700
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
40555
40701
|
/* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
40556
40702
|
/* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
|
|
40557
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
|
|
40703
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
|
|
40558
40704
|
] }),
|
|
40559
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
40560
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
|
|
40705
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
40706
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
40561
40707
|
] }) }),
|
|
40562
40708
|
/* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
40563
40709
|
const isFlagged = flaggedLines.has(line.id);
|
|
@@ -40589,7 +40735,7 @@ function DebuggerBoard({
|
|
|
40589
40735
|
);
|
|
40590
40736
|
}) }) }),
|
|
40591
40737
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
40592
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
40738
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
40593
40739
|
bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
40594
40740
|
/* @__PURE__ */ jsx(
|
|
40595
40741
|
Icon,
|
|
@@ -40605,7 +40751,7 @@ function DebuggerBoard({
|
|
|
40605
40751
|
] })
|
|
40606
40752
|
] }, line.id))
|
|
40607
40753
|
] }) }),
|
|
40608
|
-
showHint &&
|
|
40754
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
40609
40755
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
40610
40756
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
40611
40757
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -40624,6 +40770,7 @@ var init_DebuggerBoard = __esm({
|
|
|
40624
40770
|
"components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
|
|
40625
40771
|
init_atoms2();
|
|
40626
40772
|
init_useEventBus();
|
|
40773
|
+
init_boardEntity();
|
|
40627
40774
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
40628
40775
|
}
|
|
40629
40776
|
});
|
|
@@ -40661,7 +40808,7 @@ function getBadgeVariant(fieldName, value) {
|
|
|
40661
40808
|
return "default";
|
|
40662
40809
|
}
|
|
40663
40810
|
function formatFieldLabel(fieldName) {
|
|
40664
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
40811
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
|
|
40665
40812
|
}
|
|
40666
40813
|
function formatFieldValue(value, fieldName) {
|
|
40667
40814
|
if (typeof value === "number") {
|
|
@@ -40680,26 +40827,26 @@ function formatFieldValue(value, fieldName) {
|
|
|
40680
40827
|
}
|
|
40681
40828
|
function renderRichFieldValue(value, fieldName, fieldType) {
|
|
40682
40829
|
if (value === void 0 || value === null) return "\u2014";
|
|
40683
|
-
const
|
|
40830
|
+
const str2 = String(value);
|
|
40684
40831
|
switch (fieldType) {
|
|
40685
40832
|
case "image":
|
|
40686
40833
|
case "url": {
|
|
40687
|
-
if (
|
|
40834
|
+
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
40688
40835
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
40689
40836
|
"img",
|
|
40690
40837
|
{
|
|
40691
|
-
src:
|
|
40838
|
+
src: str2,
|
|
40692
40839
|
alt: formatFieldLabel(fieldName),
|
|
40693
40840
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
40694
40841
|
loading: "lazy"
|
|
40695
40842
|
}
|
|
40696
40843
|
) });
|
|
40697
40844
|
}
|
|
40698
|
-
return
|
|
40845
|
+
return str2;
|
|
40699
40846
|
}
|
|
40700
40847
|
case "markdown":
|
|
40701
40848
|
case "richtext":
|
|
40702
|
-
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children:
|
|
40849
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsx(
|
|
40703
40850
|
Box,
|
|
40704
40851
|
{
|
|
40705
40852
|
className: "prose prose-sm max-w-none",
|
|
@@ -40717,11 +40864,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40717
40864
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
40718
40865
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
40719
40866
|
},
|
|
40720
|
-
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children:
|
|
40867
|
+
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children: str2 })
|
|
40721
40868
|
}
|
|
40722
40869
|
) });
|
|
40723
40870
|
case "code":
|
|
40724
|
-
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:
|
|
40871
|
+
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 }) }) });
|
|
40725
40872
|
case "html":
|
|
40726
40873
|
return /* @__PURE__ */ jsx(
|
|
40727
40874
|
Box,
|
|
@@ -40741,12 +40888,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40741
40888
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
40742
40889
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
40743
40890
|
},
|
|
40744
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children:
|
|
40891
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: str2 })
|
|
40745
40892
|
}
|
|
40746
40893
|
);
|
|
40747
40894
|
case "date":
|
|
40748
40895
|
case "datetime": {
|
|
40749
|
-
const d = new Date(
|
|
40896
|
+
const d = new Date(str2);
|
|
40750
40897
|
if (!isNaN(d.getTime())) {
|
|
40751
40898
|
return d.toLocaleDateString(void 0, {
|
|
40752
40899
|
year: "numeric",
|
|
@@ -40755,7 +40902,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40755
40902
|
...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
|
|
40756
40903
|
});
|
|
40757
40904
|
}
|
|
40758
|
-
return
|
|
40905
|
+
return str2;
|
|
40759
40906
|
}
|
|
40760
40907
|
default:
|
|
40761
40908
|
return formatFieldValue(value, fieldName);
|
|
@@ -41433,6 +41580,40 @@ var init_RuleEditor = __esm({
|
|
|
41433
41580
|
RuleEditor.displayName = "RuleEditor";
|
|
41434
41581
|
}
|
|
41435
41582
|
});
|
|
41583
|
+
|
|
41584
|
+
// components/game/organisms/puzzles/event-handler/puzzleObject.ts
|
|
41585
|
+
function objId(o) {
|
|
41586
|
+
return o.id == null ? "" : String(o.id);
|
|
41587
|
+
}
|
|
41588
|
+
function objName(o) {
|
|
41589
|
+
return o.name == null ? "" : String(o.name);
|
|
41590
|
+
}
|
|
41591
|
+
function objIcon(o) {
|
|
41592
|
+
return o.icon == null ? "" : String(o.icon);
|
|
41593
|
+
}
|
|
41594
|
+
function objStates(o) {
|
|
41595
|
+
return Array.isArray(o.states) ? o.states : [];
|
|
41596
|
+
}
|
|
41597
|
+
function objCurrentState(o) {
|
|
41598
|
+
return o.currentState == null ? "" : String(o.currentState);
|
|
41599
|
+
}
|
|
41600
|
+
function objAvailableEvents(o) {
|
|
41601
|
+
return Array.isArray(o.availableEvents) ? o.availableEvents : [];
|
|
41602
|
+
}
|
|
41603
|
+
function objAvailableActions(o) {
|
|
41604
|
+
return Array.isArray(o.availableActions) ? o.availableActions : [];
|
|
41605
|
+
}
|
|
41606
|
+
function objRules(o) {
|
|
41607
|
+
return Array.isArray(o.rules) ? o.rules : [];
|
|
41608
|
+
}
|
|
41609
|
+
function objMaxRules(o) {
|
|
41610
|
+
const n = Number(o.maxRules);
|
|
41611
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
41612
|
+
}
|
|
41613
|
+
var init_puzzleObject = __esm({
|
|
41614
|
+
"components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
|
|
41615
|
+
}
|
|
41616
|
+
});
|
|
41436
41617
|
function ObjectRulePanel({
|
|
41437
41618
|
object,
|
|
41438
41619
|
onRulesChange,
|
|
@@ -41440,55 +41621,63 @@ function ObjectRulePanel({
|
|
|
41440
41621
|
className
|
|
41441
41622
|
}) {
|
|
41442
41623
|
const { t } = useTranslate();
|
|
41443
|
-
const
|
|
41444
|
-
const
|
|
41624
|
+
const id = objId(object);
|
|
41625
|
+
const name = objName(object);
|
|
41626
|
+
const icon = objIcon(object);
|
|
41627
|
+
const states = objStates(object);
|
|
41628
|
+
const currentState = objCurrentState(object);
|
|
41629
|
+
const availableEvents = objAvailableEvents(object);
|
|
41630
|
+
const availableActions = objAvailableActions(object);
|
|
41631
|
+
const rules = objRules(object);
|
|
41632
|
+
const maxRules = objMaxRules(object);
|
|
41633
|
+
const canAdd = rules.length < maxRules;
|
|
41445
41634
|
const handleRuleChange = useCallback((index, updatedRule) => {
|
|
41446
|
-
const newRules = [...
|
|
41635
|
+
const newRules = [...rules];
|
|
41447
41636
|
newRules[index] = updatedRule;
|
|
41448
|
-
onRulesChange(
|
|
41449
|
-
}, [
|
|
41637
|
+
onRulesChange(id, newRules);
|
|
41638
|
+
}, [id, rules, onRulesChange]);
|
|
41450
41639
|
const handleRuleRemove = useCallback((index) => {
|
|
41451
|
-
const newRules =
|
|
41452
|
-
onRulesChange(
|
|
41453
|
-
}, [
|
|
41640
|
+
const newRules = rules.filter((_, i) => i !== index);
|
|
41641
|
+
onRulesChange(id, newRules);
|
|
41642
|
+
}, [id, rules, onRulesChange]);
|
|
41454
41643
|
const handleAddRule = useCallback(() => {
|
|
41455
41644
|
if (!canAdd || disabled) return;
|
|
41456
|
-
const firstEvent =
|
|
41457
|
-
const firstAction =
|
|
41645
|
+
const firstEvent = availableEvents[0]?.value || "";
|
|
41646
|
+
const firstAction = availableActions[0]?.value || "";
|
|
41458
41647
|
const newRule = {
|
|
41459
41648
|
id: `rule-${nextRuleId++}`,
|
|
41460
41649
|
whenEvent: firstEvent,
|
|
41461
41650
|
thenAction: firstAction
|
|
41462
41651
|
};
|
|
41463
|
-
onRulesChange(
|
|
41464
|
-
}, [canAdd, disabled,
|
|
41652
|
+
onRulesChange(id, [...rules, newRule]);
|
|
41653
|
+
}, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
|
|
41465
41654
|
const machine = {
|
|
41466
|
-
name
|
|
41467
|
-
states
|
|
41468
|
-
currentState
|
|
41469
|
-
transitions:
|
|
41470
|
-
from:
|
|
41471
|
-
to:
|
|
41655
|
+
name,
|
|
41656
|
+
states,
|
|
41657
|
+
currentState,
|
|
41658
|
+
transitions: rules.map((r2) => ({
|
|
41659
|
+
from: currentState,
|
|
41660
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
41472
41661
|
event: r2.whenEvent
|
|
41473
41662
|
}))
|
|
41474
41663
|
};
|
|
41475
41664
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
41476
41665
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center", gap: "sm", children: [
|
|
41477
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h5", children:
|
|
41666
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: icon }),
|
|
41478
41667
|
/* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
41479
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children:
|
|
41480
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " +
|
|
41668
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
|
|
41669
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
|
|
41481
41670
|
] })
|
|
41482
41671
|
] }),
|
|
41483
41672
|
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
|
|
41484
41673
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
41485
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count:
|
|
41486
|
-
|
|
41674
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
|
|
41675
|
+
rules.map((rule, i) => /* @__PURE__ */ jsx(
|
|
41487
41676
|
RuleEditor,
|
|
41488
41677
|
{
|
|
41489
41678
|
rule,
|
|
41490
|
-
availableEvents
|
|
41491
|
-
availableActions
|
|
41679
|
+
availableEvents,
|
|
41680
|
+
availableActions,
|
|
41492
41681
|
onChange: (r2) => handleRuleChange(i, r2),
|
|
41493
41682
|
onRemove: () => handleRuleRemove(i),
|
|
41494
41683
|
disabled
|
|
@@ -41506,6 +41695,7 @@ var init_ObjectRulePanel = __esm({
|
|
|
41506
41695
|
init_cn();
|
|
41507
41696
|
init_TraitStateViewer();
|
|
41508
41697
|
init_RuleEditor();
|
|
41698
|
+
init_puzzleObject();
|
|
41509
41699
|
nextRuleId = 1;
|
|
41510
41700
|
ObjectRulePanel.displayName = "ObjectRulePanel";
|
|
41511
41701
|
}
|
|
@@ -41572,11 +41762,11 @@ function EventHandlerBoard({
|
|
|
41572
41762
|
}) {
|
|
41573
41763
|
const { emit } = useEventBus();
|
|
41574
41764
|
const { t } = useTranslate();
|
|
41575
|
-
const resolved =
|
|
41576
|
-
const entityObjects = resolved?.objects
|
|
41577
|
-
const [objects, setObjects] = useState(entityObjects);
|
|
41765
|
+
const resolved = boardEntity(entity);
|
|
41766
|
+
const entityObjects = rows(resolved?.objects);
|
|
41767
|
+
const [objects, setObjects] = useState(() => [...entityObjects]);
|
|
41578
41768
|
const [selectedObjectId, setSelectedObjectId] = useState(
|
|
41579
|
-
entityObjects[0]
|
|
41769
|
+
entityObjects[0] ? objId(entityObjects[0]) : null
|
|
41580
41770
|
);
|
|
41581
41771
|
const [headerError, setHeaderError] = useState(false);
|
|
41582
41772
|
const [playState, setPlayState] = useState("editing");
|
|
@@ -41587,10 +41777,10 @@ function EventHandlerBoard({
|
|
|
41587
41777
|
useEffect(() => () => {
|
|
41588
41778
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
41589
41779
|
}, []);
|
|
41590
|
-
const selectedObject = objects.find((o) => o
|
|
41780
|
+
const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
|
|
41591
41781
|
const handleRulesChange = useCallback((objectId, rules) => {
|
|
41592
41782
|
setObjects((prev) => prev.map(
|
|
41593
|
-
(o) => o
|
|
41783
|
+
(o) => objId(o) === objectId ? { ...o, rules } : o
|
|
41594
41784
|
));
|
|
41595
41785
|
}, []);
|
|
41596
41786
|
const addLogEntry = useCallback((icon, message, status = "done") => {
|
|
@@ -41604,11 +41794,12 @@ function EventHandlerBoard({
|
|
|
41604
41794
|
setEventLog([]);
|
|
41605
41795
|
const allRules = [];
|
|
41606
41796
|
objects.forEach((obj) => {
|
|
41607
|
-
obj.
|
|
41797
|
+
objRules(obj).forEach((rule) => {
|
|
41608
41798
|
allRules.push({ object: obj, rule });
|
|
41609
41799
|
});
|
|
41610
41800
|
});
|
|
41611
|
-
const triggers = resolved?.triggerEvents
|
|
41801
|
+
const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
|
|
41802
|
+
const goalEvent = str(resolved?.goalEvent);
|
|
41612
41803
|
const eventQueue = [...triggers];
|
|
41613
41804
|
const firedEvents = /* @__PURE__ */ new Set();
|
|
41614
41805
|
let stepIdx = 0;
|
|
@@ -41637,14 +41828,14 @@ function EventHandlerBoard({
|
|
|
41637
41828
|
addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
|
|
41638
41829
|
} else {
|
|
41639
41830
|
matching.forEach(({ object, rule }) => {
|
|
41640
|
-
addLogEntry(object
|
|
41831
|
+
addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
|
|
41641
41832
|
eventQueue.push(rule.thenAction);
|
|
41642
|
-
if (rule.thenAction ===
|
|
41833
|
+
if (rule.thenAction === goalEvent) {
|
|
41643
41834
|
goalReached = true;
|
|
41644
41835
|
}
|
|
41645
41836
|
});
|
|
41646
41837
|
}
|
|
41647
|
-
if (currentEvent ===
|
|
41838
|
+
if (currentEvent === goalEvent) {
|
|
41648
41839
|
goalReached = true;
|
|
41649
41840
|
}
|
|
41650
41841
|
stepIdx++;
|
|
@@ -41662,65 +41853,75 @@ function EventHandlerBoard({
|
|
|
41662
41853
|
}, []);
|
|
41663
41854
|
const handleReset = useCallback(() => {
|
|
41664
41855
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
41665
|
-
|
|
41856
|
+
const resetObjects = rows(resolved?.objects);
|
|
41857
|
+
setObjects([...resetObjects]);
|
|
41666
41858
|
setPlayState("editing");
|
|
41667
41859
|
setEventLog([]);
|
|
41668
|
-
setSelectedObjectId(
|
|
41860
|
+
setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
|
|
41669
41861
|
setAttempts(0);
|
|
41670
41862
|
}, [resolved?.objects]);
|
|
41671
41863
|
if (!resolved) return null;
|
|
41672
41864
|
const objectViewers = objects.map((obj) => {
|
|
41865
|
+
const states = objStates(obj);
|
|
41866
|
+
const currentState = objCurrentState(obj);
|
|
41673
41867
|
const machine = {
|
|
41674
|
-
name: obj
|
|
41675
|
-
states
|
|
41676
|
-
currentState
|
|
41677
|
-
transitions: obj.
|
|
41678
|
-
from:
|
|
41679
|
-
to:
|
|
41868
|
+
name: objName(obj),
|
|
41869
|
+
states,
|
|
41870
|
+
currentState,
|
|
41871
|
+
transitions: objRules(obj).map((r2) => ({
|
|
41872
|
+
from: currentState,
|
|
41873
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
41680
41874
|
event: r2.whenEvent
|
|
41681
41875
|
}))
|
|
41682
41876
|
};
|
|
41683
41877
|
return { obj, machine };
|
|
41684
41878
|
});
|
|
41685
|
-
const
|
|
41879
|
+
const hint = str(resolved.hint);
|
|
41880
|
+
const showHint = attempts >= 3 && hint;
|
|
41881
|
+
const theme = resolved.theme ?? void 0;
|
|
41882
|
+
const themeBackground = theme?.background;
|
|
41883
|
+
const headerImage = str(resolved.headerImage);
|
|
41686
41884
|
const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
|
|
41687
41885
|
return /* @__PURE__ */ jsxs(
|
|
41688
41886
|
VStack,
|
|
41689
41887
|
{
|
|
41690
41888
|
className: cn("p-4 gap-6", className),
|
|
41691
41889
|
style: {
|
|
41692
|
-
backgroundImage:
|
|
41890
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
41693
41891
|
backgroundSize: "cover",
|
|
41694
41892
|
backgroundPosition: "center"
|
|
41695
41893
|
},
|
|
41696
41894
|
children: [
|
|
41697
|
-
|
|
41895
|
+
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,
|
|
41698
41896
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
41699
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
41700
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
41897
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
41898
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
41701
41899
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
41702
41900
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
41703
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
|
|
41901
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
|
|
41704
41902
|
] })
|
|
41705
41903
|
] }),
|
|
41706
41904
|
/* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
41707
41905
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
41708
|
-
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) =>
|
|
41709
|
-
|
|
41710
|
-
|
|
41711
|
-
|
|
41712
|
-
|
|
41713
|
-
|
|
41714
|
-
|
|
41715
|
-
|
|
41716
|
-
|
|
41717
|
-
|
|
41718
|
-
/* @__PURE__ */
|
|
41719
|
-
|
|
41720
|
-
|
|
41721
|
-
|
|
41722
|
-
|
|
41723
|
-
|
|
41906
|
+
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
|
|
41907
|
+
const oid = objId(obj);
|
|
41908
|
+
return /* @__PURE__ */ jsx(
|
|
41909
|
+
Box,
|
|
41910
|
+
{
|
|
41911
|
+
className: cn(
|
|
41912
|
+
"p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
|
|
41913
|
+
selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
41914
|
+
),
|
|
41915
|
+
onClick: () => setSelectedObjectId(oid),
|
|
41916
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
41917
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: objIcon(obj) }),
|
|
41918
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
|
|
41919
|
+
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
41920
|
+
] })
|
|
41921
|
+
},
|
|
41922
|
+
oid
|
|
41923
|
+
);
|
|
41924
|
+
}) })
|
|
41724
41925
|
] }),
|
|
41725
41926
|
selectedObject && /* @__PURE__ */ jsx(
|
|
41726
41927
|
ObjectRulePanel,
|
|
@@ -41731,12 +41932,12 @@ function EventHandlerBoard({
|
|
|
41731
41932
|
}
|
|
41732
41933
|
),
|
|
41733
41934
|
eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
|
|
41734
|
-
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") }) }),
|
|
41935
|
+
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") }) }),
|
|
41735
41936
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
41736
41937
|
/* @__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) }) }),
|
|
41737
41938
|
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: [
|
|
41738
41939
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
41739
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
41940
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
41740
41941
|
] }) })
|
|
41741
41942
|
] }),
|
|
41742
41943
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -41764,6 +41965,8 @@ var init_EventHandlerBoard = __esm({
|
|
|
41764
41965
|
init_TraitStateViewer();
|
|
41765
41966
|
init_ObjectRulePanel();
|
|
41766
41967
|
init_EventLog();
|
|
41968
|
+
init_puzzleObject();
|
|
41969
|
+
init_boardEntity();
|
|
41767
41970
|
ENCOURAGEMENT_KEYS = [
|
|
41768
41971
|
"puzzle.tryAgain1",
|
|
41769
41972
|
"puzzle.tryAgain2",
|
|
@@ -41852,7 +42055,10 @@ var init_FeatureGridOrganism = __esm({
|
|
|
41852
42055
|
);
|
|
41853
42056
|
useCallback(
|
|
41854
42057
|
(feature) => {
|
|
41855
|
-
eventBus.emit("UI:FEATURE_CLICK", {
|
|
42058
|
+
eventBus.emit("UI:FEATURE_CLICK", {
|
|
42059
|
+
id: String(feature.id ?? ""),
|
|
42060
|
+
href: String(feature.href ?? "")
|
|
42061
|
+
});
|
|
41856
42062
|
},
|
|
41857
42063
|
[eventBus]
|
|
41858
42064
|
);
|
|
@@ -41862,14 +42068,17 @@ var init_FeatureGridOrganism = __esm({
|
|
|
41862
42068
|
if (error) {
|
|
41863
42069
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
41864
42070
|
}
|
|
41865
|
-
const featureCards = items.map((feature) =>
|
|
41866
|
-
|
|
41867
|
-
|
|
41868
|
-
|
|
41869
|
-
|
|
41870
|
-
|
|
41871
|
-
|
|
41872
|
-
|
|
42071
|
+
const featureCards = items.map((feature) => {
|
|
42072
|
+
const href = feature.href != null ? String(feature.href) : void 0;
|
|
42073
|
+
return {
|
|
42074
|
+
icon: feature.icon != null ? String(feature.icon) : void 0,
|
|
42075
|
+
title: String(feature.title ?? ""),
|
|
42076
|
+
description: String(feature.description ?? ""),
|
|
42077
|
+
href,
|
|
42078
|
+
linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
|
|
42079
|
+
variant: href ? "interactive" : "bordered"
|
|
42080
|
+
};
|
|
42081
|
+
});
|
|
41873
42082
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
41874
42083
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
41875
42084
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
@@ -43187,22 +43396,24 @@ var init_HeroOrganism = __esm({
|
|
|
43187
43396
|
() => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
|
|
43188
43397
|
[entity]
|
|
43189
43398
|
);
|
|
43399
|
+
const primaryAction = resolved?.primaryAction;
|
|
43400
|
+
const secondaryAction = resolved?.secondaryAction;
|
|
43190
43401
|
const handlePrimaryClick = useCallback(() => {
|
|
43191
|
-
if (
|
|
43402
|
+
if (primaryAction) {
|
|
43192
43403
|
eventBus.emit("UI:CTA_PRIMARY", {
|
|
43193
|
-
label:
|
|
43194
|
-
href:
|
|
43404
|
+
label: String(primaryAction.label ?? ""),
|
|
43405
|
+
href: String(primaryAction.href ?? "")
|
|
43195
43406
|
});
|
|
43196
43407
|
}
|
|
43197
|
-
}, [eventBus,
|
|
43408
|
+
}, [eventBus, primaryAction]);
|
|
43198
43409
|
const handleSecondaryClick = useCallback(() => {
|
|
43199
|
-
if (
|
|
43410
|
+
if (secondaryAction) {
|
|
43200
43411
|
eventBus.emit("UI:CTA_SECONDARY", {
|
|
43201
|
-
label:
|
|
43202
|
-
href:
|
|
43412
|
+
label: String(secondaryAction.label ?? ""),
|
|
43413
|
+
href: String(secondaryAction.href ?? "")
|
|
43203
43414
|
});
|
|
43204
43415
|
}
|
|
43205
|
-
}, [eventBus,
|
|
43416
|
+
}, [eventBus, secondaryAction]);
|
|
43206
43417
|
if (isLoading) {
|
|
43207
43418
|
return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
|
|
43208
43419
|
}
|
|
@@ -43212,17 +43423,19 @@ var init_HeroOrganism = __esm({
|
|
|
43212
43423
|
if (!resolved) {
|
|
43213
43424
|
return null;
|
|
43214
43425
|
}
|
|
43426
|
+
const imageRaw = resolved.image;
|
|
43427
|
+
const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
|
|
43215
43428
|
return /* @__PURE__ */ jsxs(
|
|
43216
43429
|
HeroSection,
|
|
43217
43430
|
{
|
|
43218
|
-
tag: resolved.tag,
|
|
43219
|
-
title: resolved.title,
|
|
43220
|
-
titleAccent: resolved.titleAccent,
|
|
43221
|
-
subtitle: resolved.subtitle,
|
|
43222
|
-
primaryAction:
|
|
43223
|
-
secondaryAction:
|
|
43224
|
-
installCommand: resolved.installCommand,
|
|
43225
|
-
image
|
|
43431
|
+
tag: resolved.tag != null ? String(resolved.tag) : void 0,
|
|
43432
|
+
title: String(resolved.title ?? ""),
|
|
43433
|
+
titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
|
|
43434
|
+
subtitle: String(resolved.subtitle ?? ""),
|
|
43435
|
+
primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
|
|
43436
|
+
secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
|
|
43437
|
+
installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
|
|
43438
|
+
image,
|
|
43226
43439
|
imagePosition: resolved.imagePosition,
|
|
43227
43440
|
background: resolved.background,
|
|
43228
43441
|
className: cn(className),
|
|
@@ -43231,8 +43444,8 @@ var init_HeroOrganism = __esm({
|
|
|
43231
43444
|
/* @__PURE__ */ jsx(
|
|
43232
43445
|
_HeroClickInterceptor,
|
|
43233
43446
|
{
|
|
43234
|
-
hasPrimary: !!
|
|
43235
|
-
hasSecondary: !!
|
|
43447
|
+
hasPrimary: !!primaryAction,
|
|
43448
|
+
hasSecondary: !!secondaryAction,
|
|
43236
43449
|
onPrimaryClick: handlePrimaryClick,
|
|
43237
43450
|
onSecondaryClick: handleSecondaryClick
|
|
43238
43451
|
}
|
|
@@ -43461,7 +43674,7 @@ function formatValue3(value, fieldName) {
|
|
|
43461
43674
|
return String(value);
|
|
43462
43675
|
}
|
|
43463
43676
|
function formatFieldLabel2(fieldName) {
|
|
43464
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
43677
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
|
|
43465
43678
|
}
|
|
43466
43679
|
var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
|
|
43467
43680
|
var init_List = __esm({
|
|
@@ -44308,20 +44521,22 @@ function NegotiatorBoard({
|
|
|
44308
44521
|
}) {
|
|
44309
44522
|
const { emit } = useEventBus();
|
|
44310
44523
|
const { t } = useTranslate();
|
|
44311
|
-
const resolved =
|
|
44524
|
+
const resolved = boardEntity(entity);
|
|
44312
44525
|
const [history, setHistory] = useState([]);
|
|
44313
44526
|
const [headerError, setHeaderError] = useState(false);
|
|
44314
44527
|
const [showHint, setShowHint] = useState(false);
|
|
44528
|
+
const totalRounds = num(resolved?.totalRounds);
|
|
44529
|
+
const targetScore = num(resolved?.targetScore);
|
|
44315
44530
|
const currentRound = history.length;
|
|
44316
|
-
const isComplete = currentRound >=
|
|
44531
|
+
const isComplete = currentRound >= totalRounds;
|
|
44317
44532
|
const playerTotal = history.reduce((s, r2) => s + r2.playerPayoff, 0);
|
|
44318
44533
|
const opponentTotal = history.reduce((s, r2) => s + r2.opponentPayoff, 0);
|
|
44319
|
-
const won = isComplete && playerTotal >=
|
|
44320
|
-
const actions = resolved?.actions
|
|
44321
|
-
const payoffMatrix = resolved?.payoffMatrix
|
|
44534
|
+
const won = isComplete && playerTotal >= targetScore;
|
|
44535
|
+
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
44536
|
+
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
44322
44537
|
const handleAction = useCallback((actionId) => {
|
|
44323
44538
|
if (isComplete) return;
|
|
44324
|
-
const opponentAction = getOpponentAction(resolved?.opponentStrategy
|
|
44539
|
+
const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
|
|
44325
44540
|
const payoff = payoffMatrix.find(
|
|
44326
44541
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
44327
44542
|
);
|
|
@@ -44334,42 +44549,46 @@ function NegotiatorBoard({
|
|
|
44334
44549
|
};
|
|
44335
44550
|
const newHistory = [...history, result];
|
|
44336
44551
|
setHistory(newHistory);
|
|
44337
|
-
if (newHistory.length >=
|
|
44552
|
+
if (newHistory.length >= totalRounds) {
|
|
44338
44553
|
const total = newHistory.reduce((s, r2) => s + r2.playerPayoff, 0);
|
|
44339
|
-
if (total >=
|
|
44554
|
+
if (total >= targetScore) {
|
|
44340
44555
|
emit(`UI:${completeEvent}`, { success: true, score: total });
|
|
44341
44556
|
}
|
|
44342
|
-
if (newHistory.length >= 3 && resolved?.hint) {
|
|
44557
|
+
if (newHistory.length >= 3 && str(resolved?.hint)) {
|
|
44343
44558
|
setShowHint(true);
|
|
44344
44559
|
}
|
|
44345
44560
|
}
|
|
44346
|
-
}, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
44561
|
+
}, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
44347
44562
|
const handleReset = () => {
|
|
44348
44563
|
setHistory([]);
|
|
44349
44564
|
setShowHint(false);
|
|
44350
44565
|
};
|
|
44351
44566
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
44352
44567
|
if (!resolved) return null;
|
|
44568
|
+
const theme = resolved.theme ?? void 0;
|
|
44569
|
+
const themeBackground = theme?.background;
|
|
44570
|
+
const headerImage = str(resolved.headerImage);
|
|
44571
|
+
const hint = str(resolved.hint);
|
|
44353
44572
|
return /* @__PURE__ */ jsx(
|
|
44354
44573
|
Box,
|
|
44355
44574
|
{
|
|
44356
44575
|
className,
|
|
44357
44576
|
style: {
|
|
44358
|
-
backgroundImage:
|
|
44577
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44359
44578
|
backgroundSize: "cover",
|
|
44360
44579
|
backgroundPosition: "center"
|
|
44361
44580
|
},
|
|
44362
44581
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
44363
|
-
|
|
44582
|
+
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,
|
|
44364
44583
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44365
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
44366
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
44584
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
44585
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
44367
44586
|
/* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
|
|
44368
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(
|
|
44587
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
|
|
44369
44588
|
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
44370
44589
|
t("negotiator.target"),
|
|
44371
44590
|
": ",
|
|
44372
|
-
|
|
44591
|
+
targetScore
|
|
44373
44592
|
] })
|
|
44374
44593
|
] })
|
|
44375
44594
|
] }) }),
|
|
@@ -44418,16 +44637,16 @@ function NegotiatorBoard({
|
|
|
44418
44637
|
] }) }),
|
|
44419
44638
|
isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
44420
44639
|
/* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
|
|
44421
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage
|
|
44640
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
|
|
44422
44641
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
44423
44642
|
t("negotiator.finalScore"),
|
|
44424
44643
|
": ",
|
|
44425
44644
|
playerTotal,
|
|
44426
44645
|
"/",
|
|
44427
|
-
|
|
44646
|
+
targetScore
|
|
44428
44647
|
] })
|
|
44429
44648
|
] }) }),
|
|
44430
|
-
showHint &&
|
|
44649
|
+
showHint && hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
44431
44650
|
isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
44432
44651
|
] })
|
|
44433
44652
|
}
|
|
@@ -44437,6 +44656,7 @@ var init_NegotiatorBoard = __esm({
|
|
|
44437
44656
|
"components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
|
|
44438
44657
|
init_atoms2();
|
|
44439
44658
|
init_useEventBus();
|
|
44659
|
+
init_boardEntity();
|
|
44440
44660
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
44441
44661
|
}
|
|
44442
44662
|
});
|
|
@@ -44472,13 +44692,13 @@ var init_PricingOrganism = __esm({
|
|
|
44472
44692
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
44473
44693
|
}
|
|
44474
44694
|
const plans = items.map((plan) => ({
|
|
44475
|
-
name: plan.name,
|
|
44476
|
-
price: plan.price,
|
|
44477
|
-
description: plan.description,
|
|
44478
|
-
features: plan.features,
|
|
44479
|
-
action: { label: plan.actionLabel, href: plan.actionHref },
|
|
44480
|
-
highlighted: plan.highlighted,
|
|
44481
|
-
badge: plan.badge
|
|
44695
|
+
name: String(plan.name ?? ""),
|
|
44696
|
+
price: String(plan.price ?? ""),
|
|
44697
|
+
description: plan.description != null ? String(plan.description) : void 0,
|
|
44698
|
+
features: (plan.features ?? []).map((f3) => String(f3)),
|
|
44699
|
+
action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
|
|
44700
|
+
highlighted: Boolean(plan.highlighted),
|
|
44701
|
+
badge: plan.badge != null ? String(plan.badge) : void 0
|
|
44482
44702
|
}));
|
|
44483
44703
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
44484
44704
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -46568,16 +46788,20 @@ function SequencerBoard({
|
|
|
46568
46788
|
}) {
|
|
46569
46789
|
const { emit } = useEventBus();
|
|
46570
46790
|
const { t } = useTranslate();
|
|
46571
|
-
const resolved =
|
|
46791
|
+
const resolved = boardEntity(entity);
|
|
46792
|
+
const maxSlots = num(resolved?.maxSlots);
|
|
46793
|
+
const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
|
|
46794
|
+
const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
|
|
46795
|
+
const allowDuplicates = resolved?.allowDuplicates !== false;
|
|
46572
46796
|
const [headerError, setHeaderError] = useState(false);
|
|
46573
46797
|
const [slots, setSlots] = useState(
|
|
46574
|
-
() => Array.from({ length:
|
|
46798
|
+
() => Array.from({ length: maxSlots }, () => void 0)
|
|
46575
46799
|
);
|
|
46576
46800
|
const [playState, setPlayState] = useState("idle");
|
|
46577
46801
|
const [currentStep, setCurrentStep] = useState(-1);
|
|
46578
46802
|
const [attempts, setAttempts] = useState(0);
|
|
46579
46803
|
const [slotFeedback, setSlotFeedback] = useState(
|
|
46580
|
-
() => Array.from({ length:
|
|
46804
|
+
() => Array.from({ length: maxSlots }, () => null)
|
|
46581
46805
|
);
|
|
46582
46806
|
const timerRef = useRef(null);
|
|
46583
46807
|
useEffect(() => () => {
|
|
@@ -46611,17 +46835,17 @@ function SequencerBoard({
|
|
|
46611
46835
|
}, [emit]);
|
|
46612
46836
|
const handleReset = useCallback(() => {
|
|
46613
46837
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
46614
|
-
setSlots(Array.from({ length:
|
|
46838
|
+
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
46615
46839
|
setPlayState("idle");
|
|
46616
46840
|
setCurrentStep(-1);
|
|
46617
46841
|
setAttempts(0);
|
|
46618
|
-
setSlotFeedback(Array.from({ length:
|
|
46619
|
-
}, [
|
|
46842
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
46843
|
+
}, [maxSlots]);
|
|
46620
46844
|
const filledSlots = slots.filter((s) => !!s);
|
|
46621
46845
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
46622
46846
|
const handlePlay = useCallback(() => {
|
|
46623
46847
|
if (!canPlay) return;
|
|
46624
|
-
setSlotFeedback(Array.from({ length:
|
|
46848
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
46625
46849
|
emit("UI:PLAY_SOUND", { key: "confirm" });
|
|
46626
46850
|
const sequence = slots.map((s) => s?.id || "");
|
|
46627
46851
|
if (playEvent) {
|
|
@@ -46632,10 +46856,10 @@ function SequencerBoard({
|
|
|
46632
46856
|
let step = 0;
|
|
46633
46857
|
const advance = () => {
|
|
46634
46858
|
step++;
|
|
46635
|
-
if (step >=
|
|
46859
|
+
if (step >= maxSlots) {
|
|
46636
46860
|
const playerSeq = slots.map((s) => s?.id);
|
|
46637
46861
|
const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
|
|
46638
|
-
const success =
|
|
46862
|
+
const success = solutions.some(
|
|
46639
46863
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
46640
46864
|
);
|
|
46641
46865
|
if (success) {
|
|
@@ -46647,7 +46871,7 @@ function SequencerBoard({
|
|
|
46647
46871
|
}
|
|
46648
46872
|
} else {
|
|
46649
46873
|
setAttempts((prev) => prev + 1);
|
|
46650
|
-
const feedback = computeSlotFeedback(playerSeq,
|
|
46874
|
+
const feedback = computeSlotFeedback(playerSeq, solutions);
|
|
46651
46875
|
setSlotFeedback(feedback);
|
|
46652
46876
|
setPlayState("idle");
|
|
46653
46877
|
setCurrentStep(-1);
|
|
@@ -46665,10 +46889,10 @@ function SequencerBoard({
|
|
|
46665
46889
|
}
|
|
46666
46890
|
};
|
|
46667
46891
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
46668
|
-
}, [canPlay, slots,
|
|
46892
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
46669
46893
|
const machine = {
|
|
46670
|
-
name: resolved?.title
|
|
46671
|
-
description: resolved?.description
|
|
46894
|
+
name: str(resolved?.title),
|
|
46895
|
+
description: str(resolved?.description),
|
|
46672
46896
|
states: slots.map((s, i) => stepLabel(s, i)),
|
|
46673
46897
|
currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
|
|
46674
46898
|
transitions: slots.slice(0, -1).map((s, i) => ({
|
|
@@ -46677,37 +46901,41 @@ function SequencerBoard({
|
|
|
46677
46901
|
event: "NEXT"
|
|
46678
46902
|
}))
|
|
46679
46903
|
};
|
|
46680
|
-
const usedIds =
|
|
46681
|
-
const
|
|
46904
|
+
const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
|
|
46905
|
+
const hint = str(resolved?.hint);
|
|
46906
|
+
const showHint = attempts >= 3 && !!hint;
|
|
46682
46907
|
const hasFeedback = slotFeedback.some((f3) => f3 !== null);
|
|
46683
46908
|
const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
|
|
46684
46909
|
const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
|
|
46685
46910
|
if (!resolved) return null;
|
|
46911
|
+
const theme = resolved.theme ?? void 0;
|
|
46912
|
+
const themeBackground = theme?.background;
|
|
46913
|
+
const headerImage = str(resolved.headerImage);
|
|
46686
46914
|
return /* @__PURE__ */ jsxs(
|
|
46687
46915
|
VStack,
|
|
46688
46916
|
{
|
|
46689
46917
|
className: cn("p-4 gap-6", className),
|
|
46690
46918
|
style: {
|
|
46691
|
-
backgroundImage:
|
|
46919
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
46692
46920
|
backgroundSize: "cover",
|
|
46693
46921
|
backgroundPosition: "center"
|
|
46694
46922
|
},
|
|
46695
46923
|
children: [
|
|
46696
|
-
|
|
46924
|
+
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,
|
|
46697
46925
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
46698
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
46699
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
|
|
46926
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
46927
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
|
|
46700
46928
|
] }),
|
|
46701
46929
|
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: [
|
|
46702
46930
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
46703
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
46931
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
46704
46932
|
] }) }),
|
|
46705
46933
|
filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
46706
46934
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
46707
46935
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
46708
46936
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
46709
46937
|
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
46710
|
-
`${correctCount}/${
|
|
46938
|
+
`${correctCount}/${maxSlots} `,
|
|
46711
46939
|
"\u2705"
|
|
46712
46940
|
] })
|
|
46713
46941
|
] }),
|
|
@@ -46715,7 +46943,7 @@ function SequencerBoard({
|
|
|
46715
46943
|
SequenceBar,
|
|
46716
46944
|
{
|
|
46717
46945
|
slots,
|
|
46718
|
-
maxSlots
|
|
46946
|
+
maxSlots,
|
|
46719
46947
|
onSlotDrop: handleSlotDrop,
|
|
46720
46948
|
onSlotRemove: handleSlotRemove,
|
|
46721
46949
|
playing: playState === "playing",
|
|
@@ -46729,15 +46957,15 @@ function SequencerBoard({
|
|
|
46729
46957
|
playState !== "playing" && /* @__PURE__ */ jsx(
|
|
46730
46958
|
ActionPalette,
|
|
46731
46959
|
{
|
|
46732
|
-
actions:
|
|
46960
|
+
actions: availableActions,
|
|
46733
46961
|
usedActionIds: usedIds,
|
|
46734
|
-
allowDuplicates
|
|
46962
|
+
allowDuplicates,
|
|
46735
46963
|
categoryColors,
|
|
46736
46964
|
label: t("sequencer.dragActions")
|
|
46737
46965
|
}
|
|
46738
46966
|
),
|
|
46739
46967
|
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) }) }),
|
|
46740
|
-
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") }) }),
|
|
46968
|
+
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") }) }),
|
|
46741
46969
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
46742
46970
|
/* @__PURE__ */ jsx(
|
|
46743
46971
|
Button,
|
|
@@ -46761,6 +46989,7 @@ var init_SequencerBoard = __esm({
|
|
|
46761
46989
|
init_cn();
|
|
46762
46990
|
init_useEventBus();
|
|
46763
46991
|
init_TraitStateViewer();
|
|
46992
|
+
init_boardEntity();
|
|
46764
46993
|
init_SequenceBar();
|
|
46765
46994
|
init_ActionPalette();
|
|
46766
46995
|
ENCOURAGEMENT_KEYS2 = [
|
|
@@ -46810,18 +47039,21 @@ var init_ShowcaseOrganism = __esm({
|
|
|
46810
47039
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
46811
47040
|
subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
|
|
46812
47041
|
] }),
|
|
46813
|
-
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) =>
|
|
46814
|
-
|
|
46815
|
-
|
|
46816
|
-
|
|
46817
|
-
|
|
46818
|
-
|
|
46819
|
-
|
|
46820
|
-
|
|
46821
|
-
|
|
46822
|
-
|
|
46823
|
-
|
|
46824
|
-
|
|
47042
|
+
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
|
|
47043
|
+
const imageRaw = item.image;
|
|
47044
|
+
return /* @__PURE__ */ jsx(
|
|
47045
|
+
ShowcaseCard,
|
|
47046
|
+
{
|
|
47047
|
+
title: String(item.title ?? ""),
|
|
47048
|
+
description: item.description != null ? String(item.description) : void 0,
|
|
47049
|
+
image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
|
|
47050
|
+
href: item.href != null ? String(item.href) : void 0,
|
|
47051
|
+
badge: item.badge != null ? String(item.badge) : void 0,
|
|
47052
|
+
accentColor: item.accentColor != null ? String(item.accentColor) : void 0
|
|
47053
|
+
},
|
|
47054
|
+
String(item.id ?? "")
|
|
47055
|
+
);
|
|
47056
|
+
}) })
|
|
46825
47057
|
] });
|
|
46826
47058
|
};
|
|
46827
47059
|
ShowcaseOrganism.displayName = "ShowcaseOrganism";
|
|
@@ -47189,8 +47421,8 @@ function SimulatorBoard({
|
|
|
47189
47421
|
}) {
|
|
47190
47422
|
const { emit } = useEventBus();
|
|
47191
47423
|
const { t } = useTranslate();
|
|
47192
|
-
const resolved =
|
|
47193
|
-
const parameters = resolved?.parameters
|
|
47424
|
+
const resolved = boardEntity(entity);
|
|
47425
|
+
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
47194
47426
|
const [values, setValues] = useState(() => {
|
|
47195
47427
|
const init = {};
|
|
47196
47428
|
for (const p2 of parameters) {
|
|
@@ -47204,15 +47436,15 @@ function SimulatorBoard({
|
|
|
47204
47436
|
const [showHint, setShowHint] = useState(false);
|
|
47205
47437
|
const computeOutput = useCallback((params) => {
|
|
47206
47438
|
try {
|
|
47207
|
-
const fn = new Function("params", `return (${resolved?.computeExpression})`);
|
|
47439
|
+
const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
|
|
47208
47440
|
return fn(params);
|
|
47209
47441
|
} catch {
|
|
47210
47442
|
return 0;
|
|
47211
47443
|
}
|
|
47212
47444
|
}, [resolved?.computeExpression]);
|
|
47213
47445
|
const output = useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
|
|
47214
|
-
const targetValue = resolved?.targetValue
|
|
47215
|
-
const targetTolerance = resolved?.targetTolerance
|
|
47446
|
+
const targetValue = num(resolved?.targetValue);
|
|
47447
|
+
const targetTolerance = num(resolved?.targetTolerance);
|
|
47216
47448
|
const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
|
|
47217
47449
|
const handleParameterChange = (id, value) => {
|
|
47218
47450
|
if (submitted) return;
|
|
@@ -47227,7 +47459,7 @@ function SimulatorBoard({
|
|
|
47227
47459
|
};
|
|
47228
47460
|
const handleReset = () => {
|
|
47229
47461
|
setSubmitted(false);
|
|
47230
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
47462
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
47231
47463
|
setShowHint(true);
|
|
47232
47464
|
}
|
|
47233
47465
|
};
|
|
@@ -47242,20 +47474,26 @@ function SimulatorBoard({
|
|
|
47242
47474
|
setShowHint(false);
|
|
47243
47475
|
};
|
|
47244
47476
|
if (!resolved) return null;
|
|
47477
|
+
const theme = resolved.theme ?? void 0;
|
|
47478
|
+
const themeBackground = theme?.background;
|
|
47479
|
+
const headerImage = str(resolved.headerImage);
|
|
47480
|
+
const hint = str(resolved.hint);
|
|
47481
|
+
const outputLabel = str(resolved.outputLabel);
|
|
47482
|
+
const outputUnit = str(resolved.outputUnit);
|
|
47245
47483
|
return /* @__PURE__ */ jsx(
|
|
47246
47484
|
Box,
|
|
47247
47485
|
{
|
|
47248
47486
|
className,
|
|
47249
47487
|
style: {
|
|
47250
|
-
backgroundImage:
|
|
47488
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
47251
47489
|
backgroundSize: "cover",
|
|
47252
47490
|
backgroundPosition: "center"
|
|
47253
47491
|
},
|
|
47254
47492
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
47255
|
-
|
|
47493
|
+
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,
|
|
47256
47494
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
47257
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
47258
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
47495
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
47496
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
47259
47497
|
] }) }),
|
|
47260
47498
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
47261
47499
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
@@ -47296,28 +47534,28 @@ function SimulatorBoard({
|
|
|
47296
47534
|
] }, param.id))
|
|
47297
47535
|
] }) }),
|
|
47298
47536
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
47299
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children:
|
|
47537
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
47300
47538
|
/* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
47301
47539
|
output.toFixed(2),
|
|
47302
47540
|
" ",
|
|
47303
|
-
|
|
47541
|
+
outputUnit
|
|
47304
47542
|
] }),
|
|
47305
47543
|
submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
47306
47544
|
/* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
|
|
47307
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage
|
|
47545
|
+
/* @__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") })
|
|
47308
47546
|
] }),
|
|
47309
47547
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47310
47548
|
t("simulator.target"),
|
|
47311
47549
|
": ",
|
|
47312
47550
|
targetValue,
|
|
47313
47551
|
" ",
|
|
47314
|
-
|
|
47552
|
+
outputUnit,
|
|
47315
47553
|
" (\xB1",
|
|
47316
47554
|
targetTolerance,
|
|
47317
47555
|
")"
|
|
47318
47556
|
] })
|
|
47319
47557
|
] }) }),
|
|
47320
|
-
showHint &&
|
|
47558
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
47321
47559
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
47322
47560
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
47323
47561
|
/* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
|
|
@@ -47336,6 +47574,7 @@ var init_SimulatorBoard = __esm({
|
|
|
47336
47574
|
"components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
|
|
47337
47575
|
init_atoms2();
|
|
47338
47576
|
init_useEventBus();
|
|
47577
|
+
init_boardEntity();
|
|
47339
47578
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
47340
47579
|
}
|
|
47341
47580
|
});
|
|
@@ -47761,22 +48000,25 @@ function VariablePanel({
|
|
|
47761
48000
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
47762
48001
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
|
|
47763
48002
|
variables.map((v) => {
|
|
47764
|
-
const
|
|
47765
|
-
const
|
|
47766
|
-
const
|
|
48003
|
+
const name = v.name == null ? "" : String(v.name);
|
|
48004
|
+
const value = numField(v.value);
|
|
48005
|
+
const max = numField(v.max, 100);
|
|
48006
|
+
const min = numField(v.min, 0);
|
|
48007
|
+
const unit = v.unit == null ? "" : String(v.unit);
|
|
48008
|
+
const pct = Math.round((value - min) / (max - min) * 100);
|
|
47767
48009
|
const isHigh = pct > 80;
|
|
47768
48010
|
const isLow = pct < 20;
|
|
47769
48011
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
47770
48012
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
47771
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children:
|
|
48013
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
|
|
47772
48014
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: cn(
|
|
47773
48015
|
isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
|
|
47774
48016
|
), children: [
|
|
47775
|
-
|
|
47776
|
-
|
|
48017
|
+
value,
|
|
48018
|
+
unit,
|
|
47777
48019
|
" / ",
|
|
47778
48020
|
max,
|
|
47779
|
-
|
|
48021
|
+
unit
|
|
47780
48022
|
] })
|
|
47781
48023
|
] }),
|
|
47782
48024
|
/* @__PURE__ */ jsx(
|
|
@@ -47787,14 +48029,19 @@ function VariablePanel({
|
|
|
47787
48029
|
size: "sm"
|
|
47788
48030
|
}
|
|
47789
48031
|
)
|
|
47790
|
-
] },
|
|
48032
|
+
] }, name);
|
|
47791
48033
|
})
|
|
47792
48034
|
] });
|
|
47793
48035
|
}
|
|
48036
|
+
var numField;
|
|
47794
48037
|
var init_VariablePanel = __esm({
|
|
47795
48038
|
"components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
|
|
47796
48039
|
init_atoms2();
|
|
47797
48040
|
init_cn();
|
|
48041
|
+
numField = (v, fallback = 0) => {
|
|
48042
|
+
const n = Number(v);
|
|
48043
|
+
return Number.isFinite(n) ? n : fallback;
|
|
48044
|
+
};
|
|
47798
48045
|
VariablePanel.displayName = "VariablePanel";
|
|
47799
48046
|
}
|
|
47800
48047
|
});
|
|
@@ -47821,14 +48068,21 @@ function StateArchitectBoard({
|
|
|
47821
48068
|
}) {
|
|
47822
48069
|
const { emit } = useEventBus();
|
|
47823
48070
|
const { t } = useTranslate();
|
|
47824
|
-
const resolved =
|
|
47825
|
-
const
|
|
48071
|
+
const resolved = boardEntity(entity);
|
|
48072
|
+
const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
|
|
48073
|
+
const initialState = str(resolved?.initialState);
|
|
48074
|
+
const entityName = str(resolved?.entityName);
|
|
48075
|
+
const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
|
|
48076
|
+
const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
|
|
48077
|
+
const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
|
|
48078
|
+
const entityVariables = rows(resolved?.variables);
|
|
48079
|
+
const [transitions, setTransitions] = useState(entityTransitions);
|
|
47826
48080
|
const [headerError, setHeaderError] = useState(false);
|
|
47827
48081
|
const [playState, setPlayState] = useState("editing");
|
|
47828
|
-
const [currentState, setCurrentState] = useState(
|
|
48082
|
+
const [currentState, setCurrentState] = useState(initialState);
|
|
47829
48083
|
const [selectedState, setSelectedState] = useState(null);
|
|
47830
48084
|
const [testResults, setTestResults] = useState([]);
|
|
47831
|
-
const [variables, setVariables] = useState(
|
|
48085
|
+
const [variables, setVariables] = useState(() => [...entityVariables]);
|
|
47832
48086
|
const [attempts, setAttempts] = useState(0);
|
|
47833
48087
|
const timerRef = useRef(null);
|
|
47834
48088
|
const [addingFrom, setAddingFrom] = useState(null);
|
|
@@ -47837,12 +48091,12 @@ function StateArchitectBoard({
|
|
|
47837
48091
|
}, []);
|
|
47838
48092
|
const GRAPH_W = 500;
|
|
47839
48093
|
const GRAPH_H = 400;
|
|
47840
|
-
const positions = useMemo(() => layoutStates(
|
|
48094
|
+
const positions = useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
|
|
47841
48095
|
const handleStateClick = useCallback((state) => {
|
|
47842
48096
|
if (playState !== "editing") return;
|
|
47843
48097
|
if (addingFrom) {
|
|
47844
48098
|
if (addingFrom !== state) {
|
|
47845
|
-
const event =
|
|
48099
|
+
const event = availableEvents[0] || "EVENT";
|
|
47846
48100
|
const newTrans = {
|
|
47847
48101
|
id: `t-${nextTransId++}`,
|
|
47848
48102
|
from: addingFrom,
|
|
@@ -47855,7 +48109,7 @@ function StateArchitectBoard({
|
|
|
47855
48109
|
} else {
|
|
47856
48110
|
setSelectedState(state);
|
|
47857
48111
|
}
|
|
47858
|
-
}, [playState, addingFrom,
|
|
48112
|
+
}, [playState, addingFrom, availableEvents]);
|
|
47859
48113
|
const handleStartAddTransition = useCallback(() => {
|
|
47860
48114
|
if (!selectedState) return;
|
|
47861
48115
|
setAddingFrom(selectedState);
|
|
@@ -47864,9 +48118,9 @@ function StateArchitectBoard({
|
|
|
47864
48118
|
setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
|
|
47865
48119
|
}, []);
|
|
47866
48120
|
const machine = useMemo(() => ({
|
|
47867
|
-
name:
|
|
47868
|
-
description: resolved?.description
|
|
47869
|
-
states:
|
|
48121
|
+
name: entityName,
|
|
48122
|
+
description: str(resolved?.description),
|
|
48123
|
+
states: entityStates,
|
|
47870
48124
|
currentState,
|
|
47871
48125
|
transitions: transitions.map((t2) => ({
|
|
47872
48126
|
from: t2.from,
|
|
@@ -47874,7 +48128,7 @@ function StateArchitectBoard({
|
|
|
47874
48128
|
event: t2.event,
|
|
47875
48129
|
guardHint: t2.guardHint
|
|
47876
48130
|
}))
|
|
47877
|
-
}), [resolved, currentState, transitions]);
|
|
48131
|
+
}), [entityName, resolved, entityStates, currentState, transitions]);
|
|
47878
48132
|
const handleTest = useCallback(() => {
|
|
47879
48133
|
if (playState !== "editing") return;
|
|
47880
48134
|
if (testEvent) emit(`UI:${testEvent}`, {});
|
|
@@ -47883,7 +48137,7 @@ function StateArchitectBoard({
|
|
|
47883
48137
|
const results = [];
|
|
47884
48138
|
let testIdx = 0;
|
|
47885
48139
|
const runNextTest = () => {
|
|
47886
|
-
if (testIdx >=
|
|
48140
|
+
if (testIdx >= testCases.length) {
|
|
47887
48141
|
const allPassed = results.every((r2) => r2.passed);
|
|
47888
48142
|
setPlayState(allPassed ? "success" : "fail");
|
|
47889
48143
|
setTestResults(results);
|
|
@@ -47898,9 +48152,9 @@ function StateArchitectBoard({
|
|
|
47898
48152
|
}
|
|
47899
48153
|
return;
|
|
47900
48154
|
}
|
|
47901
|
-
const testCase =
|
|
48155
|
+
const testCase = testCases[testIdx];
|
|
47902
48156
|
if (!testCase) return;
|
|
47903
|
-
let state =
|
|
48157
|
+
let state = initialState;
|
|
47904
48158
|
for (const event of testCase.events) {
|
|
47905
48159
|
const trans = transitions.find((t2) => t2.from === state && t2.event === event);
|
|
47906
48160
|
if (trans) {
|
|
@@ -47918,53 +48172,57 @@ function StateArchitectBoard({
|
|
|
47918
48172
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
47919
48173
|
};
|
|
47920
48174
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
47921
|
-
}, [playState, transitions,
|
|
48175
|
+
}, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
|
|
47922
48176
|
const handleTryAgain = useCallback(() => {
|
|
47923
48177
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
47924
48178
|
setPlayState("editing");
|
|
47925
|
-
setCurrentState(
|
|
48179
|
+
setCurrentState(initialState);
|
|
47926
48180
|
setTestResults([]);
|
|
47927
|
-
}, [
|
|
48181
|
+
}, [initialState]);
|
|
47928
48182
|
const handleReset = useCallback(() => {
|
|
47929
48183
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
47930
|
-
setTransitions(
|
|
48184
|
+
setTransitions(entityTransitions);
|
|
47931
48185
|
setPlayState("editing");
|
|
47932
|
-
setCurrentState(
|
|
48186
|
+
setCurrentState(initialState);
|
|
47933
48187
|
setTestResults([]);
|
|
47934
|
-
setVariables(
|
|
48188
|
+
setVariables([...entityVariables]);
|
|
47935
48189
|
setSelectedState(null);
|
|
47936
48190
|
setAddingFrom(null);
|
|
47937
48191
|
setAttempts(0);
|
|
47938
|
-
}, [
|
|
48192
|
+
}, [entityTransitions, initialState, entityVariables]);
|
|
47939
48193
|
const codeData = useMemo(() => ({
|
|
47940
|
-
name:
|
|
47941
|
-
states:
|
|
47942
|
-
initialState
|
|
48194
|
+
name: entityName,
|
|
48195
|
+
states: entityStates,
|
|
48196
|
+
initialState,
|
|
47943
48197
|
transitions: transitions.map((t2) => ({
|
|
47944
48198
|
from: t2.from,
|
|
47945
48199
|
to: t2.to,
|
|
47946
48200
|
event: t2.event,
|
|
47947
48201
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
47948
48202
|
}))
|
|
47949
|
-
}), [
|
|
48203
|
+
}), [entityName, entityStates, initialState, transitions]);
|
|
47950
48204
|
if (!resolved) return null;
|
|
48205
|
+
const theme = resolved.theme ?? void 0;
|
|
48206
|
+
const themeBackground = theme?.background;
|
|
48207
|
+
const headerImage = str(resolved.headerImage);
|
|
48208
|
+
const hint = str(resolved.hint);
|
|
47951
48209
|
return /* @__PURE__ */ jsxs(
|
|
47952
48210
|
VStack,
|
|
47953
48211
|
{
|
|
47954
48212
|
className: cn("p-4 gap-6", className),
|
|
47955
48213
|
style: {
|
|
47956
|
-
backgroundImage:
|
|
48214
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
47957
48215
|
backgroundSize: "cover",
|
|
47958
48216
|
backgroundPosition: "center"
|
|
47959
48217
|
},
|
|
47960
48218
|
children: [
|
|
47961
|
-
|
|
48219
|
+
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,
|
|
47962
48220
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
47963
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
47964
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
48221
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
48222
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
47965
48223
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
47966
48224
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
47967
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children:
|
|
48225
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
|
|
47968
48226
|
] })
|
|
47969
48227
|
] }),
|
|
47970
48228
|
/* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
@@ -48012,14 +48270,14 @@ function StateArchitectBoard({
|
|
|
48012
48270
|
]
|
|
48013
48271
|
}
|
|
48014
48272
|
),
|
|
48015
|
-
|
|
48273
|
+
entityStates.map((state) => /* @__PURE__ */ jsx(
|
|
48016
48274
|
StateNode2,
|
|
48017
48275
|
{
|
|
48018
48276
|
name: state,
|
|
48019
48277
|
position: positions[state],
|
|
48020
48278
|
isCurrent: state === currentState,
|
|
48021
48279
|
isSelected: state === selectedState,
|
|
48022
|
-
isInitial: state ===
|
|
48280
|
+
isInitial: state === initialState,
|
|
48023
48281
|
onClick: () => handleStateClick(state)
|
|
48024
48282
|
},
|
|
48025
48283
|
state
|
|
@@ -48066,7 +48324,7 @@ function StateArchitectBoard({
|
|
|
48066
48324
|
/* @__PURE__ */ jsx(
|
|
48067
48325
|
VariablePanel,
|
|
48068
48326
|
{
|
|
48069
|
-
entityName
|
|
48327
|
+
entityName,
|
|
48070
48328
|
variables
|
|
48071
48329
|
}
|
|
48072
48330
|
),
|
|
@@ -48081,12 +48339,12 @@ function StateArchitectBoard({
|
|
|
48081
48339
|
resolved.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
|
|
48082
48340
|
] })
|
|
48083
48341
|
] }),
|
|
48084
|
-
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") }) }),
|
|
48342
|
+
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") }) }),
|
|
48085
48343
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
48086
48344
|
/* @__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]) }) }),
|
|
48087
|
-
attempts >= 3 &&
|
|
48345
|
+
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: [
|
|
48088
48346
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
48089
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
48347
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
48090
48348
|
] }) })
|
|
48091
48349
|
] }),
|
|
48092
48350
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -48116,6 +48374,7 @@ var init_StateArchitectBoard = __esm({
|
|
|
48116
48374
|
init_TransitionArrow();
|
|
48117
48375
|
init_VariablePanel();
|
|
48118
48376
|
init_CodeView();
|
|
48377
|
+
init_boardEntity();
|
|
48119
48378
|
ENCOURAGEMENT_KEYS3 = [
|
|
48120
48379
|
"puzzle.tryAgain1",
|
|
48121
48380
|
"puzzle.tryAgain2",
|
|
@@ -48152,8 +48411,8 @@ var init_StatsOrganism = __esm({
|
|
|
48152
48411
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
48153
48412
|
}
|
|
48154
48413
|
const stats = items.map((item) => ({
|
|
48155
|
-
value: item.value,
|
|
48156
|
-
label: item.label
|
|
48414
|
+
value: String(item.value ?? ""),
|
|
48415
|
+
label: String(item.label ?? "")
|
|
48157
48416
|
}));
|
|
48158
48417
|
return /* @__PURE__ */ jsx(
|
|
48159
48418
|
StatsGrid,
|
|
@@ -48199,10 +48458,10 @@ var init_StepFlowOrganism = __esm({
|
|
|
48199
48458
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
48200
48459
|
}
|
|
48201
48460
|
const steps = items.map((item) => ({
|
|
48202
|
-
number: item.number,
|
|
48203
|
-
title: item.title,
|
|
48204
|
-
description: item.description,
|
|
48205
|
-
icon: item.icon
|
|
48461
|
+
number: item.number != null ? Number(item.number) : void 0,
|
|
48462
|
+
title: String(item.title ?? ""),
|
|
48463
|
+
description: String(item.description ?? ""),
|
|
48464
|
+
icon: item.icon != null ? String(item.icon) : void 0
|
|
48206
48465
|
}));
|
|
48207
48466
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
48208
48467
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -48375,13 +48634,13 @@ var init_TeamOrganism = __esm({
|
|
|
48375
48634
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsx(
|
|
48376
48635
|
TeamCard,
|
|
48377
48636
|
{
|
|
48378
|
-
name: member.name,
|
|
48379
|
-
nameAr: member.nameAr,
|
|
48380
|
-
role: member.role,
|
|
48381
|
-
bio: member.bio,
|
|
48382
|
-
avatar: member.avatar
|
|
48637
|
+
name: String(member.name ?? ""),
|
|
48638
|
+
nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
|
|
48639
|
+
role: String(member.role ?? ""),
|
|
48640
|
+
bio: String(member.bio ?? ""),
|
|
48641
|
+
avatar: member.avatar != null ? String(member.avatar) : void 0
|
|
48383
48642
|
},
|
|
48384
|
-
member.id
|
|
48643
|
+
String(member.id ?? "")
|
|
48385
48644
|
)) })
|
|
48386
48645
|
] });
|
|
48387
48646
|
};
|
|
@@ -48618,8 +48877,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48618
48877
|
const [turn, setTurn] = useState(1);
|
|
48619
48878
|
const [gameResult, setGameResult] = useState(null);
|
|
48620
48879
|
const checkGameEnd = useCallback((currentUnits) => {
|
|
48621
|
-
const pa = currentUnits.filter((u) => u
|
|
48622
|
-
const ea = currentUnits.filter((u) => u
|
|
48880
|
+
const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
48881
|
+
const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
48623
48882
|
if (pa.length === 0) {
|
|
48624
48883
|
setGameResult("defeat");
|
|
48625
48884
|
setPhase("game_over");
|
|
@@ -48637,34 +48896,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48637
48896
|
}
|
|
48638
48897
|
}, [onGameEnd, gameEndEvent, eventBus]);
|
|
48639
48898
|
const handleUnitClick = useCallback((unitId) => {
|
|
48640
|
-
const unit = units.find((u) => u.id === unitId);
|
|
48899
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
48641
48900
|
if (!unit) return;
|
|
48642
48901
|
if (unitClickEvent) {
|
|
48643
48902
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
48644
48903
|
}
|
|
48645
48904
|
if (phase === "observation" || phase === "selection") {
|
|
48646
|
-
if (unit
|
|
48905
|
+
if (unitTeam(unit) === "player") {
|
|
48647
48906
|
setSelectedUnitId(unitId);
|
|
48648
48907
|
setPhase("movement");
|
|
48649
48908
|
}
|
|
48650
48909
|
} else if (phase === "action") {
|
|
48651
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
48910
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
48652
48911
|
if (!selectedUnit) return;
|
|
48653
|
-
if (unit
|
|
48654
|
-
const
|
|
48655
|
-
const
|
|
48912
|
+
if (unitTeam(unit) === "enemy") {
|
|
48913
|
+
const up = unitPosition(unit);
|
|
48914
|
+
const sp = unitPosition(selectedUnit);
|
|
48915
|
+
const dx = Math.abs(up.x - sp.x);
|
|
48916
|
+
const dy = Math.abs(up.y - sp.y);
|
|
48656
48917
|
if (dx <= 1 && dy <= 1 && dx + dy > 0) {
|
|
48657
|
-
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
48658
|
-
const newHealth = Math.max(0, unit
|
|
48918
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
48919
|
+
const newHealth = Math.max(0, unitHealth(unit) - damage);
|
|
48659
48920
|
const updatedUnits = units.map(
|
|
48660
|
-
(u) => u.id === unit.id ? { ...u, health: newHealth } : u
|
|
48921
|
+
(u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
|
|
48661
48922
|
);
|
|
48662
48923
|
setUnits(updatedUnits);
|
|
48663
48924
|
onAttack?.(selectedUnit, unit, damage);
|
|
48664
48925
|
if (attackEvent) {
|
|
48665
48926
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
48666
|
-
attackerId: selectedUnit.id,
|
|
48667
|
-
targetId: unit.id,
|
|
48927
|
+
attackerId: str(selectedUnit.id),
|
|
48928
|
+
targetId: str(unit.id),
|
|
48668
48929
|
damage
|
|
48669
48930
|
});
|
|
48670
48931
|
}
|
|
@@ -48681,16 +48942,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48681
48942
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
48682
48943
|
}
|
|
48683
48944
|
if (phase === "movement" && selectedUnitId) {
|
|
48684
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
48945
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
48685
48946
|
if (!selectedUnit) return;
|
|
48686
|
-
const
|
|
48687
|
-
const
|
|
48947
|
+
const sp = unitPosition(selectedUnit);
|
|
48948
|
+
const dx = Math.abs(x - sp.x);
|
|
48949
|
+
const dy = Math.abs(y - sp.y);
|
|
48688
48950
|
const dist = dx + dy;
|
|
48689
|
-
if (dist > 0 && dist <= selectedUnit.movement) {
|
|
48690
|
-
if (!units.some((u) =>
|
|
48951
|
+
if (dist > 0 && dist <= num(selectedUnit.movement)) {
|
|
48952
|
+
if (!units.some((u) => {
|
|
48953
|
+
const p2 = unitPosition(u);
|
|
48954
|
+
return p2.x === x && p2.y === y && unitHealth(u) > 0;
|
|
48955
|
+
})) {
|
|
48691
48956
|
setUnits(
|
|
48692
48957
|
(prev) => prev.map(
|
|
48693
|
-
(u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
48958
|
+
(u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
48694
48959
|
)
|
|
48695
48960
|
);
|
|
48696
48961
|
setPhase("action");
|
|
@@ -48733,12 +48998,13 @@ var init_useBattleState = __esm({
|
|
|
48733
48998
|
"components/game/organisms/hooks/useBattleState.ts"() {
|
|
48734
48999
|
"use client";
|
|
48735
49000
|
init_useEventBus();
|
|
49001
|
+
init_boardEntity();
|
|
48736
49002
|
}
|
|
48737
49003
|
});
|
|
48738
49004
|
function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
48739
|
-
const resolved =
|
|
49005
|
+
const resolved = boardEntity(entity);
|
|
48740
49006
|
const battleState = useBattleState(
|
|
48741
|
-
resolved?.initialUnits
|
|
49007
|
+
rows(resolved?.initialUnits),
|
|
48742
49008
|
{
|
|
48743
49009
|
tileClickEvent: rest.tileClickEvent,
|
|
48744
49010
|
unitClickEvent: rest.unitClickEvent,
|
|
@@ -48774,10 +49040,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
|
48774
49040
|
var init_UncontrolledBattleBoard = __esm({
|
|
48775
49041
|
"components/game/organisms/UncontrolledBattleBoard.tsx"() {
|
|
48776
49042
|
init_BattleBoard();
|
|
49043
|
+
init_boardEntity();
|
|
48777
49044
|
init_useBattleState();
|
|
48778
49045
|
UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
|
|
48779
49046
|
}
|
|
48780
49047
|
});
|
|
49048
|
+
function heroPosition(h) {
|
|
49049
|
+
return vec2(h.position);
|
|
49050
|
+
}
|
|
49051
|
+
function heroOwner(h) {
|
|
49052
|
+
return str(h.owner);
|
|
49053
|
+
}
|
|
49054
|
+
function heroMovement(h) {
|
|
49055
|
+
return num(h.movement);
|
|
49056
|
+
}
|
|
49057
|
+
function hexPassable(h) {
|
|
49058
|
+
return h.passable !== false;
|
|
49059
|
+
}
|
|
48781
49060
|
function defaultIsInRange(from, to, range) {
|
|
48782
49061
|
return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
|
|
48783
49062
|
}
|
|
@@ -48808,36 +49087,36 @@ function WorldMapBoard({
|
|
|
48808
49087
|
className
|
|
48809
49088
|
}) {
|
|
48810
49089
|
const eventBus = useEventBus();
|
|
48811
|
-
const resolved =
|
|
48812
|
-
const hexes = resolved?.hexes
|
|
48813
|
-
const heroes = resolved?.heroes
|
|
48814
|
-
const features = resolved?.features
|
|
48815
|
-
const selectedHeroId = resolved?.selectedHeroId;
|
|
49090
|
+
const resolved = boardEntity(entity);
|
|
49091
|
+
const hexes = rows(resolved?.hexes);
|
|
49092
|
+
const heroes = rows(resolved?.heroes);
|
|
49093
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
49094
|
+
const selectedHeroId = resolved?.selectedHeroId ?? null;
|
|
48816
49095
|
const assetManifest = resolved?.assetManifest;
|
|
48817
49096
|
const backgroundImage = resolved?.backgroundImage;
|
|
48818
49097
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
48819
49098
|
const selectedHero = useMemo(
|
|
48820
|
-
() => heroes.find((h) => h.id === selectedHeroId) ?? null,
|
|
49099
|
+
() => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
|
|
48821
49100
|
[heroes, selectedHeroId]
|
|
48822
49101
|
);
|
|
48823
49102
|
const tiles = useMemo(
|
|
48824
49103
|
() => hexes.map((hex) => ({
|
|
48825
|
-
x: hex.x,
|
|
48826
|
-
y: hex.y,
|
|
48827
|
-
terrain: hex.terrain,
|
|
48828
|
-
terrainSprite: hex.terrainSprite
|
|
49104
|
+
x: num(hex.x),
|
|
49105
|
+
y: num(hex.y),
|
|
49106
|
+
terrain: str(hex.terrain),
|
|
49107
|
+
terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
|
|
48829
49108
|
})),
|
|
48830
49109
|
[hexes]
|
|
48831
49110
|
);
|
|
48832
49111
|
const baseUnits = useMemo(
|
|
48833
49112
|
() => heroes.map((hero) => ({
|
|
48834
|
-
id: hero.id,
|
|
48835
|
-
position: hero
|
|
48836
|
-
name: hero.name,
|
|
48837
|
-
team: hero
|
|
49113
|
+
id: str(hero.id),
|
|
49114
|
+
position: heroPosition(hero),
|
|
49115
|
+
name: str(hero.name),
|
|
49116
|
+
team: heroOwner(hero) === "enemy" ? "enemy" : "player",
|
|
48838
49117
|
health: 100,
|
|
48839
49118
|
maxHealth: 100,
|
|
48840
|
-
sprite: hero.sprite
|
|
49119
|
+
sprite: hero.sprite == null ? void 0 : str(hero.sprite)
|
|
48841
49120
|
})),
|
|
48842
49121
|
[heroes]
|
|
48843
49122
|
);
|
|
@@ -48878,73 +49157,94 @@ function WorldMapBoard({
|
|
|
48878
49157
|
const isoUnits = useMemo(() => {
|
|
48879
49158
|
if (movingPositions.size === 0) return baseUnits;
|
|
48880
49159
|
return baseUnits.map((u) => {
|
|
48881
|
-
const pos = movingPositions.get(u.id);
|
|
49160
|
+
const pos = u.id == null ? void 0 : movingPositions.get(u.id);
|
|
48882
49161
|
return pos ? { ...u, position: pos } : u;
|
|
48883
49162
|
});
|
|
48884
49163
|
}, [baseUnits, movingPositions]);
|
|
48885
49164
|
const validMoves = useMemo(() => {
|
|
48886
|
-
if (!selectedHero || selectedHero
|
|
49165
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
49166
|
+
const sp = heroPosition(selectedHero);
|
|
49167
|
+
const sOwner = heroOwner(selectedHero);
|
|
49168
|
+
const range = heroMovement(selectedHero);
|
|
48887
49169
|
const moves = [];
|
|
48888
49170
|
hexes.forEach((hex) => {
|
|
48889
|
-
|
|
48890
|
-
|
|
48891
|
-
if (!
|
|
48892
|
-
if (
|
|
48893
|
-
|
|
49171
|
+
const hx = num(hex.x);
|
|
49172
|
+
const hy = num(hex.y);
|
|
49173
|
+
if (!hexPassable(hex)) return;
|
|
49174
|
+
if (hx === sp.x && hy === sp.y) return;
|
|
49175
|
+
if (!isInRange(sp, { x: hx, y: hy }, range)) return;
|
|
49176
|
+
if (heroes.some((h) => {
|
|
49177
|
+
const hp = heroPosition(h);
|
|
49178
|
+
return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
|
|
49179
|
+
})) return;
|
|
49180
|
+
moves.push({ x: hx, y: hy });
|
|
48894
49181
|
});
|
|
48895
49182
|
return moves;
|
|
48896
49183
|
}, [selectedHero, hexes, heroes, isInRange]);
|
|
48897
49184
|
const attackTargets = useMemo(() => {
|
|
48898
|
-
if (!selectedHero || selectedHero
|
|
48899
|
-
|
|
49185
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
49186
|
+
const sp = heroPosition(selectedHero);
|
|
49187
|
+
const sOwner = heroOwner(selectedHero);
|
|
49188
|
+
const range = heroMovement(selectedHero);
|
|
49189
|
+
return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
|
|
48900
49190
|
}, [selectedHero, heroes, isInRange]);
|
|
48901
|
-
const maxY = Math.max(...hexes.map((h) => h.y), 0);
|
|
49191
|
+
const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
|
|
48902
49192
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
48903
49193
|
const tileToScreen = useCallback(
|
|
48904
49194
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
48905
49195
|
[scale, baseOffsetX]
|
|
48906
49196
|
);
|
|
48907
49197
|
const hoveredHex = useMemo(
|
|
48908
|
-
() => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
|
|
49198
|
+
() => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
|
|
48909
49199
|
[hoveredTile, hexes]
|
|
48910
49200
|
);
|
|
48911
49201
|
const hoveredHero = useMemo(
|
|
48912
|
-
() => hoveredTile ? heroes.find((h) =>
|
|
49202
|
+
() => hoveredTile ? heroes.find((h) => {
|
|
49203
|
+
const hp = heroPosition(h);
|
|
49204
|
+
return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
|
|
49205
|
+
}) ?? null : null,
|
|
48913
49206
|
[hoveredTile, heroes]
|
|
48914
49207
|
);
|
|
48915
49208
|
const handleTileClick = useCallback((x, y) => {
|
|
48916
49209
|
if (movementAnimRef.current) return;
|
|
48917
|
-
const hex = hexes.find((h) => h.x === x && h.y === y);
|
|
49210
|
+
const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
|
|
48918
49211
|
if (!hex) return;
|
|
48919
49212
|
if (tileClickEvent) {
|
|
48920
49213
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
48921
49214
|
}
|
|
48922
49215
|
if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
|
|
48923
|
-
|
|
48924
|
-
|
|
49216
|
+
const heroId = str(selectedHero.id);
|
|
49217
|
+
startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
|
|
49218
|
+
onHeroMove?.(heroId, x, y);
|
|
48925
49219
|
if (heroMoveEvent) {
|
|
48926
|
-
eventBus.emit(`UI:${heroMoveEvent}`, { heroId
|
|
49220
|
+
eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
|
|
48927
49221
|
}
|
|
48928
|
-
|
|
48929
|
-
|
|
49222
|
+
const feature = str(hex.feature);
|
|
49223
|
+
if (feature && feature !== "none") {
|
|
49224
|
+
onFeatureEnter?.(heroId, hex);
|
|
48930
49225
|
if (featureEnterEvent) {
|
|
48931
|
-
eventBus.emit(`UI:${featureEnterEvent}`, { heroId
|
|
49226
|
+
eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
|
|
48932
49227
|
}
|
|
48933
49228
|
}
|
|
48934
49229
|
});
|
|
48935
49230
|
return;
|
|
48936
49231
|
}
|
|
48937
|
-
const enemy = heroes.find((h) =>
|
|
49232
|
+
const enemy = heroes.find((h) => {
|
|
49233
|
+
const hp = heroPosition(h);
|
|
49234
|
+
return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
|
|
49235
|
+
});
|
|
48938
49236
|
if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
|
|
48939
|
-
|
|
49237
|
+
const attackerId = str(selectedHero.id);
|
|
49238
|
+
const defenderId = str(enemy.id);
|
|
49239
|
+
onBattleEncounter?.(attackerId, defenderId);
|
|
48940
49240
|
if (battleEncounterEvent) {
|
|
48941
|
-
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId
|
|
49241
|
+
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
|
|
48942
49242
|
}
|
|
48943
49243
|
}
|
|
48944
49244
|
}, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
|
|
48945
49245
|
const handleUnitClick = useCallback((unitId) => {
|
|
48946
|
-
const hero = heroes.find((h) => h.id === unitId);
|
|
48947
|
-
if (hero && (hero
|
|
49246
|
+
const hero = heroes.find((h) => str(h.id) === unitId);
|
|
49247
|
+
if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
|
|
48948
49248
|
onHeroSelect?.(unitId);
|
|
48949
49249
|
if (heroSelectEvent) {
|
|
48950
49250
|
eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
|
|
@@ -49017,6 +49317,7 @@ var init_WorldMapBoard = __esm({
|
|
|
49017
49317
|
init_Stack();
|
|
49018
49318
|
init_LoadingState();
|
|
49019
49319
|
init_IsometricCanvas2();
|
|
49320
|
+
init_boardEntity();
|
|
49020
49321
|
init_isometric();
|
|
49021
49322
|
WorldMapBoard.displayName = "WorldMapBoard";
|
|
49022
49323
|
}
|
|
@@ -52580,10 +52881,10 @@ function parseApplicationLevel(schema) {
|
|
|
52580
52881
|
}
|
|
52581
52882
|
const count = schema.orbitals.length;
|
|
52582
52883
|
const cols = Math.ceil(Math.sqrt(count));
|
|
52583
|
-
const
|
|
52884
|
+
const rows2 = Math.ceil(count / cols);
|
|
52584
52885
|
const spacing = 200;
|
|
52585
52886
|
const gridW = cols * spacing;
|
|
52586
|
-
const gridH =
|
|
52887
|
+
const gridH = rows2 * spacing;
|
|
52587
52888
|
const originX = (600 - gridW) / 2 + spacing / 2;
|
|
52588
52889
|
const originY = (400 - gridH) / 2 + spacing / 2;
|
|
52589
52890
|
schema.orbitals.forEach((orbital, i) => {
|
|
@@ -55725,11 +56026,11 @@ function buildMockData(schema) {
|
|
|
55725
56026
|
result[entityName] = entity.instances;
|
|
55726
56027
|
continue;
|
|
55727
56028
|
}
|
|
55728
|
-
const
|
|
56029
|
+
const rows2 = Array.from(
|
|
55729
56030
|
{ length: 10 },
|
|
55730
56031
|
(_, i) => generateEntityRow(entity, i + 1)
|
|
55731
56032
|
);
|
|
55732
|
-
result[entityName] =
|
|
56033
|
+
result[entityName] = rows2;
|
|
55733
56034
|
}
|
|
55734
56035
|
for (const orbital of schema.orbitals) {
|
|
55735
56036
|
for (const traitRef of orbital.traits ?? []) {
|
|
@@ -59228,18 +59529,18 @@ function layoutOrbitals(count, containerW, containerH) {
|
|
|
59228
59529
|
if (count === 0) return [];
|
|
59229
59530
|
if (count === 1) return [{ cx: containerW / 2, cy: containerH / 2 }];
|
|
59230
59531
|
const cols = Math.min(count, Math.ceil(Math.sqrt(count)));
|
|
59231
|
-
const
|
|
59532
|
+
const rows2 = Math.ceil(count / cols);
|
|
59232
59533
|
const edgePad = 24;
|
|
59233
59534
|
const fitMinCx = UNIT_DISPLAY_W / 2 + edgePad;
|
|
59234
59535
|
const fitMinCy = UNIT_DISPLAY_H / 2 + edgePad;
|
|
59235
59536
|
const fitMaxCx = Math.max(fitMinCx, containerW - UNIT_DISPLAY_W / 2 - edgePad);
|
|
59236
59537
|
const fitMaxCy = Math.max(fitMinCy, containerH - UNIT_DISPLAY_H / 2 - edgePad);
|
|
59237
59538
|
const fitStepX = cols > 1 ? (fitMaxCx - fitMinCx) / (cols - 1) : 0;
|
|
59238
|
-
const fitStepY =
|
|
59539
|
+
const fitStepY = rows2 > 1 ? (fitMaxCy - fitMinCy) / (rows2 - 1) : 0;
|
|
59239
59540
|
const stepX = Math.min(fitStepX, UNIT_DISPLAY_W * 3.5);
|
|
59240
59541
|
const stepY = Math.min(fitStepY, UNIT_DISPLAY_H * 3.5);
|
|
59241
59542
|
const gridW = (cols - 1) * stepX;
|
|
59242
|
-
const gridH = (
|
|
59543
|
+
const gridH = (rows2 - 1) * stepY;
|
|
59243
59544
|
const originX = (containerW - gridW) / 2;
|
|
59244
59545
|
const originY = (containerH - gridH) / 2;
|
|
59245
59546
|
return Array.from({ length: count }, (_, i) => ({
|